0001: /*
0002: * The contents of this file are subject to the terms of the Common Development
0003: * and Distribution License (the License). You may not use this file except in
0004: * compliance with the License.
0005: *
0006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
0007: * or http://www.netbeans.org/cddl.txt.
0008: *
0009: * When distributing Covered Code, include this CDDL Header Notice in each file
0010: * and include the License file at http://www.netbeans.org/cddl.txt.
0011: * If applicable, add the following below the CDDL Header, with the fields
0012: * enclosed by brackets [] replaced by your own identifying information:
0013: * "Portions Copyrighted [year] [name of copyright owner]"
0014: *
0015: * The Original Software is NetBeans. The Initial Developer of the Original
0016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0017: * Microsystems, Inc. All Rights Reserved.
0018: */
0019: package org.netbeans.modules.xslt.tmap.nodes.properties;
0020:
0021: import java.awt.Component;
0022: import java.beans.PropertyEditor;
0023: import java.lang.reflect.InvocationTargetException;
0024: import java.lang.reflect.Method;
0025: import java.lang.reflect.Modifier;
0026: import java.text.MessageFormat;
0027: import org.netbeans.modules.soa.ui.ClassBasedPool;
0028: import org.netbeans.modules.soa.ui.SoaConstants;
0029: import org.netbeans.modules.soa.ui.UserNotification;
0030: import org.netbeans.modules.soa.ui.nodes.InstanceRef;
0031: import org.netbeans.modules.xml.xam.Model;
0032: import org.netbeans.modules.xml.xam.dom.DocumentComponent;
0033: import org.netbeans.modules.xml.xam.ui.XAMUtils;
0034: import org.netbeans.modules.xslt.tmap.model.api.TMapComponent;
0035: import org.netbeans.modules.xslt.tmap.model.api.events.VetoException;
0036: import org.netbeans.modules.xslt.tmap.nodes.DecoratedTMapComponent;
0037: import org.netbeans.modules.xslt.tmap.nodes.TMapComponentNode;
0038: import org.openide.ErrorManager;
0039: import org.openide.nodes.Node;
0040: import org.openide.nodes.PropertySupport;
0041: import org.openide.nodes.Sheet;
0042: import org.openide.util.NbBundle;
0043:
0044: /**
0045: *
0046: * Utility class. It helps to register different kinds of properties.
0047: *
0048: * @author Vitaly Bychkov
0049: * @author nk160297
0050: *
0051: * @version 1.0
0052: */
0053: public class PropertyUtils {
0054: private PropertyUtils() {
0055: }
0056:
0057: public static final ClassBasedPool<Component> propertyCustomizerPool = new ClassBasedPool<Component>();
0058:
0059: public static final ClassBasedPool<PropertyEditor> propertyEditorPool = new ClassBasedPool<PropertyEditor>();
0060:
0061: public static Node.Property registerCalculatedProperty(
0062: Object objRef, Sheet.Set targetPropertySet,
0063: PropertyType propertyType, String getterName,
0064: String setterName) {
0065: return registerCalculatedProperty(objRef, targetPropertySet,
0066: propertyType, getterName, setterName, null);
0067: }
0068:
0069: public static Node.Property registerCalculatedProperty(
0070: Object objRef, Sheet.Set targetPropertySet,
0071: PropertyType propertyType, String getterName,
0072: String setterName, String removerName) {
0073: return registerPropertyImpl(null, objRef, targetPropertySet,
0074: null, null, propertyType, getterName, setterName,
0075: removerName);
0076: }
0077:
0078: public static Node.Property registerProperty(
0079: InstanceRef instanceRef, Sheet.Set targetPropertySet,
0080: PropertyType propertyType, String getterName,
0081: String setterName) {
0082: return registerPropertyImpl(instanceRef, null,
0083: targetPropertySet, null, null, propertyType,
0084: getterName, setterName, null);
0085: }
0086:
0087: public static Node.Property registerElementProperty(
0088: InstanceRef instanceRef, Object objRef,
0089: Sheet.Set targetPropertySet, Class boundElementClass,
0090: PropertyType propertyType, String getterName,
0091: String setterName, String removerName) {
0092: return registerPropertyImpl(instanceRef, objRef,
0093: targetPropertySet, null, boundElementClass,
0094: propertyType, getterName, setterName, removerName);
0095: }
0096:
0097: public static Node.Property registerAttributeProperty(
0098: InstanceRef instanceRef, Sheet.Set targetPropertySet,
0099: String boundAttributeName, PropertyType propertyType,
0100: String getterName, String setterName, String removerName) {
0101: return registerPropertyImpl(instanceRef, null,
0102: targetPropertySet, boundAttributeName, null,
0103: propertyType, getterName, setterName, removerName);
0104: }
0105:
0106: /**
0107: * This method provides a common implementation for other public methods.
0108: */
0109: private static Node.Property registerPropertyImpl(
0110: InstanceRef instanceRef, final Object objRef,
0111: Sheet.Set targetPropertySet, String boundAttributeName,
0112: Class boundElementClass, PropertyType propertyType,
0113: String getterName, String setterName, String removerName) {
0114: try {
0115: Class propClass = propertyType.getPropertyClass();
0116: String propName = propertyType.toString();
0117: String displayName = propertyType.getDisplayName();
0118: Class propEditorClass = propertyType
0119: .getPropertyEditorClass();
0120: //
0121: if (objRef == null && instanceRef != null) {
0122: PropertyUtils.Reflection prop = new Reflection(
0123: instanceRef, propClass, getterName, setterName,
0124: removerName);
0125:
0126: if (prop != null) {
0127: prop.setName(propName);
0128: prop.setValue(SoaConstants.PROPERTY_TYPE_ATTRIBUTE,
0129: propertyType);
0130: prop.setDisplayName(displayName);
0131: if (propEditorClass != null) {
0132: prop.setPropertyEditorClass(propEditorClass);
0133: }
0134: //
0135: if (boundAttributeName != null
0136: && boundAttributeName.length() > 0) {
0137: prop.setValue(
0138: SoaConstants.BOUNDED_ATTRIBUTE_NAME,
0139: boundAttributeName);
0140: }
0141: if (boundElementClass != null) {
0142: prop.setValue(
0143: SoaConstants.BOUNDED_ELEMENT_CLASS,
0144: boundElementClass);
0145: }
0146: //
0147: targetPropertySet.put(prop);
0148: return prop;
0149: }
0150: } else if (objRef != null && instanceRef == null) {
0151: //
0152: // Create fake instance ref which return objRef
0153: InstanceRef tempInnstanceRef = new InstanceRef() {
0154: public Object getReference() {
0155: return objRef;
0156: }
0157:
0158: public Object getAlternativeReference() {
0159: return null;
0160: }
0161: };
0162: //
0163: PropertyUtils.Reflection prop = new Reflection(
0164: tempInnstanceRef, propClass, getterName,
0165: setterName, removerName);
0166: // PropertySupport.Reflection prop = new PropertySupport.Reflection(
0167: // objRef, propClass, getterName, setterName);
0168: // The remover method doesn't supported in this case!
0169: //
0170: if (prop != null) {
0171: prop.setName(propName);
0172: prop.setValue(SoaConstants.PROPERTY_TYPE_ATTRIBUTE,
0173: propertyType);
0174: prop.setDisplayName(displayName);
0175: if (propEditorClass != null) {
0176: prop.setPropertyEditorClass(propEditorClass);
0177: }
0178: //
0179: if (boundAttributeName != null
0180: && boundAttributeName.length() > 0) {
0181: prop.setValue(
0182: SoaConstants.BOUNDED_ATTRIBUTE_NAME,
0183: boundAttributeName);
0184: }
0185: if (boundElementClass != null) {
0186: prop.setValue(
0187: SoaConstants.BOUNDED_ELEMENT_CLASS,
0188: boundElementClass);
0189: }
0190: //
0191: targetPropertySet.put(prop);
0192: return prop;
0193: }
0194: } else {
0195: assert true : "Illegal arguments!"; // NOI18N
0196: }
0197:
0198: } catch (NoSuchMethodException ex) {
0199: ErrorManager.getDefault().notify(ex);
0200: }
0201: return null;
0202: }
0203:
0204: /**
0205: * This method is intended to populate the column model of tables.
0206: *
0207: * TODO
0208: * This approach is artificial and can be replaced in future.
0209: * Really it seems the Column model can use PropertyType for the initialization.
0210: */
0211: public static Node.Property createPropertyStub(
0212: PropertyType propertyType) {
0213: Node.Property prop = null;
0214: try {
0215: Class propClass = propertyType.getPropertyClass();
0216: String propName = propertyType.toString();
0217: String displayName = propertyType.getDisplayName();
0218: Class propEditorClass = propertyType
0219: .getPropertyEditorClass();
0220: //
0221: prop = new PropertySupport.ReadOnly(propName, propClass,
0222: displayName, "This property is stub!") { // NOI18N
0223:
0224: public Object getValue() throws IllegalAccessException,
0225: InvocationTargetException {
0226: return null;
0227: }
0228:
0229: };
0230: if (prop != null) {
0231: prop.setValue(SoaConstants.PROPERTY_TYPE_ATTRIBUTE,
0232: propertyType);
0233: }
0234: } catch (Exception ex) {
0235: ErrorManager.getDefault().notify(ex);
0236: }
0237: return prop;
0238: }
0239:
0240: // public static Node.Property registerSimpleTypeProperty(
0241: // Sheet.Set targetPropertySet, String propName, String displayName,
0242: // Class propClass, Object referent,
0243: // String getterName, String setterName) {
0244: // Node.Property prop = null;
0245: // try {
0246: // prop = new PropertySupport.Reflection(
0247: // referent, propClass, getterName, setterName);
0248: // if (prop != null) {
0249: // prop.setName(propName);
0250: // prop.setDisplayName(displayName);
0251: // targetPropertySet.put(prop);
0252: // }
0253: // } catch (NoSuchMethodException ex) {
0254: // ErrorManager.getDefault().notify(ex);
0255: // }
0256: // return prop;
0257: // }
0258:
0259: //======================================================================
0260:
0261: public static Node.Property lookForPropertyByName(Node node,
0262: String desiredPropName) {
0263: if (desiredPropName == null || desiredPropName.length() == 0) {
0264: return null;
0265: }
0266: //
0267: for (Node.PropertySet propSet : node.getPropertySets()) {
0268: for (Node.Property prop : propSet.getProperties()) {
0269: //
0270: // Check if the source property has a name. If it isn't named then skip it.
0271: String propName = prop.getName();
0272: if (desiredPropName.equals(propName)) {
0273: return prop;
0274: }
0275: }
0276: }
0277: return null;
0278: }
0279:
0280: public static Node.Property lookForPropertyByType(Node node,
0281: PropertyType desiredPropType) {
0282: if (desiredPropType == null) {
0283: return null;
0284: }
0285: //
0286: return lookForPropertyByType(node.getPropertySets(),
0287: desiredPropType);
0288: }
0289:
0290: public static Node.Property lookForPropertyByType(
0291: Node.PropertySet[] propSetArr, PropertyType desiredPropType) {
0292: //
0293: for (Node.PropertySet propSet : propSetArr) {
0294: for (Node.Property prop : propSet.getProperties()) {
0295: //
0296: // Check if the source property has a name. If it isn't named then skip it.
0297: Object propType = prop
0298: .getValue(SoaConstants.PROPERTY_TYPE_ATTRIBUTE);
0299: if (propType == null) {
0300: continue;
0301: }
0302: assert propType instanceof PropertyType;
0303: if (desiredPropType.equals((PropertyType) propType)) {
0304: return prop;
0305: }
0306: }
0307: }
0308: return null;
0309: }
0310:
0311: public static Node.Property lookForPropertyByBoundedAttribute(
0312: Node node, String attrName) {
0313: if (attrName == null || attrName.length() == 0) {
0314: return null;
0315: }
0316: //
0317: for (Node.PropertySet propSet : node.getPropertySets()) {
0318: for (Node.Property prop : propSet.getProperties()) {
0319: //
0320: // Check if the source property has a name. If it isn't named then skip it.
0321: Object boundedAttributeName = prop
0322: .getValue(SoaConstants.BOUNDED_ATTRIBUTE_NAME);
0323: if (boundedAttributeName == null) {
0324: continue;
0325: }
0326: assert boundedAttributeName instanceof String;
0327: if (attrName.equals((String) boundedAttributeName)) {
0328: return prop;
0329: }
0330: }
0331: }
0332: return null;
0333: }
0334:
0335: public static Node.Property lookForPropertyByBoundedElement(
0336: Node node, Class elementClass) {
0337: if (elementClass == null) {
0338: return null;
0339: }
0340: //
0341: for (Node.PropertySet propSet : node.getPropertySets()) {
0342: for (Node.Property prop : propSet.getProperties()) {
0343: //
0344: // Check if the source property has a name. If it isn't named then skip it.
0345: Object boundedElementClass = prop
0346: .getValue(SoaConstants.BOUNDED_ELEMENT_CLASS);
0347: if (boundedElementClass == null) {
0348: continue;
0349: }
0350: assert boundedElementClass instanceof Class;
0351: if (((Class) boundedElementClass)
0352: .isAssignableFrom(elementClass)) {
0353: return prop;
0354: }
0355: }
0356: }
0357: return null;
0358: }
0359:
0360: //======================================================================
0361:
0362: /**
0363: * Support for properties which take the instance from an
0364: * InstanceRef.getReference() and use Java Reflection for looking the methods.
0365: */
0366: public static class Reflection extends Node.Property {
0367: /** Instance of a bean. */
0368: protected InstanceRef myInstanceRef;
0369:
0370: /** setter method */
0371: private Method mySetter;
0372:
0373: /** getter method */
0374: private Method myGetter;
0375:
0376: /** remover method */
0377: private Method myRemover;
0378:
0379: /** class of property editor */
0380: private Class propertyEditorClass;
0381:
0382: private PropertyEditor myPropertyEditor;
0383:
0384: /** Create a support with method objects specified.
0385: * The methods must be public.
0386: * @param instanceRef the InstanceRef to work on
0387: * @param valueType type of the property
0388: * @param getter getter method, can be <code>null</code>
0389: * @param setter setter method, can be <code>null</code>
0390: * @param remover remover method, can be <code>null</code>
0391: * @throws IllegalArgumentException if the methods are not public
0392: */
0393: public Reflection(InstanceRef instanceRef, Class valueType,
0394: Method getter, Method setter, Method remover) {
0395: super (valueType);
0396: assert instanceRef != null;
0397: //
0398: this .myInstanceRef = instanceRef;
0399: this .mySetter = setter;
0400: this .myGetter = getter;
0401: this .myRemover = remover;
0402: //
0403: checkMethods();
0404: }
0405:
0406: /** Create a support with methods specified by name.
0407: * The instance class will be examined for the named methods.
0408: * But if the instance class is not public, the nearest public superclass
0409: * will be used instead, so that the getters and setters remain accessible.
0410: * @param parentNode the BpelNode to work on
0411: * @param valueType type of the property
0412: * @param getter name of getter method, can be <code>null</code>
0413: * @param setter name of setter method, can be <code>null</code>
0414: * @param remover remover method, can be <code>null</code>
0415: * @exception NoSuchMethodException if the getter or setter methods cannot be found
0416: */
0417: public Reflection(InstanceRef instanceRef, Class valueType,
0418: String getterName, String setterName, String removerName)
0419: throws NoSuchMethodException {
0420: super (valueType);
0421: assert instanceRef != null;
0422: //
0423: Method getter = null;
0424: Method setter = null;
0425: Method remover = null;
0426: //
0427: this .myInstanceRef = instanceRef;
0428: Class[] targetClassesArr = findAccessibleClasses(instanceRef);
0429: //
0430: if (getterName != null) {
0431: getter = tryFindMethodByName(targetClassesArr,
0432: getterName, new Class[0]);
0433: }
0434: //
0435: if (setterName != null) {
0436: setter = tryFindMethodByName(targetClassesArr,
0437: setterName, new Class[] { valueType });
0438: }
0439: //
0440: if (removerName != null) {
0441: remover = tryFindMethodByName(targetClassesArr,
0442: removerName, new Class[0]);
0443: }
0444: //
0445: this .mySetter = setter;
0446: this .myGetter = getter;
0447: this .myRemover = remover;
0448: //
0449: checkMethods();
0450: }
0451:
0452: private Class[] findAccessibleClasses(InstanceRef instanceRef) {
0453: Class[] result = new Class[2];
0454: int counter = 0;
0455: //
0456: Object instance = instanceRef.getReference();
0457: if (instance instanceof DecoratedTMapComponent) {
0458: instance = ((DecoratedTMapComponent) instance)
0459: .getOriginal();
0460: }
0461:
0462: if (instance != null) {
0463: Class targetClass = findAccessibleClass(instance);
0464: if (targetClass != null) {
0465: result[counter] = targetClass;
0466: counter++;
0467: }
0468: }
0469: //
0470: instance = instanceRef.getAlternativeReference();
0471: if (instance != null) {
0472: Class targetClass = findAccessibleClass(instance);
0473: if (targetClass != null) {
0474: result[counter] = targetClass;
0475: counter++;
0476: }
0477: }
0478: //
0479: if (counter == 0) {
0480: throw new RuntimeException(
0481: "InstanceRef doesn't provide any instances"); // NOI18N
0482: }
0483: //
0484: return result;
0485: }
0486:
0487: /**
0488: * Looks for the method in the classes from the targetClassesArr.
0489: * The first suitable method is returned.
0490: * The NoSuchMethodException is thrown if no any method is found.
0491: */
0492: private Method tryFindMethodByName(Class[] targetClassesArr,
0493: String methodName, Class[] params)
0494: throws NoSuchMethodException {
0495: Method result = null;
0496: boolean methodFound = false;
0497: if (methodName != null) {
0498: for (Class targetClass : targetClassesArr) {
0499: try {
0500: result = targetClass.getMethod(methodName,
0501: params);
0502: } catch (NoSuchMethodException ex) {
0503: // do nothing
0504: }
0505: if (result != null) {
0506: methodFound = true;
0507: break;
0508: }
0509: }
0510: }
0511: if (!methodFound) {
0512: StringBuffer classesNames = new StringBuffer();
0513: boolean isFirst = true;
0514: for (Class classObj : targetClassesArr) {
0515: if (classObj != null) {
0516: if (isFirst) {
0517: isFirst = false;
0518: } else {
0519: classesNames.append("; "); // NOI18N
0520: }
0521: classesNames.append(classObj.getName());
0522: }
0523: }
0524: //
0525: throw new NoSuchMethodException(
0526: "The method \""
0527: + methodName
0528: + "\" can't be found "
0529: + "by the PropertyUtils.Reflection in the classes: "
0530: + classesNames); // NOI18N
0531: }
0532: return result;
0533: }
0534:
0535: /** Create a support based on the property name.
0536: * The getter and setter methods are constructed by capitalizing the first
0537: * letter in the name of propety and prefixing it with <code>get</code> and
0538: * <code>set</code>, respectively.
0539: *
0540: * @param instanceRef the InstanceRef to work on
0541: * @param valueType type of the property
0542: * @param property name of property
0543: * @exception NoSuchMethodException if the getter or setter methods cannot be found
0544: */
0545: public Reflection(InstanceRef instanceRef, Class valueType,
0546: String property) throws NoSuchMethodException {
0547: super (valueType);
0548: assert instanceRef != null;
0549: //
0550: Method getter = null;
0551: Method setter = null;
0552: Method remover = null;
0553: //
0554: Object instance = instanceRef.getReference();
0555: if (instance instanceof DecoratedTMapComponent) {
0556: instance = ((DecoratedTMapComponent) instance)
0557: .getOriginal();
0558: }
0559:
0560: Class targetClass = findAccessibleClass(instance);
0561: //
0562: getter = targetClass.getMethod(firstLetterToUpperCase(
0563: property, "get"), new Class[0]); // NOI18N
0564: if (getter == null) {
0565: getter = targetClass.getMethod(firstLetterToUpperCase(
0566: property, "is"), new Class[0]); // NOI18N
0567: }
0568: //
0569: setter = targetClass.getMethod(firstLetterToUpperCase(
0570: property, "set"), new Class[] { valueType }); // NOI18N
0571: //
0572: remover = targetClass.getMethod(firstLetterToUpperCase(
0573: property, "remove"), new Class[0]); // NOI18N
0574: //
0575: this .myInstanceRef = instanceRef;
0576: this .mySetter = setter;
0577: this .myGetter = getter;
0578: this .myRemover = remover;
0579: //
0580: checkMethods();
0581: }
0582:
0583: private void checkMethods() throws IllegalArgumentException {
0584: if ((myGetter != null)
0585: && !Modifier.isPublic(myGetter.getModifiers())) {
0586: throw new IllegalArgumentException(
0587: "Cannot use a non-public getter " + myGetter); // NOI18N
0588: }
0589:
0590: if ((mySetter != null)
0591: && !Modifier.isPublic(mySetter.getModifiers())) {
0592: throw new IllegalArgumentException(
0593: "Cannot use a non-public setter " + mySetter); // NOI18N
0594: }
0595:
0596: if ((myRemover != null)
0597: && !Modifier.isPublic(myRemover.getModifiers())) {
0598: throw new IllegalArgumentException(
0599: "Cannot use a non-public remover " + myRemover); // NOI18N
0600: }
0601: //
0602: }
0603:
0604: /**
0605: * Return the reference ptovider associated with the Property
0606: */
0607: public InstanceRef getInstanceRef() {
0608: return myInstanceRef;
0609: }
0610:
0611: private static Class findAccessibleClass(Object instance) {
0612: if (instance instanceof TMapComponent) {
0613: return ((TMapComponent) instance).getComponentType();
0614: } else {
0615: return findAccessibleClass(instance.getClass());
0616: }
0617: }
0618:
0619: /** Find the nearest superclass (or same class) that is public to this one. */
0620: private static Class findAccessibleClass(Class clazz) {
0621: if (Modifier.isPublic(clazz.getModifiers())) {
0622: return clazz;
0623: } else {
0624: Class sup = clazz.getSuperclass();
0625:
0626: if (sup == null) {
0627: return Object.class; // handle interfaces
0628: }
0629:
0630: return findAccessibleClass(sup);
0631: }
0632: }
0633:
0634: /** Helper method to convert the first letter of a string to uppercase.
0635: * And prefix the string with some next string.
0636: */
0637: private static String firstLetterToUpperCase(String s,
0638: String pref) {
0639: switch (s.length()) {
0640: case 0:
0641: return pref;
0642:
0643: case 1:
0644: return pref + Character.toUpperCase(s.charAt(0));
0645:
0646: default:
0647: return pref + Character.toUpperCase(s.charAt(0))
0648: + s.substring(1);
0649: }
0650: }
0651:
0652: /* Can read the value of the property.
0653: * @return <CODE>true</CODE> if the read of the value is supported
0654: */
0655: public boolean canRead() {
0656: return myGetter != null;
0657: }
0658:
0659: /* Getter for the value.
0660: * @return the value of the property
0661: * @exception IllegalAccessException cannot access the called method
0662: * @exception IllegalArgumentException wrong argument
0663: * @exception InvocationTargetException an exception during invocation
0664: */
0665: public Object getValue() throws IllegalAccessException,
0666: IllegalArgumentException, InvocationTargetException {
0667: if (myGetter == null) {
0668: throw new IllegalAccessException();
0669: }
0670: //
0671: try {
0672: try {
0673: return invokeMethod(myInstanceRef, myGetter,
0674: new Object[0]);
0675: } catch (IllegalAccessException ex) {
0676: try {
0677: myGetter.setAccessible(true);
0678: //
0679: return invokeMethod(myInstanceRef, myGetter,
0680: new Object[0]);
0681: } finally {
0682: myGetter.setAccessible(false);
0683: }
0684: }
0685: } catch (IllegalArgumentException iae) {
0686: //Provide a better message for debugging
0687: StringBuffer sb = new StringBuffer(
0688: "Attempted to invoke method "); // NOI18N
0689: sb.append(myGetter.getName());
0690: sb.append(" from class "); // NOI18N
0691: sb.append(myGetter.getDeclaringClass().getName());
0692: sb.append(" on an instance of "); // NOI18N
0693: sb.append(myGetter.getDeclaringClass().getName());
0694: sb.append(" Problem:"); // NOI18N
0695: sb.append(iae.getMessage());
0696:
0697: IllegalArgumentException nue = new IllegalArgumentException(
0698: sb.toString());
0699: ErrorManager.getDefault().annotate(nue, iae);
0700: throw nue;
0701: }
0702: }
0703:
0704: /* Can write the value of the property.
0705: * @return <CODE>true</CODE> if the write of the value is supported
0706: */
0707: public boolean canWrite() {
0708: Model model = getModel();
0709: if (model != null) {
0710: if (!XAMUtils.isWritable(model))
0711: return false;
0712: }
0713: return mySetter != null;
0714: }
0715:
0716: public Model getModel() {
0717: DocumentComponent dc = getDocumentComponent();
0718: return (dc != null) ? dc.getModel() : null;
0719: }
0720:
0721: public DocumentComponent getDocumentComponent() {
0722: Object ref = myInstanceRef.getReference();
0723:
0724: if (ref != null) {
0725: if (ref instanceof DocumentComponent) {
0726: return (DocumentComponent) ref;
0727: }
0728:
0729: if (ref instanceof TMapComponentNode) {
0730: TMapComponentNode node = (TMapComponentNode) ref;
0731:
0732: Object refRef = node.getReference();
0733:
0734: if ((refRef != null)
0735: && (refRef instanceof DocumentComponent)) {
0736: return (DocumentComponent) refRef;
0737: }
0738: }
0739: }
0740:
0741: if (myInstanceRef.getAlternativeReference() != null) {
0742: if (myInstanceRef.getAlternativeReference() instanceof DocumentComponent) {
0743: return (DocumentComponent) myInstanceRef
0744: .getAlternativeReference();
0745: }
0746:
0747: if (myInstanceRef.getAlternativeReference() instanceof TMapComponentNode) {
0748: TMapComponentNode node = (TMapComponentNode) myInstanceRef
0749: .getAlternativeReference();
0750:
0751: if ((node.getReference() != null)
0752: && (node.getReference() instanceof DocumentComponent)) {
0753: return (DocumentComponent) node.getReference();
0754: }
0755: }
0756: }
0757:
0758: return null;
0759: }
0760:
0761: /* Setter for the value.
0762: * @param val the value of the property
0763: * @exception IllegalAccessException cannot access the called method
0764: * @exception IllegalArgumentException wrong argument
0765: * @exception InvocationTargetException an exception during invocation
0766: */
0767: public void setValue(Object newValue)
0768: throws IllegalAccessException,
0769: IllegalArgumentException, InvocationTargetException {
0770: try {
0771: if (newValue == null
0772: || (newValue instanceof String && ((String) newValue)
0773: .length() == 0)) {
0774: if (canRemove()) {
0775: try {
0776: invokeMethod(myInstanceRef, myRemover,
0777: new Object[0]);
0778: } catch (IllegalAccessException ex) {
0779: try {
0780: myRemover.setAccessible(true);
0781: invokeMethod(myInstanceRef, myRemover,
0782: new Object[0]);
0783: } finally {
0784: myRemover.setAccessible(false);
0785: }
0786: }
0787: } else {
0788: Object oldValue = getValue();
0789: if (oldValue == null
0790: || (oldValue instanceof String && ((String) oldValue)
0791: .length() == 0)) {
0792: // DO NOTHING because of value hasn't been changed
0793: } else {
0794: // The following code is dangerous because of the
0795: // property editor can be used for other purposes.
0796: PropertyEditor pEditor = getPropertyEditor();
0797: pEditor.setValue(oldValue);
0798: String oldText = pEditor.getAsText();
0799: //
0800: if (oldText == null
0801: || oldText.length() == 0) {
0802: // DO NOTHING because of value hasn't been changed
0803: } else {
0804: //
0805: String msg = NbBundle.getMessage(
0806: TMapComponentNode.class,
0807: "ERR_REQURED_PROPERTY"); // NOI18N
0808: PropertyType pType = (PropertyType) getValue(SoaConstants.PROPERTY_TYPE_ATTRIBUTE);
0809: String propName;
0810: if (pType != null) {
0811: propName = pType.getDisplayName();
0812: } else {
0813: propName = getName();
0814: }
0815: //
0816: msg = MessageFormat.format(msg,
0817: propName);
0818: throw new InvocationTargetException(
0819: new VetoException(msg, null));
0820: }
0821: }
0822: }
0823: } else {
0824: try {
0825: if (mySetter == null) {
0826: throw new IllegalAccessException();
0827: }
0828: //
0829: invokeMethod(myInstanceRef, mySetter,
0830: new Object[] { newValue });
0831: } catch (IllegalAccessException ex) {
0832: try {
0833: mySetter.setAccessible(true);
0834: invokeMethod(myInstanceRef, mySetter,
0835: new Object[] { newValue });
0836: } finally {
0837: mySetter.setAccessible(false);
0838: }
0839: }
0840: }
0841: } catch (InvocationTargetException ex) {
0842: Throwable targetEx = ex.getTargetException();
0843: //
0844: boolean processed = false;
0845: if (targetEx instanceof VetoException) {
0846: //
0847: // Check if the setValue has been called from the property sheet
0848: StackTraceElement[] stackTraceArr = ex
0849: .getStackTrace();
0850: for (StackTraceElement stElement : stackTraceArr) {
0851: if (stElement.getMethodName().equals(
0852: "stopCellEditing")
0853: && stElement
0854: .getClassName()
0855: .equals(
0856: "org.openide.explorer.propertysheet.SheetCellEditor")) { // NOI18N
0857: //
0858: // The setValue is invoked from the propery sheet inplace editor
0859: //
0860: UserNotification.showMessage(targetEx
0861: .getLocalizedMessage());
0862: processed = true;
0863: break;
0864: } else if (stElement.getMethodName().equals(
0865: "cancelValue")
0866: && stElement
0867: .getClassName()
0868: .equals(
0869: "org.openide.explorer.propertysheet.PropertyDialogManager")) { // NOI18N
0870: //
0871: // Ignore the exception if user press the Cancel button
0872: processed = true;
0873: break;
0874: } else if (stElement.getMethodName().equals(
0875: "actionPerformed")
0876: && stElement
0877: .getClassName()
0878: .equals(
0879: "org.openide.explorer.propertysheet.PropertyDialogManager")) { // NOI18N
0880: //
0881: // The setValue is invoked from the propery customizer dialog
0882: //
0883: throw new PropertyVetoError(targetEx);
0884: }
0885: }
0886: } else if (!(targetEx instanceof Exception)) {
0887: ErrorManager.getDefault().notify(targetEx);
0888: processed = false;
0889: }
0890: //
0891: if (!processed) {
0892: throw ex;
0893: }
0894: }
0895: }
0896:
0897: /* Can remove the value of the property.
0898: * @return <CODE>true</CODE> if the remove of the value is supported
0899: */
0900: public boolean canRemove() {
0901: Model model = getModel();
0902: if (model != null) {
0903: if (!XAMUtils.isWritable(model))
0904: return false;
0905: }
0906: return myRemover != null;
0907: }
0908:
0909: public void removeValue() throws IllegalAccessException,
0910: IllegalArgumentException, InvocationTargetException {
0911: if (myRemover == null) {
0912: throw new IllegalAccessException();
0913: }
0914:
0915: //
0916: setValue(null);
0917:
0918: }
0919:
0920: /* Returns property editor for this property.
0921: * @return the property editor or <CODE>null</CODE> if there should not be
0922: * any editor.
0923: */
0924: public synchronized PropertyEditor getPropertyEditor() {
0925: if (myPropertyEditor == null) {
0926: if (propertyEditorClass != null) {
0927: Object result = null;
0928: //
0929: // if (propertyEditorClass != null &&
0930: // Reusable.class.isAssignableFrom(propertyEditorClass)) {
0931: // result = PropertyUtils.propertyEditorPool.
0932: // getObjectByClass(propertyEditorClass);
0933: // }
0934: // //
0935: // // Try to load static method "getInstance"
0936: // if (result == null) {
0937: // try {
0938: // Method method = propertyEditorClass.
0939: // getMethod("getInstance"); // NOI18N
0940: // result = method.invoke(propertyEditorClass);
0941: // } catch (Exception ex) {
0942: // // DO Nothing
0943: // }
0944: // }
0945: //
0946: // Try to call the default constructor
0947: if (result == null) {
0948: try {
0949: result = propertyEditorClass.newInstance();
0950: } catch (Exception ex) {
0951: // DO Nothing
0952: }
0953: }
0954: //
0955: if (result instanceof PropertyEditor) {
0956: myPropertyEditor = (PropertyEditor) result;
0957: }
0958: }
0959: }
0960: //
0961: if (myPropertyEditor != null) {
0962: return myPropertyEditor;
0963: } else {
0964: return super .getPropertyEditor();
0965: }
0966: }
0967:
0968: /** Set the property editor explicitly.
0969: * @param clazz class type of the property editor
0970: */
0971: public void setPropertyEditorClass(Class clazz) {
0972: propertyEditorClass = clazz;
0973: }
0974:
0975: private Object invokeMethod(InstanceRef instanceRef,
0976: Method method, Object... args)
0977: throws IllegalAccessException,
0978: IllegalArgumentException, InvocationTargetException {
0979: Class<?> requiredClass = method.getDeclaringClass();
0980: //
0981: Object instance = instanceRef.getReference();
0982: if (instance instanceof DecoratedTMapComponent) {
0983: instance = ((DecoratedTMapComponent) instance)
0984: .getOriginal();
0985: }
0986:
0987: if (instance != null
0988: && requiredClass.isAssignableFrom(instance
0989: .getClass())) {
0990: return method.invoke(instance, args);
0991: }
0992: //
0993: instance = instanceRef.getAlternativeReference();
0994: if (instance != null
0995: && requiredClass.isAssignableFrom(instance
0996: .getClass())) {
0997: return method.invoke(instance, args);
0998: }
0999: //
1000: throw new IllegalArgumentException("The method \""
1001: + method.getName()
1002: + "\" can't be called for the specified objecs"); // NOI18N
1003: }
1004: }
1005:
1006: }
|