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 static uk.ac.manchester.cs.jfact.datatypes.DatatypeFactory.LITERAL; import static uk.ac.manchester.cs.jfact.datatypes.Facets.*; import java.util.Collection; import org.semanticweb.owlapi.model.IRI; class DatatypeOrderedExpressionImpl<O extends Comparable<O>> extends ABSTRACT_DATATYPE<O> implements DatatypeExpression<O>, OrderedDatatype<O> { private static final long serialVersionUID = 11000L; // TODO handle all value space restrictions in the delegations private final Datatype<O> host; public DatatypeOrderedExpressionImpl(Datatype<O> b) { super( IRI.create(b.getDatatypeIRI() + "_" + DatatypeFactory.getIndex()), b.getFacets()); if (b.isExpression()) { this.host = b.asExpression().getHostType(); } else { this.host = b; } ancestors = Utils.generateAncestors(this.host); knownNumericFacetValues.putAll(b.getKnownNumericFacetValues()); knownNonNumericFacetValues.putAll(b.getKnownNonNumericFacetValues()); } @Override public O parseValue(String s) { return this.host.parseValue(s); } @Override public boolean isInValueSpace(O l) { // to be in value space, ex min must be smaller than l if (this.hasMinExclusive() && l.compareTo(this.getMin()) <= 0) { return false; } // to be in value space, min must be smaller or equal to l if (this.hasMinInclusive() && l.compareTo(this.getMin()) < 0) { return false; } // to be in value space, ex max must be bigger than l if (this.hasMaxExclusive() && l.compareTo(this.getMax()) >= 0) { return false; } // to be in value space, ex min must be smaller than l if (this.hasMaxInclusive() && l.compareTo(this.getMax()) > 0) { return false; } return true; } @SuppressWarnings("unchecked") @Override public boolean isCompatible(Datatype<?> type) { // if (!super.isCompatible(type)) { // return false; // } if (type.equals(LITERAL)) { return true; } // if(isSubType(type)||type.isSubType(this)) { // return true; // } if (type.isOrderedDatatype()) { OrderedDatatype<O> wrapper = (OrderedDatatype<O>) type .asOrderedDatatype(); // if both have no max or both have no min -> there is an // overlap // if one has no max, then min must be smaller than max of the // other // if one has no min, the max must be larger than min of the // other // if one has neither max nor min, they are compatible if (!this.hasMax() && !this.hasMin()) { return true; } if (!wrapper.hasMax() && !wrapper.hasMin()) { return true; } if (!this.hasMax() && !wrapper.hasMax()) { return true; } if (!this.hasMin() && !wrapper.hasMin()) { return true; } if (!this.hasMin()) { return this.overlapping(this, wrapper); } if (!this.hasMax()) { return this.overlapping(wrapper, this); } if (!wrapper.hasMin()) { return this.overlapping(wrapper, this); } if (!wrapper.hasMax()) { return this.overlapping(this, wrapper); } // compare their range facets: // disjoint if: // exclusives: // one minInclusive/exclusive is strictly larger than the other // maxinclusive/exclusive return this.overlapping(this, wrapper) || this.overlapping(wrapper, this); } else { return false; } } @Override public ordered getOrdered() { return this.host.getOrdered(); } @Override public boolean getNumeric() { return this.host.getNumeric(); } @Override public cardinality getCardinality() { return this.host.getCardinality(); } @Override public boolean getBounded() { return this.host.getBounded(); } @Override public Collection<Literal<O>> listValues() { return this.host.listValues(); } @Override public Datatype<O> getHostType() { return this.host; } @Override public DatatypeExpression<O> addNonNumericFacet(Facet f, Comparable<?> value) { if (!facets.contains(f)) { throw new IllegalArgumentException("Facet " + f + " not allowed tor datatype " + this.getHostType()); } if (value == null) { throw new IllegalArgumentException("Value cannot be null"); } if (value instanceof Literal && !this.host.isCompatible((Literal<?>) value)) { throw new IllegalArgumentException( "Not a valid value for this expression: " + f + '\t' + value + " for: " + this); } DatatypeOrderedExpressionImpl<O> toReturn = new DatatypeOrderedExpressionImpl<O>( this.host); toReturn.knownNumericFacetValues.putAll(knownNumericFacetValues); toReturn.knownNonNumericFacetValues.putAll(knownNonNumericFacetValues); toReturn.knownNonNumericFacetValues.put(f, value); return toReturn; } @Override public DatatypeExpression<O> addNumericFacet(Facet f, Comparable<?> value) { if (!facets.contains(f)) { throw new IllegalArgumentException("Facet " + f + " not allowed tor datatype " + this.getHostType()); } if (value == null) { throw new IllegalArgumentException("Value cannot be null"); } DatatypeOrderedExpressionImpl<O> toReturn = new DatatypeOrderedExpressionImpl<O>( this.host); toReturn.knownNumericFacetValues.putAll(knownNumericFacetValues); toReturn.knownNonNumericFacetValues.putAll(knownNonNumericFacetValues); // cannot have noth min/maxInclusive and min/maxExclusive values, so // remove them if the feature is min/max if (f.equals(minExclusive) || f.equals(minInclusive)) { toReturn.knownNumericFacetValues.remove(minExclusive); toReturn.knownNumericFacetValues.remove(minInclusive); } if (f.equals(maxExclusive) || f.equals(maxInclusive)) { toReturn.knownNumericFacetValues.remove(maxExclusive); toReturn.knownNumericFacetValues.remove(maxInclusive); } toReturn.knownNumericFacetValues.put(f, value); return toReturn; } @Override public boolean isExpression() { return true; } @SuppressWarnings("rawtypes") @Override public boolean emptyValueSpace() { // TODO not checking string type value spaces; looks like the only // sensible way would be to check for 0 length constraints if (this.getNumeric()) { // remember whether it's inclusive or exclusive - needed to know if // the two extremes can be the same or not int excluded = 0; Comparable min = getNumericFacetValue(minInclusive); if (min == null) { min = getNumericFacetValue(minExclusive); excluded++; } Comparable max = getNumericFacetValue(maxInclusive); if (max == null) { max = getNumericFacetValue(maxExclusive); excluded++; } return !DatatypeFactory.intervalWithValues(min, max, excluded); } return false; } @Override public boolean isNumericDatatype() { return this.host.isNumericDatatype(); } @Override public NumericDatatype<O> asNumericDatatype() { return null; } @Override public boolean isOrderedDatatype() { return this.host.isOrderedDatatype(); } @Override public OrderedDatatype<O> asOrderedDatatype() { return this; } @Override public boolean hasMinExclusive() { return knownNumericFacetValues.containsKey(minExclusive); } @Override public boolean hasMinInclusive() { return knownNumericFacetValues.containsKey(minInclusive); } @Override public boolean hasMaxExclusive() { return knownNumericFacetValues.containsKey(maxExclusive); } @Override public boolean hasMaxInclusive() { return knownNumericFacetValues.containsKey(maxInclusive); } @Override public boolean hasMin() { return this.hasMinInclusive() || this.hasMinExclusive(); } @Override public boolean hasMax() { return this.hasMaxInclusive() || this.hasMaxExclusive(); } @SuppressWarnings("unchecked") @Override public O getMin() { if (this.hasMinInclusive()) { return (O) knownNumericFacetValues.get(minInclusive); } if (this.hasMinExclusive()) { return (O) knownNumericFacetValues.get(minExclusive); } return null; } @SuppressWarnings("unchecked") @Override public O getMax() { if (this.hasMaxInclusive()) { return (O) knownNumericFacetValues.get(maxInclusive); } if (this.hasMaxExclusive()) { return (O) knownNumericFacetValues.get(maxExclusive); } return null; } @Override public String toString() { return this.getClass().getName() + '(' + this.host.toString() + "(extra facets:" + knownNumericFacetValues + "))"; } }