package com.esri.geoevent.solutions.processor.eventjoiner;
/*
* #%L
* FieldGrouperProcessor.java - fieldgrouper - Esri - 2013
* org.codehaus.mojo-license-maven-plugin-1.5
* $Id: update-file-header-config.apt.vm 17764 2012-12-12 10:22:04Z tchemit $
* $HeadURL: https://svn.codehaus.org/mojo/tags/license-maven-plugin-1.5/src/site/apt/examples/update-file-header-config.apt.vm $
* %%
* Copyright (C) 2013 - 2014 Esri
* %%
* 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.
* #L%
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.esri.ges.core.ConfigurationException;
import com.esri.ges.core.component.ComponentException;
import com.esri.ges.core.geoevent.DefaultFieldDefinition;
import com.esri.ges.core.geoevent.DefaultGeoEventDefinition;
import com.esri.ges.core.geoevent.FieldDefinition;
import com.esri.ges.core.geoevent.FieldException;
import com.esri.ges.core.geoevent.FieldGroup;
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.manager.geoeventdefinition.GeoEventDefinitionManager;
import com.esri.ges.manager.geoeventdefinition.GeoEventDefinitionManagerException;
import com.esri.ges.messaging.GeoEventCreator;
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 EventJoinerProcessor extends GeoEventProcessorBase {
Messaging messaging;
GeoEventDefinitionManager manager;
Map<String, TrackRecord> recordCache;
private static final Log LOG = LogFactory
.getLog(EventJoinerProcessor.class);
private String indefs;
private String joinfield;
private String outdefname;
private List<String> defList;
private Map<String, FieldItem> fldMgr;
private final Double THRESHOLD_MILLISEC = 100000.0;
private Boolean createNewDef;
private GeoEventDefinition outDef = null;
class TrackRecord {
String id;
List<HashMap<String, GeoEvent>> records = new ArrayList<HashMap<String, GeoEvent>>();
public void setId(String id) {
this.id = id;
}
}
class FieldItem {
String id;
Integer count = 0;
FieldType type;
ArrayList<String> tags = new ArrayList<String>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public FieldType getType() {
return type;
}
public void setType(FieldType type) {
this.type = type;
}
public void appendTags(List<String> inTags) {
for (String t : inTags) {
if (!tags.contains(t)) {
tags.add(t);
}
}
}
public ArrayList<String> getTags() {
return tags;
}
public Integer getCount() {
return count;
}
public void advance() {
++count;
}
}
public EventJoinerProcessor(GeoEventProcessorDefinition definition)
throws ComponentException {
super(definition);
}
public void setGeoEventDefinitionManager(GeoEventDefinitionManager gedm) {
manager = gedm;
}
public void setMessaging(Messaging m) {
messaging = m;
}
@Override
public synchronized void afterPropertiesSet() {
indefs = properties.get("indefs").getValueAsString();
String[] defs = indefs.split(",", 0);
defList = Arrays.asList(defs);
outdefname = properties.get("outdef").getValueAsString();
joinfield = properties.get("join").getValueAsString();
if(fldMgr!=null)
{
fldMgr.clear();
fldMgr = null;
}
if(recordCache!=null)
{
recordCache.clear();
recordCache = null;
}
createNewDef = true;
}
@Override
public void shutdown() {
if(fldMgr!=null)
{
fldMgr.clear();
fldMgr = null;
}
if(recordCache!=null)
{
recordCache.clear();
recordCache = null;
}
createNewDef = true;
super.shutdown();
}
public GeoEvent process(GeoEvent evt) throws Exception {
try {
if(recordCache == null)
recordCache = new HashMap<String, TrackRecord>();
String curDefName = evt.getGeoEventDefinition().getName();
if (!defList.contains(curDefName))
return null;
String uid = evt.getField(joinfield).toString();
if (!recordCache.containsKey(uid)) {
TrackRecord tr = new TrackRecord();
tr.setId(uid);
HashMap<String, GeoEvent> joinEvents = new HashMap<String, GeoEvent>();
joinEvents.put(curDefName, evt);
tr.records.add(joinEvents);
recordCache.put(uid, tr);
} else {
TrackRecord tr = recordCache.get(uid);
Boolean exitLoop = false;
while (!exitLoop) {
for (HashMap<String, GeoEvent> rec : tr.records) {
if (!rec.containsKey(curDefName)) {
rec.put(curDefName, evt);
if (rec.size() == defList.size()) {
if (createNewDef) {
ConstructGeoEventDef(rec);
createNewDef = false;
}
return CreateGeoEvent(rec);
}
exitLoop = true;
}
}
exitLoop = true;
}
HashMap<String, GeoEvent> joinEvents = new HashMap<String, GeoEvent>();
joinEvents.put(curDefName, evt);
tr.records.add(joinEvents);
}
return null;
} catch (Exception e) {
LOG.error(e.getMessage());
throw (e);
}
}
private void ConstructGeoEventDef(HashMap<String, GeoEvent> rec)
throws Exception {
try {
fldMgr = new HashMap<String, FieldItem>();
Set<String> keys = rec.keySet();
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
String key = it.next();
GeoEvent evt = rec.get(key);
List<FieldDefinition> fldDefs = evt.getGeoEventDefinition()
.getFieldDefinitions();
for (FieldDefinition fldDef : fldDefs) {
String fldName = fldDef.getName();
FieldType type = fldDef.getType();
if (fldMgr.containsKey(fldName)) {
FieldItem item = fldMgr.get(fldName);
if (!fldDef.getTags().isEmpty())
item.appendTags(fldDef.getTags());
item.advance();
} else {
FieldItem item = new FieldItem();
item.setId(fldName);
item.setType(type);
if (!fldDef.getTags().isEmpty())
item.appendTags(fldDef.getTags());
item.advance();
fldMgr.put(fldName, item);
}
}
}
Set<String> fldKeys = fldMgr.keySet();
Iterator<String> fldIt = fldKeys.iterator();
List<FieldDefinition> mergedFldDef = new ArrayList<FieldDefinition>();
while (fldIt.hasNext()) {
String fldName = fldIt.next();
FieldItem item = fldMgr.get(fldName);
FieldType type;
FieldType fldtype = item.getType();
ArrayList<String> tags = item.getTags();
if (tags.contains("TRACK_ID")) {
tags.remove("TRACK_ID");
}
FieldDefinition fd = null;
if (item.getCount() > 1) {
if (fldName.equals(joinfield)) {
tags.add("JOIN_ID");
tags.add("TRACK_ID");
String[]tagarr = new String[tags.size()];
tagarr = tags.toArray(tagarr);
fd = new DefaultFieldDefinition(fldName, fldtype,
(String[]) tagarr);
} else {
type = FieldType.Group;
String[] groupedTag = { "GROUPED" };
fd = new DefaultFieldDefinition(fldName, type,
groupedTag);
for (Integer i = 0; i < item.getCount(); ++i) {
String childName = defList.get(i);
FieldDefinition child = null;
if (tags.isEmpty()) {
child = new DefaultFieldDefinition(childName,
fldtype);
} else {
String[]tagarr = new String[tags.size()];
tagarr = tags.toArray(tagarr);
child = new DefaultFieldDefinition(childName,
fldtype, tagarr);
}
fd.addChild(child);
}
}
} else {
type = fldtype;
if (!tags.isEmpty()) {
fd = new DefaultFieldDefinition(fldName, fldtype,
(String[]) tags.toArray());
} else {
fd = new DefaultFieldDefinition(fldName, fldtype);
}
}
mergedFldDef.add(fd);
}
outDef = new DefaultGeoEventDefinition();
outDef.setFieldDefinitions(mergedFldDef);
outDef.setName(outdefname);
outDef.setOwner(definition.getUri().toString());
Collection<GeoEventDefinition> eventDefs = manager
.searchGeoEventDefinitionByName(outdefname);
Iterator<GeoEventDefinition> eventDefIt = eventDefs.iterator();
while (eventDefIt.hasNext()) {
GeoEventDefinition currentDef = eventDefIt.next();
manager.deleteGeoEventDefinition(currentDef.getGuid());
}
manager.addGeoEventDefinition(outDef);
} catch (ConfigurationException e) {
LOG.error(e.getMessage());
throw (e);
} catch (GeoEventDefinitionManagerException e) {
LOG.error(e.getMessage());
throw (e);
} catch (Exception e) {
LOG.error(e.getMessage());
throw (e);
}
}
private GeoEvent CreateGeoEvent(HashMap<String, GeoEvent> rec)
throws Exception {
try {
GeoEventCreator creator = messaging.createGeoEventCreator();
GeoEvent evt = creator.create(outDef.getGuid());
Set<String> keys = rec.keySet();
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
GeoEvent ge = rec.get(it.next());
List<FieldDefinition> fldDefs = ge.getGeoEventDefinition()
.getFieldDefinitions();
for (FieldDefinition fd : fldDefs) {
String name = fd.getName();
FieldItem item = fldMgr.get(name);
if (item.getCount() > 1) {
if(name.equals(joinfield))
{
evt.setField(joinfield, ge.getField(joinfield));
}
else
{
String gedname = ge.getGeoEventDefinition().getName();
String groupName = name + "." + gedname;
evt.setField(groupName, ge.getField(name));
}
} else {
evt.setField(name, ge.getField(name));
}
}
}
evt.setProperty(GeoEventPropertyName.TYPE, "event");
evt.setProperty(GeoEventPropertyName.OWNER_ID, getId());
evt.setProperty(GeoEventPropertyName.OWNER_URI, definition.getUri());
return evt;
} catch (MessagingException e) {
LOG.error(e.getMessage());
throw (e);
} catch (FieldException e) {
LOG.error(e.getMessage());
throw (e);
} catch (Exception e) {
LOG.error(e.getMessage());
throw (e);
}
}
}