001: /**
002: * <copyright>
003: *
004: * Copyright 2002-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */package org.cougaar.pizza.plugin;
026:
027: import org.cougaar.core.blackboard.IncrementalSubscription;
028: import org.cougaar.core.plugin.ComponentPlugin;
029: import org.cougaar.core.relay.Relay;
030: import org.cougaar.core.service.LoggingService;
031: import org.cougaar.pizza.Constants;
032: import org.cougaar.pizza.relay.RSVPRelayTarget;
033: import org.cougaar.pizza.relay.RSVPReply;
034: import org.cougaar.pizza.plugin.util.PizzaPreferenceHelper;
035: import org.cougaar.planning.ldm.asset.Entity;
036: import org.cougaar.util.UnaryPredicate;
037:
038: import java.util.Collection;
039: import java.util.Iterator;
040:
041: /**
042: * Reply to the RSVP relay invitation with the kind of pizza we like.
043: * <p/>
044: * Makes a new RSVPReply and sets the name of
045: * the guest (this agent) and their pizza preference, based on the PGs on the self Entity.
046: * Put the RSVPReply on the relay and sends the response back.
047: */
048: public class RSVPPlugin extends ComponentPlugin {
049:
050: private LoggingService log;
051:
052: private IncrementalSubscription relaySubscription;
053:
054: /**
055: * Set up the services we need - logging service
056: */
057: public void load() {
058: super .load();
059:
060: // get services
061: log = (LoggingService) getServiceBroker().getService(this ,
062: LoggingService.class, null);
063:
064: if (log.isDebugEnabled()) {
065: log.debug("plugin loaded, services found");
066: }
067: }
068:
069: /**
070: * We have one subscription, to the relays (the invitation) we expect to
071: * get.
072: */
073: protected void setupSubscriptions() {
074: if (log.isDebugEnabled()) {
075: log.debug("setupSubscriptions");
076: }
077:
078: // create relay subscription
079: // Note that blackboard is inherited from the BlackboardClientComponent base class
080: // (ComponentPlugin extends BlackboardClientComponent.)
081: relaySubscription = (IncrementalSubscription) blackboard
082: .subscribe(new InvitePred());
083: }
084:
085: /**
086: * Watch for incoming RSVPRelays. Then search our local Entity's topping PGs,
087: * and set that preference on a response to the relay.
088: */
089: protected void execute() {
090: if (log.isDebugEnabled()) {
091: log.debug("execute");
092: }
093:
094: // observe added relays
095: for (Iterator iter = relaySubscription.getAddedCollection()
096: .iterator(); iter.hasNext();) {
097: RSVPRelayTarget relay = (RSVPRelayTarget) iter.next();
098:
099: if (log.isInfoEnabled()) {
100: log.info("Saw added " + relay);
101: }
102:
103: // check for expected invitation relay
104: if (Constants.INVITATION_QUERY.equals(relay.getQuery())) {
105: // get the self entity
106: Entity entity = getSelfEntity();
107: if (entity == null) {
108: // This is problematic.
109: if (log.isWarnEnabled())
110: log.warn("Couldn't find self Entity!");
111: }
112:
113: // determine if I like meat or veggie pizza using the
114: // PizzaPreferenceHelper, which looks at the Entity object's role
115: String preference = PizzaPreferenceHelper
116: .getPizzaPreference(log, entity);
117:
118: // send back reply
119: RSVPReply reply = new RSVPReply(getAgentIdentifier()
120: .toString(), preference);
121: relay.setResponse(reply);
122:
123: if (log.isInfoEnabled()) {
124: log.info("Replying: " + relay);
125: }
126:
127: blackboard.publishChange(relay);
128: } else {
129: if (log.isInfoEnabled())
130: log.info("Ignoring non-invite relay " + relay);
131: }
132: }
133:
134: // Print the removed relays for debugging
135: if (log.isDebugEnabled()) {
136: // removed relays
137: for (Iterator iter = relaySubscription
138: .getRemovedCollection().iterator(); iter.hasNext();) {
139: Object sr = iter.next();
140: log.debug("observed removed " + sr);
141: }
142: }
143: }
144:
145: /**
146: * Do a blackboard query to get the self Entity.
147: * Looks for entities that have the same item id as my agent id.
148: * @return self Entity, null if not found
149: */
150: protected Entity getSelfEntity() {
151: // get the self entity
152: Collection entities = blackboard.query(new UnaryPredicate() {
153: public boolean execute(Object o) {
154: if (o instanceof Entity) {
155: return ((Entity) o).isLocal();
156: } else {
157: return false;
158: }
159: }
160: });
161:
162: // there should be only one self entity
163: if (!entities.isEmpty()) {
164: return (Entity) entities.iterator().next();
165: } else {
166: return null;
167: }
168: }
169:
170: /**
171: * My subscription predicate, which matches RSVPRelayTargets
172: */
173: private class InvitePred implements UnaryPredicate {
174: public boolean execute(Object o) {
175: return (o instanceof RSVPRelayTarget);
176: }
177: }
178: } // end of RSVPPlugin
|