001    package nl.tudelft.tbm.eeni.owl2java.generator;
002    
003    import com.hp.hpl.jena.ontology.OntClass;
004    import com.hp.hpl.jena.ontology.OntProperty;
005    import nl.tudelft.tbm.eeni.owl2java.model.jenautils.RestrictionUtils;
006    import nl.tudelft.tbm.eeni.owl2java.model.jmodel.*;
007    import nl.tudelft.tbm.eeni.owl2java.model.jmodel.utils.LogUtils;
008    import org.apache.commons.logging.Log;
009    import org.apache.commons.logging.LogFactory;
010    import org.jgraph.graph.DefaultEdge;
011    import org.jgrapht.traverse.BreadthFirstIterator;
012    
013    import java.util.ArrayList;
014    import java.util.List;
015    
016    
017    public class ModelPreparation {
018    
019        private static Log log = LogFactory.getLog(ModelPreparation.class);
020    
021        private boolean reasignDomainlessProperties;
022        private JModel jModel;
023    
024        JClass baseCls;
025    
026        public JModel prepareModel(JModel model) {
027            jModel = model;
028            baseCls = jModel.getJClass(jModel.getBaseThingUri());
029            log.info("");
030            log.info("Prepaing model for class writer");
031    
032            // assign properties without domain to restrictions
033            if (reasignDomainlessProperties)
034                reasignProperties();
035    
036            // createPropertyRepresentations
037            createDomainPropertyRepresentations();
038    
039            // aggregate properties, restriction containers...
040    
041            int aggregateActions = 1;
042            while (aggregateActions != 0) {
043                aggregateActions = aggregateAllOnClass();
044            }
045    
046    
047            return jModel;
048        }
049    
050        protected void createDomainPropertyRepresentations() {
051            log.info("Creating domain property representations");
052            JClass baseCls = jModel.getBaseThing();
053            JInheritanceGraph<JClass, DefaultEdge> classGraph = jModel.getClassGraph();
054            BreadthFirstIterator<JClass, DefaultEdge> it = new BreadthFirstIterator<JClass, DefaultEdge>(classGraph,
055                    baseCls);
056            it.setCrossComponentTraversal(true);
057            while (it.hasNext()) {
058                JClass c = (JClass) it.next();
059                c.createDomainPropertyRepresentations();
060            }
061        }
062    
063        protected int aggregateAllOnClass() {
064            int aggregateActions = 0;
065            JClass baseCls = jModel.getBaseThing();
066            JInheritanceGraph<JClass, DefaultEdge> classGraph = jModel.getClassGraph();
067            BreadthFirstIterator<JClass, DefaultEdge> it = new BreadthFirstIterator<JClass, DefaultEdge>(classGraph,
068                    baseCls);
069            it.setCrossComponentTraversal(true);
070            while (it.hasNext()) {
071                JClass c = (JClass) it.next();
072                int count = c.aggegrateAll();
073                aggregateActions = aggregateActions + count;
074            }
075            log.info("Aggregating all from parent classes: " + aggregateActions + " Actions");
076            return aggregateActions;
077        }
078    
079        protected boolean reasignProperty(JClass cls, JProperty property) {
080    
081            boolean success = false;
082    
083            // we check for each property, if we have a restriction with the given class
084            // as subject
085            OntClass ontClass = cls.getOntClass();
086            OntProperty ontProperty = property.getOntProperty();
087    
088            if (RestrictionUtils.hasRestrictionOnProperty(ontClass, ontProperty)) {
089                // baseCls as we are only testing base properties here
090                log.debug(LogUtils.toLogName(property) + ": Changing domain from " + LogUtils.toLogName(baseCls) + " to "
091                        + LogUtils.toLogName(cls));
092                property.addDomain(cls);
093    
094                // restriction container is is empty for baseClass > we ignore it (remove would be better)
095    
096                // We no longer have a global property with a local restriction!
097                // -> update "enabled" cardinality status based on cardinality
098                // -> for local restriction "aProperty max 1" disable multiple accessors
099                JRestrictionsContainer rc = cls.getDomainRestrictionsContainer(property);
100                if (rc != null) {
101                    if (rc.hasCardinalityRestriction()) {
102                        if (rc.getCardinalityRestriction().getMaxCardinality() == 1) {
103                            rc.getCardinalityRestriction().setMultipleEnabled(false);
104                            rc.getCardinalityRestriction().setSingleEnabled(true);
105    
106                            // with maxCardinality = 1 this is identical with a functional
107                            // property > marking it.
108                            property.setFunctional(true);
109                        }
110                        if (rc.getCardinalityRestriction().getMaxCardinality() == 0) {
111                            rc.getCardinalityRestriction().setMultipleEnabled(false);
112                            rc.getCardinalityRestriction().setSingleEnabled(false);
113                        }
114                    }
115                }
116                success = true;
117            } else {
118                // test all subclasses, calls this method recursively
119                for (JClass subCls : cls.listDirectSubClasses()) {
120                    boolean suc = reasignProperty(subCls, property);
121                    // if successful for this subclass, set success to true
122                    if (suc)
123                        success = true;
124                }
125            }
126            return success;
127        }
128    
129        protected void reasignProperties() {
130            log.info("Reasigning unbound properties to corresponding classes with restrictions");
131    
132            // XXX use depth first traversal here? - how to move to next branch upon success?
133    
134            // loop over all domainless properties (p's with domain OwlThing)
135            // and mark them for removal from domain OwlThing
136            List<JProperty> properties = baseCls.listDomainProperties();
137            List<JProperty> propsToRemove = new ArrayList<JProperty>();
138    
139            for (JProperty property : properties) {
140                boolean success = reasignProperty(baseCls, property);
141                if (success)
142                    propsToRemove.add(property);
143            }
144    
145            // remove the marked properties and the restriction containers
146            for (JProperty prop : propsToRemove) {
147                prop.removeDomain(baseCls);
148                prop.removeClassRestrictions(baseCls);
149                baseCls.removeDomainRestrictionsContainer(prop);
150    
151            }
152    
153        }
154    
155        public void setReasignDomainlessProperties(boolean reasignDomainlessProperties) {
156            this.reasignDomainlessProperties = reasignDomainlessProperties;
157        }
158    }