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

Last change on this file since 927 was 927, checked in by sherbold, 12 years ago
  • added copyright under the Apache License, Version 2.0
File size: 11.6 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
87        String className = mappings.getProperty(specification.getType());
88        if (className != null) {
89            try {
90                Class<?> clazz = this.getClass().getClassLoader().loadClass(className);
91
92                if (!IGUIElement.class.isAssignableFrom(clazz)) {
93                    Console.traceln(Level.WARNING, "configured GUI element representing class " +
94                        className + " is no valid GUIElement derivate.");
95
96                    return null;
97                }
98
99                Constructor<?> constructor = null;
100                Class<?> parentClass = (parent == null) ? null : parent.getClass();
101
102                // search for a constructor, that perfectly matches the types
103                for (Constructor<?> candidate : clazz.getConstructors()) {
104                    if ((parentClass != null) && (candidate.getParameterTypes().length == 2) &&
105                        (candidate.getParameterTypes()[0].equals(specification.getClass())) &&
106                        (candidate.getParameterTypes()[1].equals(parentClass)))
107                    {
108                        constructor = candidate;
109                        break;
110                    }
111                    else if (parentClass == null) {
112                        if ((candidate.getParameterTypes().length >= 1) &&
113                            (candidate.getParameterTypes()[0].equals(specification.getClass())))
114                        {
115                            constructor = candidate;
116                            break;
117                        }
118                    }
119                }
120
121                if (constructor == null) {
122                    // search for an assignable constructor
123                    for (Constructor<?> candidate : clazz.getConstructors()) {
124                        if ((candidate.getParameterTypes().length == 2) &&
125                            (candidate.getParameterTypes()[0].isInstance(specification)) &&
126                            (candidate.getParameterTypes()[1].isInstance(parent)))
127                        {
128                            constructor = candidate;
129                            break;
130                        }
131                    }
132
133                }
134               
135                if (constructor != null) {
136                    guiElement = (IGUIElement) constructor.newInstance(specification, parent);
137                }
138                else {
139                    throw new NoSuchMethodException
140                        ("no constructor with two parameters and assignable parameter types for " +
141                         specification.getClass() + " and " +
142                         (parent != null ? parent.getClass() : "null") + " found in class " +
143                         clazz);
144                }
145
146            }
147            catch (ClassNotFoundException e) {
148                Console.traceln(Level.WARNING, "configured GUI element representing class " +
149                                className + " can not be loaded.");
150                throw new GUIModelConfigurationException
151                    ("configured GUI element representing class " + className +
152                     " can not be loaded.", e);
153            }
154            catch (SecurityException e) {
155                Console.traceln(Level.WARNING, "configured GUI element representing class " +
156                                className + " can not be instantiated due to security reasons.");
157                throw new GUIModelConfigurationException
158                    ("configured GUI element representing class " + className +
159                     " can not be instantiated due to security reasons.", e);
160            }
161            catch (NoSuchMethodException e) {
162                Console.traceln(Level.WARNING, "configured GUI element representing class " +
163                                className + " does not provide an appropriate constructor.");
164                throw new GUIModelConfigurationException
165                    ("configured GUI element representing class " + className +
166                     " does not provide an appropriate constructor.", e);
167            }
168            catch (IllegalArgumentException e) {
169                Console.traceln(Level.WARNING, "configured GUI element representing class " +
170                                className + " does not provide an appropriate constructor " +
171                                "accepting the provided parameters.");
172                throw new GUIModelConfigurationException
173                    ("configured GUI element representing class " + className + " does not " +
174                     "provide an appropriate constructor accepting the provided parameters.", e);
175            }
176            catch (InstantiationException e) {
177                Console.traceln(Level.WARNING, "configured GUI element representing class " +
178                                className + " can not be instantiated.");
179                throw new GUIModelConfigurationException
180                    ("configured GUI element representing class " + className +
181                     " can not be instantiated.", e);
182            }
183            catch (IllegalAccessException 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 (InvocationTargetException 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        }
198       
199        if (guiElement == null ) {
200            Console.traceln(Level.WARNING, "no class representing GUI elements of type " +
201                            specification.getType() + " found. Please extend GUI element " +
202                            "mapping files.");
203            throw new GUIModelConfigurationException
204                ("no class representing GUI elements of type " + specification.getType() +
205                 " found. Please extend GUI element mapping files");
206        }
207
208        return guiElement;
209    }
210
211    /**
212     * <p>
213     * Loads the mappings for GUI elements. All files that start with &quot;guimapping&quot;, end
214     * with &quot;.txt&quot;, and are located in the folter &quot;data/guimappings&quot; (relative
215     * to the working directory) are loaded.
216     * </p>
217     *
218     * @return loaded GUI mappings
219     */
220    private synchronized Properties getMappingsFromConfiguration()
221        throws GUIModelConfigurationException
222    {
223        if (mappingsFromConfiguration != null) {
224            return mappingsFromConfiguration;
225        }
226        else {
227            mappingsFromConfiguration = new Properties();
228
229            File mappingsFolder = new File("data/guimappings");
230            File[] children = mappingsFolder.listFiles();
231
232            if (children != null) {
233                for (File mappingsFile : children) {
234                    if (!mappingsFile.isDirectory() &&
235                        mappingsFile.getName().startsWith("guimapping") &&
236                        mappingsFile.getName().endsWith(".txt"))
237                    {
238                        InputStream inStream = null;
239                        try {
240                            inStream = new FileInputStream(mappingsFile);
241                            mappingsFromConfiguration.load(inStream);
242                        }
243                        catch (FileNotFoundException e) {
244                            throw new GUIModelConfigurationException(
245                                                                     "could not read mapping configuration file " +
246                                                                         mappingsFile, e);
247                        }
248                        catch (IOException e) {
249                            throw new GUIModelConfigurationException(
250                                                                     "could not read mapping configuration file " +
251                                                                         mappingsFile, e);
252                        }
253                        finally {
254                            if (inStream != null) {
255                                try {
256                                    inStream.close();
257                                }
258                                catch (IOException e) {
259                                    // ignore
260                                }
261                            }
262                        }
263                    }
264                }
265            }
266            else {
267                throw new GUIModelConfigurationException(
268                                                         "no GUI mappings file provided in folder " +
269                                                             mappingsFolder);
270            }
271
272            return mappingsFromConfiguration;
273        }
274    }
275}
Note: See TracBrowser for help on using the repository browser.