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