001 package de.deepamehta.core.impl;
002
003 import de.deepamehta.core.Association;
004 import de.deepamehta.core.RelatedAssociation;
005 import de.deepamehta.core.RelatedTopic;
006 import de.deepamehta.core.Topic;
007 import de.deepamehta.core.TopicType;
008 import de.deepamehta.core.model.AssociationModel;
009 import de.deepamehta.core.model.RelatedAssociationModel;
010 import de.deepamehta.core.model.RelatedTopicModel;
011 import de.deepamehta.core.model.SimpleValue;
012 import de.deepamehta.core.model.TopicModel;
013 import de.deepamehta.core.service.Directive;
014 import de.deepamehta.core.service.Directives;
015 import de.deepamehta.core.service.ResultList;
016
017 import java.util.List;
018 import java.util.logging.Logger;
019
020
021
022 /**
023 * A topic that is attached to the {@link DeepaMehtaService}.
024 */
025 class AttachedTopic extends AttachedDeepaMehtaObject implements Topic {
026
027 // ---------------------------------------------------------------------------------------------- Instance Variables
028
029 private Logger logger = Logger.getLogger(getClass().getName());
030
031 // ---------------------------------------------------------------------------------------------------- Constructors
032
033 AttachedTopic(TopicModel model, EmbeddedService dms) {
034 super(model, dms);
035 }
036
037 // -------------------------------------------------------------------------------------------------- Public Methods
038
039
040
041 // ******************************************
042 // *** AttachedDeepaMehtaObject Overrides ***
043 // ******************************************
044
045
046
047 // === Updating ===
048
049 @Override
050 public void update(TopicModel model) {
051 // Note: the child topics are not needed for the actual update operation but for refreshing the label.
052 // ### TODO: refactor labeling. Child topics involved in labeling should be loaded on demand.
053 loadChildTopics();
054 //
055 _update(model);
056 //
057 dms.fireEvent(CoreEvent.POST_UPDATE_TOPIC_REQUEST, this);
058 }
059
060
061
062 // === Deletion ===
063
064 @Override
065 public void delete() {
066 try {
067 dms.fireEvent(CoreEvent.PRE_DELETE_TOPIC, this);
068 //
069 // delete sub-topics and associations
070 super.delete();
071 // delete topic itself
072 logger.info("Deleting " + this);
073 Directives.get().add(Directive.DELETE_TOPIC, this);
074 dms.storageDecorator.deleteTopic(getId());
075 //
076 dms.fireEvent(CoreEvent.POST_DELETE_TOPIC, this);
077 } catch (Exception e) {
078 throw new RuntimeException("Deleting topic failed (" + this + ")", e);
079 }
080 }
081
082
083
084 // ****************************
085 // *** Topic Implementation ***
086 // ****************************
087
088
089
090 @Override
091 public Topic loadChildTopics() {
092 return (Topic) super.loadChildTopics();
093 }
094
095 @Override
096 public Topic loadChildTopics(String childTypeUri) {
097 return (Topic) super.loadChildTopics(childTypeUri);
098 }
099
100 // ---
101
102 @Override
103 public TopicModel getModel() {
104 return (TopicModel) super.getModel();
105 }
106
107
108
109 // ***************************************
110 // *** DeepaMehtaObject Implementation ***
111 // ***************************************
112
113
114
115 // === Traversal ===
116
117 // --- Topic Retrieval ---
118
119 @Override
120 public ResultList<RelatedTopic> getRelatedTopics(List assocTypeUris, String myRoleTypeUri, String othersRoleTypeUri,
121 String othersTopicTypeUri, int maxResultSize) {
122 ResultList<RelatedTopicModel> topics = dms.storageDecorator.fetchTopicRelatedTopics(getId(),
123 assocTypeUris, myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri, maxResultSize);
124 return dms.instantiateRelatedTopics(topics);
125 }
126
127 // --- Association Retrieval ---
128
129 @Override
130 public RelatedAssociation getRelatedAssociation(String assocTypeUri, String myRoleTypeUri,
131 String othersRoleTypeUri, String othersAssocTypeUri) {
132 RelatedAssociationModel assoc = dms.storageDecorator.fetchTopicRelatedAssociation(getId(),
133 assocTypeUri, myRoleTypeUri, othersRoleTypeUri, othersAssocTypeUri);
134 return assoc != null ? dms.instantiateRelatedAssociation(assoc) : null;
135 }
136
137 @Override
138 public ResultList<RelatedAssociation> getRelatedAssociations(String assocTypeUri, String myRoleTypeUri,
139 String othersRoleTypeUri, String othersAssocTypeUri) {
140 ResultList<RelatedAssociationModel> assocs = dms.storageDecorator.fetchTopicRelatedAssociations(getId(),
141 assocTypeUri, myRoleTypeUri, othersRoleTypeUri, othersAssocTypeUri);
142 return dms.instantiateRelatedAssociations(assocs);
143 }
144
145 // ---
146
147 @Override
148 public Association getAssociation(String assocTypeUri, String myRoleTypeUri, String othersRoleTypeUri,
149 long othersTopicId) {
150 AssociationModel assoc = dms.storageDecorator.fetchAssociation(assocTypeUri, getId(), othersTopicId,
151 myRoleTypeUri, othersRoleTypeUri);
152 return assoc != null ? dms.instantiateAssociation(assoc) : null;
153 }
154
155 @Override
156 public List<Association> getAssociations() {
157 return dms.instantiateAssociations(dms.storageDecorator.fetchTopicAssociations(getId()));
158 }
159
160
161
162 // === Properties ===
163
164 @Override
165 public void setProperty(String propUri, Object propValue, boolean addToIndex) {
166 dms.storageDecorator.storeTopicProperty(getId(), propUri, propValue, addToIndex);
167 }
168
169 @Override
170 public void removeProperty(String propUri) {
171 dms.storageDecorator.removeTopicProperty(getId(), propUri);
172 }
173
174
175
176 // ----------------------------------------------------------------------------------------- Package Private Methods
177
178 /**
179 * Convenience method.
180 */
181 TopicType getTopicType() {
182 return (TopicType) getType();
183 }
184
185 /**
186 * Low-level update method which does not fire the POST_UPDATE_TOPIC_REQUEST event.
187 * <p>
188 * Called multiple times while updating the child topics (see AttachedChildTopics).
189 * POST_UPDATE_TOPIC_REQUEST on the other hand must be fired only once (per update request).
190 */
191 void _update(TopicModel model) {
192 logger.info("Updating topic " + getId() + " (new " + model + ")");
193 //
194 dms.fireEvent(CoreEvent.PRE_UPDATE_TOPIC, this, model);
195 //
196 TopicModel oldModel = getModel().clone();
197 super.update(model);
198 //
199 dms.fireEvent(CoreEvent.POST_UPDATE_TOPIC, this, model, oldModel);
200 }
201
202
203
204 // === Implementation of the abstract methods ===
205
206 @Override
207 String className() {
208 return "topic";
209 }
210
211 @Override
212 Directive getUpdateDirective() {
213 return Directive.UPDATE_TOPIC;
214 }
215
216 @Override
217 final void storeUri() {
218 dms.storageDecorator.storeTopicUri(getId(), getUri());
219 }
220
221 @Override
222 final void storeTypeUri() {
223 reassignInstantiation();
224 dms.storageDecorator.storeTopicTypeUri(getId(), getTypeUri());
225 }
226
227 // ---
228
229 @Override
230 final RelatedTopicModel fetchRelatedTopic(String assocTypeUri, String myRoleTypeUri,
231 String othersRoleTypeUri, String othersTopicTypeUri) {
232 return dms.storageDecorator.fetchTopicRelatedTopic(getId(), assocTypeUri, myRoleTypeUri, othersRoleTypeUri,
233 othersTopicTypeUri);
234 }
235
236 @Override
237 final ResultList<RelatedTopicModel> fetchRelatedTopics(String assocTypeUri, String myRoleTypeUri,
238 String othersRoleTypeUri, String othersTopicTypeUri,
239 int maxResultSize) {
240 return dms.storageDecorator.fetchTopicRelatedTopics(getId(), assocTypeUri, myRoleTypeUri, othersRoleTypeUri,
241 othersTopicTypeUri, maxResultSize);
242 }
243
244
245
246 // ------------------------------------------------------------------------------------------------- Private Methods
247
248 private void reassignInstantiation() {
249 // remove current assignment
250 fetchInstantiation().delete();
251 // create new assignment
252 dms.createTopicInstantiation(getId(), getTypeUri());
253 }
254
255 // Note: this method works only for instances, not for types.
256 // This is because a type is not of type "dm4.core.topic_type" but of type "dm4.core.meta_type".
257 private Association fetchInstantiation() {
258 RelatedTopic topicType = getRelatedTopic("dm4.core.instantiation", "dm4.core.instance", "dm4.core.type",
259 "dm4.core.topic_type");
260 //
261 if (topicType == null) {
262 throw new RuntimeException("Topic " + getId() + " is not associated to a topic type");
263 }
264 //
265 return topicType.getRelatingAssociation();
266 }
267 }