/*
* Copyright (C) 2008-2011 CBDP Consortium
*
* All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution.
*
* This software consists of contributions made by many individuals,
* listed below:
*
* Author: Pierre Bretault <pierre.bretault@atego.com>
*/
package cbdp.server.contextreasoner.impl;
import static cbdp.server.contextreasoner.impl.util.DebugUtils.printlnIfInDebugModel;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import cbdp.server.contextreasoner.ContextManagerWithoutExecutionSupport;
import cbdp.server.contextreasoner.exceptions.ContextManagerException;
import cbdp.server.contextreasoner.impl.util.NullChecker;
import cbdp.server.contextreasoner.internal.OntologyContainer;
import com.hp.hpl.jena.ontology.ConversionException;
import com.hp.hpl.jena.ontology.DatatypeProperty;
import com.hp.hpl.jena.ontology.HasValueRestriction;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.Restriction;
import com.hp.hpl.jena.rdf.listeners.StatementListener;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
/**
* @author bretault
*/
public class ActionStatementListener extends StatementListener implements ServiceTrackerCustomizer {
private BundleContext bc;
/**
* @uml.property name="cm"
* @uml.associationEnd
*/
private ContextManagerWithoutExecutionSupport cm;
private OntologyContainer oc;
/* eventAdmin */
private ServiceTracker ea_tracker;
private EventAdmin ea = null;
public ActionStatementListener(BundleContext bc, ContextManagerWithoutExecutionSupport cm, OntologyContainer oc) {
this.bc = bc;
this.cm = cm;
this.oc = oc;
/* find the EventAdmin */
ea_tracker = new ServiceTracker(bc, EventAdmin.class.getName(), this);
ea_tracker.open();
checkRemainingHasCommand();
}
private void checkRemainingHasCommand(){
System.out.println("checkRemainingHasCommand");
this.oc.getOntModel().enterCriticalSection(Lock.WRITE);
try
{
for (final String ns : cm.getOntologyURIs().values()){
final Property p = this.oc.getOntModel().getProperty(ns + "#hasCommand", "");
System.out.println("Property : "+p.toString());
final List<Statement> stmts = this.oc.getOntModel().listStatements(null, null, (String)null, (String)null).toList();
for(final Statement stmt: stmts)
{
if(stmt.getPredicate().getLocalName().equals("hasCommand")){
printlnIfInDebugModel("WARNING statement " + stmt + " p= "+stmt.getObject().toString()+ " should be removed");
this.oc.getOntModel().remove(stmt);
}
}
}
}
catch(Exception e){
e.printStackTrace();
}
finally
{
this.oc.getOntModel().leaveCriticalSection();
}
}
public void finalize(){
ea_tracker.close();
}
@Override
public void addedStatement(Statement s) {
printlnIfInDebugModel("[CM] Ontology Changed : " + s.toString());
if(this.ea != null){
this.oc.getOntModel().enterCriticalSection(Lock.READ);
try{
Property prop = s.getPredicate();
String hasCom = prop.getLocalName();
if(!hasCom.equals("hasCommand"))
return;
// get Functionality Instance
Individual funcInstance = this.oc.getOntModel().getIndividual(s.getSubject().toString());
NullChecker.checkNullResource(funcInstance, funcInstance.toString()+" individual not found");
ObjectProperty isFunc = this.oc.getOntModel().getObjectProperty(funcInstance.getNameSpace()+"isFunctionalityOf");
NullChecker.checkNullResource(isFunc, isFunc.toString()+" ObjectProperty not found");
Individual actuatorInstance = funcInstance.getPropertyValue(isFunc).as(Individual.class);
NullChecker.checkNullResource(actuatorInstance, actuatorInstance.toString()+" individual not found");
// get Ontology Name from URI
String ontologyName = "";
for (Map.Entry<String,String> e : this.cm.getOntologyURIs().entrySet()){
String ns = e.getValue()+"#";
if(ns.equals(actuatorInstance.getNameSpace())){
e.getKey();
ontologyName = e.getKey();
break;
}
}
if(ontologyName.equals("")){
throw (new ContextManagerException("No ontolgy associated with the URI : "+ actuatorInstance.getURI() +" in the ontology - URI mapping file"));
}
// get related Commands instance and data
if(!s.getObject().isResource()){
throw (new ContextManagerException(s.getObject().toString() + " is not a Commands" ));
}
Individual comInstance = this.oc.getOntModel().getIndividual(s.getObject().toString());
NullChecker.checkNullResource(comInstance, s.getObject().toString()+" individual not found");
printlnIfInDebugModel("[AL] the command individual is "+comInstance.getLocalName());
// Create Internal event to send to the S/A Layer
Dictionary<String, Object> eventProperties = new Hashtable<String, Object>();
eventProperties.put("ontology.name", ontologyName);
eventProperties.put("class.hierarchy", actuatorInstance.getOntClass(true).getLocalName());
eventProperties.put("instance.id", actuatorInstance.getLocalName());
// get the value of the realCommandName of the considered Commands Individuals
OntClass comClass = null;
for (ExtendedIterator<OntClass> i = comInstance.listOntClasses(true); i.hasNext(); ) {
OntClass c = (OntClass) i.next();
if(!c.getLocalName().equals("Thing")){
comClass = c;
break;
}
}
HashMap<String, String> tmpProp = new HashMap<String, String>();
final List<Statement> propList = comInstance.listProperties().toList();
int rcnIndex = 1;
for (final Statement p : propList){
try{
printlnIfInDebugModel( "[AL] "+ Integer.toString(rcnIndex) + "- Property :" + p.toString() + " - " + p.getPredicate().as(DatatypeProperty.class).getLocalName() + " -- " + p.getObject().toString());
tmpProp.put(p.getPredicate().as(DatatypeProperty.class).getLocalName(),p.getObject().toString());
eventProperties.put("action.id."+Integer.toString(rcnIndex), p.getPredicate().as(DatatypeProperty.class).getLocalName());
eventProperties.put("action.value."+Integer.toString(rcnIndex), p.getObject().toString());
rcnIndex++;
}
catch(ConversionException e){
printlnIfInDebugModel( "[AL] Property :" + p.getPredicate().toString() + " is not a DatatypeProperty");
}
}
printlnIfInDebugModel("[AL] The Command sub-class is "+comClass.getLocalName());
final List<OntClass> ontClassList = comClass.listSuperClasses( true ).toList();
for (final OntClass c : ontClassList){
if (c.isRestriction()) {
Restriction r = c.asRestriction();
if (r.isHasValueRestriction()) {
HasValueRestriction av = r.asHasValueRestriction();
Boolean overLoaded = false;
try{
if(tmpProp.get(av.getOnProperty().getLocalName()) != null ){
overLoaded = true;
}
}
catch(NullPointerException e){}
if(!overLoaded){
printlnIfInDebugModel( "[AL] "+ Integer.toString(rcnIndex) + "- HasValue :" + av.getHasValue().as(Literal.class).getValue().toString() + " on property " + av.getOnProperty().getLocalName() );
eventProperties.put("action.id."+Integer.toString(rcnIndex), av.getOnProperty().getLocalName());
eventProperties.put("action.value."+Integer.toString(rcnIndex), av.getHasValue().as(Literal.class).getValue().toString());
rcnIndex++;
}
}
}
}
if(eventProperties.get("action.id.1") == null)
printlnIfInDebugModel("[AL] ERROR : Unable to retrieve at least one DatatypeProperty of "+ comInstance.toString());
// Send event to the S/A Layer
Event e = new Event(
"cbdp/internal/salayer/updatedAction",
eventProperties);
printlnIfInDebugModel("[AL]: Send Internal Event : "+e.toString());
this.ea.sendEvent(e);
}
catch(Exception e){
e.printStackTrace();
return;
}
finally
{
this.oc.getOntModel().leaveCriticalSection();
}
this.oc.getOntModel().enterCriticalSection(Lock.WRITE);
try{
// Remove the statement as its modification doesn't allow to call addedStatement()
// TODO: managing timestamps of such a statement in the ontology in order to avoid this operation
this.oc.getOntModel().remove(s);
}
finally{
this.oc.getOntModel().leaveCriticalSection();
}
}
}
@Override
public Object addingService(ServiceReference ref) {
if (ref != null){
printlnIfInDebugModel("[AL] : Event Admin discovered ");
this.ea = (EventAdmin) this.bc.getService(ref);
}
return null;
}
@Override
public void modifiedService(ServiceReference arg0, Object arg1) {
// TODO Auto-generated method stub
}
@Override
public void removedService(ServiceReference arg0, Object arg1) {
// TODO Auto-generated method stub
}
}
|