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 edu.stanford.smi.protege.model.FrameID;
027    import edu.stanford.smi.protege.model.KnowledgeBase;
028    import edu.stanford.smi.protegex.owl.model.*;
029    import edu.stanford.smi.protegex.owl.model.visitor.OWLModelVisitor;
030    import edu.stanford.smi.protegex.owl.ui.icons.OWLIcons;
031    import org.apache.xerces.xs.XSSimpleTypeDefinition;
032    
033    import javax.swing.*;
034    import java.util.HashMap;
035    import java.util.Map;
036    import java.util.regex.Matcher;
037    import java.util.regex.Pattern;
038    
039    /**
040     * @author Holger Knublauch  <holger@knublauch.com>
041     */
042    public class DefaultRDFSDatatype extends DefaultRDFIndividual implements RDFSDatatype {
043    
044    
045        public DefaultRDFSDatatype(KnowledgeBase kb, FrameID id) {
046            super(kb, id);
047        }
048    
049    
050        public DefaultRDFSDatatype() {
051        }
052    
053    
054        public void accept(OWLModelVisitor visitor) {
055            visitor.visitRDFDatatype(this);
056        }
057    
058    
059        public boolean equalsStructurally(RDFObject object) {
060            if (object instanceof RDFSDatatype) {
061                RDFSDatatype datatype = (RDFSDatatype) object;
062                return datatype.getURI() == getURI() &&
063                       datatype.getMaxExclusive().equalsStructurally(getMaxExclusive()) &&
064                       datatype.getMinExclusive().equalsStructurally(getMinExclusive()) &&
065                       datatype.getMaxInclusive().equalsStructurally(getMaxInclusive()) &&
066                       datatype.getMinInclusive().equalsStructurally(getMinInclusive());
067            }
068            return false;
069        }
070    
071    
072        public RDFSDatatype getBaseDatatype() {
073            RDFProperty property = XSPNames.getRDFProperty(getOWLModel(), XSPNames.XSP_BASE);
074            if (property != null) {
075                return (RDFSDatatype) getPropertyValue(property);
076            }
077            else {
078                return null; // getBaseDatatypeXSD();
079            }
080        }
081    
082    //    private RDFSDatatype getBaseDatatypeXSD() {
083    //        XSSimpleType simpleType = getXSSimpleType();
084    //        if (simpleType != null) {
085    //            XSTypeDefinition baseType = simpleType.getBaseType();
086    //            if (baseType != null) {
087    //                String name = baseType.getName();
088    //                String namespace = baseType.getNamespace();
089    //                String uri = namespace + "#" + name;
090    //                return getOWLModel().getRDFSDatatypeByURI(uri);
091    //            }
092    //        }
093    //        return null;
094    //    }
095    
096    
097        public String getBrowserText() {
098            if (isAnonymous()) {
099                RDFSDatatype baseDatatype = getBaseDatatype();
100                if (baseDatatype != null) {
101                    String str = baseDatatype.getBrowserText();
102                    String openingBracket = "[";
103                    String closingBracket = "]";
104                    RDFSLiteral min = getMinInclusive();
105                    RDFSLiteral max = getMaxInclusive();
106                    if (min == null) {
107                        min = getMinExclusive();
108                        if (min != null) {
109                            openingBracket = "(";
110                            if (max == null) {
111                                closingBracket = ")";
112                            }
113                        }
114                    }
115                    if (max == null) {
116                        max = getMaxExclusive();
117                        if (max != null) {
118                            closingBracket = ")";
119                        }
120                    }
121                    if (max != null || min != null) {
122                        str += openingBracket;
123                        if (min != null) {
124                            str += min.toString();
125                        }
126                        else {
127                            str += "..";
128                        }
129                        str += ",";
130                        if (max != null) {
131                            str += max.toString();
132                        }
133                        else {
134                            str += "..";
135                        }
136                        return str + closingBracket;
137                    }
138                    else {
139                        return "variant of " + baseDatatype.getBrowserText();
140                    }
141                }
142            }
143            String bt = super.getBrowserText();
144            if (bt.startsWith(XSDNames.PREFIX)) {
145                return bt.substring(XSDNames.PREFIX.length());
146            }
147            else {
148                return bt;
149            }
150        }
151    
152    
153        public Object getDefaultValue() {
154            if (equals(getOWLModel().getXSDboolean())) {
155                return Boolean.FALSE;
156            }
157            else if (equals(getOWLModel().getXSDint())) {
158                return new Integer(0);
159            }
160            else if (equals(getOWLModel().getXSDfloat())) {
161                return new Float(0);
162            }
163            else if (equals(getOWLModel().getXSDstring())) {
164                return "";
165            }
166            else {
167                String literal = "";
168                if (isNumericDatatype()) {
169                    literal = "0";
170                }
171                return getOWLModel().createRDFSLiteral(literal, this);
172            }
173        }
174    
175    //    private Number getFacetValue(String facetName) {
176    //        XSSimpleType simpleType = getXSSimpleType();
177    //        if (simpleType != null) {
178    //            XSObjectList list = simpleType.getFacets();
179    //            int length = list.getLength();
180    //            short kind = getFacetKind(facetName);
181    //            for (int i = 0; i < length; i++) {
182    //                XSObject object = list.item(i);
183    //                if (object instanceof XSFacet) {
184    //                    XSFacet facet = (XSFacet) object;
185    //                    if (kind == facet.getFacetKind()) {
186    //                        String value = facet.getLexicalFacetValue();
187    //                        return Integer.valueOf(value);
188    //                    }
189    //                }
190    //            }
191    //        }
192    //        return null;
193    //    }
194    
195    
196        private short getFacetKind(String facetName) {
197            if (facetName.equals(XSDNames.Facet.MAX_EXCLUSIVE)) {
198                return XSSimpleTypeDefinition.FACET_MAXEXCLUSIVE;
199            }
200            else if (facetName.equals(XSDNames.Facet.MAX_INCLUSIVE)) {
201                return XSSimpleTypeDefinition.FACET_MAXINCLUSIVE;
202            }
203            else if (facetName.equals(XSDNames.Facet.MIN_EXCLUSIVE)) {
204                return XSSimpleTypeDefinition.FACET_MINEXCLUSIVE;
205            }
206            else if (facetName.equals(XSDNames.Facet.MIN_INCLUSIVE)) {
207                return XSSimpleTypeDefinition.FACET_MININCLUSIVE;
208            }
209            else {
210                return -1;
211            }
212        }
213    
214    
215        public Icon getIcon() {
216            return isEditable() ?
217                    OWLIcons.getImageIcon(OWLIcons.RDF_DATATYPE) :
218                    OWLIcons.getReadOnlyIndividualIcon(OWLIcons.getImageIcon(OWLIcons.RDF_DATATYPE));
219        }
220    
221    
222        private int getIntPropertyValue(String propertyName) {
223            RDFProperty property = getOWLModel().getRDFProperty(propertyName);
224            if (property != null) {
225                Object value = getPropertyValue(property);
226                if (value instanceof Integer) {
227                    return ((Integer) value).intValue();
228                }
229            }
230            return -1;
231        }
232    
233    
234        public int getLength() {
235            return getIntPropertyValue(XSPNames.getName(getOWLModel(), XSPNames.XSP_LENGTH));
236        }
237    
238    
239        public RDFSLiteral getMaxExclusive() {
240            return getPropertyValueLiteral(XSPNames.getName(getOWLModel(), XSPNames.XSP_MAX_EXCLUSIVE));
241        }
242    
243    
244        public RDFSLiteral getMaxInclusive() {
245            return getPropertyValueLiteral(XSPNames.getName(getOWLModel(), XSPNames.XSP_MAX_INCLUSIVE));
246        }
247    
248    
249        public int getMaxLength() {
250            return getIntPropertyValue(XSPNames.getName(getOWLModel(), XSPNames.XSP_MAX_LENGTH));
251        }
252    
253    
254        public RDFSLiteral getMinExclusive() {
255            return getPropertyValueLiteral(XSPNames.getName(getOWLModel(), XSPNames.XSP_MIN_EXCLUSIVE));
256        }
257    
258    
259        public RDFSLiteral getMinInclusive() {
260            return getPropertyValueLiteral(XSPNames.getName(getOWLModel(), XSPNames.XSP_MIN_INCLUSIVE));
261        }
262    
263    
264        public int getMinLength() {
265            return getIntPropertyValue(XSPNames.getName(getOWLModel(), XSPNames.XSP_MIN_LENGTH));
266        }
267    
268    
269        public String getPattern() {
270            RDFProperty property = XSPNames.getRDFProperty(getOWLModel(), XSPNames.XSP_PATTERN);
271            if (property != null) {
272                Object value = getPropertyValue(property);
273                if (value != null) {
274                    return value.toString();
275                }
276            }
277            return null;
278        }
279    
280    
281        private RDFSLiteral getPropertyValueLiteral(String propertyName) {
282            RDFProperty property = getOWLModel().getRDFProperty(propertyName);
283            if (property != null) {
284                return getPropertyValueLiteral(property);
285            }
286            else {
287                return null;
288            }
289        }
290    
291    //    private RDFProperty getSimpleTypeLiteralProperty() {
292    //        return getOWLModel().getRDFSLabelProperty(); //
293    //    }
294    
295    //    private XSSimpleType getXSSimpleType() {
296    //        RDFProperty stlProperty = getSimpleTypeLiteralProperty();
297    //        Object value = getPropertyValue(stlProperty);
298    //        if (value != null) {
299    //            String str = null;
300    //            if (value instanceof RDFSLiteral) {
301    //                str = ((RDFSLiteral) value).getString();
302    //            }
303    //            else {
304    //                str = value.toString();
305    //            }
306    //            str = "<?xml version='1.0'?>\n" +
307    //                    "<xs:schema " +
308    //                    "           xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n" +
309    //                    "           xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n" +
310    //                    str +
311    //                    "</xs:schema>";
312    //            XMLGrammarPreparser parser = new XMLGrammarPreparser();
313    //            parser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null);
314    //            try {
315    //                String uri = "http://dummy." + Math.random();
316    //                XMLInputSource source = new XMLInputSource(null, uri, uri, new StringReader(str), null);
317    //                XSGrammar xsg = (XSGrammar) parser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, source);
318    //                org.apache.xerces.xs.XSModel xsm = xsg.toXSModel();
319    //                XSNamedMap map = xsm.getComponents(XSTypeDefinition.SIMPLE_TYPE);
320    //                int numDefs = map.getLength();
321    //                if (numDefs > 0) {
322    //                    XSSimpleType xstype = (XSSimpleType) map.item(0);
323    //                    return xstype;
324    //                }
325    //            }
326    //            catch (Exception ex) {
327    //            }
328    //        }
329    //        return null;
330    //    }
331    
332    
333        public boolean isNumericDatatype() {
334            String uri = getURI();
335            RDFSDatatype base = getBaseDatatype();
336            if (base != null) {
337                uri = base.getURI();
338            }
339            return XMLSchemaDatatypes.isNumericDatatype(uri);
340        }
341    
342    
343        public boolean isValidValue(RDFSLiteral object) {
344            RDFSDatatype d = this;
345            RDFSDatatype baseDatatype = getBaseDatatype();
346            if (baseDatatype != null) {
347                d = baseDatatype;
348            }
349            if (!object.getDatatype().equals(d)) {
350                return false;
351            }
352            if (getOWLModel().getXSDstring().equals(d)) {
353                return isValidValueString(object);
354            }
355            else {
356                return isValidValueNumeric(object);
357            }
358        }
359    
360    
361        private boolean isValidValueNumeric(RDFSLiteral object) {
362            RDFSLiteral minInclusive = getMinInclusive();
363            if (minInclusive != null) {
364                if (object.compareTo(minInclusive) < 0) {
365                    return false;
366                }
367            }
368            RDFSLiteral minExclusive = getMinExclusive();
369            if (minExclusive != null) {
370                if (object.compareTo(minExclusive) <= 0) {
371                    return false;
372                }
373            }
374            RDFSLiteral maxInclusive = getMaxInclusive();
375            if (maxInclusive != null) {
376                if (object.compareTo(maxInclusive) > 0) {
377                    return false;
378                }
379            }
380            RDFSLiteral maxExclusive = getMaxExclusive();
381            if (maxExclusive != null) {
382                if (object.compareTo(maxExclusive) >= 0) {
383                    return false;
384                }
385            }
386            return true;
387        }
388    
389    
390        private boolean isValidValueString(RDFSLiteral object) {
391            String s = object.toString();
392            int l = s.length();
393    
394            int length = getLength();
395            if (length >= 0 && length != l) {
396                return false;
397            }
398            int minLength = getMinLength();
399            if (minLength >= 0 && l < minLength) {
400                return false;
401            }
402            int maxLength = getMaxLength();
403            if (maxLength >= 0 && l > maxLength) {
404                return false;
405            }
406            String pattern = getPattern();
407            if (pattern != null) {
408                Pattern p = Pattern.compile(pattern);
409                Matcher matcher = p.matcher(s);
410                if (!matcher.matches()) {
411                    return false;
412                }
413            }
414            return true;
415        }
416    
417    
418        public static Map parse(OWLModel owlModel, String expression) {
419            Map map = new HashMap();
420            if (owlModel.isProtegeMetaOntologyImported()) {
421                int index = 3;
422                while (index < expression.length() &&
423                       expression.charAt(index) != '(' &&
424                       expression.charAt(index) != '[') {
425                    index++;
426                }
427                if (index < expression.length()) {
428                    String baseTypeName = expression.substring(0, index).trim();
429                    RDFSDatatype datatype = owlModel.getRDFSDatatypeByName(baseTypeName);
430                    if (datatype != null) {
431                            RDFProperty subDatatypeOfProperty = XSPNames.getRDFProperty(owlModel, XSPNames.XSP_BASE);
432                        map.put(subDatatypeOfProperty, datatype);
433                        RDFProperty minProperty = null;
434                        if (expression.charAt(index) == '(') {
435                            minProperty = XSPNames.getRDFProperty(owlModel, XSPNames.XSP_MIN_EXCLUSIVE);
436                        }
437                        else {
438                            minProperty = XSPNames.getRDFProperty(owlModel, XSPNames.XSP_MIN_INCLUSIVE);
439                        }
440                        String rest = expression.substring(index + 1).trim();
441                        int minEnd = 0;
442                        while (minEnd < rest.length() &&
443                               (Character.isDigit(rest.charAt(minEnd)) || rest.charAt(minEnd) == '.')) {
444                            minEnd++;
445                        }
446                        String min = rest.substring(0, minEnd);
447                        if (min.length() > 0 && Character.isDigit(min.charAt(0))) {
448                            RDFSLiteral minLiteral = owlModel.createRDFSLiteral(min, datatype);
449                            map.put(minProperty, minLiteral);
450                        }
451                        int maxStart = minEnd;
452                        while (maxStart < rest.length() && !Character.isDigit(rest.charAt(maxStart))) {
453                            maxStart++;
454                        }
455                        if (maxStart < rest.length()) {
456                            rest = rest.substring(maxStart);
457                            int maxEnd = 0;
458                            while (maxEnd < rest.length() &&
459                                   (Character.isDigit(rest.charAt(maxEnd)) || rest.charAt(maxEnd) == '.')) {
460                                maxEnd++;
461                            }
462                            RDFProperty maxProperty = XSPNames.getRDFProperty(owlModel, XSPNames.XSP_MAX_INCLUSIVE);
463                            if (rest.endsWith(")")) {
464                                maxProperty = XSPNames.getRDFProperty(owlModel, XSPNames.XSP_MAX_EXCLUSIVE);
465                            }
466                            String max = rest.substring(0, maxEnd);
467                            if (max.length() > 0 && Character.isDigit(max.charAt(0))) {
468                                RDFSLiteral maxLiteral = owlModel.createRDFSLiteral(max, datatype);
469                                map.put(maxProperty, maxLiteral);
470                            }
471                        }
472                        if (map.size() == 1) {
473                            return new HashMap();
474                        }
475                    }
476                }
477            }
478            return map;
479        }
480    }
481