All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrdf.sesame.query.rql.model.Intersection Maven / Gradle / Ivy

Go to download

Sesame is an open source Java framework for storing, querying and reasoning with RDF.

The newest version!
/*  Sesame - Storage and Querying architecture for RDF and RDF Schema
 *  Copyright (C) 2001-2006 Aduna
 *
 *  Contact: 
 *  	Aduna
 *  	Prinses Julianaplein 14 b
 *  	3817 CS Amersfoort
 *  	The Netherlands
 *  	tel. +33 (0)33 465 99 87
 *  	fax. +33 (0)33 465 99 87
 *
 *  	http://aduna-software.com/
 *  	http://www.openrdf.org/
 *  
 *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.openrdf.sesame.query.rql.model;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import org.openrdf.model.GraphException;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.Value;
import org.openrdf.model.impl.URIImpl;

import org.openrdf.sesame.query.rql.model.iterators.StatementSubjectIterator;
import org.openrdf.sesame.sail.RdfSchemaSource;
import org.openrdf.sesame.sail.StatementIterator;
import org.openrdf.sesame.sail.ValueIterator;
import org.openrdf.sesame.sail.util.ValueCollectionIterator;

/**
 * An intersection of classes.
 **/
public class Intersection implements Resource {

	/** The members (classes) of this intersection. **/
    private TreeSet _memberSet;

	/**
	 * Creates a new, empty Intersection.
	 **/
    public Intersection() {
        _memberSet = new TreeSet();
    }

	/**
	 * Creates a new Intersection that is initialized with the objects
	 * of the statements from the supplied StatementIterator. The
	 * StatementIterator will be closed when all its elements have been
	 * read.
	 **/
	public Intersection(StatementIterator statIter) {
		this();
		while (statIter.hasNext()) {
			Statement stat = statIter.next();
			Value v = stat.getObject();
			if (v instanceof Resource) {
				this.add((Resource)v);
			}
		}
		statIter.close();
	}

	/**
	 * Gets the members of this intersection.
	 *
	 * @return a Set of Resource objects.
	 **/
    public Set getMembers() {
        return _memberSet;
    }

	public Resource getFirstMember() {
		if (_memberSet.size() > 0) {
			return (Resource)_memberSet.iterator().next();
		}
		return null;
	}

	/**
	 * Adds a resource to this intersection. The resource will be ignored
	 * if it is already in the intersection.
	 *
	 * @param resource A Resource representing a class.
	 **/
    public void add(Resource resource) {
        _memberSet.add(resource);
    }


	/**
	 * Minimizes the set of classes in this intersection by filtering out
	 * any superclasses for which there are also subclasseses in this
	 * intersection.
	 *
	 * @param rss The RdfSchemaSource to use for checking the sub-superclass
	 * relations.
	 **/
	public Value minimize(RdfSchemaSource rss) {
		// Intersections of size 0 cannot be further minimized:
		if (_memberSet.size() == 0) {
			return this;
		}

		if (_memberSet.size() == 1) {
			return getFirstMember();
		}

		Resource member, superClass;
		org.openrdf.sesame.sail.StatementIterator superClasses;
		Iterator memberIter = _memberSet.iterator();
		TreeSet resultSet = new TreeSet(_memberSet);

		while (memberIter.hasNext()) {
			member = (Resource)memberIter.next();
			superClasses = rss.getDirectSubClassOf(member, null);
				
			/*
			 * A superclass of member in the iterator is member itself,
			 * because every superclass is a superclass of itself. You
			 * don 't want to remove member from resultSet.
			 * It is skipped with equals(Object).
			 */

			while (superClasses.hasNext()) {
				superClass = (Resource)superClasses.next().getObject();

				if (!member.equals(superClass)) {
					resultSet.remove(superClass);
				}
			}
		}
		_memberSet = resultSet;

		if (_memberSet.size() == 1) {
			return getFirstMember();
		}
		else {
			return this;
		}
	}

	/**
	 * Gets the size (number of resources) of this intersection.
	 **/
	public int size() {
		return _memberSet.size();
	}

	/**
	 * Checks if the supplied resource is an instance of all classes
	 * of this intersection, using the supplied RdfSchemaSource to check
	 * the instance relations.
	 **/
	public boolean containsInstance(Resource instance, RdfSchemaSource rss) {
		boolean result = true;

		Iterator iter = _memberSet.iterator();

		while (iter.hasNext()) {
			Resource clazz = (Resource)iter.next();

			if (!rss.isType(instance, clazz)) {
				result = false;
				break;
			}
		}

		return result;
	}

	/**
	 * Gets all resources that are instances of all classes of this
	 * intersection.
	 **/
	public ValueIterator getInstances(RdfSchemaSource rss) {
		if (size() == 0) {
			// return all resources
			return new StatementSubjectIterator(
					rss.getType(null, URIImpl.RDFS_RESOURCE));
		}

		Iterator iter = _memberSet.iterator();

		// Initialize result with all instances of the first class
		Resource clazz = (Resource)iter.next();
		Set result = _getInstances(clazz, rss);

		// Retain only the instances that are also returned for the
		// other classes
		while (iter.hasNext()) {
			clazz = (Resource)iter.next();
			Set instances = _getInstances(clazz, rss);
			result.retainAll(instances);
		}

		return new ValueCollectionIterator(result);
	}

	private Set _getInstances(Resource clazz, RdfSchemaSource rss) {
		Set result = new HashSet();

		StatementIterator statIter = rss.getType(null, clazz);
		while (statIter.hasNext()) {
			result.add(statIter.next().getSubject());
		}
		statIter.close();

		return result;
	}

	/**
	 * Compares this intersection to another object.
	 *
	 * @param other The Object to compare ths intersection to.
	 * @return true if this intersection is equal to the supplied object,
	 * false otherwise.
	 **/
    public boolean equals(Object other) {
        if (other instanceof Intersection) {
            return _memberSet.equals(((Intersection)other).getMembers());
        }
        return false;
    }

	public boolean lowerEqualThan(Intersection other, RdfSchemaSource rss) {
		
		Set set2 = other.getMembers();
		
		// if set2 is a subset of (or equal to) _memberSet, then
		// _memberSet is more (or equally) constrained and therefore a
		// larger (or equal) domain/range.
		if (_memberSet.containsAll(set2)) {
			return true;
		}

		// we need to check all classes that are in set2 but not in _memberSet;
		// possibly _memberSet contains subclasses of these classes.
		TreeSet difference = new TreeSet(set2);
		difference.removeAll(_memberSet);

		Resource classResource, subClass;
		org.openrdf.sesame.sail.StatementIterator subClassIter;
		boolean subClassInSet;

		Iterator diffIter = difference.iterator();

		// for each class in the difference, a subclass has to be present
		// in _memberSet.
		while (diffIter.hasNext()) {
			subClassInSet = false;

			classResource = (Resource)diffIter.next();
			subClassIter = rss.getSubClassOf(null, classResource);

			// while we have not found a subclass of this class in _memberSet,
			// we keep on checking.
			while (!subClassInSet && subClassIter.hasNext()) {
				subClass = subClassIter.next().getSubject();
				if (_memberSet.contains(subClass)) {
					subClassInSet = true;
				}
			}
			if (! subClassInSet) {
				// there is a class in set2 that has no subclass in _memberSet.
				return false;
			}
		}
		// all classes in set2 are also in _memberSet, or a subclass of them is
		// in _memberSet.
		return true;
	}

	public boolean greaterThan(Intersection other, RdfSchemaSource rss) {
		return ! this.lowerEqualThan(other, rss);
	}

	public boolean greaterEqualThan(Intersection other, RdfSchemaSource rss) {
		return (this.equals(other) || this.greaterThan(other, rss));
	}

	public boolean lowerThan(Intersection other, RdfSchemaSource rss) {
		return (! this.equals(other)) && this.lowerEqualThan(other, rss);
	}

	/**
	 * Returns a hashcode for use in hash tables.
	 **/
	public int hashCode() {
		return _memberSet.hashCode();
	}

	public int compareTo(Object o) {
		Intersection other = (Intersection)o;

		int result = size() - other.size();

		if (result == 0) {
			// equal size

			Iterator thisIter = getMembers().iterator();
			Iterator otherIter = other.getMembers().iterator();

			while (result == 0 && thisIter.hasNext()) {
				Resource thisRes = (Resource)thisIter.next();
				Resource otherRes = (Resource)otherIter.next();

				result = thisRes.compareTo(otherRes);
			}
		}

		return result;
	}

	/**
	 * Gives a String-representation of this Intersection that can be used
	 * for debugging.
	 **/
	public String toString() {
		return _memberSet.toString();
	}

	/* (non-Javadoc)
	 * @see org.openrdf.model.Resource#addProperty(org.openrdf.model.URI, org.openrdf.model.Value)
	 */
	public void addProperty(org.openrdf.model.URI property, Value value) throws GraphException {
		throw new GraphException("no backing store associated");
	}

	/* (non-Javadoc)
	 * @see org.openrdf.model.Resource#getSubjectStatements()
	 */
	public StatementIterator getSubjectStatements() throws GraphException {
		throw new GraphException("no backing store associated");
	}

	/* (non-Javadoc)
	 * @see org.openrdf.model.Value#getObjectStatements()
	 */
	public StatementIterator getObjectStatements() throws GraphException {
		throw new GraphException("no backing store associated");
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy