001/*
002 * Copyright (c) 2004-2007 by Michael Connor. All Rights Reserved.
003 *
004 * Redistribution and use in source and binary forms, with or without
005 * modification, are permitted provided that the following conditions are met:
006 *
007 *  o Redistributions of source code must retain the above copyright notice,
008 *    this list of conditions and the following disclaimer.
009 *
010 *  o Redistributions in binary form must reproduce the above copyright notice,
011 *    this list of conditions and the following disclaimer in the documentation
012 *    and/or other materials provided with the distribution.
013 *
014 *  o Neither the name of FormLayoutBuilder or Michael Connor nor the names of
015 *    its contributors may be used to endorse or promote products derived
016 *    from this software without specific prior written permission.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.mlc.swing.layout;
031
032import java.awt.Component;
033import java.beans.BeanInfo;
034import java.beans.IntrospectionException;
035import java.beans.Introspector;
036import java.beans.PropertyDescriptor;
037import java.lang.reflect.InvocationTargetException;
038import java.lang.reflect.Method;
039import java.util.ArrayList;
040import java.util.HashMap;
041import java.util.List;
042import java.util.Map;
043
044import javax.swing.JPanel;
045
046/**
047 * This is meant to be subclassed when you want to create a ComponentBuilder
048 * that has simplistic behavior.
049 *
050 * @author Michael Connor mlconnor@yahoo.com
051@version $Id$
052@since Ptolemy II 8.0
053 */
054public class DefaultComponentBuilder implements ComponentBuilder {
055    Class clazz;
056
057    BeanInfo beanInfo;
058
059    List<PropertyDescriptor> editableProperties = new ArrayList<PropertyDescriptor>();
060
061    Map<String, PropertyDescriptor> nameToDescriptor = new HashMap<String, PropertyDescriptor>();
062
063    List<BeanProperty> properties = new ArrayList<BeanProperty>();
064
065    /** Creates a new instance of DefaultComponentFactory */
066    public DefaultComponentBuilder(Class clazz) throws IntrospectionException {
067        this(clazz, null);
068    }
069
070    /** Creates a new instance of DefaultComponentFactory */
071    public DefaultComponentBuilder(Class clazz, String[] properties)
072            throws IntrospectionException {
073        this.clazz = clazz;
074
075        beanInfo = Introspector.getBeanInfo(clazz);
076        PropertyDescriptor[] propertyDescriptors = beanInfo
077                .getPropertyDescriptors();
078
079        if (properties != null) {
080            for (String propertyName : properties) {
081                PropertyDescriptor propertyDescriptor = null;
082
083                for (PropertyDescriptor thisDescriptor : propertyDescriptors) {
084                    if (thisDescriptor.getName().equals(propertyName)) {
085                        propertyDescriptor = thisDescriptor;
086                        break;
087                    }
088                }
089
090                if (propertyDescriptor == null) {
091                    throw new RuntimeException("Could not find property '"
092                            + propertyName + "' in class " + clazz.getName());
093                } else {
094                    this.properties
095                            .add(new BeanProperty(propertyDescriptor.getName(),
096                                    propertyDescriptor.getPropertyType()));
097                    nameToDescriptor.put(propertyDescriptor.getName(),
098                            propertyDescriptor);
099                }
100            }
101        }
102    }
103
104    @Override
105    public String getDeclaration(String name,
106            Map<String, Object> beanProperties) {
107        StringBuffer buffer = new StringBuffer();
108        buffer.append(clazz.getName() + " " + name + " = new " + clazz.getName()
109                + "(");
110
111        if (beanProperties.containsKey("text")) {
112            buffer.append("\"" + (String) beanProperties.get("text") + "\"");
113        }
114
115        buffer.append(");\n");
116        return buffer.toString();
117    }
118
119    @Override
120    public ComponentDef getComponentDef(String name,
121            Map<String, Object> beanProperties) {
122        // imports
123        // declarations
124        // add
125
126        String imp = "import " + clazz.getName() + ";";
127        // does not work with JDK 1.4
128        //          String decl = clazz.getSimpleName() + " ${name}= new " + clazz.getSimpleName() + "(";
129        String decl = clazz.getName() + " ${name}= new " + clazz.getName()
130                + "(";
131
132        if (beanProperties.containsKey("text")) {
133            decl += "\"" + (String) beanProperties.get("text") + "\"";
134        }
135        decl += ");";
136
137        //          String decl = getDeclaration(name, beanProperties);
138        String add = "${container}.add(${name}, \"${name}\");";
139
140        ComponentDef cd = new ComponentDef(name, imp, decl, add);
141        return cd;
142    }
143
144    @Override
145    public java.awt.Component getInstance(
146            java.util.Map<String, Object> objectProperties)
147            throws InstantiationException, IllegalAccessException,
148            InvocationTargetException {
149        Object instance = clazz.newInstance();
150
151        for (Object element : objectProperties.keySet()) {
152            String key = (String) element;
153            PropertyDescriptor propertyDescriptor = nameToDescriptor.get(key);
154            Object value = objectProperties.get(key);
155            Method writeMethod = propertyDescriptor.getWriteMethod();
156            writeMethod.invoke(instance, new Object[] { value });
157        }
158
159        return (Component) instance;
160    }
161
162    @Override
163    public boolean isComponentALayoutContainer() {
164        return clazz.equals(JPanel.class);
165    }
166
167    @Override
168    public String toString() {
169        return clazz.getName();
170    }
171
172    @Override
173    public List<BeanProperty> getProperties() {
174        return properties;
175    }
176
177}