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

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