org.androidannotations.helper.BundleHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of androidannotations Show documentation
Show all versions of androidannotations Show documentation
The Annotation Processor jar that generates code
/**
* Copyright (C) 2010-2016 eBusiness Information, Excilys Group
* Copyright (C) 2016-2020 the AndroidAnnotations project
*
* 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 org.androidannotations.helper;
import static org.androidannotations.helper.CanonicalNameConstants.BUNDLE;
import static org.androidannotations.helper.CanonicalNameConstants.CHAR_SEQUENCE;
import static org.androidannotations.helper.CanonicalNameConstants.STRING;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import org.androidannotations.AndroidAnnotationsEnvironment;
import com.helger.jcodemodel.AbstractJClass;
import com.helger.jcodemodel.IJExpression;
import com.helger.jcodemodel.IJStatement;
import com.helger.jcodemodel.JExpr;
import com.helger.jcodemodel.JMethod;
public class BundleHelper {
public static final Map METHOD_SUFFIX_BY_TYPE_NAME = new HashMap<>();
static {
METHOD_SUFFIX_BY_TYPE_NAME.put(BUNDLE, "Bundle");
METHOD_SUFFIX_BY_TYPE_NAME.put("boolean", "Boolean");
METHOD_SUFFIX_BY_TYPE_NAME.put("boolean[]", "BooleanArray");
METHOD_SUFFIX_BY_TYPE_NAME.put("byte", "Byte");
METHOD_SUFFIX_BY_TYPE_NAME.put("byte[]", "ByteArray");
METHOD_SUFFIX_BY_TYPE_NAME.put("char", "Char");
METHOD_SUFFIX_BY_TYPE_NAME.put("char[]", "CharArray");
METHOD_SUFFIX_BY_TYPE_NAME.put(CHAR_SEQUENCE, "CharSequence");
METHOD_SUFFIX_BY_TYPE_NAME.put(CHAR_SEQUENCE + "[]", "CharSequenceArray");
METHOD_SUFFIX_BY_TYPE_NAME.put("java.util.ArrayList<" + CHAR_SEQUENCE + ">", "CharSequenceArrayList");
METHOD_SUFFIX_BY_TYPE_NAME.put("double", "Double");
METHOD_SUFFIX_BY_TYPE_NAME.put("double[]", "DoubleArray");
METHOD_SUFFIX_BY_TYPE_NAME.put("float", "Float");
METHOD_SUFFIX_BY_TYPE_NAME.put("float[]", "FloatArray");
METHOD_SUFFIX_BY_TYPE_NAME.put("int", "Int");
METHOD_SUFFIX_BY_TYPE_NAME.put("int[]", "IntArray");
METHOD_SUFFIX_BY_TYPE_NAME.put("java.util.ArrayList", "IntegerArrayList");
METHOD_SUFFIX_BY_TYPE_NAME.put("long", "Long");
METHOD_SUFFIX_BY_TYPE_NAME.put("long[]", "LongArray");
METHOD_SUFFIX_BY_TYPE_NAME.put("short", "Short");
METHOD_SUFFIX_BY_TYPE_NAME.put("short[]", "ShortArray");
METHOD_SUFFIX_BY_TYPE_NAME.put(STRING, "String");
METHOD_SUFFIX_BY_TYPE_NAME.put("java.lang.String[]", "StringArray");
METHOD_SUFFIX_BY_TYPE_NAME.put("java.util.ArrayList", "StringArrayList");
}
private AndroidAnnotationsEnvironment environment;
private AnnotationHelper annotationHelper;
private APTCodeModelHelper codeModelHelper;
private boolean restoreCallNeedCastStatement = false;
private boolean restoreCallNeedsSuppressWarning = false;
private boolean parcelerBean = false;
private String methodNameToSave;
private String methodNameToRestore;
private TypeMirror upperBound;
public BundleHelper(AndroidAnnotationsEnvironment environment, TypeMirror element) {
this.environment = environment;
annotationHelper = new AnnotationHelper(environment);
codeModelHelper = new APTCodeModelHelper(environment);
String typeString = element.toString();
TypeMirror type = element;
if (METHOD_SUFFIX_BY_TYPE_NAME.containsKey(typeString)) {
methodNameToSave = "put" + METHOD_SUFFIX_BY_TYPE_NAME.get(typeString);
methodNameToRestore = "get" + METHOD_SUFFIX_BY_TYPE_NAME.get(typeString);
} else if (element.getKind() == TypeKind.ARRAY) {
ArrayType arrayType = (ArrayType) element;
boolean hasTypeArguments = false;
if (arrayType.getComponentType() instanceof DeclaredType) {
DeclaredType declaredType = (DeclaredType) arrayType.getComponentType();
type = declaredType;
hasTypeArguments = declaredType.getTypeArguments().size() > 0;
} else if (arrayType.getComponentType().getKind() == TypeKind.TYPEVAR) {
type = arrayType.getComponentType();
upperBound = getUpperBound(type);
restoreCallNeedCastStatement = true;
restoreCallNeedsSuppressWarning = true;
} else {
type = arrayType.getComponentType();
}
if (isTypeParcelable(type)) {
methodNameToSave = "put" + "ParcelableArray";
methodNameToRestore = "get" + "ParcelableArray";
if (hasTypeArguments) {
restoreCallNeedsSuppressWarning = true;
}
} else {
methodNameToSave = "put" + "Serializable";
methodNameToRestore = "get" + "Serializable";
restoreCallNeedCastStatement = true;
}
} else if (typeString.startsWith(CanonicalNameConstants.ARRAYLIST)) {
boolean hasTypeArguments = false;
if (element instanceof DeclaredType) {
DeclaredType declaredType = (DeclaredType) element;
List extends TypeMirror> typeArguments = declaredType.getTypeArguments();
if (typeArguments.size() == 1) {
TypeMirror typeArgument = typeArguments.get(0);
if (typeArgument instanceof DeclaredType) {
declaredType = (DeclaredType) typeArgument;
type = declaredType;
hasTypeArguments = declaredType.getTypeArguments().size() > 0;
}
if (isTypeParcelable(type)) {
methodNameToSave = "put" + "ParcelableArrayList";
methodNameToRestore = "get" + "ParcelableArrayList";
if (hasTypeArguments) {
restoreCallNeedsSuppressWarning = true;
}
}
}
}
if (methodNameToSave == null) {
methodNameToSave = "put" + "Serializable";
methodNameToRestore = "get" + "Serializable";
restoreCallNeedCastStatement = true;
restoreCallNeedsSuppressWarning = true;
}
} else if (typeString.startsWith(CanonicalNameConstants.SPARSE_ARRAY)) {
methodNameToSave = "put" + "SparseParcelableArray";
methodNameToRestore = "get" + "SparseParcelableArray";
} else {
boolean hasTypeArguments = element.getKind() == TypeKind.DECLARED && hasTypeArguments(element) || //
element.getKind() == TypeKind.TYPEVAR && hasTypeArguments(getUpperBound(element));
ParcelerHelper parcelerHelper = new ParcelerHelper(environment);
if (isTypeParcelable(type)) {
methodNameToSave = "put" + "Parcelable";
methodNameToRestore = "get" + "Parcelable";
} else if (parcelerHelper.isParcelType(type)) {
methodNameToSave = "put" + "Parcelable";
methodNameToRestore = "get" + "Parcelable";
parcelerBean = true;
} else {
methodNameToSave = "put" + "Serializable";
methodNameToRestore = "get" + "Serializable";
restoreCallNeedCastStatement = true;
if (hasTypeArguments) {
restoreCallNeedsSuppressWarning = true;
}
}
}
}
private boolean isTypeParcelable(TypeMirror typeMirror) {
TypeMirror parcelableType = annotationHelper.typeElementFromQualifiedName(CanonicalNameConstants.PARCELABLE).asType();
return annotationHelper.isSubtype(typeMirror, parcelableType);
}
private TypeMirror getUpperBound(TypeMirror type) {
TypeVariable typeVariable = (TypeVariable) type;
return typeVariable.getUpperBound();
}
private boolean hasTypeArguments(TypeMirror type) {
DeclaredType declaredType = (DeclaredType) type;
return declaredType.getTypeArguments().size() > 0;
}
public IJExpression getExpressionToRestoreFromBundle(AbstractJClass variableClass, IJExpression bundle, IJExpression extraKey, JMethod method) {
IJExpression expressionToRestore;
if ("getParcelableArray".equals(methodNameToRestore)) {
AbstractJClass erasure;
if (upperBound != null) {
erasure = codeModelHelper.typeMirrorToJClass(upperBound).erasure().array();
} else {
erasure = variableClass.elementType().erasure().array();
}
expressionToRestore = environment.getJClass(org.androidannotations.api.bundle.BundleHelper.class).staticInvoke("getParcelableArray").arg(bundle).arg(extraKey).arg(erasure.dotclass());
} else {
expressionToRestore = JExpr.invoke(bundle, methodNameToRestore).arg(extraKey);
}
if (parcelerBean) {
expressionToRestore = environment.getJClass(CanonicalNameConstants.PARCELS_UTILITY_CLASS).staticInvoke("unwrap").arg(expressionToRestore);
}
if (restoreCallNeedCastStatement) {
expressionToRestore = JExpr.cast(variableClass, expressionToRestore);
if (restoreCallNeedsSuppressWarning) {
codeModelHelper.addSuppressWarnings(method, "unchecked");
}
}
return expressionToRestore;
}
public IJStatement getExpressionToSaveFromField(IJExpression saveStateBundleParam, IJExpression fieldName, IJExpression variableRef) {
IJExpression refExpression = variableRef;
if (parcelerBean) {
refExpression = environment.getJClass(CanonicalNameConstants.PARCELS_UTILITY_CLASS).staticInvoke("wrap").arg(refExpression);
}
return JExpr.invoke(saveStateBundleParam, methodNameToSave).arg(fieldName).arg(refExpression);
}
}