source: trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/GUIElementFactory.java @ 1067

Last change on this file since 1067 was 1067, checked in by pharms, 11 years ago
  • corrected formatting
File size: 11.8 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.eventcore.guimodel;
16
17import java.io.File;
18import java.io.FileInputStream;
19import java.io.FileNotFoundException;
20import java.io.IOException;
21import java.io.InputStream;
22import java.lang.reflect.Constructor;
23import java.lang.reflect.InvocationTargetException;
24import java.util.Properties;
25import java.util.logging.Level;
26
27import de.ugoe.cs.util.console.Console;
28
29/**
30 * <p>
31 * Creates {@link IGUIElement}s from a given specification. Implemented as singleton.
32 * </p>
33 *
34 * @version 1.0
35 * @author Patrick Harms
36 */
37public class GUIElementFactory implements IGUIElementFactory {
38
39    /**
40     * <p>
41     * Instance of the class (singleton)
42     * </p>
43     */
44    private static GUIElementFactory instance = new GUIElementFactory();
45
46    /**
47     * <p>
48     * Constructor. Creates a new GUIElementFactory. Private to preserve singleton property.
49     * </p>
50     */
51    private GUIElementFactory() {}
52
53    /**
54     * <p>
55     * Returns the instance of this class.
56     * </p>
57     *
58     * @return the instance
59     */
60    public static synchronized GUIElementFactory getInstance() {
61        return instance;
62    }
63
64    /**
65     * <p>
66     * A property mapping that defines to which Java class is created given the type of the GUI
67     * element found in the specification.
68     * </p>
69     */
70    private Properties mappingsFromConfiguration;
71
72   
73    /*
74     * (non-Javadoc)
75     *
76     * @see
77     * de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementFactory#instantiateGUIElement(de.ugoe.cs.autoquest
78     * .eventcore.guimodel.IGUIElementSpec, de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement)
79     */
80    @Override
81    public IGUIElement instantiateGUIElement(IGUIElementSpec specification, IGUIElement parent)
82        throws GUIModelConfigurationException
83    {
84        Properties mappings = getMappingsFromConfiguration();
85        IGUIElement guiElement = null;
86        String[] typeHierarchy = specification.getTypeHierarchy();
87        int i = 0;
88        String className = null;
89       
90        while ((className == null) && (i < typeHierarchy.length)) {
91            className = mappings.getProperty(typeHierarchy[i]);
92            i++;
93        }
94       
95        if (className != null) {
96            try {
97                Class<?> clazz = this.getClass().getClassLoader().loadClass(className);
98
99                if (!IGUIElement.class.isAssignableFrom(clazz)) {
100                    Console.traceln(Level.WARNING, "configured GUI element representing class " +
101                        className + " is no valid GUIElement derivate.");
102
103                    return null;
104                }
105
106                Constructor<?> constructor = null;
107                Class<?> parentClass = (parent == null) ? null : parent.getClass();
108
109                // search for a constructor, that perfectly matches the types
110                for (Constructor<?> candidate : clazz.getConstructors()) {
111                    if ((parentClass != null) && (candidate.getParameterTypes().length == 2) &&
112                        (candidate.getParameterTypes()[0].equals(specification.getClass())) &&
113                        (candidate.getParameterTypes()[1].equals(parentClass)))
114                    {
115                        constructor = candidate;
116                        break;
117                    }
118                    else if (parentClass == null) {
119                        if ((candidate.getParameterTypes().length >= 1) &&
120                            (candidate.getParameterTypes()[0].equals(specification.getClass())))
121                        {
122                            constructor = candidate;
123                            break;
124                        }
125                    }
126                }
127
128                if (constructor == null) {
129                    // search for an assignable constructor
130                    for (Constructor<?> candidate : clazz.getConstructors()) {
131                        if ((candidate.getParameterTypes().length == 2) &&
132                            (candidate.getParameterTypes()[0].isInstance(specification)) &&
133                            (candidate.getParameterTypes()[1].isInstance(parent)))
134                        {
135                            constructor = candidate;
136                            break;
137                        }
138                    }
139
140                }
141               
142                if (constructor != null) {
143                    guiElement = (IGUIElement) constructor.newInstance(specification, parent);
144                }
145                else {
146                    throw new NoSuchMethodException
147                        ("no constructor with two parameters and assignable parameter types for " +
148                         specification.getClass() + " and " +
149                         (parent != null ? parent.getClass() : "null") + " found in class " +
150                         clazz);
151                }
152
153            }
154            catch (ClassNotFoundException e) {
155                Console.traceln(Level.WARNING, "configured GUI element representing class " +
156                                className + " can not be loaded.");
157                throw new GUIModelConfigurationException
158                    ("configured GUI element representing class " + className +
159                     " can not be loaded.", e);
160            }
161            catch (SecurityException e) {
162                Console.traceln(Level.WARNING, "configured GUI element representing class " +
163                                className + " can not be instantiated due to security reasons.");
164                throw new GUIModelConfigurationException
165                    ("configured GUI element representing class " + className +
166                     " can not be instantiated due to security reasons.", e);
167            }
168            catch (NoSuchMethodException e) {
169                Console.traceln(Level.WARNING, "configured GUI element representing class " +
170                                className + " does not provide an appropriate constructor.");
171                throw new GUIModelConfigurationException
172                    ("configured GUI element representing class " + className +
173                     " does not provide an appropriate constructor.", e);
174            }
175            catch (IllegalArgumentException e) {
176                Console.traceln(Level.WARNING, "configured GUI element representing class " +
177                                className + " does not provide an appropriate constructor " +
178                                "accepting the provided parameters.");
179                throw new GUIModelConfigurationException
180                    ("configured GUI element representing class " + className + " does not " +
181                     "provide an appropriate constructor accepting the provided parameters.", e);
182            }
183            catch (InstantiationException e) {
184                Console.traceln(Level.WARNING, "configured GUI element representing class " +
185                                className + " can not be instantiated.");
186                throw new GUIModelConfigurationException
187                    ("configured GUI element representing class " + className +
188                     " can not be instantiated.", e);
189            }
190            catch (IllegalAccessException e) {
191                Console.traceln(Level.WARNING, "configured GUI element representing class " +
192                                className + " can not be instantiated.");
193                throw new GUIModelConfigurationException
194                    ("configured GUI element representing class " + className +
195                     " can not be instantiated.", e);
196            }
197            catch (InvocationTargetException e) {
198                Console.traceln(Level.WARNING, "configured GUI element representing class " +
199                                className + " can not be instantiated.");
200                throw new GUIModelConfigurationException
201                    ("configured GUI element representing class " + className +
202                     " can not be instantiated.", e);
203            }
204        }
205       
206        if (guiElement == null ) {
207            Console.traceln(Level.WARNING, "no class representing GUI elements of type " +
208                            specification.getType() + " found. Please extend GUI element " +
209                            "mapping files.");
210            throw new GUIModelConfigurationException
211                ("no class representing GUI elements of type " + specification.getType() +
212                 " found. Please extend GUI element mapping files");
213        }
214
215        return guiElement;
216    }
217
218    /**
219     * <p>
220     * Loads the mappings for GUI elements. All files that start with &quot;guimapping&quot;, end
221     * with &quot;.txt&quot;, and are located in the folter &quot;data/guimappings&quot; (relative
222     * to the working directory) are loaded.
223     * </p>
224     *
225     * @return loaded GUI mappings
226     */
227    private synchronized Properties getMappingsFromConfiguration()
228        throws GUIModelConfigurationException
229    {
230        if (mappingsFromConfiguration != null) {
231            return mappingsFromConfiguration;
232        }
233        else {
234            mappingsFromConfiguration = new Properties();
235
236            File mappingsFolder = new File("data/guimappings");
237            File[] children = mappingsFolder.listFiles();
238
239            if (children != null) {
240                for (File mappingsFile : children) {
241                    if (!mappingsFile.isDirectory() &&
242                        mappingsFile.getName().startsWith("guimapping") &&
243                        mappingsFile.getName().endsWith(".txt"))
244                    {
245                        InputStream inStream = null;
246                        try {
247                            inStream = new FileInputStream(mappingsFile);
248                            mappingsFromConfiguration.load(inStream);
249                        }
250                        catch (FileNotFoundException e) {
251                            throw new GUIModelConfigurationException(
252                                                                     "could not read mapping configuration file " +
253                                                                         mappingsFile, e);
254                        }
255                        catch (IOException e) {
256                            throw new GUIModelConfigurationException(
257                                                                     "could not read mapping configuration file " +
258                                                                         mappingsFile, e);
259                        }
260                        finally {
261                            if (inStream != null) {
262                                try {
263                                    inStream.close();
264                                }
265                                catch (IOException e) {
266                                    // ignore
267                                }
268                            }
269                        }
270                    }
271                }
272            }
273            else {
274                throw new GUIModelConfigurationException(
275                                                         "no GUI mappings file provided in folder " +
276                                                             mappingsFolder);
277            }
278
279            return mappingsFromConfiguration;
280        }
281    }
282}
Note: See TracBrowser for help on using the repository browser.