package edu.mit.simile.fresnel.util;
import java.util.Iterator;
import java.util.Vector;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
/**
* Convenience class representing a generic RDF container (super class of bag, alt, seq).
*
* @author ryanlee
*/
public class Container {
/**
* The graph containing this container
*/
private Repository _source;
/**
* The resource identifying this container
*/
private Resource _origin;
/**
* Constructor based on graph and container resource. Check using isXXX() methods before
* calling constructor.
*
* @param in The data <code>Graph</code>
* @param subject The container's identifying <code>Resource</code>
*/
public Container(Repository in, Resource subject) {
this._source = in;
this._origin = subject;
}
/**
* Whether a resource is any type of RDF container
*
* @param in Data <code>Graph</code>
* @param subject <code>Resource</code> to examine
* @return True if a container, false if not
*/
public static boolean isContainer(Repository in, Resource subject) {
return (isBag(in, subject) || isAlt(in, subject) || isSeq(in, subject));
}
/**
* Whether a resource is a rdf:Bag
*
* @param in Data <code>Graph</code>
* @param subject <code>Resource</code> to examine
* @return True if a bag, false if not
*/
public static boolean isBag(Repository in, Resource subject) {
return is(in, subject, RDF.BAG);
}
/**
* Whether a resource is a rdf:Alt
*
* @param in Data <code>Graph</code>
* @param subject <code>Resource</code> to examine
* @return True if an alt, false if not
*/
public static boolean isAlt(Repository in, Resource subject) {
return is(in, subject, RDF.ALT);
}
/**
* Whether a resource is a rdf:Seq
*
* @param in Data <code>Graph</code>
* @param subject <code>Resource</code> to examine
* @return True if a seq, false if not
*/
public static boolean isSeq(Repository in, Resource subject) {
return is(in, subject, RDF.SEQ);
}
/**
* Checks the type of a resource against a suggested type; no inferencing.
*
* @param in Data <code>Graph</code>
* @param subject The <code>Resource</code> to compare
* @param type A <code>URI</code> for the type to check against
* @return True if the resource is rdf:type of the type, false if not
*/
public static boolean is(Repository in, Resource subject, URI type) {
boolean out = false;
try {
RepositoryConnection conn = in.getConnection();
out = conn.hasStatement(subject, RDF.TYPE, type, false);
conn.close();
} catch (RepositoryException e) {
// TODO: how to handle exception
}
return out;
}
/**
* Iterator through the container's members. Synonymous with listContainerMembers()
*
* @return An <code>Iterator</code>
*/
public Iterator iterator() {
return listContainerMembers();
}
/**
* Iterator through the container's members. Synonymous with iterator()
* @return An <code>Iterator</code>
*/
public Iterator<Resource> listContainerMembers() {
Vector<Resource> result = new Vector<Resource>();
try {
RepositoryConnection conn = this._source.getConnection();
RepositoryResult<Statement> iter = conn.getStatements(this._origin, (URI) null, (Value) null, false);
int maxOrdinal = 0;
while (iter.hasNext()) {
Statement stmt = iter.next();
URI element = stmt.getPredicate();
if (!element.getLocalName().startsWith("_"))
continue;
int ordinal = Integer.parseInt(element.getLocalName().substring(1));
if (ordinal != 0) {
if (ordinal > maxOrdinal) {
maxOrdinal = ordinal;
result.setSize(ordinal);
}
result.setElementAt((Resource) stmt.getObject(), ordinal-1);
}
}
iter.close();
conn.close();
} catch (RepositoryException e) {
// TODO: how to handle exception
}
return result.iterator();
}
}