/** * 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. */ package org.n52.ses.filter.epl; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Vector; import net.opengis.gml.AbstractFeatureType; import net.opengis.sampling.x10.SamplingPointType; import org.n52.ses.api.IUnitConverter; import org.n52.ses.api.eml.IEML; import org.n52.ses.api.eml.ILogicController; import org.n52.ses.api.eml.IPatternSimple; import org.n52.ses.api.event.DataTypesMap; import org.n52.ses.api.event.MapEvent; import org.n52.ses.api.ws.ISubscriptionManager; import org.n52.ses.filter.epl.EPLFilterImpl.EPLFilterInstance; import org.n52.ses.util.common.ConfigurationRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.espertech.esper.client.Configuration; import com.espertech.esper.client.EPServiceProvider; import com.espertech.esper.client.EPServiceProviderManager; import com.espertech.esper.client.EPStatement; import com.espertech.esper.client.EPStatementException; import com.vividsolutions.jts.geom.Geometry; public class EPLFilterController implements ILogicController { private static final Logger logger = LoggerFactory .getLogger(EPLFilterController.class); private EPServiceProvider epService; private Configuration config; private ISubscriptionManager subMgr; private Map<String, EPStatement> epStatements = new HashMap<String, EPStatement>(); private Map<String, Object> eventProperties; private Map<String, Map<String, Object>> inputEventDataTypes = new HashMap<String, Map<String,Object>>(); public EPLFilterController(ISubscriptionManager sub, EPLFilterImpl filter) throws Exception { this.config = new Configuration(); this.subMgr = sub; String emlController = ConfigurationRegistry.getInstance().getPropertyForKey(ConfigurationRegistry.EML_CONTROLLER); if (emlController.equalsIgnoreCase(ConfigurationRegistry.EML_001_IMPL)) { this.config.addImport("org.n52.ses.eml.v001.filterlogic.esper.customFunctions.*"); } else { this.config.addImport("org.n52.ses.eml.v002.filterlogic.esper.customFunctions.*"); } //register default properties registerStandardPropertyNames(); //register the external stream w/ properties at the engine registerEvent(filter.getExternalInputName(), this.eventProperties); //register newEventName streams at engine String newEventName = null; for (EPLFilterInstance eplStmt : filter.getEplFilters().keySet()) { newEventName = eplStmt.getNewEventName(); if (newEventName != null && !newEventName.equals("")) { registerEvent(newEventName, this.eventProperties); } } //initialize esper this.epService = EPServiceProviderManager.getProvider("ses:id:"+ this.hashCode(), this.config); for (EPLFilterInstance eplStmt : filter.getEplFilters().keySet()) { String stream = filter.getEplFilters().get(eplStmt); addEPLStatement(eplStmt, stream); } } /** * Registers the standard property names at the * data types map. */ private void registerStandardPropertyNames() { //get data types map DataTypesMap dtm = DataTypesMap.getInstance(); //register types dtm.registerNewDataType(MapEvent.SENSORID_KEY, String.class); dtm.registerNewDataType(MapEvent.STRING_VALUE_KEY, String.class); dtm.registerNewDataType(MapEvent.DOUBLE_VALUE_KEY, Double.class); dtm.registerNewDataType(MapEvent.FOI_ID_KEY, String.class); dtm.registerNewDataType(MapEvent.START_KEY, Long.class); dtm.registerNewDataType(MapEvent.END_KEY, Long.class); dtm.registerNewDataType(MapEvent.OBSERVED_PROPERTY_KEY, String.class); //register Map as event type with registered phenomenons/types this.eventProperties = new HashMap<String, Object>(); this.eventProperties.put(MapEvent.START_KEY, Long.class); this.eventProperties.put(MapEvent.END_KEY, Long.class); this.eventProperties.put(MapEvent.STRING_VALUE_KEY, String.class); this.eventProperties.put(MapEvent.DOUBLE_VALUE_KEY, Double.class); this.eventProperties.put(MapEvent.CAUSALITY_KEY, Vector.class); this.eventProperties.put(MapEvent.GEOMETRY_KEY, Geometry.class); this.eventProperties.put(MapEvent.SENSORID_KEY, String.class); this.eventProperties.put(MapEvent.THIS_KEY, Map.class); HashMap<String, Object> dtmTypes = dtm.getTypes(); for (String type : dtmTypes.keySet()) { this.eventProperties.put(type, dtmTypes.get(type)); } } @Override public void initialize(IEML eml, IUnitConverter unitConverter) throws Exception { } @Override public void sendEvent(String name, MapEvent event) { sendEvent(name, event, true); } public void sendEvent(String name, MapEvent event, boolean persist) { StringBuilder sb = new StringBuilder(); sb.append("posting new event (" + new Date().getTime() + "):"); sb.append("\n\tname: " + name); logger.debug(sb.toString()); this.epService.getEPRuntime().sendEvent(event, name); if (persist && subMgr.isStreamPersistenceEnabled()) { subMgr.persistEvent(event, name); } } @Override public void registerEvent(String eventName, Map<String, Object> eventProperties) { this.config.addEventType(eventName, eventProperties); this.inputEventDataTypes.put(eventName, this.eventProperties); } @Override public Object getEventDatatype(String eventName) { return null; } @Override public Object getDatatype(String fullPropertyName) { return null; } @Override public String getNewEventName(String patternID, int selectFunctionNumber) { return null; } @Override public Map<String, IPatternSimple> getSimplePatterns() { return null; } @Override public ISubscriptionManager getSubMgr() { return this.subMgr; } @Override public void removeFromEngine() { this.epService.removeAllServiceStateListeners(); this.epService.removeAllStatementStateListeners(); this.epService.destroy(); logger.info(getClass().getSimpleName()+" shutdown complete."); } private void addEPLStatement(EPLFilterInstance eplStmt, String inputName) throws Exception { EPStatement epStatement; /* * register statements at engine. * Try-Catch needed for better SoapFaults for users -> * a statement can fail if the property was not registered * in the DataTypesMap */ epStatement = null; try { logger.info("Register EPL Statement: "+ eplStmt.getStatement()); epStatement = this.epService.getEPAdministrator().createEPL(eplStmt.getStatement()); } catch (EPStatementException e) { logger.warn(e.getMessage()); StringBuilder sb = new StringBuilder(); for (StackTraceElement ste : e.getStackTrace()) { sb.append("\n" + ste.toString()); } logger.warn(sb.toString()); if (e.getMessage().contains("Implicit conversion")) { throw new Exception("Registration of statement failed. Looks like your observerd property was" + " not registered by any publisher.\r\n" + "If you used \"value\" in your Guard, please use \"doubleValue\" or \"stringValue\" instead.\r\n" + "Standard data types:\r\n" + "sensorID = String\r\n" + "stringValue = String\r\n" + "doubleValue = double\r\n" + "startTime = long\r\n" + "endTime = long\r\n" + "observedProperty = String\r\n" + "foiID = String"); } //else throw initial exception throw new Exception("Error in esper statement, possible EPL error: '" + e.getMessage() + "'", e); } //register listener at esper statement if (epStatement != null) { //store epStatements this.epStatements.put(eplStmt.getStatement(), epStatement); epStatement.addListener(new EPLStatementListener(eplStmt, this)); } } public static void main(String[] args) { System.out.println(AbstractFeatureType.class.isAssignableFrom(SamplingPointType.class)); } @Override public void pauseAllStatements() { for (EPStatement eps : this.epStatements.values()) { eps.stop(); } } @Override public void resumeAllStatements() { for (EPStatement eps : this.epStatements.values()) { eps.start(); } } }