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