001    /*
002     * The contents of this file are subject to the Mozilla Public License
003     * Version 1.1 (the "License");  you may not use this file except in 
004     * compliance with the License.  You may obtain a copy of the License at
005     * http://www.mozilla.org/MPL/
006     *
007     * Software distributed under the License is distributed on an "AS IS" basis,
008     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
009     * the specific language governing rights and limitations under the License.
010     *
011     * The Original Code is Protege-2000.
012     *
013     * The Initial Developer of the Original Code is Stanford University. Portions
014     * created by Stanford University are Copyright (C) 2007.  All Rights Reserved.
015     *
016     * Protege was developed by Stanford Medical Informatics
017     * (http://www.smi.stanford.edu) at the Stanford University School of Medicine
018     * with support from the National Library of Medicine, the National Science
019     * Foundation, and the Defense Advanced Research Projects Agency.  Current
020     * information about Protege can be obtained at http://protege.stanford.edu.
021     *
022     */
023    
024    package edu.stanford.smi.protegex.owl.model.impl;
025    
026    import java.util.ArrayList;
027    import java.util.Collection;
028    import java.util.Collections;
029    import java.util.HashSet;
030    import java.util.Iterator;
031    import java.util.Set;
032    
033    import javax.swing.Icon;
034    import javax.swing.ImageIcon;
035    
036    import edu.stanford.smi.protege.model.Cls;
037    import edu.stanford.smi.protege.model.FrameID;
038    import edu.stanford.smi.protege.model.KnowledgeBase;
039    import edu.stanford.smi.protege.model.Slot;
040    import edu.stanford.smi.protegex.owl.model.OWLAllValuesFrom;
041    import edu.stanford.smi.protegex.owl.model.OWLAnonymousClass;
042    import edu.stanford.smi.protegex.owl.model.OWLCardinality;
043    import edu.stanford.smi.protegex.owl.model.OWLCardinalityBase;
044    import edu.stanford.smi.protegex.owl.model.OWLDatatypeProperty;
045    import edu.stanford.smi.protegex.owl.model.OWLHasValue;
046    import edu.stanford.smi.protegex.owl.model.OWLIndividual;
047    import edu.stanford.smi.protegex.owl.model.OWLIntersectionClass;
048    import edu.stanford.smi.protegex.owl.model.OWLMaxCardinality;
049    import edu.stanford.smi.protegex.owl.model.OWLMinCardinality;
050    import edu.stanford.smi.protegex.owl.model.OWLNamedClass;
051    import edu.stanford.smi.protegex.owl.model.OWLNames;
052    import edu.stanford.smi.protegex.owl.model.OWLRestriction;
053    import edu.stanford.smi.protegex.owl.model.OWLSomeValuesFrom;
054    import edu.stanford.smi.protegex.owl.model.ProtegeNames;
055    import edu.stanford.smi.protegex.owl.model.RDFProperty;
056    import edu.stanford.smi.protegex.owl.model.RDFResource;
057    import edu.stanford.smi.protegex.owl.model.RDFSClass;
058    import edu.stanford.smi.protegex.owl.model.RDFSNamedClass;
059    import edu.stanford.smi.protege.model.Transaction;
060    import edu.stanford.smi.protegex.owl.model.*;
061    import edu.stanford.smi.protegex.owl.model.visitor.OWLModelVisitor;
062    import edu.stanford.smi.protegex.owl.ui.icons.OWLIcons;
063    
064    /**
065     * The default implementation of the OWLNamedClass interface.
066     *
067     * @author Holger Knublauch  <holger@knublauch.com>
068     */
069    public class DefaultOWLNamedClass extends DefaultRDFSNamedClass implements OWLNamedClass {
070    
071    
072        public DefaultOWLNamedClass(KnowledgeBase kb, FrameID id) {
073            super(kb, id);
074        }
075    
076    
077        public DefaultOWLNamedClass() {
078        }
079    
080    
081        public void addDisjointClass(RDFSClass aClass) {
082            Slot disjointClassesSlot = getOWLModel().getOWLDisjointWithProperty();
083            addOwnSlotValue(disjointClassesSlot, aClass);
084        }
085    
086    
087        public void addEquivalentClass(final RDFSClass aClass) {
088            new Transaction(getOWLModel(), "Add Equivalent Class" + Transaction.APPLY_TO_TRAILER_STRING + this.getName()) {
089                public boolean doOperations() {
090                    if (!hasDirectSuperclass(aClass)) {
091                        addDirectSuperclass(aClass);
092                    }
093                    if (!aClass.isSubclassOf(DefaultOWLNamedClass.this)) {
094                        aClass.addSuperclass(DefaultOWLNamedClass.this);
095                    }
096                    return true;
097                };
098            }.execute();
099        }
100    
101    
102        public void addInferredSuperclass(RDFSClass superclass) {
103            Slot superclassesSlot = getAbstractOWLModel().getProtegeInferredSuperclassesProperty();
104            addOwnSlotValue(superclassesSlot, superclass);
105            if (superclass instanceof OWLNamedClass) {
106                Slot subclassesSlot = getAbstractOWLModel().getProtegeInferredSubclassesProperty();
107                ((Cls) superclass).addOwnSlotValue(subclassesSlot, this);
108            }
109        }
110    
111    
112        public OWLIndividual createOWLIndividual(String name) {
113            return (OWLIndividual) createInstance(OWLUtil.getInternalFullName(getOWLModel(), name));
114        }
115    
116    
117        public boolean equalsStructurally(RDFSClass cls) {
118            return getName().equals(cls.getName());
119        }
120    
121    
122        public RDFResource getAllValuesFrom(RDFProperty property) {
123            Collection restrictions = getRestrictions(property, true);
124            for (Iterator it = restrictions.iterator(); it.hasNext();) {
125                OWLRestriction restriction = (OWLRestriction) it.next();
126                if (restriction instanceof OWLAllValuesFrom) {
127                    return ((OWLAllValuesFrom) restriction).getAllValuesFrom();
128                }
129            }
130            return property.getRange();
131        }
132    
133    
134        @Override
135        public Set getAssociatedProperties() {
136            Set set = super.getAssociatedProperties();
137            Set maxZeroProperties = new HashSet();
138            Iterator restrictions = getRestrictions(true).iterator();
139            while (restrictions.hasNext()) {
140                OWLRestriction restriction = (OWLRestriction) restrictions.next();
141                RDFProperty property = restriction.getOnProperty();
142                if ((restriction instanceof OWLCardinality || restriction instanceof OWLMaxCardinality) &&
143                        ((OWLCardinalityBase) restriction).getCardinality() == 0) {
144                    maxZeroProperties.add(property);
145                    maxZeroProperties.add(property.getSubproperties(true));
146                }
147                else {
148                    set.add(property);
149                    set.addAll(property.getSubproperties(true));
150                }
151            }
152            set.removeAll(maxZeroProperties);
153            return set;
154        }
155    
156    
157        public int getClassificationStatus() {
158            final Slot slot = getAbstractOWLModel().getProtegeClassificationStatusProperty();
159            Collection values = getDirectOwnSlotValues(slot);
160            if (values.size() == 0) {
161                return OWLNames.CLASSIFICATION_STATUS_UNDEFINED;
162            }
163            else {
164                return ((Integer) values.iterator().next()).intValue();
165            }
166        }
167    
168    
169        public Collection getDirectRestrictions() {
170            Collection result = new ArrayList();
171            getDirectRestrictions(result, getDirectSuperclasses().iterator());
172            return result;
173        }
174    
175        
176        public Collection getHasValues(RDFProperty property) {
177            Set hasValues = new HashSet();
178            
179            for (Iterator it = getRestrictions(property, true).iterator(); it.hasNext();) {
180                OWLRestriction restriction = (OWLRestriction) it.next();
181                if (restriction instanceof OWLHasValue) {
182                    OWLHasValue hasValue = (OWLHasValue) restriction;
183                    hasValues.add(hasValue.getHasValue());
184                }
185            }
186            return hasValues;       
187        }
188    
189        public Object getHasValue(RDFProperty property) {
190            for (Iterator it = getRestrictions(property, true).iterator(); it.hasNext();) {
191                OWLRestriction restriction = (OWLRestriction) it.next();
192                if (restriction instanceof OWLHasValue) {
193                    OWLHasValue hasValue = (OWLHasValue) restriction;
194                    return hasValue.getHasValue();
195                }
196            }
197            return null;
198        }
199    
200    
201        public Collection getInferredEquivalentClasses() {
202            Collection result = new HashSet();
203            for (Iterator it = getInferredSuperclasses().iterator(); it.hasNext();) {
204                Cls superCls = (Cls) it.next();
205                if (getInferredSubclasses().contains(superCls)) {
206                    result.add(superCls);
207                }
208            }
209            return result;
210        }
211    
212    
213        private void getDirectRestrictions(Collection results, Iterator clses) {
214            while (clses.hasNext()) {
215                Cls cls = (Cls) clses.next();
216                if (cls instanceof OWLRestriction) {
217                    results.add(cls);
218                }
219                else if (cls instanceof OWLIntersectionClass) {
220                    OWLIntersectionClass logicalCls = (OWLIntersectionClass) cls;
221                    getDirectRestrictions(results, logicalCls.getOperands().iterator());
222                }
223            }
224        }
225    
226    
227        public Collection getInferredSubclasses() {
228            Slot slot = getAbstractOWLModel().getProtegeInferredSubclassesProperty();
229            return getDirectOwnSlotValues(slot);
230        }
231    
232    
233        public Collection getInferredSuperclasses() {
234            Slot slot = getAbstractOWLModel().getProtegeInferredSuperclassesProperty();
235            return getDirectOwnSlotValues(slot);
236        }
237    
238    
239        public int getMaxCardinality(RDFProperty property) {
240            if (property.isFunctional()) {
241                return 1;
242            }
243            Collection restrictions = getRestrictions(property, true);
244            for (Iterator it = restrictions.iterator(); it.hasNext();) {
245                OWLRestriction restriction = (OWLRestriction) it.next();
246                if (restriction instanceof OWLCardinalityBase) {
247                    OWLCardinalityBase base = (OWLCardinalityBase) restriction;
248                    if (!base.isQualified()) {
249                        if (restriction instanceof OWLMaxCardinality) {
250                            return ((OWLMaxCardinality) restriction).getCardinality();
251                        }
252                        else if (restriction instanceof OWLCardinality) {
253                            return ((OWLCardinality) restriction).getCardinality();
254                        }
255                    }
256                }
257            }
258            return -1;
259        }
260    
261    
262        public int getMinCardinality(RDFProperty property) {
263            Collection restrictions = getRestrictions(property, true);
264            for (Iterator it = restrictions.iterator(); it.hasNext();) {
265                OWLRestriction restriction = (OWLRestriction) it.next();
266                if (restriction instanceof OWLMinCardinality) {
267                    return ((OWLMinCardinality) restriction).getCardinality();
268                }
269                else if (restriction instanceof OWLCardinality) {
270                    return ((OWLCardinality) restriction).getCardinality();
271                }
272            }
273            return 0;
274        }
275    
276    
277        public Collection getRestrictions() {
278            return getRestrictions(false);
279        }
280    
281    
282        @Override
283        public Icon getIcon() {
284            if (!getOWLModel().getProject().isMultiUserClient() && isMetaCls()) {
285                return super.getIcon();
286            }
287            else {
288                ImageIcon ii = getImageIconForNonMetaclass();
289                if (isEditable()) {
290                    return ii;
291                }
292                else {
293                    return OWLIcons.getReadOnlyClsIcon(ii);
294                }
295            }
296        }
297    
298    
299        @Override
300        public String getIconName() {
301            if(isMetaclass()) {
302                return super.getIconName();
303            }
304            else {
305                return getImageIconNameForNonMetaclass();
306            }
307        }
308    
309    
310        @Override
311        public ImageIcon getImageIcon() {
312            if (isMetaCls()) {
313                return super.getImageIcon();
314            }
315            else {
316                return getImageIconForNonMetaclass();
317            }
318        }
319    
320    
321        private ImageIcon getImageIconForNonMetaclass() {
322            String str = getImageIconNameForNonMetaclass();
323            return OWLIcons.getImageIcon(str);
324        }
325    
326    
327        private String getImageIconNameForNonMetaclass() {
328            String str = null;
329            if (getPropertyValueCount(getOWLModel().getOWLEquivalentClassProperty()) == 0) {
330                str = OWLIcons.PRIMITIVE_OWL_CLASS;
331            }
332            else {
333                str = OWLIcons.DEFINED_OWL_CLASS;
334            }
335            if (!getOWLModel().getProject().isMultiUserClient()) {
336                if (isConsistent() == false) {
337                    str += "Inconsistent";
338                }
339                if (getSubclassesDisjoint()) {
340                    str += "SD";
341                }
342            }
343            return str;
344        }
345    
346    
347        public Collection getRestrictions(boolean includingSuperclassRestrictions) {
348            if (includingSuperclassRestrictions) {
349                Set reached = new HashSet();
350                Collection restrictions = new ArrayList();
351                getRestrictions(this, reached, restrictions);
352                return restrictions;
353            }
354            else {
355                return getDirectRestrictions();
356            }
357        }
358    
359    
360        public Collection getRestrictions(RDFProperty property, boolean includingSuperclassRestrictions) {
361            Collection result = new ArrayList();
362            Collection rs = getRestrictions(includingSuperclassRestrictions);
363            for (Iterator it = rs.iterator(); it.hasNext();) {
364                OWLRestriction restriction = (OWLRestriction) it.next();
365                if (property.equals(restriction.getOnProperty())) {
366                    result.add(restriction);
367                }
368            }
369            return result;
370        }
371    
372    
373        private static void getRestrictions(OWLNamedClass cls, Set reached, Collection results) {
374            reached.add(cls);
375            Collection restrictions = cls.getRestrictions(false);
376            for (Iterator rit = restrictions.iterator(); rit.hasNext();) {
377                OWLRestriction restriction = (OWLRestriction) rit.next();
378                if (restriction instanceof OWLAllValuesFrom) {
379                    if (!isOverloadedAllValuesFrom((OWLAllValuesFrom) restriction, results)) {
380                        results.add(restriction);
381                    }
382                }
383                else if (restriction instanceof OWLMinCardinality) {
384                    if (!isOverloadedMinCardinality((OWLMinCardinality) restriction, results)) {
385                        results.add(restriction);
386                    }
387                }
388                else if (restriction instanceof OWLMaxCardinality) {
389                    if (!isOverloadedMaxCardinality((OWLMaxCardinality) restriction, results)) {
390                        results.add(restriction);
391                    }
392                }
393                else if (restriction instanceof OWLCardinality) {
394                    if (!isOverloadedCardinality((OWLCardinality) restriction, results)) {
395                        results.add(restriction);
396                    }
397                }
398                else {  // owl:hasValue or owl:someValuesFrom cannot be overloaded
399                    results.add(restriction);
400                }
401            }
402    
403            for (Iterator it = cls.getNamedSuperclasses().iterator(); it.hasNext();) {
404                RDFSNamedClass superclass = (RDFSNamedClass) it.next();
405                if (superclass instanceof OWLNamedClass && !reached.contains(superclass)) {
406                    getRestrictions((OWLNamedClass) superclass, reached, results);
407                }
408            }
409        }
410    
411    
412        public RDFResource getSomeValuesFrom(RDFProperty property) {
413            Collection restrictions = getRestrictions(property, true);
414            for (Iterator it = restrictions.iterator(); it.hasNext();) {
415                OWLRestriction restriction = (OWLRestriction) it.next();
416                if (restriction instanceof OWLSomeValuesFrom) {
417                    return ((OWLSomeValuesFrom) restriction).getSomeValuesFrom();
418                }
419            }
420            return null;
421        }
422    
423    
424        public boolean isConsistent() {
425            return getInferredSuperclasses().contains(getOWLModel().getOWLNothing()) == false;
426        }
427    
428    
429        private static boolean isOverloadedAllValuesFrom(OWLAllValuesFrom restriction, Collection restrictions) {
430            RDFProperty property = restriction.getOnProperty();
431            for (Iterator it = restrictions.iterator(); it.hasNext();) {
432                OWLRestriction owlRestriction = (OWLRestriction) it.next();
433                if (owlRestriction instanceof OWLAllValuesFrom && owlRestriction.getOnProperty().equals(property)) {
434                    return true;
435                }
436            }
437            return false;
438        }
439    
440    
441        private static boolean isOverloadedCardinality(OWLCardinality restriction, Collection restrictions) {
442            RDFProperty property = restriction.getOnProperty();
443            for (Iterator it = restrictions.iterator(); it.hasNext();) {
444                OWLRestriction owlRestriction = (OWLRestriction) it.next();
445                if (property.equals(owlRestriction.getOnProperty())) {
446                    if (owlRestriction instanceof OWLCardinality) {
447                        return true;
448                    }
449                }
450            }
451            return false;
452        }
453    
454    
455        private static boolean isOverloadedMaxCardinality(OWLMaxCardinality restriction, Collection restrictions) {
456            RDFProperty property = restriction.getOnProperty();
457            for (Iterator it = restrictions.iterator(); it.hasNext();) {
458                OWLRestriction owlRestriction = (OWLRestriction) it.next();
459                if (property.equals(owlRestriction.getOnProperty())) {
460                    if (owlRestriction instanceof OWLCardinality || owlRestriction instanceof OWLMaxCardinality) {
461                        return true;
462                    }
463                }
464            }
465            return false;
466        }
467    
468    
469        private static boolean isOverloadedMinCardinality(OWLMinCardinality restriction, Collection restrictions) {
470            RDFProperty property = restriction.getOnProperty();
471            for (Iterator it = restrictions.iterator(); it.hasNext();) {
472                OWLRestriction owlRestriction = (OWLRestriction) it.next();
473                if (property.equals(owlRestriction.getOnProperty())) {
474                    if (owlRestriction instanceof OWLCardinality || owlRestriction instanceof OWLMinCardinality) {
475                        return true;
476                    }
477                }
478            }
479            return false;
480        }
481    
482    
483        public boolean getSubclassesDisjoint() {
484            final Slot slot = getOWLModel().getProtegeSubclassesDisjointProperty();
485            if (slot != null) {
486                final Object value = getDirectOwnSlotValue(slot);
487                if (value instanceof Boolean) {
488                    return ((Boolean) value).booleanValue();
489                }
490            }
491            return false;
492        }
493    
494    
495        public boolean hasNamedSuperclass() {
496            return getNamedSuperclasses().size() > 0;
497        }
498    
499    
500        public boolean isDefinedClass() {
501            return getDefinition() != null;
502        }
503    
504    
505        @Override
506        public boolean isFunctionalProperty(RDFProperty property) {
507            int max = getMaxCardinality(property);
508            return max == 0 || max == 1;
509        }
510    
511    
512        public boolean hasNamedSuperClass() {
513            return hasNamedSuperclass();
514        }
515    
516    
517        public boolean isProbeClass() {
518            Slot slot = getKnowledgeBase().getSlot(ProtegeNames.getProbeClassSlotName());
519            if (slot instanceof OWLDatatypeProperty) {
520                return Boolean.TRUE.equals(getDirectOwnSlotValue(slot));
521            }
522            return false;
523        }
524    
525    
526        public void removeDisjointClass(RDFSClass aClass) {
527            Slot disjointClassesSlot = getOWLModel().getOWLDisjointWithProperty();
528            removeOwnSlotValue(disjointClassesSlot, aClass);
529            if (aClass.isAnonymous()) {
530                getKnowledgeBase().deleteCls(aClass);
531            }
532        }
533    
534    
535        public void removeEquivalentClass(final RDFSClass equivalentClass) {
536            new Transaction(getOWLModel(), "Remove Equivalent Class" + Transaction.APPLY_TO_TRAILER_STRING + this.getName()) {
537                public boolean doOperations() {
538                            if (equivalentClass instanceof OWLAnonymousClass) {
539                                removeDirectSuperclass(equivalentClass);
540                            }
541                            else {
542                                removeDirectSuperclass(equivalentClass);
543                                equivalentClass.removeSuperclass(DefaultOWLNamedClass.this);
544                            }
545                            return true;
546                };
547            }.execute();
548        }
549    
550    
551        public void removeInferredSuperclass(RDFSClass superclass) {
552            Slot superclassesSlot = getAbstractOWLModel().getProtegeInferredSuperclassesProperty();
553            Slot subclassesSlot = getAbstractOWLModel().getProtegeInferredSubclassesProperty();
554            removeOwnSlotValue(superclassesSlot, superclass);
555            ((Cls) superclass).removeOwnSlotValue(subclassesSlot, this);
556        }
557    
558    
559        public void setClassificationStatus(int value) {
560            if (value != getClassificationStatus()) {
561                final Slot slot = getAbstractOWLModel().getProtegeClassificationStatusProperty();
562                setOwnSlotValue(slot, new Integer(value));
563            }
564        }
565    
566    
567        public void setDefinition(RDFSClass definingClass) {
568            for (Iterator it = getEquivalentClasses().iterator(); it.hasNext();) {
569                RDFSClass cls = (RDFSClass) it.next();
570                removeEquivalentClass(cls);
571            }
572            if (definingClass != null) {
573                addEquivalentClass(definingClass);
574            }
575            if (!hasNamedSuperClass()) {
576                addDirectSuperclass(getKnowledgeBase().getRootCls());
577            }
578        }
579    
580    
581        public void setSubclassesDisjoint(boolean value) {
582            final Slot slot = getOWLModel().getProtegeSubclassesDisjointProperty();
583            if (slot == null) {
584                throw new RuntimeException("Could not find slot " + ProtegeNames.getSubclassesDisjointSlotName());
585            }
586            if (value) {
587                setDirectOwnSlotValue(slot, Boolean.TRUE);
588                OWLUtil.ensureSubclassesDisjoint(this);
589            }
590            else {
591                setDirectOwnSlotValues(slot, Collections.EMPTY_LIST);
592                OWLUtil.removeSubclassesDisjoint(this);
593            }
594        }
595    
596    
597        @Override
598        public void accept(OWLModelVisitor visitor) {
599            visitor.visitOWLNamedClass(this);
600        }
601    }
602