001: /*
002: * <copyright>
003: *
004: * Copyright 2003-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: */
026: package org.cougaar.logistics.plugin.manager;
027:
028: import java.util.Collection;
029: import java.util.Collections;
030: import java.util.HashSet;
031: import java.util.Iterator;
032: import java.util.Set;
033:
034: import org.cougaar.core.mts.MessageAddress;
035: import org.cougaar.core.relay.Relay;
036: import org.cougaar.core.util.UID;
037: import org.cougaar.core.util.UniqueObject;
038:
039: /**
040: * Implementation of RelayAdapter.
041: * Declared abstract because it does not include the ability to convey content.
042: * Extenders are responsible for defining content semantics.
043: **/
044: abstract public class RelayAdapter implements Relay.Source,
045: Relay.Target, UniqueObject, Cloneable {
046:
047: private transient Set myTargetSet = null;
048:
049: private UID myUID = null;
050: private MessageAddress mySource = null;
051:
052: /**
053: * Add a target message address.
054: * @param target the address of the target agent.
055: **/
056: public void addTarget(MessageAddress target) {
057: if (myTargetSet == null) {
058: myTargetSet = new HashSet();
059: }
060: myTargetSet.add(target);
061: }
062:
063: /**
064: * Add a collection of target message addresses.
065: * @param targets Collection of target agent addresses.
066: **/
067: public void addAllTargets(Collection targets) {
068: if (myTargetSet == null) {
069: myTargetSet = new HashSet();
070: }
071:
072: for (Iterator iterator = targets.iterator(); iterator.hasNext();) {
073: Object target = iterator.next();
074: if (target instanceof MessageAddress) {
075: addTarget((MessageAddress) target);
076: } else {
077: throw new IllegalArgumentException(
078: "Invalid target class: "
079: + target.getClass()
080: + " all targets must extend MessageAddress.");
081: }
082: }
083: }
084:
085: /**
086: * Remove a target message address.
087: * @param target the address of the target agent to be removed.
088: **/
089: public void removeTarget(MessageAddress target) {
090: if (myTargetSet != null) {
091: myTargetSet.remove(target);
092: }
093: }
094:
095: public void clearTargets() {
096: myTargetSet = null;
097: }
098:
099: // UniqueObject interface
100: /** @return the UID of a UniqueObject. If the object was created
101: * correctly (e.g. via a Factory), will be non-null.
102: **/
103: public UID getUID() {
104: return myUID;
105: }
106:
107: /** set the UID of a UniqueObject. This should only be done by
108: * an LDM factory. Will throw a RuntimeException if
109: * the UID was already set.
110: **/
111: public void setUID(UID uid) {
112: if (myUID != null) {
113: RuntimeException rt = new RuntimeException(
114: "Attempt to call setUID() more than once.");
115: throw rt;
116: }
117:
118: myUID = uid;
119: }
120:
121: // Relay.Source interface
122:
123: /**
124: * @return MessageAddress of the source
125: */
126: public MessageAddress getSource() {
127: return mySource;
128: }
129:
130: /** set the MessageAddress of the source. This should only be done by
131: * an LDM factory. Will throw a RuntimeException if
132: * the source was already set.
133: **/
134: public void setSource(MessageAddress source) {
135: if (mySource != null) {
136: RuntimeException rt = new RuntimeException(
137: "Attempt to call setSource() more than once.");
138: throw rt;
139: }
140: mySource = source;
141: }
142:
143: /**
144: * Get all the addresses of the target agents to which this Relay
145: * should be sent.
146: **/
147: public Set getTargets() {
148: Set targets = (myTargetSet == null) ? Collections.EMPTY_SET
149: : Collections.unmodifiableSet(myTargetSet);
150: return targets;
151: }
152:
153: /**
154: * Set the addresses of the target agents to which this Relay
155: * should be sent.
156: **/
157: public void setTargets(Set targets) {
158: myTargetSet = targets;
159: }
160:
161: /**
162: * Get an object representing the value of this Relay suitable
163: * for transmission. This implementation uses itself to represent
164: * its Content.
165: **/
166: public Object getContent() {
167: return this ;
168: }
169:
170: protected boolean contentChanged(RelayAdapter newCCN) {
171: return false;
172: }
173:
174: private static final class SimpleRelayFactory implements
175: TargetFactory, java.io.Serializable {
176:
177: public static final SimpleRelayFactory INSTANCE = new SimpleRelayFactory();
178:
179: private SimpleRelayFactory() {
180: }
181:
182: /**
183: * Convert the given content and related information into a Target
184: * that will be published on the target's blackboard.
185: **/
186: public Relay.Target create(UID uid, MessageAddress source,
187: Object content, Token token) {
188: RelayAdapter target = null;
189:
190: if (content instanceof RelayAdapter) {
191: RelayAdapter relayAdapter = (RelayAdapter) content;
192:
193: if (relayAdapter.myTargetSet != null) {
194: // intra-vm case so must clone
195: try {
196: target = (RelayAdapter) ((RelayAdapter) content)
197: .clone();
198:
199: // Relay.Target's should not have targets. Causes infinite loops
200: if (target != null) {
201: target.clearTargets();
202: }
203:
204: } catch (CloneNotSupportedException cnse) {
205: throw new IllegalArgumentException(
206: "content argument: " + content
207: + " does not support clone.");
208: }
209: } else {
210: target = relayAdapter;
211: }
212:
213: } else {
214: throw new IllegalArgumentException(
215: "content argument must extend RelayAdapter.");
216: }
217:
218: // Use arguments to customize the target.
219: if (!uid.equals(target.getUID())) {
220: throw new IllegalArgumentException(
221: "uid argument does not match source's UID.");
222: }
223: target.setSource(source);
224:
225: return target;
226: }
227:
228: private Object readResolve() {
229: return INSTANCE;
230: }
231: };
232:
233: /**
234: * Get a factory for creating the target.
235: */
236: public TargetFactory getTargetFactory() {
237: return SimpleRelayFactory.INSTANCE;
238: }
239:
240: /**
241: * Set the response that was sent from a target. For LP use only.
242: * This implemenation does nothing because responses are not needed
243: * or used.
244: **/
245: public int updateResponse(MessageAddress target, Object response) {
246: // No response expected
247: return Relay.NO_CHANGE;
248: }
249:
250: /**
251: * Get the current Response for this target. Null indicates that
252: * this target has no response.
253: */
254: public Object getResponse() {
255: return null;
256: }
257:
258: /**
259: * Update the target with the new content.
260: * @return true if the update changed the Relay, in which
261: * case the infrastructure should "publishChange" this
262: */
263: public int updateContent(Object content, Token token) {
264: return (contentChanged((RelayAdapter) content) ? Relay.CONTENT_CHANGE
265: : Relay.NO_CHANGE);
266: }
267:
268: protected Object clone() throws CloneNotSupportedException {
269: RelayAdapter clone;
270:
271: clone = (RelayAdapter) super .clone();
272:
273: // Make sure we have a distinct target hash set
274: clone.clearTargets();
275: if (getTargets().size() > 0) {
276: clone.addAllTargets(getTargets());
277: }
278: return clone;
279: }
280: }
|