001: /*
002: * <copyright>
003: *
004: * Copyright 1997-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.mlm.debug.ui;
028:
029: import java.beans.BeanInfo;
030: import java.beans.Introspector;
031: import java.beans.PropertyDescriptor;
032: import java.lang.reflect.Field;
033: import java.lang.reflect.InvocationTargetException;
034: import java.lang.reflect.Method;
035: import java.util.Enumeration;
036: import java.util.Hashtable;
037: import java.util.Vector;
038:
039: import org.cougaar.planning.ldm.asset.Asset;
040: import org.cougaar.planning.ldm.asset.PropertyGroup;
041:
042: /** A tree node for an asset and its attributes.
043: Overrides the UITreeNode loadChildren, toString and isLeaf
044: methods to dynamically display the asset which has no children.
045: */
046:
047: public class UIAssetAttributeNode extends UITreeNode {
048: Asset asset;
049: int treeIndex = 0;
050:
051: /** Create a tree node for the Asset.
052: @param asset the asset for which to create a tree node
053: */
054:
055: public UIAssetAttributeNode(Asset asset) {
056: super (asset);
057: this .asset = asset;
058: }
059:
060: /** The Asset is a parent (of its properties and attributes).
061: @return false
062: */
063: public boolean isLeaf() {
064: return false;
065: }
066:
067: /** Children are its properties and attributes.
068: */
069:
070: public void loadChildren() {
071: fetchAllProperties();
072: }
073:
074: /** Return the representation of a Asset in a tree.
075: This is the asset name, and
076: for physical objects, the serial number, if specified,
077: and the capabilities.
078: @return asset name followed by serial number (optional) and capabilities
079: */
080:
081: public String toString() {
082: return prettyName(asset.toString());
083: }
084:
085: public void fetchAllProperties() {
086: // getMethods key is a property Class object
087: // getMethods value is the Method that returns the instance of the Property
088: Hashtable getMethods = new Hashtable();
089: Class this Class = asset.getClass();
090: Field fields[] = null;
091: Vector fieldVector = new Vector(2);
092: Method methods[] = null;
093: Object result = null;
094:
095: // retrieve all public methods of this class and its ancestor classes
096: // retrieve all attributes of this class and ancestors
097: try {
098: methods = this Class.getMethods();
099: Class ancestorClass = this Class;
100: while (Asset.class.isAssignableFrom(ancestorClass)) {
101: fields = ancestorClass.getDeclaredFields();
102: for (int i = 0; i < fields.length; i++) {
103: fieldVector.addElement(fields[i]);
104: }
105: ancestorClass = ancestorClass.getSuperclass();
106: }
107: } catch (SecurityException se) {
108: System.out.println("In Asset.fetchAllProperties: "
109: + se.toString());
110: }
111:
112: // Build a Hashtable of the methods with the right signature, where
113: // "right signature" means the method returns a subtype of Property
114: // and requires no arguments.
115: for (int methodIndex = 0; methodIndex < methods.length; methodIndex++) {
116: Class returntype = methods[methodIndex].getReturnType();
117: if (returntype != null
118: && PropertyGroup.class.isAssignableFrom(returntype)
119: && methods[methodIndex].getParameterTypes().length == 0) {
120: getMethods.put(methods[methodIndex].getReturnType(),
121: methods[methodIndex]);
122: }
123: }
124:
125: // Walk through the list of fields looking for subtypes of Property.
126: // If the field's Class is in the Hashtable, do introspection
127: // this section is a bit complex because we want to introspect
128: // on the DECLARED return property CLASS to determine what
129: // attributes to fetch, but we want to fetch
130: // the attributes by invoking methods on the actual property object
131: Enumeration fieldEnum = fieldVector.elements();
132: while (fieldEnum.hasMoreElements()) {
133: Field currentField = (Field) fieldEnum.nextElement();
134: Method currentMethod = (Method) getMethods.get(currentField
135: .getType());
136: if (currentMethod != null) {
137: try {
138: // invoke the get property method on the asset
139: Object returnedObject = currentMethod.invoke(asset,
140: null);
141: if (returnedObject != null) {
142: Class returnType = currentMethod
143: .getReturnType();
144: // introspect on property class to get attributes
145: // throws Introspection exception
146: //System.out.println("Introspecting on: " + returnType +
147: //" for " + asset.toString());
148: BeanInfo info = Introspector
149: .getBeanInfo(returnType);
150: PropertyDescriptor[] pds = info
151: .getPropertyDescriptors();
152: // invoke read methods to get attributes of property
153: for (int j = 0; j < pds.length; j++) {
154: Method readMethod = pds[j].getReadMethod();
155: if (readMethod != null) {
156: try {
157: //System.out.println("Invoking: " + readMethod.getName() +
158: //" on " + returnedObject);
159: result = readMethod.invoke(
160: returnedObject, null);
161:
162: String s = prettyName(returnType
163: .toString())
164: + ": "
165: + pds[j].getName()
166: + ": " + result;
167: insert(new UIStringNode(s),
168: treeIndex++);
169: } catch (NullPointerException e) {
170: System.out
171: .println("In Asset.fetchAllProperties: "
172: + e.toString());
173: e.printStackTrace();
174: } catch (InvocationTargetException e) {
175: System.out
176: .println("Invocation target error; method: "
177: + currentMethod
178: .getName()
179: + " exception: "
180: + e.toString());
181: e.printStackTrace();
182: }
183:
184: }
185: }
186: }
187: } catch (Exception e) {
188: System.out.println("Exception caught; method: "
189: + currentMethod.getName() + " exception: "
190: + e.toString());
191: e.printStackTrace();
192: }
193: }
194: }
195:
196: // now handle the dynamically added properties
197: Method readAttributeMethod = null;
198: Enumeration dynamic = asset.getOtherProperties();
199: while (dynamic.hasMoreElements()) {
200: Object o = dynamic.nextElement();
201: try {
202: PropertyGroup p = (PropertyGroup) o;
203: Class interfaceToUse = p.getPrimaryClass();
204: // System.out.println("Introspecting on: " + interfaceToUse);
205: //System.out.println("Introspecting on: " + interfaceToUse +
206: //" for " + asset.toString());
207: BeanInfo propertyBeanInfo = Introspector
208: .getBeanInfo(interfaceToUse);
209: PropertyDescriptor[] attributePds = propertyBeanInfo
210: .getPropertyDescriptors();
211: for (int k = 0; k < attributePds.length; k++) {
212: readAttributeMethod = attributePds[k]
213: .getReadMethod();
214: if (readAttributeMethod != null) {
215: // System.out.println("From other properties, Invoking: " + readAttributeMethod.getName() +
216: // " on " + o);
217: result = readAttributeMethod.invoke(o, null);
218: String s = prettyName(interfaceToUse.toString())
219: + ": "
220: + attributePds[k].getName()
221: + ": " + result;
222: insert(new UIStringNode(s), treeIndex++);
223: }
224: }
225: } catch (Exception e) {
226: String n = "(null method)";
227: if (readAttributeMethod != null)
228: n = readAttributeMethod.getName();
229: System.out
230: .println("Exception introspecting on other properties: "
231: + e.toString()
232: + " while invoking "
233: + n
234: + " on " + o.getClass());
235: }
236: }
237: }
238:
239: // Return the last field of a fully qualified name.
240: // If the input string contains an "@" then it's assumed
241: // that the fully qualified name preceeds it.
242:
243: private String prettyName(String s) {
244: int i = s.indexOf("@");
245: if (i != -1)
246: s = s.substring(0, i);
247: return (s.substring(s.lastIndexOf(".") + 1));
248: }
249:
250: }
|