├── .gitignore ├── README.md ├── auto-value-querymap ├── build.gradle ├── gradle.properties └── src │ ├── main │ └── java │ │ └── com │ │ └── oguzbabaoglu │ │ └── auto │ │ └── value │ │ └── querymap │ │ ├── AutoValueQueryMapExtension.java │ │ ├── ConstructorMethod.java │ │ ├── MapMethod.java │ │ ├── Param.java │ │ └── Property.java │ └── test │ └── java │ └── com │ └── oguzbabaoglu │ └── auto │ └── value │ └── querymap │ └── AutoValueQueryMapExtensionTest.java ├── build.gradle ├── example ├── build.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── oguzbabaoglu │ │ └── example │ │ ├── DemoRequest.java │ │ └── Nullable.java │ └── test │ └── java │ └── com │ └── oguzbabaoglu │ └── example │ └── DemoRequestTest.java ├── gradle.properties ├── gradle ├── gradle-mvn-push.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ IDEA 2 | .idea 3 | *.iml 4 | annotations 5 | 6 | # Gradle 7 | .gradle 8 | gradlew.bat 9 | build 10 | local.properties 11 | 12 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoValue: QueryMap Extension 2 | 3 | An extension for Google's [AutoValue](https://github.com/google/auto) that implements a "toQueryMap" method for Retrofit's [QueryMap](https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/QueryMap.html). 4 | 5 | ## Usage 6 | 7 | Include auto-value-querymap in your project and add a `public abstract Map toQueryMap()` method to your `@AutoValue` 8 | annotated class. 9 | 10 | You can also annotate your properties using `@Param` to define an alternate key name in the `QueryMap`. 11 | 12 | ```java 13 | @AutoValue public abstract class Foo { 14 | abstract String bar(); // Will be mapped as "bar":"" 15 | @Param("Bazoo") abstract String baz(); // Will be mapped as "Bazoo":"" 16 | 17 | // This method is what auto-value-querymap will implement. 18 | public abstract Map toQueryMap(); 19 | 20 | // Retrofit will convert this to "?bar=&Bazoo=" 21 | } 22 | ``` 23 | 24 | Now build your project and auto-value-querymap will implement the method. 25 | 26 | - `null` values will not be added to the map (Not allowed by `QueryMap`) 27 | - all values will be converted to `String` using `String.valueOf()` 28 | - the map will preserve order of decleration of the fields 29 | 30 | ## Download 31 | 32 | ### Android 33 | Add a Gradle dependency to the `apt` and `provided` configuration. 34 | 35 | ```groovy 36 | apt 'com.oguzbabaoglu:auto-value-querymap:1.0' 37 | provided 'com.oguzbabaoglu:auto-value-querymap:1.0' 38 | ``` 39 | 40 | (Using the [android-apt](https://bitbucket.org/hvisser/android-apt) plugin) 41 | 42 | ### Java 43 | Add a Gradle dependency to the `apt` and `compileOnly` configuration. 44 | 45 | ```groovy 46 | apt 'com.oguzbabaoglu:auto-value-querymap:1.0' 47 | compileOnly 'com.oguzbabaoglu:auto-value-querymap:1.0' 48 | ``` 49 | 50 | (Using the [gradle-apt-plugin](https://github.com/tbroyer/gradle-apt-plugin) plugin) 51 | 52 | ## Credit 53 | Based on the existing [auto-value-map](https://github.com/cynnyx/auto-value-map) extension by Cynny. 54 | 55 | ## License 56 | 57 | ``` 58 | Copyright 2016 Oguz Babaoglu. 59 | 60 | Licensed under the Apache License, Version 2.0 (the "License"); 61 | you may not use this file except in compliance with the License. 62 | You may obtain a copy of the License at 63 | 64 | http://www.apache.org/licenses/LICENSE-2.0 65 | 66 | Unless required by applicable law or agreed to in writing, software 67 | distributed under the License is distributed on an "AS IS" BASIS, 68 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 69 | See the License for the specific language governing permissions and 70 | limitations under the License. 71 | ``` 72 | -------------------------------------------------------------------------------- /auto-value-querymap/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | sourceCompatibility = JavaVersion.VERSION_1_7 4 | targetCompatibility = JavaVersion.VERSION_1_7 5 | 6 | dependencies { 7 | compile 'com.squareup:javapoet:1.7.0' 8 | compile 'com.google.auto.value:auto-value:1.3-rc1' 9 | compile 'com.google.auto.service:auto-service:1.0-rc2' 10 | compile 'com.google.auto:auto-common:0.6' 11 | 12 | testCompile 'junit:junit:4.12' 13 | testCompile 'com.google.truth:truth:0.27' 14 | testCompile 'com.google.testing.compile:compile-testing:0.9' 15 | testCompile files(org.gradle.internal.jvm.Jvm.current().getToolsJar()) 16 | } 17 | 18 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle') 19 | -------------------------------------------------------------------------------- /auto-value-querymap/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=auto-value-querymap 2 | POM_NAME=AutoValue: QueryMap Extension 3 | POM_PACKAGING=jar 4 | -------------------------------------------------------------------------------- /auto-value-querymap/src/main/java/com/oguzbabaoglu/auto/value/querymap/AutoValueQueryMapExtension.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.auto.value.querymap; 2 | 3 | import com.google.auto.service.AutoService; 4 | import com.google.auto.value.extension.AutoValueExtension; 5 | import com.squareup.javapoet.JavaFile; 6 | import com.squareup.javapoet.TypeSpec; 7 | import com.squareup.javapoet.TypeVariableName; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | import javax.lang.model.element.ExecutableElement; 13 | 14 | import static javax.lang.model.element.Modifier.ABSTRACT; 15 | import static javax.lang.model.element.Modifier.FINAL; 16 | 17 | @AutoService(AutoValueExtension.class) 18 | public class AutoValueQueryMapExtension extends AutoValueExtension { 19 | 20 | @Override public boolean applicable(Context context) { 21 | return MapMethod.findDeclaredMethod(context).size() > 0; 22 | } 23 | 24 | @Override public Set consumeMethods(Context context) { 25 | return MapMethod.findDeclaredMethod(context); 26 | } 27 | 28 | @Override public String generateClass(Context context, String className, String classToExtend, boolean isFinal) { 29 | List properties = Property.readProperties(context.properties()); 30 | 31 | TypeSpec.Builder subclass = TypeSpec.classBuilder(className) 32 | .superclass(TypeVariableName.get(classToExtend)) 33 | .addMethod(ConstructorMethod.generateConstructor(properties)) 34 | .addMethod(MapMethod.generateMethod(properties)); 35 | 36 | if (isFinal) { 37 | subclass.addModifiers(FINAL); 38 | } else { 39 | subclass.addModifiers(ABSTRACT); 40 | } 41 | 42 | return JavaFile.builder(context.packageName(), subclass.build()).build().toString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /auto-value-querymap/src/main/java/com/oguzbabaoglu/auto/value/querymap/ConstructorMethod.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.auto.value.querymap; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.squareup.javapoet.MethodSpec; 5 | import com.squareup.javapoet.ParameterSpec; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | class ConstructorMethod { 11 | static MethodSpec generateConstructor(List properties) { 12 | List params = Lists.newArrayList(); 13 | List keySet = new ArrayList<>(); 14 | for (Property p : properties) { 15 | params.add(ParameterSpec.builder(p.type, p.humanName).build()); 16 | keySet.add(p.humanName); 17 | } 18 | 19 | MethodSpec.Builder builder = MethodSpec.constructorBuilder() 20 | .addParameters(params); 21 | 22 | StringBuilder superFormat = new StringBuilder("super("); 23 | for (int i = properties.size(); i > 0; i--) { 24 | superFormat.append("$N"); 25 | if (i > 1) superFormat.append(", "); 26 | } 27 | superFormat.append(")"); 28 | builder.addStatement(superFormat.toString(), keySet.toArray()); 29 | 30 | return builder.build(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /auto-value-querymap/src/main/java/com/oguzbabaoglu/auto/value/querymap/MapMethod.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.auto.value.querymap; 2 | 3 | import com.google.auto.value.extension.AutoValueExtension; 4 | import com.google.common.collect.ImmutableSet; 5 | import com.squareup.javapoet.MethodSpec; 6 | import com.squareup.javapoet.ParameterizedTypeName; 7 | import com.squareup.javapoet.TypeName; 8 | 9 | import java.util.LinkedHashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | import javax.lang.model.element.ExecutableElement; 15 | import javax.lang.model.element.Modifier; 16 | import javax.lang.model.element.TypeElement; 17 | import javax.lang.model.type.TypeMirror; 18 | import javax.lang.model.util.ElementFilter; 19 | 20 | import static javax.lang.model.element.Modifier.PUBLIC; 21 | 22 | class MapMethod { 23 | private static final String METHOD_NAME = "toQueryMap"; 24 | private static final ParameterizedTypeName METHOD_RETURN_TYPE = ParameterizedTypeName 25 | .get(Map.class, String.class, String.class); 26 | 27 | static MethodSpec generateMethod(List properties) { 28 | MethodSpec.Builder builder = MethodSpec.methodBuilder(METHOD_NAME) 29 | .addModifiers(PUBLIC) 30 | .addAnnotation(Override.class) 31 | .returns(METHOD_RETURN_TYPE); 32 | 33 | builder.addStatement("$T queryMap = new $T<>()", METHOD_RETURN_TYPE, LinkedHashMap.class); 34 | for (Property p : properties) { 35 | if (!p.isPrimitive) builder.beginControlFlow("if ($L() != null)", p.methodName); 36 | builder.addStatement("queryMap.put($S, $T.valueOf($L()))", p.keyValue, String.class, p.methodName); 37 | if (!p.isPrimitive) builder.endControlFlow(); 38 | } 39 | builder.addStatement("return queryMap"); 40 | 41 | return builder.build(); 42 | } 43 | 44 | static Set findDeclaredMethod(AutoValueExtension.Context context) { 45 | TypeElement type = context.autoValueClass(); 46 | 47 | for (ExecutableElement method : ElementFilter.methodsIn(type.getEnclosedElements())) { 48 | if (method.getModifiers().contains(Modifier.ABSTRACT) && method.getModifiers().contains(Modifier.PUBLIC) 49 | && method.getSimpleName().toString().equals(METHOD_NAME) && method.getParameters().size() == 0) { 50 | TypeMirror rType = method.getReturnType(); 51 | TypeName returnType = TypeName.get(rType); 52 | if (returnType.equals(METHOD_RETURN_TYPE)) { 53 | return ImmutableSet.of(method); 54 | } 55 | } 56 | } 57 | 58 | return ImmutableSet.of(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /auto-value-querymap/src/main/java/com/oguzbabaoglu/auto/value/querymap/Param.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.auto.value.querymap; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.METHOD; 7 | import static java.lang.annotation.RetentionPolicy.SOURCE; 8 | 9 | /** 10 | * Annotation to indicate that this field should be added to the parameter map with 11 | * the provided name value as its key name. 12 | */ 13 | @Retention(SOURCE) 14 | @Target(METHOD) 15 | public @interface Param { 16 | 17 | /** 18 | * @return the desired key of the field in the map 19 | */ 20 | String value(); 21 | } 22 | -------------------------------------------------------------------------------- /auto-value-querymap/src/main/java/com/oguzbabaoglu/auto/value/querymap/Property.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.auto.value.querymap; 2 | 3 | import com.squareup.javapoet.TypeName; 4 | 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import javax.lang.model.element.AnnotationMirror; 10 | import javax.lang.model.element.ExecutableElement; 11 | import javax.lang.model.element.TypeElement; 12 | 13 | class Property { 14 | final String methodName; 15 | final String humanName; 16 | final TypeName type; 17 | final String keyValue; 18 | final boolean isPrimitive; 19 | 20 | Property(String humanName, ExecutableElement element) { 21 | this.methodName = element.getSimpleName().toString(); 22 | this.humanName = humanName; 23 | this.type = TypeName.get(element.getReturnType()); 24 | 25 | String definedKey = getKeyFromAnnotation(element); 26 | this.keyValue = definedKey == null ? humanName : definedKey; 27 | 28 | this.isPrimitive = element.getReturnType().getKind().isPrimitive(); 29 | } 30 | 31 | private String getKeyFromAnnotation(ExecutableElement element) { 32 | List annotations = element.getAnnotationMirrors(); 33 | for (AnnotationMirror annotation : annotations) { 34 | if (Param.class.getCanonicalName().equals( 35 | ((TypeElement) annotation.getAnnotationType().asElement()).getQualifiedName().toString())) { 36 | return (String) annotation.getElementValues().values().iterator().next().getValue(); 37 | } 38 | } 39 | return null; 40 | } 41 | 42 | static List readProperties(Map properties) { 43 | List values = new LinkedList<>(); 44 | for (Map.Entry entry : properties.entrySet()) { 45 | values.add(new Property(entry.getKey(), entry.getValue())); 46 | } 47 | return values; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /auto-value-querymap/src/test/java/com/oguzbabaoglu/auto/value/querymap/AutoValueQueryMapExtensionTest.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.auto.value.querymap; 2 | 3 | import com.google.auto.value.processor.AutoValueProcessor; 4 | import com.google.common.truth.Truth; 5 | import com.google.testing.compile.JavaFileObjects; 6 | 7 | import org.junit.Test; 8 | 9 | import javax.tools.JavaFileObject; 10 | 11 | import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 12 | 13 | public class AutoValueQueryMapExtensionTest { 14 | 15 | @Test public void testNoQueryMapMethod() throws Exception { 16 | JavaFileObject source = JavaFileObjects.forSourceString("test.Simple", 17 | "package test;\n" 18 | + "import com.google.auto.value.AutoValue;\n" 19 | + "@AutoValue\n" 20 | + "public abstract class Simple {\n" 21 | + " public abstract String name();\n" 22 | + " public abstract Long value();\n" 23 | + "}"); 24 | 25 | JavaFileObject expected = JavaFileObjects.forSourceString("test/AutoValue_Simple", 26 | "package test;\n" 27 | + "\n" 28 | + "import javax.annotation.Generated;\n" 29 | + "\n" 30 | + "@Generated(\"com.google.auto.value.processor.AutoValueProcessor\")\n" 31 | + "final class AutoValue_Simple extends Simple {\n" 32 | + "\n" 33 | + " private final String name;\n" 34 | + " private final Long value;\n" 35 | + "\n" 36 | + " AutoValue_Simple(\n" 37 | + " String name,\n" 38 | + " Long value) {\n" 39 | + " if (name == null) {\n" 40 | + " throw new NullPointerException(\"Null name\");\n" 41 | + " }\n" 42 | + " this.name = name;\n" 43 | + " if (value == null) {\n" 44 | + " throw new NullPointerException(\"Null value\");\n" 45 | + " }\n" 46 | + " this.value = value;\n" 47 | + " }\n" 48 | + "\n" 49 | + " @Override\n" 50 | + " public String name() {\n" 51 | + " return name;\n" 52 | + " }\n" 53 | + "\n" 54 | + " @Override\n" 55 | + " public Long value() {\n" 56 | + " return value;\n" 57 | + " }\n" 58 | + "\n" 59 | + " @Override\n" 60 | + " public String toString() {\n" 61 | + " return \"Simple{\"\n" 62 | + " + \"name=\" + name + \", \"\n" 63 | + " + \"value=\" + value\n" 64 | + " + \"}\";\n" 65 | + " }\n" 66 | + "\n" 67 | + " @Override\n" 68 | + " public boolean equals(Object o) {\n" 69 | + " if (o == this) {\n" 70 | + " return true;\n" 71 | + " }\n" 72 | + " if (o instanceof Simple) {\n" 73 | + " Simple that = (Simple) o;\n" 74 | + " return (this.name.equals(that.name()))\n" 75 | + " && (this.value.equals(that.value()));\n" 76 | + " }\n" 77 | + " return false;\n" 78 | + " }\n" 79 | + "\n" 80 | + " @Override\n" 81 | + " public int hashCode() {\n" 82 | + " int h = 1;\n" 83 | + " h *= 1000003;\n" 84 | + " h ^= this.name.hashCode();\n" 85 | + " h *= 1000003;\n" 86 | + " h ^= this.value.hashCode();\n" 87 | + " return h;\n" 88 | + " }\n" 89 | + "\n" 90 | + "}"); 91 | 92 | Truth.assert_().about(javaSource()) 93 | .that(source) 94 | .processedWith(new AutoValueProcessor()) 95 | .compilesWithoutError() 96 | .and() 97 | .generatesSources(expected); 98 | } 99 | 100 | @Test public void testWithoutAnnotations() throws Exception { 101 | JavaFileObject source = JavaFileObjects.forSourceString("test.Simple", 102 | "package test;\n" 103 | + "import java.util.Map;\n" 104 | + "import com.google.auto.value.AutoValue;\n" 105 | + "@AutoValue\n" 106 | + "public abstract class Simple {\n" 107 | + " public abstract String name();\n" 108 | + " public abstract Long value();\n" 109 | + " public abstract int primitive();\n" 110 | + " public abstract Map toQueryMap();\n" 111 | + "}"); 112 | 113 | JavaFileObject expected = JavaFileObjects.forSourceString("test/AutoValue_Simple", 114 | "package test;\n" 115 | + "\n" 116 | + "import java.lang.Long;\n" 117 | + "import java.lang.Override;\n" 118 | + "import java.lang.String;\n" 119 | + "import java.util.LinkedHashMap;\n" 120 | + "import java.util.Map;\n" 121 | + "\n" 122 | + "final class AutoValue_Simple extends $AutoValue_Simple {\n" 123 | + " AutoValue_Simple(String name, Long value, int primitive) {\n" 124 | + " super(name, value, primitive);\n" 125 | + " }\n" 126 | + "\n" 127 | + " @Override\n" 128 | + " public Map toQueryMap() {\n" 129 | + " Map queryMap = new LinkedHashMap<>();\n" 130 | + " if (name() != null) {\n" 131 | + " queryMap.put(\"name\", String.valueOf(name()));\n" 132 | + " }\n" 133 | + " if (value() != null) {\n" 134 | + " queryMap.put(\"value\", String.valueOf(value()));\n" 135 | + " }\n" 136 | + " queryMap.put(\"primitive\", String.valueOf(primitive()));\n" 137 | + " return queryMap;\n" 138 | + " }\n" 139 | + "}"); 140 | 141 | Truth.assert_().about(javaSource()) 142 | .that(source) 143 | .processedWith(new AutoValueProcessor()) 144 | .compilesWithoutError() 145 | .and() 146 | .generatesSources(expected); 147 | } 148 | 149 | @Test public void testWithAnnotations() throws Exception { 150 | JavaFileObject source = JavaFileObjects.forSourceString("test.Simple", 151 | "package test;\n" 152 | + "import java.util.Map;\n" 153 | + "import com.google.auto.value.AutoValue;\n" 154 | + "import com.oguzbabaoglu.auto.value.querymap.Param;\n" 155 | + "@AutoValue\n" 156 | + "public abstract class Simple {\n" 157 | + " @Param(\"nameKey\") public abstract String name();\n" 158 | + " @Param(\"valueKey\") public abstract Long value();\n" 159 | + " @Param(\"primitiveKey\") public abstract int primitive();\n" 160 | + " public abstract Map toQueryMap();\n" 161 | + "}"); 162 | 163 | JavaFileObject expected = JavaFileObjects.forSourceString("test/AutoValue_Simple", 164 | "package test;\n" 165 | + "\n" 166 | + "import java.lang.Long;\n" 167 | + "import java.lang.Override;\n" 168 | + "import java.lang.String;\n" 169 | + "import java.util.LinkedHashMap;\n" 170 | + "import java.util.Map;\n" 171 | + "\n" 172 | + "final class AutoValue_Simple extends $AutoValue_Simple {\n" 173 | + " AutoValue_Simple(String name, Long value, int primitive) {\n" 174 | + " super(name, value, primitive);\n" 175 | + " }\n" 176 | + "\n" 177 | + " @Override\n" 178 | + " public Map toQueryMap() {\n" 179 | + " Map queryMap = new LinkedHashMap<>();\n" 180 | + " if (name() != null) {\n" 181 | + " queryMap.put(\"nameKey\", String.valueOf(name()));\n" 182 | + " }\n" 183 | + " if (value() != null) {\n" 184 | + " queryMap.put(\"valueKey\", String.valueOf(value()));\n" 185 | + " }\n" 186 | + " queryMap.put(\"primitiveKey\", String.valueOf(primitive()));\n" 187 | + " return queryMap;\n" 188 | + " }\n" 189 | + "}"); 190 | 191 | Truth.assert_().about(javaSource()) 192 | .that(source) 193 | .processedWith(new AutoValueProcessor()) 194 | .compilesWithoutError() 195 | .and() 196 | .generatesSources(expected); 197 | } 198 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | maven { url 'https://plugins.gradle.org/m2/' } 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:2.1.3' 10 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.1' 11 | classpath 'net.ltgt.gradle:gradle-apt-plugin:0.8' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'net.ltgt.apt' 3 | 4 | repositories { 5 | mavenLocal() 6 | } 7 | 8 | dependencies { 9 | compileOnly 'com.google.auto.value:auto-value:1.3-rc1' 10 | apt 'com.google.auto.value:auto-value:1.3-rc1' 11 | apt 'com.oguzbabaoglu:auto-value-querymap:1.0' 12 | compileOnly 'com.oguzbabaoglu:auto-value-querymap:1.0' 13 | 14 | testCompile 'junit:junit:4.12' 15 | testCompile 'org.assertj:assertj-core:1.7.1' 16 | } -------------------------------------------------------------------------------- /example/src/main/java/com/oguzbabaoglu/example/DemoRequest.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.example; 2 | 3 | import com.google.auto.value.AutoValue; 4 | import com.oguzbabaoglu.auto.value.querymap.Param; 5 | 6 | import java.util.Map; 7 | 8 | @AutoValue 9 | public abstract class DemoRequest { 10 | 11 | @Param("customKey") public abstract int annotatedField(); 12 | public abstract String normalField(); 13 | @Nullable public abstract Object nullField(); 14 | 15 | public abstract Map toQueryMap(); 16 | 17 | public static DemoRequest create(int annotatedField, String normalField, Object nullField) { 18 | return new AutoValue_DemoRequest(annotatedField, normalField, nullField); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/src/main/java/com/oguzbabaoglu/example/Nullable.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.example; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.CLASS) 9 | @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE}) 10 | public @interface Nullable { 11 | } 12 | -------------------------------------------------------------------------------- /example/src/test/java/com/oguzbabaoglu/example/DemoRequestTest.java: -------------------------------------------------------------------------------- 1 | package com.oguzbabaoglu.example; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Map; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | public class DemoRequestTest { 10 | 11 | @Test public void testQueryMap() throws Exception { 12 | DemoRequest demoRequest = DemoRequest.create(2, "test", null); 13 | 14 | Map queryMap = demoRequest.toQueryMap(); 15 | assertThat(queryMap).hasSize(2); 16 | assertThat(queryMap.get("customKey")).isEqualTo("2"); 17 | assertThat(queryMap.get("normalField")).isEqualTo("test"); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | GROUP=com.oguzbabaoglu 2 | VERSION_NAME=1.0 3 | 4 | POM_DESCRIPTION=AutoValue extension to add toQueryMap() for Retrofit. 5 | 6 | POM_URL=https://github.com/oguzbabaoglu/auto-value-querymap/ 7 | POM_SCM_URL=https://github.com/oguzbabaoglu/auto-value-querymap/ 8 | POM_SCM_CONNECTION=scm:git:git://github.com/oguzbabaoglu/auto-value-querymap.git 9 | POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/oguzbabaoglu/auto-value-querymap.git 10 | 11 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 12 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 13 | POM_LICENCE_DIST=repo 14 | 15 | POM_DEVELOPER_ID=oguzbabaoglu 16 | POM_DEVELOPER_NAME=Oguz Babaoglu 17 | -------------------------------------------------------------------------------- /gradle/gradle-mvn-push.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Chris Banes 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | apply plugin: 'maven' 18 | apply plugin: 'com.jfrog.bintray' 19 | 20 | version = VERSION_NAME 21 | group = GROUP 22 | 23 | def bin_user = "" 24 | def bin_key = "" 25 | def oss_user = "" 26 | def oss_pass = "" 27 | try { 28 | bin_user = BINTRAY_USER 29 | bin_key = BINTRAY_KEY 30 | oss_user = OSS_USER 31 | oss_pass = OSS_PASS 32 | } catch (Exception ignored) { 33 | println 'Failed to find credentials. Maven deploy disabled' 34 | } 35 | 36 | afterEvaluate { project -> 37 | bintray { 38 | user = bin_user 39 | key = bin_key 40 | configurations = ['archives'] 41 | publish = true 42 | pkg { 43 | repo = 'maven' 44 | name = POM_ARTIFACT_ID 45 | desc = POM_DESCRIPTION 46 | websiteUrl = POM_URL 47 | issueTrackerUrl = POM_URL + 'issues' 48 | vcsUrl = POM_URL.substring(0, POM_URL.length() - 1) + '.git' 49 | licenses = ['Apache-2.0'] 50 | version { 51 | name = VERSION_NAME 52 | vcsTag = VERSION_NAME 53 | gpg { 54 | sign = true 55 | } 56 | mavenCentralSync { 57 | sync = true 58 | user = oss_user 59 | password = oss_pass 60 | } 61 | } 62 | } 63 | } 64 | 65 | if (project.getPlugins().hasPlugin('com.android.application') || 66 | project.getPlugins().hasPlugin('com.android.library')) { 67 | task install(type: Upload, dependsOn: assemble) { 68 | repositories.mavenInstaller { 69 | configuration = configurations.archives 70 | 71 | pom.groupId = GROUP 72 | pom.artifactId = POM_ARTIFACT_ID 73 | pom.version = VERSION_NAME 74 | 75 | pom.project { 76 | name POM_NAME 77 | packaging POM_PACKAGING 78 | description POM_DESCRIPTION 79 | url POM_URL 80 | 81 | scm { 82 | url POM_SCM_URL 83 | connection POM_SCM_CONNECTION 84 | developerConnection POM_SCM_DEV_CONNECTION 85 | } 86 | 87 | licenses { 88 | license { 89 | name POM_LICENCE_NAME 90 | url POM_LICENCE_URL 91 | distribution POM_LICENCE_DIST 92 | } 93 | } 94 | 95 | developers { 96 | developer { 97 | id POM_DEVELOPER_ID 98 | name POM_DEVELOPER_NAME 99 | } 100 | } 101 | } 102 | } 103 | } 104 | 105 | task androidJavadocs(type: Javadoc) { 106 | source = android.sourceSets.main.java.source 107 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 108 | } 109 | 110 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 111 | classifier = 'javadoc' 112 | from androidJavadocs.destinationDir 113 | } 114 | 115 | task androidSourcesJar(type: Jar) { 116 | classifier = 'sources' 117 | from android.sourceSets.main.java.source 118 | } 119 | } else { 120 | install { 121 | repositories.mavenInstaller { 122 | pom.groupId = GROUP 123 | pom.artifactId = POM_ARTIFACT_ID 124 | pom.version = VERSION_NAME 125 | 126 | pom.project { 127 | name POM_NAME 128 | packaging POM_PACKAGING 129 | description POM_DESCRIPTION 130 | url POM_URL 131 | 132 | scm { 133 | url POM_SCM_URL 134 | connection POM_SCM_CONNECTION 135 | developerConnection POM_SCM_DEV_CONNECTION 136 | } 137 | 138 | licenses { 139 | license { 140 | name POM_LICENCE_NAME 141 | url POM_LICENCE_URL 142 | distribution POM_LICENCE_DIST 143 | } 144 | } 145 | 146 | developers { 147 | developer { 148 | id POM_DEVELOPER_ID 149 | name POM_DEVELOPER_NAME 150 | } 151 | } 152 | } 153 | } 154 | } 155 | 156 | task sourcesJar(type: Jar, dependsOn:classes) { 157 | classifier = 'sources' 158 | from sourceSets.main.allSource 159 | } 160 | 161 | task javadocJar(type: Jar, dependsOn:javadoc) { 162 | classifier = 'javadoc' 163 | from javadoc.destinationDir 164 | } 165 | } 166 | 167 | if (JavaVersion.current().isJava8Compatible()) { 168 | allprojects { 169 | tasks.withType(Javadoc) { 170 | options.addStringOption('Xdoclint:none', '-quiet') 171 | } 172 | } 173 | } 174 | 175 | artifacts { 176 | if (project.getPlugins().hasPlugin('com.android.application') || 177 | project.getPlugins().hasPlugin('com.android.library')) { 178 | archives androidSourcesJar 179 | archives androidJavadocsJar 180 | } else { 181 | archives sourcesJar 182 | archives javadocJar 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oguzbabaoglu/auto-value-querymap/cd657b99bba3729821ba22c19ad892ba444d5341/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Aug 21 19:07:59 CEST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':auto-value-querymap' 2 | include ':example' 3 | --------------------------------------------------------------------------------