package uk.ac.manchester.cs.jfact.datatypes; /* This file is part of the JFact DL reasoner Copyright 2011-2013 by Ignazio Palmisano, Dmitry Tsarkov, University of Manchester This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*/ import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.List; import org.semanticweb.owlapi.model.OWLRuntimeException; import org.semanticweb.owlapi.reasoner.ReasonerInternalException; import org.semanticweb.owlapi.vocab.OWLFacet; /** * facets * * @author ignazio */ public class Facets implements Serializable { private static final long serialVersionUID = 11000L; private static abstract class AbstractFacet implements Facet, Serializable { private static final long serialVersionUID = 11000L; protected final String uri; protected final String fragment; public AbstractFacet(String u) { uri = DatatypeFactory.getNamespace() + u; fragment = u; } @Override public String getURI() { return uri; } @Override public String toString() { return "facet[" + fragment + ']'; } @Override public int hashCode() { return uri.hashCode(); } @Override public boolean equals(Object obj) { if (super.equals(obj)) { return true; } if (obj instanceof Facet) { return uri.equals(((Facet) obj).getURI()); } return false; } @SuppressWarnings("rawtypes") @Override public Comparable parseNumber(Object value) { if (!isNumberFacet()) { throw new UnsupportedOperationException( "Only number facets can parse numbers"); } if (value == null) { throw new IllegalArgumentException("Cannot parse a null value"); } try { if (value instanceof String) { return new BigDecimal((String) value); } if (value instanceof Number) { return new BigDecimal(value.toString()); } if (value instanceof Literal) { Object typedValue = ((Literal<?>) value).typedValue(); if (typedValue instanceof Number) { return new BigDecimal(typedValue.toString()); } if (typedValue instanceof Calendar) { return (Comparable<?>) typedValue; } } if (value instanceof Comparable) { return (Comparable<?>) value; } // any other type, its string form must be parseable by // BigDecimal - or exceptions will be spat out return new BigDecimal(value.toString()); } catch (NumberFormatException e) { throw new NumberFormatException("Cannot parse '" + value.toString() + "' as a big decimal"); } } @SuppressWarnings("rawtypes") @Override public Comparable parse(Object o) { return (Comparable<?>) o; } } private static class LimitFacet extends AbstractFacet { private static final long serialVersionUID = 11000L; public LimitFacet(String u) { super(u); } @Override public boolean isNumberFacet() { return true; } } /** * whitespace enum * * @author ignazio */ public enum whitespace { // 4.3.6 whiteSpace /* * [Definition:] whiteSpace constrains the ·value space· of types * ·derived· from string such that the various behaviors specified in * Attribute Value Normalization in [XML 1.0 (Second Edition)] are * realized. The value of whiteSpace must be one of {preserve, replace, * collapse}. */ // preserve /* * No normalization is done, the value is not changed (this is the * behavior required by [XML 1.0 (Second Edition)] for element content) */ // replace /* * All occurrences of #x9 (tab), #xA (line feed) and #xD (carriage * return) are replaced with #x20 (space) */ // collapse /* * After the processing implied by replace, contiguous sequences of * #x20's are collapsed to a single #x20, and leading and trailing * #x20's are removed. */ /* * NOTE: The notation #xA used here (and elsewhere in this * specification) represents the Universal Character Set (UCS) code * point hexadecimal A (line feed), which is denoted by U+000A. This * notation is to be distinguished from , which is the XML * character reference to that same UCS code point. */ /** preserve */ preserve { @Override public String normalize(String input) { return input; } }, /** replace */ replace { @Override public String normalize(String input) { return input.replace('\t', ' ').replace('\n', ' ') .replace('\r', ' '); } }, /** collapse */ collapse { @Override public String normalize(String input) { StringBuilder b = new StringBuilder(replace.normalize(input)); for (int i = 0; i < b.length(); i++) { if (b.charAt(i) == ' ') { while (i < b.length() - 1 && b.charAt(i + 1) == ' ') { b.deleteCharAt(i + 1); } } } return b.toString(); } }; /** * @param input * input * @return normalized input */ public abstract String normalize(String input); } /** length */ public static final Facet length = new LimitFacet("length"); /** minLength */ public static final Facet minLength = new LimitFacet("minLength"); /** maxLength */ public static final Facet maxLength = new LimitFacet("maxLength"); /** totalDigits */ public static final Facet totalDigits = new LimitFacet("totalDigits"); /** fractionDigits */ public static final Facet fractionDigits = new LimitFacet("fractionDigits"); /** whiteSpace */ public static final Facet whiteSpace = new AbstractFacet("whiteSpace") { private static final long serialVersionUID = 11000L; @Override public boolean isNumberFacet() { return false; } @Override public whitespace parse(Object value) { if (value instanceof whitespace) { return (whitespace) value; } if (value instanceof String) { return whitespace.valueOf((String) value); } throw new ReasonerInternalException("Cannot parse " + value + " as a whitespace enum value"); } }; /** pattern */ public static final Facet pattern = new AbstractFacet("pattern") { private static final long serialVersionUID = 11000L; @Override public boolean isNumberFacet() { return false; } @Override public String parse(Object value) { return value.toString(); } }; /** enumeration */ public static final Facet enumeration = new AbstractFacet("enumeration") { private static final long serialVersionUID = 11000L; @Override public boolean isNumberFacet() { return false; } }; /** maxInclusive */ public static final Facet maxInclusive = new LimitFacet("maxInclusive") { private static final long serialVersionUID = 11000L; @Override public String toString() { return "]"; } }; /** maxExclusive */ public static final Facet maxExclusive = new LimitFacet("maxExclusive") { private static final long serialVersionUID = 11000L; @Override public String toString() { return ")"; } }; /** minInclusive */ public static final Facet minInclusive = new LimitFacet("minInclusive") { private static final long serialVersionUID = 11000L; @Override public String toString() { return "["; } }; /** minExclusive */ public static final Facet minExclusive = new LimitFacet("minExclusive") { private static final long serialVersionUID = 11000L; @Override public String toString() { return "("; } }; /** @return all facets */ public static List<Facet> values() { return new ArrayList<Facet>(values); } private static final List<Facet> values = Arrays.asList(enumeration, fractionDigits, length, maxExclusive, maxInclusive, minExclusive, minInclusive, maxLength, minLength, pattern, totalDigits, whiteSpace); /** * @param f * owl facet * @return facet */ public static Facet parse(OWLFacet f) { switch (f) { case LENGTH: return length; case MIN_LENGTH: return minLength; case MAX_LENGTH: return maxLength; case PATTERN: return pattern; case MIN_INCLUSIVE: return minInclusive; case MIN_EXCLUSIVE: return minExclusive; case MAX_INCLUSIVE: return maxInclusive; case MAX_EXCLUSIVE: return maxExclusive; case TOTAL_DIGITS: return totalDigits; case FRACTION_DIGITS: return fractionDigits; default: throw new OWLRuntimeException("Unsupported facet: " + f); } } /** * @param _f * string facet * @return facet */ public static Facet parse(String _f) { String f = '#' + _f.substring(_f.indexOf(':') + 1); for (Facet facet : values) { if (facet.getURI().endsWith(f)) { return facet; } } throw new OWLRuntimeException("Unsupported facet: " + f); } }