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.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.semanticweb.owlapi.model.IRI;
/**
* @author ignazio
* @param <T>
* type
*/
public class DatatypeIntersection<T extends Comparable<T>> implements
DatatypeCombination<DatatypeIntersection<T>, Datatype<T>> {
private final Set<Datatype<T>> basics = new HashSet<Datatype<T>>();
private final IRI uri;
private final Datatype<T> host;
/**
* @param collection
* collection
* @return datatype host for a set of datatypes
*/
public static Datatype<?>
getHostDatatype(Collection<Datatype<?>> collection) {
List<Datatype<?>> list = new ArrayList<Datatype<?>>(collection);
// all types need to be compatible, or the intersection cannot be
// anything but empty
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
if (!list.get(i).isCompatible(list.get(j))) {
return null;
}
}
}
// the most specific type needs to be returned
int old_size;
do {
old_size = list.size();
for (int i = 0; i < list.size() - 1;) {
if (list.get(i).isSubType(list.get(i + 1))) {
list.remove(i + 1);
} else if (list.get(i + 1).isSubType(list.get(i))) {
list.remove(i);
} else {
i++;
}
}
} while (list.size() > 1 && old_size != list.size());
// now if list.size >1, there is no single most specific type...
// troubles
if (list.size() == 1) {
return list.get(0);
}
return null;
}
/**
* @param host
* host
*/
public DatatypeIntersection(Datatype<T> host) {
uri = IRI.create("urn:intersection#a" + DatatypeFactory.getIndex());
this.host = host;
}
/**
* @param host
* host
* @param list
* list
*/
public DatatypeIntersection(Datatype<T> host, Iterable<Datatype<T>> list) {
this(host);
for (Datatype<T> d : list) {
basics.add(d);
}
}
@Override
public Datatype<?> getHost() {
return host;
}
@Override
public Iterable<Datatype<T>> getList() {
return basics;
}
@Override
public DatatypeIntersection<T> add(Datatype<T> d) {
DatatypeIntersection<T> toReturn = new DatatypeIntersection<T>(host,
basics);
toReturn.basics.add(d);
return toReturn;
}
@Override
public boolean isCompatible(Literal<?> l) {
// must be compatible with all basics
// host is a shortcut to them
if (!host.isCompatible(l)) {
return false;
}
for (Datatype<?> d : basics) {
if (!d.isCompatible(l)) {
return false;
}
}
return true;
}
@Override
public IRI getDatatypeIRI() {
return uri;
}
@Override
public boolean isCompatible(Datatype<?> type) {
// must be compatible with all basics
// host is a shortcut to them
if (!host.isCompatible(type)) {
return false;
}
for (Datatype<?> d : basics) {
if (!d.isCompatible(type)) {
return false;
}
}
return true;
}
@Override
public boolean isContradictory(Datatype<?> type) {
return !isCompatible(type);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public boolean emptyValueSpace() {
// all base types must be numeric
if (!host.getNumeric()) {
return false;
}
Comparable min = null;
Comparable max = null;
// all intervals must intersect - i.e., the interval with max min
// (excluded if any interval excludes it), min max (excluded if any
// interval excludes it) must contain at least one element
// get max minimum value
boolean minExclusive = false;
boolean maxExclusive = false;
for (Datatype<T> dt : basics) {
Comparable facetValue = dt.asNumericDatatype().getMin();
if (facetValue != null
&& (min == null || min.compareTo(facetValue) < 0)) {
min = facetValue;
}
facetValue = dt.asNumericDatatype().getMax();
if (facetValue != null
&& (max == null || facetValue.compareTo(max) < 0)) {
max = facetValue;
}
if (dt.asNumericDatatype().hasMinExclusive()) {
minExclusive = true;
}
if (dt.asNumericDatatype().hasMaxExclusive()) {
maxExclusive = true;
}
}
int excluded = 0;
if (minExclusive) {
excluded++;
}
if (maxExclusive) {
excluded++;
}
return !DatatypeFactory.intervalWithValues(min, max, excluded);
}
@Override
public String toString() {
return uri + "{" + basics + '}';
}
}