001: /*
002: * <copyright>
003: *
004: * Copyright 2000-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.tools.csmart.society;
027:
028: import org.cougaar.core.component.ComponentDescription;
029: import org.cougaar.tools.csmart.core.cdata.ComponentData;
030: import org.cougaar.tools.csmart.core.property.*;
031: import org.cougaar.tools.csmart.core.property.name.CompositeName;
032: import org.cougaar.tools.csmart.ui.viewer.CSMART;
033: import org.cougaar.util.log.Logger;
034:
035: import java.io.IOException;
036: import java.io.ObjectInputStream;
037: import java.util.Collection;
038: import java.util.Iterator;
039:
040: /**
041: * Abstract base-class for Agents
042: * Implementers must take care of ensuring that Plugins, Binders,
043: * AssetData (and soon other misc components) are added.
044: */
045: public abstract class AgentBase extends ModifiableConfigurableComponent
046: implements AgentComponent, PropertiesListener {
047:
048: private transient Logger log;
049: protected String classname;
050: protected boolean modified = true;
051:
052: /** Agent Classname Property Definitions **/
053: private static final String DEFAULT_CLASS = "org.cougaar.core.agent.SimpleAgent";
054:
055: /** Classname Property Definition **/
056: public static final String PROP_CLASSNAME = "Classname";
057:
058: /** Classname Description Property Definition **/
059: public static final String PROP_CLASSNAME_DESC = "Name of the Agent Class";
060:
061: /**
062: * Creates a new <code>AgentBase</code> instance.
063: *
064: * @param name Name of the new Component
065: * @param classname Classname for the agent
066: */
067: public AgentBase(String name, String classname) {
068: super (name);
069: this .classname = classname;
070: createLogger();
071: if (log.isDebugEnabled()) {
072: log.debug("Creating Agent: " + name);
073: }
074: installListeners();
075: }
076:
077: public AgentBase(String name) {
078: this (name, AgentBase.DEFAULT_CLASS);
079: }
080:
081: private void createLogger() {
082: log = CSMART.createLogger(this .getClass().getName());
083: }
084:
085: /**
086: * Initialize all local properties
087: *
088: */
089: public void initProperties() {
090: Property p = addProperty(PROP_CLASSNAME, new String(classname));
091: p.setToolTip(PROP_CLASSNAME_DESC);
092: }
093:
094: /**
095: * Adds any relevent <code>ComponentData</code> for this component.
096: * This method does not modify any existing <code>ComponentData</code>
097: * Warning: This expects to be handed itself
098: *
099: * @see ComponentData
100: * @param data Pointer to the global <code>ComponentData</code>
101: * @return an updated <code>ComponentData</code> object
102: */
103: public ComponentData addComponentData(ComponentData data) {
104: if (data.getType() != ComponentData.AGENT) {
105: if (log.isErrorEnabled()) {
106: log.error("Got a non-Agent to be self: " + data);
107: }
108: // FIXME: Try to recover
109: return data;
110: }
111:
112: // When this was created we did agent.getShortName().
113: // Is name the same thing?
114: if (!data.getName().equals(this .getShortName())) {
115: if (log.isErrorEnabled()) {
116: log.error("Got an agent with wrong name to be self: "
117: + data + ". My name is " + this .getShortName());
118: }
119: // FIXME: Try to recover??
120: return data;
121: }
122:
123: data.setClassName(getAgentClassName());
124:
125: // I assume the society set the owner & parent
126: // And I explicitly wont set any properties
127:
128: // Process AssetData
129: Iterator iter = ((Collection) getDescendentsOfClass(AssetComponent.class))
130: .iterator();
131: while (iter.hasNext()) {
132: AssetComponent asset = (AssetComponent) iter.next();
133: asset.addComponentData(data);
134: }
135:
136: // Process all other components.
137: iter = ((Collection) getDescendentsOfClass(ContainerBase.class))
138: .iterator();
139: while (iter.hasNext()) {
140: ContainerBase container = (ContainerBase) iter.next();
141: if (container.getShortName().equals("Binders")
142: || container.getShortName().equals("Plugins")
143: || container.getShortName().equals(
144: "Other Components")) {
145: for (int i = 0; i < container.getChildCount(); i++) {
146: BaseComponent base = (BaseComponent) container
147: .getChild(i);
148: base.addComponentData(data);
149: }
150: }
151: }
152:
153: return data;
154: }
155:
156: /**
157: * Gets the classname for this agent
158: *
159: * @return a <code>String</code> value
160: */
161: public String getAgentClassName() {
162: Property p = getProperty(PROP_CLASSNAME);
163: if (p != null) {
164: Object o = p.getValue();
165: if (o != null)
166: return o.toString();
167: }
168: return DEFAULT_CLASS;
169: }
170:
171: /**
172: * Sets the classname for this agent
173: *
174: * @param aClass new agent classname
175: */
176: public void setAgentClassName(String aClass) {
177: if (aClass == null)
178: return;
179: aClass = aClass.trim();
180: Property p = getProperty(PROP_CLASSNAME);
181: if (p != null) {
182: Object o = p.getValue();
183: if (o != null && o.equals(aClass))
184: return;
185: else
186: p.setValue(aClass);
187: } else {
188: addProperty(PROP_CLASSNAME, aClass);
189: }
190: }
191:
192: /**
193: * Tests equality for agents.
194: * Agents are equal if they have the same short name.
195: * @param o Object to test for equality
196: * @return returns true if the object is an AgentComponent with same name
197: */
198: public boolean equals(Object o) {
199: // if (log.isDebugEnabled())
200: // log.debug(this + ": AgentBase.equals with other: " + o);
201:
202: if (this == o)
203: return true;
204:
205: if (o instanceof AgentComponent) {
206: AgentComponent that = (AgentComponent) o;
207: if (!this .getShortName().equals(that.getShortName())) {
208: return false;
209: }
210: return true;
211: }
212: return false;
213: }
214:
215: /**
216: * Has this agent been modified, such that a save would do something.
217: *
218: * @return a <code>boolean</code>, false if no save necessary
219: */
220: public boolean isModified() {
221: return modified;
222: }
223:
224: /**
225: * Set the internal modified flag (returned by isModified)
226: * and fire a modification event.
227: */
228: public void fireModification() {
229: modified = true;
230: super .fireModification();
231: }
232:
233: // agents listen on all properties, because subcomponents
234: // of agents don't have listeners on them
235:
236: private void installListeners() {
237: addPropertiesListener(this );
238: for (Iterator i = getPropertyNames(); i.hasNext();) {
239: Property p = getProperty((CompositeName) i.next());
240: p.addPropertyListener(myPropertyListener);
241: }
242: }
243:
244: public void propertyAdded(PropertyEvent e) {
245: Property addedProperty = e.getProperty();
246: setPropertyVisible(addedProperty, true);
247: addedProperty.addPropertyListener(myPropertyListener);
248: fireModification();
249: }
250:
251: public void propertyRemoved(PropertyEvent e) {
252: e.getProperty().removePropertyListener(myPropertyListener);
253: fireModification();
254: }
255:
256: PropertyListener myPropertyListener = new PropertyListener() {
257: public void propertyValueChanged(PropertyEvent e) {
258: fireModification();
259: }
260:
261: public void propertyOtherChanged(PropertyEvent e) {
262: fireModification();
263: }
264: };
265:
266: ModificationListener myModificationListener = new MyModificationListener();
267:
268: public int addChild(ComposableComponent c) {
269: ((ModifiableConfigurableComponent) c)
270: .addModificationListener(myModificationListener);
271: fireModification();
272: return super .addChild(c);
273: }
274:
275: public void removeChild(ComposableComponent c) {
276: ((ModifiableConfigurableComponent) c)
277: .removeModificationListener(myModificationListener);
278: fireModification();
279: super .removeChild(c);
280: }
281:
282: private void readObject(ObjectInputStream ois) throws IOException,
283: ClassNotFoundException {
284: ois.defaultReadObject();
285: createLogger();
286: modified = false;
287: installListeners();
288: }
289:
290: class MyModificationListener implements ModificationListener,
291: ConfigurableComponentListener {
292: public void modified(ModificationEvent e) {
293: fireModification();
294: }
295: }
296:
297: } // end of AgentBase
|