Skip to content

Commit

Permalink
Merge pull request #1 from joxad/anno
Browse files Browse the repository at this point in the history
Anno
  • Loading branch information
joxad authored Aug 9, 2016
2 parents 434e26f + 33f36c7 commit 2285abe
Show file tree
Hide file tree
Showing 41 changed files with 842 additions and 121 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@

[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-easydatabinding-green.svg?style=true)](https://android-arsenal.com/details/1/4106)

# easydatabinding
This project goal is to create activity fragment and views, with less code to be more efficient on the view models


# Version : 0.4.5
# Version : 0.6.0
# Goal

I used DataBinding for a few weeks since Google allows us to use it.
Expand Down
1 change: 1 addition & 0 deletions annotation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
32 changes: 32 additions & 0 deletions annotation/annotation.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":annotation" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="easydatabinding" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":annotation" />
</configuration>
</facet>
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="true" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/main" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="annotation.annotation" level="project" />
</component>
</module>
7 changes: 7 additions & 0 deletions annotation/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apply plugin: 'java'
apply plugin: 'maven'

// This is important for publishing, even if Android Studio claims it isn't
// used. Android can't interpret Java 8 byte code.
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.joxad.easydatabinding;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(value = ElementType.TYPE)
public @interface DataBindable {
}
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ buildscript {

}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'

classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
}
Expand Down
1 change: 1 addition & 0 deletions compiler/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
10 changes: 10 additions & 0 deletions compiler/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apply plugin: 'java'

sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7

dependencies {
compile project (':annotation')
compile 'com.google.auto.service:auto-service:1.0-rc2'
compile 'com.squareup:javapoet:1.0.0'
}
37 changes: 37 additions & 0 deletions compiler/compiler.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":compiler" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="easydatabinding" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":compiler" />
</configuration>
</facet>
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="true" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/main" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="annotation" exported="" />
<orderEntry type="library" exported="" name="auto-service-1.0-rc2" level="project" />
<orderEntry type="library" exported="" name="javapoet-1.0.0" level="project" />
<orderEntry type="library" exported="" name="auto-common-0.3" level="project" />
<orderEntry type="library" exported="" name="guava-18.0" level="project" />
<orderEntry type="library" exported="" name="compiler.compiler" level="project" />
</component>
</module>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.joxad.easydatabinding;

import java.util.List;

import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;

class AnnotatedClass {
public final String annotatedClassName;
public final List<String> variableNames;
public final TypeElement typeElement;

public AnnotatedClass(TypeElement typeElement, List<String> variableNames) {
this.annotatedClassName = typeElement.getSimpleName().toString();
this.variableNames = variableNames;
this.typeElement = typeElement;
}

public TypeMirror getType() {
return typeElement.asType();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.joxad.easydatabinding;

import javax.lang.model.element.TypeElement;

import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.PUBLIC;
final class ClassValidator {
static boolean isPublic(TypeElement annotatedClass) {
return annotatedClass.getModifiers().contains(PUBLIC);
}

static boolean isAbstract(TypeElement annotatedClass) {
return annotatedClass.getModifiers().contains(ABSTRACT);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.joxad.easydatabinding;

import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;

import java.util.List;

import static com.squareup.javapoet.ClassName.get;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;

final class CodeGenerator {

private static final String CLASS_NAME = "DataBindableUtil";

public static TypeSpec generateClass(List<AnnotatedClass> classes) {
TypeSpec.Builder builder = classBuilder(CLASS_NAME)
.addModifiers(PUBLIC, FINAL);
for (AnnotatedClass anno : classes) {
builder.addMethod(makeCreateStringMethod(anno));
}
return builder.build();
}

/**
* @return a createString() method that takes annotatedClass's type as an input.
*/
private static MethodSpec makeCreateStringMethod(AnnotatedClass annotatedClass) {
StringBuilder builder = new StringBuilder();
builder.append(String.format("return \"%s{\" + ", annotatedClass.annotatedClassName));
for (String variableName : annotatedClass.variableNames) {
builder.append(String.format(" \"%s='\" + String.valueOf(instance.%s) + \"',\" + ",
variableName, variableName));
}
builder.append("\"}\"");
return methodBuilder("createString")
.addJavadoc("@return string suitable for {@param instance}'s toString()")
.addModifiers(PUBLIC, STATIC)
.addParameter(get(annotatedClass.getType()), "instance")
.addStatement(builder.toString())
.returns(String.class)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.joxad.easydatabinding;

import com.google.auto.service.AutoService;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.annotation.processing.*;
import javax.annotation.processing.Messager;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;

import static com.squareup.javapoet.JavaFile.builder;
import static java.util.Collections.singleton;
import static javax.lang.model.SourceVersion.latestSupported;
import static javax.tools.Diagnostic.Kind.*;


@AutoService(Processor.class)
public class DataBindableProcessor extends AbstractProcessor {

private static final String ANNOTATION = "@" + DataBindable.class.getSimpleName();

private Messager messager;

@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
messager = processingEnv.getMessager();
}

@Override
public Set<String> getSupportedAnnotationTypes() {
return singleton(DataBindableProcessor.class.getCanonicalName());
}

@Override
public SourceVersion getSupportedSourceVersion() {
return latestSupported();
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
ArrayList<com.joxad.easydatabinding.AnnotatedClass> annotatedClasses = new ArrayList<>();
for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(DataBindable.class)) {
// Our annotation is defined with @Target(value=TYPE). Therefore, we can assume that
// this annotatedElement is a TypeElement.
TypeElement annotatedClass = (TypeElement) annotatedElement;
if (!isValidClass(annotatedClass)) {
return true;
}
try {
annotatedClasses.add(buildAnnotatedClass(annotatedClass));
} catch (NoPackageNameException | IOException e) {
String message = String.format("Couldn't process class %s: %s", annotatedClass,
e.getMessage());
messager.printMessage(ERROR, message, annotatedElement);
}
}
try {
generate(annotatedClasses);
} catch (NoPackageNameException | IOException e) {
messager.printMessage(ERROR, "Couldn't generate class");
}
return true;
}

private boolean isValidClass(TypeElement annotatedClass) {

if (!ClassValidator.isPublic(annotatedClass)) {
String message = String.format("Classes annotated with %s must be public.",
ANNOTATION);
messager.printMessage(ERROR, message, annotatedClass);
return false;
}

if (ClassValidator.isAbstract(annotatedClass)) {
String message = String.format("Classes annotated with %s must not be abstract.",
ANNOTATION);
messager.printMessage(ERROR, message, annotatedClass);
return false;
}

return true;
}

private com.joxad.easydatabinding.AnnotatedClass buildAnnotatedClass(TypeElement annotatedClass)
throws NoPackageNameException, IOException {
ArrayList<String> variableNames = new ArrayList<>();
for (Element element : annotatedClass.getEnclosedElements()) {
if (!(element instanceof VariableElement)) {
continue;
}
VariableElement variableElement = (VariableElement) element;
variableNames.add(variableElement.getSimpleName().toString());
}
return new com.joxad.easydatabinding.AnnotatedClass(annotatedClass, variableNames);
}

private void generate(List<com.joxad.easydatabinding.AnnotatedClass> annos) throws NoPackageNameException, IOException {
if (annos.size() == 0) {
return;
}
String packageName = Utils.getPackageName(processingEnv.getElementUtils(),
annos.get(0).typeElement);
TypeSpec generatedClass = com.joxad.easydatabinding.CodeGenerator.generateClass(annos);

JavaFile javaFile = builder(packageName, generatedClass).build();
javaFile.writeTo(processingEnv.getFiler());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.joxad.easydatabinding;

import javax.lang.model.element.TypeElement;

class NoPackageNameException extends Exception {

public NoPackageNameException(TypeElement typeElement) {
super("The package of " + typeElement.getSimpleName() + " has no name");
}
}
21 changes: 21 additions & 0 deletions compiler/src/main/java/com/joxad/easydatabinding/Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.joxad.easydatabinding;

import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;

final class Utils {

private Utils() {
// no instances
}

static String getPackageName(Elements elementUtils, TypeElement type)
throws NoPackageNameException {
PackageElement pkg = elementUtils.getPackageOf(type);
if (pkg.isUnnamed()) {
throw new NoPackageNameException(type);
}
return pkg.getQualifiedName().toString();
}
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

# When configured, Gradle will run in incubating parallel mode.
# When configured, Gradle will run incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

VERSION_NAME=0.4.5
VERSION_NAME=0.6.0

POM_GROUP=com.joxad.easydatabinding
POM_NAME=easydatabinding
Expand Down
1 change: 0 additions & 1 deletion lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,5 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile libs.appCompat
provided libs.lombok
}
apply from: '../gradle/tasks/bintray_upload.gradle'
Loading

0 comments on commit 2285abe

Please sign in to comment.