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    // ### TODO: differentiate between a model and an update model.
011    // ### The latter's constructor must set no default values (see #311).
012    public abstract class DeepaMehtaObjectModel implements Identifiable, JSONEnabled, Cloneable {
013    
014        // ---------------------------------------------------------------------------------------------- Instance Variables
015    
016        // ### TODO: make these private?
017        protected long id;                  // is -1 in models used for a create operation. ### FIXDOC
018                                            // is never -1 in models used for an update operation.
019        protected String uri;               // is never null in models used for a create operation, may be empty. ### FIXDOC
020                                            // may be null in models used for an update operation.
021        protected String typeUri;           // is never null in models used for a create operation. ### FIXDOC
022                                            // may be null in models used for an update operation.
023        protected SimpleValue value;        // is never null in models used for a create operation, may be constructed
024                                            //                                                   on empty string. ### FIXDOC
025                                            // may be null in models used for an update operation.
026        protected CompositeValueModel composite; // is never null, may be empty. ### FIXDOC
027    
028        // ---------------------------------------------------------------------------------------------------- Constructors
029    
030        public DeepaMehtaObjectModel(String typeUri) {
031            this(-1, typeUri);
032        }
033    
034        public DeepaMehtaObjectModel(String typeUri, SimpleValue value) {
035            this(null, typeUri, value);
036        }
037    
038        public DeepaMehtaObjectModel(String typeUri, CompositeValueModel composite) {
039            this(null, typeUri, composite);
040        }
041    
042        public DeepaMehtaObjectModel(String uri, String typeUri) {
043            this(-1, uri, typeUri, null, null);
044        }
045    
046        public DeepaMehtaObjectModel(String uri, String typeUri, SimpleValue value) {
047            this(-1, uri, typeUri, value, null);
048        }
049    
050        public DeepaMehtaObjectModel(String uri, String typeUri, CompositeValueModel composite) {
051            this(-1, uri, typeUri, null, composite);
052        }
053    
054        public DeepaMehtaObjectModel(long id) {
055            this(id, null, null);
056        }
057    
058        public DeepaMehtaObjectModel(long id, String typeUri) {
059            this(id, typeUri, null);
060        }
061    
062        public DeepaMehtaObjectModel(long id, CompositeValueModel composite) {
063            this(id, null, composite);
064        }
065    
066        public DeepaMehtaObjectModel(long id, String typeUri, CompositeValueModel composite) {
067            this(id, null, typeUri, null, composite);
068        }
069    
070        /**
071         * @param   uri         If <code>null</code> an empty string is set. This is OK. ### FIXDOC
072         * @param   typeUri     Mandatory. Note: only the internal meta type topic (ID 0) has no type URI (null). ### FIXDOC
073         * @param   value       If <code>null</code> an empty string value is set. This is OK. ### FIXDOC
074         * @param   composite   If <code>null</code> an empty composite is set. This is OK. ### FIXDOC
075         */
076        public DeepaMehtaObjectModel(long id, String uri, String typeUri, SimpleValue value,
077                                                                          CompositeValueModel composite) {
078            this.id = id;
079            this.uri = uri != null ? uri : "";                          // ### FIXME: don't set default at this level
080            this.typeUri = typeUri;
081            this.value = value != null ? value : new SimpleValue("");   // ### FIXME: don't set default at this level
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                JSONObject o = new JSONObject();
213                o.put("id", id);
214                o.put("uri", uri);
215                o.put("type_uri", typeUri);
216                o.put("value", value.value());
217                o.put("composite", composite.toJSON());
218                return o;
219            } catch (Exception e) {
220                throw new RuntimeException("Serialization failed (" + this + ")", e);
221            }
222        }
223    
224    
225    
226        // === Java API ===
227    
228        @Override
229        public DeepaMehtaObjectModel clone() {
230            try {
231                DeepaMehtaObjectModel model = (DeepaMehtaObjectModel) super.clone();
232                model.composite = composite.clone();
233                return model;
234            } catch (Exception e) {
235                throw new RuntimeException("Cloning a DeepaMehtaObjectModel failed", e);
236            }
237        }
238    
239        @Override
240        public boolean equals(Object o) {
241            return ((DeepaMehtaObjectModel) o).id == id;
242        }
243    
244        @Override
245        public int hashCode() {
246            return ((Long) id).hashCode();
247        }
248    
249        @Override
250        public String toString() {
251            return "id=" + id + ", uri=\"" + uri + "\", typeUri=\"" + typeUri + "\", value=\"" + value +
252                "\", composite=" + composite;
253        }
254    }