001    package nl.tudelft.tbm.eeni.owl2java.model.jmodel;
002    
003    import com.hp.hpl.jena.ontology.OntClass;
004    import nl.tudelft.tbm.eeni.owl2java.model.jmodel.utils.LogUtils;
005    import nl.tudelft.tbm.eeni.owl2java.model.jmodel.utils.NamingUtils;
006    import nl.tudelft.tbm.eeni.owl2java.utils.StringUtils;
007    import org.apache.commons.logging.Log;
008    import org.apache.commons.logging.LogFactory;
009    import org.jgraph.graph.DefaultEdge;
010    
011    import java.util.*;
012    
013    
014    public class JClass extends JMapped {
015        public static enum AnonymousClassType {
016            NONE,           // Not an anonymous class
017            INTERSECTION,   // Anonymous intersection class
018            UNION           // Anonymous union class
019        }
020    
021        private static Log log = LogFactory.getLog(JClass.class);
022    
023        private OntClass ontClass;
024        private JModel jModel;
025        private JPackage jPkg;
026    
027        AnonymousClassType anonymousClassType = AnonymousClassType.NONE;
028        List<? extends OntClass> anonymousClassOperands = null;
029    
030        private List<JProperty> domainProperties = new ArrayList<JProperty>();
031        private List<JProperty> aggregatedProperties = new ArrayList<JProperty>();
032        private List<JClass> equivalentClasses = new ArrayList<JClass>();
033    
034        private Map<JProperty, JRestrictionsContainer> domainPropertyRestrictions = new HashMap<JProperty, JRestrictionsContainer>();
035        private Map<JProperty, JRestrictionsContainer> aggregatedPropertyRestrictions = new HashMap<JProperty, JRestrictionsContainer>();
036        // PropRepresentation = (0..1) CardRestriction + 1 AllValuesRestriction + (0..1) + OtherRestriction
037        private List<JPropertyRepresentation> domainPropertyRepresentations = new ArrayList<JPropertyRepresentation>();
038        private List<JPropertyRepresentation> aggregatedPropertyRepresentations = new ArrayList<JPropertyRepresentation>();
039    
040        public JClass(JModel model, String name, String mapUri) {
041            super(name, mapUri);
042            this.jModel = model;
043            this.jModel.getClassGraph().addVertex(this);
044        }
045    
046        public void addDomainProperty(JProperty prop) {
047            if (!domainProperties.contains(prop))
048                domainProperties.add(prop);
049            if (!prop.propertyDomain.contains(this))
050                prop.propertyDomain.add(this);
051            if (!domainPropertyRestrictions.containsKey(prop)) {
052                log.debug(LogUtils.toLogName(this, prop) + ": Creating RestrictionsContainer");
053                JRestrictionsContainer rc = new JRestrictionsContainer(this, prop);
054                domainPropertyRestrictions.put(prop, rc);
055            }
056        }
057    
058        public void addEquivalentClass(JClass cls) {
059            if (!equivalentClasses.contains(cls))
060                equivalentClasses.add(cls);
061            if (!cls.equivalentClasses.contains(this))
062                cls.equivalentClasses.add(this);
063        }
064    
065        public void addDomainRestrictionsContainer(JProperty property, JRestrictionsContainer rc) {
066            if (!domainPropertyRestrictions.containsKey(property))
067                domainPropertyRestrictions.put(property, rc);
068        }
069    
070        public void addSubClass(JClass cls) {
071            jModel.getClassGraph().addChildVertex(this, cls);
072        }
073    
074        public void addSuperClass(JClass cls) {
075            jModel.getClassGraph().addParentVertex(this, cls);
076        }
077    
078        public int aggegrateAll() {
079            int aggregateActions = 0;
080            if (jModel.isBaseThing(this)) {
081                log.debug(LogUtils.toLogName(this) + ": No aggregation for BaseThing");
082                return aggregateActions;
083            }
084            log.debug(LogUtils.toLogName(this) + ": Aggregating all definitions from parent classes");
085            List<JClass> parentClasses = jModel.getClassGraph().listDirectParents(this);
086            aggregateActions += aggregateProperties(parentClasses);
087            aggregateActions += aggregateRestrictionContainers(parentClasses);
088            aggregateActions += aggegrateRestrictionDefinitions(parentClasses);
089            aggregateActions += aggregatePropertyRepresentations(parentClasses);
090            return aggregateActions;
091        }
092    
093        protected int aggregatePropertyRepresentations(List<JClass> parentClasses) {
094            int aggregateActions = 0;
095            // copy local domain property representations to all representations
096            for (JPropertyRepresentation rep : domainPropertyRepresentations) {
097                // already aggregated in previous run
098                if (hasAggregatedPropertyRepresentation(rep.getOnProperty()))
099                    continue;
100                aggregatedPropertyRepresentations.add(rep);
101                aggregateActions++;
102            }
103    
104            // copy parent representations to all representations
105            for (JClass cls : parentClasses) {
106                log.debug(LogUtils.toLogName(this) + ": Aggregating property presentations of parent class "
107                        + LogUtils.toLogName(cls));
108    
109                for (JPropertyRepresentation representation : cls.listAggregatedPropertyRepresentations()) {
110    
111                    // clone the representation and add it to our list of aggregated representations
112                    JPropertyRepresentation pr = representation.clone();
113    
114    
115                    // Check for identity. Otherwise, two parent provide the same representation
116                    // We ignore the deprecated status as this can change later on
117                    boolean prExists = hasAggregatedPropertyRepresentation(pr);
118                    if (prExists) {
119                        log.debug(LogUtils.toLogName(this) + ": Skipping identical representation from parent class "
120                                + LogUtils.toLogName(cls));
121                    } else {
122                        // if we have a domain representation for a property -> mark deprecated + add
123                        if (hasAggregatedPropertyRepresentation(pr.getOnProperty())) {
124                            log.debug(LogUtils.toLogName(this) + ": Setting parent representation to deprecated");
125                            pr.setDeprecated(true);
126                        }
127                        aggregatedPropertyRepresentations.add(pr);
128                        aggregateActions++;
129                        log.debug(LogUtils.toLogName(this) + ": Adding parent representation");
130                    }
131                }
132            }
133            return aggregateActions;
134        }
135    
136        public List<JPropertyRepresentation> listAggregatedPropertyRepresentations() {
137            return aggregatedPropertyRepresentations;
138        }
139    
140        protected int aggegrateRestrictionDefinitions(List<JClass> parentClasses) {
141            int aggregateActions = 0;
142            Iterator<JProperty> it = aggregatedPropertyRestrictions.keySet().iterator();
143            while (it.hasNext()) {
144                JProperty property = (JProperty) it.next();
145                JRestrictionsContainer propertyRestrictionContainer = getAggregatedRestrictionsContainer(property
146                        .getMapUri());
147                propertyRestrictionContainer.aggregateRestrictions(parentClasses);
148                log.debug(LogUtils.toLogName(this) + ": Merging restriction definitions for property "
149                        + LogUtils.toLogName(property));
150            }
151            return aggregateActions;
152        }
153    
154        protected int aggregateProperties(List<JClass> parentClasses) {
155            int aggregateActions = 0;
156            // copy local domain properties to allProperites
157            for (JProperty property : domainProperties) {
158                if (hasAggregatedProperty(property.getMapUri()))
159                    continue;
160                aggregateActions++;
161                aggregatedProperties.add(property);
162            }
163    
164            // copy parent properties to allProperties
165            for (JClass cls : parentClasses) {
166                log.debug(LogUtils.toLogName(this) + ": Aggregating domain properties of parent class "
167                        + LogUtils.toLogName(cls));
168    
169                for (JProperty property : cls.listAggregatedProperties()) {
170                    if (!hasAggregatedProperty(property.getMapUri())) {
171                        aggregateActions++;
172                        aggregatedProperties.add(property);
173                    }
174                }
175            }
176            return aggregateActions;
177        }
178    
179        protected int aggregateRestrictionContainers(List<JClass> parentClasses) {
180            int aggregateActions = 0;
181            // add our restrictions
182            for (JProperty property : domainPropertyRestrictions.keySet()) {
183                log.debug(LogUtils.toLogName(this) + ": Aggregating domain restriction containers ");
184                JRestrictionsContainer rc = domainPropertyRestrictions.get(property);
185                // already added in previous run
186                if (hasAggregatedRestrictionsContainer(property.getMapUri()))
187                    continue;
188                aggregateActions++;
189                aggregatedPropertyRestrictions.put(property, rc);
190            }
191    
192            // add parent class stuff
193            for (JClass cls : parentClasses) {
194                log.debug(LogUtils.toLogName(this) + ": Aggregating restriction containers of parent class "
195                        + LogUtils.toLogName(cls));
196    
197                // aggregate the restriction containers from parent classes
198                for (JProperty property : cls.listAggregatedProperties()) {
199                    // already present -> skip (handled in aggegateRestrictionDefinitions)
200                    if (hasAggregatedRestrictionsContainer(property.getMapUri()))
201                        continue;
202                    // copy restriction container to here
203                    JRestrictionsContainer rc = cls.getAggregatedRestrictionsContainer(property);
204                    aggregatedPropertyRestrictions.put(property, rc.clone());
205                    aggregateActions++;
206                }
207            }
208            return aggregateActions;
209        }
210    
211        public void createDomainPropertyRepresentations() {
212            log.debug(LogUtils.toLogName(this) + ": Creating property representations for domain properties");
213            // loop over all properties
214    
215            for (JProperty property : domainPropertyRestrictions.keySet()) {
216                log.debug(LogUtils.toLogName(this) + ": Creating domain property representations for "
217                        + LogUtils.toLogName(property));
218                JRestrictionsContainer rc = domainPropertyRestrictions.get(property);
219    
220                // create the default representation based on the property range
221                // if no allValues restriction for this property
222                // -> otherwise the domain property has a allValues additional restriction
223                // and is handled below
224                if (rc.listAllValuesRestrictions().isEmpty()) {
225                    log.debug(LogUtils.toLogName(property) + ": Creating default representation");
226                    JPropertyRepresentation jpr = new JPropertyRepresentation(property);
227                    jpr.setHasDefaultPropertyRange(true);
228                    if (rc.hasCardinalityRestriction())
229                        jpr.setCardinalityRestriction(rc.getCardinalityRestriction().clone());
230                    if (rc.hasOtherRestriction())
231                        jpr.setOtherRestriction(rc.getOtherRestriction().clone());
232                    domainPropertyRepresentations.add(jpr);
233                }
234    
235                // for each AllValues create a single representation
236                for (JAllValuesRestriction avr : rc.listAllValuesRestrictions()) {
237                    log.debug(LogUtils.toLogName(property) + ": Creating representation for AllValues "
238                            + LogUtils.toLogName(avr.getAllValues()));
239                    JPropertyRepresentation pr = new JPropertyRepresentation(property);
240                    pr.setHasDefaultPropertyRange(false);
241                    pr.setAllValuesRestriction(avr);
242                    pr.setCardinalityRestriction(rc.getCardinalityRestriction());
243                    pr.setOtherRestriction(rc.getOtherRestriction());
244                    domainPropertyRepresentations.add(pr);
245                }
246            }
247        }
248    
249        public String getJavaClassFullName() {
250            return NamingUtils.getJavaFullName(jPkg, getJavaClassName());
251    
252        }
253    
254        public String getJavaClassName() {
255            if (this.ontClass != null)
256                return NamingUtils.getJavaClassName(this.ontClass);
257    
258            // no OntClass given (base.thing e. g. )
259            return NamingUtils.getJavaClassName(getName(), JModel.BASEPREFIX);
260        }
261    
262        public String getJavaInterfaceFullName() {
263            return NamingUtils.getJavaFullName(jPkg, getJavaInterfaceName());
264        }
265    
266        public String getJavaInterfaceName() {
267            if (this.ontClass != null)
268                return NamingUtils.getJavaInterfaceName(this.ontClass);
269    
270            // no OntClass given (base.thing e. g. )
271            String javaName = NamingUtils.getJavaInterfaceName(getName(), JModel.BASEPREFIX);
272            return javaName;
273        }
274    
275        public String getJavaPackageName() {
276            return jPkg.getPackageName();
277        }
278    
279        public JModel getJModel() {
280            return jModel;
281        }
282    
283        public OntClass getOntClass() {
284            return ontClass;
285        }
286    
287        public JPackage getPackage() {
288            return jPkg;
289        }
290    
291        public List<JPropertyRepresentation> getDomainPropertyRepresentations() {
292            return domainPropertyRepresentations;
293        }
294    
295        public List<JPropertyRepresentation> getAggregatedPropertyRepresentations() {
296            return aggregatedPropertyRepresentations;
297        }
298    
299        @Override
300        public String getJModelReport() {
301            String report = new String();
302            report += StringUtils.toSubHeader("Class " + getJavaClassFullName());
303    
304            report += StringUtils.indentText("Parent Classes\n");
305            Iterator<DefaultEdge> parentIt = jModel.getClassGraph().incomingEdgesOf(this).iterator();
306            while (parentIt.hasNext()) {
307                DefaultEdge edge = parentIt.next();
308                JClass parent = jModel.getClassGraph().getEdgeSource(edge);
309                report += StringUtils.indentText(parent.getJavaClassFullName(), 2) + "\n";
310            }
311    
312            report += StringUtils.indentText("Child Classes\n");
313            Iterator<DefaultEdge> childIt = jModel.getClassGraph().outgoingEdgesOf(this).iterator();
314            while (childIt.hasNext()) {
315                DefaultEdge edge = childIt.next();
316                JClass parent = jModel.getClassGraph().getEdgeTarget(edge);
317                report += StringUtils.indentText(parent.getJavaClassFullName(), 2) + "\n";
318            }
319    
320            report += StringUtils.indentText("Equivalent Classes\n");
321            for (JClass child : equivalentClasses) {
322                report += StringUtils.indentText(child.getJavaClassFullName(), 2) + "\n";
323            }
324    
325            report += StringUtils.indentText("Domain Properties\n");
326            for (JProperty prop : domainProperties) {
327                report += StringUtils.indentText(prop.getJavaName(), 2) + "\n";
328                report += prop.getJModelReport();
329            }
330    
331            report += StringUtils.indentText("Class Restrictions\n");
332            for (JRestrictionsContainer restr : domainPropertyRestrictions.values()) {
333                report += StringUtils.indentText(restr.getJModelReport(), 3) + "\n";
334            }
335            return report;
336        }
337    
338        public JRestrictionsContainer getDomainRestrictionsContainer(JProperty prop) {
339            return getDomainRestrictionsContainer(prop.getMapUri());
340        }
341    
342        public JRestrictionsContainer getAggregatedRestrictionsContainer(JProperty prop) {
343            return getAggregatedRestrictionsContainer(prop.getMapUri());
344        }
345    
346        public JRestrictionsContainer getDomainRestrictionsContainer(String uri) {
347            for (JProperty property : domainPropertyRestrictions.keySet()) {
348                if (property.getMapUri().equals(uri))
349                    return domainPropertyRestrictions.get(property);
350            }
351            return null;
352        }
353    
354        public JRestrictionsContainer getAggregatedRestrictionsContainer(String uri) {
355            for (JProperty property : aggregatedPropertyRestrictions.keySet()) {
356                if (property.getMapUri().equals(uri))
357                    return aggregatedPropertyRestrictions.get(property);
358            }
359            return null;
360        }
361    
362        public boolean hasDomainProperty(JProperty property) {
363            return hasDomainProperty(property.getMapUri());
364        }
365    
366        public boolean hasDomainProperty(String uri) {
367            for (JProperty domainProp : domainProperties) {
368                if (domainProp.getMapUri().equals(uri))
369                    return true;
370            }
371            return false;
372        }
373    
374        public boolean hasAggregatedProperty(String uri) {
375            for (JProperty prop : aggregatedProperties) {
376                if (prop.getMapUri().equals(uri))
377                    return true;
378            }
379            return false;
380        }
381    
382        public boolean hasDomainPropertyRepresentation(JPropertyRepresentation representation) {
383            return domainPropertyRepresentations.contains(representation);
384        }
385    
386        public boolean hasAggregatedPropertyRepresentation(JProperty property) {
387            for (JPropertyRepresentation pr : aggregatedPropertyRepresentations) {
388                if (pr.getOnProperty().getMapUri().equals(property.getMapUri()))
389                    return true;
390            }
391            return false;
392        }
393    
394        private boolean hasAggregatedPropertyRepresentation(JPropertyRepresentation representation) {
395            for (JPropertyRepresentation pr : aggregatedPropertyRepresentations) {
396                if (pr.equalsIgnoreDeprecated(representation))
397                    return true;
398            }
399            return false;
400        }
401    
402        public boolean hasDomainRestrictionsContainer(String propertyUri) {
403            for (JProperty prop : domainPropertyRestrictions.keySet()) {
404                JRestrictionsContainer rc = domainPropertyRestrictions.get(prop);
405                if (prop.getMapUri().equals(propertyUri) && rc != null)
406                    return true;
407            }
408            return false;
409        }
410    
411        public boolean hasAggregatedRestrictionsContainer(String propertyUri) {
412            for (JProperty prop : aggregatedPropertyRestrictions.keySet()) {
413                JRestrictionsContainer rc = aggregatedPropertyRestrictions.get(prop);
414                if (prop.getMapUri().equals(propertyUri) && rc != null)
415                    return true;
416            }
417            return false;
418        }
419    
420        public boolean hasDomainRestrictionsContainer(JProperty property) {
421            return hasDomainRestrictionsContainer(property.getMapUri());
422        }
423    
424        public boolean hasDomainRestrictionsContainer(JRestrictionsContainer restriction) {
425            return domainPropertyRestrictions.containsValue(restriction);
426        }
427    
428        public boolean hasSubClass(JClass cls, boolean recursive) {
429            return jModel.getClassGraph().hasChild(this, cls, recursive);
430        }
431    
432        public boolean hasSuperClass(JClass cls, boolean recursive) {
433            return jModel.getClassGraph().hasParent(this, cls, recursive);
434        }
435    
436        public boolean hasSuperClasses() {
437            if (jModel.getClassGraph().incomingEdgesOf(this).size() > 0)
438                return true;
439            return false;
440        }
441    
442        /**
443         * List JClass representations of all (direct and indirect) subclasses of this class
444         */
445        public List<JClass> listAllSubClasses() {
446            return listAllSubClasses(this);
447        }
448    
449        private List<JClass> listAllSubClasses(JClass cls) {
450            List<JClass> subClasses = new ArrayList<JClass>();
451            for (JClass subClass : jModel.getClassGraph().listDirectChildren(cls)) {
452                subClasses.add(subClass);
453                subClasses.addAll(listAllSubClasses(subClass));
454            }
455            return subClasses;
456        }
457    
458        public boolean isAnonymous() {
459            return anonymousClassType != AnonymousClassType.NONE;
460        }
461    
462        public AnonymousClassType getAnonymousClassType() {
463            return anonymousClassType;
464        }
465    
466        public List<? extends OntClass> getAnonymousClassOperands() {
467            return anonymousClassOperands;
468        }
469    
470        public void setAnonymous(AnonymousClassType type, List<? extends OntClass> operands) {
471            this.anonymousClassType = type;
472            this.anonymousClassOperands = operands;
473        }
474    
475        public boolean isRootClass() {
476            return (!hasSuperClasses());
477        }
478    
479        public List<JProperty> listAggregatedProperties() {
480            return aggregatedProperties;
481        }
482    
483        public List<JProperty> listDomainProperties() {
484            return domainProperties;
485        }
486    
487        public List<JPropertyRepresentation> listDomainPropertyRepresentations() {
488            return domainPropertyRepresentations;
489        }
490    
491        public List<JPropertyRepresentation> listDomainPropertyRepresentations(JProperty property) {
492            List<JPropertyRepresentation> representations = new ArrayList<JPropertyRepresentation>();
493            for (JPropertyRepresentation rep : domainPropertyRepresentations) {
494                if (rep.getOnProperty().getMapUri().equals(property.getMapUri()))
495                    representations.add(rep);
496            }
497            return representations;
498        }
499    
500        public List<JPropertyRepresentation> listAggregatedPropertyRepresentations(JProperty property) {
501            List<JPropertyRepresentation> representations = new ArrayList<JPropertyRepresentation>();
502            for (JPropertyRepresentation rep : aggregatedPropertyRepresentations) {
503                if (rep.getOnProperty().getMapUri().equals(property.getMapUri()))
504                    representations.add(rep);
505            }
506            return representations;
507        }
508    
509        public List<JClass> listDirectSubClasses() {
510            List<JClass> subClasses = new ArrayList<JClass>();
511            Iterator<DefaultEdge> children = jModel.getClassGraph().outgoingEdgesOf(this).iterator();
512            while (children.hasNext()) {
513                DefaultEdge edge = (DefaultEdge) children.next();
514                JClass child = jModel.getClassGraph().getEdgeTarget(edge);
515                subClasses.add(child);
516            }
517    
518            return subClasses;
519        }
520    
521        public List<JClass> listDirectSuperClasses() {
522            List<JClass> superClasses = new ArrayList<JClass>();
523            Iterator<DefaultEdge> parents = jModel.getClassGraph().incomingEdgesOf(this).iterator();
524            while (parents.hasNext()) {
525                DefaultEdge edge = (DefaultEdge) parents.next();
526                JClass parent = jModel.getClassGraph().getEdgeSource(edge);
527                superClasses.add(parent);
528            }
529            return superClasses;
530        }
531    
532        public JClass getFirstDirectSuperClass() {
533            return listDirectSuperClasses().get(0);
534        }
535    
536    
537        public Map<String, JProperty> listDomainPropertiesAsMap(boolean recursive) {
538            Map<String, JProperty> uri2prop = new HashMap<String, JProperty>();
539    
540            // add current props, if not present
541            for (JProperty p : domainProperties) {
542                if (!uri2prop.containsKey(p.getMapUri()))
543                    uri2prop.put(p.getMapUri(), p);
544            }
545    
546            if (recursive) {
547                List<JClass> superClasses = jModel.getClassGraph().listDirectParents(this);
548                for (JClass sCls : superClasses) {
549                    uri2prop.putAll(sCls.listDomainPropertiesAsMap(recursive));
550                }
551            }
552            return uri2prop;
553        }
554    
555        public List<JRestrictionsContainer> listDomainRestrictionContainers() {
556            List<JRestrictionsContainer> restrictions = new ArrayList<JRestrictionsContainer>();
557            restrictions.addAll(domainPropertyRestrictions.values());
558            return restrictions;
559        }
560    
561        public void removeAllPropertyRepresentations() {
562            domainPropertyRepresentations.clear();
563        }
564    
565        public void removeDomainProperty(JProperty property) {
566            if (domainProperties.contains(property))
567                domainProperties.remove(property);
568        }
569    
570        public void removeDomainRestrictionsContainer(JProperty property) {
571            if (domainPropertyRestrictions.containsKey(property))
572                domainPropertyRestrictions.remove(property);
573        }
574    
575        public void removeSubClassRelation(JClass subCls) {
576            jModel.getClassGraph().removeAllEdges(this, subCls);
577            // jModel.getClassGraph().removeVertex(subCls);
578        }
579    
580        public void removeSuperClassRelation(JClass superCls) {
581            jModel.getClassGraph().removeAllEdges(superCls, this);
582            // jModel.getClassGraph().removeVertex(superCls);
583        }
584    
585        public void setOntClass(OntClass ontClass) {
586            this.ontClass = ontClass;
587        }
588    
589        public void setPackage(JPackage pkg) {
590            this.jPkg = pkg;
591            pkg.addClass(this);
592        }
593    
594        public String toString() {
595            return getJavaClassName();
596        }
597    
598    }