blob: 43763df670b8e84d4f557f50d6b2e109a60e36d8 [file] [log] [blame]
/*
* 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.web.bindery.autobean.gwt.rebind.model;
import com.google.web.bindery.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.JType;
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 {
/**
* Creates AutoBeanMethods.
*/
public static class Builder {
private AutoBeanMethod toReturn = new AutoBeanMethod();
public AutoBeanMethod build() {
if (toReturn.action.equals(JBeanMethod.GET)
|| toReturn.action.equals(JBeanMethod.SET)
|| toReturn.action.equals(JBeanMethod.SET_BUILDER)) {
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(JBeanMethod action) {
toReturn.action = action;
}
public void setMethod(JMethod method) {
toReturn.method = method;
TypeOracle oracle = method.getEnclosingType().getOracle();
JType returnType = method.getReturnType();
toReturn.isValueType = ModelUtils.isValueType(oracle, returnType);
if (!toReturn.isValueType) {
// See if it's a collection or a map
JClassType returnClass = returnType.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];
maybeProcessEnumType(toReturn.elementType);
} else if (mapInterface.isAssignableFrom(returnClass)) {
JClassType[] parameterizations = ModelUtils.findParameterizationOf(
mapInterface, returnClass);
toReturn.keyType = parameterizations[0];
toReturn.valueType = parameterizations[1];
maybeProcessEnumType(toReturn.keyType);
maybeProcessEnumType(toReturn.valueType);
}
} else {
maybeProcessEnumType(returnType);
}
}
public void setNoWrap(boolean noWrap) {
toReturn.isNoWrap = noWrap;
}
public void setStaticImp(JMethod staticImpl) {
toReturn.staticImpl = staticImpl;
}
/**
* Call {@link #processEnumType(JEnumType)} if {@code type} is a
* {@link JEnumType}.
*/
private void maybeProcessEnumType(JType type) {
assert type != null : "type == null";
JEnumType enumType = type.isEnum();
if (enumType != null) {
processEnumType(enumType);
}
}
/**
* Adds a JEnumType to the AutoBeanMethod's enumMap so that the
* AutoBeanFactoryGenerator can embed extra metadata about the enum values.
*/
private void processEnumType(JEnumType enumType) {
Map<JEnumConstant, String> map = toReturn.enumMap;
if (map == null) {
map = toReturn.enumMap = new LinkedHashMap<JEnumConstant, String>();
}
for (JEnumConstant e : enumType.getEnumConstants()) {
String name = getEnumName(e);
map.put(e, name);
}
}
}
static String getEnumName(JEnumConstant e) {
String name;
PropertyName annotation = e.getAnnotation(PropertyName.class);
if (annotation == null) {
name = e.getName();
} else {
name = annotation.value();
}
return name;
}
private JBeanMethod 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 JBeanMethod 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 hasEnumMap() {
return enumMap != null;
}
public boolean isCollection() {
return elementType != 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();
}
}