Package com.google.gwt.autobean.rebind.model

Source Code of com.google.gwt.autobean.rebind.model.AutoBeanMethod$Builder

/*
* Copyright 2010 Google Inc.
*
* 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.google.gwt.autobean.rebind.model;

import com.google.gwt.autobean.shared.AutoBean.PropertyName;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumConstant;
import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.editor.rebind.model.ModelUtils;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
* Describes a method implemented by an AutoBean.
*/
public class AutoBeanMethod {
  /**
   * Describes the type of method that was invoked.
   */
  public enum Action {
    GET {
      @Override
      String inferName(JMethod method) {
        if (JPrimitiveType.BOOLEAN.equals(method.getReturnType())) {
          String name = method.getName();
          if (name.startsWith("is") && name.length() > 2) {
            name = Character.toLowerCase(name.charAt(2))
                + (name.length() >= 4 ? name.substring(3) : "");
            return name;
          }
        }
        return super.inferName(method);
      }

      @Override
      boolean matches(JMethod method) {
        if (method.getParameters().length > 0) {
          return false;
        }
        String name = method.getName();

        // Allow boolean isFoo() or boolean hasFoo();
        if (JPrimitiveType.BOOLEAN.equals(method.getReturnType())) {
          if (name.startsWith("is") && name.length() > 2) {
            return true;
          }
          if (name.startsWith("has") && name.length() > 3) {
            return true;
          }
        }
        if (name.startsWith("get") && name.length() > 3) {
          return true;
        }
        return false;
      }
    },
    SET {
      @Override
      boolean matches(JMethod method) {
        if (!JPrimitiveType.VOID.equals(method.getReturnType())) {
          return false;
        }
        if (method.getParameters().length != 1) {
          return false;
        }
        String name = method.getName();
        if (name.startsWith("set") && name.length() > 3) {
          return true;
        }
        return false;
      }
    },
    CALL {
      /**
       * Matches all leftover methods.
       */
      @Override
      boolean matches(JMethod method) {
        return true;
      }
    };

    /**
     * Determine which Action a method maps to.
     */
    public static Action which(JMethod method) {
      for (Action action : Action.values()) {
        if (action.matches(method)) {
          return action;
        }
      }
      throw new RuntimeException("CALL should have matched");
    }

    /**
     * Infer the name of a property from the method.
     */
    String inferName(JMethod method) {
      String name = method.getName();
      name = Character.toLowerCase(name.charAt(3))
          + (name.length() >= 5 ? name.substring(4) : "");
      return name;
    }

    /**
     * Returns {@code true} if the Action matches the method.
     */
    abstract boolean matches(JMethod method);
  }

  /**
   * Creates AutoBeanMethods.
   */
  public static class Builder {
    private AutoBeanMethod toReturn = new AutoBeanMethod();

    public AutoBeanMethod build() {
      if (toReturn.action.equals(Action.GET)
          || toReturn.action.equals(Action.SET)) {
        PropertyName annotation = toReturn.method.getAnnotation(PropertyName.class);
        if (annotation != null) {
          toReturn.propertyName = annotation.value();
        } else {
          toReturn.propertyName = toReturn.action.inferName(toReturn.method);
        }
      }

      try {
        return toReturn;
      } finally {
        toReturn = null;
      }
    }

    public void setAction(Action action) {
      toReturn.action = action;
    }

    public void setMethod(JMethod method) {
      toReturn.method = method;
      TypeOracle oracle = method.getEnclosingType().getOracle();

      toReturn.isValueType = ModelUtils.isValueType(oracle,
          method.getReturnType());

      if (!toReturn.isValueType) {
        // See if it's a collection or a map
        JClassType returnClass = method.getReturnType().isClassOrInterface();
        JClassType collectionInterface = oracle.findType(Collection.class.getCanonicalName());
        JClassType mapInterface = oracle.findType(Map.class.getCanonicalName());
        if (collectionInterface.isAssignableFrom(returnClass)) {
          JClassType[] parameterizations = ModelUtils.findParameterizationOf(
              collectionInterface, returnClass);
          toReturn.elementType = parameterizations[0];
        } else if (mapInterface.isAssignableFrom(returnClass)) {
          JClassType[] parameterizations = ModelUtils.findParameterizationOf(
              mapInterface, returnClass);
          toReturn.keyType = parameterizations[0];
          toReturn.valueType = parameterizations[1];
        }
      }

      JEnumType enumType = method.getReturnType().isEnum();
      if (enumType != null) {
        Map<JEnumConstant, String> map = new LinkedHashMap<JEnumConstant, String>();
        for (JEnumConstant e : enumType.getEnumConstants()) {
          String name;
          PropertyName annotation = e.getAnnotation(PropertyName.class);
          if (annotation == null) {
            name = e.getName();
          } else {
            name = annotation.value();
          }
          map.put(e, name);
        }
        toReturn.enumMap = map;
      }
    }

    public void setNoWrap(boolean noWrap) {
      toReturn.isNoWrap = noWrap;
    }

    public void setStaticImp(JMethod staticImpl) {
      toReturn.staticImpl = staticImpl;
    }
  }

  private Action action;
  private JClassType elementType;
  private Map<JEnumConstant, String> enumMap;
  private JClassType keyType;
  private JMethod method;
  private boolean isNoWrap;
  private boolean isValueType;
  private String propertyName;
  private JMethod staticImpl;
  private JClassType valueType;

  private AutoBeanMethod() {
  }

  public Action getAction() {
    return action;
  }

  public JClassType getElementType() {
    return elementType;
  }

  public Map<JEnumConstant, String> getEnumMap() {
    return enumMap;
  }

  public JClassType getKeyType() {
    return keyType;
  }

  public JMethod getMethod() {
    return method;
  }

  public String getPropertyName() {
    return propertyName;
  }

  /**
   * If the AutoBean method was declared in a type containing a
   * {@link com.google.gwt.editor.client.AutoBean.Category Category} annotation,
   * this method will return the static implementation.
   */
  public JMethod getStaticImpl() {
    return staticImpl;
  }

  public JClassType getValueType() {
    return valueType;
  }

  public boolean isCollection() {
    return elementType != null;
  }

  public boolean isEnum() {
    return enumMap != null;
  }

  public boolean isMap() {
    return keyType != null;
  }

  public boolean isNoWrap() {
    return isNoWrap;
  }

  public boolean isValueType() {
    return isValueType;
  }

  /**
   * For debugging use only.
   */
  @Override
  public String toString() {
    return method.toString();
  }
}
TOP

Related Classes of com.google.gwt.autobean.rebind.model.AutoBeanMethod$Builder

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.