package com.esri.geoevent.solutions.processor.timewindowsort; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Observable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.esri.ges.core.component.ComponentException; import com.esri.ges.core.geoevent.FieldDefinition; import com.esri.ges.core.geoevent.FieldType; import com.esri.ges.core.geoevent.GeoEvent; import com.esri.ges.core.geoevent.GeoEventDefinition; import com.esri.ges.core.geoevent.GeoEventPropertyName; import com.esri.ges.core.validation.ValidationException; import com.esri.ges.manager.geoeventdefinition.GeoEventDefinitionManager; import com.esri.ges.messaging.EventDestination; import com.esri.ges.messaging.EventUpdatable; import com.esri.ges.messaging.GeoEventCreator; import com.esri.ges.messaging.GeoEventProducer; import com.esri.ges.messaging.Messaging; import com.esri.ges.messaging.MessagingException; import com.esri.ges.processor.GeoEventProcessorBase; import com.esri.ges.processor.GeoEventProcessorDefinition; public class TimeWindowSortProcessor extends GeoEventProcessorBase implements Runnable, GeoEventProducer, EventUpdatable { private static final Log LOG = LogFactory .getLog(TimeWindowSortProcessor.class); private boolean monitoring = false; private boolean running = false; private Integer interval; private String sortfield; //private SortedMap<Object, ArrayList<GeoEvent>> sorted = new TreeMap<Object, ArrayList<GeoEvent>>(); @SuppressWarnings("rawtypes") private HashMap cache; private GeoEventCreator geoEventCreator; private GeoEventDefinitionManager manager; private Messaging messaging; private GeoEventProducer geoEventProducer; private long timestamp; private Thread t; private FieldType sortedFieldType; public TimeWindowSortProcessor(GeoEventProcessorDefinition definition) throws ComponentException { super(definition); } @Override public void send(GeoEvent geoEvent) throws MessagingException { if (geoEventProducer != null && geoEvent != null) geoEventProducer.send(geoEvent); } @Override public void setId(String id) { super.setId(id); geoEventProducer = messaging .createGeoEventProducer(new EventDestination(id + ":event")); } @Override public void afterPropertiesSet() { interval = (Integer) properties.get("interval").getValue(); sortfield = properties.get("orderby").getValueAsString(); timestamp = System.currentTimeMillis(); String type = properties.get("expectedType").getValueAsString(); if(type.equals("string")) { cache = new HashMap<String, ArrayList<GeoEvent>>(); sortedFieldType = FieldType.String; } if(type.equals("int")) { cache = new HashMap<Integer, ArrayList<GeoEvent>>(); sortedFieldType = FieldType.Integer; } if(type.equals("long")) { cache = new HashMap<Long, ArrayList<GeoEvent>>(); sortedFieldType = FieldType.Long; } if(type.equals("short")) { cache = new HashMap<Short, ArrayList<GeoEvent>>(); sortedFieldType = FieldType.Short; } if(type.equals("double")) { cache = new HashMap<Double, ArrayList<GeoEvent>>(); sortedFieldType = FieldType.Double; } if(type.equals("Float")) { cache = new HashMap<Float, ArrayList<GeoEvent>>(); sortedFieldType = FieldType.Float; } if(type.equals("date")) { cache = new HashMap<Long, ArrayList<GeoEvent>>(); sortedFieldType = FieldType.Date; } this.running = true; } @SuppressWarnings("unchecked") public GeoEvent process(GeoEvent evt) throws Exception { GeoEventDefinition ged = evt.getGeoEventDefinition(); FieldDefinition fd = ged.getFieldDefinition(sortfield); if(fd == null) return null; Object val = null; FieldType type = fd.getType(); if(type != sortedFieldType) { return null; } if(sortedFieldType == FieldType.Date) { Date d = (Date)evt.getField(sortfield); val = (Long)d.getTime(); } else { val = evt.getField(sortfield); } if (cache.containsKey(val)) { ArrayList<GeoEvent> evtList = (ArrayList<GeoEvent>) cache.get(val); evtList.add(evt); cache.put(val, evtList); } else { ArrayList<GeoEvent> evtList = new ArrayList<GeoEvent>(); evtList.add(evt); cache.put(val, evtList); } return null; } @Override public synchronized void validate() throws ValidationException { // Validation Phase ... super.validate(); } @Override public void onServiceStart() { startMonitoring(); } @Override public void onServiceStop() { stopMonitoring(); } @Override public void shutdown() { cache.clear(); super.shutdown(); } @Override public boolean isGeoEventMutator() { return true; } @Override public EventDestination getEventDestination() { return (geoEventProducer != null) ? geoEventProducer .getEventDestination() : null; } @Override public List<EventDestination> getEventDestinations() { return (geoEventProducer != null) ? Arrays.asList(geoEventProducer .getEventDestination()) : new ArrayList<EventDestination>(); } @Override public void disconnect() { if (geoEventProducer != null) geoEventProducer.disconnect(); } @Override public boolean isConnected() { return (geoEventProducer != null) ? geoEventProducer.isConnected() : false; } @Override public String getStatusDetails() { return (geoEventProducer != null) ? geoEventProducer.getStatusDetails() : ""; } @Override public void setup() throws MessagingException { ; } @Override public void init() throws MessagingException { ; } @Override public void update(Observable o, Object arg) { ; } public void setManager(GeoEventDefinitionManager manager) { this.manager = manager; } public void setMessaging(Messaging messaging) { this.messaging = messaging; this.geoEventCreator = messaging.createGeoEventCreator(); } private void startMonitoring() { try { this.monitoring=true; t = new Thread(this); t.start(); } catch (Exception e) { e.printStackTrace(); } } private void stopMonitoring() { this.monitoring=false; cache.clear(); t.interrupt(); } @Override public void run() { while (this.monitoring) { try { if (running) { long now = System.currentTimeMillis(); long testInterval = now - this.timestamp; if (testInterval>=this.interval) { timestamp = now; flush(); } } } catch (Exception e) { } } } @SuppressWarnings({ "unchecked", "rawtypes" }) private void flush() throws MessagingException, InterruptedException { HashMap cacheCopy = null; ArrayList sorted = null; if(sortedFieldType==FieldType.String) { HashMap<String, ArrayList<GeoEvent>> tmpCache = cache; cacheCopy = tmpCache; cache = new HashMap<String, ArrayList<GeoEvent>>(); sorted = new ArrayList<String>(cacheCopy.keySet()); } else if(sortedFieldType==FieldType.Integer) { HashMap<Integer, ArrayList<GeoEvent>> tmpCache = cache; cacheCopy = tmpCache; cache = new HashMap<Integer, ArrayList<GeoEvent>>(); sorted = new ArrayList<Integer>(cacheCopy.keySet()); } else if(sortedFieldType==FieldType.Long) { HashMap<Long, ArrayList<GeoEvent>> tmpCache = cache; cacheCopy = tmpCache; cache = new HashMap<Long, ArrayList<GeoEvent>>(); sorted = new ArrayList<Long>(cacheCopy.keySet()); } else if(sortedFieldType==FieldType.Short) { HashMap<Long, ArrayList<GeoEvent>> tmpCache = cache; cacheCopy = tmpCache; cache = new HashMap<Short, ArrayList<GeoEvent>>(); sorted = new ArrayList<Short>(cacheCopy.keySet()); } else if(sortedFieldType==FieldType.Double) { HashMap<Double, ArrayList<GeoEvent>> tmpCache = cache; cacheCopy = tmpCache; cache = new HashMap<Double, ArrayList<GeoEvent>>(); sorted = new ArrayList<Double>(cacheCopy.keySet()); } else if(sortedFieldType==FieldType.Float) { HashMap<Float, ArrayList<GeoEvent>> tmpCache = cache; cacheCopy = tmpCache; cache = new HashMap<Float, ArrayList<GeoEvent>>(); sorted = new ArrayList<Float>(cacheCopy.keySet()); } else if(sortedFieldType==FieldType.Date) { HashMap<Long, ArrayList<GeoEvent>> tmpCache = cache; cacheCopy = tmpCache; cache = new HashMap<Long, ArrayList<GeoEvent>>(); sorted = new ArrayList<Long>(cacheCopy.keySet()); } Collections.sort(sorted); for(Object k: sorted) { List<GeoEvent> list = (List<GeoEvent>) cacheCopy.get(k); for (GeoEvent msg : list) { msg.setProperty(GeoEventPropertyName.TYPE, "event"); msg.setProperty(GeoEventPropertyName.OWNER_ID, getId()); msg.setProperty(GeoEventPropertyName.OWNER_URI, definition.getUri()); send(msg); t.wait(250); } } cacheCopy.clear(); cacheCopy = null; } }