001: /*
002: * <copyright>
003: *
004: * Copyright 2001-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.core.cdata;
028:
029: import org.cougaar.core.component.ComponentDescription;
030: import org.cougaar.core.plugin.PluginManager;
031: import org.cougaar.core.agent.AgentManager;
032: import org.cougaar.core.agent.Agent;
033: import org.cougaar.tools.csmart.core.property.ConfigurableComponent;
034: import org.cougaar.tools.csmart.ui.viewer.CSMART;
035: import org.cougaar.util.log.Logger;
036:
037: import java.io.IOException;
038: import java.io.ObjectInputStream;
039: import java.io.Serializable;
040: import java.util.ArrayList;
041:
042: /**
043: * Generic Component Data.
044: * All components, except for Agent components can use
045: * the generic component data structure.
046: *
047: * @see ComponentData for docs.
048: */
049: public class GenericComponentData implements ComponentData,
050: Serializable {
051: protected String type = null;
052: private String name = null;
053: protected String className = null;
054: private String priority = ComponentDescription
055: .priorityToString(ComponentDescription.PRIORITY_COMPONENT);
056: private ArrayList children = null;
057: private ArrayList parameters = null;
058: private ComponentData parent = null;
059: private transient ConfigurableComponent owner = null;
060: private ArrayList leafComponents = null;
061: private ArrayList timePhasedData = null;
062: private AgentAssetData assetData = null;
063: private String aLibID = null;
064: private String libID = null;
065:
066: private transient Logger log;
067:
068: // Flag: Recipe modified the component, so must compare it with DB on save
069: private boolean modified = false;
070:
071: public GenericComponentData() {
072: createLogger();
073: children = new ArrayList();
074: parameters = new ArrayList();
075: leafComponents = new ArrayList();
076: timePhasedData = new ArrayList();
077: }
078:
079: private void createLogger() {
080: log = CSMART.createLogger(this .getClass().getName());
081: }
082:
083: public String getType() {
084: return this .type;
085: }
086:
087: public void setType(String type) {
088: if (type == null || type.trim().equals("")) {
089: if (log.isDebugEnabled())
090: log.debug("setType got empty type in " + this ,
091: new Throwable());
092: return;
093: }
094: if (type.equals(this .type))
095: return;
096: this .type = type;
097: // log.debug(this + " fireModified due to changed type");
098: fireModified();
099: }
100:
101: public String getName() {
102: return this .name;
103: }
104:
105: public void setName(String name) {
106: if (name == null && this .name == null)
107: return;
108: if (name != null && name.equals(this .name))
109: return;
110: this .name = name;
111: // log.debug(this + " fireModified due to changed name");
112: fireModified();
113: }
114:
115: public String getClassName() {
116: return this .className;
117: }
118:
119: public void setClassName(String className) {
120: if (className == null && this .className == null)
121: return;
122: if (className != null && className.equals(this .className))
123: return;
124: this .className = className;
125: // log.debug(this + " fireModified due to changed classname");
126: fireModified();
127: }
128:
129: public String getPriority() {
130: return this .priority;
131: }
132:
133: public void setPriority(String priority) {
134: try {
135: ComponentDescription.parsePriority(priority);
136: if (this .priority.equals(priority))
137: return;
138: this .priority = priority;
139: // log.debug(this + " fireModified due to changed priority");
140: fireModified();
141: } catch (IllegalArgumentException e) {
142: if (log.isErrorEnabled()) {
143: log
144: .error(
145: "IllegalArgumentException setting component priority",
146: e);
147: }
148: }
149: }
150:
151: public void setPriority(int priority) {
152: try {
153: String old = this .priority;
154: this .priority = ComponentDescription
155: .priorityToString(priority);
156: if (old.equals(this .priority))
157: return;
158: // log.debug(this + " fireModified due to changed priority");
159: fireModified();
160: } catch (IllegalArgumentException e) {
161: if (log.isErrorEnabled()) {
162: log
163: .error(
164: "IllegalArgumentException setting component priority",
165: e);
166: }
167: }
168: }
169:
170: public ComponentData[] getChildren() {
171: return (ComponentData[]) children
172: .toArray(new ComponentData[children.size()]);
173: }
174:
175: public void setChildren(ComponentData[] child) {
176: if (child == null || child.length == 0 && log.isDebugEnabled()) {
177: log
178: .debug(getName()
179: + ".setChildren called with empty list - will clear children.");
180: }
181:
182: this .children.clear();
183: for (int i = 0; i < child.length; i++) {
184: if (child[i] != null) {
185: this .children.add(child[i]);
186: // log.debug(this + " fireModified due to setChildren");
187: if (!child[i].isModified()) {
188: if (log.isDebugEnabled())
189: log
190: .debug("where the child being added IS NOT MODIFIED!");
191: child[i].fireModified();
192: } else {
193: // If the child is already modified then it will not propagate
194: // up, so call locally to be safe
195: if (log.isDebugEnabled()) {
196: if (!isModified())
197: log
198: .debug("setChildren where child was modified but parent(this) not!");
199: else
200: log
201: .debug("setChildren where both child & parent modified");
202: }
203: fireModified();
204: }
205: // or should I do child.fireModified()?
206: } else if (log.isDebugEnabled()) {
207: log
208: .debug(getName()
209: + ".setChildren got a null child at index "
210: + i);
211: }
212: }
213: }
214:
215: public void addChild(ComponentData child) {
216: if (child != null) {
217: this .children.add(child);
218: // log.debug(this + " fireModified due to addChild");
219: if (!child.isModified()) {
220: if (log.isDebugEnabled())
221: log
222: .debug("addChild where the child being added IS NOT MODIFIED!");
223: child.fireModified();
224: } else {
225: if (log.isDebugEnabled()) {
226: if (!isModified())
227: log
228: .debug("addChild where child was modified but parent(this) not!");
229: else
230: log
231: .debug("addChild where child was modified and so was parent.");
232: }
233: fireModified();
234: }
235: // or should I do child.fireModified()?
236: } else {
237: if (log.isDebugEnabled())
238: log.debug(getName() + ".addChild got a null child");
239: if (log.isErrorEnabled())
240: log.error("addChild", new Throwable());
241: }
242: }
243:
244: public void addChild(int index, ComponentData child) {
245: if (child != null) {
246: this .children.add(index, child);
247: // log.debug(this + " fireModified due to addChild");
248: if (!child.isModified()) {
249: if (log.isDebugEnabled())
250: log
251: .debug("addChild where the child being added IS NOT MODIFIED!");
252: child.fireModified();
253: } else {
254: if (log.isDebugEnabled()) {
255: if (!isModified())
256: log
257: .debug("addChild where child was modified but parent(this) not!");
258: else
259: log
260: .debug("addChild where child was modified and so was parent.");
261: }
262:
263: fireModified();
264: }
265: // or should I do child.fireModified()?
266: } else {
267: if (log.isDebugEnabled())
268: log.debug(getName()
269: + ".addChild got a null child to add at index "
270: + index);
271: if (log.isErrorEnabled())
272: log.error("addChild index, child", new Throwable());
273: }
274: }
275:
276: public void setChild(int index, ComponentData child) {
277: if (child != null) {
278: this .children.set(index, child);
279: // log.debug(this + " fireModified due to setChild");
280: if (!child.isModified()) {
281: if (log.isDebugEnabled())
282: log
283: .debug("addChild where the child being added IS NOT MODIFIED!");
284: child.fireModified();
285: } else {
286: if (log.isDebugEnabled()) {
287: if (!isModified())
288: log
289: .debug("setChild where child was modified but parent(this) not!");
290: else
291: log
292: .debug("setChild where child was modified and so was parent.");
293: }
294: fireModified();
295: }
296: // or should I do child.fireModified()?
297: } else {
298: if (log.isDebugEnabled())
299: log.debug(getName()
300: + ".setChild got a null child to put at index "
301: + index);
302: if (log.isErrorEnabled())
303: log.error("setChild index, child", new Throwable());
304: }
305: }
306:
307: public int childCount() {
308: return children.size();
309: }
310:
311: public int getChildIndex(ComponentData child) {
312: return this .children.indexOf(child);
313: }
314:
315: public void addChildDefaultLoc(ComponentData comp) {
316: if (comp == null) {
317: if (log.isDebugEnabled()) {
318: log.debug(getName()
319: + ".addChildDefaultLoc got null component");
320: }
321: if (log.isErrorEnabled())
322: log.error("addChildDefaultLoc", new Throwable());
323: return;
324: }
325:
326: // Binders will be inserted before other items
327: // at the same level.
328: // Components that are .equals with other items already
329: // there will replace the existing versions
330: if (log.isDebugEnabled()) {
331: log.debug("Adding comp: " + comp + " to " + this .getName());
332: }
333: ComponentData[] dkids = this .getChildren();
334: int lastbinder = -1; // last binder
335: int firstother = -1; // -1 if no kids or first is after
336: // last binder
337: // else index of first other
338: for (int i = 0; i < dkids.length; i++) {
339: ComponentData kid = dkids[i];
340: if (this .getType().equals(ComponentData.NODE)) {
341: if (kid.getType().equals(ComponentData.AGENT)) {
342: // if(log.isDebugEnabled()) {
343: // log.debug("Got an agent at index: " + i);
344: // }
345: if (firstother < 0)
346: firstother = i;
347: } else if (kid.getType().equals(
348: ComponentData.NODEBINDER)) {
349: // if(log.isDebugEnabled()) {
350: // log.debug("Got a nodebinder at index: " + i);
351: // }
352: lastbinder = i;
353: } else {
354: // Plugins, AgentBinders, misc components
355: // FIXME!!!
356: }
357: } else if (this .getType().equals(ComponentData.AGENT)) {
358: if (kid.getType().equals(ComponentData.PLUGIN)) {
359: // if(log.isDebugEnabled()) {
360: // log.debug("Got a plugin at index: " + i);
361: // }
362: if (firstother < 0)
363: firstother = i;
364: } else if (kid.getType().equals(
365: ComponentData.AGENTBINDER)) {
366: // if(log.isDebugEnabled()) {
367: // log.debug("Got an agentbinder at index: " + i);
368: // }
369: lastbinder = i;
370: } else {
371: // Misc components
372: // FIXME!!!
373: }
374: } else if (this .getType().equals(ComponentData.RECIPE)) {
375: if (firstother < 0)
376: firstother = i;
377: }
378:
379: } // end of loop over kids of this data item
380: // Now lastbinder points to the last binder.
381: // I use lastbinder+1
382:
383: // If this is a binder
384: if (comp.getType().equals(ComponentData.NODEBINDER)
385: || comp.getType().equals(ComponentData.AGENTBINDER)) {
386: // if(log.isDebugEnabled()) {
387: // log.debug("Comp being added is a binder");
388: // }
389: // see if it is in node/agent at all
390: if (this .getChildIndex(comp) >= 0) {
391: // if it is there
392: // see if there are any agents/plugins before it
393: if (firstother < this .getChildIndex(comp)) {
394: // if there are, must remove it and later add it
395: // Its easiest to do a complete fix
396: // FIXME: This shuffles all the other binders,
397: // when maybe they're intentionally placed where they are?
398: ArrayList dkidsnew = new ArrayList();
399: for (int i = 0; i < dkids.length; i++) {
400: // First add all the binders
401: if (dkids[i].getType().equals(comp.getType())) {
402: if (i == this .getChildIndex(comp)) {
403: dkidsnew.add(comp);
404: } else {
405: dkidsnew.add(dkids[i]);
406: }
407: dkids[i] = null;
408: }
409: } // end of loop to add binders
410: for (int i = 0; i < dkids.length; i++) {
411: if (dkids[i] != null)
412: dkidsnew.add(dkids[i]);
413: } // end of loop to add others
414: this
415: .setChildren((ComponentData[]) dkidsnew
416: .toArray(new ComponentData[dkidsnew
417: .size()]));
418: } else {
419: // if(log.isDebugEnabled()) {
420: // log.debug(".. replacing old version with new");
421: // }
422: // else all agents/plugins are after it. Replace old with new
423: this .setChild(this .getChildIndex(comp), comp);
424: }
425: } else {
426: // if(log.isDebugEnabled()) {
427: // log.debug("Adding at index: " + (lastbinder + 1));
428: // }
429: // else if it is not there at all, insert it after last binder
430: this .addChild(lastbinder + 1, comp);
431: }
432: } else {
433: // if(log.isDebugEnabled()) {
434: // log.debug("Adding a non binder");
435: // }
436: // else if its an agent or a plugin
437: // see if it is there at all
438: if (this .getChildIndex(comp) >= 0) {
439: // if it is, do this.setChild(its index>, comp)
440: this .setChild(this .getChildIndex(comp), comp);
441: } else {
442: // else (it is not there), do this.addChild(comp)
443: // FIXME: Maybe this should add it after the last item not its type?
444: this .addChild(comp);
445: }
446: } // finished handling non binders
447: }
448:
449: public Object[] getParameters() {
450: return parameters.toArray();
451: }
452:
453: public void setParameters(Object[] params) {
454: this .parameters.clear();
455: for (int i = 0; i < params.length; i++) {
456: this .parameters.add(params[i]);
457: }
458: // log.debug(this + " fireModified due to setParams");
459: fireModified();
460: }
461:
462: public void addParameter(Object param) {
463: this .parameters.add(param);
464: // log.debug(this + " fireModified due to addParam");
465: fireModified();
466: }
467:
468: public void setParameter(int index, Object param) {
469: if (index < 0 || index >= parameterCount()) {
470: if (log.isErrorEnabled())
471: log.error(this + " got illegal new param index "
472: + index + " when parameters size is "
473: + parameterCount());
474: return;
475: }
476: this .parameters.set(index, param);
477: // log.debug(this + " fireModified due to setParam");
478: fireModified();
479: }
480:
481: public Object getParameter(int index) {
482: return parameters.get(index);
483: }
484:
485: public int parameterCount() {
486: return parameters.size();
487: }
488:
489: public ComponentData getParent() {
490: return parent;
491: }
492:
493: public void setParent(ComponentData parent) {
494: if (parent == null && this .parent == null)
495: return;
496: // Is this next line expensive?
497: // if (parent != null && parent.equals(this.parent))
498: // return;
499: this .parent = parent;
500: // log.debug(this + " fireMod due to setParent, where before this.mod=" + isModified() + ", and parent.isMod=" + parent.isModified());
501: // fireModified(); // really?
502: // Perhaps dont do this cause some code sets the parent
503: // on a component before deciding if it really needs to be
504: // added to the parent. And since fireModified will go up
505: // even if the chain is not complete going down, and saves go down,
506: // this risks marking the parent modified even if the parent
507: // will never get this child
508: }
509:
510: public ConfigurableComponent getOwner() {
511: return owner;
512: }
513:
514: public void setOwner(ConfigurableComponent owner) {
515: this .owner = owner;
516: }
517:
518: public LeafComponentData[] getLeafComponents() {
519: return (LeafComponentData[]) leafComponents
520: .toArray(new LeafComponentData[leafComponents.size()]);
521: }
522:
523: public void setLeafComponents(LeafComponentData[] leaves) {
524: leafComponents.clear();
525: for (int i = 0; i < leaves.length; i++) {
526: leafComponents.add(leaves[i]);
527: }
528: fireModified();
529: }
530:
531: public void addLeafComponent(LeafComponentData leaf) {
532: leafComponents.add(leaf);
533: fireModified();
534: }
535:
536: public void setLeafComponent(int index, LeafComponentData leaf) {
537: leafComponents.set(index, leaf);
538: fireModified();
539: }
540:
541: public int leafCount() {
542: return leafComponents.size();
543: }
544:
545: public AgentAssetData getAgentAssetData() {
546: return assetData;
547: }
548:
549: public void addAgentAssetData(AgentAssetData data) {
550: if (data == null && this .assetData == null)
551: return;
552: if (data != null && data.equals(this .assetData))
553: return;
554: this .assetData = data;
555: if (log.isDebugEnabled())
556: log.debug(this + " fireMod due to added assetData");
557: fireModified();
558: }
559:
560: // For testing, dump out the tree from here down
561: public String toString() {
562: StringBuffer buf = new StringBuffer();
563: buf.append(this .getClass().toString() + ": ");
564: buf.append("Name: " + getName());
565: buf.append(", Type: " + getType());
566: buf.append(", Class: " + getClassName());
567: buf.append(", AlibID: " + getAlibID());
568: buf.append(", libID: " + getLibID());
569: buf.append(", Priority: " + getPriority());
570: if (owner != null) {
571: buf.append(", Owner: " + getOwner());
572: }
573: buf.append(", LeafCount: " + leafCount());
574: // FIXME print out the arguments
575: buf.append(", ChildCount: " + childCount());
576: ComponentData[] children = getChildren();
577: for (int i = 0; i < childCount(); i++) {
578: buf.append(", Child[" + i + "]: \n" + children[i].getName()
579: + "\n");
580: }
581: return buf.toString();
582: }
583:
584: public TimePhasedData[] getTimePhasedData() {
585: return (TimePhasedData[]) timePhasedData
586: .toArray(new TimePhasedData[timePhasedData.size()]);
587: }
588:
589: public void setTimePhasedData(TimePhasedData[] data) {
590: timePhasedData.clear();
591: for (int i = 0; i < data.length; i++) {
592: timePhasedData.add(data[i]);
593: }
594: fireModified();
595: }
596:
597: public void setTimePhasedData(int index, TimePhasedData data) {
598: timePhasedData.set(index, data);
599: fireModified();
600: }
601:
602: public void addTimePhasedData(TimePhasedData data) {
603: timePhasedData.add(data);
604: }
605:
606: public int timePhasedCount() {
607: return timePhasedData.size();
608: }
609:
610: public void setAlibID(String alibID) {
611: if (aLibID != null && aLibID.equals(this .aLibID))
612: return;
613: if (aLibID == null && this .aLibID == null)
614: return;
615: this .aLibID = alibID;
616: // log.debug(this + " fireModified due to changed alibid");
617: fireModified();
618: }
619:
620: public String getAlibID() {
621: return aLibID;
622: }
623:
624: public void setLibID(String libID) {
625: if (libID != null && libID.equals(this .libID))
626: return;
627: if (libID == null && this .libID == null)
628: return;
629: this .libID = libID;
630: // log.debug(this + " fireModified due to changed libid");
631: fireModified();
632: }
633:
634: public String getLibID() {
635: return libID;
636: }
637:
638: private void readObject(ObjectInputStream ois) throws IOException,
639: ClassNotFoundException {
640: ois.defaultReadObject();
641: createLogger();
642: }
643:
644: public boolean equals(Object o) {
645: if (o instanceof GenericComponentData) {
646: GenericComponentData that = (GenericComponentData) o;
647: // FIXME: Compare AlibIDs if they're both not null first?
648: // if (this.getAlibID() != null && that.getAlibID() != null) {
649: // return (this.getAlibID().equals(that.getAlibID()));
650: // } else
651: if (this .getName() == null) {
652: if (this .getClassName() != null
653: && this .getClassName().equals(
654: that.getClassName())
655: && this .getType() != null
656: && this .getType().equals(that.getType())
657: && this .parameterCount() == that
658: .parameterCount()
659: && this .getPriority() != null
660: && this .getPriority()
661: .equals(that.getPriority())) {
662: for (int j = 0; j < that.parameterCount(); j++) {
663: if (!that.getParameter(j).equals(
664: this .getParameter(j))) {
665: return false;
666: }
667: }
668: // FIXME: Compare the children?
669: return true;
670: }
671: } else if (this .getName().equals(that.getName())) {
672: return true;
673: }
674: }
675: return false;
676: }
677:
678: /**
679: * Generate the standard unique name for a sub-component (Binder, Plugin).
680: * The rule is that the name should be parent|<classname>.
681: * However, if the ComponentData has a non-null name when passed in,
682: * then use that as the base.
683: * But if that is taken within this parent, and you have a first parameter, add |<param 0>.
684: * Otherwise, or if that too is taken, add a number: The index at which
685: * this component will be added to the parent.
686: * Note that the self component should <i>not</i> be currently a child of the parent - at least,
687: * not to the best of the caller's knowledge.
688: * Also note that this method does not <i>set</i> the name, just calculate it.
689: *
690: * @param parent a <code>ComponentData</code> to which this Component has <i>not yet</i> been added
691: * @param self a <code>ComponentData</code> which will be added to the parent and whose name should be calculated
692: * @return a <code>String</code> name for the self ComponentData, null if the self ComponentData was null
693: */
694: public static String getSubComponentUniqueName(
695: ComponentData parent, ComponentData self) {
696: // FIXME: This needs to match up with PopulateDb's ideas of Alib IDs and stuff
697: if (self == null)
698: return null;
699:
700: String cname = self.getName();
701: if (parent == null)
702: if (cname != null)
703: return cname;
704: else
705: return self.getClassName();
706:
707: String type = self.getType();
708:
709: // Create a default component name if necessary
710: if (cname == null)
711: cname = self.getClassName();
712:
713: // Either way, ensure the name starts with the parent name
714: // for things that arent Nodes or Agents,
715: // cause PopulateDb will assume so in creating Alib IDs
716: if (type != null && !type.equals(ComponentData.NODE)
717: && !type.equals(ComponentData.AGENT)
718: && !type.equals(ComponentData.HOST)
719: && !type.equals(ComponentData.SOCIETY)
720: && !cname.startsWith(parent.getName() + "|"))
721: cname = parent.getName() + "|" + cname;
722:
723: ComponentData[] children = parent.getChildren();
724: if (children == null)
725: return cname;
726: boolean addedparam = false;
727: for (int i = 0; i < children.length; i++) {
728: ComponentData kid = children[i];
729: if (kid != null && kid.getName().equals(cname)) {
730: // OK, must at least add a paramter if it has one
731: if (self.parameterCount() > 0 && !addedparam) {
732: cname = cname + "|" + self.getParameter(0);
733: addedparam = true;
734: } else {
735: // OK, no params. Add a number? Maybe the others do have a param?
736: cname = cname + children.length;
737: }
738: }
739: }
740: return cname;
741: }
742:
743: /**
744: * Look for the given ComponentData in the given parent,
745: * using its class, type, and parameters.
746: * Do not consider the name of the child, or any
747: * AssetData or children it might have.
748: * That is, if any existing child of the given parent has the same type,
749: * class, and parameter list
750: * of the given candidate child, return true. Also return true
751: * if the parent or child is null.
752: * Return false if the parent has no children.
753: *
754: * @param parent <code>ComponentData</code> that may already contain the component
755: * @param self a <code>ComponentData</code> a component to look for
756: * @return a <code>boolean</code>, true if a component with the same type,
757: * class, and parameters is already present
758: */
759: public static boolean alreadyAdded(final ComponentData parent,
760: final ComponentData self) {
761: Logger log = CSMART.createLogger(GenericComponentData.class
762: .getName());
763: if (self == null || parent == null)
764: return true;
765:
766: if (parent.getType().equals(ComponentData.RECIPE)) {
767: if (log.isDebugEnabled()) {
768: log
769: .debug("Ignore checking for duplicates, we are saving a recipe");
770: }
771: return false;
772: }
773:
774: ComponentData[] children = parent.getChildren();
775: if (children == null)
776: return false;
777: if (log.isDebugEnabled()
778: && children.length != parent.childCount()) {
779: log.debug(parent + " says childCount is "
780: + parent.childCount()
781: + " but returned array of children was of length "
782: + children.length);
783: }
784: for (int i = 0; i < children.length; i++) {
785: boolean isdiff = false;
786: ComponentData kid = children[i];
787: if (kid == null) {
788: if (log.isErrorEnabled()) {
789: log.error(
790: "Please report seeing Bug 1279: Using CSMART "
791: + CSMART.writeDebug() + " Child "
792: + i + " out of "
793: + parent.childCount()
794: + " is null in " + parent.getName()
795: + " while considering adding "
796: + self.getName() + " with class "
797: + self.getClassName(),
798: new Throwable());
799: }
800: // FIXME: Maybe do a parent.setChildren with a new list that doesn't include
801: // the null?
802: } else if (kid.getClassName().equals(self.getClassName())) {
803: if (kid.getType().equals(self.getType())) {
804: if (kid.parameterCount() == self.parameterCount()) {
805: // Then we better compare the parameters in turn.
806: // As soon as we find one that differs, were OK.
807: for (int j = 0; j < kid.parameterCount(); j++) {
808: if (!kid.getParameter(j).equals(
809: self.getParameter(j))) {
810: isdiff = true;
811: break;
812: }
813: } // loop over params
814: // If we get here, we finished comparing the parameters
815: // Either cause we broke out, and isdiff is true
816: // Or we completely compared the child, and it is
817: // identical.
818: // If we did not mark this child as different,
819: // then return true - it is the same
820: if (!isdiff)
821: return true;
822: } // check param count
823: } // check comp type
824: } // check comp class
825: } // loop over children
826:
827: // If we get here, we did not find any component that is identical
828: return false;
829: }
830:
831: /**
832: * Has this Component been modified by a recipe, requiring possible save?
833: */
834: public boolean isModified() {
835: return modified;
836: }
837:
838: /**
839: * The component has been saved. Mark it and all children as saved.
840: */
841: public void resetModified() {
842: // If this is not modified, neither are its children
843: if (!modified)
844: return;
845: // if (log.isDebugEnabled())
846: // log.debug(this + " resetmodified");
847: modified = false;
848:
849: // reset any assetdata
850: if (this .assetData != null)
851: this .assetData.resetModified();
852:
853: // recurse down
854: if (children != null) {
855: for (int i = 0; i < children.size(); i++) {
856: ((ComponentData) children.get(i)).resetModified();
857: }
858: }
859: }
860:
861: /**
862: * The component has been modified from its initial state.
863: * Mark it and all ancestors modified.
864: **/
865: public void fireModified() {
866: // Problem: I only want to call this after the society generates
867: // the CData, and before the recipes are applied....
868:
869: // make this private?
870:
871: // If this is already modified, so will the parents
872: if (modified)
873: return;
874: // if (log.isDebugEnabled())
875: // log.debug(this + " fireModified");
876: modified = true;
877: // recurse _up_
878: if (parent != null)
879: parent.fireModified();
880: }
881:
882: public static String getCanonicalType(String type) {
883: if (type == null || type.equals("")) {
884: return null;
885: }
886:
887: if (type.equalsIgnoreCase(Agent.INSERTION_POINT))
888: type = ComponentData.AGENT;
889: else if (type.equalsIgnoreCase(AgentManager.INSERTION_POINT
890: + ".Binder"))
891: type = ComponentData.NODEBINDER;
892: else if (type.equalsIgnoreCase(PluginManager.INSERTION_POINT
893: + ".Binder"))
894: type = ComponentData.AGENTBINDER;
895: else if (type
896: .equalsIgnoreCase(org.cougaar.core.plugin.PluginBase.INSERTION_POINT))
897: type = ComponentData.PLUGIN;
898: else if (type.equalsIgnoreCase("binder"))
899: type = ComponentData.AGENTBINDER;
900: else if (type.equalsIgnoreCase("nodebinder"))
901: type = ComponentData.NODEBINDER;
902: else if (type.equalsIgnoreCase("agentbinder"))
903: type = ComponentData.AGENTBINDER;
904: else if (type.equalsIgnoreCase("domain"))
905: type = ComponentData.DOMAIN;
906: else if (type.equalsIgnoreCase(ComponentData.NODEBINDER))
907: type = ComponentData.NODEBINDER;
908: else if (type.equalsIgnoreCase(ComponentData.AGENTBINDER))
909: type = ComponentData.AGENTBINDER;
910: else if (type.equalsIgnoreCase(ComponentData.PLUGIN))
911: type = ComponentData.PLUGIN;
912: else if (type.equalsIgnoreCase(ComponentData.AGENT))
913: type = ComponentData.AGENT;
914: else if (type.equalsIgnoreCase(ComponentData.DOMAIN))
915: type = ComponentData.DOMAIN;
916:
917: return type;
918: }
919:
920: public static String getLongType(String type) {
921: if (type == null || type.equals("")) {
922: return null;
923: }
924:
925: if (type.equalsIgnoreCase(ComponentData.AGENT))
926: type = Agent.INSERTION_POINT;
927: else if (type.equalsIgnoreCase(ComponentData.NODEBINDER))
928: type = AgentManager.INSERTION_POINT + ".Binder";
929: else if (type.equalsIgnoreCase(ComponentData.AGENTBINDER))
930: type = PluginManager.INSERTION_POINT + ".Binder";
931: else if (type.equalsIgnoreCase(ComponentData.PLUGIN))
932: type = org.cougaar.core.plugin.PluginBase.INSERTION_POINT;
933: else if (type.equalsIgnoreCase(ComponentData.DOMAIN))
934: type = "domain";
935:
936: return type;
937: }
938:
939: }
|