Java tutorial
/** * Copyright (C) 2010-2015 eBusiness Information, Excilys Group * * 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 com.sun.codemodel.JExpr._new; import static com.sun.codemodel.JExpr.ref; import static com.sun.codemodel.JMod.PRIVATE; import static com.sun.codemodel.JMod.PUBLIC; import static com.sun.codemodel.JMod.STATIC; import java.util.List; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import org.androidannotations.holder.HasIntentBuilder; import com.sun.codemodel.JBlock; import com.sun.codemodel.JClass; import com.sun.codemodel.JClassAlreadyExistsException; import com.sun.codemodel.JConditional; import com.sun.codemodel.JExpr; import com.sun.codemodel.JExpression; import com.sun.codemodel.JFieldRef; import com.sun.codemodel.JFieldVar; import com.sun.codemodel.JInvocation; import com.sun.codemodel.JMethod; import com.sun.codemodel.JMod; import com.sun.codemodel.JVar; public class ActivityIntentBuilder extends IntentBuilder { private static final int MIN_SDK_WITH_FRAGMENT_SUPPORT = 11; private static final int MIN_SDK_WITH_ACTIVITY_OPTIONS = 16; private JFieldVar fragmentField; private JFieldVar fragmentSupportField; private JFieldRef optionsField; public ActivityIntentBuilder(HasIntentBuilder holder, AndroidManifest androidManifest) { super(holder, androidManifest); } @Override public void build() throws JClassAlreadyExistsException { super.build(); optionsField = ref("lastOptions"); createAdditionalConstructor(); // See issue #541 createAdditionalIntentMethods(); overrideStartForResultMethod(); } private void createAdditionalIntentMethods() { if (hasFragmentInClasspath()) { // intent() with android.app.Fragment param JMethod method = holder.getGeneratedClass().method(STATIC | PUBLIC, holder.getIntentBuilderClass(), "intent"); JVar fragmentParam = method.param(holder.classes().FRAGMENT, "fragment"); method.body()._return(_new(holder.getIntentBuilderClass()).arg(fragmentParam)); } if (hasFragmentSupportInClasspath()) { // intent() with android.support.v4.app.Fragment param JMethod method = holder.getGeneratedClass().method(STATIC | PUBLIC, holder.getIntentBuilderClass(), "intent"); JVar fragmentParam = method.param(holder.classes().SUPPORT_V4_FRAGMENT, "supportFragment"); method.body()._return(_new(holder.getIntentBuilderClass()).arg(fragmentParam)); } } @Override protected JClass getSuperClass() { JClass superClass = holder.refClass(org.androidannotations.api.builder.ActivityIntentBuilder.class); return superClass.narrow(builderClass); } private void createAdditionalConstructor() { if (hasFragmentInClasspath()) { fragmentField = addFragmentConstructor(holder.classes().FRAGMENT, "fragment_"); } if (hasFragmentSupportInClasspath()) { fragmentSupportField = addFragmentConstructor(holder.classes().SUPPORT_V4_FRAGMENT, "fragmentSupport_"); } } private JFieldVar addFragmentConstructor(JClass fragmentClass, String fieldName) { JFieldVar fragmentField = holder.getIntentBuilderClass().field(PRIVATE, fragmentClass, fieldName); JExpression generatedClass = holder.getGeneratedClass().dotclass(); JMethod constructor = holder.getIntentBuilderClass().constructor(JMod.PUBLIC); JVar constructorFragmentParam = constructor.param(fragmentClass, "fragment"); JBlock constructorBody = constructor.body(); constructorBody.invoke("super").arg(constructorFragmentParam.invoke("getActivity")).arg(generatedClass); constructorBody.assign(fragmentField, constructorFragmentParam); return fragmentField; } private void overrideStartForResultMethod() { JMethod method = holder.getIntentBuilderClass().method(PUBLIC, holder.codeModel().VOID, "startForResult"); method.annotate(Override.class); JVar requestCode = method.param(holder.codeModel().INT, "requestCode"); JBlock body = method.body(); JConditional condition = null; if (fragmentSupportField != null) { condition = body._if(fragmentSupportField.ne(JExpr._null())); condition._then() // .invoke(fragmentSupportField, "startActivityForResult").arg(intentField).arg(requestCode); } if (fragmentField != null) { if (condition == null) { condition = body._if(fragmentField.ne(JExpr._null())); } else { condition = condition._elseif(fragmentField.ne(JExpr._null())); } JBlock fragmentStartForResultInvocationBlock; if (hasActivityOptionsInFragment() && shouldGuardActivityOptions()) { fragmentStartForResultInvocationBlock = createCallWithIfGuard(requestCode, condition._then(), fragmentField); } else { fragmentStartForResultInvocationBlock = condition._then(); } JInvocation invocation = fragmentStartForResultInvocationBlock // .invoke(fragmentField, "startActivityForResult").arg(intentField).arg(requestCode); if (hasActivityOptionsInFragment()) { invocation.arg(optionsField); } } JBlock activityStartInvocationBlock = null; if (condition != null) { activityStartInvocationBlock = condition._else(); } else { activityStartInvocationBlock = method.body(); } JConditional activityCondition = activityStartInvocationBlock ._if(contextField._instanceof(holder.classes().ACTIVITY)); JBlock thenBlock = activityCondition._then(); JVar activityVar = thenBlock.decl(holder.classes().ACTIVITY, "activity", JExpr.cast(holder.classes().ACTIVITY, contextField)); if (hasActivityCompatInClasspath() && hasActivityOptionsInActivityCompat()) { thenBlock.staticInvoke(holder.classes().ACTIVITY_COMPAT, "startActivityForResult") // .arg(activityVar).arg(intentField).arg(requestCode).arg(optionsField); } else if (hasActivityOptionsInFragment()) { JBlock startForResultInvocationBlock; if (shouldGuardActivityOptions()) { startForResultInvocationBlock = createCallWithIfGuard(requestCode, thenBlock, activityVar); } else { startForResultInvocationBlock = thenBlock; } startForResultInvocationBlock.invoke(activityVar, "startActivityForResult") // .arg(intentField).arg(requestCode).arg(optionsField); } else { thenBlock.invoke(activityVar, "startActivityForResult").arg(intentField).arg(requestCode); } if (hasActivityOptionsInFragment()) { JBlock startInvocationBlock; if (shouldGuardActivityOptions()) { startInvocationBlock = createCallWithIfGuard(null, activityCondition._else(), contextField); } else { startInvocationBlock = activityCondition._else(); } startInvocationBlock.invoke(contextField, "startActivity").arg(intentField).arg(optionsField); } else { activityCondition._else().invoke(contextField, "startActivity").arg(intentField); } } private JBlock createCallWithIfGuard(JVar requestCode, JBlock thenBlock, JExpression invocationTarget) { JConditional guardIf = thenBlock._if(holder.classes().BUILD_VERSION.staticRef("SDK_INT") .gte(holder.classes().BUILD_VERSION_CODES.staticRef("JELLY_BEAN"))); JBlock startInvocationBlock = guardIf._then(); String methodName = requestCode != null ? "startActivityForResult" : "startActivity"; JInvocation invocation = guardIf._else().invoke(invocationTarget, methodName).arg(intentField); if (requestCode != null) { invocation.arg(requestCode); } return startInvocationBlock; } protected boolean hasFragmentInClasspath() { boolean fragmentExistsInSdk = androidManifest.getMinSdkVersion() >= MIN_SDK_WITH_FRAGMENT_SUPPORT; return fragmentExistsInSdk && elementUtils.getTypeElement(CanonicalNameConstants.FRAGMENT) != null; } protected boolean hasFragmentSupportInClasspath() { return elementUtils.getTypeElement(CanonicalNameConstants.SUPPORT_V4_FRAGMENT) != null; } protected boolean hasActivityCompatInClasspath() { return elementUtils.getTypeElement(CanonicalNameConstants.ACTIVITY_COMPAT) != null; } protected boolean hasActivityOptionsInFragment() { if (!hasFragmentInClasspath()) { return false; } TypeElement fragment = elementUtils.getTypeElement(CanonicalNameConstants.FRAGMENT); return hasActivityOptions(fragment, 1); } protected boolean hasActivityOptionsInActivityCompat() { TypeElement activityCompat = elementUtils.getTypeElement(CanonicalNameConstants.ACTIVITY_COMPAT); return hasActivityOptions(activityCompat, 2); } private boolean hasActivityOptions(TypeElement type, int optionsParamPosition) { if (type == null) { return false; } for (Element element : type.getEnclosedElements()) { if (element.getKind() == ElementKind.METHOD) { ExecutableElement executableElement = (ExecutableElement) element; if (executableElement.getSimpleName().contentEquals("startActivity")) { List<? extends VariableElement> parameters = executableElement.getParameters(); if (parameters.size() == optionsParamPosition + 1) { VariableElement parameter = parameters.get(optionsParamPosition); if (parameter.asType().toString().equals(CanonicalNameConstants.BUNDLE)) { return true; } } } } } return false; } protected boolean shouldGuardActivityOptions() { return androidManifest.getMinSdkVersion() < MIN_SDK_WITH_ACTIVITY_OPTIONS; } }