001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s): Alexandre Iline.
025: *
026: * The Original Software is the Jemmy library.
027: * The Initial Developer of the Original Software is Alexandre Iline.
028: * All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: *
041: *
042: *
043: * $Id$ $Revision$ $Date$
044: *
045: */
046:
047: package org.netbeans.jemmy.util;
048:
049: import org.netbeans.jemmy.ComponentChooser;
050: import org.netbeans.jemmy.ClassReference;
051: import org.netbeans.jemmy.JemmyProperties;
052: import org.netbeans.jemmy.Outputable;
053: import org.netbeans.jemmy.TestOut;
054:
055: import java.awt.Component;
056:
057: import java.lang.reflect.InvocationTargetException;
058:
059: /**
060: *
061: * Implementation of org.netbeans.jemmy.ComponentChooser interface.
062: * Class can be used to find component by its field/methods values. <br>
063: * Example:
064: * <pre>
065: * String[] methods = {"getClientProperty"};
066: * Object[][] params = {{"classname"}};
067: * Class[][] classes = {{Object.class}};
068: * Object[] results = {"javax.swing.JCheckBox"};
069: *
070: * JCheckBox box = JCheckBoxOperator.findJCheckBox(frm0, new PropChooser(methods, params, classes, results));
071: * </pre>
072: * Or:
073: * <pre>
074: * String[] methods = {"getText"};
075: * Object[] results = {"Open"};
076: *
077: * JButtonOperator box = new JButtonOperator(containerOperator, new PropChooser(fields, results));
078: * </pre>
079: *
080: * @author Alexandre Iline (alexandre.iline@sun.com)
081: */
082: public class PropChooser implements ComponentChooser, Outputable {
083:
084: /**
085: * Names of methods to check.
086: */
087: protected String[] propNames;
088:
089: /**
090: * Methods parameters.
091: */
092: protected Object[][] params;
093:
094: /**
095: * Classes of parameters.
096: */
097: protected Class[][] classes;
098:
099: /**
100: * Expected results of methods.
101: */
102: protected Object[] results;
103:
104: private TestOut output;
105:
106: /**
107: * Constructs a PropChooser object.
108: * @param propNames Names of methods/fields
109: * @param params Parameters values for methods. <BR>
110: * params[0] is an array of parameters for propNames[0] methods. <BR>
111: * If propNames[0] is a field, params[0] is ignored.
112: * @param classes Parameters classes.
113: * @param results Objects to compare method/field values to. <BR>
114: * A value of propNames[0] method/field should be equal to results[0] object.
115: */
116: public PropChooser(String[] propNames, Object[][] params,
117: Class[][] classes, Object[] results) {
118: this .propNames = propNames;
119: this .results = results;
120: if (params != null) {
121: this .params = params;
122: } else {
123: this .params = new Object[propNames.length][0];
124: }
125: if (classes != null) {
126: this .classes = classes;
127: } else {
128: this .classes = new Class[this .params.length][0];
129: for (int i = 0; i < this .params.length; i++) {
130: Class[] clsss = new Class[this .params[i].length];
131: for (int j = 0; j < this .params[i].length; j++) {
132: clsss[j] = this .params[i][j].getClass();
133: }
134: this .classes[i] = clsss;
135: }
136: }
137: setOutput(JemmyProperties.getCurrentOutput());
138: }
139:
140: /**
141: * Constructs a PropChooser object for checking of methods
142: * with no parameters.
143: * @param propNames Names of methods/fields
144: * @param results Objects to compare method/field values to.
145: */
146: public PropChooser(String[] propNames, Object[] results) {
147: this (propNames, null, null, results);
148: }
149:
150: public void setOutput(TestOut output) {
151: this .output = output;
152: }
153:
154: public TestOut getOutput() {
155: return (output);
156: }
157:
158: public boolean checkComponent(Component comp) {
159: try {
160: String propName = null;
161: Object value;
162: ClassReference disp = new ClassReference(comp);
163: for (int i = 0; i < propNames.length; i++) {
164: propName = propNames[i];
165: if (propName != null) {
166: if (isField(comp, propName, classes[i])) {
167: try {
168: value = disp.getField(propName);
169: } catch (IllegalStateException e) {
170: output.printStackTrace(e);
171: return (false);
172: } catch (NoSuchFieldException e) {
173: output.printStackTrace(e);
174: return (false);
175: } catch (IllegalAccessException e) {
176: output.printStackTrace(e);
177: return (false);
178: }
179: } else {
180: try {
181: value = disp.invokeMethod(propName,
182: params[i], classes[i]);
183: } catch (InvocationTargetException e) {
184: output.printStackTrace(e);
185: return (false);
186: } catch (IllegalStateException e) {
187: output.printStackTrace(e);
188: return (false);
189: } catch (NoSuchMethodException e) {
190: output.printStackTrace(e);
191: return (false);
192: } catch (IllegalAccessException e) {
193: output.printStackTrace(e);
194: return (false);
195: }
196: }
197: if (!checkProperty(value, results[i])) {
198: return (false);
199: }
200: }
201: }
202: return (true);
203: } catch (SecurityException e) {
204: output.printStackTrace(e);
205: return (false);
206: }
207: }
208:
209: public String getDescription() {
210: String result = "";
211: for (int i = 0; i < propNames.length; i++) {
212: result = result + " " + propNames[i];
213: }
214: return ("Component by properties array\n :" + result);
215: }
216:
217: /**
218: * Method to check one method result with an etalon.
219: * Can be overrided by a subclass.
220: * @param value Method/field value
221: * @param etalon Object to compare to.
222: * @return true if the value matches the etalon.
223: */
224: protected boolean checkProperty(Object value, Object etalon) {
225: return (value.equals(etalon));
226: }
227:
228: /* try to define if propName is a field or method*/
229: private boolean isField(Component comp, String propName,
230: Class[] params) throws SecurityException {
231: try {
232: comp.getClass().getField(propName);
233: comp.getClass().getMethod(propName, params);
234: } catch (NoSuchMethodException e) {
235: return (true);
236: } catch (NoSuchFieldException e) {
237: return (false);
238: }
239: return (true);
240: }
241: }
|