PropChooser.java revision 13978:1993af50385d
1/*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.netbeans.jemmy.util;
24
25import java.awt.Component;
26import java.lang.reflect.InvocationTargetException;
27
28import org.netbeans.jemmy.ClassReference;
29import org.netbeans.jemmy.ComponentChooser;
30import org.netbeans.jemmy.JemmyProperties;
31import org.netbeans.jemmy.Outputable;
32import org.netbeans.jemmy.TestOut;
33
34/**
35 *
36 * Implementation of org.netbeans.jemmy.ComponentChooser interface. Class can be
37 * used to find component by its field/methods values. <br>
38 * Example:
39 * <pre>
40 *            String[] methods = {"getClientProperty"};
41 *            Object[][] params = {{"classname"}};
42 *            Class<?>[][] classes = {{Object.class}};
43 *            Object[] results = {"javax.swing.JCheckBox"};
44 *
45 *            JCheckBox box = JCheckBoxOperator.findJCheckBox(frm0, new PropChooser(methods, params, classes, results));
46 * </pre> Or:
47 * <pre>
48 *            String[] methods = {"getText"};
49 *            Object[] results = {"Open"};
50 *
51 *            JButtonOperator box = new JButtonOperator(containerOperator, new PropChooser(fields, results));
52 * </pre>
53 *
54 * @author Alexandre Iline (alexandre.iline@oracle.com)
55 */
56public class PropChooser implements ComponentChooser, Outputable {
57
58    /**
59     * Names of methods to check.
60     */
61    protected String[] propNames;
62
63    /**
64     * Methods parameters.
65     */
66    protected Object[][] params;
67
68    /**
69     * Classes of parameters.
70     */
71    protected Class<?>[][] classes;
72
73    /**
74     * Expected results of methods.
75     */
76    protected Object[] results;
77
78    private TestOut output;
79
80    /**
81     * Constructs a PropChooser object.
82     *
83     * @param propNames Names of methods/fields
84     * @param params Parameters values for methods. <BR>
85     * params[0] is an array of parameters for propNames[0] methods. <BR>
86     * If propNames[0] is a field, params[0] is ignored.
87     * @param classes Parameters classes.
88     * @param results Objects to compare method/field values to. <BR>
89     * A value of propNames[0] method/field should be equal to results[0]
90     * object.
91     */
92    public PropChooser(String[] propNames,
93            Object[][] params,
94            Class<?>[][] classes,
95            Object[] results) {
96        this.propNames = propNames;
97        this.results = results;
98        if (params != null) {
99            this.params = params;
100        } else {
101            this.params = new Object[propNames.length][0];
102        }
103        if (classes != null) {
104            this.classes = classes;
105        } else {
106            this.classes = new Class<?>[this.params.length][0];
107            for (int i = 0; i < this.params.length; i++) {
108                Class<?>[] clsss = new Class<?>[this.params[i].length];
109                for (int j = 0; j < this.params[i].length; j++) {
110                    clsss[j] = this.params[i][j].getClass();
111                }
112                this.classes[i] = clsss;
113            }
114        }
115        setOutput(JemmyProperties.getCurrentOutput());
116    }
117
118    /**
119     * Constructs a PropChooser object for checking of methods with no
120     * parameters.
121     *
122     * @param propNames Names of methods/fields
123     * @param results Objects to compare method/field values to.
124     */
125    public PropChooser(String[] propNames,
126            Object[] results) {
127        this(propNames, null, null, results);
128    }
129
130    @Override
131    public void setOutput(TestOut output) {
132        this.output = output;
133    }
134
135    @Override
136    public TestOut getOutput() {
137        return output;
138    }
139
140    @Override
141    public boolean checkComponent(Component comp) {
142        try {
143            String propName = null;
144            Object value;
145            ClassReference disp = new ClassReference(comp);
146            for (int i = 0; i < propNames.length; i++) {
147                propName = propNames[i];
148                if (propName != null) {
149                    if (isField(comp, propName, classes[i])) {
150                        try {
151                            value = disp.getField(propName);
152                        } catch (IllegalStateException e) {
153                            output.printStackTrace(e);
154                            return false;
155                        } catch (NoSuchFieldException e) {
156                            output.printStackTrace(e);
157                            return false;
158                        } catch (IllegalAccessException e) {
159                            output.printStackTrace(e);
160                            return false;
161                        }
162                    } else {
163                        try {
164                            value = disp.invokeMethod(propName, params[i], classes[i]);
165                        } catch (InvocationTargetException e) {
166                            output.printStackTrace(e);
167                            return false;
168                        } catch (IllegalStateException e) {
169                            output.printStackTrace(e);
170                            return false;
171                        } catch (NoSuchMethodException e) {
172                            output.printStackTrace(e);
173                            return false;
174                        } catch (IllegalAccessException e) {
175                            output.printStackTrace(e);
176                            return false;
177                        }
178                    }
179                    if (!checkProperty(value, results[i])) {
180                        return false;
181                    }
182                }
183            }
184            return true;
185        } catch (SecurityException e) {
186            output.printStackTrace(e);
187            return false;
188        }
189    }
190
191    @Override
192    public String getDescription() {
193        StringBuilder result = new StringBuilder();
194        for (String propName : propNames) {
195            result.append(' ').append(propName);
196        }
197        return "Component by properties array\n    :" + result.toString();
198    }
199
200    @Override
201    public String toString() {
202        return "PropChooser{" + "description=" + getDescription() + '}';
203    }
204
205    /**
206     * Method to check one method result with an etalon. Can be overrided by a
207     * subclass.
208     *
209     * @param value Method/field value
210     * @param etalon Object to compare to.
211     * @return true if the value matches the etalon.
212     */
213    protected boolean checkProperty(Object value, Object etalon) {
214        return value.equals(etalon);
215    }
216
217    /* try to define if propName is a field or method*/
218    private boolean isField(Component comp, String propName, Class<?>[] params)
219            throws SecurityException {
220        try {
221            comp.getClass().getField(propName);
222            comp.getClass().getMethod(propName, params);
223        } catch (NoSuchMethodException e) {
224            return true;
225        } catch (NoSuchFieldException e) {
226            return false;
227        }
228        return true;
229    }
230}
231