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        // === Deletion ===
050    
051        @Override
052        public void delete(Directives directives) {
053            DeepaMehtaTransaction tx = dms.beginTx();
054            try {
055                // delete sub-topics and associations
056                super.delete(directives);
057                // delete topic itself
058                logger.info("Deleting " + this);
059                directives.add(Directive.DELETE_TOPIC, this);
060                dms.storageDecorator.deleteTopic(getId());
061                //
062                tx.success();
063            } catch (Exception e) {
064                logger.warning("ROLLBACK!");
065                throw new RuntimeException("Deleting topic failed (" + this + ")", e);
066            } finally {
067                tx.finish();
068            }
069        }
070    
071    
072    
073        // ****************************
074        // *** Topic Implementation ***
075        // ****************************
076    
077    
078    
079        @Override
080        public TopicModel getModel() {
081            return (TopicModel) super.getModel();
082        }
083    
084    
085    
086        // === Updating ===
087    
088        @Override
089        public void update(TopicModel model, ClientState clientState, Directives directives) {
090            logger.info("Updating topic " + getId() + " (new " + model + ")");
091            //
092            dms.fireEvent(CoreEvent.PRE_UPDATE_TOPIC, this, model, directives);
093            //
094            TopicModel oldModel = getModel().clone();
095            super.update(model, clientState, directives);
096            //
097            addUpdateDirective(directives);
098            //
099            dms.fireEvent(CoreEvent.POST_UPDATE_TOPIC, this, model, oldModel, clientState, directives);
100        }
101    
102    
103    
104        // === Traversal ===
105    
106        // --- Association Retrieval ---
107    
108        @Override
109        public RelatedAssociation getRelatedAssociation(String assocTypeUri, String myRoleTypeUri,
110                                                        String othersRoleTypeUri, String othersAssocTypeUri,
111                                                        boolean fetchComposite, boolean fetchRelatingComposite) {
112            RelatedAssociationModel assoc = dms.storageDecorator.fetchTopicRelatedAssociation(getId(), assocTypeUri,
113                myRoleTypeUri, othersRoleTypeUri, othersAssocTypeUri);
114            return assoc != null ? dms.instantiateRelatedAssociation(assoc, fetchComposite, fetchRelatingComposite) : null;
115        }
116    
117        @Override
118        public List<RelatedAssociation> getRelatedAssociations(String assocTypeUri, String myRoleTypeUri,
119                                                               String othersRoleTypeUri, String othersAssocTypeUri,
120                                                               boolean fetchComposite, boolean fetchRelatingComposite) {
121            List<RelatedAssociationModel> assocs = dms.storageDecorator.fetchTopicRelatedAssociations(getId(), assocTypeUri,
122                myRoleTypeUri, othersRoleTypeUri, othersAssocTypeUri);
123            return dms.instantiateRelatedAssociations(assocs, fetchComposite, fetchRelatingComposite);
124        }
125    
126    
127    
128        // ***************************************
129        // *** DeepaMehtaObject Implementation ***
130        // ***************************************
131    
132    
133    
134        // === Traversal ===
135    
136        // --- Topic Retrieval ---
137    
138        @Override
139        public ResultList<RelatedTopic> getRelatedTopics(List assocTypeUris, String myRoleTypeUri, String othersRoleTypeUri,
140                                        String othersTopicTypeUri, boolean fetchComposite, boolean fetchRelatingComposite,
141                                        int maxResultSize) {
142            ResultList<RelatedTopicModel> topics = dms.storageDecorator.fetchTopicRelatedTopics(getId(), assocTypeUris,
143                myRoleTypeUri, othersRoleTypeUri, othersTopicTypeUri, maxResultSize);
144            return dms.instantiateRelatedTopics(topics, fetchComposite, fetchRelatingComposite);
145        }
146    
147        // --- Association Retrieval ---
148    
149        @Override
150        public Association getAssociation(String assocTypeUri, String myRoleTypeUri, String othersRoleTypeUri,
151                                                                                       long othersTopicId) {
152            AssociationModel assoc = dms.storageDecorator.fetchAssociation(assocTypeUri, getId(), othersTopicId,
153                myRoleTypeUri, othersRoleTypeUri);
154            return assoc != null ? dms.instantiateAssociation(assoc, false) : null;     // fetchComposite=false
155        }
156    
157        @Override
158        public List<Association> getAssociations() {
159            return dms.instantiateAssociations(dms.storageDecorator.fetchTopicAssociations(getId()), false);
160                                                                                        // fetchComposite=false
161        }
162    
163    
164    
165        // === Properties ===
166    
167        @Override
168        public Object getProperty(String propUri) {
169            return dms.storageDecorator.fetchTopicProperty(getId(), propUri);
170        }
171    
172        @Override
173        public void setProperty(String propUri, Object propValue, boolean addToIndex) {
174            dms.storageDecorator.storeTopicProperty(getId(), propUri, propValue, addToIndex);
175        }
176    
177        @Override
178        public boolean hasProperty(String propUri) {
179            return dms.storageDecorator.hasTopicProperty(getId(), propUri);
180        }
181    
182        @Override
183        public void removeProperty(String propUri) {
184            dms.storageDecorator.removeTopicProperty(getId(), propUri);
185        }
186    
187    
188    
189        // ----------------------------------------------------------------------------------------- Package Private Methods
190    
191        /**
192         * Convenience method.
193         */
194        TopicType getTopicType() {
195            return (TopicType) getType();
196        }
197    
198    
199    
200        // === Implementation of the abstract methods ===
201    
202        @Override
203        String className() {
204            return "topic";
205        }
206    
207        @Override
208        void addUpdateDirective(Directives directives) {
209            directives.add(Directive.UPDATE_TOPIC, this);
210        }
211    
212        @Override
213        final void storeUri() {
214            dms.storageDecorator.storeTopicUri(getId(), getUri());
215        }
216    
217        @Override
218        final void storeTypeUri() {
219            reassignInstantiation();
220            dms.storageDecorator.storeTopicTypeUri(getId(), getTypeUri());
221        }
222    
223        // ---
224    
225        @Override
226        final RelatedTopicModel fetchRelatedTopic(String assocTypeUri, String myRoleTypeUri,
227                                                  String othersRoleTypeUri, String othersTopicTypeUri) {
228            return dms.storageDecorator.fetchTopicRelatedTopic(getId(), assocTypeUri, myRoleTypeUri, othersRoleTypeUri,
229                othersTopicTypeUri);
230        }
231    
232        @Override
233        final ResultList<RelatedTopicModel> fetchRelatedTopics(String assocTypeUri, String myRoleTypeUri,
234                                                              String othersRoleTypeUri, String othersTopicTypeUri,
235                                                              int maxResultSize) {
236            return dms.storageDecorator.fetchTopicRelatedTopics(getId(), assocTypeUri, myRoleTypeUri, othersRoleTypeUri,
237                othersTopicTypeUri, maxResultSize);
238        }
239    
240    
241    
242        // ------------------------------------------------------------------------------------------------- Private Methods
243    
244        private void reassignInstantiation() {
245            // remove current assignment
246            fetchInstantiation().delete(new Directives());      // ### FIXME: receive directives as argument
247            // create new assignment
248            dms.createTopicInstantiation(getId(), getTypeUri());
249        }
250    
251        // Note: this method works only for instances, not for types.
252        // This is because a type is not of type "dm4.core.topic_type" but of type "dm4.core.meta_type".
253        private Association fetchInstantiation() {
254            RelatedTopic topicType = getRelatedTopic("dm4.core.instantiation", "dm4.core.instance", "dm4.core.type",
255                "dm4.core.topic_type", false, false);
256            //
257            if (topicType == null) {
258                throw new RuntimeException("Topic " + getId() + " is not associated to a topic type");
259            }
260            //
261            return topicType.getRelatingAssociation();
262        }
263    }