001package de.deepamehta.core.impl;
002
003import de.deepamehta.core.Topic;
004import de.deepamehta.core.model.AssociationDefinitionModel;
005import de.deepamehta.core.model.ChildTopicsModel;
006import de.deepamehta.core.model.IndexMode;
007import de.deepamehta.core.model.RoleModel;
008import de.deepamehta.core.model.TopicModel;
009import de.deepamehta.core.model.TopicTypeModel;
010import de.deepamehta.core.model.TypeModel;
011import de.deepamehta.core.service.DeepaMehtaEvent;
012import de.deepamehta.core.service.Directive;
013
014import java.util.List;
015
016
017
018class TopicModelImpl extends DeepaMehtaObjectModelImpl implements TopicModel {
019
020    // ---------------------------------------------------------------------------------------------------- Constructors
021
022    TopicModelImpl(DeepaMehtaObjectModelImpl object) {
023        super(object);
024    }
025
026    // -------------------------------------------------------------------------------------------------- Public Methods
027
028
029
030    // === Implementation of the abstract methods ===
031
032    @Override
033    public RoleModel createRoleModel(String roleTypeUri) {
034        return mf.newTopicRoleModel(id, roleTypeUri);
035    }
036
037
038
039    // === Java API ===
040
041    @Override
042    public TopicModel clone() {
043        try {
044            return (TopicModel) super.clone();
045        } catch (Exception e) {
046            throw new RuntimeException("Cloning a TopicModel failed", e);
047        }
048    }
049
050    @Override
051    public String toString() {
052        return "topic (" + super.toString() + ")";
053    }
054
055
056
057    // ----------------------------------------------------------------------------------------- Package Private Methods
058
059    @Override
060    String className() {
061        return "topic";
062    }
063
064    @Override
065    Topic instantiate() {
066        return new TopicImpl(this, pl);
067    }
068
069    // ---
070
071    @Override
072    TopicTypeModel getType() {
073        return pl.typeStorage.getTopicType(typeUri);
074    }
075
076    @Override
077    List<AssociationModelImpl> getAssociations() {
078        return pl.fetchTopicAssociations(id);
079    }
080
081    // ---
082
083    @Override
084    RelatedTopicModelImpl getRelatedTopic(String assocTypeUri, String myRoleTypeUri, String othersRoleTypeUri,
085                                                                                     String othersTopicTypeUri) {
086        return pl.fetchTopicRelatedTopic(id, assocTypeUri, myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri);
087    }
088
089    @Override
090    List<RelatedTopicModelImpl> getRelatedTopics(String assocTypeUri, String myRoleTypeUri, String othersRoleTypeUri,
091                                                                                            String othersTopicTypeUri) {
092        return pl.fetchTopicRelatedTopics(id, assocTypeUri, myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri);
093    }
094
095    @Override
096    List<RelatedTopicModelImpl> getRelatedTopics(List assocTypeUris, String myRoleTypeUri, String othersRoleTypeUri,
097                                                                                           String othersTopicTypeUri) {
098        return pl.fetchTopicRelatedTopics(id, assocTypeUris, myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri);
099    }
100
101    // ---
102
103    @Override
104    void storeUri() {
105        pl.storeTopicUri(id, uri);
106    }
107
108    @Override
109    void storeTypeUri() {
110        reassignInstantiation();
111        pl.storeTopicTypeUri(id, typeUri);
112    }
113
114    @Override
115    void storeSimpleValue() {
116        TypeModel type = getType();
117        pl.storeTopicValue(id, value, type.getIndexModes(), type.getUri(), getIndexValue());
118    }
119
120    @Override
121    void indexSimpleValue(IndexMode indexMode) {
122        pl.indexTopicValue(id, indexMode, typeUri, getIndexValue());
123    }
124
125    // ---
126
127    @Override
128    void updateChildTopics(ChildTopicsModel childTopics) {
129        update(mf.newTopicModel(childTopics));
130    }
131
132    @Override
133    void _delete() {
134        pl._deleteTopic(id);
135    }
136
137    // ---
138
139    @Override
140    DeepaMehtaEvent getPreGetEvent() {
141        return CoreEvent.PRE_GET_TOPIC;
142    }
143
144    @Override
145    DeepaMehtaEvent getPreUpdateEvent() {
146        return CoreEvent.PRE_UPDATE_TOPIC;
147    }
148
149    @Override
150    DeepaMehtaEvent getPostUpdateEvent() {
151        return CoreEvent.POST_UPDATE_TOPIC;
152    }
153
154    @Override
155    DeepaMehtaEvent getPreDeleteEvent() {
156        return CoreEvent.PRE_DELETE_TOPIC;
157    }
158
159    @Override
160    DeepaMehtaEvent getPostDeleteEvent() {
161        return CoreEvent.POST_DELETE_TOPIC;
162    }
163
164    // ---
165
166    @Override
167    Directive getUpdateDirective() {
168        return Directive.UPDATE_TOPIC;
169    }
170
171    @Override
172    Directive getDeleteDirective() {
173        return Directive.DELETE_TOPIC;
174    }
175
176    // ---
177
178    TopicModelImpl findChildTopic(String topicTypeUri) {
179        if (typeUri.equals(topicTypeUri)) {
180            return this;
181        }
182        //
183        for (AssociationDefinitionModel assocDef : getType().getAssocDefs()) {
184            String assocDefUri    = assocDef.getAssocDefUri();
185            String cardinalityUri = assocDef.getChildCardinalityUri();
186            TopicModelImpl childTopic = null;
187            if (cardinalityUri.equals("dm4.core.one")) {
188                childTopic = childTopics.getTopicOrNull(assocDefUri);                                // no load from DB
189            } else if (cardinalityUri.equals("dm4.core.many")) {
190                List<RelatedTopicModelImpl> _childTopics = childTopics.getTopicsOrNull(assocDefUri); // no load from DB
191                if (_childTopics != null && !_childTopics.isEmpty()) {
192                    childTopic = _childTopics.get(0);
193                }
194            } else {
195                throw new RuntimeException("\"" + cardinalityUri + "\" is an unexpected cardinality URI");
196            }
197            // Note: topics just created have no child topics yet
198            if (childTopic == null) {
199                continue;
200            }
201            // recursion
202            childTopic = childTopic.findChildTopic(topicTypeUri);
203            if (childTopic != null) {
204                return childTopic;
205            }
206        }
207        return null;
208    }
209
210
211
212    // ------------------------------------------------------------------------------------------------- Private Methods
213
214    private void reassignInstantiation() {
215        // remove current assignment
216        fetchInstantiation().delete();
217        // create new assignment
218        pl.createTopicInstantiation(id, typeUri);
219    }
220
221    // Note: this method works only for instances, not for types.
222    // This is because a type is not of type "dm4.core.topic_type" but of type "dm4.core.meta_type".
223    private AssociationModelImpl fetchInstantiation() {
224        RelatedTopicModelImpl topicType = getRelatedTopic("dm4.core.instantiation", "dm4.core.instance",
225            "dm4.core.type", "dm4.core.topic_type");
226        //
227        if (topicType == null) {
228            throw new RuntimeException("Topic " + id + " is not associated to a topic type");
229        }
230        //
231        return topicType.getRelatingAssociation();
232    }
233}