/*******************************************************************************
* 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 static org.sharegov.cirm.OWL.fullIri;
import static org.sharegov.cirm.OWL.ontology;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.hypergraphdb.HGHandle;
import org.hypergraphdb.HGPersistentHandle;
import org.hypergraphdb.annotation.AtomReference;
import org.hypergraphdb.util.Pair;
import org.hypergraphdb.util.RefResolver;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataRange;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyChange;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.RemoveAxiom;
import org.semanticweb.owlapi.model.SWRLDArgument;
import org.semanticweb.owlapi.model.SWRLIArgument;
import org.semanticweb.owlapi.model.SWRLIndividualArgument;
import org.semanticweb.owlapi.model.SWRLLiteralArgument;
import org.semanticweb.owlapi.model.SWRLVariable;
import org.sharegov.cirm.OWL;
import org.sharegov.cirm.Refs;
// TODO: the following dependency should be removed (refact the getForm code somewhere else)
import org.sharegov.cirm.rest.UiService;
import mjson.Json;
public abstract class Task implements WorkflowStep
{
@AtomReference("symbolic")
private WorkflowStep next;
private Set<IRI> outputVariables = new HashSet<IRI>();
protected HGHandle handle;
protected HGPersistentHandle prototypeId;
private double assignedScore = -1.0;
// The following represents variable bindings from upstream (where values are output)
// steps to downstream steps (where values are received)
// local input var <- pair(upstream task, upstream output var)
private Map<IRI, Pair<HGHandle, IRI>> inputVariables = new HashMap<IRI, Pair<HGHandle, IRI>>();
protected RefResolver<SWRLVariable, OWLObject> getVarResolver(final WorkflowExecutionContext ctx)
{
return new RefResolver<SWRLVariable, OWLObject>(){
public OWLObject resolve(SWRLVariable var)
{
Pair<HGHandle, IRI> globalId = getInputVariables().get(var.getIRI());
if (globalId == null)
globalId = new Pair<HGHandle, IRI>(getPrototypeId(), var.getIRI());
OWLObject x = (OWLObject)ctx.getVariable(globalId == null ? getPrototypeId() : globalId.getFirst(),
globalId == null ? var.getIRI() : globalId.getSecond());
//(OWLObject)ctx.getVariables().get(globalId);
return (x == null) ? ctx.getVarResolver().resolve(var) : x;
}
};
}
protected void deleteObjectProperty(final WorkflowExecutionContext ctx,
OWLObjectProperty prop,
OWLIndividual ind,
Json value)
{
OWLOntologyManager manager = OWL.manager();
OWLDataFactory df = manager.getOWLDataFactory();
Set<OWLIndividual> all = ind.getObjectPropertyValues(prop, ctx.getBusinessObjectOntology().getOntology());
for (OWLIndividual x : all)
{
OWLAxiom axiom = df.getOWLObjectPropertyAssertionAxiom(prop, ind, x);
manager.applyChange(new RemoveAxiom(ctx.getBusinessObjectOntology().getOntology(), axiom));
}
}
protected OWLIndividual assignObjectProperty(final WorkflowExecutionContext ctx,
OWLObjectProperty prop,
OWLIndividual ind,
Json value)
{
OWLOntologyManager manager = OWL.manager();
OWLDataFactory df = manager.getOWLDataFactory();
OWLIndividual object = null;
OWLClassExpression objectType = null;
for (OWLClassExpression range : prop.getRanges(ontology()))
// TODO: we need to somehow pass the actual type of the property value
// to the client (hidden form field perhaps) and back to the server
// this is a hack because PromptUserTask currently uses the first range that has a form
if (new UiService().getForm(range) != null)
{
objectType = range;
break;
}
if (value.isObject())
object = makeObjectIndividual(ctx,
fullIri(objectType.asOWLClass().getIRI().getFragment() +
Refs.idFactory.resolve().newId()),
value);
else
object = df.getOWLNamedIndividual(IRI.create(value.asString()));
ArrayList<OWLOntologyChange> L = new ArrayList<OWLOntologyChange>();
L.add(new AddAxiom(ctx.getBusinessObjectOntology().getOntology(),
df.getOWLClassAssertionAxiom(objectType, object)));
L.add(new AddAxiom(ctx.getBusinessObjectOntology().getOntology(),
df.getOWLObjectPropertyAssertionAxiom(prop, ind, object)));
manager.applyChanges(L);
// for (OWLAxiom ax : ctx.getBusinessObjectOntology().getObjectPropertyAssertionAxioms(ctx.getBusinessObject()))
// System.out.println("ax : " + ax);
return object;
}
protected OWLLiteral toOWLLiteral(OWLDataFactory df, OWLDataRange range, Json value)
{
if (range instanceof OWLDatatype)
{
String v = value.asString();
OWLDatatype type = (OWLDatatype)range;
if (type.isBoolean())
{
if (v.equalsIgnoreCase("on") || v.equalsIgnoreCase("yes") ||
v.equalsIgnoreCase("t") ||
v.equalsIgnoreCase("true"))
v = "true";
else
v = "false";
}
return df.getOWLLiteral(v, (OWLDatatype) range);
}
else
return null;
}
protected void deleteDataProperty(final WorkflowExecutionContext ctx,
OWLDataProperty prop,
OWLIndividual ind,
Json value)
{
OWLOntologyManager manager = OWL.manager();
OWLDataFactory df = manager.getOWLDataFactory();
Set<OWLLiteral> all = ind.getDataPropertyValues(prop, ctx.getBusinessObjectOntology().getOntology());
for (OWLLiteral x : all)
{
OWLAxiom axiom = df.getOWLDataPropertyAssertionAxiom(prop, ind, x);
manager.applyChange(new RemoveAxiom(ctx.getBusinessObjectOntology().getOntology(), axiom));
}
}
protected OWLLiteral assignDataProperty(final WorkflowExecutionContext ctx,
OWLDataProperty prop,
OWLIndividual ind,
Json value)
{
OWLOntologyManager manager = OWL.manager();
OWLDataFactory df = manager.getOWLDataFactory();
OWLOntology mainOntology = ontology();
OWLLiteral literal = null;
for (OWLDataRange range : prop.getRanges(mainOntology))
{
literal = toOWLLiteral(df, range, value);
if (literal != null)
break;
}
if (literal == null)
literal = df.getOWLLiteral(value.toString());
OWLAxiom axiom = df.getOWLDataPropertyAssertionAxiom(prop, ind, literal);
manager.applyChange(new AddAxiom(ctx.getBusinessObjectOntology().getOntology(),
axiom));
return literal;
}
protected OWLIndividual makeObjectIndividual(final WorkflowExecutionContext ctx,
IRI indIri,
Json properties)
{
OWLOntologyManager manager = OWL.manager();
OWLDataFactory df = manager.getOWLDataFactory();
OWLOntology mainOntology = ontology();
OWLIndividual result = indIri == null ? df.getOWLAnonymousIndividual()
: df.getOWLNamedIndividual(indIri);
for (Map.Entry<String, Json> e : properties.asJsonMap().entrySet())
{
IRI propIri = fullIri(e.getKey());
try
{
if (mainOntology.getAxioms(df.getOWLDataProperty(propIri)).isEmpty())
assignObjectProperty(ctx, df.getOWLObjectProperty(propIri),
result, e.getValue());
else
assignDataProperty(ctx, df.getOWLDataProperty(propIri),
result, e.getValue());
}
catch (RuntimeException ex)
{
System.out.println("Failed to assign property " + propIri);
ex.printStackTrace(System.err);
}
}
return result;
}
protected OWLObject assignProperty(final WorkflowExecutionContext ctx,
OWLIndividual ind,
IRI propIri,
Json value)
{
OWLDataFactory df = OWL.dataFactory();
OWLOntology mainOntology = ontology();
try
{
if (mainOntology.getAxioms(df.getOWLDataProperty(propIri)).isEmpty())
return assignObjectProperty(ctx, df.getOWLObjectProperty(propIri), ind, value);
else
{
return assignDataProperty(ctx,
df.getOWLDataProperty(propIri),
ind,
value.at(propIri.getFragment()));
}
}
catch (RuntimeException ex)
{
System.out.println("Failed to assign property " + propIri);
throw ex;
}
}
protected void deleteProperty(final WorkflowExecutionContext ctx,
OWLIndividual ind,
IRI propIri,
Json value)
{
OWLDataFactory df = OWL.dataFactory();
OWLOntology mainOntology = ontology();
try
{
if (mainOntology.getAxioms(df.getOWLDataProperty(propIri)).isEmpty())
deleteObjectProperty(ctx, df.getOWLObjectProperty(propIri), ind, value);
else
{
deleteDataProperty(ctx,
df.getOWLDataProperty(propIri),
ind,
value != null ? value.at(propIri.getFragment()) : null);
}
}
catch (RuntimeException ex)
{
System.out.println("Failed to assign property " + propIri);
throw ex;
}
}
protected OWLIndividual getIndividual(WorkflowExecutionContext ctx, SWRLIArgument indarg)
{
if (indarg instanceof SWRLIndividualArgument)
return ((SWRLIndividualArgument)indarg).getIndividual();
else
{
SWRLVariable var = (SWRLVariable)indarg;
return (OWLIndividual)getVarResolver(ctx).resolve(var);
}
}
protected OWLLiteral getLiteral(WorkflowExecutionContext ctx, SWRLDArgument darg)
{
if (darg instanceof SWRLLiteralArgument)
return ((SWRLLiteralArgument)darg).getLiteral();
else
{
SWRLVariable var = (SWRLVariable)darg;
return (OWLLiteral)getVarResolver(ctx).resolve(var);
}
}
public HGPersistentHandle getPrototypeId()
{
return prototypeId;
}
public void setPrototypeId(HGPersistentHandle prototypeId)
{
this.prototypeId = prototypeId;
}
public HGHandle getAtomHandle()
{
return handle;
}
public void setAtomHandle(HGHandle handle)
{
this.handle = handle;
}
public void setOutputVariables(Set<IRI> outputVariables)
{
this.outputVariables = outputVariables;
}
public void setInputVariables(Map<IRI, Pair<HGHandle, IRI>> inputVariables)
{
this.inputVariables = inputVariables;
}
public Set<IRI> getOutputVariables()
{
return outputVariables;
}
public Map<IRI, Pair<HGHandle, IRI>> getInputVariables()
{
return inputVariables;
}
public WorkflowStep getNext()
{
return next;
}
public void setNext(WorkflowStep next)
{
this.next = next;
}
public double getAssignedScore()
{
return assignedScore;
}
public void setAssignedScore(double assignedScore)
{
this.assignedScore = assignedScore;
}
}