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

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