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 TopicImpl instantiate() { 066 return new TopicImpl(this, pl); 067 } 068 069 @Override 070 final TopicModelImpl createModelWithChildTopics(ChildTopicsModel childTopics) { 071 return mf.newTopicModel(childTopics); 072 } 073 074 // --- 075 076 @Override 077 final TopicTypeModelImpl getType() { 078 return pl.typeStorage.getTopicType(typeUri); 079 } 080 081 @Override 082 final List<AssociationModelImpl> getAssociations() { 083 return pl.fetchTopicAssociations(id); 084 } 085 086 // --- 087 088 @Override 089 final RelatedTopicModelImpl getRelatedTopic(String assocTypeUri, String myRoleTypeUri, String othersRoleTypeUri, 090 String othersTopicTypeUri) { 091 return pl.fetchTopicRelatedTopic(id, assocTypeUri, myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri); 092 } 093 094 @Override 095 final List<RelatedTopicModelImpl> getRelatedTopics(String assocTypeUri, String myRoleTypeUri, 096 String othersRoleTypeUri, 097 String othersTopicTypeUri) { 098 return pl.fetchTopicRelatedTopics(id, assocTypeUri, myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri); 099 } 100 101 @Override 102 final List<RelatedTopicModelImpl> getRelatedTopics(List assocTypeUris, String myRoleTypeUri, 103 String othersRoleTypeUri, 104 String othersTopicTypeUri) { 105 return pl.fetchTopicRelatedTopics(id, assocTypeUris, myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri); 106 } 107 108 // --- 109 110 @Override 111 final void storeUri() { 112 pl.storeTopicUri(id, uri); 113 } 114 115 @Override 116 final void storeTypeUri() { 117 reassignInstantiation(); 118 pl.storeTopicTypeUri(id, typeUri); 119 } 120 121 @Override 122 final void storeSimpleValue() { 123 TypeModel type = getType(); 124 pl.storeTopicValue(id, value, type.getIndexModes(), type.getUri(), getIndexValue()); 125 } 126 127 @Override 128 final void indexSimpleValue(IndexMode indexMode) { 129 pl.indexTopicValue(id, indexMode, typeUri, getIndexValue()); 130 } 131 132 @Override 133 final void storeProperty(String propUri, Object propValue, boolean addToIndex) { 134 pl.storeTopicProperty(id, propUri, propValue, addToIndex); 135 } 136 137 @Override 138 final void removeProperty(String propUri) { 139 pl.removeTopicProperty(id, propUri); 140 } 141 142 // --- 143 144 @Override 145 final void _delete() { 146 pl._deleteTopic(id); 147 } 148 149 // --- 150 151 @Override 152 final void checkReadAccess() { 153 pl.checkTopicReadAccess(id); 154 } 155 156 @Override 157 final void checkWriteAccess() { 158 pl.checkTopicWriteAccess(id); 159 } 160 161 // --- 162 163 @Override 164 final DeepaMehtaEvent getPreUpdateEvent() { 165 return CoreEvent.PRE_UPDATE_TOPIC; 166 } 167 168 @Override 169 final DeepaMehtaEvent getPostUpdateEvent() { 170 return CoreEvent.POST_UPDATE_TOPIC; 171 } 172 173 @Override 174 final DeepaMehtaEvent getPreDeleteEvent() { 175 return CoreEvent.PRE_DELETE_TOPIC; 176 } 177 178 @Override 179 final DeepaMehtaEvent getPostDeleteEvent() { 180 return CoreEvent.POST_DELETE_TOPIC; 181 } 182 183 // --- 184 185 @Override 186 final Directive getUpdateDirective() { 187 return Directive.UPDATE_TOPIC; 188 } 189 190 @Override 191 final Directive getDeleteDirective() { 192 return Directive.DELETE_TOPIC; 193 } 194 195 196 197 // === Core Internal Hooks === 198 199 @Override 200 void preDelete() { 201 if (typeUri.equals("dm4.core.topic_type") || typeUri.equals("dm4.core.assoc_type")) { 202 throw new RuntimeException("Tried to delete a type with a generic delete-topic call. " + 203 "Use a delete-type call instead."); 204 } 205 } 206 207 208 209 // === 210 211 TopicModelImpl findChildTopic(String topicTypeUri) { 212 try { 213 if (typeUri.equals(topicTypeUri)) { 214 return this; 215 } 216 // 217 for (AssociationDefinitionModel assocDef : getType().getAssocDefs()) { 218 String assocDefUri = assocDef.getAssocDefUri(); 219 String cardinalityUri = assocDef.getChildCardinalityUri(); 220 TopicModelImpl childTopic = null; 221 if (cardinalityUri.equals("dm4.core.one")) { 222 childTopic = childTopics.getTopicOrNull(assocDefUri); // no DB access 223 } else if (cardinalityUri.equals("dm4.core.many")) { 224 List<RelatedTopicModelImpl> _childTopics = childTopics.getTopicsOrNull(assocDefUri); // no DB access 225 if (_childTopics != null && !_childTopics.isEmpty()) { 226 childTopic = _childTopics.get(0); 227 } 228 } else { 229 throw new RuntimeException("\"" + cardinalityUri + "\" is an unexpected cardinality URI"); 230 } 231 // Note: topics just created have no child topics yet 232 if (childTopic == null) { 233 continue; 234 } 235 // recursion 236 childTopic = childTopic.findChildTopic(topicTypeUri); 237 if (childTopic != null) { 238 return childTopic; 239 } 240 } 241 return null; 242 } catch (Exception e) { 243 throw new RuntimeException("Searching topic " + id + " for \"" + topicTypeUri + "\" failed", e); 244 } 245 } 246 247 248 249 // ------------------------------------------------------------------------------------------------- Private Methods 250 251 private void reassignInstantiation() { 252 // remove current assignment 253 fetchInstantiation().delete(); 254 // create new assignment 255 pl.createTopicInstantiation(id, typeUri); 256 } 257 258 // Note: this method works only for instances, not for types. 259 // This is because a type is not of type "dm4.core.topic_type" but of type "dm4.core.meta_type". 260 private AssociationModelImpl fetchInstantiation() { 261 RelatedTopicModelImpl topicType = getRelatedTopic("dm4.core.instantiation", "dm4.core.instance", 262 "dm4.core.type", "dm4.core.topic_type"); 263 // 264 if (topicType == null) { 265 throw new RuntimeException("Topic " + id + " is not associated to a topic type"); 266 } 267 // 268 return topicType.getRelatingAssociation(); 269 } 270}