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:
027: package org.cougaar.tools.csmart.experiment;
028:
029: import org.cougaar.tools.csmart.core.property.ModifiableConfigurableComponent;
030: import org.cougaar.tools.csmart.core.property.Property;
031: import org.cougaar.tools.csmart.society.AgentComponent;
032: import org.cougaar.tools.csmart.ui.viewer.CSMART;
033: import org.cougaar.tools.csmart.util.ReadOnlyProperties;
034: import org.cougaar.util.log.Logger;
035:
036: import java.io.IOException;
037: import java.io.ObjectInputStream;
038: import java.io.Serializable;
039: import java.util.ArrayList;
040: import java.util.Collections;
041: import java.util.List;
042: import java.util.Observable;
043: import java.util.Observer;
044: import java.util.Properties;
045: import java.util.Enumeration;
046:
047: /**
048: * Maintains information about a node and generates the
049: * node .ini file.
050: * @property org.cougaar.node.name is the name of the Node as it will be passed to the running process
051: **/
052: public class ExperimentNode extends ModifiableConfigurableComponent
053: implements Serializable, NodeComponent {
054: private static final long serialVersionUID = 253490717511962460L;
055:
056: public static final String DEFAULT_NODE_NAME = "DefaultNode";
057:
058: private List agents = new ArrayList();
059: private Experiment experiment;
060: private ReadOnlyProperties arguments = null;
061: private transient Logger log;
062:
063: public ExperimentNode(String nodeName, Experiment experiment) {
064: super (nodeName);
065: this .experiment = experiment;
066: addProperty("Experiment", experiment);
067: addDefaultArgumentsToNode(nodeName);
068: createLogger();
069: }
070:
071: private void createLogger() {
072: log = CSMART.createLogger(this .getClass().getName());
073: }
074:
075: public void initProperties() {
076: addProperty("AgentNames", new ArrayList());
077: }
078:
079: public boolean equals(Object o) {
080: if (this == o)
081: return true;
082: if (o instanceof ExperimentNode) {
083: return getShortName().equals(
084: ((ExperimentNode) o).getShortName());
085: } else {
086: return false;
087: }
088: }
089:
090: /**
091: * Adds node name as an argument to the node.
092: */
093:
094: // add an observer to my arguments
095: // if the caller changes these arguments,
096: // notify my modification listeners
097: private transient Observer myObserver = null;
098:
099: private void createObserver() {
100: if (myObserver == null) {
101: myObserver = new Observer() {
102: public void update(final Observable o, final Object arg) {
103: ExperimentNode.this .fireModification();
104: }
105: };
106: arguments.addObserver(myObserver);
107: }
108: }
109:
110: private void addDefaultArgumentsToNode(String nodeName) {
111: arguments = new ReadOnlyProperties(Collections
112: .singleton(Experiment.NODE_NAME), experiment
113: .getDefaultNodeArguments());
114: createObserver();
115: arguments.setReadOnlyProperty(Experiment.NODE_NAME, nodeName);
116: }
117:
118: public void rename(String newName) {
119: arguments.setReadOnlyProperty(Experiment.NODE_NAME, newName);
120: setName(newName); // invokes setName in ConfigurableComponent
121: }
122:
123: private int getAgentCount() {
124: return agents.size();
125: }
126:
127: public AgentComponent[] getAgents() {
128: return (AgentComponent[]) agents
129: .toArray(new AgentComponent[getAgentCount()]);
130: }
131:
132: public void addAgent(AgentComponent agent) {
133: Property prop = getProperty("AgentNames");
134: if (prop == null)
135: prop = addProperty("AgentNames", new ArrayList());
136: ArrayList names = (ArrayList) prop.getValue();
137: names.add(agent.getShortName());
138: // if(log.isDebugEnabled()) {
139: // log.debug("ExperimentNode: " + getShortName() +
140: // " added agent: " + agent.getShortName());
141: // }
142: agents.add(agent);
143: fireModification();
144: }
145:
146: public AgentComponent getAgent(int ix) {
147: return (AgentComponent) agents.get(ix);
148: }
149:
150: public void removeAgent(AgentComponent agent) {
151: Property prop = getProperty("AgentNames");
152: if (prop != null) {
153: ArrayList names = (ArrayList) prop.getValue();
154: int index = names.indexOf(agent.getShortName());
155: if (index != -1)
156: names.remove(agent.getShortName());
157: }
158: if (log.isDebugEnabled()) {
159: log.debug("ExperimentNode: " + getShortName()
160: + " removed agent: " + agent.getShortName());
161: }
162: agents.remove(agent);
163: fireModification();
164: }
165:
166: public void dispose() {
167: agents.clear();
168: fireModification();
169: }
170:
171: /**
172: * Set arguments.
173: */
174:
175: public void setArguments(Properties arguments) {
176: Enumeration keys = arguments.keys();
177: while (keys.hasMoreElements()) {
178: String key = (String) keys.nextElement();
179: this .arguments.setReadOnlyProperty(key, arguments
180: .getProperty(key));
181: }
182: }
183:
184: public void addArgument(String name, Object value) {
185: if (this .arguments.containsKey(name)
186: && this .arguments.get(name) == value) {
187: if (log.isDebugEnabled()) {
188: log.debug("Value already exists, skipping.");
189: }
190:
191: } else {
192: this .arguments.setReadOnlyProperty(name, (String) value);
193: }
194: }
195:
196: /**
197: * Get arguments.
198: */
199:
200: public Properties getArguments() {
201: return arguments;
202: }
203:
204: /**
205: * Copy this node and return the new node.
206: * @param experimentCopy experiment which will contain this node
207: */
208:
209: public NodeComponent copy(Experiment experimentCopy) {
210: NodeComponent nodeCopy = new ExperimentNode(getShortName(),
211: experimentCopy);
212: Properties newProps = nodeCopy.getArguments();
213: newProps.clear();
214: newProps.putAll(getArguments());
215:
216: // FIXME: Copy the other Properties (description, etc)
217: // Just want to avoid copying the Property named "AgentNames"
218: return nodeCopy;
219: }
220:
221: private void readObject(ObjectInputStream ois) throws IOException,
222: ClassNotFoundException {
223: ois.defaultReadObject();
224: createLogger();
225: createObserver();
226: }
227:
228: }
|