001package de.deepamehta.core.impl;
002
003import de.deepamehta.core.AssociationDefinition;
004import de.deepamehta.core.DeepaMehtaObject;
005import de.deepamehta.core.RelatedTopic;
006import de.deepamehta.core.model.ChildTopicsModel;
007import de.deepamehta.core.model.DeepaMehtaObjectModel;
008import de.deepamehta.core.model.RelatedTopicModel;
009import de.deepamehta.core.model.SimpleValue;
010
011import org.codehaus.jettison.json.JSONObject;
012
013import java.util.List;
014
015
016
017/**
018 * A DeepaMehta object model that is attached to the DB.
019 *
020 * Method name conventions and semantics:
021 *  - getXX()           Reads from memory (model).
022 *  - setXX(arg)        Writes to memory (model) and DB. Elementary operation.
023 *  - updateXX(arg)     Compares arg with current value (model) and calls setXX() method(s) if required.
024 *                      Can be called with arg=null which indicates no update is requested.
025 *                      Typically returns nothing.
026 *  - fetchXX()         Fetches value from DB.              ### FIXDOC
027 *  - storeXX()         Stores current value (model) to DB. ### FIXDOC
028 */
029abstract class DeepaMehtaObjectImpl implements DeepaMehtaObject {
030
031    // ---------------------------------------------------------------------------------------------- Instance Variables
032
033    DeepaMehtaObjectModelImpl model;    // underlying model
034
035    PersistenceLayer pl;
036    ModelFactoryImpl mf;
037
038    // ---------------------------------------------------------------------------------------------------- Constructors
039
040    DeepaMehtaObjectImpl(DeepaMehtaObjectModelImpl model, PersistenceLayer pl) {
041        this.model = model;
042        this.pl = pl;
043        this.mf = pl.mf;
044    }
045
046    // -------------------------------------------------------------------------------------------------- Public Methods
047
048
049
050    // ***************************************
051    // *** DeepaMehtaObject Implementation ***
052    // ***************************************
053
054
055
056    // === Model ===
057
058    // --- ID ---
059
060    @Override
061    public long getId() {
062        return model.getId();
063    }
064
065    // --- URI ---
066
067    @Override
068    public String getUri() {
069        return model.getUri();
070    }
071
072    @Override
073    public void setUri(String uri) {
074        model.updateUri(uri);
075    }
076
077    // --- Type URI ---
078
079    @Override
080    public String getTypeUri() {
081        return model.getTypeUri();
082    }
083
084    @Override
085    public void setTypeUri(String typeUri) {
086        model.updateTypeUri(typeUri);
087    }
088
089    // --- Simple Value ---
090
091    @Override
092    public SimpleValue getSimpleValue() {
093        return model.getSimpleValue();
094    }
095
096    // ---
097
098    @Override
099    public void setSimpleValue(String value) {
100        setSimpleValue(new SimpleValue(value));
101    }
102
103    @Override
104    public void setSimpleValue(int value) {
105        setSimpleValue(new SimpleValue(value));
106    }
107
108    @Override
109    public void setSimpleValue(long value) {
110        setSimpleValue(new SimpleValue(value));
111    }
112
113    @Override
114    public void setSimpleValue(boolean value) {
115        setSimpleValue(new SimpleValue(value));
116    }
117
118    @Override
119    public void setSimpleValue(SimpleValue value) {
120        model.updateSimpleValue(value);
121    }
122
123    // --- Child Topics ---
124
125    @Override
126    public ChildTopicsImpl getChildTopics() {
127        return new ChildTopicsImpl(model.childTopics, model, pl);
128    }
129
130    // ### FIXME: no UPDATE directive for *this* object is added. No UPDATE event for *this* object is fired.
131    // We should call the abstract updateChildTopics() instead.
132    @Override
133    public void setChildTopics(ChildTopicsModel childTopics) {
134        try {
135            model._updateChildTopics((ChildTopicsModelImpl) childTopics);
136        } catch (Exception e) {
137            throw new RuntimeException("Setting the child topics failed (" + childTopics + ")", e);
138        }
139    }
140
141    // ---
142
143    @Override
144    public DeepaMehtaObject loadChildTopics() {
145        model.loadChildTopics();
146        return this;
147    }
148
149    @Override
150    public DeepaMehtaObject loadChildTopics(String assocDefUri) {
151        model.loadChildTopics(assocDefUri);
152        return this;
153    }
154
155    // ---
156
157    // Note: getType() remains abstract
158
159    @Override
160    public DeepaMehtaObjectModelImpl getModel() {
161        return model;
162    }
163
164
165
166    // === Updating ===
167
168    @Override
169    public final void update(DeepaMehtaObjectModel newModel) {
170        model.update((DeepaMehtaObjectModelImpl) newModel);     // ### FIXME: call through pl for access control
171    }
172
173    // ---
174
175    // ### FIXME: no UPDATE directive for *this* object is added. No UPDATE event for *this* object is fired.
176    // Directives/events is handled only in the high-level update() method.
177    // Here however we need to call the low-level updateChildTopics() method in order to pass an arbitrary assoc def.
178    @Override
179    public void updateChildTopic(RelatedTopicModel newChildTopic, AssociationDefinition assocDef) {
180        model.updateChildTopics((RelatedTopicModelImpl) newChildTopic, null, assocDef.getModel());
181                                                                                                // newChildTopics=null
182    }
183
184    // ### FIXME: no UPDATE directive for *this* object is added. No UPDATE event for *this* object is fired.
185    // Directives/events is handled only in the high-level update() method.
186    // Here however we need to call the low-level updateChildTopics() method in order to pass an arbitrary assoc def.
187    @Override
188    public void updateChildTopics(List<? extends RelatedTopicModel> newChildTopics, AssociationDefinition assocDef) {
189        model.updateChildTopics(null, (List<RelatedTopicModelImpl>) newChildTopics, assocDef.getModel());
190                                                                                                // newChildTopic=null
191    }
192
193
194
195    // === Deletion ===
196
197    @Override
198    public final void delete() {
199        model.delete();     // ### FIXME: call through pl for access control
200    }
201
202
203
204    // === Traversal ===
205
206    // --- Topic Retrieval ---
207
208    @Override
209    public RelatedTopic getRelatedTopic(String assocTypeUri, String myRoleTypeUri, String othersRoleTypeUri,
210                                                                                   String othersTopicTypeUri) {
211        RelatedTopicModelImpl topic = model.getRelatedTopic(assocTypeUri, myRoleTypeUri, othersRoleTypeUri,
212            othersTopicTypeUri);
213        return topic != null ? pl.<RelatedTopic>checkReadAccessAndInstantiate(topic) : null;
214    }
215
216    @Override
217    public List<RelatedTopic> getRelatedTopics(String assocTypeUri) {
218        return getRelatedTopics(assocTypeUri, null, null, null);
219    }
220
221    @Override
222    public List<RelatedTopic> getRelatedTopics(String assocTypeUri, String myRoleTypeUri, String othersRoleTypeUri,
223                                                                                          String othersTopicTypeUri) {
224        List<RelatedTopicModelImpl> topics = model.getRelatedTopics(assocTypeUri, myRoleTypeUri, othersRoleTypeUri,
225            othersTopicTypeUri);
226        return pl.checkReadAccessAndInstantiate(topics);
227    }
228
229    // Note: this method is implemented in the subclasses (this is an abstract class):
230    //     getRelatedTopics(List assocTypeUris, ...)
231
232    // --- Association Retrieval ---
233
234    // Note: these methods are implemented in the subclasses (this is an abstract class):
235    //     getAssociation(...)
236    //     getAssociations()
237
238
239
240    // === Properties ===
241
242    @Override
243    public Object getProperty(String propUri) {
244        return pl.fetchProperty(getId(), propUri);
245    }
246
247    @Override
248    public boolean hasProperty(String propUri) {
249        return pl.hasProperty(getId(), propUri);
250    }
251
252    // Note: these methods are implemented in the subclasses:
253    //     setProperty(...)
254    //     removeProperty(...)
255
256
257
258    // === Misc ===
259
260    @Override
261    public Object getDatabaseVendorObject() {
262        return pl.getDatabaseVendorObject(getId());
263    }
264
265
266
267    // **********************************
268    // *** JSONEnabled Implementation ***
269    // **********************************
270
271
272
273    @Override
274    public JSONObject toJSON() {
275        return model.toJSON();
276    }
277
278
279
280    // ****************
281    // *** Java API ***
282    // ****************
283
284
285
286    @Override
287    public boolean equals(Object o) {
288        return ((DeepaMehtaObjectImpl) o).model.equals(model);
289    }
290
291    @Override
292    public int hashCode() {
293        return model.hashCode();
294    }
295
296    @Override
297    public String toString() {
298        return model.toString();
299    }
300
301
302
303    // ----------------------------------------------------------------------------------------- Package Private Methods
304
305    final String className() {
306        return model.className();
307    }
308}