package xacmltest.semantics;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.ModelMaker;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.reasoner.ReasonerRegistry;
import com.hp.hpl.jena.shared.PrefixMapping;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.BooleanAttribute;
import com.sun.xacml.attr.StringAttribute;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.cond.FunctionBase;
/**
* A class that implements an "is-instance-of" function. It takes two String
* operands and returns a <code>BooleanAttribute</code> indicating whether the
* first argument can be inferred from the second argument.
*
* @author Julian Schuette
*/
public class IsInstanceOfFunction extends FunctionBase {
// Directory where the ontology files are
private static final String DATA_DIR = "ontologies";
// File name of ontology to be used
public static final String DEVICE_ONTOLOGY = "securityontologytest.owl";
// Full URL of the rdf:type relation
public static final String rdfType = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
/**
* Standard identifier for the string-equal function.
*/
public static final String NAME_STRING_EQUAL = FUNCTION_NS
+ "is-instance-of";
// private mapping of standard functions to their argument types
private static HashMap typeMap;
private static Model m;
/**
* Static initializer sets up a map of standard function names to their
* associated datatypes
*/
static {
typeMap = new HashMap();
typeMap.put(NAME_STRING_EQUAL, StringAttribute.identifier);
// Get the raw model
m = getModel();
}
/**
* Creates a new <code>IsInstanceOfFunction</code> object that supports
* one of the standard type-equal functions. If you need to create an
* instance for a custom type, use the <code>getEqualInstance</code>
* method or the alternate constructor.
*
* @param functionName
* the standard XACML name of the function to be handled by this
* object, including the full namespace
*
* @throws IllegalArgumentException
* if the function isn't standard
*/
public IsInstanceOfFunction(String functionName) {
this(functionName, getArgumentType(functionName));
}
/**
* Creates a new <code>IsInstanceOfFunction</code> object.
*
* @param functionName
* the standard XACML name of the function to be handled by this
* object, including the full namespace
* @param argumentType
* the standard XACML name for the type of the arguments,
* inlcuding the full namespace
*/
public IsInstanceOfFunction(String functionName, String argumentType) {
super(functionName, 0, argumentType, false, 2,
BooleanAttribute.identifier, false);
}
/**
* Private helper that returns the type used for the given standard
* type-equal function.
*/
private static String getArgumentType(String functionName) {
String datatype = (String) (typeMap.get(functionName));
if (datatype == null)
throw new IllegalArgumentException("not a standard function: "
+ functionName);
return datatype;
}
/**
* Returns a <code>Set</code> containing all the function identifiers
* supported by this class.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public static Set getSupportedIdentifiers() {
return Collections.unmodifiableSet(typeMap.keySet());
}
/**
* Evaluate the function, using specified parameters.
*
* @param inputs
* a <code>List</code> of <code>Evaluatable</code> objects
* representing the arguments passed to the function
* @param context
* an <code>EvaluationCtx</code> so that the
* <code>Evaluatable</code> objects can be evaluated
* @return an <code>EvaluationResult</code> representing the function's
* result
*/
public EvaluationResult evaluate(List inputs, EvaluationCtx context) {
// Evaluate the arguments
AttributeValue[] argValues = new AttributeValue[inputs.size()];
EvaluationResult result = evalArgs(inputs, context, argValues);
// If no error: result==null
if (result != null)
return result;
return EvaluationResult.getInstance(isOfType(argValues[1].encode(),
argValues[0].encode()));
}
/**
* Returns true if <code>instance</code> can be inferred from
* <code>type</code> using the ontology.
*
* @param instance
* @param type
* @return
*/
private boolean isOfType(String instance, String type) {
System.out.println("Checking " + instance + " against " + type);
try {
// Start inference (add implicit knowledge)
Reasoner reasoner = ReasonerRegistry.getRDFSReasoner();
InfModel inf = ModelFactory.createInfModel(reasoner, m);
//This is a convenient method for the RDFS reasoner
//InfModel inf = ModelFactory.createRDFSModel(m);
// Define the query: (?a rdf:type ?b)
String queryString = "select ?device\n" + "WHERE \n" + "{ \n"
+ "?device <" + rdfType
+ "> <http://www.owl-ontologies.com/unnamed.owl#" + type
+ ">.\n" + " \n} \n";
Query query = QueryFactory.create(queryString);
QueryExecution qexec = QueryExecutionFactory.create(query, inf);
// Execute SPARQL query
ResultSet results = qexec.execSelect();
// Step through solution, check for instance
boolean itemFound = false;
while (results.hasNext()) {
QuerySolution solution = results.nextSolution();
// This toString().Contains() solution is quick and dirty,
// should be improved.
if (solution.toString().contains(instance)) {
itemFound = true;
System.out.println("Solution: " + solution.toString());
}
}
qexec.close();
// m.close();
return itemFound;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Returns the model provided by the ontology file.
*
* @return
*/
protected static Model getModel() {
ModelMaker maker = ModelFactory.createFileModelMaker(DATA_DIR);
// get the existing model with that name if we can
Model m = maker.getModel(DEVICE_ONTOLOGY);
// if we didn't find it, create a new one
if (m == null) {
m = maker.createModel(DEVICE_ONTOLOGY);
m.withDefaultMappings(PrefixMapping.Standard);
}
return m;
}
}