Package org.vaadin.teemu.clara.factory

Source Code of org.vaadin.teemu.clara.factory.DefaultComponentManager

package org.vaadin.teemu.clara.factory;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;

public class DefaultComponentManager implements ComponentManager {

    private List<AttributeHandler> attributeHandlers = new ArrayList<AttributeHandler>();

    private Logger getLogger() {
        return Logger.getLogger(DefaultComponentManager.class.getName());
    }

    public DefaultComponentManager() {
        // Setup the default AttributeHandlers.
        addAttributeHandler(new PrimitiveAttributeHandler());
        addAttributeHandler(new VaadinAttributeHandler());
    }

    public void addAttributeHandler(AttributeHandler handler) {
        attributeHandlers.add(handler);
    }

    public void removeAttributeHandler(AttributeHandler handler) {
        attributeHandlers.remove(handler);
    }

    public Component createComponent(String namespace, String name,
            Map<String, String> attributes)
            throws ComponentInstantiationException {
        try {
            Class<? extends Component> componentClass = resolveComponentClass(
                    namespace, name);
            Component newComponent = componentClass.newInstance();
            handleAttributes(newComponent, attributes);
            return newComponent;
        } catch (Exception e) {
            throw createException(e, namespace, name);
        }
    }

    protected ComponentInstantiationException createException(Exception e,
            String namespace, String name) {
        String message = String
                .format("Couldn't instantiate a component for namespace %s and name %s.",
                        namespace, name);
        if (e != null) {
            return new ComponentInstantiationException(message, e);
        } else {
            return new ComponentInstantiationException(message);
        }
    }

    @SuppressWarnings("unchecked")
    protected Class<? extends Component> resolveComponentClass(
            String namespace, String name) throws ClassNotFoundException {
        String qualifiedClassName = namespace + "." + name;
        Class<?> componentClass = null;
        componentClass = Class.forName(qualifiedClassName);

        // Check that we're dealing with a Component.
        if (isComponent(componentClass)) {
            return (Class<? extends Component>) componentClass;
        } else {
            throw new IllegalArgumentException(String.format(
                    "Resolved class %s is not a %s.", componentClass.getName(),
                    Component.class.getName()));
        }
    }

    /**
     * Returns {@code true} if the given {@link Class} implements the
     * {@link Component} interface of Vaadin Framework otherwise {@code false}.
     *
     * @param componentClass
     *            {@link Class} to check against {@link Component} interface.
     * @return {@code true} if the given {@link Class} is a {@link Component},
     *         {@code false} otherwise.
     */
    protected boolean isComponent(Class<?> componentClass) {
        if (componentClass != null) {
            return Component.class.isAssignableFrom(componentClass);
        } else {
            return false;
        }
    }

    protected void handleAttributes(Component component,
            Map<String, String> attributes) {
        getLogger().fine(attributes.toString());

        try {
            // Get the Component properties.
            BeanInfo beanInfo = Introspector.getBeanInfo(component.getClass());
            PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();

            for (Map.Entry<String, String> attribute : attributes.entrySet()) {
                for (PropertyDescriptor property : properties) {
                    if (property.getName().equals(attribute.getKey())) {
                        AttributeHandler handler = getHandlerFor(property
                                .getPropertyType());
                        if (handler != null) {
                            Method setter = property.getWriteMethod();
                            if (setter.getParameterTypes().length == 1) {
                                String attributeValue = attribute.getValue();
                                if (attributeValue == null
                                        || attributeValue.length() == 0) {
                                    // No need for conversion.
                                    setter.invoke(component, attributeValue);
                                } else {
                                    // Ask the AttributeHandler to convert the
                                    // value.
                                    setter.invoke(
                                            component,
                                            handler.getValueAs(
                                                    attributeValue,
                                                    setter.getParameterTypes()[0]));
                                }
                            }
                        }
                    }
                }
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }
    }

    protected AttributeHandler getHandlerFor(Class<?> type) {
        for (AttributeHandler handler : attributeHandlers) {
            if (handler.isSupported(type)) {
                return handler;
            }
        }
        return null;
    }

    public void applyLayoutAttributes(ComponentContainer container,
            Component component, Map<String, String> attributes) {
        if (!component.getParent().equals(container)) {
            throw new IllegalStateException(
                    "The given container must be the parent of given component.");
        }
        try {
            for (Map.Entry<String, String> attribute : attributes.entrySet()) {
                if (attribute.getKey().startsWith("layout_")) {
                    String layoutProperty = attribute.getKey().substring(
                            "layout_".length());
                    Method layoutMethod = findLayoutMethod(
                            container.getClass(), layoutProperty);
                    if (layoutMethod != null) {
                        AttributeHandler handler = getHandlerFor(layoutMethod
                                .getParameterTypes()[1]);
                        if (handler != null)
                            layoutMethod
                                    .invoke(container, component,
                                            handler.getValueAs(attribute
                                                    .getValue(), layoutMethod
                                                    .getParameterTypes()[1]));
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    protected static Method findLayoutMethod(
            Class<? extends ComponentContainer> layoutClass, String propertyName) {
        Method[] layoutMethods = layoutClass.getMethods();
        Method candiateMethod = null;
        String methodToLookFor = "set"
                + propertyName.substring(0, 1).toUpperCase()
                + propertyName.substring(1);

        for (Method layoutMethod : layoutMethods) {
            Class<?>[] params = layoutMethod.getParameterTypes();
            if (params.length == 2
                    && params[0].isAssignableFrom(Component.class)
                    && layoutMethod.getName().equals(methodToLookFor)) {
                if (layoutMethod.getAnnotation(Deprecated.class) == null) {
                    // Prefer non-deprecated methods.
                    return layoutMethod;
                } else {
                    // Use deprecated methods only if no other match found.
                    candiateMethod = layoutMethod;
                }
            }
        }
        return candiateMethod;
    }

}
TOP

Related Classes of org.vaadin.teemu.clara.factory.DefaultComponentManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.