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

Last change on this file since 1796 was 1796, checked in by pharms, 10 years ago
File size: 11.8 KB
RevLine 
[927]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.
[831]14
[922]15package de.ugoe.cs.autoquest.eventcore.guimodel;
[545]16
[585]17import java.io.File;
18import java.io.FileInputStream;
19import java.io.FileNotFoundException;
[545]20import java.io.IOException;
21import java.io.InputStream;
[604]22import java.lang.reflect.Constructor;
[545]23import java.lang.reflect.InvocationTargetException;
24import java.util.Properties;
25import java.util.logging.Level;
26
[724]27import de.ugoe.cs.util.console.Console;
28
[545]29/**
[831]30 * <p>
31 * Creates {@link IGUIElement}s from a given specification. Implemented as singleton.
32 * </p>
[545]33 *
[831]34 * @version 1.0
35 * @author Patrick Harms
[545]36 */
[592]37public class GUIElementFactory implements IGUIElementFactory {
[831]38
39    /**
40     * <p>
41     * Instance of the class (singleton)
42     * </p>
43     */
[592]44    private static GUIElementFactory instance = new GUIElementFactory();
[585]45
46    /**
[831]47     * <p>
48     * Constructor. Creates a new GUIElementFactory. Private to preserve singleton property.
49     * </p>
[585]50     */
[831]51    private GUIElementFactory() {}
[585]52
53    /**
[831]54     * <p>
55     * Returns the instance of this class.
56     * </p>
[585]57     *
[831]58     * @return the instance
[585]59     */
[592]60    public static synchronized GUIElementFactory getInstance() {
[585]61        return instance;
62    }
63
[545]64    /**
[831]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>
[545]69     */
[831]70    private Properties mappingsFromConfiguration;
[545]71
[831]72   
73    /*
74     * (non-Javadoc)
[545]75     *
[831]76     * @see
[922]77     * de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementFactory#instantiateGUIElement(de.ugoe.cs.autoquest
78     * .eventcore.guimodel.IGUIElementSpec, de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement)
[545]79     */
[585]80    @Override
[603]81    public IGUIElement instantiateGUIElement(IGUIElementSpec specification, IGUIElement parent)
[592]82        throws GUIModelConfigurationException
83    {
[545]84        Properties mappings = getMappingsFromConfiguration();
[585]85        IGUIElement guiElement = null;
[990]86        String[] typeHierarchy = specification.getTypeHierarchy();
[984]87        int i = 0;
88        String className = null;
[1067]89       
90        while ((className == null) && (i < typeHierarchy.length)) {
91            className = mappings.getProperty(typeHierarchy[i]);
92            i++;
[984]93        }
[1067]94       
[545]95        if (className != null) {
96            try {
97                Class<?> clazz = this.getClass().getClassLoader().loadClass(className);
98
99                if (!IGUIElement.class.isAssignableFrom(clazz)) {
[724]100                    Console.traceln(Level.WARNING, "configured GUI element representing class " +
[831]101                        className + " is no valid GUIElement derivate.");
[545]102
103                    return null;
104                }
105
[604]106                Constructor<?> constructor = null;
107                Class<?> parentClass = (parent == null) ? null : parent.getClass();
[831]108
[604]109                // search for a constructor, that perfectly matches the types
110                for (Constructor<?> candidate : clazz.getConstructors()) {
[831]111                    if ((parentClass != null) && (candidate.getParameterTypes().length == 2) &&
[604]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                }
[831]127
[604]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                    }
[831]139
[604]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                }
[545]152
153            }
154            catch (ClassNotFoundException e) {
[724]155                Console.traceln(Level.WARNING, "configured GUI element representing class " +
156                                className + " can not be loaded.");
[545]157                throw new GUIModelConfigurationException
158                    ("configured GUI element representing class " + className +
159                     " can not be loaded.", e);
160            }
161            catch (SecurityException e) {
[724]162                Console.traceln(Level.WARNING, "configured GUI element representing class " +
163                                className + " can not be instantiated due to security reasons.");
[545]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) {
[724]169                Console.traceln(Level.WARNING, "configured GUI element representing class " +
170                                className + " does not provide an appropriate constructor.");
[545]171                throw new GUIModelConfigurationException
172                    ("configured GUI element representing class " + className +
[724]173                     " does not provide an appropriate constructor.", e);
[545]174            }
175            catch (IllegalArgumentException e) {
[724]176                Console.traceln(Level.WARNING, "configured GUI element representing class " +
177                                className + " does not provide an appropriate constructor " +
178                                "accepting the provided parameters.");
[545]179                throw new GUIModelConfigurationException
180                    ("configured GUI element representing class " + className + " does not " +
[724]181                     "provide an appropriate constructor accepting the provided parameters.", e);
[545]182            }
183            catch (InstantiationException e) {
[724]184                Console.traceln(Level.WARNING, "configured GUI element representing class " +
185                                className + " can not be instantiated.");
[545]186                throw new GUIModelConfigurationException
187                    ("configured GUI element representing class " + className +
188                     " can not be instantiated.", e);
189            }
190            catch (IllegalAccessException e) {
[724]191                Console.traceln(Level.WARNING, "configured GUI element representing class " +
192                                className + " can not be instantiated.");
[545]193                throw new GUIModelConfigurationException
194                    ("configured GUI element representing class " + className +
195                     " can not be instantiated.", e);
196            }
197            catch (InvocationTargetException e) {
[724]198                Console.traceln(Level.WARNING, "configured GUI element representing class " +
199                                className + " can not be instantiated.");
[545]200                throw new GUIModelConfigurationException
201                    ("configured GUI element representing class " + className +
202                     " can not be instantiated.", e);
203            }
204        }
[610]205       
206        if (guiElement == null ) {
[724]207            Console.traceln(Level.WARNING, "no class representing GUI elements of type " +
[739]208                            specification.getType() + " found. Please extend GUI element " +
[724]209                            "mapping files.");
[610]210            throw new GUIModelConfigurationException
211                ("no class representing GUI elements of type " + specification.getType() +
[739]212                 " found. Please extend GUI element mapping files");
[585]213        }
[545]214
[585]215        return guiElement;
[545]216    }
217
218    /**
[831]219     * <p>
220     * Loads the mappings for GUI elements. All files that start with &quot;guimapping&quot;, end
[1796]221     * with &quot;.txt&quot;, and are located in the folder &quot;data/guimappings&quot; (relative
[831]222     * to the working directory) are loaded.
223     * </p>
[545]224     *
[831]225     * @return loaded GUI mappings
[545]226     */
[603]227    private synchronized Properties getMappingsFromConfiguration()
228        throws GUIModelConfigurationException
229    {
[550]230        if (mappingsFromConfiguration != null) {
231            return mappingsFromConfiguration;
[545]232        }
233        else {
[550]234            mappingsFromConfiguration = new Properties();
[831]235
[585]236            File mappingsFolder = new File("data/guimappings");
[603]237            File[] children = mappingsFolder.listFiles();
[831]238
[603]239            if (children != null) {
240                for (File mappingsFile : children) {
241                    if (!mappingsFile.isDirectory() &&
242                        mappingsFile.getName().startsWith("guimapping") &&
243                        mappingsFile.getName().endsWith(".txt"))
244                    {
[744]245                        InputStream inStream = null;
[603]246                        try {
247                            inStream = new FileInputStream(mappingsFile);
248                            mappingsFromConfiguration.load(inStream);
249                        }
250                        catch (FileNotFoundException e) {
[831]251                            throw new GUIModelConfigurationException(
252                                                                     "could not read mapping configuration file " +
253                                                                         mappingsFile, e);
[603]254                        }
255                        catch (IOException e) {
[831]256                            throw new GUIModelConfigurationException(
257                                                                     "could not read mapping configuration file " +
258                                                                         mappingsFile, e);
[603]259                        }
[744]260                        finally {
261                            if (inStream != null) {
262                                try {
263                                    inStream.close();
264                                }
265                                catch (IOException e) {
266                                    // ignore
267                                }
268                            }
269                        }
[585]270                    }
[545]271                }
272            }
[603]273            else {
[831]274                throw new GUIModelConfigurationException(
275                                                         "no GUI mappings file provided in folder " +
276                                                             mappingsFolder);
[603]277            }
[545]278
[550]279            return mappingsFromConfiguration;
[545]280        }
281    }
282}
Note: See TracBrowser for help on using the repository browser.