001    package de.deepamehta.core.model;
002    
003    import de.deepamehta.core.Identifiable;
004    import de.deepamehta.core.JSONEnabled;
005    
006    import org.codehaus.jettison.json.JSONObject;
007    
008    
009    
010    public abstract class DeepaMehtaObjectModel implements Identifiable, JSONEnabled, Cloneable {
011    
012        // ---------------------------------------------------------------------------------------------- Instance Variables
013    
014        // ### TODO: make these private?
015        protected long id;                  // is -1 in models used for a create operation. ### FIXDOC
016                                            // is never -1 in models used for an update operation.
017        protected String uri;               // is never null in models used for a create operation, may be empty. ### FIXDOC
018                                            // may be null in models used for an update operation.
019        protected String typeUri;           // is never null in models used for a create operation. ### FIXDOC
020                                            // may be null in models used for an update operation.
021        protected SimpleValue value;        // is never null in models used for a create operation, may be constructed
022                                            //                                                   on empty string. ### FIXDOC
023                                            // may be null in models used for an update operation.
024        protected ChildTopicsModel childTopics; // is never null, may be empty. ### FIXDOC
025    
026        // ---------------------------------------------------------------------------------------------------- Constructors
027    
028        public DeepaMehtaObjectModel(String typeUri) {
029            this(-1, typeUri);
030        }
031    
032        public DeepaMehtaObjectModel(String typeUri, SimpleValue value) {
033            this(null, typeUri, value);
034        }
035    
036        public DeepaMehtaObjectModel(String typeUri, ChildTopicsModel childTopics) {
037            this(null, typeUri, childTopics);
038        }
039    
040        public DeepaMehtaObjectModel(String uri, String typeUri) {
041            this(-1, uri, typeUri, null, null);
042        }
043    
044        public DeepaMehtaObjectModel(String uri, String typeUri, SimpleValue value) {
045            this(-1, uri, typeUri, value, null);
046        }
047    
048        public DeepaMehtaObjectModel(String uri, String typeUri, ChildTopicsModel childTopics) {
049            this(-1, uri, typeUri, null, childTopics);
050        }
051    
052        public DeepaMehtaObjectModel(long id) {
053            this(id, null, null);
054        }
055    
056        public DeepaMehtaObjectModel(long id, ChildTopicsModel childTopics) {
057            this(id, null, childTopics);
058        }
059    
060        public DeepaMehtaObjectModel(long id, String typeUri) {
061            this(id, typeUri, null);
062        }
063    
064        public DeepaMehtaObjectModel(long id, String typeUri, ChildTopicsModel childTopics) {
065            this(id, null, typeUri, null, childTopics);
066        }
067    
068        /**
069         * @param   id          Optional (-1 is a valid value and represents "not set").
070         * @param   uri         Optional (<code>null</code> is a valid value).
071         * @param   typeUri     Mandatory in the context of a create operation.
072         *                      Optional (<code>null</code> is a valid value) in the context of an update opereation.
073         * @param   value       Optional (<code>null</code> is a valid value).
074         * @param   childTopics Optional (<code>null</code> is a valid value and is transformed into an empty composite).
075         */
076        public DeepaMehtaObjectModel(long id, String uri, String typeUri, SimpleValue value, ChildTopicsModel childTopics) {
077            this.id = id;
078            this.uri = uri;
079            this.typeUri = typeUri;
080            this.value = value;
081            this.childTopics = childTopics != null ? childTopics : new ChildTopicsModel();
082        }
083    
084        public DeepaMehtaObjectModel(DeepaMehtaObjectModel model) {
085            this(model.id, model.uri, model.typeUri, model.value, model.childTopics);
086        }
087    
088        /**
089         * Used for regular objects: topics and associations.
090         */
091        public DeepaMehtaObjectModel(JSONObject model) {
092            try {
093                this.id          = model.optLong("id", -1);
094                this.uri         = model.optString("uri", null);
095                this.typeUri     = model.optString("type_uri", null);
096                this.value       = model.has("value") ? new SimpleValue(model.get("value")) : null;
097                this.childTopics = model.has("childs") ? new ChildTopicsModel(model.getJSONObject("childs"))
098                                                       : new ChildTopicsModel();
099            } catch (Exception e) {
100                throw new RuntimeException("Parsing DeepaMehtaObjectModel failed (JSONObject=" + model + ")", e);
101            }
102        }
103    
104        /**
105         * Used for types: topic types and association types.
106         */
107        public DeepaMehtaObjectModel(JSONObject typeModel, String typeUri) {
108            try {
109                this.id = typeModel.optLong("id", -1);
110                this.uri = typeModel.optString("uri");
111                this.typeUri = typeUri;
112                this.value = new SimpleValue(typeModel.get("value"));
113                this.childTopics = new ChildTopicsModel();
114            } catch (Exception e) {
115                throw new RuntimeException("Parsing DeepaMehtaObjectModel failed (JSONObject=" + typeModel +
116                    ", typeUri=\"" + typeUri + "\")", e);
117            }
118        }
119    
120        // -------------------------------------------------------------------------------------------------- Public Methods
121    
122        // --- ID ---
123    
124        public long getId() {
125            return id;
126        }
127    
128        public void setId(long id) {
129            this.id = id;
130        }
131    
132        // --- URI ---
133    
134        public String getUri() {
135            return uri;
136        }
137    
138        public void setUri(String uri) {
139            this.uri = uri;
140        }
141    
142        // --- Type URI ---
143    
144        public String getTypeUri() {
145            return typeUri;
146        }
147    
148        public void setTypeUri(String typeUri) {
149            this.typeUri = typeUri;
150        }
151    
152        // --- Simple Value ---
153    
154        public SimpleValue getSimpleValue() {
155            return value;
156        }
157    
158        // ---
159    
160        public void setSimpleValue(String value) {
161            setSimpleValue(new SimpleValue(value));
162        }
163    
164        public void setSimpleValue(int value) {
165            setSimpleValue(new SimpleValue(value));
166        }
167    
168        public void setSimpleValue(long value) {
169            setSimpleValue(new SimpleValue(value));
170        }
171    
172        public void setSimpleValue(boolean value) {
173            setSimpleValue(new SimpleValue(value));
174        }
175    
176        public void setSimpleValue(SimpleValue value) {
177            this.value = value;
178        }
179    
180        // --- Child Topics ---
181    
182        public ChildTopicsModel getChildTopicsModel() {
183            return childTopics;
184        }
185    
186        public void setChildTopicsModel(ChildTopicsModel childTopics) {
187            this.childTopics = childTopics;
188        }
189    
190        // ---
191    
192        public void set(DeepaMehtaObjectModel model) {
193            setId(model.getId());
194            setUri(model.getUri());
195            setTypeUri(model.getTypeUri());
196            setSimpleValue(model.getSimpleValue());
197            setChildTopicsModel(model.getChildTopicsModel());
198        }
199    
200        // ---
201    
202        public abstract RoleModel createRoleModel(String roleTypeUri);
203    
204    
205    
206        // === Serialization ===
207    
208        @Override
209        public JSONObject toJSON() {
210            try {
211                // Note: for models used for topic/association enrichment (e.g. timestamps, permissions)
212                // default values must be set in case they are not fully initialized.
213                setDefaults();
214                //
215                JSONObject o = new JSONObject();
216                o.put("id", id);
217                o.put("uri", uri);
218                o.put("type_uri", typeUri);
219                o.put("value", value.value());
220                o.put("childs", childTopics.toJSON());
221                return o;
222            } catch (Exception e) {
223                throw new RuntimeException("Serialization failed (" + this + ")", e);
224            }
225        }
226    
227    
228    
229        // === Java API ===
230    
231        @Override
232        public DeepaMehtaObjectModel clone() {
233            try {
234                DeepaMehtaObjectModel model = (DeepaMehtaObjectModel) super.clone();
235                model.childTopics = childTopics.clone();
236                return model;
237            } catch (Exception e) {
238                throw new RuntimeException("Cloning a DeepaMehtaObjectModel failed", e);
239            }
240        }
241    
242        @Override
243        public boolean equals(Object o) {
244            return ((DeepaMehtaObjectModel) o).id == id;
245        }
246    
247        @Override
248        public int hashCode() {
249            return ((Long) id).hashCode();
250        }
251    
252        @Override
253        public String toString() {
254            return "id=" + id + ", uri=\"" + uri + "\", typeUri=\"" + typeUri + "\", value=\"" + value +
255                "\", childTopics=" + childTopics;
256        }
257    
258    
259    
260        // ------------------------------------------------------------------------------------------------- Private Methods
261    
262        // ### TODO: a principal copy exists in Neo4jStorage.
263        // Should this be public? It is not meant to be called by the user.
264        private void setDefaults() {
265            if (getUri() == null) {
266                setUri("");
267            }
268            if (getSimpleValue() == null) {
269                setSimpleValue("");
270            }
271        }
272    }