package ch.uzh.ifi.ddis.ifp.streams;
/*
* #%L
* Esper implementation of Streams Nodes
* %%
* Copyright (C) 2013 University of Zurich, Department of Informatics
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
import java.io.Serializable;
import java.util.List;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import stream.Data;
import stream.data.DataFactory;
import stream.io.Sink;
import com.espertech.esper.client.UpdateListener;
/**
* <p>
* The subscriber outputs data from an
* {@link com.espertech.esper.client.EPStatement} to a Streams
* {@link stream.io.QueueService}.
* </p>
* <p>
* A subscriber object directly binds query results to a Java object. According
* the the <a href=
* "http://esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html_single/#api-admin-subscriber"
* > Esper documentation</a> a subscriber is much faster than an
* {@link UpdateListener}.
* </p>
* <p>
* This class provides a generic implementation of a subscriber. As such it
* needs to know (i) the Streams sink it shall write data to and (ii) the keys
* for the Streams {@link Data} item. The subscriber follows no implementation
* pattern but requiring the subscriber class to implement an update method.
* This {@link #update(Object...)} method is simply requires to have an array of
* or a fixed number of objects as parameters. To have a generic implementation,
* we need to know the keys (in the extreme only the number of parameters) for
* the Streams {@link Data} item.
* </p>
*
* @author Thomas Scharrenbach
* @version 0.0.2
* @since 0.0.1
*
*/
public class EsperStatementSubscriber {
private final Logger _log = LoggerFactory
.getLogger(EsperStatementSubscriber.class);
private final Sink[] _sinksList;
private final String[] _keys;
/**
* <p>
* Create a new subscriber with the specified keys writing to the specified
* {@link Sink}.
* </p>
*
* @param sinksList
* @param keys
*
* @version 0.2.2
* @since 0.0.1
*/
public EsperStatementSubscriber(List<Sink> sinksList, String[] keys) {
_sinksList = sinksList.toArray(new Sink[sinksList.size()]);
_keys = new String[keys.length];
for (int i = 0; i < keys.length; ++i) {
// TODO replace this by a regular expression.
_keys[i] = keys[i].replace('`', ' ').trim();
}
}
/**
*
* @param values
* the values of an Esper event.
* @throws Exception
*/
public void update(Object... values) throws Exception {
synchronized (_sinksList) {
Data item = DataFactory.create();
for (int i = 0; i < values.length; ++i) {
item.put(_keys[i], (Serializable) values[i]);
}
item.put("@stream", _sinksList[0].getId());
_log.debug("Updating subscriber {}, item {}", values, item);
_sinksList[0].write(item);
for (int s = 1; s < _sinksList.length; ++s) {
Data result = stream.data.DataFactory.copy(item);
result.put("@stream", _sinksList[s].getId());
_log.debug("Updating subscriber {}, item {}", values, result);
_sinksList[s].write(result);
}
}
}
/**
*
* @param values
* the values of an Esper event.
* @throws Exception
*/
public void update(java.util.Map<String, Serializable> values)
throws Exception {
synchronized (_sinksList) {
Data item = DataFactory.create();
for (Entry<String, Serializable> entry : values.entrySet()) {
item.put(entry.getKey().replace('`', ' ').trim(),
entry.getValue());
}
item.put("@stream", _sinksList[0].getId());
_log.debug("Updating subscriber {}, item {}", values, item);
_sinksList[0].write(item);
for (int s = 1; s < _sinksList.length; ++s) {
Data result = stream.data.DataFactory.copy(item);
result.put("@stream", _sinksList[s].getId());
_log.debug("Updating subscriber {}, item {}", values, result);
_sinksList[s].write(result);
}
}
}
}