package org.oliot.epcis.service.capture; import java.io.InputStream; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import javax.xml.bind.JAXB; import org.bson.BsonBoolean; import org.bson.BsonDateTime; import org.bson.BsonDocument; import org.bson.BsonDouble; import org.bson.BsonInt32; import org.bson.BsonInt64; import org.bson.BsonString; import org.bson.BsonValue; import org.oliot.epcis.configuration.Configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.context.ServletContextAware; import org.oliot.epcis.converter.mongodb.ECReportWriteConverter; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; import org.oliot.epcis.service.subscription.TriggerEngine; import org.oliot.model.ale.ECReport; import org.oliot.model.ale.ECReportMemberField; import org.oliot.model.ale.ECReports; import org.oliot.model.ale.ECReportGroupListMemberExtension.FieldList; /** * Copyright (C) 2014-2017 Jaewook Byun * * This project is part of Oliot open source (http://oliot.org). Oliot EPCIS * v1.2.x is Java Web Service complying with Electronic Product Code Information * Service (EPCIS) v1.2. * * @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 */ @Controller @RequestMapping("/ECReportCapture") public class ECReportCapture implements ServletContextAware { @Autowired ServletContext servletContext; @Override public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } /** * ECReportCapture API is a convenient method to convert ECReport into * ObjectEvent with the following additional parameters * * @param inputString: * ECReport * @param eventTimeZoneOffset * @param action * @param bizStep * @param disposition * @param readPoint * @param bizLocation * @return */ @RequestMapping(method = RequestMethod.POST) @ResponseBody public ResponseEntity<?> post(@RequestBody String inputString, @RequestParam(required = false) String eventTimeZoneOffset, @RequestParam(required = false) String action, @RequestParam(required = false) String bizStep, @RequestParam(required = false) String disposition, @RequestParam(required = false) String readPoint, @RequestParam(required = false) String bizLocation) { Configuration.logger.info(" ECReport Capture Started.... "); ECReports ecReports = null; if (Configuration.isCaptureVerfificationOn == true) { InputStream validateStream = CaptureUtil.getXMLDocumentInputStream(inputString); boolean isValidated = CaptureUtil.validate(validateStream, Configuration.wsdlPath + "/EPCglobal-ale-1_1-ale.xsd"); if (isValidated == false) { Configuration.logger.info(" ECReport : Verification Failed "); return new ResponseEntity<>(new String("[Error] Input EC Report does not comply the standard schema"), HttpStatus.BAD_REQUEST); } Configuration.logger.info(" ECReport : Validated "); } InputStream stream = CaptureUtil.getXMLDocumentInputStream(inputString); ecReports = JAXB.unmarshal(stream, ECReports.class); String msg = capture(ecReports, eventTimeZoneOffset, action, bizStep, disposition, readPoint, bizLocation); if (msg == null) { Configuration.logger.info(" ECReport : Captured "); return new ResponseEntity<>(new String(), HttpStatus.OK); } else { Configuration.logger.info(" ECReport : Some errors occurred "); return new ResponseEntity<>(msg, HttpStatus.BAD_REQUEST); } } private Map<String, BsonValue> getExtensionMap(List<ECReportMemberField> fields) { Map<String, BsonValue> extMap = new HashMap<String, BsonValue>(); for (int l = 0; l < fields.size(); l++) { ECReportMemberField field = fields.get(l); String key = field.getName(); String value = field.getValue(); String[] valArr = value.split("\\^"); if (valArr.length != 2) { extMap.put(key, new BsonString(value)); continue; } try { String type = valArr[1]; if (type.equals("int")) { extMap.put(key, new BsonInt32(Integer.parseInt(valArr[0]))); } else if (type.equals("long")) { extMap.put(key, new BsonInt64(Long.parseLong(valArr[0]))); } else if (type.equals("double")) { extMap.put(key, new BsonDouble(Double.parseDouble(valArr[0]))); } else if (type.equals("boolean")) { extMap.put(key, new BsonBoolean(Boolean.parseBoolean(valArr[0]))); } else if (type.equals("dateTime")) { extMap.put(key, new BsonDateTime(Long.parseLong(valArr[0]))); } else { extMap.put(key, new BsonString(valArr[0])); } } catch (NumberFormatException e) { extMap.put(key, new BsonString(valArr[0])); } } return extMap; } private String capture(ECReports ecReports, String eventTimeZoneOffset, String action, String bizStep, String disposition, String readPoint, String bizLocation) { // Event Time in timemillis , type long long eventTime = ecReports.getCreationDate().toGregorianCalendar().getTimeInMillis(); // Record Time long recordTimeMillis = new GregorianCalendar().getTimeInMillis(); List<ECReport> ecReportList = ecReports.getReports().getReport(); try { ecReportList.parallelStream().filter(ecReport -> ecReport.getGroup() != null).forEach(ecReport -> { ecReport.getGroup().parallelStream().filter(ecReportGroup -> ecReportGroup.getGroupList() != null) .forEach(ecReportGroup -> { ecReportGroup.getGroupList().getMember().parallelStream() .filter(member -> (member.getExtension() != null) && (member.getExtension().getFieldList() != null)) .forEach(member -> { String epcString = member.getEpc().getValue(); FieldList fieldList = member.getExtension().getFieldList(); List<ECReportMemberField> fields = fieldList.getField(); Map<String, BsonValue> extMap = getExtensionMap(fields); BsonDocument dbo = ECReportWriteConverter.convert(epcString, eventTime, eventTimeZoneOffset, recordTimeMillis, action, bizStep, disposition, readPoint, bizLocation, extMap); MongoCollection<BsonDocument> collection = Configuration.mongoDatabase .getCollection("EventData", BsonDocument.class); if (Configuration.isTriggerSupported == true) { TriggerEngine.examineAndFire("ObjectEvent", dbo); } collection.insertOne(dbo); }); }); }); } catch (MongoException ex) { return ex.toString(); } return null; } }