package abbot.editor.editors; import java.awt.Component; import java.awt.event.ActionEvent; import java.lang.reflect.*; import java.util.*; import javax.swing.*; import abbot.Log; import abbot.i18n.Strings; import abbot.script.*; import abbot.tester.ComponentTester; /** Provide convenient editing of a PropertyCall step. */ public abstract class PropertyCallEditor extends CallEditor { private JComboBox component; private PropertyCall call; public PropertyCallEditor(PropertyCall call) { super(call); this.call = call; component = addComponentSelector(Strings.get("ComponentID"), call.getComponentID(), call.getResolver(), true); component.setName(TAG_COMPONENT); } /** Get the class of the current component target, if any. */ protected Class getComponentTargetClass(Class cls) { String[] args = getCall().getArguments(); if (args.length == 1) { String id = args[0]; ComponentReference ref = getCall().getResolver().getComponentReference(id); if (ref != null) { try { return getCall().resolveClass(ref.getRefClassName()); } catch(ClassNotFoundException e) { } } } return null; } /** If the target is Component or ComponentTester, provide a merge of property-like methods from both. */ protected Map getMethods(Class cls, int mask) { boolean isTester = ComponentTester.class.isAssignableFrom(cls); boolean isComponent = Component.class.isAssignableFrom(cls); Class componentClass = isTester ? getComponentTargetClass(cls) : (isComponent ? cls : null); Class testerClass = isTester ? cls : (isComponent ? ComponentTester.getTester(componentClass).getClass() : null); if (!isTester && !isComponent) return super.getMethods(cls, mask); Map map = new HashMap(); if (componentClass != null) { Iterator iter = super.getMethods(componentClass, mask).values().iterator(); while (iter.hasNext()) { Method m = (Method)iter.next(); if (PropertyCall.isPropertyMethod(m)) { map.put(m.getName(), m); } } } // Scan the corresponding component tester for additional property // methods try { ComponentTester tester = componentClass != null ? ComponentTester.getTester(componentClass) : (ComponentTester)testerClass.newInstance(); Iterator iter = getComponentTesterMethods(tester).iterator(); while (iter.hasNext()) { Method m = (Method)iter.next(); map.put(m.getName(), m); } } catch(Exception e) { } return map; } protected boolean includeMethod(Class cls, Method m) { return true; } protected Collection getComponentTesterMethods(ComponentTester tester) { return Arrays.asList(tester.getPropertyMethods()); } /** Synchronize the component selector with the PropertyCall data. */ protected void componentChanged() { component.setSelectedItem(call.getComponentID()); } public void actionPerformed(ActionEvent ev) { Object src = ev.getSource(); if (src == component) { String id = (String)component.getSelectedItem(); if (id != null) id = id.trim(); if ("".equals(id)) { id = null; } ComponentReference ref = call.getResolver().getComponentReference(id); String tcn = ref != null ? ref.getRefClassName() : Component.class.getClass().getName(); call.setComponentID(id); call.setTargetClassName(tcn); call.setArguments(new String[0]); targetClassChanged(); argumentsChanged(); fireStepChanged(); } else if (src == method) { super.actionPerformed(ev); // When the method changes to or from a ComponentTester // pseudo-property method, we need to change the target class. try { Class cls = call.getTargetClass(); String methodName = (String)method.getSelectedItem(); Map methods = getMethods(cls, Modifier.PUBLIC); Method m = (Method)methods.get(methodName); if (m != null) { Class newClass = m.getDeclaringClass(); if (ComponentTester.class.isAssignableFrom(newClass) && Component.class.isAssignableFrom(cls)) { String id = call.getComponentID(); if (id != null) { call.setArguments(new String[] { id }); argumentsChanged(); } call.setComponentID(null); call.setTargetClassName(newClass.getName()); componentChanged(); targetClassChanged(); fireStepChanged(); } else if (Component.class.isAssignableFrom(newClass) && ComponentTester.class.isAssignableFrom(cls) && call.getArguments().length == 1) { newClass = getComponentTargetClass(cls); String id = call.getArguments()[0]; call.setArguments(new String[0]); call.setComponentID(id); call.setTargetClassName(newClass.getName()); argumentsChanged(); componentChanged(); targetClassChanged(); fireStepChanged(); } } } catch(ClassNotFoundException e) { // don't care } } else { super.actionPerformed(ev); } } }