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 CompositeValueModel composite; // 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, CompositeValueModel composite) {
037            this(null, typeUri, composite);
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, CompositeValueModel composite) {
049            this(-1, uri, typeUri, null, composite);
050        }
051    
052        public DeepaMehtaObjectModel(long id) {
053            this(id, null, null);
054        }
055    
056        public DeepaMehtaObjectModel(long id, CompositeValueModel composite) {
057            this(id, null, composite);
058        }
059    
060        public DeepaMehtaObjectModel(long id, String typeUri) {
061            this(id, typeUri, null);
062        }
063    
064        public DeepaMehtaObjectModel(long id, String typeUri, CompositeValueModel composite) {
065            this(id, null, typeUri, null, composite);
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   composite   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,
077                                                                          CompositeValueModel composite) {
078            this.id = id;
079            this.uri = uri;
080            this.typeUri = typeUri;
081            this.value = value;
082            this.composite = composite != null ? composite : new CompositeValueModel();
083        }
084    
085        public DeepaMehtaObjectModel(DeepaMehtaObjectModel model) {
086            this(model.id, model.uri, model.typeUri, model.value, model.composite);
087        }
088    
089        /**
090         * Used for regular objects: topics and associations.
091         */
092        public DeepaMehtaObjectModel(JSONObject model) {
093            try {
094                this.id        = model.optLong("id", -1);
095                this.uri       = model.optString("uri", null);
096                this.typeUri   = model.optString("type_uri", null);
097                this.value     = model.has("value") ? new SimpleValue(model.get("value")) : null;
098                this.composite = model.has("composite") ? new CompositeValueModel(model.getJSONObject("composite"))
099                                                        : new CompositeValueModel();
100            } catch (Exception e) {
101                throw new RuntimeException("Parsing DeepaMehtaObjectModel failed (JSONObject=" + model + ")", e);
102            }
103        }
104    
105        /**
106         * Used for types: topic types and association types.
107         */
108        public DeepaMehtaObjectModel(JSONObject typeModel, String typeUri) {
109            try {
110                this.id = typeModel.optLong("id", -1);
111                this.uri = typeModel.optString("uri");
112                this.typeUri = typeUri;
113                this.value = new SimpleValue(typeModel.get("value"));
114                this.composite = new CompositeValueModel();
115            } catch (Exception e) {
116                throw new RuntimeException("Parsing DeepaMehtaObjectModel failed (JSONObject=" + typeModel +
117                    ", typeUri=\"" + typeUri + "\")", e);
118            }
119        }
120    
121        // -------------------------------------------------------------------------------------------------- Public Methods
122    
123        // --- ID ---
124    
125        public long getId() {
126            return id;
127        }
128    
129        public void setId(long id) {
130            this.id = id;
131        }
132    
133        // --- URI ---
134    
135        public String getUri() {
136            return uri;
137        }
138    
139        public void setUri(String uri) {
140            this.uri = uri;
141        }
142    
143        // --- Type URI ---
144    
145        public String getTypeUri() {
146            return typeUri;
147        }
148    
149        public void setTypeUri(String typeUri) {
150            this.typeUri = typeUri;
151        }
152    
153        // --- Simple Value ---
154    
155        public SimpleValue getSimpleValue() {
156            return value;
157        }
158    
159        // ---
160    
161        public void setSimpleValue(String value) {
162            setSimpleValue(new SimpleValue(value));
163        }
164    
165        public void setSimpleValue(int value) {
166            setSimpleValue(new SimpleValue(value));
167        }
168    
169        public void setSimpleValue(long value) {
170            setSimpleValue(new SimpleValue(value));
171        }
172    
173        public void setSimpleValue(boolean value) {
174            setSimpleValue(new SimpleValue(value));
175        }
176    
177        public void setSimpleValue(SimpleValue value) {
178            this.value = value;
179        }
180    
181        // --- Composite Value ---
182    
183        public CompositeValueModel getCompositeValueModel() {
184            return composite;
185        }
186    
187        public void setCompositeValue(CompositeValueModel comp) {
188            this.composite = comp;
189        }
190    
191        // ---
192    
193        public void set(DeepaMehtaObjectModel model) {
194            setId(model.getId());
195            setUri(model.getUri());
196            setTypeUri(model.getTypeUri());
197            setSimpleValue(model.getSimpleValue());
198            setCompositeValue(model.getCompositeValueModel());
199        }
200    
201        // ---
202    
203        public abstract RoleModel createRoleModel(String roleTypeUri);
204    
205    
206    
207        // === Serialization ===
208    
209        @Override
210        public JSONObject toJSON() {
211            try {
212                // Note: for models used for topic/association enrichment (e.g. timestamps, permissions)
213                // default values must be set in case they are not fully initialized.
214                setDefaults();
215                //
216                JSONObject o = new JSONObject();
217                o.put("id", id);
218                o.put("uri", uri);
219                o.put("type_uri", typeUri);
220                o.put("value", value.value());
221                o.put("composite", composite.toJSON());
222                return o;
223            } catch (Exception e) {
224                throw new RuntimeException("Serialization failed (" + this + ")", e);
225            }
226        }
227    
228    
229    
230        // === Java API ===
231    
232        @Override
233        public DeepaMehtaObjectModel clone() {
234            try {
235                DeepaMehtaObjectModel model = (DeepaMehtaObjectModel) super.clone();
236                model.composite = composite.clone();
237                return model;
238            } catch (Exception e) {
239                throw new RuntimeException("Cloning a DeepaMehtaObjectModel failed", e);
240            }
241        }
242    
243        @Override
244        public boolean equals(Object o) {
245            return ((DeepaMehtaObjectModel) o).id == id;
246        }
247    
248        @Override
249        public int hashCode() {
250            return ((Long) id).hashCode();
251        }
252    
253        @Override
254        public String toString() {
255            return "id=" + id + ", uri=\"" + uri + "\", typeUri=\"" + typeUri + "\", value=\"" + value +
256                "\", composite=" + composite;
257        }
258    
259    
260    
261        // ------------------------------------------------------------------------------------------------- Private Methods
262    
263        // ### TODO: a principal copy exists in Neo4jStorage.
264        // Should this be public? It is not meant to be called by the user.
265        private void setDefaults() {
266            if (getUri() == null) {
267                setUri("");
268            }
269            if (getSimpleValue() == null) {
270                setSimpleValue("");
271            }
272        }
273    }