package edu.mit.simile.fresnel.format;
import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
import fr.inria.jfresnel.fsl.FSLPath;
import edu.mit.simile.fresnel.FresnelCoreTypes;
import edu.mit.simile.fresnel.configuration.Configuration;
import edu.mit.simile.fresnel.purpose.Purpose;
import edu.mit.simile.fresnel.selection.FSESelector;
import edu.mit.simile.fresnel.selection.ISelector;
import edu.mit.simile.fresnel.selection.ParsingException;
import edu.mit.simile.fresnel.selection.SPARQLSelector;
import edu.mit.simile.fresnel.selection.TypeSelector;
import edu.mit.simile.fresnel.selection.UnresolvableException;
import edu.mit.simile.vocabularies.FresnelCore;
/**
* Format matching an rdf:type value.
*
* @author ryanlee
*/
public class ClassFormat extends Format {
/**
* Context for determining FSL first location step type.
*/
protected final static short _fslContext = FSLPath.NODE_STEP;
/**
* Constructor based on the resource identifier of the format.
*
* @param id A <code>Resource</code>
*/
public ClassFormat(Resource id) {
super(id);
}
/**
* Parses a resource into a valid fresnel:Format object.
*
* @param in The <code>Repository</code> the configuration is derived from
* @param selected The fresnel:Format <code>Resource</code>
* @param conf The <code>Configuration</code> to add to
* @return A new <code>Format</code>
* @throws UnresolvableException When the wrong count for a predicate is present
* @throws ParsingException When any other syntax error occurs
*/
public static Format parse(Repository in, Resource selected, Configuration conf)
throws UnresolvableException, ParsingException {
ClassFormat out = new ClassFormat(selected);
try {
// Parse domain
ClassFormat.parseDomain(out, in, selected, conf);
RepositoryConnection conn = in.getConnection();
// Set of purposes
RepositoryResult<Statement> purposesI = conn.getStatements(selected, FresnelCore.purpose, (Value) null, false);
try {
while (purposesI.hasNext()) {
Value purposeNode = purposesI.next().getObject();
if (purposeNode instanceof Resource) {
Resource purposeRes = (Resource) purposeNode;
out.addPurpose(new Purpose(purposeRes));
} else {
throw new ParsingException(purposeNode.toString() + "could not be used as a :Purpose");
}
}
} finally {
purposesI.close();
}
// resource style
RepositoryResult<Statement> resourceStyleI = conn.getStatements(selected, FresnelCore.resourceStyle, (Value) null, false);
while (resourceStyleI.hasNext()) {
Statement resourceStyleS = resourceStyleI.next();
Value styleObj = resourceStyleS.getObject();
out.addResourceStyle(Style.parse(styleObj));
}
resourceStyleI.close();
// resource format
RepositoryResult<Statement> resourceFormatI = conn.getStatements(selected, FresnelCore.resourceFormat, (Value) null, false);
while (resourceFormatI.hasNext()) {
Statement resourceFormatS = resourceFormatI.next();
Resource formatObj = (Resource) resourceFormatS.getObject();
out.addResourceFormat(FormatDescription.parse(in, formatObj));
}
resourceFormatI.close();
conn.close();
} catch (RepositoryException e) {
throw new UnresolvableException("Problem connecting to repository: " + e.getLocalizedMessage());
}
return out;
}
/**
* Parse out domain information and add to the Format.
*
* @param out The <code>Format</code> to modify
* @param in The <code>Repository</code> containing configuration information
* @param selected The <code>Resource</code> identifying the style
* @param conf The <code>Configuration</code> parsing this format
*/
protected static void parseDomain(Format out, Repository in, Resource selected, Configuration conf) throws RepositoryException {
RepositoryConnection conn = in.getConnection();
RepositoryResult<Statement> domainsI = conn.getStatements(selected, FresnelCore.classFormatDomain, (Value) null, false);
while (domainsI.hasNext()) {
ISelector domain = null;
Value domainNode = domainsI.next().getObject();
if (domainNode instanceof Resource) {
// This is a type selector
domain = new TypeSelector((URI) domainNode);
} else if (domainNode instanceof Literal) {
Literal domainL = (Literal) domainNode;
// TODO: catch bad expressions? throw exceptions?
if (domainL.getDatatype().equals(FresnelCoreTypes.fslSelector)) {
domain = new FSESelector(domainL.getLabel(), _fslContext, conf.getNamespaceMap());
} else if (domainL.getDatatype().equals(FresnelCoreTypes.sparqlSelector)) {
domain = new SPARQLSelector(domainL.getLabel(), conf.getNamespaces());
}
}
out.addDomain(domain);
}
domainsI.close();
conn.close();
}
}