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(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    }