com.jhickman.web.gwt.gxtuibinder.elementparsers.util.ElementParserUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.jhickman.web.gwt.gxtuibinder.elementparsers.util.ElementParserUtil.java

Source

/**
 * Copyright 2010 Justin Hickman
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * 
 */
package com.jhickman.web.gwt.gxtuibinder.elementparsers.util;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLAttribute;
import com.google.gwt.uibinder.rebind.XMLElement;
import com.jhickman.web.gwt.gxtuibinder.elementparsers.GxtClassnameConstants;

/**
 * @author hickman
 *
 */
public final class ElementParserUtil {

    /**
     * @param elem
     * @param fieldName
     * @param typeName
     * @param writer
     */
    public static void applyAttributes(XMLElement elem, String fieldName, String typeName, UiBinderWriter writer)
            throws UnableToCompleteException {
        JClassType type = writer.getOracle().findType(typeName);
        applyAttributes(elem, fieldName, type, writer);
    }

    /**
     * Consumes and applies attributes to given element
     * 
     * @param elem
     * @param fieldName
     * @param type
     * @param writer
     * @throws UnableToCompleteException
     */
    public static void applyAttributes(XMLElement elem, String fieldName, JClassType type, UiBinderWriter writer)
            throws UnableToCompleteException {

        // first get the special Margin attribute
        ElementParserUtil.consumeRegionAttributes(elem, fieldName, writer);

        Map<String, JType> setterMethods = fetchSetterMethods(type);
        int attributeCount = elem.getAttributeCount();

        // count backwards since we're consuming as we go
        for (int i = attributeCount - 1; i >= 0; i--) {
            // always get 0 because we're consuming them
            XMLAttribute attribute = elem.getAttribute(i);

            String setterMethod = "set" + initialCap(attribute.getName());

            if (setterMethods.containsKey(setterMethod)) {
                JType setterType = setterMethods.get(setterMethod);
                String value;

                if ("float".equals(setterType.getQualifiedSourceName())) {
                    value = attribute.consumeRawValue();
                    float floatValue = 0;
                    try {
                        floatValue = Float.parseFloat(value);
                    } catch (NumberFormatException e) {
                        writer.die(elem, "Cannot parse float value for attribute '%s'.  Found %s.",
                                attribute.getName(), value);
                    }
                    // assuming that we didn't die due to a NumberFormatException, we can use the value
                    value = floatValue + "f";
                } else if ("java.lang.Number".equals(setterType.getQualifiedSourceName())) {
                    value = elem.consumeRawAttribute(attribute.getName());
                } else {
                    value = elem.consumeAttribute(attribute.getName(), setterType);
                }
                writer.addStatement("%s.%s(%s);", fieldName, setterMethod, value);

            } else {
                try {
                    writer.findFieldType(elem);
                } catch (UnableToCompleteException e) {
                    writer.warn(elem, "Found attribute without associated setter method: %s.  IGNORING",
                            attribute.getName());
                }
            }
        }
    }

    /**
     * Grabs all write-property names with associated JType
     * 
     * @param type
     * @return map of write-property name to JType
     */
    public static Map<String, JType> fetchSetterMethods(JClassType type) {
        Map<String, JType> columnConfigSetterTypes = new HashMap<String, JType>();
        JMethod[] columnConfigTypeMethods = type.getMethods();
        for (JMethod jMethod : columnConfigTypeMethods) {
            if (jMethod.getName().startsWith("set") && jMethod.getParameters().length == 1) {
                columnConfigSetterTypes.put(jMethod.getName(), jMethod.getParameters()[0].getType());
            }
        }
        if (type.getSuperclass() != null) {
            columnConfigSetterTypes.putAll(fetchSetterMethods(type.getSuperclass()));
        }
        return columnConfigSetterTypes;
    }

    /**
     * Capitalizes the first character of provided String
     * @param text
     * @return same String, but first character capitalized
     */
    public static String initialCap(String text) {
        return text.substring(0, 1).toUpperCase() + text.substring(1);
    }

    public static void consumeRegionAttributes(XMLElement elem, String fieldName, UiBinderWriter writer)
            throws UnableToCompleteException {
        consumeMarginAttribute(elem, fieldName, writer);
        consumePaddingAttribute(elem, fieldName, writer);
    }

    /**
     * Consumes the margins attribute from provided element and constructs
     * a proper Margins object from the comma separated data.
     * @param elem - Element that contains the margins attribute
     * @param fieldName - variable name of the object to receive the new Margins object
     * @param writer
     * @return fieldName of Margins object
     * @throws UnableToCompleteException
     */
    public static String consumeMarginAttribute(XMLElement elem, String fieldName, UiBinderWriter writer)
            throws UnableToCompleteException {
        String marginsField = parseMarginsAttribute(elem, writer);
        if (marginsField != null) {
            writer.addStatement("%s.setMargins(%s);", fieldName, marginsField);

            return marginsField;
        }
        return null;
    }

    public static String consumePaddingAttribute(XMLElement elem, String fieldName, UiBinderWriter writer)
            throws UnableToCompleteException {
        String paddingField = parsePaddingAttribute(elem, writer);
        if (paddingField != null) {
            writer.addStatement("%s.setPadding(%s);", fieldName, paddingField);

            return paddingField;
        }
        return null;
    }

    public static String parseMarginsAttribute(XMLElement elem, UiBinderWriter writer)
            throws UnableToCompleteException {
        return parseAttributeWithArrayConstructor(elem, "margins", GxtClassnameConstants.MARGINS, writer);
    }

    public static String parsePaddingAttribute(XMLElement elem, UiBinderWriter writer)
            throws UnableToCompleteException {
        return parseAttributeWithArrayConstructor(elem, "padding", GxtClassnameConstants.PADDING, writer);
    }

    public static String parseAttributeWithArrayConstructor(XMLElement elem, String attributeName, String typeName,
            UiBinderWriter writer) throws UnableToCompleteException {
        String[] arrayData = elem.consumeRawArrayAttribute(attributeName);

        if (arrayData != null && arrayData.length > 0) {
            JClassType type = writer.getOracle().findType(typeName);
            String fieldName = writer.declareField(typeName, elem);
            writer.setFieldInitializerAsConstructor(fieldName, type, arrayData);
            return fieldName;
        }

        return null;
    }

    /**
     * Consumes the styleAttribute attribute from the provided elements.
     * 
     * Allowed value format is:
     * styleName:value;styleName:value
     * 
     * 
     * @param elem
     * @param fieldName
     * @param writer
     * @return
     * @throws UnableToCompleteException
     */
    public static void consumeStyleAttribute(XMLElement elem, String fieldName, UiBinderWriter writer)
            throws UnableToCompleteException {
        String styleAttributes = elem.consumeRawAttribute("styleAttribute");
        if (styleAttributes == null)
            return;

        String[] styles = styleAttributes.split("\\s*;\\s*");
        for (String style : styles) {
            String[] keyValue = style.split("\\s*:\\s*");
            if (keyValue.length != 2) {
                writer.die(elem,
                        "styleAttribute should be in format: styleName:styleValue;styleName:styleValue  but found %s",
                        styleAttributes);
            }

            writer.addStatement("%s.setStyleAttribute(\"%s\", \"%s\");", fieldName, keyValue[0], keyValue[1]);
        }

    }

    private ElementParserUtil() {
        throw new UnsupportedOperationException("Utility class cannot be instantiated");
    }

    /**
     * @param button
     * @param button2
     * @return
     */
    public static boolean isElementOfType(UiBinderWriter writer, XMLElement elem, String typeName)
            throws UnableToCompleteException {
        JClassType elemType = writer.findFieldType(elem);
        JClassType componentType;
        try {
            componentType = writer.getOracle().getType(typeName);
        } catch (NotFoundException e) {
            throw new UnableToCompleteException();
        }

        return componentType.isAssignableFrom(elemType);
    }
}