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 Object getProperty(String propUri) { 166 return dms.storageDecorator.fetchTopicProperty(getId(), propUri); 167 } 168 169 @Override 170 public void setProperty(String propUri, Object propValue, boolean addToIndex) { 171 dms.storageDecorator.storeTopicProperty(getId(), propUri, propValue, addToIndex); 172 } 173 174 @Override 175 public boolean hasProperty(String propUri) { 176 return dms.storageDecorator.hasTopicProperty(getId(), propUri); 177 } 178 179 @Override 180 public void removeProperty(String propUri) { 181 dms.storageDecorator.removeTopicProperty(getId(), propUri); 182 } 183 184 185 186 // ----------------------------------------------------------------------------------------- Package Private Methods 187 188 /** 189 * Convenience method. 190 */ 191 TopicType getTopicType() { 192 return (TopicType) getType(); 193 } 194 195 /** 196 * Low-level update method which does not fire the POST_UPDATE_TOPIC_REQUEST event. 197 * <p> 198 * Called multiple times while updating the child topics (see AttachedChildTopics). 199 * POST_UPDATE_TOPIC_REQUEST on the other hand must be fired only once (per update request). 200 */ 201 void _update(TopicModel model) { 202 logger.info("Updating topic " + getId() + " (new " + model + ")"); 203 // 204 dms.fireEvent(CoreEvent.PRE_UPDATE_TOPIC, this, model); 205 // 206 TopicModel oldModel = getModel().clone(); 207 super.update(model); 208 // 209 dms.fireEvent(CoreEvent.POST_UPDATE_TOPIC, this, model, oldModel); 210 } 211 212 213 214 // === Implementation of the abstract methods === 215 216 @Override 217 String className() { 218 return "topic"; 219 } 220 221 @Override 222 Directive getUpdateDirective() { 223 return Directive.UPDATE_TOPIC; 224 } 225 226 @Override 227 final void storeUri() { 228 dms.storageDecorator.storeTopicUri(getId(), getUri()); 229 } 230 231 @Override 232 final void storeTypeUri() { 233 reassignInstantiation(); 234 dms.storageDecorator.storeTopicTypeUri(getId(), getTypeUri()); 235 } 236 237 // --- 238 239 @Override 240 final RelatedTopicModel fetchRelatedTopic(String assocTypeUri, String myRoleTypeUri, 241 String othersRoleTypeUri, String othersTopicTypeUri) { 242 return dms.storageDecorator.fetchTopicRelatedTopic(getId(), assocTypeUri, myRoleTypeUri, othersRoleTypeUri, 243 othersTopicTypeUri); 244 } 245 246 @Override 247 final ResultList<RelatedTopicModel> fetchRelatedTopics(String assocTypeUri, String myRoleTypeUri, 248 String othersRoleTypeUri, String othersTopicTypeUri, 249 int maxResultSize) { 250 return dms.storageDecorator.fetchTopicRelatedTopics(getId(), assocTypeUri, myRoleTypeUri, othersRoleTypeUri, 251 othersTopicTypeUri, maxResultSize); 252 } 253 254 255 256 // ------------------------------------------------------------------------------------------------- Private Methods 257 258 private void reassignInstantiation() { 259 // remove current assignment 260 fetchInstantiation().delete(); 261 // create new assignment 262 dms.createTopicInstantiation(getId(), getTypeUri()); 263 } 264 265 // Note: this method works only for instances, not for types. 266 // This is because a type is not of type "dm4.core.topic_type" but of type "dm4.core.meta_type". 267 private Association fetchInstantiation() { 268 RelatedTopic topicType = getRelatedTopic("dm4.core.instantiation", "dm4.core.instance", "dm4.core.type", 269 "dm4.core.topic_type"); 270 // 271 if (topicType == null) { 272 throw new RuntimeException("Topic " + getId() + " is not associated to a topic type"); 273 } 274 // 275 return topicType.getRelatingAssociation(); 276 } 277 }