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.ClientState; 014 import de.deepamehta.core.service.Directive; 015 import de.deepamehta.core.service.Directives; 016 import de.deepamehta.core.service.ResultList; 017 import de.deepamehta.core.storage.spi.DeepaMehtaTransaction; 018 019 import java.util.List; 020 import java.util.logging.Logger; 021 022 023 024 /** 025 * A topic that is attached to the {@link DeepaMehtaService}. 026 */ 027 class AttachedTopic extends AttachedDeepaMehtaObject implements Topic { 028 029 // ---------------------------------------------------------------------------------------------- Instance Variables 030 031 private Logger logger = Logger.getLogger(getClass().getName()); 032 033 // ---------------------------------------------------------------------------------------------------- Constructors 034 035 AttachedTopic(TopicModel model, EmbeddedService dms) { 036 super(model, dms); 037 } 038 039 // -------------------------------------------------------------------------------------------------- Public Methods 040 041 042 043 // ****************************************** 044 // *** AttachedDeepaMehtaObject Overrides *** 045 // ****************************************** 046 047 048 049 // === Updating === 050 051 @Override 052 public void update(TopicModel model, ClientState clientState, Directives directives) { 053 _update(model, clientState, directives); 054 // 055 dms.fireEvent(CoreEvent.POST_UPDATE_TOPIC_REQUEST, this); 056 } 057 058 059 060 // === Deletion === 061 062 @Override 063 public void delete(Directives directives) { 064 DeepaMehtaTransaction tx = dms.beginTx(); 065 try { 066 dms.fireEvent(CoreEvent.PRE_DELETE_TOPIC, this, directives); 067 // 068 // delete sub-topics and associations 069 super.delete(directives); 070 // delete topic itself 071 logger.info("Deleting " + this); 072 directives.add(Directive.DELETE_TOPIC, this); 073 dms.storageDecorator.deleteTopic(getId()); 074 // 075 tx.success(); 076 // 077 dms.fireEvent(CoreEvent.POST_DELETE_TOPIC, this, directives); 078 } catch (Exception e) { 079 logger.warning("ROLLBACK!"); 080 throw new RuntimeException("Deleting topic failed (" + this + ")", e); 081 } finally { 082 tx.finish(); 083 } 084 } 085 086 087 088 // **************************** 089 // *** Topic Implementation *** 090 // **************************** 091 092 093 094 @Override 095 public TopicModel getModel() { 096 return (TopicModel) super.getModel(); 097 } 098 099 100 101 // === Traversal === 102 103 // --- Association Retrieval --- 104 105 @Override 106 public RelatedAssociation getRelatedAssociation(String assocTypeUri, String myRoleTypeUri, 107 String othersRoleTypeUri, String othersAssocTypeUri, 108 boolean fetchComposite, boolean fetchRelatingComposite) { 109 RelatedAssociationModel assoc = dms.storageDecorator.fetchTopicRelatedAssociation(getId(), assocTypeUri, 110 myRoleTypeUri, othersRoleTypeUri, othersAssocTypeUri); 111 return assoc != null ? dms.instantiateRelatedAssociation(assoc, fetchComposite, fetchRelatingComposite) : null; 112 } 113 114 @Override 115 public List<RelatedAssociation> getRelatedAssociations(String assocTypeUri, String myRoleTypeUri, 116 String othersRoleTypeUri, String othersAssocTypeUri, 117 boolean fetchComposite, boolean fetchRelatingComposite) { 118 List<RelatedAssociationModel> assocs = dms.storageDecorator.fetchTopicRelatedAssociations(getId(), assocTypeUri, 119 myRoleTypeUri, othersRoleTypeUri, othersAssocTypeUri); 120 return dms.instantiateRelatedAssociations(assocs, fetchComposite, fetchRelatingComposite); 121 } 122 123 124 125 // *************************************** 126 // *** DeepaMehtaObject Implementation *** 127 // *************************************** 128 129 130 131 // === Traversal === 132 133 // --- Topic Retrieval --- 134 135 @Override 136 public ResultList<RelatedTopic> getRelatedTopics(List assocTypeUris, String myRoleTypeUri, String othersRoleTypeUri, 137 String othersTopicTypeUri, boolean fetchComposite, boolean fetchRelatingComposite, 138 int maxResultSize) { 139 ResultList<RelatedTopicModel> topics = dms.storageDecorator.fetchTopicRelatedTopics(getId(), assocTypeUris, 140 myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri, maxResultSize); 141 return dms.instantiateRelatedTopics(topics, fetchComposite, fetchRelatingComposite); 142 } 143 144 // --- Association Retrieval --- 145 146 @Override 147 public Association getAssociation(String assocTypeUri, String myRoleTypeUri, String othersRoleTypeUri, 148 long othersTopicId) { 149 AssociationModel assoc = dms.storageDecorator.fetchAssociation(assocTypeUri, getId(), othersTopicId, 150 myRoleTypeUri, othersRoleTypeUri); 151 return assoc != null ? dms.instantiateAssociation(assoc, false) : null; // fetchComposite=false 152 } 153 154 @Override 155 public List<Association> getAssociations() { 156 return dms.instantiateAssociations(dms.storageDecorator.fetchTopicAssociations(getId()), false); 157 // fetchComposite=false 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 a composite value (see AttachedCompositeValue). 199 * POST_UPDATE_TOPIC_REQUEST on the other hand must be fired only once (per update request). 200 */ 201 void _update(TopicModel model, ClientState clientState, Directives directives) { 202 logger.info("Updating topic " + getId() + " (new " + model + ")"); 203 // 204 dms.fireEvent(CoreEvent.PRE_UPDATE_TOPIC, this, model, directives); 205 // 206 TopicModel oldModel = getModel().clone(); 207 super.update(model, clientState, directives); 208 // 209 addUpdateDirective(directives); 210 // 211 dms.fireEvent(CoreEvent.POST_UPDATE_TOPIC, this, model, oldModel, clientState, directives); 212 } 213 214 215 216 // === Implementation of the abstract methods === 217 218 @Override 219 String className() { 220 return "topic"; 221 } 222 223 @Override 224 void addUpdateDirective(Directives directives) { 225 directives.add(Directive.UPDATE_TOPIC, this); 226 } 227 228 @Override 229 final void storeUri() { 230 dms.storageDecorator.storeTopicUri(getId(), getUri()); 231 } 232 233 @Override 234 final void storeTypeUri() { 235 reassignInstantiation(); 236 dms.storageDecorator.storeTopicTypeUri(getId(), getTypeUri()); 237 } 238 239 // --- 240 241 @Override 242 final RelatedTopicModel fetchRelatedTopic(String assocTypeUri, String myRoleTypeUri, 243 String othersRoleTypeUri, String othersTopicTypeUri) { 244 return dms.storageDecorator.fetchTopicRelatedTopic(getId(), assocTypeUri, myRoleTypeUri, othersRoleTypeUri, 245 othersTopicTypeUri); 246 } 247 248 @Override 249 final ResultList<RelatedTopicModel> fetchRelatedTopics(String assocTypeUri, String myRoleTypeUri, 250 String othersRoleTypeUri, String othersTopicTypeUri, 251 int maxResultSize) { 252 return dms.storageDecorator.fetchTopicRelatedTopics(getId(), assocTypeUri, myRoleTypeUri, othersRoleTypeUri, 253 othersTopicTypeUri, maxResultSize); 254 } 255 256 257 258 // ------------------------------------------------------------------------------------------------- Private Methods 259 260 private void reassignInstantiation() { 261 // remove current assignment 262 fetchInstantiation().delete(new Directives()); // ### FIXME: receive directives as argument 263 // create new assignment 264 dms.createTopicInstantiation(getId(), getTypeUri()); 265 } 266 267 // Note: this method works only for instances, not for types. 268 // This is because a type is not of type "dm4.core.topic_type" but of type "dm4.core.meta_type". 269 private Association fetchInstantiation() { 270 RelatedTopic topicType = getRelatedTopic("dm4.core.instantiation", "dm4.core.instance", "dm4.core.type", 271 "dm4.core.topic_type", false, false); 272 // 273 if (topicType == null) { 274 throw new RuntimeException("Topic " + getId() + " is not associated to a topic type"); 275 } 276 // 277 return topicType.getRelatingAssociation(); 278 } 279 }