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 // --- 157 158 @Override 159 final DeepaMehtaEvent getPreUpdateEvent() { 160 return CoreEvent.PRE_UPDATE_TOPIC; 161 } 162 163 @Override 164 final DeepaMehtaEvent getPostUpdateEvent() { 165 return CoreEvent.POST_UPDATE_TOPIC; 166 } 167 168 @Override 169 final DeepaMehtaEvent getPreDeleteEvent() { 170 return CoreEvent.PRE_DELETE_TOPIC; 171 } 172 173 @Override 174 final DeepaMehtaEvent getPostDeleteEvent() { 175 return CoreEvent.POST_DELETE_TOPIC; 176 } 177 178 // --- 179 180 @Override 181 final Directive getUpdateDirective() { 182 return Directive.UPDATE_TOPIC; 183 } 184 185 @Override 186 final Directive getDeleteDirective() { 187 return Directive.DELETE_TOPIC; 188 } 189 190 191 192 // === Core Internal Hooks === 193 194 @Override 195 void preDelete() { 196 if (typeUri.equals("dm4.core.topic_type") || typeUri.equals("dm4.core.assoc_type")) { 197 throw new RuntimeException("Tried to delete a type with a generic delete-topic call. " + 198 "Use a delete-type call instead."); 199 } 200 } 201 202 203 204 // === 205 206 TopicModelImpl findChildTopic(String topicTypeUri) { 207 try { 208 if (typeUri.equals(topicTypeUri)) { 209 return this; 210 } 211 // 212 for (AssociationDefinitionModel assocDef : getType().getAssocDefs()) { 213 String assocDefUri = assocDef.getAssocDefUri(); 214 String cardinalityUri = assocDef.getChildCardinalityUri(); 215 TopicModelImpl childTopic = null; 216 if (cardinalityUri.equals("dm4.core.one")) { 217 childTopic = childTopics.getTopicOrNull(assocDefUri); // no DB access 218 } else if (cardinalityUri.equals("dm4.core.many")) { 219 List<RelatedTopicModelImpl> _childTopics = childTopics.getTopicsOrNull(assocDefUri); // no DB access 220 if (_childTopics != null && !_childTopics.isEmpty()) { 221 childTopic = _childTopics.get(0); 222 } 223 } else { 224 throw new RuntimeException("\"" + cardinalityUri + "\" is an unexpected cardinality URI"); 225 } 226 // Note: topics just created have no child topics yet 227 if (childTopic == null) { 228 continue; 229 } 230 // recursion 231 childTopic = childTopic.findChildTopic(topicTypeUri); 232 if (childTopic != null) { 233 return childTopic; 234 } 235 } 236 return null; 237 } catch (Exception e) { 238 throw new RuntimeException("Searching topic " + id + " for \"" + topicTypeUri + "\" failed", e); 239 } 240 } 241 242 243 244 // ------------------------------------------------------------------------------------------------- Private Methods 245 246 private void reassignInstantiation() { 247 // remove current assignment 248 fetchInstantiation().delete(); 249 // create new assignment 250 pl.createTopicInstantiation(id, typeUri); 251 } 252 253 // Note: this method works only for instances, not for types. 254 // This is because a type is not of type "dm4.core.topic_type" but of type "dm4.core.meta_type". 255 private AssociationModelImpl fetchInstantiation() { 256 RelatedTopicModelImpl topicType = getRelatedTopic("dm4.core.instantiation", "dm4.core.instance", 257 "dm4.core.type", "dm4.core.topic_type"); 258 // 259 if (topicType == null) { 260 throw new RuntimeException("Topic " + id + " is not associated to a topic type"); 261 } 262 // 263 return topicType.getRelatingAssociation(); 264 } 265}