001    package de.deepamehta.plugins.facets;
002    
003    import de.deepamehta.plugins.facets.service.FacetsService;
004    
005    import de.deepamehta.core.Association;
006    import de.deepamehta.core.AssociationDefinition;
007    import de.deepamehta.core.DeepaMehtaObject;
008    import de.deepamehta.core.RelatedTopic;
009    import de.deepamehta.core.Topic;
010    import de.deepamehta.core.model.AssociationModel;
011    import de.deepamehta.core.model.TopicModel;
012    import de.deepamehta.core.model.TopicRoleModel;
013    import de.deepamehta.core.osgi.PluginActivator;
014    import de.deepamehta.core.service.ClientState;
015    import de.deepamehta.core.service.Directives;
016    
017    import java.util.List;
018    import java.util.logging.Logger;
019    
020    
021    
022    public class FacetsPlugin extends PluginActivator implements FacetsService {
023    
024        // ---------------------------------------------------------------------------------------------- Instance Variables
025    
026        private Logger logger = Logger.getLogger(getClass().getName());
027    
028        // -------------------------------------------------------------------------------------------------- Public Methods
029    
030    
031    
032        // ************************************
033        // *** FacetsService Implementation ***
034        // ************************************
035    
036    
037    
038        @Override
039        public Topic getFacet(long topicId, String facetTypeUri) {
040            Topic topic = dms.getTopic(topicId, false);                         // fetchComposite=false
041            return getFacet(topic, facetTypeUri);
042        }
043    
044        @Override
045        public Topic getFacet(DeepaMehtaObject object, String facetTypeUri) {
046            // ### TODO: integrity check: is the object an instance of that facet type?
047            return fetchChildTopic(object, getAssocDef(facetTypeUri), true);    // fetchComposite=true
048        }
049    
050        // ---
051    
052        @Override
053        public List<RelatedTopic> getFacets(DeepaMehtaObject object, String facetTypeUri) {
054            // ### TODO: integrity check: is the object an instance of that facet type?
055            return fetchChildTopics(object, getAssocDef(facetTypeUri), true);   // fetchComposite=true
056        }
057    
058        // ---
059    
060        @Override
061        public void addFacetTypeToTopic(long topicId, String facetTypeUri) {
062            dms.createAssociation(new AssociationModel("dm4.core.instantiation",
063                new TopicRoleModel(topicId,      "dm4.core.instance"),
064                new TopicRoleModel(facetTypeUri, "dm4.facets.facet")), null);   // clientState=null
065        }
066    
067        // ---
068    
069        @Override
070        public void updateFacet(DeepaMehtaObject object, String facetTypeUri, TopicModel facetValue,
071                                                         ClientState clientState, Directives directives) {
072            // ### TODO: incorporate the Facets module into the DeepaMehta core?
073            object.updateChildTopic(facetValue, getAssocDef(facetTypeUri), clientState, directives);
074        }
075    
076        @Override
077        public void updateFacets(DeepaMehtaObject object, String facetTypeUri, List<? extends TopicModel> facetValues,
078                                                          ClientState clientState, Directives directives) {
079            // ### TODO: incorporate the Facets module into the DeepaMehta core?
080            object.updateChildTopics(facetValues, getAssocDef(facetTypeUri), clientState, directives);
081        }
082    
083        // ---
084    
085        // Note: there is a similar private method in AttachedDeepaMehtaObject:
086        // fetchChildTopic(AssociationDefinition assocDef, long childTopicId, boolean fetchComposite)
087        // ### TODO: Extend DeepaMehtaObject interface by hasChildTopic()?
088        @Override
089        public boolean hasFacet(long topicId, String facetTypeUri, long facetTopicId) {
090            String assocTypeUri = getAssocDef(facetTypeUri).getInstanceLevelAssocTypeUri();
091            Association assoc = dms.getAssociation(assocTypeUri, topicId, facetTopicId, "dm4.core.parent", "dm4.core.child",
092                false);     // fetchComposite=false
093            return assoc != null;
094        }
095    
096    
097    
098        // ------------------------------------------------------------------------------------------------- Private Methods
099    
100        /**
101         * Fetches and returns a child topic or <code>null</code> if no such topic extists.
102         * <p>
103         * Note: There is a principal copy in AttachedDeepaMehtaObject but here the precondition is different:
104         * The given association definition must not necessarily originate from the given object's type definition.
105         * ### TODO: meanwhile we have the ValueStorage. Can we use its method instead?
106         */
107        private RelatedTopic fetchChildTopic(DeepaMehtaObject object, AssociationDefinition assocDef,
108                                                                      boolean fetchComposite) {
109            String assocTypeUri  = assocDef.getInstanceLevelAssocTypeUri();
110            String othersTypeUri = assocDef.getChildTypeUri();
111            return object.getRelatedTopic(assocTypeUri, "dm4.core.parent", "dm4.core.child", othersTypeUri, fetchComposite,
112                false);
113        }
114    
115        /**
116         * Fetches and returns child topics.
117         * <p>
118         * Note: There is a principal copy in AttachedDeepaMehtaObject but here the precondition is different:
119         * The given association definition must not necessarily originate from the given object's type definition.
120         * ### TODO: meanwhile we have the ValueStorage. Can we use its method instead?
121         */
122        private List<RelatedTopic> fetchChildTopics(DeepaMehtaObject object, AssociationDefinition assocDef,
123                                                                             boolean fetchComposite) {
124            String assocTypeUri  = assocDef.getInstanceLevelAssocTypeUri();
125            String othersTypeUri = assocDef.getChildTypeUri();
126            return object.getRelatedTopics(assocTypeUri, "dm4.core.parent", "dm4.core.child", othersTypeUri, fetchComposite,
127                false, 0).getItems();
128        }
129    
130        // ---
131    
132        private AssociationDefinition getAssocDef(String facetTypeUri) {
133            // Note: a facet type has exactly *one* association definition
134            return dms.getTopicType(facetTypeUri).getAssocDefs().iterator().next();
135        }
136    }