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