/**
* Copyright (C) 2012-2013 eBusiness Information (www.ebusinessinformation.fr)
*
* 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.athomas.androidkickstartr.generator;
import static com.sun.codemodel.JExpr.TRUE;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.athomas.androidkickstartr.AppDetails;
import com.athomas.androidkickstartr.util.CodeModelHelper;
import com.athomas.androidkickstartr.util.RefHelper;
import com.sun.codemodel.JAnnotationUse;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldRef;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JForEach;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JVar;
public class MainActivityGenerator implements Generator {
private Logger LOGGER = LoggerFactory.getLogger(getClass());
private JDefinedClass jClass;
private RefHelper ref;
private JCodeModel jCodeModel;
private AppDetails appDetails;
private CodeModelHelper codeModelHelper;
/**
* Code elements
*/
private JFieldVar pagerField;
private JFieldVar locationsField;
private JBlock afterViewsBody;
public MainActivityGenerator(AppDetails appDetails) {
this.appDetails = appDetails;
}
public JCodeModel generate(JCodeModel jCodeModel, RefHelper ref) throws IOException {
this.jCodeModel = jCodeModel;
this.ref = ref;
codeModelHelper = new CodeModelHelper(ref, appDetails);
startGeneration(jCodeModel);
return jCodeModel;
}
private void startGeneration(JCodeModel jCodeModel) {
try {
jClass = jCodeModel._class(appDetails.getActivityPackage());
createActivity();
afterViewsBody = createAfterViewsMethod();
if (!appDetails.isSample()) {
JFieldVar textViewField = null;
if (!appDetails.isViewPager()) {
textViewField = createTextViewField("hello");
codeModelHelper.doViewById(afterViewsBody, "hello", textViewField);
}
if (appDetails.isRestTemplate() && appDetails.isAndroidAnnotations()) {
addRestClient(textViewField);
}
if (appDetails.isTabNavigation() || appDetails.isListNavigation()) {
createAndInitLocationsField();
}
if (appDetails.isViewPager()) {
addViewPager(jCodeModel);
}
createConfigureActionBar();
}
createOnCreateOptionsMenu();
} catch (JClassAlreadyExistsException e1) {
LOGGER.error("Classname already exists", e1);
}
}
private void createAndInitLocationsField() {
// private String[] locations;
locationsField = jClass.field(JMod.PRIVATE, ref.string().array(), "locations");
// locations = getResources().getStringArray(R.array.locations);
JFieldRef rArrayLocations = ref.r().staticRef("array").ref("locations");
JInvocation getResources = JExpr.invoke("getResources");
JInvocation getStringArray = getResources.invoke("getStringArray").arg(rArrayLocations);
afterViewsBody.assign(locationsField, getStringArray);
}
private void createActivity() {
JClass parentActivity;
if (appDetails.isRoboguice() && appDetails.isActionBarSherlock()) {
if (appDetails.isViewPager()) {
parentActivity = ref.ref(appDetails.getRoboSherlockFragmentActivityPackage());
} else {
parentActivity = ref.ref(appDetails.getRoboSherlockActivityPackage());
}
} else if (appDetails.isActionBarSherlock()) {
parentActivity = appDetails.isViewPager() ? ref.sFragmentActivity() : ref.sActivity();
} else if (appDetails.isRoboguice()) {
parentActivity = appDetails.isViewPager() ? ref.roboFragmentActivity() : ref.roboActivity();
} else {
parentActivity = appDetails.isViewPager() ? ref.fragmentActivity() : ref.activity();
}
jClass._extends(parentActivity);
// @EActivity
if (appDetails.isAndroidAnnotations()) {
JAnnotationUse eactivityAnnotation = jClass.annotate(ref.eactivity());
JFieldRef field = ref.r().staticRef("layout").ref(appDetails.getActivityLayout());
eactivityAnnotation.param("value", field);
}
}
private JFieldVar createViewField(JClass type, String name) {
int mod = appDetails.isAndroidAnnotations() || appDetails.isRoboguice() ? JMod.NONE : JMod.PRIVATE;
JFieldVar field = jClass.field(mod, type, name);
return field;
}
private JFieldVar createTextViewField(String name) {
return createViewField(ref.textView(), name);
}
private JBlock createAfterViewsMethod() {
JBlock afterViewsBody;
if (!appDetails.isAndroidAnnotations()) {
JMethod onCreate = jClass.method(JMod.PUBLIC, jCodeModel.VOID, "onCreate");
onCreate.annotate(ref.override());
JVar params = onCreate.param(ref.bundle(), "savedInstanceState");
afterViewsBody = onCreate.body();
// super.onCreate()
afterViewsBody.invoke(JExpr._super(), "onCreate").arg(params);
// setContentView(R.layout.xxx)
afterViewsBody.invoke("setContentView").arg(ref.r().staticRef("layout").ref(appDetails.getActivityLayout()));
} else {
JMethod afterViews = jClass.method(JMod.NONE, jCodeModel.VOID, "afterViews");
afterViews.annotate(ref.afterViews());
afterViewsBody = afterViews.body();
}
return afterViewsBody;
}
private void createOnCreateOptionsMenu() {
JMethod onCreateOptionsMenu = null;
JClass menu = !appDetails.isActionBarSherlock() ? ref.menu() : ref.sMenu();
onCreateOptionsMenu = jClass.method(JMod.PUBLIC, jCodeModel.BOOLEAN, "onCreateOptionsMenu");
JVar menuVar = onCreateOptionsMenu.param(menu, "menu");
onCreateOptionsMenu.annotate(ref.override());
JBlock onCreateOptionsMenuBody = onCreateOptionsMenu.body();
String getMenuInflater = appDetails.isActionBarSherlock() ? "getSupportMenuInflater" : "getMenuInflater";
JFieldRef rMenuMain = ref.r().staticRef("menu").ref("activity_main");
onCreateOptionsMenuBody.invoke(getMenuInflater).//
invoke("inflate"). //
arg(rMenuMain). //
arg(menuVar);
onCreateOptionsMenuBody._return(TRUE);
}
private void createConfigureActionBar() {
if (appDetails.isActionBarSherlock() && (appDetails.isListNavigation() || appDetails.isTabNavigation())) {
JMethod configureActionBar = jClass.method(JMod.PRIVATE, jCodeModel.VOID, "configureActionBar");
JBlock configureActionBarBody = configureActionBar.body();
// LIST NAVIGATION
if (appDetails.isListNavigation()) {
addListNavigationConfiguration(configureActionBarBody);
}
// TAB NAVIGATION
if (appDetails.isTabNavigation()) {
addTabNavigationConfiguration(configureActionBarBody);
}
afterViewsBody.invoke(configureActionBar);
}
}
private void addTabNavigationConfiguration(JBlock configureActionBarBody) {
// implements TabListener
jClass._implements(ref.sTabListener());
// @Override
// public void onTabSelected(Tab tab, FragmentTransaction ft) {
JMethod onTabSelectedMethod = jClass.method(JMod.PUBLIC, jCodeModel.VOID, "onTabSelected");
JVar tabParam = onTabSelectedMethod.param(ref.sTab(), "tab");
onTabSelectedMethod.param(ref.fragmentTransaction(), "ft");
onTabSelectedMethod.annotate(ref.override());
if (appDetails.isViewPager()) {
JBlock onTabSelectedBody = onTabSelectedMethod.body();
// int position = tab.getPosition();
JVar positionVar = onTabSelectedBody.decl(jCodeModel.INT, "position", tabParam.invoke("getPosition"));
// pager.setCurrentItem(position);
onTabSelectedBody.invoke(pagerField, "setCurrentItem").arg(positionVar);
}
jClass.direct("@Override\n " + //
"public void onTabUnselected(Tab tab, FragmentTransaction ft) {}");
jClass.direct("@Override\n" + //
"public void onTabReselected(Tab tab, FragmentTransaction ft) {}");
JInvocation getSupportActionBar = JExpr.invoke("getSupportActionBar");
JFieldRef navigationModeList = ref.sActionBar().staticRef("NAVIGATION_MODE_TABS");
configureActionBarBody.invoke(getSupportActionBar, "setNavigationMode").arg(navigationModeList);
JForEach forEachLocation = configureActionBarBody.forEach(ref.string(), "location", locationsField);
JVar location = forEachLocation.var();
JBlock forEachLocationBody = forEachLocation.body();
JVar tab = forEachLocationBody.decl(ref.sTab(), "tab", getSupportActionBar.invoke("newTab"));
forEachLocationBody.invoke(tab, "setText").arg(location);
forEachLocationBody.invoke(tab, "setTabListener").arg(JExpr._this());
forEachLocationBody.invoke(getSupportActionBar, "addTab").arg(tab);
}
private void addListNavigationConfiguration(JBlock configureActionBarBody) {
jClass._implements(ref.sNavigationListener());
// @Override
// public boolean onNavigationItemSelected(int itemPosition, long itemId) {
JMethod onNavigationItemSelectedMethod = jClass.method(JMod.PUBLIC, jCodeModel.BOOLEAN, "onNavigationItemSelected");
JVar itemPositionParam = onNavigationItemSelectedMethod.param(jCodeModel.INT, "itemPosition");
onNavigationItemSelectedMethod.param(jCodeModel.LONG, "itemId");
onNavigationItemSelectedMethod.annotate(ref.override());
JBlock onNavigationItemSelectedBody = onNavigationItemSelectedMethod.body();
if (appDetails.isViewPager()) {
// pager.setCurrentItem(itemPosition);
onNavigationItemSelectedBody.invoke(pagerField, "setCurrentItem").arg(itemPositionParam);
}
// return true;
onNavigationItemSelectedBody._return(JExpr.TRUE);
// configure Tab navigation
JInvocation getSupportActionbar = JExpr.invoke("getSupportActionBar");
JInvocation getContext = getSupportActionbar.invoke("getThemedContext");
JVar contextVar = configureActionBarBody.decl(ref.context(), "context", getContext);
JFieldRef rArrayLocations = ref.r().staticRef("array").ref("locations");
// NEEDED! CodeModel doesn't manage the case where two
// classes have the same name
JExpression rLayoutSherlockSpinner = JExpr.direct("android.R.layout.simple_list_item_1");
JClass arrayAdapter = ref.arrayAdapter();
JInvocation createFromResource = arrayAdapter.staticInvoke("createFromResource"). //
arg(contextVar). //
arg(rArrayLocations). //
arg(rLayoutSherlockSpinner);
JClass listType = arrayAdapter.narrow(ref.charSequence());
JVar listVar = configureActionBarBody.decl(listType, "list", createFromResource);
JFieldRef navigationModeList = ref.sActionBar().staticRef("NAVIGATION_MODE_LIST");
configureActionBarBody.invoke(getSupportActionbar, "setNavigationMode").arg(navigationModeList);
configureActionBarBody.invoke(getSupportActionbar, "setListNavigationCallbacks").//
arg(listVar).//
arg(JExpr._this());
}
private void addRestClient(JFieldVar textViewField) {
// add annotated restClient field
JFieldVar restClient = jClass.field(JMod.NONE, ref.ref(appDetails.getRestClientPackage()), "restClient");
restClient.annotate(ref.restService());
// add doSomethingElseOnUiThread method
JMethod doSomethingElseOnUiThread = jClass.method(JMod.NONE, jCodeModel.VOID, "doSomethingElseOnUiThread");
doSomethingElseOnUiThread.annotate(ref.uithread());
JBlock body = doSomethingElseOnUiThread.body();
if (textViewField != null) {
body.invoke(textViewField, "setText").arg("Hi!");
} else {
body.directStatement("// do something on UIThread");
}
// add doSomethingInBackground method
JMethod doSomethingInBackground = jClass.method(JMod.NONE, jCodeModel.VOID, "doSomethingInBackground");
doSomethingInBackground.annotate(ref.background());
JBlock doSomethingInBackgroundBody = doSomethingInBackground.body();
doSomethingInBackgroundBody.invoke(restClient, "main");
doSomethingInBackgroundBody.invoke(doSomethingElseOnUiThread);
}
private void addViewPager(JCodeModel jCodeModel) {
pagerField = createViewField(ref.viewPager(), "pager");
codeModelHelper.doViewById(afterViewsBody, "pager", pagerField);
// configureViewPager();
afterViewsBody.invoke("configureViewPager");
// private void configureViewPager() {
JMethod configureViewPager = jClass.method(JMod.PRIVATE, jCodeModel.VOID, "configureViewPager");
JBlock configureViewPagerBody = configureViewPager.body();
JClass viewPagerAdapterClass = ref.ref(appDetails.getViewPagerAdapterPackage());
// ViewFragmentPagerAdapter viewPagerAdapter = new ViewFragmentPagerAdapter(getSupportFragmentManager(), locations);
JInvocation getFragmentManagerInvoke = JExpr.invoke("getSupportFragmentManager");
JInvocation newViewPagerAdapter = JExpr._new(viewPagerAdapterClass).arg(getFragmentManagerInvoke);
if (appDetails.isListNavigation() || appDetails.isTabNavigation()) {
newViewPagerAdapter.arg(locationsField);
}
JVar viewPagerAdapterVar = configureViewPagerBody.decl(viewPagerAdapterClass, "viewPagerAdapter", newViewPagerAdapter);
// pager.setAdapter(viewPagerAdapter);
configureViewPagerBody.invoke(pagerField, "setAdapter").arg(viewPagerAdapterVar);
if (appDetails.isListNavigation() || appDetails.isTabNavigation()) {
// pager.setOnPageChangeListener(this);
configureViewPagerBody.invoke(pagerField, "setOnPageChangeListener").arg(JExpr._this());
// implements OnPageChangeListener
jClass._implements(ref.onPageChangeListener());
jClass.direct("@Override\n" + //
"public void onPageScrollStateChanged(int position) {}");
jClass.direct("@Override\n" + //
" public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}");
// @Override
// public void onPageSelected(int position) {
JMethod onPageSelectedMethod = jClass.method(JMod.PUBLIC, jCodeModel.VOID, "onPageSelected");
JVar positionVar = onPageSelectedMethod.param(jCodeModel.INT, "position");
JBlock onPageSelectedBody = onPageSelectedMethod.body();
if (appDetails.isTabNavigation()) {
// Tab tab = getSupportActionBar().getTabAt(position);
// getSupportActionBar().selectTab(tab);
JInvocation getTabAtMethod = JExpr.invoke("getSupportActionBar").invoke("getTabAt").arg(positionVar);
JVar tabVar = onPageSelectedBody.decl(ref.sTab(), "tab", getTabAtMethod);
JInvocation getSupportActionBarInvoke = JExpr.invoke("getSupportActionBar");
onPageSelectedBody.invoke(getSupportActionBarInvoke, "selectTab").arg(tabVar);
} else if (appDetails.isListNavigation()) {
// getSupportActionBar().setSelectedNavigationItem(position);
JInvocation getSupportActionBarInvoke = JExpr.invoke("getSupportActionBar");
onPageSelectedBody.invoke(getSupportActionBarInvoke, "setSelectedNavigationItem").arg(positionVar);
}
}
}
}