/**
* Copyright (c) 2011-2014, OpenIoT
*
* This file is part of OpenIoT.
*
* OpenIoT is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* OpenIoT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenIoT. If not, see <http://www.gnu.org/licenses/>.
*
* Contact: OpenIoT mailto: info@openiot.eu
*/
package org.openiot.ui.request.definition.web.sparql;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.logging.Level;
import org.openiot.ui.request.commons.interfaces.GraphModel;
import org.openiot.ui.request.commons.logging.LoggerService;
import org.openiot.ui.request.commons.nodes.base.AbstractGraphNodeVisitor;
import org.openiot.ui.request.commons.nodes.enums.EndpointType;
import org.openiot.ui.request.commons.nodes.interfaces.GraphNode;
import org.openiot.ui.request.commons.nodes.interfaces.GraphNodeConnection;
import org.openiot.ui.request.commons.nodes.interfaces.GraphNodeEndpoint;
import org.openiot.ui.request.commons.nodes.interfaces.GraphNodeProperty;
import org.openiot.ui.request.definition.web.model.nodes.impl.sinks.LineChart;
import org.openiot.ui.request.definition.web.model.nodes.impl.sinks.Passthrough;
import org.openiot.ui.request.definition.web.model.nodes.impl.sinks.Pie;
import org.openiot.ui.request.definition.web.model.nodes.impl.sources.GenericSource;
import org.openiot.ui.request.definition.web.sparql.nodes.base.AbstractSparqlNode;
import org.openiot.ui.request.definition.web.sparql.nodes.base.AggregateExpression;
import org.openiot.ui.request.definition.web.sparql.nodes.base.Comment;
import org.openiot.ui.request.definition.web.sparql.nodes.base.Expression;
import org.openiot.ui.request.definition.web.sparql.nodes.base.From;
import org.openiot.ui.request.definition.web.sparql.nodes.base.Group;
import org.openiot.ui.request.definition.web.sparql.nodes.base.Order;
import org.openiot.ui.request.definition.web.sparql.nodes.base.Root;
import org.openiot.ui.request.definition.web.sparql.nodes.base.Scope;
import org.openiot.ui.request.definition.web.sparql.nodes.base.Select;
import org.openiot.ui.request.definition.web.sparql.nodes.base.SensorSelectExpression;
import org.openiot.ui.request.definition.web.sparql.nodes.base.Where;
/**
*
* @author Achilleas Anagnostopoulos (aanag) email: aanag@sensap.eu
*/
public class SparqlGenerator extends AbstractGraphNodeVisitor {
private GraphModel model;
// Nodes
private Root primaryRootNode;
private Comment primaryCommentNode;
private Select primarySelectNode;
private From primaryFromNode;
private Where primaryWhereNode;
private Group primaryGroupNode;
//
private AbstractSparqlNode subSelectOriginalNode;
private AbstractSparqlNode subSelectNode;
private Where subWhereNode;
private Group subGroupNode;
private Order subOrderNode;
private boolean sinkNodeNeedsGeoCoords;
//
private GenericSource targetDataSource;
private GraphNodeEndpoint targetAttribute;
private Set<String> visitedSensorTypes;
private Map<GraphNodeProperty, Object> variableMap;
private Stack<GraphNodeConnection> visitedConnectionGraphStack;
// Generated code blocks
private List<String> queryBlocks;
// -------------------------------------------------------------------------
// Public API
// -------------------------------------------------------------------------
public SparqlGenerator() {
this.visitedConnectionGraphStack = new Stack<GraphNodeConnection>();
this.visitedSensorTypes = new LinkedHashSet<String>();
this.variableMap = new LinkedHashMap<GraphNodeProperty, Object>();
this.queryBlocks = new ArrayList<String>();
}
public List<String> generateQueriesForNodeEndpoints(GraphModel model, GraphNode visualizerNode) {
this.model = model;
this.queryBlocks.clear();
reset();
// Generate code for passed node
visitSink(visualizerNode);
// Return output
return this.queryBlocks;
}
public Map<GraphNodeProperty, Object> getVariableMap() {
return variableMap;
}
// -------------------------------------------------------------------------
// Query blocks
// -------------------------------------------------------------------------
private void reset() {
this.visitedConnectionGraphStack.clear();
this.visitedSensorTypes.clear();
this.variableMap.clear();
// Allocate initial nodes
primaryCommentNode = new Comment();
primarySelectNode = new Select();
primaryFromNode = new From(AbstractSparqlNode.GRAPH_DATA_URI);
primaryWhereNode = new Where();
primaryGroupNode = new Group();
primaryRootNode = new Root();
primaryRootNode.appendToScope(primaryCommentNode);
primaryRootNode.appendToScope(primarySelectNode);
primaryRootNode.appendToScope(primaryFromNode);
primaryRootNode.appendToScope(primaryWhereNode);
primaryRootNode.appendToScope(primaryGroupNode);
}
private void beginQueryBlock(GraphNode visNode, int tupleIndex, int totalTuples) {
reset();
this.visitedConnectionGraphStack.clear();
primaryCommentNode.appendComment("[" + tupleIndex + " / " + totalTuples + "] visualization type: '" + visNode.getLabel() + "' and sensors of type:");
this.visitedSensorTypes.clear();
}
private void endQueryBlock() {
// Setup comments
primaryCommentNode.appendComment("\t - " + org.apache.commons.lang3.StringUtils.join(visitedSensorTypes, "\n#\t - "));
primaryCommentNode.appendComment("Generated: " + (new Date()));
if (this.variableMap.size() > 0) {
primaryCommentNode.appendComment("Using " + this.variableMap.size() + " variable" + (this.variableMap.size() > 1 ? "s" : "") + ":");
for (Map.Entry<GraphNodeProperty, Object> entry : variableMap.entrySet()) {
primaryCommentNode.appendComment("- " + entry.getKey().getVariableName() + " (default value: " + entry.getValue() + ")");
}
}
queryBlocks.add(primaryRootNode.generate());
}
private void generateAttributeSubQueryWhereCode(GenericSource sensorNode, GraphNodeEndpoint attributeEndpoint) {
// Encode attribute selection
if (attributeEndpoint != null) {
subWhereNode.appendToScope(new Expression("?" + sensorNode.getUID() + "_record <http://openiot.eu/ontology/ns/value> ?" + attributeEndpoint.getUID() + " ."));
subWhereNode.appendToScope(new Expression("?" + sensorNode.getUID() + "_record <http://www.w3.org/2000/01/rdf-schema#label> '" + attributeEndpoint.getUserData() + "' ."));
}
subWhereNode.appendToScope(new Expression("?" + sensorNode.getUID() + "_record <http://purl.oclc.org/NET/ssnx/ssn#observationResultTime> ?" + sensorNode.getUID() + "_recordTime ."));
// Encode sensor selection expression
GraphNodeProperty prop = sensorNode.getPropertyByName("LAT");
Object latQuery = sensorNode.getPropertyValueMap().get("LAT");
if (prop.isVariable()) {
defineVariable(prop, latQuery);
latQuery = "#" + prop.getVariableName() + "#";
}
prop = sensorNode.getPropertyByName("LON");
Object lonQuery = sensorNode.getPropertyValueMap().get("LON");
if (prop.isVariable()) {
defineVariable(prop, lonQuery);
lonQuery = "#" + prop.getVariableName() + "#";
}
prop = sensorNode.getPropertyByName("RADIUS");
Object radiusQuery = sensorNode.getPropertyValueMap().get("RADIUS");
if (prop.isVariable()) {
defineVariable(prop, radiusQuery);
radiusQuery = "#" + prop.getVariableName() + "#";
}
subWhereNode.appendToScope(new SensorSelectExpression(sensorNode.getUID(),sensorNode.getLabel() ,latQuery, lonQuery, radiusQuery, this.sinkNodeNeedsGeoCoords));
}
private void defineVariable(GraphNodeProperty property, Object defaultValue) {
this.variableMap.put(property, defaultValue);
}
// -------------------------------------------------------------------------
// Generic non-sink node visitors
// -------------------------------------------------------------------------
@Override
public void defaultVisit(GraphNode node) {
if (node instanceof GenericSource) {
visit((GenericSource) node);
return;
}
LoggerService.log(Level.SEVERE, "[SparqlGenerator] Default visitor called for node of class: " + node.getClass().getSimpleName());
}
public void visit(GenericSource node) {
visitedSensorTypes.add(node.getLabel());
// Examine the connection endpoint that lead us to the sensor
GraphNodeConnection outgoingConnection = visitedConnectionGraphStack.peek();
GraphNodeEndpoint sourceEndpoint = outgoingConnection.getSourceEndpoint();
// Remember the sensor we landed to as well as the target attribute
// endpoint
targetDataSource = node;
targetAttribute = sourceEndpoint;
// Encode selection query
subSelectNode.appendToScope(new Expression("?" + sourceEndpoint.getUID()));
// Generate nested where clause for selected attribute
this.generateAttributeSubQueryWhereCode(targetDataSource, targetAttribute);
// If sensor node has an incoming filter node connection
// visit it and append any additional filters
for (GraphNodeEndpoint endpoint : node.getEndpointDefinitions()) {
if (endpoint.getType().equals(EndpointType.Output)) {
continue;
}
List<GraphNodeConnection> incomingConnections = model.findGraphEndpointConnections(endpoint);
for (GraphNodeConnection connection : incomingConnections) {
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
this.visitedConnectionGraphStack.pop();
}
}
}
// -------------------------------------------------------------------------
// Sink node Visitors
// -------------------------------------------------------------------------
public void visitSink(GraphNode node) {
// Only process the viz node that was passed to the
// 'generateQueriesForNodeEndpoints' method
if (!node.getType().equals("SINK")) {
return;
}
this.sinkNodeNeedsGeoCoords = false;
if (node instanceof LineChart) {
visitLineChartSink((LineChart) node);
} else if (node instanceof Passthrough) {
visitPassthroughSink((Passthrough) node);
} else if (node instanceof org.openiot.ui.request.definition.web.model.nodes.impl.sinks.Map) {
visitMapSink((org.openiot.ui.request.definition.web.model.nodes.impl.sinks.Map) node);
} else if (node instanceof Pie) {
visitPieSink((Pie) node);
} else {
visitGenericSink(node);
}
}
public void visitGenericSink(GraphNode node) {
beginQueryBlock(node, 1, 1);
// Visit incoming neighbors
for (GraphNodeEndpoint endpoint : node.getEndpointDefinitions()) {
if (endpoint.getType().equals(EndpointType.Output)) {
continue;
}
List<GraphNodeConnection> incomingConnections = model.findGraphEndpointConnections(endpoint);
for (GraphNodeConnection connection : incomingConnections) {
// Generate primary select
primarySelectNode.appendToScope(new Expression("?" + endpoint.getLabel()));
// Generate new scope for assembling the selection queries
// *unless* this is a grp_Date scope where
// we re use the current
Scope subScope = new Scope();
primaryWhereNode.appendToScope(subScope);
// Generate subquery helpers
subSelectNode = subSelectOriginalNode = new Select();
subWhereNode = new Where();
subGroupNode = new Group();
subScope.appendToScope(subSelectNode);
subScope.appendToScope(subWhereNode);
subScope.appendToScope(subGroupNode);
// Explore graph till we reach a sensor node.
targetDataSource = null;
targetAttribute = null;
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
// Append the endpoint label to the end of the generated select
// statement
subSelectNode.appendToScope(new Expression("AS ?" + endpoint.getLabel()));
//
this.visitedConnectionGraphStack.pop();
}
}
endQueryBlock();
}
public void visitMapSink(org.openiot.ui.request.definition.web.model.nodes.impl.sinks.Map node) {
this.sinkNodeNeedsGeoCoords = true;
beginQueryBlock(node, 1, 1);
// Visit incoming neighbors
for (GraphNodeEndpoint endpoint : node.getEndpointDefinitions()) {
if (endpoint.getType().equals(EndpointType.Output)) {
continue;
}
// If this is a LAT or LON connection, skip it because we will
// include it
// together with the VALUE endpoint
if (endpoint.getScope().contains("geo_lat") || endpoint.getScope().contains("geo_lon")) {
continue;
}
LoggerService.log(Level.INFO, "Visit endpoint with scope: " + endpoint.getScope());
List<GraphNodeConnection> incomingConnections = model.findGraphEndpointConnections(endpoint);
for (GraphNodeConnection connection : incomingConnections) {
// Generate primary select (also include LAT/LON fields)
primarySelectNode.appendToScope(new Expression("?" + endpoint.getLabel()));
primarySelectNode.appendToScope(new Expression("?LAT"));
primarySelectNode.appendToScope(new Expression("?LON"));
// Generate new scope for assembling the selection queries
// *unless* this is a grp_Date scope where
// we re use the current
Scope subScope = new Scope();
primaryWhereNode.appendToScope(subScope);
// Generate subquery helpers
subSelectNode = subSelectOriginalNode = new Select();
subWhereNode = new Where();
subGroupNode = new Group();
subScope.appendToScope(subSelectNode);
subScope.appendToScope(subWhereNode);
subScope.appendToScope(subGroupNode);
// Explore graph till we reach a sensor node.
targetDataSource = null;
targetAttribute = null;
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
// Append the endpoint label to the end of the generated select
// statement
subSelectNode.appendToScope(new Expression("AS ?" + endpoint.getLabel()));
subSelectNode.appendToScope(new Expression("?" + targetDataSource.getUID() + "_lat AS ?LAT"));
subSelectNode.appendToScope(new Expression("?" + targetDataSource.getUID() + "_lon AS ?LON"));
//
this.visitedConnectionGraphStack.pop();
}
}
endQueryBlock();
}
public void visitLineChartSink(LineChart node) {
String xAxisType = (String) node.getPropertyValueMap().get("X_AXIS_TYPE");
// Group queries for xy tuples
int seriesCount = Integer.valueOf((String) node.getPropertyValueMap().get("SERIES"));
for (int i = 0; i < seriesCount; i++) {
// Start a new code block for each series
beginQueryBlock(node, i + 1, seriesCount);
GraphNodeEndpoint xEndpoint = node.getEndpointByLabel("x" + (i + 1));
GraphNodeEndpoint yEndpoint = node.getEndpointByLabel("y" + (i + 1));
// Follow Y axis value
for (GraphNodeConnection connection : model.findGraphEndpointConnections(yEndpoint)) {
Scope subScope = new Scope();
primaryWhereNode.appendToScope(subScope);
// Generate subquery helpers
subSelectNode = subSelectOriginalNode = new Select();
subWhereNode = new Where();
subGroupNode = new Group();
subOrderNode = new Order();
subScope.appendToScope(subSelectNode);
subScope.appendToScope(subWhereNode);
subScope.appendToScope(subGroupNode);
subScope.appendToScope(subOrderNode);
// Explore graph till we reach a sensor node.
targetDataSource = null;
targetAttribute = null;
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
this.visitedConnectionGraphStack.pop();
subSelectNode.appendToScope(new Expression("AS ?" + yEndpoint.getLabel()));
primarySelectNode.appendToScope(new Expression("?" + yEndpoint.getLabel()));
}
// Process x axis endpoint
if (xEndpoint != null) {
for (GraphNodeConnection connection : model.findGraphEndpointConnections(xEndpoint)) {
if (xAxisType.equals("Date (observation)")) {
String timeComponent = connection.getSourceEndpoint().getLabel().replace("grp_recordTime_", "");
// Note: We need to apply an aggregation function to
// timestamp components
// for the value grouping to work
subSelectNode.appendToScope(new Expression("AVG( fn:" + timeComponent + "-from-dateTime(?" + targetDataSource.getUID() + "_recordTime) ) AS ?" + xEndpoint.getLabel() + "_" + timeComponent));
primarySelectNode.appendToScope(new Expression("?" + xEndpoint.getLabel() + "_" + timeComponent));
} else {
Scope subScope = new Scope();
primaryWhereNode.appendToScope(subScope);
// Generate subquery helpers
subSelectNode = subSelectOriginalNode = new Select();
subWhereNode = new Where();
subGroupNode = new Group();
subOrderNode = new Order();
subScope.appendToScope(subSelectNode);
subScope.appendToScope(subWhereNode);
subScope.appendToScope(subGroupNode);
subScope.appendToScope(subOrderNode);
// Explore graph till we reach a sensor node.
targetDataSource = null;
targetAttribute = null;
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
this.visitedConnectionGraphStack.pop();
subSelectNode.appendToScope(new Expression("AS ?" + xEndpoint.getLabel()));
primarySelectNode.appendToScope(new Expression("?" + xEndpoint.getLabel()));
}
}
}
endQueryBlock();
}
}
public void visitPassthroughSink(Passthrough node) {
// Generate one query per attribute
int attrCount = Integer.valueOf(node.getPropertyValueMap().get("ATTRIBUTES").toString());
for (int i = 0; i < attrCount; i++) {
// Start a new code block for each attribute
beginQueryBlock(node, i + 1, attrCount);
GraphNodeEndpoint attrEndpoint = node.getEndpointByLabel("attr" + (i + 1));
// Follow attr value
for (GraphNodeConnection connection : model.findGraphEndpointConnections(attrEndpoint)) {
Scope subScope = new Scope();
primaryWhereNode.appendToScope(subScope);
// Generate subquery helpers
subSelectNode = subSelectOriginalNode = new Select();
subWhereNode = new Where();
subGroupNode = new Group();
subOrderNode = new Order();
subScope.appendToScope(subSelectNode);
subScope.appendToScope(subWhereNode);
subScope.appendToScope(subGroupNode);
subScope.appendToScope(subOrderNode);
// Explore graph till we reach a sensor node.
targetDataSource = null;
targetAttribute = null;
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
this.visitedConnectionGraphStack.pop();
subSelectNode.appendToScope(new Expression("AS ?" + attrEndpoint.getLabel()));
primarySelectNode.appendToScope(new Expression("?" + attrEndpoint.getLabel()));
}
endQueryBlock();
}
}
public void visitPieSink(Pie node) {
// Generate one query per attribute
int seriesCount = Integer.valueOf((String) node.getPropertyValueMap().get("SERIES"));
for (int i = 0; i < seriesCount; i++) {
// Start a new code block for each series
beginQueryBlock(node, i + 1, seriesCount);
GraphNodeEndpoint attrEndpoint = node.getEndpointByLabel("y" + (i + 1));
// Follow attr value
for (GraphNodeConnection connection : model.findGraphEndpointConnections(attrEndpoint)) {
Scope subScope = new Scope();
primaryWhereNode.appendToScope(subScope);
// Generate subquery helpers
subSelectNode = subSelectOriginalNode = new Select();
subWhereNode = new Where();
subGroupNode = new Group();
subOrderNode = new Order();
subScope.appendToScope(subSelectNode);
subScope.appendToScope(subWhereNode);
subScope.appendToScope(subGroupNode);
subScope.appendToScope(subOrderNode);
// Explore graph till we reach a sensor node.
targetDataSource = null;
targetAttribute = null;
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
this.visitedConnectionGraphStack.pop();
subSelectNode.appendToScope(new Expression("AS ?" + attrEndpoint.getLabel()));
primarySelectNode.appendToScope(new Expression("?" + attrEndpoint.getLabel()));
}
endQueryBlock();
}
}
private void visitIncomingConnections(GraphNode destinationNode) {
for (GraphNodeEndpoint endpoint : destinationNode.getEndpointDefinitions()) {
if (endpoint.getType().equals(EndpointType.Output)) {
continue;
}
List<GraphNodeConnection> incomingConnections = model.findGraphEndpointConnections(endpoint);
for (GraphNodeConnection connection : incomingConnections) {
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
this.visitedConnectionGraphStack.pop();
}
}
}
// -------------------------------------------------------------------------
// Filter node visitors
// -------------------------------------------------------------------------
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.filters.SelectionFilter node) {
// Visit all outgoing connections except the one connecting to the
// sensor
for (GraphNodeEndpoint endpoint : node.getEndpointDefinitions()) {
if (endpoint.getType().equals(EndpointType.Input)) {
continue;
}
List<GraphNodeConnection> incomingConnections = model.findGraphEndpointConnections(endpoint);
for (GraphNodeConnection connection : incomingConnections) {
if (connection.getDestinationNode() instanceof GenericSource) {
continue;
}
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getDestinationNode());
this.visitedConnectionGraphStack.pop();
}
}
}
protected void generateTimeGroups(List<String> groupList) {
}
@SuppressWarnings("unchecked")
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.filters.Group node) {
// Unwind the stack till we find the sink
GraphNodeEndpoint ourEndpoint = null;
ListIterator<GraphNodeConnection> connectionIt = visitedConnectionGraphStack.listIterator(visitedConnectionGraphStack.size());
ourEndpoint = connectionIt.previous().getSourceEndpoint();
// Get attributes endpoint
GraphNodeEndpoint attributesEndpoint = node.getEndpointByLabel("ATTRIBUTES");
this.targetDataSource = (GenericSource) model.findGraphEndpointConnections(attributesEndpoint).get(0).getSourceNode();
// Generate groups
List<String> groupList = (List<String>) node.getPropertyValueMap().get("GROUPS");
for (String group : groupList) {
String timeComponent = group.replace("recordTime_", "");
subGroupNode.appendToScope(new Expression("( fn:" + timeComponent + "-from-dateTime(?" + targetDataSource.getUID() + "_recordTime) )"));
subOrderNode.appendToScope(new Expression("( fn:" + timeComponent + "-from-dateTime(?" + targetDataSource.getUID() + "_recordTime) )"));
}
// Follow the connection that matches our endpoint label (ie the
// currently grouped property)
List<GraphNodeConnection> incomingConnections = model.findGraphEndpointConnections(attributesEndpoint);
String attrName = ourEndpoint.getLabel().replace("grp_", "");
for (GraphNodeConnection connection : incomingConnections) {
if (!attrName.equals(connection.getSourceEndpoint().getLabel())) {
continue;
}
this.visitedConnectionGraphStack.push(connection);
this.visitViaReflection(connection.getSourceNode());
this.visitedConnectionGraphStack.pop();
}
}
// -------------------------------------------------------------------------
// Comparator node visitors
// -------------------------------------------------------------------------
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.comparators.CompareAbsoluteDateTime node) {
// Generate date string in appropriate format.
// xsd:datetime type formats dates a bit differently than the pattern
// used by simple date
// format (separates hours and mins of the timezone with a colon) so we
// need to patch it here
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
Date cmpValue = (Date) node.getPropertyValueMap().get("CMP_VALUE");
String formattedDate = sdf.format(cmpValue);
formattedDate = formattedDate.substring(0, formattedDate.length() - 2) + ":" + formattedDate.substring(formattedDate.length() - 2);
GraphNodeProperty prop = node.getPropertyByName("CMP_VALUE");
if (prop.isVariable()) {
defineVariable(prop, formattedDate);
formattedDate = "#" + prop.getVariableName() + "#";
}
subWhereNode.appendToScope(new Expression("FILTER (?" + targetDataSource.getUID() + "_recordTime " + node.getPropertyValueMap().get("OPERATOR") + " \"" + formattedDate + "\"^^xsd:date )."));
}
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.comparators.CompareRelativeDateTime node) {
long scaler = 1L;
String unit = (String) node.getPropertyValueMap().get("CMP_VALUE_UNIT");
if ("SECOND(S)".equals(unit)) {
scaler = 1L;
} else if ("MINUTE(S)".equals(unit)) {
scaler = 60L;
} else if ("HOUR(S)".equals(unit)) {
scaler = 60 * 60L;
} else if ("DAY(S)".equals(unit)) {
scaler = 24 * 60 * 60L;
} else if ("MONTH(S)".equals(unit)) {
scaler = 30 * 24 * 60 * 60L;
} else if ("YEAR(S)".equals(unit)) {
scaler = 365 * 24 * 60 * 60L;
}
String cmpValue = "" + Long.valueOf(node.getPropertyValueMap().get("CMP_VALUE").toString()) * scaler;
GraphNodeProperty prop = node.getPropertyByName("CMP_VALUE");
if (prop.isVariable()) {
defineVariable(prop, cmpValue);
cmpValue = "#" + prop.getVariableName() + "#";
}
subWhereNode.appendToScope(new Expression("FILTER( bif:datediff('second', xsd:dateTime(str(?" + targetDataSource.getUID() + "_recordTime)), bif:curdatetime()) " + node.getPropertyValueMap().get("OPERATOR") + " " + cmpValue + ")."));
}
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.comparators.BetweenDateTime node) {
// Generate date string in appropriate format.
// xsd:datetime type formats dates a bit differently than the pattern
// used by simple date
// format (separates hours and mins of the timezone with a colon) so we
// need to patch it here
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
Date cmpFromValue = (Date) node.getPropertyValueMap().get("CMP_VALUE1");
String formattedFromDate = sdf.format(cmpFromValue);
formattedFromDate = formattedFromDate.substring(0, formattedFromDate.length() - 2) + ":" + formattedFromDate.substring(formattedFromDate.length() - 2);
Date cmpToValue = (Date) node.getPropertyValueMap().get("CMP_VALUE2");
String formattedToDate = sdf.format(cmpToValue);
formattedToDate = formattedToDate.substring(0, formattedToDate.length() - 2) + ":" + formattedToDate.substring(formattedToDate.length() - 2);
GraphNodeProperty prop = node.getPropertyByName("CMP_VALUE1");
if (prop.isVariable()) {
defineVariable(prop, formattedFromDate);
formattedFromDate = "#" + prop.getVariableName() + "#";
}
prop = node.getPropertyByName("CMP_VALUE2");
if (prop.isVariable()) {
defineVariable(prop, formattedToDate);
formattedToDate = "#" + prop.getVariableName() + "#";
}
subWhereNode.appendToScope(new Expression("FILTER (?" + targetDataSource.getUID() + "_recordTime >= \"" + formattedFromDate + "\"^^xsd:date AND ?" + targetDataSource.getUID() + "_recordTime <= \"" + formattedToDate + "\"^^xsd:date )."));
}
// -------------------------------------------------------------------------
// Aggregator node visitors
// -------------------------------------------------------------------------
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.aggegators.Min node) {
AbstractSparqlNode current = subSelectNode;
subSelectNode = subSelectNode.appendToScope(new AggregateExpression("MIN"));
visitIncomingConnections(node);
subSelectNode = current;
}
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.aggegators.Max node) {
AbstractSparqlNode current = subSelectNode;
subSelectNode = subSelectNode.appendToScope(new AggregateExpression("MAX"));
visitIncomingConnections(node);
subSelectNode = current;
}
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.aggegators.Count node) {
AbstractSparqlNode current = subSelectNode;
subSelectNode = subSelectNode.appendToScope(new AggregateExpression("COUNT"));
visitIncomingConnections(node);
subSelectNode = current;
}
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.aggegators.Sum node) {
AbstractSparqlNode current = subSelectNode;
subSelectNode = subSelectNode.appendToScope(new AggregateExpression("SUM"));
visitIncomingConnections(node);
subSelectNode = current;
}
public void visit(org.openiot.ui.request.definition.web.model.nodes.impl.aggegators.Average node) {
AbstractSparqlNode current = subSelectNode;
subSelectNode = subSelectNode.appendToScope(new AggregateExpression("AVG"));
visitIncomingConnections(node);
subSelectNode = current;
}
}