/* * Dog - Core * * Copyright (c) 2011-2014 Dario Bonino and Luigi De Russis * * 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 it.polito.elite.dog.core.housemodel.semantic.query; import it.polito.elite.dog.core.library.model.DeviceCostants; import it.polito.elite.dog.core.library.semantic.util.SimplifiedQueryExecutor; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import com.hp.hpl.jena.ontology.DatatypeProperty; import com.hp.hpl.jena.ontology.Individual; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntProperty; import com.hp.hpl.jena.ontology.OntResource; import com.hp.hpl.jena.ontology.UnionClass; import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.NodeIterator; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.util.iterator.ExtendedIterator; /** * @author <a href="mailto:dario.bonino@polito.it">Dario Bonino</a> * @see <a href="http://elite.polito.it">http://elite.polito.it</a> * */ public class SPARQLQueryWrapper { // the inner namespaces collection protected Map<String, String> namespaces; // name spaces declaration protected String namespaceDecl; // the model to query protected OntModel model; /** * The SPARQLQueryWrapper constructor. It creates and instance of * SPARQLQueryWrapper which allows to query the given ontology model by * simply calling wrapper Java methods * * @param namespaces * the different namespaces currently loaded in the ontology * @param model * the ontology model (Jena {@link OntModel}). */ public SPARQLQueryWrapper(Map<String, String> namespaces, OntModel model) { // store the namespaces this.namespaces = namespaces; // store the model this.model = model; // generate the namespaceDecl this.namespaceDecl = this.genNamespaceDecl(); // debug TODO: change this to logger... System.err.println("SPARQL Prefixes: " + this.namespaceDecl); } /** * Given the map of currently loaded namespaces, generate the corresponding * prefixes * * @return the prefix declaration as {@link String} */ protected String genNamespaceDecl() { // The string buffer for holding the namespace declaration StringBuffer bf = new StringBuffer(); // "PREFIX simple_home:<http://elite.polito.it/ontologies/simplehome.owl#>\n"+ for (String namespace : this.namespaces.keySet()) { bf.append("PREFIX " + namespace + ": <" + this.namespaces.get(namespace) + "#>\n"); } // append the standard prefixes bf.append("PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>\n"); bf.append("PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"); bf.append("PREFIX owl:<http://www.w3.org/2002/07/owl#>\n"); bf.append("PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>\n"); bf.append("PREFIX list:<http://jena.hpl.hp.com/ARQ/list#>\n"); return bf.toString(); } /** * Wraps a general SPARQL query which provides back a list of all * controllable device instances...as a {@link Set} of URIs that point to * the corresponding ontology definition * * @return a {@link Set} of URIs that point to the corresponding ontology * definition */ public Set<String> getAllControllableInstances() { // initially empty device set Set<String> controllables = new HashSet<String>(); // build the query body String queryBody = "SELECT DISTINCT ?cntrl WHERE" + "{" + "?cntrl a dogOnt:Controllable" + ". FILTER (?cntrl!=owl:Nothing)" + "}" + "ORDER by ?cntrl"; // send the query ResultSet queryResults = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + queryBody, this.model); // iterate over the result set QuerySolution cSolution; long eTime = System.currentTimeMillis(); boolean first = true; while (queryResults.hasNext()) { // get the current solution cSolution = queryResults.nextSolution(); if (first) { eTime = System.currentTimeMillis(); first = false; } // extract the device name String devName = cSolution.getResource("cntrl").getURI(); // add the device to the set controllables.add(devName); } eTime = System.currentTimeMillis() - eTime; // debug TODO: insert logger here System.err.println("All controllables (" + controllables.size() + ") extracted in: " + eTime + "ms"); // return all controllable devices return controllables; } /** * Wraps a general SPARQL query which provides back a list of all * controllable device classes...as a {@link Set} of class names that point * to the corresponding ontology definition * * @return a {@link Set} of class names that point to the corresponding * ontology definition */ public Set<String> getAllControllableClasses() { // initially empty device set Set<String> controllables = new HashSet<String>(); // build the query body String queryBody = "SELECT DISTINCT ?cntrl WHERE" + "{" + "?cntrl rdfs:subClassOf dogOnt:Controllable" + ". FILTER (?cntrl!=owl:Nothing)" + "}" + "ORDER by ?cntrl"; // send the query ResultSet queryResults = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + queryBody, this.model); // iterate over the result set QuerySolution cSolution; long eTime = System.currentTimeMillis(); boolean first = true; while (queryResults.hasNext()) { // get the current solution cSolution = queryResults.nextSolution(); if (first) { eTime = System.currentTimeMillis(); first = false; } // extract the device name String devName = cSolution.getResource("cntrl").getLocalName(); if (devName != null) { // add the device to the set controllables.add(devName); } } eTime = System.currentTimeMillis() - eTime; // debug TODO: insert logger here System.err.println("All controllables (" + controllables.size() + ") extracted in: " + eTime + "ms\n" + controllables.toString()); // return all controllable devices return controllables; } /** * Wraps a general SPARQL query which provides back a list of all * controllable device instances...as a {@link Set} of URIs that point to * the corresponding ontology definition * * @return a {@link Set} of URIs that point to the corresponding ontology * definition */ public Set<String> getCategoryFilteredControllableInstances(Set<String> categories) { // initially empty device set Set<String> controllables = new HashSet<String>(); // build the query body boolean first = true; String queryBody = "SELECT DISTINCT ?cntrl WHERE" + "{"; for (String category : categories) { if (!first) queryBody += " UNION "; else first = false; if (category.indexOf(':') == -1) category = "dogOnt:" + category; queryBody += "{" + "?cntrl a " + category + "}"; } queryBody += ". FILTER (?cntrl!=owl:Nothing)" + "}" + "ORDER by ?cntrl"; // send the query ResultSet queryResults = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + queryBody, this.model); // iterate over the result set QuerySolution cSolution; long eTime = System.currentTimeMillis(); first = true; while (queryResults.hasNext()) { // get the current solution cSolution = queryResults.nextSolution(); if (first) { eTime = System.currentTimeMillis(); first = false; } // extract the device name String devName = cSolution.getResource("cntrl").getURI(); // add the device to the set controllables.add(devName); } eTime = System.currentTimeMillis() - eTime; // debug TODO: insert logger here System.err.println("All controllables belonging to " + categories + " (" + controllables.size() + ") extracted in: " + eTime + "ms"); // return all controllable devices return controllables; } /** * Wraps the complex ontology navigation process needed to extract the low * level features of the given DogOnt device instances (represented by its * full URI). It provides back a {@link Map} containing the device type (key * {@link DeviceCostants.TYPE}, the device uri (key * {@link DeviceCostants.DEVICEURI}, the device description (key * {@link DeviceCostants.DEVICE_DESCRIPTION} and the device manufacturer * (key {@link DeviceCostants.MANUFACTURER}). Please be aware that device * description and manufacturer might be empty, i.e., null. * * @param deviceURI * the device URI as a {@link String} * @return the {@link Map}<{@link String},{@link String}> containing the * device features */ public Map<String, String> getControllableInstanceBasicData(String deviceURI) { // create the map to fill with basic device data Map<String, String> devData = new HashMap<String, String>(); // store the device id devData.put(DeviceCostants.DEVICEURI, deviceURI.substring(deviceURI.indexOf('#') + 1)); // all direct classes Individual devInd = this.model.getIndividual(deviceURI); Set<OntClass> devClasses = devInd.listOntClasses(true).toSet(); // iterate over the classes String clsURI; Set<String> possibleClasses = new HashSet<String>(); for (OntClass devCls : devClasses) { // check the current direct class clsURI = devCls.getURI(); // filter null and component if ((clsURI != null) && (!clsURI.endsWith("Component")) && (!clsURI.endsWith("Gateway"))) { possibleClasses.add(clsURI); } else if (clsURI != null) { int cIndex = -1; if (clsURI.endsWith("Component")) cIndex = clsURI.indexOf("Component"); else if (clsURI.endsWith("Gateway")) { cIndex = clsURI.indexOf("Gateway"); // dirt... in the gateway case it must be also inserted in // the possibleClasses since // a gateway has only one direct type which both identifies // the network and the // device type possibleClasses.add(clsURI); } // split the name int sharpIndex = clsURI.indexOf('#'); clsURI = clsURI.substring(sharpIndex + 1, cIndex); // store the name devData.put(DeviceCostants.MANUFACTURER, clsURI.toUpperCase()); } } // if no manufacturer has been inserted...then no manufacturer is // specified if (!devData.containsKey(DeviceCostants.MANUFACTURER)) devData.put(DeviceCostants.MANUFACTURER, null); // if the possible classes set has only one entry (most cases) // directly add the entry as device type, otherwise search the most // specific // class and add it if (possibleClasses.size() == 1) { // get the device name purging the common namespace URI String devType = possibleClasses.iterator().next(); devType = devType.substring(devType.indexOf('#') + 1); // directly add the device name devData.put(DeviceCostants.TYPE, devType); } else if (possibleClasses.size() > 1) { // get the most specific class... String devType = this.getMostSpecificType(possibleClasses); // purge the common namespace URI devType = devType.substring(devType.indexOf('#') + 1); // directly add the device name devData.put(DeviceCostants.TYPE, devType); } // add the device description if available String comment = devInd.getComment(null); // if not null add the comment, else....maybe in the future // we can define a comment based on the relative location // if(comment!=null) // { devData.put(DeviceCostants.DEVICE_DESCRIPTION, comment); // } // return the device data map return devData; } /** * Wraps a query for getting all the Locations (typically Rooms) in Which * the given entity is located. Although this method supports multiple * locations for the same device, this can never happen with the current * DogOnt as it will make the ontology inconsistent. * * @param entityURI * The URI of the object to locate * @return A {@link String} representing the location */ public String getEntityLocationInRoom(String entityURI) { // get the location if possible String location = ""; // the query String qBody = "SELECT DISTINCT ?loc WHERE {<" + entityURI + "> dogOnt:isIn ?loc}"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results QuerySolution sol; while (res.hasNext()) { // get the current location sol = res.next(); if (sol != null) // if the location is not null....store it location = sol.getResource("loc").getLocalName(); } // return found locations return location; } /** * Wraps a query for getting all the network parameters associated to a * given device instance, it does not retrieve those parameters associated * to the device commands. Parameters are retrieved opaquely, i.e., they are * extracted by listing all the data type properties associated to the * network nature of the device (i.e., the properties having a * NetworkComponent subclass as domain). * * @param deviceURI * the device URI as {@link String} * @return A {@link Map}<{@link String},{@link String}> containing couples * of parameter name and value. */ public Map<String, Set<String>> getInstanceProperties(String deviceURI, Set<String> properties) { // the map for holding the entity parameters (data type properties // captured without prior knowledge Map<String, Set<String>> params = new HashMap<String, Set<String>>(); // get the device Individual devInd = this.model.getIndividual(deviceURI); // iterate over the properties for (String prop : properties) { // get the model representation of the property OntProperty cProp = this.model.getOntProperty(this.namespaces.get("dogOnt") + "#" + prop); if (cProp != null) { // get the devcie property if available RDFNode resValue = devInd.getPropertyValue(cProp); if ((resValue != null) && (resValue.isLiteral())) { // if there is already a value...add a new one, else just // add the new set Set<String> propValues = params.get(prop); if (propValues != null) propValues.add(((Literal) resValue).getString()); // if it is a literal and it is available, store the // property params.put(prop, (Collections.singleton(((Literal) resValue).getString()))); } } } return params; } public Set<String> getDatatypePropertiesOf(String cls) { // the set for holding the network component datatype properties Set<String> props = new HashSet<String>(); // prepare the query (TODO: check if the distinct clause is right, wrong // or not influent) String qBody = "SELECT DISTINCT ?p WHERE{" + "{?c rdfs:subClassOf " + cls + " . ?p rdfs:domain ?c }" + " UNION {?c rdfs:subClassOf " + cls + " . " + "?p rdfs:domain [owl:unionOf [list:member ?c]]}" + " UNION {" + cls + " rdfs:subClassOf ?c . ?p rdfs:domain ?c }" + " UNION {" + cls + " rdfs:subClassOf ?c . ?p rdfs:domain [owl:unionOf [list:member ?c]]}" + " UNION {" + " ?p rdfs:domain " + cls + "} UNION { ?p rdfs:domain [owl:unionOf [list:member " + cls + "]]}" + // "?p rdfs:subPropertyOf owl:DatatypeProperty" + ". FILTER(?p!=owl:bottomDataProperty)} ORDER BY ?p"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results QuerySolution cSol; while (res.hasNext()) { // the current query solution cSol = res.next(); // if not null work on it if (cSol != null) { Resource pRes = cSol.getResource("p"); OntProperty pProp = this.model.getOntProperty(pRes.getURI()); if ((pProp != null) && (pProp.isDatatypeProperty())) { // get the parameter name String pName = pRes.getLocalName(); props.add(pName); } } } return props; } /** * Shall check the domain of the given property, gives a warning from pellet * and it is really slow however it will be left here for future uses * ...need to be checked / verified * * @param propURI * @param classURI * @return */ @SuppressWarnings("unchecked") protected boolean checkDomain(String propURI, String classURI) { boolean found = false; OntClass networkCls = this.model.getOntClass(classURI); DatatypeProperty pProp = this.model.getDatatypeProperty(propURI); if (pProp != null) { Set<OntResource> domainClasses = (Set<OntResource>) pProp.listDomain().toSet(); // dump System.err.println(domainClasses); for (OntResource propRes : domainClasses) { // tODO deal with intersections and unions (the operands....i.e. // the classes taking part in the // boolean combination if (((OntClass) propRes).isUnionClass()) { UnionClass union = ((OntClass) propRes).asUnionClass(); // get the binary operation operands Set<OntClass> bClasses = (Set<OntClass>) union.listOperands().toSet(); // check if one of the operands is subclass of a network // class for (OntClass bClass : bClasses) { if (bClass.hasSuperClass(networkCls)) { found = true; break; } } if (found) break; } else if (((OntClass) propRes).hasSuperClass(networkCls)) { found = true; break; } } } return found; } /** * Wraps a query for getting all the specific commands, grouped by * controlFunctionality associate to the given device instance * * @param deviceURI * the device URI as {@link String} * @return A {@link Map}<{@link String}{@link Set}<{@link String}>> keys-> * functionalities , values commands */ public Map<String, Set<String>> getDeviceInstanceSpecificFunctionalitiesCommands(String deviceURI) { // the returned map Map<String, Set<String>> functionalitiesCommands = new HashMap<String, Set<String>>(); // the query String qBody = "SELECT ?c ?f WHERE {" + "<" + deviceURI + "> dogOnt:hasFunctionality ?f ." + "?f dogOnt:hasCommand ?c }"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results to fill the set QuerySolution cSol; // the set containing commands uri Set<String> commands = null; while (res.hasNext()) { // the current query solution cSol = res.next(); // if not null work on it if (cSol != null) { String functionality = cSol.getResource("f").getURI(); // get the command set if exist the key functinality commands = functionalitiesCommands.get(functionality); if (commands == null) { // the functionality does not exist commands = new HashSet<String>(); functionalitiesCommands.put(functionality, commands); } // get the command name and add it the list commands.add(cSol.getResource("c").getURI()); } } return functionalitiesCommands; } /** * Wraps a query for getting all the network specific commands associate to * the given device instance * * @param deviceURI * the device URI as {@link String} * @return A {@link Set}<{@link String}> of command URIs */ public Set<String> getDeviceInstanceNetworkSpecificCommands(String deviceURI) { // the set that will contain the URIs of the device commands Set<String> commands = new HashSet<String>(); // the query String qBody = "SELECT ?c WHERE {" + "<" + deviceURI + "> dogOnt:hasFunctionality ?f ." + "?f dogOnt:hasCommand ?c ." + "?c a ?cType . ?cType rdfs:subClassOf dogOnt:NetworkSpecificCommand }"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results to fill the set QuerySolution cSol; while (res.hasNext()) { // the current query solution cSol = res.next(); // if not null work on it if (cSol != null) { // get the command name commands.add(cSol.getResource("c").getURI()); } } return commands; } /** * Wraps a query for getting the device associated to the given command * instance * * @param commandURI * the command URI as {@link String} * @return A {@link String} representing the URI of the device instance * having this command */ public String getCommandOf(String cmdURI) { // the set that will contain the URIs of the device commands Set<String> device = new HashSet<String>(); // the query String qBody = "SELECT ?d WHERE {?d dogOnt:hasFunctionality ?f ." + "?f dogOnt:hasCommand <" + cmdURI + "> }"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results to fill the set QuerySolution cSol; while (res.hasNext()) { // the current query solution cSol = res.next(); // if not null work on it if (cSol != null) { // get the command name device.add(cSol.getResource("d").getLocalName()); } } // only one result is allowed if (device.size() > 0) return device.iterator().next(); else return null; } /** * Wraps a query for getting all the network specific commands associate to * the given device instance * * @param deviceURI * the device URI as {@link String} * @return A {@link Set}<{@link String}> of command URIs */ public Set<String> getDeviceInstanceNetworkSpecificNotifications(String deviceURI) { // the set that will contain the URIs of the device commands Set<String> notifications = new HashSet<String>(); // the query String qBody = "SELECT ?n WHERE {" + "<" + deviceURI + "> dogOnt:hasFunctionality ?f ." + "?f dogOnt:hasNotification ?n ." + "?n a ?nType . ?nType rdfs:subClassOf dogOnt:NetworkSpecificNotification }"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results to fill the set QuerySolution cSol; while (res.hasNext()) { // the current query solution cSol = res.next(); // if not null work on it if (cSol != null) { // get the command name notifications.add(cSol.getResource("n").getURI()); } } return notifications; } /** * Wraps a query for getting all the specific notifications, grouped by * notificationFunctionality associate to the given device instance * * @param deviceURI * the device URI as {@link String} * @return A {@link Map}<{@link String}{@link Set}<{@link String}>> keys-> * functionalities , values notifications */ public Map<String, Set<String>> getDeviceInstanceSpecificFunctionalitiesNotifications(String deviceURI) { // the returned map Map<String, Set<String>> functionalitiesNotifications = new HashMap<String, Set<String>>(); // the query String qBody = "SELECT ?n ?f WHERE {" + "<" + deviceURI + "> dogOnt:hasFunctionality ?f ." + "?f dogOnt:hasNotification ?n .}"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results to fill the set QuerySolution cSol; // the set containing commands uri Set<String> notifications = null; while (res.hasNext()) { // the current query solution cSol = res.next(); // if not null work on it if (cSol != null) { String functionality = cSol.getResource("f").getURI(); // get the command set if exist the key functionality notifications = functionalitiesNotifications.get(functionality); if (notifications == null) { // the functionality does not exist notifications = new HashSet<String>(); functionalitiesNotifications.put(functionality, notifications); } // get the command name and add it the list notifications.add(cSol.getResource("n").getURI()); } } return functionalitiesNotifications; } /* * Given a set of ontology classes provides back the most specific one. (or * the first type for which no descendants are found and having the maximum * sized set of superclasses (WARNING: this might sometimes lead to wrong * results! therefore this method has to be considered as "risky"and its use * is deprecated) * * @param deviceClasses - The "candidate" classes. * * @return - The most specific class. */ @Deprecated private String getMostSpecificType(Set<String> deviceClasses) { // the minimum number of subclasses found until now int subClassNumber = Integer.MAX_VALUE; int superClassNumber = Integer.MIN_VALUE; // the found type String mostSpecificType = null; // iterate over device classes for (String currentCls : deviceClasses) { // get the class resources OntClass currentDeviceType = this.model.getOntClass(currentCls); ExtendedIterator<OntClass> it = currentDeviceType.listSubClasses(); ExtendedIterator<OntClass> itS = currentDeviceType.listSuperClasses(); if (it != null) { // get the direct subclass of the current device Set<OntClass> subclasses = it.toSet(); Set<OntClass> superclasses = itS.toSet(); if ((subclasses.size() < subClassNumber) || ((subclasses.size() == subClassNumber) && (superclasses.size() > superClassNumber))) { subClassNumber = subclasses.size(); superClassNumber = superclasses.size(); mostSpecificType = currentDeviceType.getLocalName(); } } else { mostSpecificType = currentDeviceType.getLocalName(); subClassNumber = 0; } } return mostSpecificType; } /** * Given a set of ontology classes provides back the most specific one. (or * the first type for which no descendants are found and having the maximum * sized set of superclasses (WARNING: this might sometimes lead to wrong * results! therefore this method has to be considered as "risky"and its use * is deprecated) * * @param deviceClasses * - The "candidate" classes. * * @return - The most specific class. */ @Deprecated private String getMostSpecificTypeO(Set<OntClass> deviceClasses, OntClass filter) { // the minimum number of subclasses found until now int subClassNumber = Integer.MAX_VALUE; int superClassNumber = Integer.MIN_VALUE; // the found type String mostSpecificType = null; // iterate over device classes for (OntClass currentCls : deviceClasses) { if(!currentCls.isAnon() && !currentCls.getURI().equals("http://www.w3.org/2002/07/owl#NamedIndividual")){ // get the class resources if ((filter == null) || ((filter != null) && (!currentCls.hasSuperClass(filter)))) { ExtendedIterator<OntClass> it = currentCls.listSubClasses(); ExtendedIterator<OntClass> itS = currentCls.listSuperClasses(); if (it != null) { // get the direct subclass of the current device Set<OntClass> subclasses = it.toSet(); Set<OntClass> superclasses = itS.toSet(); if ((subclasses.size() < subClassNumber) || ((subclasses.size() == subClassNumber) && (superclasses.size() > superClassNumber))) { subClassNumber = subclasses.size(); superClassNumber = superclasses.size(); mostSpecificType = currentCls.getLocalName(); } } else { mostSpecificType = currentCls.getLocalName(); subClassNumber = 0; } } } } return mostSpecificType; } /** * Gets the "most specific" type of a device given its uri, and optionally * accepts a filter class specifying that the found type must not be a * descendant of the given filter class. * * This class is currently a dirt way of identifying the specific type of a * device and might be subject to changes in the upcoming revisions of the * SemanticHouseModel * * @param devURI * The URI of the device for which the most specific class shall * be retrieved * @param filterURI * The class defining the hierarchy branch that shall be avoided * in finding the most specific type (might not be sufficient, * and in future implementations this might become a set of * classes to avoid) * * @return the name of the most specific type (Ontology Class) associated to * the given device */ public String getType(String devURI, String filterURI) { // all direct classes Individual devInd = this.model.getIndividual(devURI); Set<OntClass> devClasses = devInd.listOntClasses(true).toSet(); // the filter (not subclass of) OntClass devFilter = null; if (filterURI != null) devFilter = this.model.getOntClass(filterURI); String type = this.getMostSpecificTypeO(devClasses, devFilter); return type; } public String checkAndRepairDogOntNameSpace(String name) { if (name.indexOf(':') == -1) { name += this.namespaces.get("dogOnt") + "#" + name; } return name; } /** * Given a device class name, provides back a {@link Set} of functionalities * associated to the device class * * @param devClass * @return A {@link Set} containing all the functionalities associated to a * given device class. */ public Set<String> getDevFunctionalities(String devClass) { Set<String> functionalities = new HashSet<String>(); String allDevFunctionality = "SELECT ?device WHERE {dogOnt:" + devClass + " rdfs:subClassOf ?device ." + "?device rdfs:subClassOf dogOnt:Controllable}"; // exec the query ResultSet resSet = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + allDevFunctionality, this.model); // the class itself this.addFunctionalities(functionalities, devClass); // cycle over results, i.e. over all the class ancestors while (resSet.hasNext()) { String deviceClass = resSet.next().getResource("device").getLocalName(); if (deviceClass != null) { // System.err.println("Class: " + deviceClass); this.addFunctionalities(functionalities, deviceClass); } } return functionalities; } private void addFunctionalities(Set<String> functionalities, String deviceClass) { // prepare the query String qBody = "SELECT ?f WHERE {" + "dogOnt:" + deviceClass + " rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:hasFunctionality;" + "owl:someValuesFrom ?f] " + "}"; // execute the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the result set QuerySolution cSol; while (res.hasNext()) { // the current query solution... cSol = res.next(); // store the names Resource functionalityR = cSol.getResource("f"); // if not null store the local name in the functionality set if (functionalityR != null) { functionalities.add(functionalityR.getLocalName()); } } } /** * Given a device class name, provides back a {@link Set} of states * associated to the device class * * @param devClass * @return A {@link Set} containing all the states associated to a given * device class. */ public Set<String> getDevStates(String devClassName) { Set<String> states = new HashSet<String>(); Set<String> allSuperClasses = this.getAllSuperClasses(this.namespaces.get("dogOnt") + "#" + devClassName); for (String devClass : allSuperClasses) { devClass = this.toShortForm(devClass); // prepare the query String qBody = "SELECT ?s WHERE {" + "dogOnt:" + devClass + " rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:hasState;" + "owl:someValuesFrom ?s]}"; // execute the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the result set QuerySolution cSol; while (res.hasNext()) { // the current query solution... cSol = res.next(); // store the names Resource stateR = cSol.getResource("s"); // if not null store the local name in the functionality set if (stateR != null) { states.add(stateR.getLocalName()); } } } return states; } /** * Provides back all the ontology-declared functionalities and the relative * commands (only the names...), it is only aimed at supporting the horrible * way of providing such information to external apps defined in the * DOG2.0.8 version. * * @return A {@link Map}<{@link String},<{@link Set}<{@link String}>> * containing the found functionalities as keys and the relative * commands as a set of {@link String}s */ @Deprecated public Map<String, Set<String>> getFunctionalitiesAndCommands() { // create the map for storing the command associated to each // functionality Map<String, Set<String>> functionalities = new HashMap<String, Set<String>>(); // do not know if it works... // first get the functionalities String qBody1 = "SELECT ?functionality WHERE {" + "?functionality rdfs:subClassOf dogOnt:Functionality}"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody1, this.model); // iterate over functionalities and extract the commands (implementing // restriction inheritance) QuerySolution cSol1; while (res.hasNext()) { cSol1 = res.next(); String functionality = cSol1.getResource("functionality").getLocalName(); String functionalityURI = cSol1.getResource("functionality").getURI(); Set<String> allSuperFunctionalities = this.getAllSuperClasses(functionalityURI); for (String cFunctionality : allSuperFunctionalities) { cFunctionality = this.toShortForm(cFunctionality); // the query String qBody = "SELECT ?commandValue ?cmdParamValue WHERE {" + "dogOnt:" + cFunctionality + " rdfs:subClassOf dogOnt:Functionality ." + "dogOnt:" + cFunctionality + " rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:hasCommand;" + "owl:someValuesFrom ?command] ." + "?command rdfs:subClassOf dogOnt:Command ." + "?command rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:realCommandName;" + "owl:hasValue ?commandValue] . OPTIONAL" + "{?command rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:commandParamName;" + "owl:hasValue ?cmdParamValue]}}"; // exec the query ResultSet res2 = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results QuerySolution cSol; while (res2.hasNext()) { cSol = res2.next(); // String functionality = // cSol.getResource("functionality").getLocalName(); String command = cSol.getLiteral("commandValue").getString(); Literal paramValueR = cSol.getLiteral("cmdParamValue"); // deal with the param... if (paramValueR != null) { // split... String typeAndName[] = paramValueR.getString().split("\\^\\^"); // store... command += "(" + typeAndName[1] + "[])"; } // if not null add them if (((functionality != null) && (!functionality.isEmpty())) && ((command != null) && (!command.isEmpty()))) { // check if the functionality is already there Set<String> cmds = functionalities.get(functionality); if (cmds == null) { // create the command set cmds = new HashSet<String>(); cmds.add(command); functionalities.put(functionality, cmds); } else { // just add the command cmds.add(command); } } } } } return functionalities; } /** * Provides back all the ontology-declared notification functionalities and * the relative notifications (only the names...), it is only aimed at * supporting the horrible way of providing such information to external * apps defined in the DOG2.0.8 version. * * @return A {@link Map}<{@link String},<{@link Set}<{@link String}>> * containing the found functionalities as keys and the relative * notifications as a set of {@link String}s */ @Deprecated public Map<String, Set<String>> getFunctionalitiesAndNotifications() { // create the map for storing the command associated to each // functionality Map<String, Set<String>> allNotifications = new HashMap<String, Set<String>>(); // do not know if it works... // first get the functionalities String qBody1 = "SELECT ?functionality WHERE {" + "?functionality rdfs:subClassOf dogOnt:Functionality}"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody1, this.model); // iterate over functionalities and extract the commands (implementing // restriction inheritance) QuerySolution cSol1; while (res.hasNext()) { cSol1 = res.next(); String functionality = cSol1.getResource("functionality").getLocalName(); String functionalityURI = cSol1.getResource("functionality").getURI(); Set<String> allSuperFunctionalities = this.getAllSuperClasses(functionalityURI); for (String cFunctionality : allSuperFunctionalities) { cFunctionality = this.toShortForm(cFunctionality); // the query String qBody = "SELECT ?notifValue ?notifParamValue WHERE {" + "dogOnt:" + cFunctionality + " rdfs:subClassOf dogOnt:NotificationFunctionality ." + "dogOnt:" + cFunctionality + " rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:hasNotification;" + "owl:someValuesFrom ?notification] ." + "?notification rdfs:subClassOf dogOnt:Notification ." + "?notification rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:notificationName;" + "owl:hasValue ?notifValue] . OPTIONAL" + "{?notification rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:notificationParamName;" + "owl:hasValue ?notifParamValue]}}"; // exec the query ResultSet res2 = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results QuerySolution cSol; while (res2.hasNext()) { cSol = res2.next(); // String functionality = // cSol.getResource("functionality").getLocalName(); String notif = cSol.getLiteral("notifValue").getString(); Literal paramValueR = cSol.getLiteral("?notifParamValue"); // deal with the param... if (paramValueR != null) { // split... String typeAndName[] = paramValueR.getString().split("\\^\\^"); // store... notif += "(" + typeAndName[1] + "[])"; } // if not null add them if (((functionality != null) && (!functionality.isEmpty())) && ((notif != null) && (!notif.isEmpty()))) { // check if the functionality is already there Set<String> notifications = allNotifications.get(functionality); if (notifications == null) { // create the command set notifications = new HashSet<String>(); notifications.add(notif); allNotifications.put(functionality, notifications); } else { // just add the command notifications.add(notif); // allNotifications.put(functionality, // notifications); } } } } } return allNotifications; } /** * Provides back all the ontology-declared states and the relative values * (only the names...), it is only aimed at supporting the horrible way of * providing such information to external apps defined in the DOG2.0.8 * version. * * @return A {@link Map}<{@link String},<{@link Set}<{@link String}>> * containing the found states as keys and the relative values as a * set of {@link String}s */ @Deprecated public Map<String, Set<String>> getStatesAndStateValues() { // create the map for storing the command associated to each // functionality Map<String, Set<String>> states = new HashMap<String, Set<String>>(); // the query String qBody = "SELECT ?state ?value WHERE {" + "?state rdfs:subClassOf dogOnt:State ." + "?state rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:hasStateValue;" + "owl:someValuesFrom ?stateValue] ." + "?stateValue rdfs:subClassOf dogOnt:StateValue ." + "OPTIONAL {?stateValue rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:realStateValue;" + "owl:hasValue ?value]}} "; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results QuerySolution cSol; while (res.hasNext()) { cSol = res.next(); String state = cSol.getResource("state").getLocalName(); Literal valueR = cSol.getLiteral("value"); // if not null add them if ((state != null) && (!state.isEmpty())) { // check if the functionality is already there Set<String> values = states.get(state); if (values == null) { // create the value set, will be null for continuous // states... (though it's an // horrible trick) if (valueR != null) { values = new HashSet<String>(); values.add(valueR.getString()); } states.put(state, values); } else { if (valueR != null) // just add the command values.add(valueR.getString()); } } } return states; } public Set<String> getFunctionalityCommands(String functionalityURI) { // the set containing the names of the commands associated to the given // functionality HashSet<String> commands = new HashSet<String>(); // trick for avoiding pellet loops Set<String> allFunctionalitiesURI = this.getAllSuperClasses(functionalityURI); for (String cFunctionalityURI : allFunctionalitiesURI) { // the query for extracting the functionality commands String cmdQueryBody = "SELECT DISTINCT ?command WHERE {" + "<" + cFunctionalityURI + "> rdfs:subClassOf dogOnt:Functionality ." + "<" + cFunctionalityURI + "> rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:hasCommand;" + "owl:someValuesFrom ?command] ." + "?command rdfs:subClassOf dogOnt:Command}"; // execute the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + cmdQueryBody, this.model); // iterate over results QuerySolution cSol; while (res.hasNext()) { // extract the current solution cSol = res.next(); // get the command name String cmdName = cSol.getResource("command").getURI(); // if the command is not null, add it to the command set if ((cmdName != null) && (!cmdName.isEmpty())) { commands.add(cmdName); } } } return commands; } public Set<String> getAllSuperClasses(String classURI) { HashSet<String> allSuperClassURIs = new HashSet<String>(); allSuperClassURIs.add(classURI); OntClass cls = this.model.getOntClass(classURI); ExtendedIterator<OntClass> it = cls.listSuperClasses(); if (it != null) { Set<OntClass> allSuperClasses = it.toSet(); for (OntClass superClass : allSuperClasses) { String superURI = superClass.getURI(); if ((superURI != null) && (!superURI.isEmpty())) allSuperClassURIs.add(superURI); } } return allSuperClassURIs; } public Set<String> getFunctionalityNotifications(String functionalityURI) { // the set containing the names of the commands associated to the given // functionality HashSet<String> notifications = new HashSet<String>(); // trick for avoiding pellet loops Set<String> allFunctionalitiesURI = this.getAllSuperClasses(functionalityURI); for (String cFunctionalityURI : allFunctionalitiesURI) { // the query for extracting the functionality commands String notificationQueryBody = "SELECT ?notification WHERE {" + "<" + cFunctionalityURI + "> rdfs:subClassOf dogOnt:Functionality ." + "<" + cFunctionalityURI + "> rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:hasNotification;" + "owl:someValuesFrom ?notification] ." + "?notification rdfs:subClassOf dogOnt:Notification}"; // execute the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + notificationQueryBody, this.model); // iterate over results QuerySolution cSol; while (res.hasNext()) { // extract the current solution cSol = res.next(); // get the command name String notificationName = cSol.getResource("notification").getURI(); // if the command is not null, add it to the command set if ((notificationName != null) && (!notificationName.isEmpty())) { notifications.add(notificationName); } } } return notifications; } public Set<String> getStateValues(String stateURI) { // the set containing the names of the state values associated to the // given // functionality HashSet<String> stateValues = new HashSet<String>(); // the query for extracting the functionality commands String stateValueQueryBody = "SELECT ?stateValue WHERE {" + "<" + stateURI + "> rdfs:subClassOf dogOnt:State ." + "<" + stateURI + "> rdfs:subClassOf [rdf:type owl:Restriction;" + "owl:onProperty dogOnt:hasStateValue;" + "owl:someValuesFrom ?stateValue] ." + "?stateValue rdfs:subClassOf dogOnt:StateValue}"; // execute the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + stateValueQueryBody, this.model); // iterate over results QuerySolution cSol; while (res.hasNext()) { // extract the current solution cSol = res.next(); // get the command name String stateValueName = cSol.getResource("stateValue").getURI(); // if the command is not null, add it to the command set if ((stateValueName != null) && (!stateValueName.isEmpty())) { stateValues.add(stateValueName); } } return stateValues; } /** * Retrieve the uri of the instances contained in the container passed as * parameter * * @param container * uri of the instance * @return Set of uris of instances */ public Set<String> getContainedInstanceUri(String container) { HashSet<String> contents = new HashSet<String>(); String contetQuery = "SELECT ?content WHERE { " + " <" + container + "> dogOnt:contains ?content" + "}"; ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + contetQuery, this.model); // iterate over results QuerySolution cSol; while (res.hasNext()) { // extract the current solution cSol = res.next(); // get the command name String contentUri = cSol.getResource("content").getURI(); // if the command is not null, add it to the command set if ((contentUri != null) && (!contentUri.isEmpty())) { contents.add(contentUri); } } return contents; } public String getTopMostRoomContainerInstance() { // the top most instance String topMostInstance = null; // the building environment query String containerQuery = "SELECT DISTINCT ?container WHERE {{" + "?container a dogOnt:BuildingEnvironment." + "?container dogOnt:contains ?room." + "?room a dogOnt:Room}" + "UNION" + "{?container a dogOnt:BuildingEnvironment." + "?container dogOnt:contains ?container2." + "?container2 dogOnt:contains ?room." + "?room a dogOnt:Room}" + " FILTER (?container!=owl:Nothing)} ORDER BY ?container"; // execute the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + containerQuery, this.model); // iterate over the results QuerySolution cSol; Individual container = null; boolean found = false; while ((res.hasNext()) && (!found)) { // extract the current solution cSol = res.next(); // get the command name container = this.model.getIndividual(cSol.getResource("container").getURI()); RDFNode p = container.getPropertyValue(this.model.getProperty(this.namespaces.get("dogOnt") + "#isIn")); // if p is null then the topmost container is found if (p == null) found = true; } // if found is true, than container store sthe toMostInstance containing // rooms if (found) topMostInstance = container.getURI(); return topMostInstance; } public Set<String> getAllComponentClasses() { // the set holding the component class names HashSet<String> componentClasses = new HashSet<String>(); // the root class for components OntClass superComponent = this.model.getOntClass(this.namespaces.get("dogOnt") + "#DomoticNetworkComponent"); // list the direct subclasses ExtendedIterator<OntClass> componentOntClasses = superComponent.listSubClasses(true); // iterate over the component classes OntClass currentClass; while (componentOntClasses.hasNext()) { // the current component OntClass currentClass = componentOntClasses.next(); // store the component name componentClasses.add(currentClass.getLocalName()); } return componentClasses; } /****************************************************************************************************************** * * Environment-related queries... * *****************************************************************************************************************/ /** * Returns all the direct Building instances define in the model * * @return a @link{Set}<@link{String}> containing the labels of all Building * instances */ public Set<String> getAllBuildingInstances(boolean direct) { return this.getAllInstancesOfType("Building", direct); } /** * Returns all the direct Garden Instances * * @return a @link{Set}<@link{String}> containing the labels of all Garden * instances */ public Set<String> getAllGardenInstances(boolean direct) { return this.getAllInstancesOfType("Garden", direct); } /** * Returns all the direct Garage instances * * @return a @link{Set}<@link{String}> containing the labels of all Garage * instances */ public Set<String> getAllGarageInstances(boolean direct) { return this.getAllInstancesOfType("Garage", direct); } /** * Returns all the direct Flat instances * * @return a @link{Set}<@link{String}> containing the labels of all Flat * instances */ public Set<String> getAllFlatInstances(boolean direct) { return this.getAllInstancesOfType("Flat", direct); } /** * Returns all the direct Flat instances * * @return a @link{Set}<@link{String}> containing the labels of all Flat * instances */ public Set<String> getAllStoreyInstances(boolean direct) { return this.getAllInstancesOfType("Storey", direct); } /** * Returns all the direct Room instances * * @return a @link{Set}<@link{String}> containing the labels of all Room * instances */ public Set<String> getAllRoomInstances(boolean direct) { return this.getAllInstancesOfType("Room", direct); } public Set<String> getAllInstancesOfType(String type, boolean direct) { // initially empty device set Set<String> instances = new HashSet<String>(); OntClass instanceClass = this.model.getOntClass(this.namespaces.get("dogOnt") + "#" + type); ExtendedIterator<? extends OntResource> allInstances = instanceClass.listInstances(direct); while (allInstances.hasNext()) { OntResource cInstance = allInstances.next(); if (cInstance instanceof Individual) { instances.add(cInstance.getLocalName()); } } // return all controllable devices return instances; } public String getCeilingOf(String roomURI) { return getSingleObjPropertyValueOf(roomURI, this.namespaces.get("dogOnt") + "#hasCeiling"); } public String getFloorOf(String roomURI) { return getSingleObjPropertyValueOf(roomURI, this.namespaces.get("dogOnt") + "#hasFloor"); } public String getActuatorOf(String actuatorURI) { return getSingleObjPropertyValueOf(actuatorURI, this.namespaces.get("dogOnt") + "#actuatorOf"); } public String getSensorOf(String sensorURI) { return getSingleObjPropertyValueOf(sensorURI, this.namespaces.get("dogOnt") + "#isSensorOf"); } public Set<String> getControlledObjects(String deviceURI) { return getMultipleObjPropertyValueOf(deviceURI, this.namespaces.get("dogOnt") + "#controlledObject"); } public Set<String> getGeneratesCommands(String notificationURI) { return getMultipleObjPropertyValueOf(notificationURI, this.namespaces.get("dogOnt") + "#generateCommand"); } public Set<String> getAllWallsOf(String roomURI) { return this.getMultipleObjPropertyValueOf(roomURI, this.namespaces.get("dogOnt") + "#hasWall"); } public Set<String> getAllWallOpeningsIn(String wallURI) { return this.getMultipleObjPropertyValueOf(wallURI, this.namespaces.get("dogOnt") + "#hasWallOpening"); } public Set<String> getIsIn(String devURI) { return getMultipleObjPropertyValueOf(devURI, this.namespaces.get("dogOnt") + "#isIn"); } /** * Retrieve the id of the meter if exists * * @param devUri * device uri * @return uri of the meter or null */ public String getHasMeter(String devUri) { return getSingleObjPropertyValueOf(devUri, this.namespaces.get("dogOnt") + "#hasMeter"); } /** * Retrieve the device "metered" by the given meter instance * * @param devUri * device uri * @return A {@link Set}<{@link String}> of URIs of devices metered by the given meter instance */ public Set<String> getMeterOf(String devUri) { return getMultipleObjPropertyValueOf(devUri, this.namespaces.get("dogOnt") + "#meterOf"); } /** * Retrieve the plug in which the device identified by the given URI is plugged * * @param devUri * device uri * @return the URI( {@link String}) of the plug in which the device identified by the given URI is plugged, if any */ public String getPluggedIn(String devUri) { return getSingleObjPropertyValueOf(devUri, this.namespaces.get("dogOnt") + "#pluggedIn"); } /** * Retrieve the id of the gate if exists * * @param devUri * device uri * @return uri of the meter or null */ public String getHasGateway(String devUri) { return getSingleObjPropertyValueOf(devUri, this.namespaces.get("dogOnt") + "#hasGateway"); } public String getSingleObjPropertyValueOf(String instURI, String relationURI) { String value = null; Individual roomInd = this.model.getIndividual(instURI); Property prop = this.model.getProperty(relationURI); RDFNode objNode = roomInd.getPropertyValue(prop); if (objNode != null) { if (objNode.canAs(Resource.class)) { value = ((Resource) objNode).getLocalName(); } } return value; } public Set<String> getMultipleObjPropertyValueOf(String instURI, String relationURI) { Set<String> allValues = null; // get the individual represented by the given instance uri Individual roomInd = this.model.getIndividual(instURI); // get the property for which values must be gathered Property prop = this.model.getProperty(relationURI); // list all the values of the given property, for the given instance NodeIterator nodes = roomInd.listPropertyValues(prop); // convert the iterator to a set for easier navigation (less efficient) Set<RDFNode> nodesSet = nodes.toSet(); if (!nodesSet.isEmpty()) { // if the set is not empty init the result set holding the string // representations of the // property values allValues = new HashSet<String>(); for (RDFNode node : nodesSet) { if (node.canAs(Resource.class)) { allValues.add(((Resource) node).getLocalName()); } } } return allValues; } /** * Get all the values associated to the datatype properties of a given * instance * * @param instance * the instance for which the datatype properties values shall be * retrieved * @return A @link{Map}<@link{String},@link{Set}<@link{String}>> containing * the datatype property name as key and the set of values as value */ public Map<String, Set<String>> getDatatypePropertyValuesOf(String instance, String type) { Map<String, Set<String>> datatypePropertyValues = new HashMap<String, Set<String>>(); // get the instance class, for the given type (avoid ambiguities due to // multiple inheritance) OntClass instanceClass = this.model.getOntClass(this.namespaces.get("dogOnt") + "#" + type); // get all the datatype properties Set<String> datatypeProperties = this.getDatatypePropertiesOf("dogOnt:" + instanceClass.getLocalName()); // for all the datatype properties retrieve the values Individual instanceInd = this.model.getIndividual(instance); for (String property : datatypeProperties) { Property prop = this.model.getProperty(this.namespaces.get("dogOnt") + "#" + property); NodeIterator nodeIt = instanceInd.listPropertyValues(prop); // iterate over results and fill the set of values Set<String> values = new HashSet<String>(); while (nodeIt.hasNext()) { values.add(nodeIt.next().asLiteral().getString()); } if (!values.isEmpty()) datatypePropertyValues.put(this.toShortForm(property), values); } return datatypePropertyValues; } /** * Returns the comment associated to a given ontology instance * * @param instanceURI * @return the associated comment or null if the comment does not exist */ public String getDescriptionOf(String instanceURI) { Individual ind = this.model.getIndividual(instanceURI); return ind.getComment(null); } /*** * Provide the list of the states of the Device * * @param deviceURI * uri of the device * @return list of state belonging to the device */ public Set<String> getDeviceInstanceLevelStates(String deviceURI) { Set<String> states = new HashSet<String>(); // the query String qBody = "SELECT ?s WHERE {" + "<" + deviceURI + "> dogOnt:hasState ?s}"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results to fill the set QuerySolution cSol; while (res.hasNext()) { // the current query solution cSol = res.next(); // if not null work on it if (cSol != null) { // get the state uri and add it the list states.add(cSol.getResource("s").getURI()); } } return states; } /*** * Provide the list of the states of the Device * * @param deviceURI * uri of the device * @return list of state belonging to the device */ public Map<String, String> getDeviceInstanceLevelStatesValues(String stateURI) { Map<String, String> states = new HashMap<String, String>(); // the query String qBody = "SELECT ?sv WHERE {" + "<" + stateURI + "> dogOnt:hasStateValue ?sv}"; // exec the query ResultSet res = SimplifiedQueryExecutor.execQuery(this.namespaceDecl + qBody, this.model); // iterate over the results to fill the set QuerySolution cSol; while (res.hasNext()) { // the current query solution cSol = res.next(); // if not null work on it if (cSol != null) { Resource stateValue = cSol.getResource("sv"); if (stateValue != null) { Property prop = this.model.getProperty(this.namespaces.get("dogOnt") + "#" + "realStateValue"); String propValue = ""; try { propValue = stateValue.getProperty(prop).getString(); } catch (Exception e) { } // get the state uri and add it the list states.put(stateValue.getURI(), propValue); } } } return states; } public Map<String, Set<String>> getInstanceLevelDeviceNetworkParameters(String devURI) { return this.getDatatypePropertyValuesOf(devURI, "DomoticNetworkComponent"); } public Map<String, Set<String>> getInstanceLevelCommandNetworkParameters(String cmdURI) { return this.getDatatypePropertyValuesOf(cmdURI, "NetworkSpecificCommand"); } public Map<String, Set<String>> getInstanceLevelCommandParameters(String cmdURI) { return this.getDatatypePropertyValuesOf(cmdURI, this.getType(cmdURI, null)); } public Map<String, Set<String>> getInstanceLevelNotificationNetworkParameters(String notifURI) { return this.getDatatypePropertyValuesOf(notifURI, "NetworkSpecificNotification"); } public Map<String, Set<String>> getInstanceLevelNotificationParameters(String notifURI) { return this.getDatatypePropertyValuesOf(notifURI, this.getType(notifURI, null)); } /****************************************************************************************************************** * * Common utility methods * * @param devCategory * TODO complete * *****************************************************************************************************************/ public String toShortForm(String devCategory) { String shortForm = ""; // check if the string contains is a full ontology URI or not (quick and // dirt) if (devCategory.contains("#")) { // we assume the devCategory is a full URI shortForm = devCategory.substring(devCategory.indexOf('#') + 1); } else if (devCategory.contains(":")) { // we assume that the devCategory is in the namespace:name form shortForm = devCategory.substring(devCategory.indexOf(':') + 1); } else { // it is already in the shortForm shortForm = devCategory; } return shortForm; } public Set<String> getTypes(String content) { // all direct classes Individual devInd = this.model.getIndividual(content); Set<OntClass> devClasses = devInd.listOntClasses(false).toSet(); Set<String> returnedClasses = new HashSet<String>(); for (OntClass devClass : devClasses) { returnedClasses.add(this.toShortForm(devClass.getURI())); } return returnedClasses; } }