All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ebay.jetstream.event.JetstreamEvent Maven / Gradle / Ivy

/*******************************************************************************
 *  Copyright © 2012-2015 eBay Software Foundation
 *  This program is dual licensed under the MIT and Apache 2.0 licenses.
 *  Please see LICENSE for more information.
 *******************************************************************************/
package com.ebay.jetstream.event;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.NamedBean;

import com.ebay.jetstream.util.CommonUtils;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoSerializable;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

/**
 * JetstreamEvent is a generalized event structure for wrapping underlying event implementations. The JetstreamEvent type is
 * used throughout the event framework for processing events. There are few distinguished attributes of the event,
 * primarily required for routing and state management. The remaining contents of the events are opaque, with the
 * semantics being defined by the query processing statements. 
*
* The attributes of the events are retrieved via the Map.get method. The attributes specified by EQL are keys directly * into the Map.get method. The key must be a string while the type of the value can vary depending upon the context. * EQL will attempt to make the appropriate type conversions. * * Metadata can be passed in this event between various stages within the process. The metadata will not be serialized over the wire. * * @author [email protected] - derived from original impl created by Dan Pritchett * */ public class JetstreamEvent implements Map, Externalizable, Cloneable, KryoSerializable { private static final long serialVersionUID = -2339580269438201272L; private static final Logger LOGGER = LoggerFactory.getLogger("com.ebay.jetstream.event"); private String[] m_topics; private String[] m_urls; private final Map m_backingMap; private final Map m_metadata = new HashMap(2); public JetstreamEvent() { this(new HashMap()); } public JetstreamEvent(Map map) { this(null, null, map); } public JetstreamEvent(String eventType, EventId id, Map map) { m_backingMap = map != null ? map : new HashMap(); if (eventType != null) setEventType(eventType); if (id != null) setEventId(id); } public void addMetaData(String key, Object value) { m_metadata.put(key, value); } public Object getMetaData(String key) { return m_metadata.get(key); } @Override public void clear() { m_backingMap.clear(); } @Override public boolean containsKey(Object key) { return m_backingMap.containsKey(key); } @Override public boolean containsValue(Object value) { return m_backingMap.containsValue(value); } @Override public Set> entrySet() { return m_backingMap.entrySet(); } @Override public boolean equals(Object o) { return super.equals(o) || m_backingMap.equals(o); } @Override public Object get(Object key) { return m_backingMap.get(key); } /** * The event id is an opaque handle to the event. This is used for state tracking in the ESP system. * * @return the opaque event identifier */ public EventId getEventId() { return (EventId) get(JetstreamReservedKeys.EventId.toString()); } /** * All events must be defined by a type. The ESP system considers an event to be uniquely identified by the * combination of type and identifier. Types are also used in some cases for routing events. */ public String getEventType() { return (String) get(JetstreamReservedKeys.EventType.toString()); } /** * @return A copy of this event with any entries held with a reserved key stripped */ public JetstreamEvent getFilteredEvent() { JetstreamEvent newEvent = new JetstreamEvent(); for (Map.Entry entry : m_backingMap.entrySet()) { if (JetstreamReservedKeys.isReserved(entry.getKey())) continue; newEvent.put(entry.getKey(), entry.getValue()); } return newEvent; } public String[] getForwardingTopics() { return m_topics; } public String[] getForwardingUrls() { return m_urls; } @Override public int hashCode() { return m_backingMap.hashCode(); } @Override public boolean isEmpty() { return m_backingMap.isEmpty(); } @Override public Set keySet() { return m_backingMap.keySet(); } /** * Any caller is required to pass a source Identifier which will be part of the log message. The * implementation of this method must add the event ID to the log message along with the passed source Identifier * * @param source * @return */ public void log(NamedBean source) { LOGGER.debug( "eventSource=" + source.getBeanName() + "&eventId = " + getEventId()); } @Override public Object put(String key, Object value) { return m_backingMap.put(key, value); } @Override public void putAll(Map t) { m_backingMap.putAll(t); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { int mapSize = in.readInt(); for (int i = 0; i < mapSize; i++) m_backingMap.put((String)in.readObject(), (Serializable) in.readObject()); } @Override public Object remove(Object key) { return m_backingMap.remove(key); } public void setEventId(EventId id) { put(JetstreamReservedKeys.EventId.toString(), id); } public void setEventType(String type) { put(JetstreamReservedKeys.EventType.toString(), type); } public void setForwardingTopics(String[] topics) { m_topics = topics; } public void setForwardingUrls(String[] urls) { m_urls = urls; } @Override public int size() { return m_backingMap.size(); } @Override public String toString() { return m_backingMap.toString(); } @Override public Collection values() { return m_backingMap.values(); } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeInt(m_backingMap.size()); Iterator> itr = m_backingMap.entrySet().iterator(); while (itr.hasNext()) { Map.Entry entry1 = itr.next(); out.writeObject(entry1.getKey()); out.writeObject(entry1.getValue()); } } public JetstreamEvent clone() throws CloneNotSupportedException { JetstreamEvent event; try { event = CommonUtils.getDeepCopy(this); } catch (InstantiationException e) { return null; } catch (IllegalAccessException e) { return null; } event.m_metadata.putAll(this.m_metadata); if (this.m_urls != null) { event.m_urls = new String[this.m_urls.length]; System.arraycopy(this.m_urls, 0, event.m_urls, 0, this.m_urls.length); } if (this.m_topics != null) { event.m_topics = new String[this.m_topics.length]; System.arraycopy(this.m_topics, 0, event.m_topics, 0, this.m_topics.length); } return event; } @Override public void write(Kryo kryo, Output out) { out.writeInt(m_backingMap.size(), true); Iterator> itr = m_backingMap.entrySet().iterator(); while (itr.hasNext()) { Map.Entry entry1 = itr.next(); out.writeString(entry1.getKey()); kryo.writeClassAndObject(out, entry1.getValue()); } } @Override public void read(Kryo kryo, Input in) { int mapSize = in.readInt(true); for (int i = 0; i < mapSize; i++) { m_backingMap.put(in.readString(), kryo.readClassAndObject(in)); } } }