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.tools.csmart.society;
026:
027: import org.cougaar.core.agent.Agent;
028: import org.cougaar.core.agent.AgentManager;
029: import org.cougaar.core.component.ComponentDescription;
030: import org.cougaar.core.plugin.PluginManager;
031: import org.cougaar.tools.csmart.core.cdata.ComponentData;
032: import org.cougaar.tools.csmart.core.cdata.GenericComponentData;
033: import org.cougaar.tools.csmart.core.property.ModifiableConfigurableComponent;
034: import org.cougaar.tools.csmart.core.property.PropertiesListener;
035: import org.cougaar.tools.csmart.core.property.Property;
036: import org.cougaar.tools.csmart.core.property.PropertyAlias;
037: import org.cougaar.tools.csmart.core.property.PropertyEvent;
038: import org.cougaar.tools.csmart.core.property.PropertyListener;
039: import org.cougaar.tools.csmart.core.property.name.CompositeName;
040: import org.cougaar.tools.csmart.recipe.PriorityProperty;
041: import org.cougaar.tools.csmart.ui.viewer.CSMART;
042:
043: import java.util.Iterator;
044:
045: /**
046: * ComponentBase is the basic implementation for editing & configuring
047: * arbitrary component.
048: */
049: public class ComponentBase extends ModifiableConfigurableComponent
050: implements MiscComponent, PropertiesListener {
051:
052: /** Component Classname Property Definition **/
053: public static final String PROP_CLASSNAME = "Component Class Name";
054: public static final String PROP_CLASSNAME_DESC = "Name of the Component Class";
055:
056: public static final String PROP_PRIORITY = "Component Priority";
057: public static final String PROP_PRIORITY_DESC = "Load Priority of the component in it's container relative to other child components";
058: public static final String PROP_PRIORITY_DFLT = ComponentDescription
059: .priorityToString(ComponentDescription.PRIORITY_STANDARD);
060:
061: // FIXME:
062: // Need to specify the insertion point
063: // and actual type of this component
064:
065: public static final String PROP_TYPE = "Component Type";
066: public static final String PROP_TYPE_DESC = "Type of component (Insertion point if not standard)";
067: protected String type = ComponentData.PLUGIN;
068:
069: protected String folderLabel = "Other Components";
070: protected boolean modified = true;
071:
072: private String alibID = null;
073: private String libID = null;
074:
075: public static final String PROP_PARAM = "param-";
076: protected int nParameters = 0;
077: protected String classname = "";
078: protected String priority = ComponentDescription
079: .priorityToString(ComponentDescription.PRIORITY_STANDARD);
080:
081: public ComponentBase(String name) {
082: this (
083: name,
084: "",
085: ComponentDescription
086: .priorityToString(ComponentDescription.PRIORITY_STANDARD));
087: }
088:
089: public ComponentBase(String name, String classname, String priority) {
090: this (name, classname, priority, ComponentData.PLUGIN);
091: }
092:
093: public ComponentBase(String name, String classname,
094: String priority, String type) {
095: super (name);
096: this .classname = classname;
097: if (type != null && !type.trim().equals(""))
098: this .type = getCanonicalType(type);
099: else {
100: if (log.isDebugEnabled())
101: log.debug(
102: "CompBase constructor got empty type for name "
103: + name, new Throwable());
104: }
105: if (priority != null && !priority.trim().equals(""))
106: this .priority = priority;
107: createLogger();
108: installListeners();
109: }
110:
111: private void createLogger() {
112: log = CSMART
113: .createLogger("org.cougaar.tools.csmart.society.ComponentBase");
114: }
115:
116: /**
117: * Initializes properties for this component;
118: * in particular, initializes the property class name.
119: */
120: public void initProperties() {
121: Property prop = addProperty(PROP_CLASSNAME, classname);
122: prop.setToolTip(PROP_CLASSNAME_DESC);
123:
124: if (log.isDebugEnabled()) {
125: if (type == null || type.trim().equals(""))
126: log.debug("type is null in initProps for "
127: + getFullName().toString());
128: }
129: prop = addProperty(PROP_TYPE, type);
130: prop.setToolTip(PROP_TYPE_DESC);
131:
132: prop = addPriorityProperty(PROP_PRIORITY, priority);
133: prop.setToolTip(PROP_PRIORITY_DESC);
134: }
135:
136: private Property addPriorityProperty(String name, String dflt) {
137: Property prop = addProperty(new PriorityProperty(this , name,
138: dflt));
139: prop.setPropertyClass(String.class);
140: return prop;
141: }
142:
143: /**
144: * Adds this component to the ComponentData structure.
145: *
146: * @param data
147: * @return a <code>ComponentData</code> value
148: */
149: public ComponentData addComponentData(ComponentData data) {
150: if (log.isDebugEnabled()) {
151: log.debug("Adding ComponentData for: " + data.getName());
152: }
153:
154: // Warning: This assumes it has been handed the component in
155: // which to add itself
156: // if (data.getType() != ComponentData.AGENT && data.getType() != ComponentData.NODE) {
157: // if (log.isErrorEnabled()) {
158: // log.error("Asked to add to non Agent/Node: " + data);
159: // }
160: // return data;
161: // }
162:
163: // Create a new componentdata
164: // set the type, etc appropriately
165: // set self as the owner
166: // set data as the parent
167: // add self to data
168: ComponentData self = new GenericComponentData();
169:
170: // We don't try to translate the component type here
171: // because that might cause a modification,
172: // which isn't the intent at this point
173: self.setType(getComponentType());
174:
175: self.setOwner(this );
176: self.setParent(data);
177:
178: self.setClassName(getComponentClassName());
179: self.setPriority(getPriority());
180: self.setAlibID(getAlibID());
181: self.setLibID(getLibID());
182:
183: Iterator names = getSortedLocalPropertyNames();
184: while (names.hasNext()) {
185: CompositeName cname = (CompositeName) names.next();
186: String name = cname.toString();
187: // if (log.isDebugEnabled()) {
188: // log.debug("Looking at property " + name);
189: // }
190: if (name.indexOf(PROP_PARAM) != -1) {
191: if (log.isDebugEnabled()) {
192: log.debug("Found parameter " + name);
193: }
194: self.addParameter(getProperty(cname).getValue());
195: }
196: }
197:
198: // for(int i=0; i < nParameters; i++) {
199: // // getLocalPropertyNames
200: // // Iterate through them, looking for PROP_PARAM
201: // // when get one, store it in hash by the number in it?
202: // // Then with the count, create an array of that size,
203: // // stick the items from the hash in the array, and do
204: // // self.setParameters...
205: // if (getProperty(PROP_PARAM + i) != null) {
206: // if(log.isDebugEnabled()) {
207: // log.debug("Adding Parameter: " + PROP_PARAM + i +
208: // " Value: " + getProperty(PROP_PARAM + i).getValue());
209: // }
210: // self.addParameter(getProperty(PROP_PARAM + i).getValue());
211: // }
212: // }
213:
214: if (GenericComponentData.alreadyAdded(data, self)) {
215: if (log.isDebugEnabled()) {
216: log.debug(data.getName() + " already has component "
217: + self);
218: }
219: return data;
220: }
221:
222: if (getAlibID() != null) {
223: self.setName(getAlibID());
224: self.setName(GenericComponentData
225: .getSubComponentUniqueName(data, self));
226: } else {
227: self.setName(GenericComponentData
228: .getSubComponentUniqueName(data, self));
229: }
230:
231: data.addChildDefaultLoc(self);
232: // if (log.isDebugEnabled()) {
233: // log.warn("CompBase added comp " + self);
234: // log.warn("CompBase says type is " + getComponentType());
235: // }
236: return data;
237: }
238:
239: public ComponentData modifyComponentData(ComponentData data) {
240: if (log.isDebugEnabled()) {
241: log.debug("Adding ComponentData for: " + data.getName());
242: }
243:
244: // Warning: This assumes it has been handed the component in
245: // which to add itself
246: if (data.getType() != ComponentData.AGENT
247: && data.getType() != ComponentData.NODE) {
248: if (log.isErrorEnabled()) {
249: log.error("Asked to add to non Agent/Node: " + data);
250: }
251: return data;
252: }
253:
254: // Create a new componentdata
255: // set the type, etc appropriately
256: // set self as the owner
257: // set data as the parent
258: // add self to data
259: ComponentData self = new GenericComponentData();
260:
261: // We don't try to translate the component type here
262: // because that might cause a modification,
263: // which isn't the intent at this point
264: self.setType(getComponentType());
265:
266: self.setOwner(this );
267: self.setParent(data);
268:
269: self.setClassName(getComponentClassName());
270: self.setPriority(getPriority());
271: self.setAlibID(getAlibID());
272: self.setLibID(getLibID());
273:
274: Iterator names = getSortedLocalPropertyNames();
275: while (names.hasNext()) {
276: CompositeName cname = (CompositeName) names.next();
277: String name = cname.toString();
278: // if (log.isDebugEnabled()) {
279: // log.debug("Looking at property " + name);
280: // }
281: if (name.indexOf(PROP_PARAM) != -1) {
282: if (log.isDebugEnabled()) {
283: log.debug("Found parameter " + name);
284: }
285: self.addParameter(getProperty(cname).getValue());
286: }
287: }
288:
289: if (GenericComponentData.alreadyAdded(data, self)) {
290: if (log.isDebugEnabled()) {
291: log.debug(data.getName() + " already has component "
292: + self);
293: }
294: return data;
295: }
296:
297: if (getAlibID() != null) {
298: self.setName(getAlibID());
299: self.setName(GenericComponentData
300: .getSubComponentUniqueName(data, self));
301: } else {
302: self.setName(GenericComponentData
303: .getSubComponentUniqueName(data, self));
304: }
305:
306: data.addChildDefaultLoc(self);
307:
308: // if (log.isDebugEnabled()) {
309: // log.warn("CompBase moded comp " + self);
310: // log.warn("CompBase says type is " + getComponentType());
311: // }
312:
313: return data;
314: }
315:
316: public String getFolderLabel() {
317: return folderLabel;
318: }
319:
320: /**
321: * Gets the classname for this component
322: *
323: * @return a <code>String</code> value
324: */
325: public String getComponentClassName() {
326: Property p = getProperty(PROP_CLASSNAME);
327: if (p != null) {
328: Object o = p.getValue();
329: if (o != null)
330: return o.toString();
331: }
332: return null;
333: }
334:
335: /**
336: * Get the type of this Component, from the property.
337: *
338: * @return a <code>String</code> type from the constants in ComponentData
339: */
340: public String getComponentType() {
341: Property p = getProperty(PROP_TYPE);
342: if (p != null) {
343: Object o = p.getValue();
344: if (o != null)
345: return o.toString();
346: }
347: return type;
348: }
349:
350: // Turn random strings into the constants wherever possible
351: protected String getCanonicalType(String type) {
352: if (type == null || type.equals("")) {
353: if (log.isDebugEnabled()) {
354: log.debug("getCanonType got empty type in "
355: + getFullName().toString() + "!",
356: new Throwable());
357: }
358: return "";
359: }
360:
361: if (type.equalsIgnoreCase(Agent.INSERTION_POINT))
362: type = ComponentData.AGENT;
363: else if (type.equalsIgnoreCase(AgentManager.INSERTION_POINT
364: + ".Binder"))
365: type = ComponentData.NODEBINDER;
366: else if (type.equalsIgnoreCase(PluginManager.INSERTION_POINT
367: + ".Binder"))
368: type = ComponentData.AGENTBINDER;
369: else if (type
370: .equalsIgnoreCase(org.cougaar.core.plugin.PluginBase.INSERTION_POINT))
371: type = ComponentData.PLUGIN;
372: else if (type.equalsIgnoreCase("binder"))
373: type = ComponentData.AGENTBINDER;
374: else if (type.equalsIgnoreCase("nodebinder"))
375: type = ComponentData.NODEBINDER;
376: else if (type.equalsIgnoreCase("agentbinder"))
377: type = ComponentData.AGENTBINDER;
378: else if (type.equalsIgnoreCase("domain"))
379: type = ComponentData.DOMAIN;
380: else if (type.equalsIgnoreCase(ComponentData.NODEBINDER))
381: type = ComponentData.NODEBINDER;
382: else if (type.equalsIgnoreCase(ComponentData.AGENTBINDER))
383: type = ComponentData.AGENTBINDER;
384: else if (type.equalsIgnoreCase(ComponentData.PLUGIN))
385: type = ComponentData.PLUGIN;
386: else if (type.equalsIgnoreCase(ComponentData.AGENT))
387: type = ComponentData.AGENT;
388: else if (type.equalsIgnoreCase(ComponentData.DOMAIN))
389: type = ComponentData.DOMAIN;
390:
391: return type;
392: }
393:
394: /**
395: * Allow outside users to set the Component type to one of the
396: * values in the constants in ComponentData.
397: *
398: * @param type a <code>String</code> binder type
399: */
400: public void setComponentType(String type) {
401: if (type == null || type.equals("")) {
402: if (log.isDebugEnabled())
403: log.debug("setCompType got empty type where was "
404: + getComponentType() + " for "
405: + getFullName().toString(), new Throwable());
406: return;
407: }
408:
409: if (type.equals(this .getComponentType()))
410: return;
411:
412: type = getCanonicalType(type);
413:
414: Property p = getProperty(PROP_TYPE);
415: if (p != null) {
416: p.setValue(type);
417: fireModification();
418: }
419: }
420:
421: public String getPriority() {
422: Property p = getProperty(PROP_PRIORITY);
423: if (p != null) {
424: Object o = p.getValue();
425: if (o != null) {
426: String ret = o.toString();
427: if (ret != null && !ret.trim().equals("")
428: && !ret.equals("<not set>"))
429: return ret;
430: }
431: }
432: return ComponentDescription
433: .priorityToString(ComponentDescription.PRIORITY_COMPONENT);
434: }
435:
436: /**
437: * Adds a Parameter to this component.
438: *
439: * @param param Unique Integer for this parameter
440: * @return a <code>Property</code> value
441: */
442: public Property addParameter(int param) {
443: return addProperty(PROP_PARAM + nParameters++, new Integer(
444: param));
445: }
446:
447: /**
448: * Adds a Parameter to this component
449: *
450: * @param param Unique Object for this parameter's value
451: * @return a <code>Property</code> value
452: */
453: public Property addParameter(Object param) {
454: return addProperty(PROP_PARAM + nParameters++, param);
455: }
456:
457: /**
458: * Add a parameter that is based on some other property (typically a
459: * property of our parent.
460: **/
461: public Property addParameter(Property prop) {
462: return addProperty(new PropertyAlias(this , PROP_PARAM
463: + nParameters++, prop));
464: }
465:
466: public void setAlibID(String alibID) {
467: this .alibID = alibID;
468: }
469:
470: public String getAlibID() {
471: return this .alibID;
472: }
473:
474: public void setLibID(String libID) {
475: this .libID = libID;
476: }
477:
478: public String getLibID() {
479: return this .libID;
480: }
481:
482: /**
483: * Has this Component been modified, such that a save would do something.
484: *
485: * @return a <code>boolean</code>, false if no save necessary
486: */
487: public boolean isModified() {
488: return modified;
489: }
490:
491: /**
492: * Set the internal modified flag (returned by isModified)
493: * and fire a modification event.
494: */
495:
496: public void fireModification() {
497: modified = true;
498: super .fireModification();
499: }
500:
501: private void installListeners() {
502: addPropertiesListener(this );
503: for (Iterator i = getPropertyNames(); i.hasNext();) {
504: Property p = getProperty((CompositeName) i.next());
505: p.addPropertyListener(myPropertyListener);
506: }
507: }
508:
509: public void propertyAdded(PropertyEvent e) {
510: Property addedProperty = e.getProperty();
511: setPropertyVisible(addedProperty, true);
512: addedProperty.addPropertyListener(myPropertyListener);
513: fireModification();
514: }
515:
516: public void propertyRemoved(PropertyEvent e) {
517: e.getProperty().removePropertyListener(myPropertyListener);
518: fireModification();
519: }
520:
521: PropertyListener myPropertyListener = new PropertyListener() {
522: public void propertyValueChanged(PropertyEvent e) {
523: fireModification();
524: }
525:
526: public void propertyOtherChanged(PropertyEvent e) {
527: fireModification();
528: }
529: };
530:
531: } // End of ComponentBase
|