/*******************************************************************************
* Copyright 2014 Miami-Dade County
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.sharegov.cirm.legacy;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.sharegov.cirm.OWL;
import static org.sharegov.cirm.OWL.*;
public class Permissions
{
//This wont work: having a datafactory is a miracle at that point.
public static final String PROTECTED_CLASS = "mdc:Protected";
public static final OWLNamedIndividual BO_NEW = individual(fullIri("BO_New"));
public static final OWLNamedIndividual BO_VIEW = individual(fullIri("BO_View"));
public static final OWLNamedIndividual BO_UPDATE = individual(fullIri("BO_Update"));
public static final OWLNamedIndividual BO_DELETE = individual(fullIri("BO_Delete"));
public static boolean check(OWLNamedIndividual action,
OWLNamedIndividual entity,
Set<OWLNamedIndividual> groups)
{
return getAllowedActions(action, entity, groups).contains(action);
}
public static Set<OWLNamedIndividual> getAllowedActions(OWLNamedIndividual action, OWLNamedIndividual entity, Set<OWLNamedIndividual> groups)
{
// Here's how the DL expression looks like:
// inverse hasAction some (AccessPolicy and hasActor value
// Animal_Services and hasObject value ASBITE)
if (groups.isEmpty()) return Collections.<OWLNamedIndividual>emptySet();
Set<OWLClassExpression> S = new HashSet<OWLClassExpression>();
if (!groups.isEmpty())
{
for (OWLNamedIndividual group : groups)
S.add(hasObject("hasActor", group));
OWLClassExpression query = some(inverse("hasAction"),
and(owlClass("AccessPolicy"), or(S.toArray(new OWLClassExpression[0])),
hasObject("hasObject", entity)));
//System.out.println(query);
Set<OWLNamedIndividual> allowed = reasoner().getInstances(query, false).getFlattened();
return allowed;
}
else
{
return Collections.<OWLNamedIndividual>emptySet();
}
}
/**
* e.g. inverse hasObject some (AccessPolicy and (hasActor value X or hasActor value Y) ) and ServiceCase
* @param action
* @param objectClass
* @param groups
* @return
*/
public static Set<OWLNamedIndividual> getAllowedObjectsOfClassOld(OWLNamedIndividual action, OWLClass objectClass, Set<OWLNamedIndividual> actors)
{
if (actors.isEmpty()) return Collections.<OWLNamedIndividual>emptySet();
String dlQuery = constrainClause(action, actors);
dlQuery += " and " + OWL.prefixedIRI(objectClass.getIRI());
return OWL.queryIndividuals(dlQuery);
}
/**
* Gets all individuals that are objects in any AccessPolicy for any given actors
* in the fastest known way (by elimitating adding a constrain clause to the reasoner query)
* @param action parameter is currently ignored
* @param objectClass
* @param actors
* @return
*/
public static Set<OWLNamedIndividual> getAllowedObjectsOfClass(OWLNamedIndividual action, OWLClass objectClass, Set<OWLNamedIndividual> actors)
{
//action param currently ignored
if (objectClass == null) throw new NullPointerException();
if (actors.isEmpty()) return Collections.<OWLNamedIndividual>emptySet();
OWLOntology ontology = ontology();
OWLReasoner reasoner = reasoner(ontology);
Set<OWLNamedIndividual> allAllowed = null;
if (reasoner.getSuperClasses(objectClass, false).containsEntity(owlClass("Protected")))
{
allAllowed = new HashSet<OWLNamedIndividual>();
Set<OWLNamedIndividual> policies = policiesForActors(actors);
for (OWLNamedIndividual x : policies)
{
Set<OWLNamedIndividual> allowedActions = OWL.objectProperties(x, "hasAction");
if (allowedActions.contains(action)) {
Set<OWLNamedIndividual> policyObjects = OWL.objectProperties(x, "hasObject");
allAllowed.addAll(policyObjects);
}
}
}
// The following is not a 100% test for protection. To be 100%, we'd have
// to check that getInstances returns an empty set rather than getSubClasses, but
// this will work in practice and it's a hopefully faster test
else if (!reasoner.getSubClasses(and(objectClass, owlClass("Protected")), false).isBottomSingleton())
{
System.err.println("Permissions:getAllowedObjectsOfClass Unsafe Query for " + objectClass + " - Returning empty set.");
return Collections.<OWLNamedIndividual>emptySet();
}
Set<OWLNamedIndividual> result = new HashSet<OWLNamedIndividual>();
for (OWLNamedIndividual ind : reasoner.getInstances(objectClass, false).getFlattened())
{
if (allAllowed == null || allAllowed.contains(ind))
result.add(ind);
}
return result;
}
/**
* Constrain for protected individuals. All non protected should be allowed.
* @param action
* @param actors
* @return
*/
public static OWLClassExpression constrain(OWLNamedIndividual action, Set<OWLNamedIndividual> actors)
{
Set<OWLClassExpression> S = new HashSet<OWLClassExpression>();
if (!actors.isEmpty())
{
for (OWLNamedIndividual actor : actors)
S.add(hasObject("hasActor", actor));
}
else
{
S.add(OWL.dataFactory().getOWLNothing());
}
return some(inverse("hasObject"),
and(owlClass("AccessPolicy"),
or(S.toArray(new OWLClassExpression[0]))));
}
/**
* Same as constrain but returns it as a String so it can be added to a Manchester
* syntax DL expression.
*
* @param action
* @param actors
* @return
*/
public static String constrainClause(OWLNamedIndividual action, Set<OWLNamedIndividual> actors)
{
//Set<OWLClassExpression> S = new HashSet<OWLClassExpression>();
StringBuilder or = new StringBuilder();
if (!actors.isEmpty())
{
for (Iterator<OWLNamedIndividual> i = actors.iterator(); i.hasNext(); )
{
or.append("hasActor value " + OWL.prefixedIRI(i.next().getIRI()));
if (i.hasNext())
or.append(" or ");
}
}
else
{
or.append("Nothing");
}
return " inverse hasObject some (AccessPolicy and (" + or + "))";
}
public static Set<OWLNamedIndividual> policiesForActors(Set<OWLNamedIndividual> actors)
{
StringBuilder or = new StringBuilder();
if (!actors.isEmpty())
{
for (Iterator<OWLNamedIndividual> i = actors.iterator(); i.hasNext(); )
{
or.append("hasActor value " + OWL.prefixedIRI(i.next().getIRI()));
if (i.hasNext())
or.append(" or ");
}
}
else
{
or.append("Nothing");
}
return OWL.queryIndividuals(or.toString());
}
}