Package com.googlecode.gwt.test.uibinder

Source Code of com.googlecode.gwt.test.uibinder.UiBinderInstanciator

package com.googlecode.gwt.test.uibinder;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.UIObject;
import com.googlecode.gwt.test.exceptions.GwtTestUiBinderException;
import com.googlecode.gwt.test.internal.GwtParanamer;
import com.googlecode.gwt.test.utils.GwtReflectionUtils;

/**
* Class responsible for Object instantiations. It handles provided {@link UiField},
* {@link UiFactory} fields and {@link UiConstructor} fields.
*
* @author Gael Lazzari
*
*/
@SuppressWarnings("unchecked")
class UiBinderInstanciator {
   public final static Map<Class<?>, Class<?>> primitiveMap = new HashMap<Class<?>, Class<?>>();
   static {
      primitiveMap.put(boolean.class, Boolean.class);
      primitiveMap.put(byte.class, Byte.class);
      primitiveMap.put(short.class, Short.class);
      primitiveMap.put(char.class, Character.class);
      primitiveMap.put(int.class, Integer.class);
      primitiveMap.put(long.class, Long.class);
      primitiveMap.put(float.class, Float.class);
      primitiveMap.put(double.class, Double.class);
   }

   static <U> U getInstance(Class<U> clazz, Map<String, Object> attributes, Object owner) {

      String uiFieldValue = (String) attributes.get("ui:field");
      U instance = getProvidedUiField(clazz, owner, uiFieldValue);

      if (instance == null) {
         instance = getObjectFromUiFactory(clazz, owner);
      }

      if (instance == null) {
         instance = getObjectFromUiConstructor(clazz, attributes);
      }

      if (instance == null && !UIObject.class.isAssignableFrom(clazz)
               && !IsWidget.class.isAssignableFrom(clazz)) {
         instance = GWT.<U> create(clazz);
      }

      return instance;
   }

   private static boolean allArgsAreDeclaredInUiFile(String[] argNames,
            Map<String, Object> attributes) {
      for (String argName : argNames) {
         if (!attributes.containsKey(argName)) {
            return false;
         }
      }
      return true;
   }

   private static Object convertArgs(Class<?> paramType, Object object)
            throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
      if (paramType == String.class) {
         return object;
      }

      if (paramType.isPrimitive()) {
         paramType = primitiveMap.get(paramType);
      }

      Method valueOfMethod = null;
      try {
         valueOfMethod = paramType.getDeclaredMethod("valueOf", String.class);
         if (valueOfMethod.getReturnType() != paramType) {
            // This is not valueOf() I want.
            return object;
         }
      } catch (Exception e) {
         // No valueOf() method
         return object;
      }

      return valueOfMethod.invoke(null, object);
   }

   private static List<Object> extractArgs(String[] argNames, Map<String, Object> attributes) {

      List<Object> args = new ArrayList<Object>();
      for (String argName : argNames) {
         Object arg = attributes.get(argName);
         if (arg == null) {
            // the widget .ui.xml declaration does not match with this
            // @UiConstructor
            return null;
         }

         args.add(arg);
      }

      return args;
   }

   private static <U> U getObjectFromUiConstructor(Class<U> clazz, Map<String, Object> attributes) {

      for (Constructor<?> cons : clazz.getDeclaredConstructors()) {
         if (cons.getAnnotation(UiConstructor.class) == null) {
            continue;
         }

         Constructor<U> uiConstructor = (Constructor<U>) cons;

         String[] argNames = GwtParanamer.get().lookupParameterNames(uiConstructor);

         if (allArgsAreDeclaredInUiFile(argNames, attributes)) {
            List<Object> constructorArgs = extractArgs(argNames, attributes);

            if (constructorArgs != null) {
               Class<?>[] paramTypes = uiConstructor.getParameterTypes();
               for (int i = 0; i < argNames.length; i++) {
                  String argName = argNames[i];
                  try {
                     Object convertedArg = convertArgs(paramTypes[i], constructorArgs.get(i));
                     constructorArgs.set(i, convertedArg);

                     // remove the attribute from the map to populate the widget with since it's
                     // used in the constructor
                     attributes.remove(argName);
                  } catch (Exception e) {
                     throw new GwtTestUiBinderException("Error while converting argument "
                              + argNames[i] + " to " + paramTypes[i], e);
                  }
               }
            }

            return instanciate(uiConstructor, constructorArgs);
         }

      }

      return null;
   }

   private static <U> U getObjectFromUiFactory(Class<U> clazz, Object owner) {
      Map<Method, UiFactory> map = GwtReflectionUtils.getAnnotatedMethod(owner.getClass(),
               UiFactory.class);

      List<Method> compatibleFactories = new ArrayList<Method>();
      for (Method factoryMethod : map.keySet()) {
         if (clazz.isAssignableFrom(factoryMethod.getReturnType())) {
            compatibleFactories.add(factoryMethod);
         }
      }

      switch (compatibleFactories.size()) {
         case 0:
            return null;
         case 1:
            return (U) GwtReflectionUtils.callPrivateMethod(owner, compatibleFactories.get(0));
         default:
            throw new GwtTestUiBinderException("Duplicate factory in class '"
                     + owner.getClass().getName() + " for type '" + clazz.getName() + "'");
      }
   }

   private static <U> U getProvidedUiField(Class<U> clazz, Object owner, String uiFieldValue) {
      Map<Field, UiField> map = GwtReflectionUtils.getAnnotatedField(owner.getClass(),
               UiField.class);

      for (Map.Entry<Field, UiField> entry : map.entrySet()) {
         if (!entry.getValue().provided()) {
            // not a provided uiField
            continue;
         } else if (entry.getKey().getName().equals(uiFieldValue)
                  || (uiFieldValue == null && entry.getKey().getType() == clazz)) {
            Object providedObject = GwtReflectionUtils.getPrivateFieldValue(owner, entry.getKey());
            if (providedObject == null) {
               throw new GwtTestUiBinderException(
                        "The UiField(provided=true) '"
                                 + entry.getKey().getDeclaringClass().getSimpleName()
                                 + "."
                                 + entry.getKey().getName()
                                 + "' has not been initialized before calling 'UiBinder.createAndBind(..)' method");
            }

            return (U) providedObject;
         }
      }

      return null;
   }

   private static <U> U instanciate(Constructor<U> cons, List<Object> args) {
      try {
         return GwtReflectionUtils.instantiateClass(cons, args.toArray());
      } catch (Exception e) {
         StringBuilder sb = new StringBuilder();
         sb.append("Error while calling @UiConstructor 'new ").append(
                  cons.getDeclaringClass().getSimpleName()).append("(");

         for (Object arg : args) {
            sb.append("\"" + arg.toString() + "\"");
            sb.append(", ");
         }

         if (args.size() > 0) {
            sb.delete(sb.length() - 2, sb.length() - 1);
         }

         sb.append(");'");

         throw new GwtTestUiBinderException(sb.toString(), e);
      }
   }

}
TOP

Related Classes of com.googlecode.gwt.test.uibinder.UiBinderInstanciator

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.