package org.oliot.epcis.service.subscription;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXB;
import org.apache.log4j.Level;
import org.bson.BsonDocument;
import org.bson.BsonString;
import org.oliot.epcis.configuration.Configuration;
import org.oliot.epcis.service.query.mongodb.MongoQueryService;
import org.oliot.model.epcis.EPCISQueryDocumentType;
import org.oliot.model.epcis.ImplementationException;
import org.oliot.model.epcis.QueryResults;
import org.oliot.model.epcis.QueryTooLargeException;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import com.mongodb.client.MongoCollection;
/**
* Copyright (C) 2014-2016 Jaewook Byun
*
* This project is part of Oliot (oliot.org), pursuing the implementation of
* Electronic Product Code Information Service(EPCIS) v1.1 specification in
* EPCglobal.
* [http://www.gs1.org/gsmp/kc/epcglobal/epcis/epcis_1_1-standard-20140520.pdf]
*
*
* @author Jaewook Byun, Ph.D student
*
* Korea Advanced Institute of Science and Technology (KAIST)
*
* Real-time Embedded System Laboratory(RESL)
*
* bjw0829@kaist.ac.kr, bjw0829@gmail.com
*/
public class MongoSubscriptionTask implements Job {
/**
* Whenever execute method invoked according to the cron expression Query
* the database and send the result to the destination.
*/
@SuppressWarnings("unchecked")
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap map = context.getJobDetail().getJobDataMap();
String queryName = map.getString("queryName");
String subscriptionID = map.getString("subscriptionID");
String dest = map.getString("dest");
// String cronExpression = map.getString("cronExpression");
boolean ignoreReceivedEvent = map.getBoolean("ignoreReceivedEvent");
boolean reportIfEmpty = map.getBoolean("reportIfEmpty");
String initialRecordTime = map.getString("initialRecordTime");
String eventType = map.getString("eventType");
String GE_eventTime = map.getString("GE_eventTime");
String LT_eventTime = map.getString("LT_eventTime");
String GE_recordTime = map.getString("GE_recordTime");
String LT_recordTime = map.getString("LT_recordTime");
String EQ_action = map.getString("EQ_action");
String EQ_bizStep = map.getString("EQ_bizStep");
String EQ_disposition = map.getString("EQ_disposition");
String EQ_readPoint = map.getString("EQ_readPoint");
String WD_readPoint = map.getString("WD_readPoint");
String EQ_bizLocation = map.getString("EQ_bizLocation");
String WD_bizLocation = map.getString("WD_bizLocation");
String EQ_transformationID = map.getString("EQ_transformationID");
String MATCH_epc = map.getString("MATCH_epc");
String MATCH_parentID = map.getString("MATCH_parentID");
String MATCH_inputEPC = map.getString("MATCH_inputEPC");
String MATCH_outputEPC = map.getString("MATCH_outputEPC");
String MATCH_anyEPC = map.getString("MATCH_anyEPC");
String MATCH_epcClass = map.getString("MATCH_epcClass");
String MATCH_inputEPCClass = map.getString("MATCH_inputEPCClass");
String MATCH_outputEPCClass = map.getString("MATCH_outputEPCClass");
String MATCH_anyEPCClass = map.getString("MATCH_anyEPCClass");
String EQ_quantity = map.getString("EQ_quantity");
String GT_quantity = map.getString("GT_quantity");
String GE_quantity = map.getString("GE_quantity");
String LT_quantity = map.getString("LT_quantity");
String LE_quantity = map.getString("LE_quantity");
String orderBy = map.getString("orderBy");
String orderDirection = map.getString("orderDirection");
String eventCountLimit = map.getString(" eventCountLimit");
String maxEventCount = map.getString("maxEventCount");
String format = map.getString("format");
Map<String, String> paramMap = (Map<String, String>) map.get("paramMap");
// InitialRecordTime limits recordTime
if (ignoreReceivedEvent == true) {
try {
GE_recordTime = initialRecordTime;
GregorianCalendar cal = new GregorianCalendar();
Date curTime = cal.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
initialRecordTime = sdf.format(curTime);
updateInitialRecordTime(subscriptionID, initialRecordTime);
JobDetail detail = context.getJobDetail();
detail.getJobDataMap().put("initialRecordTime", initialRecordTime);
MongoSubscription.sched.addJob(detail, true, true);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
MongoQueryService queryService = new MongoQueryService();
String pollResult = queryService.poll(queryName, eventType, GE_eventTime, LT_eventTime, GE_recordTime,
LT_recordTime, EQ_action, EQ_bizStep, EQ_disposition, EQ_readPoint, WD_readPoint, EQ_bizLocation,
WD_bizLocation, EQ_transformationID, MATCH_epc, MATCH_parentID, MATCH_inputEPC, MATCH_outputEPC,
MATCH_anyEPC, MATCH_epcClass, MATCH_inputEPCClass, MATCH_outputEPCClass, MATCH_anyEPCClass, EQ_quantity,
GT_quantity, GE_quantity, LT_quantity, LE_quantity, orderBy, orderDirection, eventCountLimit,
maxEventCount, null, false, false, null, null, null, null, null, format, null, null, paramMap);
String resultString = "";
if (format == null || format.equals("XML")) {
EPCISQueryDocumentType resultXML = JAXB.unmarshal(new StringReader(pollResult),
EPCISQueryDocumentType.class);
if (resultXML != null && resultXML.getEPCISBody() != null
&& resultXML.getEPCISBody().getQueryTooLargeException() != null) {
QueryTooLargeException e = resultXML.getEPCISBody().getQueryTooLargeException();
StringWriter sw = new StringWriter();
JAXB.marshal(e, sw);
resultString = sw.toString();
} else if (resultXML != null && resultXML.getEPCISBody() != null
&& resultXML.getEPCISBody().getImplementationException() != null) {
ImplementationException e = resultXML.getEPCISBody().getImplementationException();
StringWriter sw = new StringWriter();
JAXB.marshal(e, sw);
resultString = sw.toString();
} else if (resultXML != null && resultXML.getEPCISBody() != null
&& resultXML.getEPCISBody().getQueryResults() != null
&& resultXML.getEPCISBody().getQueryResults().getResultsBody() != null) {
List<Object> checkList = resultXML.getEPCISBody().getQueryResults().getResultsBody().getEventList()
.getObjectEventOrAggregationEventOrQuantityEvent();
if (reportIfEmpty == false) {
if (checkList == null || checkList.size() == 0) {
// Do not report if reportIfEmpty is true
return;
}
}
QueryResults queryResults = new QueryResults();
queryResults.setQueryName(queryName);
queryResults.setResultsBody(resultXML.getEPCISBody().getQueryResults().getResultsBody());
StringWriter sw = new StringWriter();
JAXB.marshal(queryResults, sw);
resultString = sw.toString();
}
} else {
resultString = pollResult;
}
try {
URL url = new URL(dest);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-Length", "" + Integer.toString(resultString.getBytes().length));
conn.setRequestProperty("Content-Type", "application/xml; charset=utf-8");
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(resultString);
wr.flush();
wr.close();
int x = conn.getResponseCode();
System.out.println(x);
conn.disconnect();
} catch (MalformedURLException e) {
Configuration.logger.log(Level.ERROR, e.toString());
} catch (IOException e) {
Configuration.logger.log(Level.ERROR, e.toString());
}
}
private void updateInitialRecordTime(String subscriptionID, String initialRecordTime) {
MongoCollection<BsonDocument> collection = Configuration.mongoDatabase.getCollection("Subscription",
BsonDocument.class);
BsonDocument subscription = collection.find(new BsonDocument("subscriptionID", new BsonString(subscriptionID)))
.first();
if (subscription != null) {
collection.findOneAndReplace(new BsonDocument("subscriptionID", new BsonString(subscriptionID)),
subscription);
}
Configuration.logger.log(Level.INFO,
"InitialRecordTime of Subscription ID: " + subscriptionID + " is updated to DB. ");
}
}