001: /*
002:
003: * <copyright>
004: *
005: * Copyright 2002-2007 BBNT Solutions, LLC
006: * under sponsorship of the Defense Advanced Research Projects
007: * Agency (DARPA).
008: *
009: * You can redistribute this software and/or modify it under the
010: * terms of the Cougaar Open Source License as published on the
011: * Cougaar Open Source Website (www.cougaar.org).
012: *
013: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
014: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
015: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
016: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
017: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
018: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
019: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
020: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
021: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
022: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
023: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
024: *
025: * </copyright>
026:
027: */
028:
029: package org.cougaar.qos.qrs;
030:
031: import java.util.ArrayList;
032: import java.util.HashMap;
033: import java.util.Iterator;
034: import java.util.List;
035: import java.util.Map;
036:
037: import org.cougaar.qos.ResourceStatus.BadAttributeValueException;
038: import org.cougaar.qos.ResourceStatus.CrossesThresholdQualifierFactoryPOA;
039: import org.cougaar.qos.ResourceStatus.DataValueHolder;
040: import org.cougaar.qos.ResourceStatus.EveryQualifierFactoryPOA;
041: import org.cougaar.qos.ResourceStatus.ExceedsThresholdQualifierFactoryPOA;
042: import org.cougaar.qos.ResourceStatus.MinCredibilityQualifierFactoryPOA;
043: import org.cougaar.qos.ResourceStatus.MinDeltaQualifierFactoryPOA;
044: import org.cougaar.qos.ResourceStatus.NoSuchAttributeException;
045: import org.cougaar.qos.ResourceStatus.Qualifier;
046: import org.cougaar.qos.ResourceStatus.QualifierFactory;
047: import org.cougaar.qos.ResourceStatus.QualifierHelper;
048: import org.cougaar.qos.ResourceStatus.QualifierKind;
049: import org.cougaar.qos.ResourceStatus.QualifierPOA;
050: import org.cougaar.qos.ResourceStatus.RSSSubscriber;
051: import org.cougaar.qos.ResourceStatus.ResourceDescriptionParseException;
052: import org.cougaar.qos.ResourceStatus.ResourceNode;
053: import org.cougaar.qos.ResourceStatus.ResourceStatusService;
054: import org.cougaar.qos.ResourceStatus.ResourceStatusServiceOperations;
055: import org.cougaar.qos.ResourceStatus.ResourceStatusServicePOATie;
056: import org.cougaar.qos.ResourceStatus.SomeQualifierFactoryPOA;
057: import org.cougaar.qos.ResourceStatus.data_types;
058: import org.cougaar.qos.ResourceStatus.data_value;
059: import org.cougaar.qos.ResourceStatus.data_valueHolder;
060: import org.cougaar.util.log.Logger;
061:
062: import org.omg.CosNaming.NameComponent;
063: import org.omg.PortableServer.Servant;
064:
065: public class ResourceStatusServiceImpl implements
066: ResourceStatusServiceOperations {
067:
068: private final Map<RSSSubscriber, List<RSSSubscriberProxy>> subscribers;
069: private QualifierFactory[] factories;
070: private final Logger debugLogger;
071: private final Logger eventLogger;
072: private final TimerQueueingDataFeed corbaFeed;
073: private final Servant servant;
074:
075: protected ResourceStatusServiceImpl() {
076: subscribers = new HashMap<RSSSubscriber, List<RSSSubscriberProxy>>(); // subscriber -> proxy
077: debugLogger = Logging
078: .getLogger(ResourceStatusServiceImpl.class);
079: eventLogger = Logging
080: .getEventLogger(ResourceStatusServiceImpl.class);
081:
082: corbaFeed = new TimerQueueingDataFeed();
083: servant = makeServant();
084:
085: }
086:
087: public static NameComponent[] DEFAULT_RSS_NAME = {
088: new NameComponent("com", ""), new NameComponent("bbn", ""),
089: new NameComponent("ResourceStatus", ""),
090: new NameComponent("ResourceStatusService", ""), };
091:
092: protected Servant makeServant() {
093: return new ResourceStatusServicePOATie(this );
094: }
095:
096: protected Servant getServant() {
097: return servant;
098: }
099:
100: protected NameComponent[] getNSName() {
101: return DEFAULT_RSS_NAME;
102: }
103:
104: protected String guiTitle() {
105: return "RSS";
106: }
107:
108: // Make the qualifier factories
109: protected void postInit() {
110: RSS.instance().registerFeed(corbaFeed, "Corba");
111:
112: // This shouldn't be hardwired...
113: factories = new QualifierFactory[6];
114: try {
115: MinDeltaQualifierFactoryPOA fact1 = new MinDeltaQualifierFactoryImpl();
116: CorbaUtils.poa.activate_object(fact1);
117: factories[QualifierKind.min_delta.value()] = fact1._this ();
118:
119: MinCredibilityQualifierFactoryPOA fact2 = new MinCredibilityQualifierFactoryImpl();
120: CorbaUtils.poa.activate_object(fact2);
121: factories[QualifierKind.min_credibility.value()] = fact2
122: ._this ();
123:
124: ExceedsThresholdQualifierFactoryPOA fact3 = new ExceedsThresholdQualifierFactoryImpl();
125: CorbaUtils.poa.activate_object(fact3);
126: factories[QualifierKind.exceeds_threshold.value()] = fact3
127: ._this ();
128:
129: CrossesThresholdQualifierFactoryPOA fact4 = new CrossesThresholdQualifierFactoryImpl();
130: CorbaUtils.poa.activate_object(fact4);
131: factories[QualifierKind.crosses_threshold.value()] = fact4
132: ._this ();
133:
134: EveryQualifierFactoryPOA fact5 = new EveryQualifierFactoryImpl();
135: CorbaUtils.poa.activate_object(fact5);
136: factories[QualifierKind.every.value()] = fact5._this ();
137:
138: SomeQualifierFactoryPOA fact6 = new SomeQualifierFactoryImpl();
139: CorbaUtils.poa.activate_object(fact6);
140: factories[QualifierKind.some.value()] = fact6._this ();
141:
142: } catch (Exception ex) {
143: debugLogger.error(ex.toString(), ex);
144: }
145:
146: if (debugLogger.isDebugEnabled()) {
147: debugLogger.debug("postInit()");
148: }
149:
150: register();
151: }
152:
153: protected void register() {
154: NameComponent[] name = getNSName();
155: if (name != null) {
156: CorbaUtils.nsBind(name, servant);
157: }
158: }
159:
160: public void pushString(String key, String value) {
161: if (eventLogger.isInfoEnabled()) {
162: eventLogger.info("Method entry: pushString " + key + "->"
163: + value);
164: }
165: corbaFeed.newData(key, new DataValue(value), null);
166: if (eventLogger.isInfoEnabled()) {
167: eventLogger.info("Method exit: pushString " + key + "->"
168: + value);
169: }
170: }
171:
172: public void pushLong(String key, int value) {
173: if (eventLogger.isInfoEnabled()) {
174: eventLogger.info("Method entry: pushLong " + key + "->"
175: + value);
176: }
177: corbaFeed.newData(key, new DataValue(value), null);
178: if (eventLogger.isInfoEnabled()) {
179: eventLogger.info("Method exit: pushLong " + key + "->"
180: + value);
181: }
182: }
183:
184: public boolean invoke_s(String path_string, String method,
185: String[] args)
186: throws org.cougaar.qos.ResourceStatus.NoSuchMethodException,
187: ResourceDescriptionParseException
188:
189: {
190: ResourceNode[] path = PathParser.parsePath(path_string);
191: return invoke(path, method, args);
192: }
193:
194: public boolean invoke(ResourceNode[] path, String method,
195: String[] args)
196: throws org.cougaar.qos.ResourceStatus.NoSuchMethodException {
197: boolean success = false;
198: String logmsg = null;
199: if (eventLogger.isInfoEnabled()) {
200: StringBuffer msg = new StringBuffer();
201: msg.append("invoke ");
202: msg.append(method);
203: msg.append(" path = ");
204: RSSUtils.pathToString(msg, path);
205: if (args.length > 0) {
206: msg.append(" with args ");
207: msg.append(args[0]);
208: for (int i = 1; i < args.length; i++) {
209: msg.append(", ");
210: msg.append(args[i]);
211: }
212: }
213: logmsg = msg.toString();
214: eventLogger.info("Method entry: " + logmsg);
215: }
216: ResourceContext context = RSS.instance().getPathContext(path);
217:
218: if (context != null) {
219: try {
220: context.invoke(method, args);
221: success = true;
222: } catch (ResourceContext.NoSuchMethodException ex) {
223: throw new org.cougaar.qos.ResourceStatus.NoSuchMethodException(
224: ex.getMethod());
225: }
226: } else {
227: if (eventLogger.isInfoEnabled()) {
228: StringBuffer msg = new StringBuffer();
229: msg.append("No such context as ");
230: RSSUtils.pathToString(msg, path);
231: eventLogger.info(msg.toString());
232: }
233: }
234:
235: if (eventLogger.isInfoEnabled()) {
236: eventLogger.info("Method exit: " + logmsg + " returning "
237: + success);
238: }
239: return success;
240: }
241:
242: public void addDependency(ResourceNode node,
243: ResourceNode[] node_dependencies,
244: ResourceStatusService[] ignore) {
245: String logmsg = null;
246: if (eventLogger.isInfoEnabled()) {
247: StringBuffer msg = new StringBuffer();
248: msg.append("addDependency ");
249: RSSUtils.nodeToString(msg, node);
250: msg.append(":");
251: RSSUtils.pathToString(msg, node_dependencies);
252: logmsg = msg.toString();
253: eventLogger.info("Method entry: " + logmsg);
254: }
255: // // Set up the RelayFeed
256: // DataFeed relay_feed = new PromiscuousRelayDataFeed(rss_dependencies);
257: // RSS.instance().registerFeed(relay_feed, "Relay");
258: // Create and notify the context
259: ResourceContext context = RSS.instance().resolveSpec(node.kind,
260: node.parameters);
261: if (context != null) {
262: context.setDependencies(node_dependencies);
263: }
264: if (eventLogger.isInfoEnabled()) {
265: eventLogger.info("Method exit: " + logmsg);
266: }
267:
268: }
269:
270: // An Observer which listens for a callback from a
271: // BoundDataFormula. If it gets one it fills in a
272: // DataValueHolder with the value in the callback and wakes up
273: // the waitForCallback thread.
274: private class FormulaObserver implements java.util.Observer {
275: DataValueHolder result;
276: NotificationQualifier qualifier;
277: boolean succeeded = false;
278:
279: FormulaObserver(DataValueHolder result,
280: NotificationQualifier qualifier) {
281: this .result = result;
282: this .qualifier = qualifier;
283: }
284:
285: public void update(java.util.Observable o, Object value) {
286: synchronized (this ) {
287: // fill in 'result' from value
288: DataValue v = (DataValue) value;
289: if (v != null && qualifier.shouldNotify(v)) {
290: result.value = v.getCorbaValue();
291: succeeded = true;
292: if (eventLogger.isInfoEnabled()) {
293: eventLogger.info("value = " + v);
294: }
295: this .notifyAll();
296: }
297: }
298: }
299: }
300:
301: private boolean waitForCallback(BoundDataFormula bdf, long timeout,
302: NotificationQualifier qualifier, DataValueHolder result) {
303: FormulaObserver observer = new FormulaObserver(result,
304: qualifier);
305: bdf.addObserver(observer);
306: Runnable creator = bdf.getDelayedFormulaCreator();
307: Thread thread = new Thread(creator);
308: synchronized (observer) {
309: thread.start();
310: try {
311: observer.wait(timeout);
312: } catch (InterruptedException ex) {
313: }
314: }
315:
316: if (!observer.succeeded) {
317: eventLogger.warn("blockingQuery timed out");
318: result.value = DataValue.NO_VALUE.getCorbaValue();
319: }
320: bdf.deleteObserver(observer);
321: bdf.unsubscribe();
322: return observer.succeeded;
323: }
324:
325: // The two blockingQuery calls should take a qualifier. For now
326: // used a canned one that just ensures the value has positive
327: // credibility.
328: private static final NotificationQualifier Not_No_Value = new NotificationQualifier() {
329: public boolean shouldNotify(DataValue value) {
330: return value.getCredibility() > 0.0;
331: }
332: };
333:
334: public boolean blockingQuery_s(String path_string, long timeout,
335: DataValueHolder result)
336: throws ResourceDescriptionParseException {
337:
338: ResourceNode[] path = PathParser.parsePath(path_string);
339: return blockingQuery(path, timeout, result);
340: }
341:
342: public boolean blockingQuery(ResourceNode[] path, long timeout,
343: DataValueHolder result) {
344: boolean success = false;
345: String logmsg = null;
346:
347: if (eventLogger.isInfoEnabled()) {
348: StringBuffer buf = new StringBuffer();
349: buf.append("blockingQuery path = ");
350: RSSUtils.pathToString(buf, path);
351: logmsg = buf.toString();
352: eventLogger.info("Method entry: " + logmsg);
353: }
354:
355: try {
356: BoundDataFormula bdf = new BoundDataFormula(path, true,
357: null);
358: success = waitForCallback(bdf, timeout, Not_No_Value,
359: result);
360: } catch (NullFormulaException ex) {
361: // Can't be null
362: eventLogger.warn("Invalid formula");
363: result.value = DataValue.NO_VALUE.getCorbaValue();
364: success = false;
365: }
366: if (eventLogger.isInfoEnabled()) {
367: eventLogger.info("Method exit: " + logmsg + " returning "
368: + success);
369: }
370: return success;
371: }
372:
373: public boolean query_s(String path_string, DataValueHolder result)
374: throws ResourceDescriptionParseException {
375:
376: ResourceNode[] path = PathParser.parsePath(path_string);
377: return query(path, result);
378: }
379:
380: public boolean query(ResourceNode[] path, DataValueHolder result) {
381: boolean success = false;
382: String logmsg = null;
383:
384: if (eventLogger.isInfoEnabled()) {
385: StringBuffer buf = new StringBuffer();
386: buf.append("query path = ");
387: RSSUtils.pathToString(buf, path);
388: logmsg = buf.toString();
389: eventLogger.info("Method entry: " + logmsg);
390: }
391:
392: DataFormula formula = null;
393: formula = RSS.instance().getPathFormula(path);
394:
395: if (formula != null) {
396: DataValue v = formula.computeValue(true); // ??
397: result.value = v.getCorbaValue();
398: if (eventLogger.isInfoEnabled()) {
399: eventLogger.info("value = " + v);
400: }
401: success = true;
402: } else {
403: // Can't be null
404: eventLogger.warn("Invalid formula");
405: result.value = DataValue.NO_VALUE.getCorbaValue();
406: success = false;
407: }
408:
409: if (eventLogger.isInfoEnabled()) {
410: eventLogger.info("Method exit: " + logmsg + " returning "
411: + success);
412: }
413:
414: return success;
415: }
416:
417: public QualifierFactory getQualifierFactory(QualifierKind kind) {
418: if (eventLogger.isInfoEnabled()) {
419: eventLogger.info("getQualifierFactory: " + kind);
420: }
421: int tag = kind.value();
422: return factories[tag];
423: }
424:
425: public boolean qualifiedSubscribe_s(RSSSubscriber subscriber,
426: String path_string, int callback_id, Qualifier qualifier)
427: throws ResourceDescriptionParseException {
428: ResourceNode[] path = PathParser.parsePath(path_string);
429: return qualifiedSubscribe(subscriber, path, callback_id,
430: qualifier);
431: }
432:
433: public boolean qualifiedSubscribe(RSSSubscriber subscriber,
434: ResourceNode[] path, int callback_id, Qualifier qualifier) {
435: String logmsg = null;
436: boolean success = false;
437: if (eventLogger.isInfoEnabled()) {
438: StringBuffer buf = new StringBuffer();
439: if (qualifier == null) {
440: buf.append("unqualifiedSubscribe ");
441: } else {
442: buf.append("qualifiedSubscribe ");
443: }
444: buf.append(" path = ");
445: RSSUtils.pathToString(buf, path);
446: if (qualifier != null) {
447: buf.append(" qualifier type: ");
448: buf.append(qualifier.getClass());
449: }
450: logmsg = buf.toString();
451: eventLogger.info("Method entry: " + logmsg);
452: }
453: NotificationQualifier nqualifier = null;
454: if (qualifier != null) {
455: try {
456: nqualifier = (NotificationQualifier) CorbaUtils.poa
457: .reference_to_servant(qualifier);
458: } catch (Exception ex) {
459: eventLogger.error(ex.toString(), ex);
460: }
461: }
462: try {
463: BoundDataFormula bdf = new BoundDataFormula(path, true,
464: nqualifier);
465: RSSSubscriberProxy proxy = new RSSSubscriberProxy(bdf,
466: subscriber, callback_id, this );
467: synchronized (subscribers) {
468: List<RSSSubscriberProxy> proxies = subscribers
469: .get(subscriber);
470: if (proxies == null) {
471: proxies = new ArrayList<RSSSubscriberProxy>();
472: subscribers.put(subscriber, proxies);
473: }
474: proxies.add(proxy);
475: }
476: Runnable r = bdf.getDelayedFormulaCreator();
477: RSSUtils.schedule(r, 500);
478: success = true;
479: } catch (Exception ex) {
480: eventLogger.error(ex.toString(), ex);
481: success = false;
482: }
483:
484: if (eventLogger.isInfoEnabled()) {
485: eventLogger.info("Method exit: " + logmsg + " returning = "
486: + success);
487: }
488: return success;
489:
490: }
491:
492: public boolean unqualifiedSubscribe_s(RSSSubscriber subscriber,
493: String path_string, int callback_id)
494: throws ResourceDescriptionParseException {
495: ResourceNode[] path = PathParser.parsePath(path_string);
496: return qualifiedSubscribe(subscriber, path, callback_id, null);
497: }
498:
499: public boolean unqualifiedSubscribe(RSSSubscriber subscriber,
500: ResourceNode[] path, int callback_id) {
501: return qualifiedSubscribe(subscriber, path, callback_id, null);
502: }
503:
504: public void unsubscribe_s(RSSSubscriber subscriber,
505: String path_string)
506: throws ResourceDescriptionParseException {
507: ResourceNode[] path = PathParser.parsePath(path_string);
508: unsubscribe(subscriber, path);
509: }
510:
511: public void unsubscribe(RSSSubscriber subscriber,
512: ResourceNode[] path) {
513: String logmsg = null;
514:
515: if (eventLogger.isInfoEnabled()) {
516: StringBuffer buf = new StringBuffer();
517: buf.append("unsubscribe path = ");
518: RSSUtils.pathToString(buf, path);
519: logmsg = buf.toString();
520: eventLogger.info("Method entry: " + logmsg);
521: }
522: synchronized (subscribers) {
523: List<RSSSubscriberProxy> proxies = subscribers
524: .get(subscriber);
525: if (proxies != null) {
526: Iterator<RSSSubscriberProxy> itr = proxies.iterator();
527: while (itr.hasNext()) {
528: RSSSubscriberProxy proxy = itr.next();
529: if (proxy.hasPath(path)) {
530: proxy.unbind();
531: itr.remove();
532: break;
533: }
534: }
535: }
536: }
537:
538: if (eventLogger.isInfoEnabled()) {
539: eventLogger.info("Method exit: " + logmsg);
540: }
541: }
542:
543: // Standalone CORBA-accessible RSS
544: public static void main(String[] args) {
545: CorbaUtils.main(args, new ResourceStatusServiceImpl());
546: }
547:
548: // NotificationQualifier classes
549:
550: private static class EveryQualifier extends QualifierPOA implements
551: NotificationQualifier {
552: Qualifier[] qualifiers;
553:
554: EveryQualifier(Qualifier[] qualifiers) {
555: this .qualifiers = qualifiers;
556: }
557:
558: public boolean shouldNotify(DataValue value) {
559: for (Qualifier element : qualifiers) {
560: NotificationQualifier qualifier = (NotificationQualifier) element;
561: if (!qualifier.shouldNotify(value)) {
562: return false;
563: }
564: }
565: return true;
566: }
567:
568: public void getAttribute(String attr_name,
569: data_valueHolder attr_value)
570: throws NoSuchAttributeException {
571: throw new NoSuchAttributeException(attr_name);
572: }
573:
574: public void setAttribute(String attr_name, data_value attr_value)
575: throws NoSuchAttributeException {
576: throw new NoSuchAttributeException(attr_name);
577: }
578: }
579:
580: private static class SomeQualifier extends QualifierPOA implements
581: NotificationQualifier {
582: Qualifier[] qualifiers;
583:
584: SomeQualifier(Qualifier[] qualifiers) {
585: this .qualifiers = qualifiers;
586: }
587:
588: public boolean shouldNotify(DataValue value) {
589: for (Qualifier element : qualifiers) {
590: NotificationQualifier qualifier = (NotificationQualifier) element;
591: if (qualifier.shouldNotify(value)) {
592: return true;
593: }
594: }
595: return false;
596: }
597:
598: public void getAttribute(String attr_name,
599: data_valueHolder attr_value)
600: throws NoSuchAttributeException {
601: throw new NoSuchAttributeException(attr_name);
602: }
603:
604: public void setAttribute(String attr_name, data_value attr_value)
605: throws NoSuchAttributeException {
606: throw new NoSuchAttributeException(attr_name);
607: }
608: }
609:
610: private static abstract class ThresholdQualifierPOA extends
611: QualifierPOA implements NotificationQualifier {
612: double threshold;
613:
614: ThresholdQualifierPOA(double threshold) {
615: this .threshold = threshold;
616: }
617:
618: public void getAttribute(String attr_name,
619: data_valueHolder holder)
620: throws BadAttributeValueException,
621: NoSuchAttributeException {
622: data_value attr_value = holder.value;
623: if (!attr_name.equals("threshold")) {
624: throw new NoSuchAttributeException(attr_name);
625: } else if (attr_value.discriminator() != data_types.number_data) {
626: throw new BadAttributeValueException(attr_name);
627: } else {
628: attr_value.d_value(threshold);
629: }
630: }
631:
632: public void setAttribute(String attr_name, data_value attr_value)
633: throws BadAttributeValueException,
634: NoSuchAttributeException {
635: if (!attr_name.equals("threshold")) {
636: throw new NoSuchAttributeException(attr_name);
637: } else if (attr_value.discriminator() != data_types.number_data) {
638: throw new BadAttributeValueException(attr_name);
639: } else {
640: this .threshold = attr_value.d_value();
641: }
642: }
643:
644: }
645:
646: private static class MinDeltaQualifier extends
647: ThresholdQualifierPOA {
648: DataValue last;
649:
650: MinDeltaQualifier(double threshold) {
651: super (threshold);
652: }
653:
654: boolean sufficientChange(DataValue value) {
655: double delta = value.getDoubleValue()
656: - last.getDoubleValue();
657: return delta < 0 ? -delta > threshold : delta > threshold;
658: }
659:
660: public boolean shouldNotify(DataValue value) {
661: if (last == null || sufficientChange(value)) {
662: last = value;
663: return true;
664: } else {
665: return false;
666: }
667: }
668:
669: }
670:
671: private static class MinCredibilityQualifier extends
672: ThresholdQualifierPOA {
673: MinCredibilityQualifier(double threshold) {
674: super (threshold);
675: }
676:
677: public boolean shouldNotify(DataValue value) {
678: return value.getCredibility() > threshold;
679: }
680:
681: }
682:
683: private static class ExceedsThresholdQualifier extends
684: ThresholdQualifierPOA {
685: ExceedsThresholdQualifier(double threshold) {
686: super (threshold);
687: }
688:
689: public boolean shouldNotify(DataValue value) {
690: return value.getDoubleValue() > threshold;
691: }
692:
693: }
694:
695: private static class CrossesThresholdQualifier extends
696: ThresholdQualifierPOA {
697: DataValue last;
698:
699: CrossesThresholdQualifier(double threshold) {
700: super (threshold);
701: }
702:
703: boolean sufficientChange(DataValue value) {
704: double delta = value.getDoubleValue()
705: - last.getDoubleValue();
706: return delta < 0 ? -delta > threshold : delta > threshold;
707: }
708:
709: public boolean shouldNotify(DataValue value) {
710: boolean notify = false;
711: if (last == null) {
712: // first time
713: notify = value.getDoubleValue() > threshold;
714: } else if (last.getDoubleValue() <= threshold) {
715: // was below
716: notify = value.getDoubleValue() > threshold;
717: } else {
718: // was above
719: notify = value.getDoubleValue() <= threshold;
720: }
721: last = value;
722: return notify;
723: }
724:
725: }
726:
727: private static Qualifier getQualifierReference(QualifierPOA impl) {
728: org.omg.CORBA.Object reference = null;
729: try {
730: CorbaUtils.poa.activate_object(impl);
731: reference = CorbaUtils.poa.servant_to_reference(impl);
732: } catch (Exception ex) {
733: Logger logger = Logging
734: .getLogger(ResourceStatusServiceImpl.class);
735: logger.error(ex.toString(), ex);
736: }
737: return QualifierHelper.narrow(reference);
738: }
739:
740: private static class EveryQualifierFactoryImpl extends
741: EveryQualifierFactoryPOA {
742: public Qualifier getQualifier(Qualifier[] qualifiers) {
743: QualifierPOA impl = new EveryQualifier(qualifiers);
744: return getQualifierReference(impl);
745: }
746: }
747:
748: private static class SomeQualifierFactoryImpl extends
749: SomeQualifierFactoryPOA {
750: public Qualifier getQualifier(Qualifier[] qualifiers) {
751: QualifierPOA impl = new SomeQualifier(qualifiers);
752: return getQualifierReference(impl);
753: }
754: }
755:
756: private static class MinDeltaQualifierFactoryImpl extends
757: MinDeltaQualifierFactoryPOA {
758: public Qualifier getQualifier(double threshold) {
759: QualifierPOA impl = new MinDeltaQualifier(threshold);
760: return getQualifierReference(impl);
761: }
762: }
763:
764: private static class ExceedsThresholdQualifierFactoryImpl extends
765: ExceedsThresholdQualifierFactoryPOA {
766: public Qualifier getQualifier(double threshold) {
767: QualifierPOA impl = new ExceedsThresholdQualifier(threshold);
768: return getQualifierReference(impl);
769: }
770: }
771:
772: private static class CrossesThresholdQualifierFactoryImpl extends
773: CrossesThresholdQualifierFactoryPOA {
774: public Qualifier getQualifier(double threshold) {
775: QualifierPOA impl = new CrossesThresholdQualifier(threshold);
776: return getQualifierReference(impl);
777: }
778: }
779:
780: private static class MinCredibilityQualifierFactoryImpl extends
781: MinCredibilityQualifierFactoryPOA {
782: public Qualifier getQualifier(double threshold) {
783: QualifierPOA impl = new MinCredibilityQualifier(threshold);
784: return getQualifierReference(impl);
785: }
786: }
787:
788: }
|