/** * Copyright (C) 2008 - 2014 52°North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * - Apache License, version 2.0 * - Apache Software License, version 1.0 * - GNU Lesser General Public License, version 3 * - Mozilla Public License, versions 1.0, 1.1 and 2.0 * - Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * icense version 2 and the aforementioned licenses. * * This program 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 General * Public License for more details. */ /** * Part of the diploma thesis of Thomas Everding. * @author Thomas Everding */ package org.n52.ses.eml.v002.pattern; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import javax.xml.namespace.QName; import net.opengis.fes.x20.DistanceBufferType; import net.opengis.fes.x20.FilterType; import net.opengis.fes.x20.SpatialOpsType; import org.apache.xmlbeans.GDuration; import org.n52.ses.eml.v002.Constants; import org.n52.ses.eml.v002.filter.spatial.DWithinFilter; import org.n52.ses.eml.v002.filter.spatial.SpatialFilterFactory; import org.n52.ses.eml.v002.views.DynamicSpatialBufferView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Represents a single view * * @author Thomas Everding * */ public class DataView { /* * Logger instance for this class */ private static final Logger logger = LoggerFactory .getLogger(DataView.class); private String viewName; private String esperString = ""; private boolean batch = false; private HashMap<String, Object> parameters; /** * * Constructor * */ public DataView() { this.parameters = new HashMap<String, Object>(); } /** * @return the viewName */ public String getViewName() { return this.viewName; } /** * @param viewName the viewName to set */ public void setViewName(String viewName) { this.viewName = viewName; } /** * @return the parameters */ public HashMap<String, Object> getParameters() { return this.parameters; } /** * adds a parameter for the view * * @param pName name of the parameter * @param pValue value of the parameter */ public void addParameter(String pName, Object pValue) { this.parameters.put(pName, pValue); } /** * @return the batch */ public boolean isBatch() { return this.batch; } /** * @param batch the batch to set */ public void setBatch(boolean batch) { this.batch = batch; } /** * * @return the view as esper statement part, creates it if necessary */ public String getViewString() { if (this.esperString.equals("")) { //create esper string /* * AllView */ if (this.viewName.equals(Constants.VIEW_ALL_NAME)) { this.esperString = ".win:keepall()"; } /* * LengthView */ else if (this.viewName.equals(Constants.VIEW_LENGTH_NAME)) { this.esperString = ".win:length"; if (this.batch) { this.esperString += "_batch"; } this.esperString += "(" + this.parameters.get(Constants.VIEW_PARAM_EVENT_COUNT_NAME) + ")"; } /* * TimeView */ else if (this.viewName.equals(Constants.VIEW_TIME_NAME)) { this.esperString = ".win:time"; if (this.batch) { this.esperString += "_batch"; } this.esperString += "(" + this.parameters.get(Constants.VIEW_PARAM_DURATION_NAME) + " msec)"; } /* * TimeLengthView */ else if (this.viewName.equals(Constants.VIEW_TIME_LENGTH_NAME)) { if (!this.batch) { logger.warn("sliding TimeLengthView is not supported, using batch mode"); } this.esperString = ".win:time_length_batch(" + this.parameters.get(Constants.VIEW_PARAM_DURATION_NAME) + " msec, " + this.parameters.get(Constants.VIEW_PARAM_EVENT_COUNT_NAME) + ")"; } /* * create statements for additional views here */ /* * TimeWithParameter (user defined) * is a user defined view with three parameters * - START_EAGER set to true or false (default false) * - FORCE_UPDATES set to true or false (default false) * - Duration * See http://esper.codehaus.org/esper-2.3.0/doc/reference/en/html/epl-views.html#view-win-time-batch */ else if (this.viewName.equals(Constants.VIEW_TIME_WITH_PARAMETER)) { logger.info("####### creating esper string for user defined view \"TimeBatchWithParameter\""); // get parameter boolean isForceUpdates = false; boolean isStartEager = false; boolean first = true; String parameter = null; long duration = 60000l; Object obj = null; GDuration gDuration = null; // // isForceUpdates obj = this.parameters.get(Constants.VIEW_PARAM_USD_FORCE_UPDATES); if (obj != null) { isForceUpdates = Boolean.parseBoolean(obj.toString()); } // // isStartEager obj = this.parameters.get(Constants.VIEW_PARAM_USD_START_EAGER); if (obj != null) { isStartEager = Boolean.parseBoolean(obj.toString()); } // // duration obj = this.parameters.get(Constants.VIEW_PARAM_DURATION_NAME); // we have to parse the duration here try{ gDuration = new GDuration(obj.toString()); duration = this.parseTimerDuration(gDuration); } catch (Exception e) { logger.warn("duration in EML documet is not parseable, using default 60 sec"); } logger.debug("####### " + "parameter:\nisForceUpdates: " + isForceUpdates + "\nisStartEager: " + isStartEager + "\nDuration: " + duration + ""); // // create esperString // esper keywords if (isForceUpdates) { parameter = "\"FORCE_UPDATE"; first = false; } if (isStartEager) { if (first) { parameter = "\""; } else{ parameter += ", "; } parameter += "START_EAGER"; } if(isForceUpdates || isStartEager){ parameter += "\""; } // this.esperString = ".win:time_batch(" + duration +" msec" + (parameter!=null?", " + parameter : "") // add parameter only if given + ")"; logger.debug("####### created esper string: \"" + this.esperString + "\""); } /* * User Define View "SelectLast" * * combines two views: {Time/Batch|Length/Batch} && std:lastevent * * Three parameters: * - type: allowed values "time"|"length" * - Duration: XMLDuration | integer <-- event count * - isBatch: true | false * * See http://esper.codehaus.org/esper-2.3.0/doc/reference/en/html/epl-views.html#view-std-last */ else if (this.viewName.equals(Constants.VIEW_SELECT_LAST)) { logger.info("####### creating esper string for user defined view \"SelectLast\""); // boolean isTime = false; // default is length view boolean isBatch = false; String durationOrLength = null; long duration = 60000l; Object obj = null; GDuration gDuration = null; // // Time or Length obj = this.parameters.get(Constants.VIEW_PARAM_USD_TYPE); if (obj != null) { String type = (String) obj; if (type.equals(Constants.VIEW_PARAM_USD_TYPE_TIME)) { isTime = true; } else if (!type.equals(Constants.VIEW_PARAM_USD_TYPE_LENGTH)) { logger.warn("####### wrong input parameter for user " + "defined view \"SelectLast\": given value: " + type + "; allowed values: [" + Constants.VIEW_PARAM_USD_TYPE_TIME + " | " + Constants.VIEW_PARAM_USD_TYPE_LENGTH + "] using default: length"); } } // // parse duration -> durationOrLength obj = this.parameters.get(Constants.VIEW_PARAM_DURATION_NAME); if (isTime) { // we have to parse the duration here try{ gDuration = new GDuration(obj.toString()); duration = this.parseTimerDuration(gDuration); durationOrLength = duration + ""; } catch (Exception e) { logger.warn("duration in EML documet is not parseable, using default 60 sec"); } } else{ // we have to parse to int Integer length = 1; try{ length = Integer.parseInt(((String) obj)); } catch (NumberFormatException nfe) { logger.warn("length in EML documet is not parseable, using default \"1\""); } durationOrLength = length + ""; } // // parse isBatch obj = this.parameters.get(Constants.VIEW_PARAM_USD_IS_BATCH); if (obj != null) { isBatch = Boolean.parseBoolean(obj.toString()); } // // logger.debug("####### " + "parameter:\nisTime: " + isTime + "\nisBatch: " + isBatch + "\nDuration: " + duration + "\ndurationOrLength: " + durationOrLength); // // // build esper statement if (isTime) { this.esperString = ".win:time"; if (isBatch) { this.esperString += "_batch"; } this.esperString += "(" + durationOrLength + " msec)"; } else { this.esperString = ".win:length"; if (isBatch) { this.esperString += "_batch"; } this.esperString += "(" + durationOrLength + ")"; } // this.esperString += ".std:lastevent()"; // this.esperString += ".ext:sort(startTime,false,1)"; /* * selection of lastevent is implemented in the EsperController * method buildListeners. workaround because esper is not * capable of this functionality */ logger.debug("####### created esper string: \"" + this.esperString + "\""); } /* * generic view */ else if (this.viewName.equals(Constants.VIEW_GENERIC_NAME)) { this.esperString = ".win:keepAll()"; if (this.parameters.containsKey("SelectFunctions")) { @SuppressWarnings("unchecked") List<SelFunction> funcs = (List<SelFunction>) this.parameters.get("SelectFunctions"); for (SelFunction selFunction : funcs) { if (selFunction.getFunctionName().equals(DynamicSpatialBufferView.SELECTFUNCTION_NAME)) { /* * ##### * this is the dynamic spatial buffer! * ##### */ this.esperString = ".custom:dynamicSpatialBuffer("; /* * TODO the REAL stuff. skeleton is ready for it. */ Object tmp = this.parameters.get("InsertCriteria"); FilterType buffer = null; if (tmp != null) { @SuppressWarnings("unchecked") List<FilterType> bufferList = (List<FilterType>) tmp; if (bufferList.size() > 0) buffer = bufferList.get(0); } if (buffer != null) { SpatialOpsType sot = buffer.getSpatialOps(); QName sotQName = sot.newCursor().getName(); if (SpatialFilterFactory.DWITHIN_QNAME.equals(sotQName)) { DWithinFilter filter = new DWithinFilter((DistanceBufferType) sot); filter.createExpressionString(false); this.esperString += "fromWKT(\""+ filter.getOriginalGeometry().toText() +"\"), "+ filter.getDistance()+", \""+ filter.getUom() +"\", \""+ filter.getCRS() +"\", "; } if (this.parameters.containsKey("AffectingParameters")) { @SuppressWarnings("unchecked") List<String> affecting = (List<String>) this.parameters.get("AffectingParameters"); if (affecting.size() == 2) { this.esperString += affecting.get(0).replaceAll("/", ".")+ ", "+ affecting.get(1).replaceAll("/", "."); } } } this.esperString += ")"; break; } } } } } return this.esperString; } /** * parses a xs:duration to long(ms) * * used for TimeBatchWithParameter (user defined view) * * @param timerInterval xs:duration * @return long(ms) */ private long parseTimerDuration(GDuration timerInterval) { long result = 0; //years result += timerInterval.getYear() * 365 * 24 * 60 * 60 * 1000; //months result += timerInterval.getMonth() * 30 * 24 * 60 * 60 * 1000; //days result += timerInterval.getDay() * 24 * 60 * 60 * 1000; //hours result += timerInterval.getHour() * 60 * 60 * 1000; //minutes result += timerInterval.getMinute() * 60 * 1000; //seconds result += timerInterval.getSecond() * 1000; //fraction of second result += timerInterval.getFraction().multiply(new BigDecimal(1000)).longValue(); return result; } }