package com.produban.openbus.storm;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.wso2.siddhi.core.SiddhiManager;
import org.wso2.siddhi.core.config.SiddhiConfiguration;
import org.wso2.siddhi.core.event.Event;
import org.wso2.siddhi.core.query.output.QueryCallback;
import org.wso2.siddhi.core.stream.input.InputHandler;
import backtype.storm.Config;
import backtype.storm.Constants;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.BasicOutputCollector;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseBasicBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
public class SiddhiBolt extends BaseBasicBolt {
private static final long serialVersionUID = 1L;
private static Logger LOG = Logger.getLogger(SiddhiBolt.class);
private transient SiddhiManager siddhiManager;
private BasicOutputCollector collector;
private boolean useDefaultAsStreamName = true;
private String componentID;
private final static String SEPARADOR = "\001";
@Override
public Map<String, Object> getComponentConfiguration() {
Config conf = new Config();
int tickFrequencyInSeconds = 10;
conf.put(Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS, tickFrequencyInSeconds);
return conf;
}
public void init() {
SiddhiConfiguration configuration = new SiddhiConfiguration();
this.siddhiManager = new SiddhiManager(configuration);
}
public SiddhiBolt() {
init();
}
@Override
public void execute(Tuple tuple, BasicOutputCollector collectorAux) {
try {
this.collector = collectorAux;
if (siddhiManager == null) {
init();
}
String queryID = null;
InputHandler inputHandler = null;
JSONObject jsonObject = getJson();
String operation = (String) jsonObject.get("operation");
LOG.info(operation);
String define = (String) jsonObject.get("define");
LOG.info(define);
final String streamID = define.split(" ")[2];
if (isTickTuple(tuple)) {
if (streamID != null) {
if (operation.equals("insert")) {
if (siddhiManager.getStreamDefinition(streamID) == null) {
siddhiManager.defineStream(define);
}
}
}
else {
if (operation.equals("delete")) {
siddhiManager.removeStream(streamID);
}
}
String query = (String) jsonObject.get("query");
LOG.info(query);
if (operation.equals("delete")) {
siddhiManager.removeQuery(query);
}
else if (operation.equals("insert")) {
if (query != null) {
siddhiManager.removeQuery(query);
}
queryID = siddhiManager.addQuery(query);
}
siddhiManager.addCallback(queryID, new QueryCallback() {
@Override
public void receive(long timeStamp, Event[] inEvents, Event[] removeEvents) {
if (inEvents != null) {
for (Event e : inEvents) {
collector.emit(new Values(e.getStreamId(), e.getData()));
}
}
if (removeEvents != null) {
for (Event e : removeEvents) {
collector.emit(new Values(e.getStreamId(), e.getData()));
}
}
}
});
}
else {
inputHandler = siddhiManager.getInputHandler(streamID);
if (inputHandler != null) {
inputHandler.send(tuple.toString().split(this.SEPARADOR));
}
else {
throw new RuntimeException("Input handler for stream " + streamID + " not found");
}
}
}
catch (InterruptedException e) {
LOG.error(e);
}
catch (Exception e) {
LOG.error(e);
}
}
private static boolean isTickTuple(Tuple tuple) {
return tuple.getSourceComponent().equals(Constants.SYSTEM_COMPONENT_ID)
&& tuple.getSourceStreamId().equals(Constants.SYSTEM_TICK_STREAM_ID);
}
private InputStreamReader callRestClient() throws ClientProtocolException, IOException {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://localhost");
HttpResponse response = client.execute(request);
return new InputStreamReader(response.getEntity().getContent());
}
private JSONObject getJson() throws Exception {
JSONParser parser = new JSONParser();
Object obj = parser.parse(callRestClient());
JSONObject jsonObject = (JSONObject) obj;
return jsonObject;
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("streamID", "datos"));
}
public BasicOutputCollector getCollector() {
return collector;
}
public void setUseDefaultAsStreamName(boolean useDefaultAsStreamName) {
this.useDefaultAsStreamName = useDefaultAsStreamName;
}
public boolean isUseDefaultAsStreamName() {
return useDefaultAsStreamName;
}
@Override
public void prepare(Map stormConf, TopologyContext context) {
super.prepare(stormConf, context);
this.componentID = context.getThisComponentId();
}
}