1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.fosstrak.epcis.repository.query;
22
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.sql.SQLException;
26 import java.text.ParseException;
27 import java.util.ArrayList;
28 import java.util.Calendar;
29 import java.util.Collections;
30 import java.util.Comparator;
31 import java.util.GregorianCalendar;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36
37 import javax.servlet.ServletContext;
38 import javax.sql.DataSource;
39 import javax.xml.datatype.XMLGregorianCalendar;
40
41 import org.fosstrak.epcis.model.ArrayOfString;
42 import org.fosstrak.epcis.model.DuplicateSubscriptionException;
43 import org.fosstrak.epcis.model.EPCISEventType;
44 import org.fosstrak.epcis.model.EventListType;
45 import org.fosstrak.epcis.model.ImplementationException;
46 import org.fosstrak.epcis.model.ImplementationExceptionSeverity;
47 import org.fosstrak.epcis.model.InvalidURIException;
48 import org.fosstrak.epcis.model.NoSuchNameException;
49 import org.fosstrak.epcis.model.NoSuchSubscriptionException;
50 import org.fosstrak.epcis.model.QueryParam;
51 import org.fosstrak.epcis.model.QueryParameterException;
52 import org.fosstrak.epcis.model.QueryParams;
53 import org.fosstrak.epcis.model.QueryResults;
54 import org.fosstrak.epcis.model.QueryResultsBody;
55 import org.fosstrak.epcis.model.QuerySchedule;
56 import org.fosstrak.epcis.model.QueryTooLargeException;
57 import org.fosstrak.epcis.model.SubscribeNotPermittedException;
58 import org.fosstrak.epcis.model.SubscriptionControls;
59 import org.fosstrak.epcis.model.SubscriptionControlsException;
60 import org.fosstrak.epcis.model.ValidationException;
61 import org.fosstrak.epcis.model.VocabularyListType;
62 import org.fosstrak.epcis.repository.EpcisConstants;
63 import org.fosstrak.epcis.repository.EpcisQueryControlInterface;
64 import org.fosstrak.epcis.repository.query.SimpleEventQueryDTO.EventQueryParam;
65 import org.fosstrak.epcis.repository.query.SimpleEventQueryDTO.Operation;
66 import org.fosstrak.epcis.repository.query.SimpleEventQueryDTO.OrderDirection;
67 import org.fosstrak.epcis.soap.DuplicateSubscriptionExceptionResponse;
68 import org.fosstrak.epcis.soap.ImplementationExceptionResponse;
69 import org.fosstrak.epcis.soap.InvalidURIExceptionResponse;
70 import org.fosstrak.epcis.soap.NoSuchNameExceptionResponse;
71 import org.fosstrak.epcis.soap.NoSuchSubscriptionExceptionResponse;
72 import org.fosstrak.epcis.soap.QueryParameterExceptionResponse;
73 import org.fosstrak.epcis.soap.QueryTooComplexExceptionResponse;
74 import org.fosstrak.epcis.soap.QueryTooLargeExceptionResponse;
75 import org.fosstrak.epcis.soap.SecurityExceptionResponse;
76 import org.fosstrak.epcis.soap.SubscribeNotPermittedExceptionResponse;
77 import org.fosstrak.epcis.soap.SubscriptionControlsExceptionResponse;
78 import org.fosstrak.epcis.soap.ValidationExceptionResponse;
79 import org.fosstrak.epcis.utils.TimeParser;
80 import org.apache.commons.collections.CollectionUtils;
81 import org.apache.commons.collections.Transformer;
82 import org.apache.commons.logging.Log;
83 import org.apache.commons.logging.LogFactory;
84 import org.w3c.dom.Element;
85 import org.w3c.dom.Node;
86 import org.w3c.dom.NodeList;
87
88
89
90
91
92
93
94
95
96
97
98 public class QueryOperationsModule implements EpcisQueryControlInterface {
99
100 private static final Log LOG = LogFactory.getLog(QueryOperationsModule.class);
101
102
103
104
105 private static final String STD_VERSION = "1.0";
106
107
108
109
110 private static final List<String> QUERYNAMES;
111 static {
112 QUERYNAMES = new ArrayList<String>(2);
113 QUERYNAMES.add("SimpleEventQuery");
114 QUERYNAMES.add("SimpleMasterDataQuery");
115 }
116
117
118
119
120
121
122 private String serviceVersion = "";
123
124
125
126
127 private int maxQueryRows;
128
129
130
131
132 private int maxQueryTime;
133
134
135 private String triggerConditionSeconds;
136 private String triggerConditionMinutes;
137
138 private ServletContext servletContext;
139 private DataSource dataSource;
140 private QueryOperationsBackend backend;
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 private List<SimpleEventQueryDTO> constructSimpleEventQueries(final QueryParams queryParams) throws SQLException,
198 QueryParameterExceptionResponse {
199 SimpleEventQueryDTO aggrEventQuery = new SimpleEventQueryDTO(EpcisConstants.AGGREGATION_EVENT);
200 SimpleEventQueryDTO objEventQuery = new SimpleEventQueryDTO(EpcisConstants.OBJECT_EVENT);
201 SimpleEventQueryDTO quantEventQuery = new SimpleEventQueryDTO(EpcisConstants.QUANTITY_EVENT);
202 SimpleEventQueryDTO transEventQuery = new SimpleEventQueryDTO(EpcisConstants.TRANSACTION_EVENT);
203
204 boolean includeAggrEvents = true;
205 boolean includeObjEvents = true;
206 boolean includeQuantEvents = true;
207 boolean includeTransEvents = true;
208
209 String orderBy = null;
210 OrderDirection orderDirection = null;
211 int eventCountLimit = -1;
212 int maxEventCount = -1;
213
214
215
216 List<String> sortedParamNames = new ArrayList<String>();
217
218 int nofEventFieldExtensions = 0;
219 for (QueryParam param : queryParams.getParam()) {
220 String paramName = param.getName();
221 Object paramValue = param.getValue();
222
223
224 if (paramName == null || "".equals(paramName)) {
225 String msg = "Missing name for a query parameter";
226 throw queryParameterException(msg, null);
227 }
228 if (paramValue == null) {
229 String msg = "Missing value for query parameter '" + paramName + "'";
230 throw queryParameterException(msg, null);
231 }
232
233 int index = Collections.binarySearch(sortedParamNames, paramName);
234 if (index < 0) {
235
236 sortedParamNames.add(-index - 1, paramName);
237 } else {
238
239 String msg = "Query parameter '" + paramName + "' provided more than once";
240 throw queryParameterException(msg, null);
241 }
242
243 if (LOG.isDebugEnabled()) {
244 LOG.debug("Handling query parameter: " + paramName);
245 }
246 try {
247 if (paramName.equals("eventType")) {
248
249 List<String> eventTypes = parseAsArrayOfString(paramValue).getString();
250 if (!eventTypes.isEmpty()) {
251
252 checkEventTypes(eventTypes);
253
254
255 if (!eventTypes.contains(EpcisConstants.AGGREGATION_EVENT)) {
256 includeAggrEvents = false;
257 }
258 if (!eventTypes.contains(EpcisConstants.OBJECT_EVENT)) {
259 includeObjEvents = false;
260 }
261 if (!eventTypes.contains(EpcisConstants.QUANTITY_EVENT)) {
262 includeQuantEvents = false;
263 }
264 if (!eventTypes.contains(EpcisConstants.TRANSACTION_EVENT)) {
265 includeTransEvents = false;
266 }
267 }
268 } else if (paramName.equals("GE_eventTime") || paramName.equals("LT_eventTime")
269 || paramName.equals("GE_recordTime") || paramName.equals("LT_recordTime")) {
270 Calendar cal = parseAsCalendar(paramValue, paramName);
271 Operation op = Operation.valueOf(paramName.substring(0, 2));
272 String eventField = paramName.substring(3, paramName.length()) + "Ms";
273 aggrEventQuery.addEventQueryParam(eventField, op, cal.getTimeInMillis());
274 objEventQuery.addEventQueryParam(eventField, op, cal.getTimeInMillis());
275 quantEventQuery.addEventQueryParam(eventField, op, cal.getTimeInMillis());
276 transEventQuery.addEventQueryParam(eventField, op, cal.getTimeInMillis());
277
278 } else if (paramName.equals("EQ_action")) {
279
280 includeQuantEvents = false;
281 ArrayOfString aos = parseAsArrayOfString(paramValue);
282 if (!aos.getString().isEmpty()) {
283 checkActionValues(aos.getString());
284 aggrEventQuery.addEventQueryParam("action", Operation.EQ, aos.getString());
285 objEventQuery.addEventQueryParam("action", Operation.EQ, aos.getString());
286 transEventQuery.addEventQueryParam("action", Operation.EQ, aos.getString());
287 }
288
289 } else if (paramName.equals("EQ_bizStep") || paramName.equals("EQ_disposition")
290 || paramName.equals("EQ_readPoint") || paramName.equals("EQ_bizLocation")) {
291 ArrayOfString aos = parseAsArrayOfString(paramValue);
292 if (!aos.getString().isEmpty()) {
293 String eventField = paramName.substring(3, paramName.length());
294 aggrEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
295 objEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
296 quantEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
297 transEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
298 }
299
300 } else if (paramName.equals("WD_readPoint") || paramName.equals("WD_bizLocation")) {
301 ArrayOfString aos = parseAsArrayOfString(paramValue);
302 if (!aos.getString().isEmpty()) {
303
304
305
306 CollectionUtils.transform(aos.getString(), new StringTransformer());
307 String eventField = paramName.substring(3, paramName.length());
308 aggrEventQuery.addEventQueryParam(eventField, Operation.WD, aos.getString());
309 objEventQuery.addEventQueryParam(eventField, Operation.WD, aos.getString());
310 quantEventQuery.addEventQueryParam(eventField, Operation.WD, aos.getString());
311 transEventQuery.addEventQueryParam(eventField, Operation.WD, aos.getString());
312 }
313
314 } else if (paramName.startsWith("EQ_bizTransaction_")) {
315
316 String bizTransType = paramName.substring(18);
317 ArrayOfString aos = parseAsArrayOfString(paramValue);
318 if (!aos.getString().isEmpty()) {
319 aggrEventQuery.addEventQueryParam("bizTransList.type", Operation.EQ, bizTransType);
320 objEventQuery.addEventQueryParam("bizTransList.type", Operation.EQ, bizTransType);
321 quantEventQuery.addEventQueryParam("bizTransList.type", Operation.EQ, bizTransType);
322 transEventQuery.addEventQueryParam("bizTransList.type", Operation.EQ, bizTransType);
323 aggrEventQuery.addEventQueryParam("bizTransList.bizTrans", Operation.EQ, aos.getString());
324 objEventQuery.addEventQueryParam("bizTransList.bizTrans", Operation.EQ, aos.getString());
325 quantEventQuery.addEventQueryParam("bizTransList.bizTrans", Operation.EQ, aos.getString());
326 transEventQuery.addEventQueryParam("bizTransList.bizTrans", Operation.EQ, aos.getString());
327 }
328
329 } else if (paramName.equals("MATCH_epc") || paramName.equals("MATCH_anyEPC")) {
330
331 includeQuantEvents = false;
332 ArrayOfString aos = parseAsArrayOfString(paramValue);
333 if (!aos.getString().isEmpty()) {
334 aggrEventQuery.addEventQueryParam("childEPCs", Operation.MATCH, aos.getString());
335 objEventQuery.addEventQueryParam("epcList", Operation.MATCH, aos.getString());
336 transEventQuery.addEventQueryParam("epcList", Operation.MATCH, aos.getString());
337 if (paramName.equals("MATCH_anyEPC")) {
338
339
340 aggrEventQuery.setIsAnyEpc(true);
341 transEventQuery.setIsAnyEpc(true);
342 }
343 }
344
345 } else if (paramName.equals("MATCH_parentID")) {
346 includeQuantEvents = false;
347 includeObjEvents = false;
348 ArrayOfString aos = parseAsArrayOfString(paramValue);
349 if (!aos.getString().isEmpty()) {
350 aggrEventQuery.addEventQueryParam("parentID", Operation.MATCH, aos.getString());
351 transEventQuery.addEventQueryParam("parentID", Operation.MATCH, aos.getString());
352 }
353
354 } else if (paramName.equals("MATCH_epcClass")) {
355 includeAggrEvents = false;
356 includeObjEvents = false;
357 includeTransEvents = false;
358 ArrayOfString aos = parseAsArrayOfString(paramValue);
359 if (!aos.getString().isEmpty()) {
360 quantEventQuery.addEventQueryParam("epcClass", Operation.MATCH, aos.getString());
361 }
362
363 } else if (paramName.endsWith("_quantity")) {
364 includeAggrEvents = false;
365 includeObjEvents = false;
366 includeTransEvents = false;
367 Operation op = Operation.valueOf(paramName.substring(0, paramName.indexOf('_')));
368 quantEventQuery.addEventQueryParam("quantity", op, parseAsInteger(paramValue));
369
370 } else if (paramName.startsWith("GT_") || paramName.startsWith("GE_") || paramName.startsWith("EQ_")
371 || paramName.startsWith("LE_") || paramName.startsWith("LT_")) {
372
373 String fieldname = paramName.substring(3);
374 String[] parts = fieldname.split("#");
375 if (parts.length != 2) {
376 String msg = "Invalid parameter " + paramName;
377 throw queryParameterException(msg, null);
378 }
379 nofEventFieldExtensions++;
380 String eventFieldExtBase = "extension" + nofEventFieldExtensions;
381 EventQueryParam queryParam = parseExtensionField(eventFieldExtBase, paramName, paramValue);
382 aggrEventQuery.addEventQueryParam(queryParam);
383 objEventQuery.addEventQueryParam(queryParam);
384 quantEventQuery.addEventQueryParam(queryParam);
385 transEventQuery.addEventQueryParam(queryParam);
386 String eventFieldExt = eventFieldExtBase + ".fieldname";
387 aggrEventQuery.addEventQueryParam(eventFieldExt, Operation.EQ, fieldname);
388 objEventQuery.addEventQueryParam(eventFieldExt, Operation.EQ, fieldname);
389 quantEventQuery.addEventQueryParam(eventFieldExt, Operation.EQ, fieldname);
390 transEventQuery.addEventQueryParam(eventFieldExt, Operation.EQ, fieldname);
391
392 } else if (paramName.startsWith("EXISTS_")) {
393 String fieldname = paramName.substring(7);
394 if (fieldname.equals("childEPCs")) {
395 includeObjEvents = false;
396 includeQuantEvents = false;
397 includeTransEvents = false;
398 aggrEventQuery.addEventQueryParam("childEPCs", Operation.EXISTS, null);
399 } else if (fieldname.equals("epcList")) {
400 includeAggrEvents = false;
401 includeQuantEvents = false;
402 objEventQuery.addEventQueryParam("epcList", Operation.EXISTS, null);
403 transEventQuery.addEventQueryParam("epcList", Operation.EXISTS, null);
404 } else if (fieldname.equals("action")) {
405 includeQuantEvents = false;
406 aggrEventQuery.addEventQueryParam("action", Operation.EXISTS, null);
407 objEventQuery.addEventQueryParam("action", Operation.EXISTS, null);
408 transEventQuery.addEventQueryParam("action", Operation.EXISTS, null);
409 } else if (fieldname.equals("parentID")) {
410 includeObjEvents = false;
411 includeQuantEvents = false;
412 aggrEventQuery.addEventQueryParam("parentID", Operation.EXISTS, null);
413 transEventQuery.addEventQueryParam("parentID", Operation.EXISTS, null);
414 } else if (fieldname.equals("quantity") || fieldname.equals("epcClass")) {
415 includeAggrEvents = false;
416 includeObjEvents = false;
417 includeTransEvents = false;
418 quantEventQuery.addEventQueryParam(fieldname, Operation.EXISTS, null);
419 } else if (fieldname.equals("eventTime") || fieldname.equals("recordTime")
420 || fieldname.equals("eventTimeZoneOffset") || fieldname.equals("bizStep")
421 || fieldname.equals("disposition") || fieldname.equals("readPoint")
422 || fieldname.equals("bizLocation") || fieldname.equals("bizTransList")) {
423 aggrEventQuery.addEventQueryParam(fieldname, Operation.EXISTS, null);
424 objEventQuery.addEventQueryParam(fieldname, Operation.EXISTS, null);
425 quantEventQuery.addEventQueryParam(fieldname, Operation.EXISTS, null);
426 transEventQuery.addEventQueryParam(fieldname, Operation.EXISTS, null);
427 } else {
428
429 String[] parts = fieldname.split("#");
430 if (parts.length != 2) {
431 String msg = "Invalid parameter " + paramName;
432 throw queryParameterException(msg, null);
433 }
434 nofEventFieldExtensions++;
435 String eventFieldExt = "extension" + nofEventFieldExtensions + ".fieldname";
436 aggrEventQuery.addEventQueryParam(eventFieldExt, Operation.EQ, fieldname);
437 objEventQuery.addEventQueryParam(eventFieldExt, Operation.EQ, fieldname);
438 quantEventQuery.addEventQueryParam(eventFieldExt, Operation.EQ, fieldname);
439 transEventQuery.addEventQueryParam(eventFieldExt, Operation.EQ, fieldname);
440 }
441
442 } else if (paramName.startsWith("HASATTR_")) {
443
444 String fieldname = paramName.substring(8);
445 ArrayOfString aos = parseAsArrayOfString(paramValue);
446 String eventField = fieldname + ".attribute";
447 aggrEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
448 objEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
449 quantEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
450 transEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
451
452 } else if (paramName.startsWith("EQATTR_")) {
453 String fieldname = paramName.substring(7);
454 String attrname = null;
455 String[] parts = fieldname.split("_");
456 if (parts.length > 2) {
457 String msg = "Query parameter has invalid format: " + paramName
458 + ". Expected: EQATTR_fieldname_attrname";
459 throw queryParameterException(msg, null);
460 } else if (parts.length == 2) {
461 fieldname = parts[0];
462 attrname = parts[1];
463 }
464
465 String eventField = fieldname + ".attribute";
466 aggrEventQuery.addEventQueryParam(eventField, Operation.EQ, attrname);
467 objEventQuery.addEventQueryParam(eventField, Operation.EQ, attrname);
468 quantEventQuery.addEventQueryParam(eventField, Operation.EQ, attrname);
469 transEventQuery.addEventQueryParam(eventField, Operation.EQ, attrname);
470
471 ArrayOfString aos = parseAsArrayOfString(paramValue);
472 eventField = eventField + ".value";
473 aggrEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
474 objEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
475 quantEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
476 transEventQuery.addEventQueryParam(eventField, Operation.EQ, aos.getString());
477
478 } else if (paramName.equals("orderBy")) {
479 orderBy = parseAsString(paramValue);
480 if (!"eventTime".equals(orderBy) && !"recordTime".equals(orderBy) && !"quantity".equals(orderBy)) {
481 String[] parts = orderBy.split("#");
482 if (parts.length != 2) {
483 String msg = "orderBy must be one of eventTime, recordTime, quantity, or an extension field";
484 throw queryParameterException(msg, null);
485 }
486 }
487
488 } else if (paramName.equals("orderDirection")) {
489 orderDirection = OrderDirection.valueOf(parseAsString(paramValue));
490
491 } else if (paramName.equals("eventCountLimit")) {
492 eventCountLimit = parseAsInteger(paramValue).intValue();
493
494 } else if (paramName.equals("maxEventCount")) {
495 maxEventCount = parseAsInteger(paramValue).intValue();
496
497 } else {
498 String msg = "Unknown query parameter: " + paramName;
499 throw queryParameterException(msg, null);
500 }
501 } catch (ClassCastException e) {
502 String msg = "Type of value invalid for query parameter '" + paramName + "': " + paramValue;
503 throw queryParameterException(msg, e);
504 } catch (IllegalArgumentException e) {
505 String msg = "Unparseable value for query parameter '" + paramName + "'. " + e.getMessage();
506 throw queryParameterException(msg, e);
507 }
508 }
509
510
511 if (maxEventCount > -1 && eventCountLimit > -1) {
512 String msg = "Paramters 'maxEventCount' and 'eventCountLimit' are mutually exclusive";
513 throw queryParameterException(msg, null);
514 }
515 if (orderBy == null && eventCountLimit > -1) {
516 String msg = "'eventCountLimit' may only be used when 'orderBy' is specified";
517 throw queryParameterException(msg, null);
518 }
519 if (orderBy == null && orderDirection != null) {
520 String msg = "'orderDirection' may only be used when 'orderBy' is specified";
521 throw queryParameterException(msg, null);
522 }
523 if (orderBy != null) {
524 aggrEventQuery.setOrderBy(orderBy);
525 objEventQuery.setOrderBy(orderBy);
526 quantEventQuery.setOrderBy(orderBy);
527 transEventQuery.setOrderBy(orderBy);
528 if (orderDirection != null) {
529 aggrEventQuery.setOrderDirection(orderDirection);
530 objEventQuery.setOrderDirection(orderDirection);
531 quantEventQuery.setOrderDirection(orderDirection);
532 transEventQuery.setOrderDirection(orderDirection);
533 }
534 }
535 if (eventCountLimit > -1) {
536 aggrEventQuery.setLimit(eventCountLimit);
537 objEventQuery.setLimit(eventCountLimit);
538 quantEventQuery.setLimit(eventCountLimit);
539 transEventQuery.setLimit(eventCountLimit);
540 }
541 if (maxEventCount > -1) {
542 aggrEventQuery.setMaxEventCount(maxEventCount);
543 objEventQuery.setMaxEventCount(maxEventCount);
544 quantEventQuery.setMaxEventCount(maxEventCount);
545 transEventQuery.setMaxEventCount(maxEventCount);
546 }
547
548 List<SimpleEventQueryDTO> eventQueries = new ArrayList<SimpleEventQueryDTO>(4);
549 if (includeAggrEvents) {
550 eventQueries.add(aggrEventQuery);
551 }
552 if (includeObjEvents) {
553 eventQueries.add(objEventQuery);
554 }
555 if (includeQuantEvents) {
556 eventQueries.add(quantEventQuery);
557 }
558 if (includeTransEvents) {
559 eventQueries.add(transEventQuery);
560 }
561 return eventQueries;
562 }
563
564
565
566
567
568
569 private EventQueryParam parseExtensionField(String eventFieldExtBase, String paramName, Object paramValue) {
570 Operation op = Operation.valueOf(paramName.substring(0, 2));
571 String eventField;
572 Object value;
573
574
575 try {
576 value = parseAsInteger(paramValue);
577 eventField = eventFieldExtBase + ".intValue";
578 return new EventQueryParam(eventField, op, value);
579 } catch (NumberFormatException e) {}
580
581
582 try {
583 value = parseAsFloat(paramValue);
584 eventField = eventFieldExtBase + ".floatValue";
585 return new EventQueryParam(eventField, op, value);
586 } catch (NumberFormatException e) {}
587
588
589 try {
590 value = parseAsCalendar(paramValue, paramName);
591 eventField = eventFieldExtBase + ".dateValue";
592 return new EventQueryParam(eventField, op, value);
593 } catch (QueryParameterExceptionResponse e) {}
594
595
596 try {
597 ArrayOfString aos = parseAsArrayOfString(paramValue);
598 if (!aos.getString().isEmpty()) {
599 value = aos.getString();
600 eventField = eventFieldExtBase + ".strValue";
601 return new EventQueryParam(eventField, op, value);
602 }
603 } catch (Throwable t) {}
604
605
606 value = parseAsString(paramValue);
607 eventField = eventFieldExtBase + ".strValue";
608 return new EventQueryParam(eventField, op, value);
609 }
610
611
612
613
614
615
616
617
618
619
620
621 private void checkEventTypes(List<String> eventTypes) throws QueryParameterExceptionResponse {
622 for (String eventType : eventTypes) {
623 if (!EpcisConstants.EVENT_TYPES.contains(eventType)) {
624 String msg = "Unsupported eventType: " + eventType;
625 throw queryParameterException(msg, null);
626 }
627 }
628 }
629
630
631
632
633
634
635
636
637 private String parseAsString(Object queryParamValue) throws ClassCastException {
638 if (queryParamValue instanceof String) {
639 return (String) queryParamValue;
640 } else if (queryParamValue instanceof Element) {
641 Element elem = (Element) queryParamValue;
642 return elem.getTextContent().trim();
643 } else {
644 return queryParamValue.toString();
645 }
646 }
647
648
649
650
651
652
653
654
655
656
657 private Float parseAsFloat(Object queryParamValue) throws NumberFormatException {
658 if (queryParamValue instanceof Float) {
659 return (Float) queryParamValue;
660 } else if (queryParamValue instanceof Element) {
661 Element elem = (Element) queryParamValue;
662 return Float.valueOf(elem.getTextContent().trim());
663 } else {
664 return Float.valueOf(queryParamValue.toString());
665 }
666 }
667
668
669
670
671
672
673
674
675
676
677
678
679 private Calendar parseAsCalendar(Object queryParamValue, String queryParamName)
680 throws QueryParameterExceptionResponse {
681 Calendar cal;
682 if (queryParamValue instanceof Calendar) {
683
684 cal = (Calendar) queryParamValue;
685 } else if (queryParamValue instanceof XMLGregorianCalendar) {
686
687
688 cal = ((XMLGregorianCalendar) queryParamValue).toGregorianCalendar();
689 } else {
690
691 String date = null;
692 if (queryParamValue instanceof Element) {
693
694
695 Element elem = (Element) queryParamValue;
696 date = elem.getTextContent().trim();
697 } else {
698 date = queryParamValue.toString();
699 }
700 if (LOG.isDebugEnabled()) {
701 LOG.debug("Trying to parse the value (" + date + ") for parameter " + queryParamName + " as date/time");
702 }
703 try {
704 cal = TimeParser.parseAsCalendar(date);
705 } catch (ParseException e) {
706 String msg = "Unable to parse the value for query parameter '" + queryParamName + "' as date/time";
707 throw queryParameterException(msg, e);
708 }
709 }
710 return cal;
711 }
712
713
714
715
716
717
718
719
720
721
722 private Integer parseAsInteger(Object queryParamValue) throws NumberFormatException {
723 if (queryParamValue instanceof Integer) {
724 return (Integer) queryParamValue;
725 } else if (queryParamValue instanceof Element) {
726 Element elem = (Element) queryParamValue;
727 return Integer.valueOf(elem.getTextContent().trim());
728 } else {
729 return Integer.valueOf(queryParamValue.toString());
730 }
731 }
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749 private ArrayOfString parseAsArrayOfString(Object queryParamValue) throws ClassCastException,
750 QueryParameterExceptionResponse {
751 try {
752 return (ArrayOfString) queryParamValue;
753 } catch (ClassCastException e) {
754
755 Element elem = (Element) queryParamValue;
756 NodeList strings = elem.getChildNodes();
757 ArrayOfString aos = new ArrayOfString();
758 for (int i = 0; i < strings.getLength(); i++) {
759 if (strings.item(i).getNodeType() == Node.ELEMENT_NODE) {
760 if ("string".equalsIgnoreCase(strings.item(i).getNodeName())) {
761 String s = strings.item(i).getTextContent().trim();
762 aos.getString().add(s);
763 } else {
764 String msg = "Invalid ArrayOfString syntax: matching <string> </string> tags expected";
765 throw queryParameterException(msg, null);
766 }
767 }
768 }
769 if (LOG.isDebugEnabled()) {
770 LOG.debug("ArrayOfString parsed to: " + aos.getString());
771 }
772 return aos;
773 }
774 }
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792 private MasterDataQueryDTO constructMasterDataQuery(final QueryParams queryParams)
793 throws QueryParameterExceptionResponse {
794 MasterDataQueryDTO mdQuery = new MasterDataQueryDTO();
795
796
797
798 List<String> sortedParamNames = new ArrayList<String>();
799
800 Boolean includeAttributes = null;
801 Boolean includeChildren = null;
802 List<String> vocabularyTypes = null;
803 List<String> includedAttributeNames = null;
804
805 for (QueryParam param : queryParams.getParam()) {
806 String paramName = param.getName();
807 Object paramValue = param.getValue();
808
809
810 if (paramName == null || "".equals(paramName)) {
811 String msg = "Missing name for a query parameter";
812 throw queryParameterException(msg, null);
813 }
814 if (paramValue == null) {
815 String msg = "Missing value for query parameter '" + paramName + "'";
816 throw queryParameterException(msg, null);
817 }
818
819 int index = Collections.binarySearch(sortedParamNames, paramName);
820 if (index < 0) {
821
822 sortedParamNames.add(-index - 1, paramName);
823 } else {
824
825 String msg = "Query parameter '" + paramName + "' provided more than once";
826 throw queryParameterException(msg, null);
827 }
828
829 try {
830 if (paramName.equals("includeAttributes")) {
831
832 includeAttributes = Boolean.valueOf(parseAsString(paramValue));
833 mdQuery.setIncludeAttributes(includeAttributes.booleanValue());
834
835 } else if (paramName.equals("includeChildren")) {
836
837 includeChildren = Boolean.valueOf(parseAsString(paramValue));
838 mdQuery.setIncludeChildren(includeChildren.booleanValue());
839
840 } else if (paramName.equals("maxElementCount")) {
841 int maxElementCount = parseAsInteger(paramValue).intValue();
842 mdQuery.setMaxElementCount(maxElementCount);
843
844 } else if (paramName.equals("vocabularyName")) {
845 ArrayOfString aos = parseAsArrayOfString(paramValue);
846 vocabularyTypes = aos.getString();
847
848 } else if (paramName.equals("attributeNames")) {
849 ArrayOfString aos = parseAsArrayOfString(paramValue);
850 includedAttributeNames = aos.getString();
851
852 } else if (paramName.equals("EQ_name")) {
853 ArrayOfString aos = parseAsArrayOfString(paramValue);
854 mdQuery.setVocabularyEqNames(aos.getString());
855
856 } else if (paramName.equals("WD_name")) {
857 ArrayOfString aos = parseAsArrayOfString(paramValue);
858 mdQuery.setVocabularyWdNames(aos.getString());
859
860 } else if (paramName.equals("HASATTR")) {
861 ArrayOfString aos = parseAsArrayOfString(paramValue);
862 mdQuery.setAttributeNames(aos.getString());
863
864 } else if (paramName.startsWith("EQATTR_")) {
865 String attrName = paramName.substring(7);
866 ArrayOfString aos = parseAsArrayOfString(paramValue);
867 mdQuery.addAttributeNameAndValues(attrName, aos.getString());
868
869 }
870 } catch (ClassCastException e) {
871 String msg = "The type of the value for query parameter '" + paramName + "': " + paramValue
872 + " is invalid";
873 throw queryParameterException(msg, e);
874 }
875 }
876
877
878 if (includeAttributes == null || includeChildren == null) {
879 String missing = (includeAttributes == null) ? " includeAttributes" : "";
880 missing += (includeChildren == null) ? " includeChildren" : "";
881 String msg = "Missing required masterdata query parameter(s):" + missing;
882 throw queryParameterException(msg, null);
883 }
884 if (includeAttributes.booleanValue() && includedAttributeNames != null) {
885 mdQuery.setIncludedAttributeNames(includedAttributeNames);
886 }
887
888 if (vocabularyTypes == null) {
889
890 vocabularyTypes = EpcisConstants.VOCABULARY_TYPES;
891 }
892 mdQuery.setVocabularyTypes(vocabularyTypes);
893
894 return mdQuery;
895 }
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918 private QueryParameterExceptionResponse queryParameterException(String msg, Exception e) {
919 LOG.info("QueryParameterException: " + msg);
920 if (LOG.isTraceEnabled() && e != null) {
921 LOG.trace("Exception details: " + e.getMessage(), e);
922 }
923 QueryParameterException qpe = new QueryParameterException();
924 qpe.setReason(msg);
925 return new QueryParameterExceptionResponse(msg, qpe);
926 }
927
928
929
930
931
932
933
934
935
936
937
938 private void checkActionValues(final List<String> actions) throws QueryParameterExceptionResponse {
939 for (String action : actions) {
940 if (!(action.equalsIgnoreCase("ADD") || action.equalsIgnoreCase("OBSERVE") || action.equalsIgnoreCase("DELETE"))) {
941 String msg = "Invalid value for parameter EQ_action: " + action
942 + " - must be one of ADD, OBSERVE, or DELETE";
943 throw queryParameterException(msg, null);
944 }
945 }
946 }
947
948
949
950
951
952
953
954 private void saveSubscriptions(final Map<String, QuerySubscriptionScheduled> subscriptions) {
955 servletContext.setAttribute("subscribedMap", subscriptions);
956 }
957
958
959
960
961
962
963
964
965
966
967 @SuppressWarnings("unchecked")
968 private Map<String, QuerySubscriptionScheduled> loadSubscriptions(QueryOperationsSession session)
969 throws ImplementationExceptionResponse, SQLException {
970 LOG.debug("Retrieving subscriptions from application context");
971 Object subscribedMap = servletContext.getAttribute("subscribedMap");
972 Map<String, QuerySubscriptionScheduled> subscriptions = (HashMap<String, QuerySubscriptionScheduled>) subscribedMap;
973 if (subscriptions == null) {
974 LOG.debug("Subscriptions not found - retrieving subscriptions from database");
975 subscriptions = backend.fetchSubscriptions(session);
976 }
977 return subscriptions;
978 }
979
980
981
982
983 public List<String> getQueryNames() throws SecurityExceptionResponse, ValidationExceptionResponse,
984 ImplementationExceptionResponse {
985 LOG.info("Invoking 'getQueryNames'");
986 return QUERYNAMES;
987 }
988
989
990
991
992 public String getStandardVersion() throws SecurityExceptionResponse, ValidationExceptionResponse,
993 ImplementationExceptionResponse {
994 LOG.info("Invoking 'getStandardVersion'");
995 return STD_VERSION;
996 }
997
998
999
1000
1001 public List<String> getSubscriptionIDs(String queryName) throws NoSuchNameExceptionResponse,
1002 SecurityExceptionResponse, ValidationExceptionResponse, ImplementationExceptionResponse {
1003 try {
1004 LOG.info("Invoking 'getSubscriptionIDs'");
1005 QueryOperationsSession session = null;
1006 try {
1007 session = backend.openSession(dataSource);
1008
1009
1010 Map<String, QuerySubscriptionScheduled> subscribedMap = loadSubscriptions(session);
1011 Set<String> temp = subscribedMap.keySet();
1012 return new ArrayList<String>(temp);
1013 } finally {
1014 if (session != null) {
1015 session.close();
1016 }
1017 LOG.debug("DB connection closed");
1018 }
1019 } catch (SQLException e) {
1020 ImplementationException iex = new ImplementationException();
1021 String msg = "SQL error during query execution: " + e.getMessage();
1022 LOG.error(msg, e);
1023 iex.setReason(msg);
1024 iex.setSeverity(ImplementationExceptionSeverity.ERROR);
1025 throw new ImplementationExceptionResponse(msg, iex, e);
1026 }
1027 }
1028
1029
1030
1031
1032 public String getVendorVersion() throws SecurityExceptionResponse, ValidationExceptionResponse,
1033 ImplementationExceptionResponse {
1034 LOG.info("Invoking 'getVendorVersion'");
1035 return serviceVersion;
1036 }
1037
1038
1039
1040
1041 public QueryResults poll(String queryName, QueryParams queryParams) throws NoSuchNameExceptionResponse,
1042 QueryParameterExceptionResponse, QueryTooComplexExceptionResponse, QueryTooLargeExceptionResponse,
1043 SecurityExceptionResponse, ValidationExceptionResponse, ImplementationExceptionResponse {
1044 try {
1045 LOG.info("Invoking 'poll'");
1046 QueryOperationsSession session = null;
1047 try {
1048 session = backend.openSession(dataSource);
1049 QueryResultsBody resultsBody = null;
1050 if (queryName.equals("SimpleEventQuery")) {
1051 LOG.info("This is a SimpleEventQuery");
1052 EventListType eventList = new EventListType();
1053 List<SimpleEventQueryDTO> eventQueries = constructSimpleEventQueries(queryParams);
1054
1055
1056 String orderBy = null;
1057 OrderDirection orderDirection = null;
1058 int limit = -1;
1059 for (SimpleEventQueryDTO eventQuery : eventQueries) {
1060 if (eventQuery.getOrderBy() != null) {
1061 orderBy = eventQuery.getOrderBy();
1062 orderDirection = eventQuery.getOrderDirection();
1063 limit = eventQuery.getLimit();
1064 }
1065 backend.runSimpleEventQuery(session, eventQuery,
1066 eventList.getObjectEventOrAggregationEventOrQuantityEvent());
1067 }
1068 eventList = checkOrdering(eventList, orderBy, orderDirection, limit);
1069
1070 resultsBody = new QueryResultsBody();
1071 resultsBody.setEventList(eventList);
1072 } else if (queryName.equals("SimpleMasterDataQuery")) {
1073 LOG.info("This is a SimpleMasterDataQuery");
1074 VocabularyListType vocList = new VocabularyListType();
1075 MasterDataQueryDTO mdQuery = constructMasterDataQuery(queryParams);
1076 backend.runMasterDataQuery(session, mdQuery, vocList.getVocabulary());
1077
1078 resultsBody = new QueryResultsBody();
1079 resultsBody.setVocabularyList(vocList);
1080 } else {
1081 session.close();
1082 String msg = "Unsupported query name '" + queryName + "' provided";
1083 LOG.info("NoSuchNameException: " + msg);
1084 NoSuchNameException e = new NoSuchNameException();
1085 e.setReason(msg);
1086 throw new NoSuchNameExceptionResponse(msg, e);
1087 }
1088 QueryResults results = new QueryResults();
1089 results.setResultsBody(resultsBody);
1090 results.setQueryName(queryName);
1091
1092 LOG.info("poll request for '" + queryName + "' succeeded");
1093 return results;
1094 } finally {
1095 if (session != null) {
1096 session.close();
1097 }
1098 LOG.debug("DB connection closed");
1099 }
1100 } catch (SQLException e) {
1101 ImplementationException iex = new ImplementationException();
1102 String msg = "SQL error during query execution: " + e.getMessage();
1103 LOG.error(msg, e);
1104 iex.setReason(msg);
1105 iex.setSeverity(ImplementationExceptionSeverity.ERROR);
1106 throw new ImplementationExceptionResponse(msg, iex, e);
1107 }
1108 }
1109
1110
1111
1112
1113
1114
1115
1116
1117 private EventListType checkOrdering(EventListType eventList, String orderBy, OrderDirection orderDirection,
1118 int limit) {
1119 if (orderBy == null) {
1120
1121 return eventList;
1122 }
1123 if ("quantity".equals(orderBy)) {
1124
1125 return eventList;
1126 }
1127 int size = eventList.getObjectEventOrAggregationEventOrQuantityEvent().size();
1128 if (limit > -1 && size == limit) {
1129
1130
1131 return eventList;
1132 }
1133 LOG.debug("Need to apply sorting across the different event types (sortBy=" + orderBy + ")");
1134 boolean orderByEventTime = "eventTime".equals(orderBy);
1135 Comparator<Object> comparator = new EventComparator(orderByEventTime, orderDirection);
1136 Collections.sort(eventList.getObjectEventOrAggregationEventOrQuantityEvent(), comparator);
1137 if (limit > -1 && size > limit) {
1138 LOG.debug("Need to apply global limit to events (limit=" + limit + ")");
1139
1140 eventList.getObjectEventOrAggregationEventOrQuantityEvent().subList(limit, size).clear();
1141 }
1142 return eventList;
1143 }
1144
1145
1146
1147
1148 public void subscribe(String queryName, QueryParams params, String dest, SubscriptionControls controls,
1149 String subscriptionID) throws NoSuchNameExceptionResponse, InvalidURIExceptionResponse,
1150 DuplicateSubscriptionExceptionResponse, QueryParameterExceptionResponse, QueryTooComplexExceptionResponse,
1151 SubscriptionControlsExceptionResponse, SubscribeNotPermittedExceptionResponse, SecurityExceptionResponse,
1152 ValidationExceptionResponse, ImplementationExceptionResponse {
1153 try {
1154 LOG.info("Invoking 'subscribe'");
1155 QueryOperationsSession session = null;
1156 try {
1157 session = backend.openSession(dataSource);
1158 String triggerURI = controls.getTrigger();
1159 QuerySubscriptionScheduled newSubscription = null;
1160 Schedule schedule = null;
1161 Calendar initialRecordTime;
1162 try {
1163 initialRecordTime = controls.getInitialRecordTime().toGregorianCalendar();
1164 }catch(Exception e){
1165 initialRecordTime = GregorianCalendar.getInstance();
1166 }
1167
1168
1169
1170
1171
1172
1173 if (dest == null || dest.toString().equals("")) {
1174 String msg = "Destination URI is empty. This implementation doesn't support pre-arranged destinations.";
1175 LOG.info("QueryParameterException: " + msg);
1176 InvalidURIException e = new InvalidURIException();
1177 e.setReason(msg);
1178 throw new InvalidURIExceptionResponse(msg, e);
1179 }
1180 try {
1181 new URL(dest.toString());
1182 } catch (MalformedURLException ex) {
1183 String msg = "Destination URI is invalid: " + ex.getMessage();
1184 LOG.info("InvalidURIException: " + msg);
1185 InvalidURIException e = new InvalidURIException();
1186 e.setReason(msg);
1187 throw new InvalidURIExceptionResponse(msg, e, ex);
1188 }
1189
1190
1191 if (!QUERYNAMES.contains(queryName)) {
1192 String msg = "Illegal query name '" + queryName + "'";
1193 LOG.info("NoSuchNameException: " + msg);
1194 NoSuchNameException e = new NoSuchNameException();
1195 e.setReason(msg);
1196 throw new NoSuchNameExceptionResponse(msg, e);
1197 }
1198
1199
1200 if (queryName.equals("SimpleMasterDataQuery")) {
1201 String msg = "Subscription not allowed for SimpleMasterDataQuery";
1202 LOG.info("SubscribeNotPermittedException: " + msg);
1203 SubscribeNotPermittedException e = new SubscribeNotPermittedException();
1204 e.setReason(msg);
1205 throw new SubscribeNotPermittedExceptionResponse(msg, e);
1206 }
1207
1208
1209 if (subscriptionID == null || subscriptionID.equals("")) {
1210 String msg = "SubscriptionID is empty. Choose a valid subscriptionID";
1211 LOG.info(msg);
1212 ValidationException e = new ValidationException();
1213 e.setReason(msg);
1214 throw new ValidationExceptionResponse(msg, e);
1215 }
1216
1217
1218 if (backend.fetchExistsSubscriptionId(session, subscriptionID)) {
1219 String msg = "SubscriptionID '" + subscriptionID
1220 + "' already exists. Choose a different subscriptionID";
1221 LOG.info("DuplicateSubscriptionException: " + msg);
1222 DuplicateSubscriptionException e = new DuplicateSubscriptionException();
1223 e.setReason(msg);
1224 throw new DuplicateSubscriptionExceptionResponse(msg, e);
1225 }
1226
1227
1228
1229 if (controls.getSchedule() != null && controls.getTrigger() != null) {
1230 String msg = "Schedule and trigger cannot be used together";
1231 LOG.info("SubscriptionControlsException: " + msg);
1232 SubscriptionControlsException e = new SubscriptionControlsException();
1233 e.setReason(msg);
1234 throw new SubscriptionControlsExceptionResponse(msg, e);
1235 }
1236 if (controls.getSchedule() == null && controls.getTrigger() == null) {
1237 String msg = "Either schedule or trigger has to be provided";
1238 LOG.info("SubscriptionControlsException: " + msg);
1239 SubscriptionControlsException e = new SubscriptionControlsException();
1240 e.setReason(msg);
1241 throw new SubscriptionControlsExceptionResponse(msg, e);
1242 }
1243 if (controls.getSchedule() != null) {
1244 LOG.debug("Received new scheduled query.");
1245
1246 schedule = new Schedule(controls.getSchedule());
1247 newSubscription = new QuerySubscriptionScheduled(subscriptionID, params, dest,
1248 Boolean.valueOf(controls.isReportIfEmpty()), initialRecordTime, initialRecordTime,
1249 schedule, queryName);
1250 } else {
1251 LOG.debug("Received new triggered query.");
1252
1253
1254 QuerySchedule qSchedule = new QuerySchedule();
1255 qSchedule.setSecond(triggerConditionSeconds);
1256 if (triggerConditionMinutes != null) {
1257 qSchedule.setMinute(triggerConditionMinutes);
1258 }
1259 schedule = new Schedule(qSchedule);
1260 QuerySubscriptionTriggered trigger = new QuerySubscriptionTriggered(subscriptionID, params, dest,
1261 Boolean.valueOf(controls.isReportIfEmpty()), initialRecordTime, initialRecordTime,
1262 queryName, triggerURI, schedule);
1263 newSubscription = trigger;
1264 }
1265
1266
1267 Map<String, QuerySubscriptionScheduled> subscribedMap = loadSubscriptions(session);
1268
1269
1270
1271 backend.storeSupscriptions(session, params, dest, subscriptionID, controls, triggerURI,
1272 newSubscription, queryName, schedule);
1273 subscribedMap.put(subscriptionID, newSubscription);
1274 saveSubscriptions(subscribedMap);
1275 } finally {
1276 if (session != null) {
1277 session.close();
1278 }
1279 LOG.debug("DB connection closed");
1280 }
1281 } catch (SQLException e) {
1282 String msg = "SQL error during query execution: " + e.getMessage();
1283 LOG.error(msg, e);
1284 ImplementationException iex = new ImplementationException();
1285 iex.setReason(msg);
1286 iex.setSeverity(ImplementationExceptionSeverity.ERROR);
1287 throw new ImplementationExceptionResponse(msg, iex, e);
1288 }
1289 }
1290
1291
1292
1293
1294 public void unsubscribe(String subscriptionID) throws NoSuchSubscriptionExceptionResponse,
1295 SecurityExceptionResponse, ValidationExceptionResponse, ImplementationExceptionResponse {
1296 try {
1297 LOG.info("Invoking 'unsubscribe'");
1298 QueryOperationsSession session = null;
1299 try {
1300 session = backend.openSession(dataSource);
1301 Map<String, QuerySubscriptionScheduled> subscribedMap = loadSubscriptions(session);
1302 if (subscribedMap.containsKey(subscriptionID)) {
1303
1304 QuerySubscriptionScheduled toDelete = subscribedMap.get(subscriptionID);
1305 toDelete.stopSubscription();
1306 subscribedMap.remove(subscriptionID);
1307 saveSubscriptions(subscribedMap);
1308
1309
1310 backend.deleteSubscription(session, subscriptionID);
1311 } else {
1312 String msg = "There is no subscription with ID '" + subscriptionID + "'";
1313 LOG.info("NoSuchSubscriptionException: " + msg);
1314 NoSuchSubscriptionException e = new NoSuchSubscriptionException();
1315 e.setReason(msg);
1316 throw new NoSuchSubscriptionExceptionResponse(msg, e);
1317 }
1318 } finally {
1319 if (session != null) {
1320 session.close();
1321 }
1322 LOG.debug("DB connection closed");
1323 }
1324 } catch (SQLException e) {
1325 ImplementationException iex = new ImplementationException();
1326 String msg = "SQL error during query execution: " + e.getMessage();
1327 LOG.error(msg, e);
1328 iex.setReason(msg);
1329 iex.setSeverity(ImplementationExceptionSeverity.ERROR);
1330 throw new ImplementationExceptionResponse(msg, iex, e);
1331 }
1332 }
1333
1334
1335
1336
1337
1338
1339
1340 private static class StringTransformer implements Transformer {
1341 public Object transform(Object o) {
1342 if (o instanceof String) {
1343 o = ((String) o).concat("*");
1344 }
1345 return o;
1346 }
1347 }
1348
1349
1350
1351
1352 public DataSource getDataSource() {
1353 return dataSource;
1354 }
1355
1356
1357
1358
1359
1360 public void setDataSource(DataSource dataSource) {
1361 this.dataSource = dataSource;
1362 }
1363
1364
1365
1366
1367 public int getMaxQueryRows() {
1368 return maxQueryRows;
1369 }
1370
1371
1372
1373
1374
1375 public void setMaxQueryRows(int maxQueryRows) {
1376 this.maxQueryRows = maxQueryRows;
1377 }
1378
1379
1380
1381
1382 public int getMaxQueryTime() {
1383 return maxQueryTime;
1384 }
1385
1386
1387
1388
1389
1390 public void setMaxQueryTime(int maxQueryTime) {
1391 this.maxQueryTime = maxQueryTime;
1392 }
1393
1394
1395
1396
1397 public String getTriggerConditionSeconds() {
1398 return triggerConditionSeconds;
1399 }
1400
1401
1402
1403
1404
1405 public void setTriggerConditionSeconds(String triggerConditionSeconds) {
1406 this.triggerConditionSeconds = triggerConditionSeconds;
1407 }
1408
1409
1410
1411
1412 public String getTriggerConditionMinutes() {
1413 return triggerConditionMinutes;
1414 }
1415
1416
1417
1418
1419
1420 public void setTriggerConditionMinutes(String triggerConditionMinutes) {
1421 this.triggerConditionMinutes = triggerConditionMinutes;
1422 }
1423
1424
1425
1426
1427
1428 public void setServletContext(ServletContext servletContext) {
1429 this.servletContext = servletContext;
1430 }
1431
1432
1433
1434
1435 public String getServiceVersion() {
1436 return serviceVersion;
1437 }
1438
1439
1440
1441
1442
1443 public void setServiceVersion(String serviceVersion) {
1444 if (!"".equals(serviceVersion)) {
1445
1446 try {
1447 new URL(serviceVersion);
1448 } catch (MalformedURLException e) {
1449 serviceVersion = "http://www.fosstrak.org/epcis/" + serviceVersion;
1450 }
1451 }
1452 this.serviceVersion = serviceVersion;
1453 }
1454
1455
1456
1457
1458 public QueryOperationsBackend getBackend() {
1459 return backend;
1460 }
1461
1462
1463
1464
1465
1466 public void setBackend(QueryOperationsBackend backend) {
1467 this.backend = backend;
1468 }
1469
1470
1471
1472
1473
1474
1475
1476
1477 public class EventComparator implements Comparator<Object> {
1478 private boolean orderByEventTime = false;
1479 private OrderDirection orderDirection = null;
1480
1481 public EventComparator(boolean orderByEventTime, OrderDirection orderDirection) {
1482 this.orderByEventTime = orderByEventTime;
1483 this.orderDirection = orderDirection;
1484 }
1485
1486 public int compare(Object o1, Object o2) {
1487 EPCISEventType event1 = (EPCISEventType) o1;
1488 EPCISEventType event2 = (EPCISEventType) o2;
1489 if (orderByEventTime) {
1490 if (orderDirection == OrderDirection.ASC) {
1491 return event1.getEventTime().compare(event2.getEventTime());
1492 } else {
1493 return event2.getEventTime().compare(event1.getEventTime());
1494 }
1495 } else {
1496
1497 if (orderDirection == OrderDirection.ASC) {
1498 return event1.getRecordTime().compare(event2.getRecordTime());
1499 } else {
1500 return event2.getEventTime().compare(event1.getEventTime());
1501 }
1502 }
1503 }
1504 }
1505 }