aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java')
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java455
1 files changed, 0 insertions, 455 deletions
diff --git a/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java b/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
deleted file mode 100644
index cee2ebe381..0000000000
--- a/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright 2000-2014 Vaadin Ltd.
- *
- * 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.vaadin.ui.declarative;
-
-import java.beans.BeanInfo;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.jsoup.nodes.Attribute;
-import org.jsoup.nodes.Attributes;
-import org.jsoup.nodes.Element;
-import org.jsoup.nodes.Node;
-
-import com.vaadin.data.util.converter.Converter;
-import com.vaadin.shared.util.SharedUtil;
-
-/**
- * Default attribute handler implementation used when parsing designs to
- * component trees. Handles all the component attributes that do not require
- * custom handling.
- *
- * @since 7.4
- * @author Vaadin Ltd
- */
-public class DesignAttributeHandler implements Serializable {
-
- private static Logger getLogger() {
- return Logger.getLogger(DesignAttributeHandler.class.getName());
- }
-
- private static Map<Class<?>, AttributeCacheEntry> cache = new ConcurrentHashMap<Class<?>, AttributeCacheEntry>();
-
- // translates string <-> object
- private static DesignFormatter FORMATTER = new DesignFormatter();
-
- /**
- * Returns the currently used formatter. All primitive types and all types
- * needed by Vaadin components are handled by that formatter.
- *
- * @return An instance of the formatter.
- */
- public static DesignFormatter getFormatter() {
- return FORMATTER;
- }
-
- /**
- * Clears the children and attributes of the given element
- *
- * @param design
- * the element to be cleared
- */
- public static void clearElement(Element design) {
- Attributes attr = design.attributes();
- for (Attribute a : attr.asList()) {
- attr.remove(a.getKey());
- }
- List<Node> children = new ArrayList<Node>();
- children.addAll(design.childNodes());
- for (Node node : children) {
- node.remove();
- }
- }
-
- /**
- * Assigns the specified design attribute to the given component.
- *
- * @param target
- * the target to which the attribute should be set
- * @param attribute
- * the name of the attribute to be set
- * @param value
- * the string value of the attribute
- * @return true on success
- */
- public static boolean assignValue(Object target, String attribute,
- String value) {
- if (target == null || attribute == null || value == null) {
- throw new IllegalArgumentException(
- "Parameters with null value not allowed");
- }
- boolean success = false;
- try {
- Method setter = findSetterForAttribute(target.getClass(), attribute);
- if (setter == null) {
- // if we don't have the setter, there is no point in continuing
- success = false;
- } else {
- // we have a value from design attributes, let's use that
- Object param = getFormatter().parse(value,
- setter.getParameterTypes()[0]);
- setter.invoke(target, param);
- success = true;
- }
- } catch (Exception e) {
- getLogger().log(
- Level.WARNING,
- "Failed to set value \"" + value + "\" to attribute "
- + attribute, e);
- }
- if (!success) {
- getLogger().info(
- "property " + attribute
- + " ignored by default attribute handler");
- }
- return success;
- }
-
- /**
- * Searches for supported setter and getter types from the specified class
- * and returns the list of corresponding design attributes
- *
- * @param clazz
- * the class scanned for setters
- * @return the list of supported design attributes
- */
- public static Collection<String> getSupportedAttributes(Class<?> clazz) {
- resolveSupportedAttributes(clazz);
- return cache.get(clazz).getAttributes();
- }
-
- /**
- * Resolves the supported attributes and corresponding getters and setters
- * for the class using introspection. After resolving, the information is
- * cached internally by this class
- *
- * @param clazz
- * the class to resolve the supported attributes for
- */
- private static void resolveSupportedAttributes(Class<?> clazz) {
- if (clazz == null) {
- throw new IllegalArgumentException("The clazz can not be null");
- }
- if (cache.containsKey(clazz)) {
- // NO-OP
- return;
- }
- BeanInfo beanInfo;
- try {
- beanInfo = Introspector.getBeanInfo(clazz);
- } catch (IntrospectionException e) {
- throw new RuntimeException(
- "Could not get supported attributes for class "
- + clazz.getName());
- }
- AttributeCacheEntry entry = new AttributeCacheEntry();
- for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
- Method getter = descriptor.getReadMethod();
- Method setter = descriptor.getWriteMethod();
- if (getter != null && setter != null
- && getFormatter().canConvert(descriptor.getPropertyType())) {
- String attribute = toAttributeName(descriptor.getName());
- entry.addAttribute(attribute, getter, setter);
- }
- }
- cache.put(clazz, entry);
- }
-
- /**
- * Writes the specified attribute to the design if it differs from the
- * default value got from the <code> defaultInstance <code>
- *
- * @param component
- * the component used to get the attribute value
- * @param attribute
- * the key for the attribute
- * @param attr
- * the attribute list where the attribute will be written
- * @param defaultInstance
- * the default instance for comparing default values
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static void writeAttribute(Object component, String attribute,
- Attributes attr, Object defaultInstance) {
- Method getter = findGetterForAttribute(component.getClass(), attribute);
- if (getter == null) {
- getLogger().warning(
- "Could not find getter for attribute " + attribute);
- } else {
- try {
- // compare the value with default value
- Object value = getter.invoke(component);
- Object defaultValue = getter.invoke(defaultInstance);
- writeAttribute(attribute, attr, value, defaultValue,
- (Class) getter.getReturnType());
- } catch (Exception e) {
- getLogger()
- .log(Level.SEVERE,
- "Failed to invoke getter for attribute "
- + attribute, e);
- }
- }
- }
-
- /**
- * Writes the given attribute value to a set of attributes if it differs
- * from the default attribute value.
- *
- * @param attribute
- * the attribute key
- * @param attributes
- * the set of attributes where the new attribute is written
- * @param value
- * the attribute value
- * @param defaultValue
- * the default attribute value
- * @param inputType
- * the type of the input value
- */
- public static <T> void writeAttribute(String attribute,
- Attributes attributes, T value, T defaultValue, Class<T> inputType) {
- if (!getFormatter().canConvert(inputType)) {
- throw new IllegalArgumentException("input type: "
- + inputType.getName() + " not supported");
- }
- if (!SharedUtil.equals(value, defaultValue)) {
- String attributeValue = toAttributeValue(inputType, value);
- if ("".equals(attributeValue)
- && (inputType == boolean.class || inputType == Boolean.class)) {
- attributes.put(attribute, true);
- } else {
- attributes.put(attribute, attributeValue);
- }
- }
- }
-
- /**
- * Reads the given attribute from a set of attributes. If attribute does not
- * exist return a given default value.
- *
- * @param attribute
- * the attribute key
- * @param attributes
- * the set of attributes to read from
- * @param defaultValue
- * the default value to return if attribute does not exist
- * @param outputType
- * the output type for the attribute
- * @return the attribute value or the default value if the attribute is not
- * found
- */
- public static <T> T readAttribute(String attribute, Attributes attributes,
- T defaultValue, Class<T> outputType) {
- T value = readAttribute(attribute, attributes, outputType);
- if (value != null) {
- return value;
- }
- return defaultValue;
- }
-
- /**
- * Reads the given attribute from a set of attributes.
- *
- * @param attribute
- * the attribute key
- * @param attributes
- * the set of attributes to read from
- * @param outputType
- * the output type for the attribute
- * @return the attribute value or null
- */
- public static <T> T readAttribute(String attribute, Attributes attributes,
- Class<T> outputType) {
- if (!getFormatter().canConvert(outputType)) {
- throw new IllegalArgumentException("output type: "
- + outputType.getName() + " not supported");
- }
- if (!attributes.hasKey(attribute)) {
- return null;
- } else {
- try {
- String value = attributes.get(attribute);
- return getFormatter().parse(value, outputType);
- } catch (Exception e) {
- throw new DesignException("Failed to read attribute "
- + attribute, e);
- }
- }
- }
-
- /**
- * Returns the design attribute name corresponding the given method name.
- * For example given a method name <code>setPrimaryStyleName</code> the
- * return value would be <code>primary-style-name</code>
- *
- * @param propertyName
- * the property name returned by {@link IntroSpector}
- * @return the design attribute name corresponding the given method name
- */
- private static String toAttributeName(String propertyName) {
- propertyName = removeSubsequentUppercase(propertyName);
- String[] words = propertyName.split("(?<!^)(?=[A-Z])");
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < words.length; i++) {
- if (builder.length() > 0) {
- builder.append("-");
- }
- builder.append(words[i].toLowerCase());
- }
- return builder.toString();
- }
-
- /**
- * Replaces subsequent UPPERCASE strings of length 2 or more followed either
- * by another uppercase letter or an end of string. This is to generalise
- * handling of method names like <tt>showISOWeekNumbers</tt>.
- *
- * @param param
- * Input string.
- * @return Input string with sequences of UPPERCASE turned into Normalcase.
- */
- private static String removeSubsequentUppercase(String param) {
- StringBuffer result = new StringBuffer();
- // match all two-or-more caps letters lead by a non-uppercase letter
- // followed by either a capital letter or string end
- Pattern pattern = Pattern.compile("(^|[^A-Z])([A-Z]{2,})([A-Z]|$)");
- Matcher matcher = pattern.matcher(param);
- while (matcher.find()) {
- String matched = matcher.group(2);
- // if this is a beginning of the string, the whole matched group is
- // written in lower case
- if (matcher.group(1).isEmpty()) {
- matcher.appendReplacement(result, matched.toLowerCase()
- + matcher.group(3));
- // otherwise the first character of the group stays uppercase,
- // while the others are lower case
- } else {
- matcher.appendReplacement(
- result,
- matcher.group(1) + matched.substring(0, 1)
- + matched.substring(1).toLowerCase()
- + matcher.group(3));
- }
- // in both cases the uppercase letter of the next word (or string's
- // end) is added
- // this implies there is at least one extra lowercase letter after
- // it to be caught by the next call to find()
- }
- matcher.appendTail(result);
- return result.toString();
- }
-
- /**
- * Serializes the given value to valid design attribute representation
- *
- * @param sourceType
- * the type of the value
- * @param value
- * the value to be serialized
- * @return the given value as design attribute representation
- */
- private static String toAttributeValue(Class<?> sourceType, Object value) {
- if (value == null) {
- // TODO: Handle corner case where sourceType is String and default
- // value is not null. How to represent null value in attributes?
- return "";
- }
- Converter<String, Object> converter = getFormatter().findConverterFor(
- sourceType);
- if (converter != null) {
- return converter.convertToPresentation(value, String.class, null);
- } else {
- return value.toString();
- }
- }
-
- /**
- * Returns a setter that can be used for assigning the given design
- * attribute to the class
- *
- * @param clazz
- * the class that is scanned for setters
- * @param attribute
- * the design attribute to find setter for
- * @return the setter method or null if not found
- */
- private static Method findSetterForAttribute(Class<?> clazz,
- String attribute) {
- resolveSupportedAttributes(clazz);
- return cache.get(clazz).getSetter(attribute);
- }
-
- /**
- * Returns a getter that can be used for reading the given design attribute
- * value from the class
- *
- * @param clazz
- * the class that is scanned for getters
- * @param attribute
- * the design attribute to find getter for
- * @return the getter method or null if not found
- */
- private static Method findGetterForAttribute(Class<?> clazz,
- String attribute) {
- resolveSupportedAttributes(clazz);
- return cache.get(clazz).getGetter(attribute);
- }
-
- /**
- * Cache object for caching supported attributes and their getters and
- * setters
- *
- * @author Vaadin Ltd
- */
- private static class AttributeCacheEntry implements Serializable {
- private Map<String, Method[]> accessMethods = new ConcurrentHashMap<String, Method[]>();
-
- private void addAttribute(String attribute, Method getter, Method setter) {
- Method[] methods = new Method[2];
- methods[0] = getter;
- methods[1] = setter;
- accessMethods.put(attribute, methods);
- }
-
- private Collection<String> getAttributes() {
- ArrayList<String> attributes = new ArrayList<String>();
- attributes.addAll(accessMethods.keySet());
- return attributes;
- }
-
- private Method getGetter(String attribute) {
- Method[] methods = accessMethods.get(attribute);
- return (methods != null && methods.length > 0) ? methods[0] : null;
- }
-
- private Method getSetter(String attribute) {
- Method[] methods = accessMethods.get(attribute);
- return (methods != null && methods.length > 1) ? methods[1] : null;
- }
- }
-}