/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT 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 3 of the License, or
(at your option) any later version.
HermiT 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 HermiT. If not, see <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT.datatypes.anyuri;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Set;
import org.semanticweb.HermiT.Prefixes;
import org.semanticweb.HermiT.datatypes.DatatypeHandler;
import org.semanticweb.HermiT.datatypes.MalformedLiteralException;
import org.semanticweb.HermiT.datatypes.UnsupportedFacetException;
import org.semanticweb.HermiT.datatypes.ValueSpaceSubset;
import org.semanticweb.HermiT.model.Constant;
import org.semanticweb.HermiT.model.DatatypeRestriction;
import dk.brics.automaton.Automaton;
public class AnyURIDatatypeHandler implements DatatypeHandler {
protected static final String XSD_NS=Prefixes.s_semanticWebPrefixes.get("xsd:");
protected static final ValueSpaceSubset ANY_URI_ALL=new AnyURIValueSpaceSubset(AnyURIValueSpaceSubset.s_anyURI);
protected static final ValueSpaceSubset EMPTY_SUBSET=new AnyURIValueSpaceSubset(AnyURIValueSpaceSubset.s_empty);
protected static final Set<String> s_managedDatatypeURIs=Collections.singleton(XSD_NS+"anyURI");
public Set<String> getManagedDatatypeURIs() {
return s_managedDatatypeURIs;
}
public Object parseLiteral(String lexicalForm,String datatypeURI) throws MalformedLiteralException {
assert s_managedDatatypeURIs.contains(datatypeURI);
if (!AnyURIValueSpaceSubset.s_anyURI.run(lexicalForm))
throw new MalformedLiteralException(lexicalForm,datatypeURI);
try {
return new URI(lexicalForm);
}
catch (URISyntaxException error) {
throw new MalformedLiteralException(lexicalForm,datatypeURI);
}
}
public void validateDatatypeRestriction(DatatypeRestriction datatypeRestriction) throws UnsupportedFacetException {
assert s_managedDatatypeURIs.contains(datatypeRestriction.getDatatypeURI());
for (int index=datatypeRestriction.getNumberOfFacetRestrictions()-1;index>=0;--index) {
String facetURI=datatypeRestriction.getFacetURI(index);
Constant facetValue=datatypeRestriction.getFacetValue(index);
Object facetDataValue=facetValue.getDataValue();
if ((XSD_NS+"minLength").equals(facetURI) || (XSD_NS+"maxLength").equals(facetURI) || (XSD_NS+"length").equals(facetURI)) {
if (facetDataValue instanceof Integer) {
int value=(Integer)facetDataValue;
if (value<0 || value==Integer.MAX_VALUE)
throw new UnsupportedFacetException("The datatype restriction "+this.toString()+" cannot be handled. The facet with URI '"+facetURI+"' does not support integer "+value+" as value. "+(value<0?"The value should not be negative. ":"The value is outside of the supported integer range, i.e., it is larger than "+Integer.MAX_VALUE));
}
else
throw new UnsupportedFacetException("The datatype xsd:anyURI accepts only integers as facet values for the facet with URI '"+facetURI+"', but in the ontology we have a datatype restriction "+this.toString()+". The value '"+facetValue.toString()+"' does not seem to be an integer.");
}
else if ((XSD_NS+"pattern").equals(facetURI)) {
if (facetDataValue instanceof String) {
String pattern=(String)facetDataValue;
if (!AnyURIValueSpaceSubset.isValidPattern(pattern))
throw new UnsupportedFacetException("String '"+pattern+"' in the datatype restriction "+this.toString()+" is not a valid regular expression.");
}
else
throw new UnsupportedFacetException("The facet with URI '"+facetURI+"' supports only strings as values, but '"+facetValue.toString()+"' in the restriction "+this.toString()+" does not seem to be a string. It is an instance of the class "+facetValue.getClass()+". ");
}
else
throw new UnsupportedFacetException("Facet with URI '"+facetURI+"' is not supported on xsd:anyURI; only xsd:minLength, xsd:maxLength, xsd:length, and xsd:pattern are supported, but the ontology contains the restriction: "+this.toString());
}
}
public ValueSpaceSubset createValueSpaceSubset(DatatypeRestriction datatypeRestriction) {
assert s_managedDatatypeURIs.contains(datatypeRestriction.getDatatypeURI());
if (datatypeRestriction.getNumberOfFacetRestrictions()==0)
return ANY_URI_ALL;
else {
Automaton automaton=getAutomatonFor(AnyURIValueSpaceSubset.s_anyURI,datatypeRestriction);
if (automaton==null)
return EMPTY_SUBSET;
else
return new AnyURIValueSpaceSubset(automaton);
}
}
public ValueSpaceSubset conjoinWithDR(ValueSpaceSubset valueSpaceSubset,DatatypeRestriction datatypeRestriction) {
assert s_managedDatatypeURIs.contains(datatypeRestriction.getDatatypeURI());
if (valueSpaceSubset==EMPTY_SUBSET || datatypeRestriction.getNumberOfFacetRestrictions()==0)
return valueSpaceSubset;
else {
Automaton restrictionAutomaton=getAutomatonFor(((AnyURIValueSpaceSubset)valueSpaceSubset).m_automaton,datatypeRestriction);
if (restrictionAutomaton==null)
return EMPTY_SUBSET;
else
return new AnyURIValueSpaceSubset(restrictionAutomaton);
}
}
public ValueSpaceSubset conjoinWithDRNegation(ValueSpaceSubset valueSpaceSubset,DatatypeRestriction datatypeRestriction) {
assert s_managedDatatypeURIs.contains(datatypeRestriction.getDatatypeURI());
if (valueSpaceSubset==EMPTY_SUBSET || datatypeRestriction.getNumberOfFacetRestrictions()==0)
return EMPTY_SUBSET;
else {
Automaton restrictionAutomaton=getAutomatonFor(AnyURIValueSpaceSubset.s_anyURI,datatypeRestriction);
if (restrictionAutomaton==null)
return valueSpaceSubset;
Automaton difference=((AnyURIValueSpaceSubset)valueSpaceSubset).m_automaton.minus(restrictionAutomaton);
if (difference.isEmpty())
return EMPTY_SUBSET;
else
return new AnyURIValueSpaceSubset(difference);
}
}
protected Automaton getAutomatonFor(Automaton automaton,DatatypeRestriction datatypeRestriction) {
int minLength=0;
int maxLength=Integer.MAX_VALUE;
for (int index=datatypeRestriction.getNumberOfFacetRestrictions()-1;index>=0;--index) {
String facetURI=datatypeRestriction.getFacetURI(index);
Object facetDataValue=datatypeRestriction.getFacetValue(index).getDataValue();
if ((XSD_NS+"minLength").equals(facetURI))
minLength=Math.max(minLength,(Integer)facetDataValue);
else if ((XSD_NS+"maxLength").equals(facetURI))
maxLength=Math.min(maxLength,(Integer)facetDataValue);
else if ((XSD_NS+"length").equals(facetURI)) {
minLength=Math.max(minLength,(Integer)facetDataValue);
maxLength=Math.min(maxLength,(Integer)facetDataValue);
}
else if ((XSD_NS+"pattern").equals(facetURI)) {
String pattern=(String)facetDataValue;
Automaton facetAutomaton=AnyURIValueSpaceSubset.getPatternAutomaton(pattern);
automaton=automaton.intersection(facetAutomaton);
}
else
throw new UnsupportedFacetException("Facet with URI '"+facetURI+"' not supported on xsd:anyURI.");
}
if (minLength>maxLength)
return null;
else if (minLength!=0 || maxLength!=Integer.MAX_VALUE)
automaton=automaton.intersection(AnyURIValueSpaceSubset.toAutomaton(minLength,maxLength));
if (automaton.isEmpty())
return null;
else
return automaton;
}
public boolean isSubsetOf(String subsetDatatypeURI,String supersetDatatypeURI) {
assert s_managedDatatypeURIs.contains(subsetDatatypeURI);
assert s_managedDatatypeURIs.contains(supersetDatatypeURI);
return true;
}
public boolean isDisjointWith(String datatypeURI1,String datatypeURI2) {
assert s_managedDatatypeURIs.contains(datatypeURI1);
assert s_managedDatatypeURIs.contains(datatypeURI2);
return false;
}
}