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: */
026:
027: package org.cougaar.core.relay;
028:
029: import java.util.Set;
030:
031: import org.cougaar.core.mts.MessageAddress;
032: import org.cougaar.core.util.UID;
033: import org.cougaar.core.util.UniqueObject;
034:
035: /**
036: * A Relay is a blackboard object that allows a source agent
037: * to stream content changes to multiple target agents, and
038: * for each target to stream back a response.
039: * <p>
040: * The Relay API is a intended to be a generic mechanism for
041: * transfering data between agents. Specific subclasses and
042: * clients may not need the full Relay features, such as
043: * multiple-targets or target-responses.
044: */
045: public interface Relay extends UniqueObject {
046: // The kinds of changes caused by updateResponse and updateContent
047: int NO_CHANGE = 0;
048: int CONTENT_CHANGE = 1;
049: int RESPONSE_CHANGE = 2;
050:
051: // UID support from UniqueObject -- note that the
052: // Source and Target(s) all have the same UID.
053:
054: /**
055: * The source-side Relay, which contains the content and
056: * a set of target-addresses, and also receives response
057: * updates from the Target(s).
058: */
059: interface Source extends Relay {
060:
061: /**
062: * Get the addresses of the target agents to which this
063: * Relay should be sent.
064: */
065: Set getTargets();
066:
067: /**
068: * Get an object representing the value of this Relay
069: * suitable for transmission. Caution!!! The content should, in
070: * general <em>not</em> contain targets, source, responses,
071: * factories or anything else that is not essential for specifying
072: * the content. For implementations wishing to use the same class
073: * for implementing Relay.Source, Relay.Target, and Relay.Content,
074: * these non-essential items should be declared transient and
075: * writeObject and readObject methods written to serialize these
076: * items only for persistence, that is, only if the object streams
077: * are instances of PersistenceOutputStream or
078: * PersistenceInputStream.
079: * <p>Also, see the cautions for
080: * {@link #getTargetFactory getTargetFactory}
081: */
082: Object getContent();
083:
084: /**
085: * Get a factory for creating the target.
086: * Null indicates that the content can be directly cast into
087: * the Target object. Be wary of aliasing of the content between
088: * multiple agents in the same node. If the content is immutable,
089: * there is no problem, but if the content can be changed by
090: * either the source or target, the content should be cloned or
091: * otherwise used to create a new target object.
092: */
093: TargetFactory getTargetFactory();
094:
095: /**
096: * Update the source with the new response.
097: * @return NO_CHANGE if the update caused no change to the source<br>
098: * RESPONSE_CHANGED if the source is also a target and the
099: * incoming response requires that a new outgoing response be sent
100: * to the source.<br>
101: * CONTENT_CHANGED if the update has changed the content of
102: * the source<br>
103: * RESPONSE_CHANGED|CONTENT_CHANGED if both changes occurred
104: */
105: int updateResponse(MessageAddress target, Object response);
106: }
107:
108: /**
109: * The target-side Relay, which receives content updates and
110: * can send response updates back to the Source.
111: */
112: interface Target extends Relay {
113:
114: /**
115: * Get the address of the Agent holding the Source copy of this
116: * Relay. If null is returned, then responses will not be sent.
117: * @return the address from which this Relay came.
118: */
119: MessageAddress getSource();
120:
121: /**
122: * Get the current Response for this target. Null indicates that
123: * this target has no response.
124: */
125: Object getResponse();
126:
127: /**
128: * Update the target with the new content.
129: * @return NO_CHANGE if the update caused no change to the target<br>
130: * RESPONSE_CHANGED if the update has changed the response to
131: * be sent to the source.<br>
132: * CONTENT_CHANGED if the update has changed the content of
133: * the target<br>
134: * RESPONSE_CHANGED|CONTENT_CHANGED if both changes occurred
135: */
136: int updateContent(Object content, Token token);
137: }
138:
139: /**
140: * A factory for creating a Target from the Source's content.
141: */
142: interface TargetFactory {
143:
144: /**
145: * Convert the given content and related information into a
146: * Target, that will be published on the target's blackboard.
147: * <p>
148: * If the implementation simply casts the content into the
149: * Target then the Source can instead simply use:<pre>
150: * public TargetFactory getTargetFactory() { return null; }
151: * </pre>
152: * <p>
153: * Care must be taken when the same class implements both
154: * Relay.Source and Relay.Target. When a relay is transmitted between agents
155: * in the same node the received content is the same object as the
156: * source content. Usually, the factory should create a new
157: * instance to avoid aliasing pitfalls. The factory can avoid the
158: * expense of creating a new instance by taking advantage of the
159: * treatment of transient fields in the content. Such fields are
160: * initialized to default values when deserialized in another node
161: * and such default values can be used to detect that the content
162: * has already been copied and a new copy is not necessary.
163: * <p>
164: * Other implementations may create an instance of a different
165: * class that is just sufficient to implement the Relay.Target
166: * interface. In particular, the content can be trimmed to the
167: * minimal information needed to create the Target.
168: * <p>
169: * In some cases the UID and source address may be redundant
170: * with the content information; this information allows
171: * the content to be trimmed, such as just passing a String.
172: */
173: Relay.Target create(UID uid, MessageAddress source,
174: Object content, Token token);
175:
176: }
177:
178: /**
179: * An object that is passed from the Source to the Target(s), which
180: * authorizes content updates.
181: * <p>
182: * The Target implementation can optionally save the Token
183: * that was used in the factory "create" and later assert that
184: * all content-updates must pass the same Token instance.
185: */
186: class Token implements java.io.Serializable {
187: /** Restricted to infrastructure-only construction. */
188: Token() {
189: }
190: }
191: }
|