/*******************************************************************************
* 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.workflows;
import org.hypergraphdb.app.owl.model.swrl.SWRLVariableHGDB;
import org.hypergraphdb.util.RefResolver;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.*;
import org.sharegov.cirm.utils.EvalUtils;
import java.util.*;
/**
*
* <p>
* An AppliedRule contains evaluation information for a single SWRLRule. The information
* consists of the following maps:
*
* variables: contains the value of each variable we were able to resolve.
* truthValues: contains the result (true, false, unknown) of evaluating each atom in the rule's body
* instantiated: contains an instantiated version (i.e. with known variables replaced by their values)
* of each atom in the rule's head
* dependents/dependsOn: an atom A in the rule's body depends on another atom B if A contains a variable
* which was instantiated from A and the same variable also occurs in B. The dependents map associates
* atoms with set of dependents and the dependsOn map is just the reverse relationship. Dependencies
* are used to order atoms in an execution workflow.
* </p>
*
* @author Borislav Iordanov
*
*/
public class AppliedRule
{
OWLOntologyManager manager;
SWRLRule rule;
Map<SWRLVariable, OWLObject> variables = new HashMap<SWRLVariable, OWLObject>();
Map<SWRLAtom, AtomValue> truthValues = new HashMap<SWRLAtom, AtomValue>();
Map<SWRLAtom, Set<SWRLAtom>> dependents = new HashMap<SWRLAtom, Set<SWRLAtom>>();
Map<SWRLAtom, Set<SWRLAtom>> dependsOn = new HashMap<SWRLAtom, Set<SWRLAtom>>();
Map<SWRLAtom, SWRLAtom> instantiated = new HashMap<SWRLAtom, SWRLAtom>();
SWRLVariable getDependableVar(SWRLAtom atom, Set<SWRLAtom> depset)
{
System.out.println("Get DEP VAR in " + atom);
Set<SWRLAtom> reverse = dependsOn.get(atom);
Set<SWRLVariable> knownVars = new HashSet<SWRLVariable>();
knownVars.add(new SWRLVariableHGDB(RulesToWorkflow.boVar));
if (reverse != null) for (SWRLAtom dep : reverse)
{
if (depset.contains(dep))
throw new RuntimeException("Circular dependency in " + depset);
depset.add(dep);
SWRLVariable var = getDependableVar(dep, depset);
if (var != null)
knownVars.add(var);
}
return EvalUtils.getDependableVar(substituteVars(atom), knownVars);
}
SWRLVariable getDependableVar(SWRLAtom atom)
{
return getDependableVar(atom, new HashSet<SWRLAtom>(Collections.singleton(atom)));
}
void computeDependents()
{
if (rule.getBody().size() != truthValues.size())
throw new RuntimeException("rule not evaluated yet");
for (boolean done = false; !done; )
{
done = true;
for (SWRLAtom atom : rule.getBody())
{
// the form we are expecting is (Predicate KnownSubject Variable) for
// dependable atoms
SWRLVariable var = getDependableVar(atom);
if (var == null)
continue;
Set<SWRLAtom> S = dependents.get(atom);
if (S == null)
{
S = new HashSet<SWRLAtom>();
dependents.put(atom, S);
}
for (SWRLAtom other : rule.getBody())
{
if (other.equals(atom) || S.contains(other))
continue;
for (SWRLArgument arg : other.getAllArguments())
if (arg instanceof SWRLVariable && var.equals(arg))
{
S.add(other);
Set<SWRLAtom> reverseS = dependsOn.get(other);
if (reverseS == null)
{
reverseS = new HashSet<SWRLAtom>();
dependsOn.put(other, reverseS);
}
reverseS.add(atom);
done = false;
break;
}
}
}
}
System.out.println("Dependson:" + dependsOn);
}
public SWRLRule getRule() { return rule; }
public Map<SWRLVariable, OWLObject> getVariables() { return variables; }
public SWRLAtom substituteVars(SWRLAtom a)
{
return instantiated.containsKey(a) ? instantiated.get(a) : a;
}
/**
* Does evaluation of this atom depend on variable instantiation by some
* other atom before it?
*
* @param atom
* @return
*/
boolean isIndependent(SWRLAtom atom)
{
Set<SWRLAtom> S = dependsOn.get(atom);
return S == null || S.isEmpty();
}
public Set<SWRLAtom> getUnknowns()
{
if (rule.getBody().size() != truthValues.size())
throw new RuntimeException("rule not evaluated yet");
HashSet<SWRLAtom> S = new HashSet<SWRLAtom>();
for (Map.Entry<SWRLAtom, AtomValue> e : truthValues.entrySet())
if (e.getValue() == AtomValue.Unknown)
S.add(e.getKey());
return S;
}
public AtomValue isSatisfied()
{
if (rule.getBody().size() != truthValues.size())
throw new RuntimeException("rule not evaluated yet");
AtomValue result = AtomValue.True;
for (AtomValue x : truthValues.values())
if (x == AtomValue.False)
return AtomValue.False;
else if (x == AtomValue.Unknown)
result = AtomValue.Unknown;
return result;
}
public void assign(SWRLVariable v, OWLObject x)
{
variables.put(v, x);
}
@SuppressWarnings("unchecked")
public <T extends OWLObject> T valueOf(SWRLVariable v)
{
return (T)variables.get(v);
}
public RefResolver<SWRLVariable, OWLObject> getVarResolver()
{
return new RefResolver<SWRLVariable, OWLObject>()
{
public OWLObject resolve(SWRLVariable v) { return valueOf(v); }
};
}
public int hashCode() { return rule.hashCode(); }
public boolean equals(Object x) { return rule.equals(((AppliedRule)x).rule); }
}