001    package de.deepamehta.plugins.typeeditor;
002    
003    import de.deepamehta.core.Association;
004    import de.deepamehta.core.Topic;
005    import de.deepamehta.core.Type;
006    import de.deepamehta.core.model.AssociationModel;
007    import de.deepamehta.core.model.AssociationDefinitionModel;
008    import de.deepamehta.core.osgi.PluginActivator;
009    import de.deepamehta.core.service.ClientState;
010    import de.deepamehta.core.service.Directive;
011    import de.deepamehta.core.service.Directives;
012    import de.deepamehta.core.service.event.PostDeleteAssociationListener;
013    import de.deepamehta.core.service.event.PostUpdateAssociationListener;
014    
015    import java.util.logging.Logger;
016    
017    
018    
019    public class TypeEditorPlugin extends PluginActivator implements PostUpdateAssociationListener,
020                                                                     PostDeleteAssociationListener {
021    
022        // ---------------------------------------------------------------------------------------------- Instance Variables
023    
024        private Logger logger = Logger.getLogger(getClass().getName());
025    
026        // -------------------------------------------------------------------------------------------------- Public Methods
027    
028    
029    
030        // ********************************
031        // *** Listener Implementations ***
032        // ********************************
033    
034    
035    
036        @Override
037        public void postUpdateAssociation(Association assoc, AssociationModel oldModel, ClientState clientState,
038                                                                                        Directives directives) {
039            if (isAssocDef(assoc.getModel())) {
040                if (isAssocDef(oldModel)) {
041                    updateAssocDef(assoc, directives);
042                } else {
043                    createAssocDef(assoc, directives);
044                }
045            } else if (isAssocDef(oldModel)) {
046                removeAssocDef(assoc, directives);
047            }
048        }
049    
050        @Override
051        public void postDeleteAssociation(Association assoc, Directives directives) {
052            if (isAssocDef(assoc.getModel())) {
053                removeAssocDef(assoc, directives);
054            }
055        }
056    
057    
058    
059        // ------------------------------------------------------------------------------------------------- Private Methods
060    
061        private void createAssocDef(Association assoc, Directives directives) {
062            Type parentType = fetchParentType(assoc);
063            String childTypeUri = fetchChildType(assoc).getUri();
064            // Note: the assoc def's ID is already known. Setting it explicitely
065            // prevents the core from creating the underlying association.
066            AssociationDefinitionModel assocDef = new AssociationDefinitionModel(
067                assoc.getId(), assoc.getUri(), assoc.getTypeUri(),
068                parentType.getUri(), childTypeUri, "dm4.core.one", "dm4.core.one",
069                null    // viewConfigModel=null
070            );
071            logger.info("### Adding association definition \"" + childTypeUri + "\" to type \"" + parentType.getUri() +
072                "\" (" + assocDef + ")");
073            //
074            parentType.addAssocDef(assocDef);
075            //
076            addUpdateTypeDirective(parentType, directives);
077        }
078    
079        private void updateAssocDef(Association assoc, Directives directives) {
080            Type parentType = fetchParentType(assoc);
081            AssociationDefinitionModel assocDef = dms.getTypeStorage().fetchAssociationDefinition(assoc);
082            logger.info("### Updating association definition \"" + assocDef.getChildTypeUri() + "\" of type \"" +
083                parentType.getUri() + "\" (" + assocDef + ")");
084            //
085            parentType.updateAssocDef(assocDef);
086            //
087            addUpdateTypeDirective(parentType, directives);
088        }
089    
090        private void removeAssocDef(Association assoc, Directives directives) {
091            Type parentType = fetchParentType(assoc);
092            String childTypeUri = fetchChildType(assoc).getUri();
093            logger.info("### Removing association definition \"" + childTypeUri + "\" from type \"" + parentType.getUri() +
094                "\"");
095            //
096            parentType.removeAssocDef(childTypeUri);
097            //
098            addUpdateTypeDirective(parentType, directives);
099        }
100    
101    
102    
103        // === Helper ===
104    
105        private boolean isAssocDef(AssociationModel assoc) {
106            String typeUri = assoc.getTypeUri();
107            if (!typeUri.equals("dm4.core.aggregation_def") &&
108                !typeUri.equals("dm4.core.composition_def")) {
109                return false;
110            }
111            //
112            if (assoc.hasSameRoleTypeUris()) {
113                return false;
114            }
115            //
116            if (assoc.getRoleModel("dm4.core.parent_type") == null ||
117                assoc.getRoleModel("dm4.core.child_type") == null)  {
118                return false;
119            }
120            //
121            return true;
122        }
123    
124        private void addUpdateTypeDirective(Type type, Directives directives) {
125            if (type.getTypeUri().equals("dm4.core.topic_type")) {
126                directives.add(Directive.UPDATE_TOPIC_TYPE, type);
127            } else if (type.getTypeUri().equals("dm4.core.assoc_type")) {
128                directives.add(Directive.UPDATE_ASSOCIATION_TYPE, type);
129            }
130            // Note: no else here as error check already performed in fetchParentType()
131        }
132    
133        // ---
134    
135        private Type fetchParentType(Association assoc) {
136            Topic type = dms.getTypeStorage().fetchParentType(assoc);
137            String typeUri = type.getTypeUri();
138            if (typeUri.equals("dm4.core.topic_type")) {
139                return dms.getTopicType(type.getUri());
140            } else if (typeUri.equals("dm4.core.assoc_type")) {
141                return dms.getAssociationType(type.getUri());
142            } else {
143                throw new RuntimeException("Invalid association definition: the dm4.core.parent_type " +
144                    "player is not a type but of type \"" + typeUri + "\" (" + assoc + ")");
145            }
146        }
147    
148        private Topic fetchChildType(Association assoc) {
149            return dms.getTypeStorage().fetchChildType(assoc);
150        }
151    }