io.requery.processor.AndroidParcelableExtension Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of requery-processor Show documentation
Show all versions of requery-processor Show documentation
A light but powerful object mapper and SQL generator for Java/Android
/*
* Copyright 2016 requery.io
*
* 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 io.requery.processor;
import com.squareup.javapoet.ArrayTypeName;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Types;
/**
* Handler for Android's Parcelable objects. If the target entity object implements Parcelable but
* doesn't provide it's own implementation than a implementation will be provided in the generated
* entity using {@link io.requery.android.EntityParceler}
*
* @author Nikhil Purushe
*/
@SuppressWarnings("JavadocReference")
class AndroidParcelableExtension implements TypeGenerationExtension {
private static final String PACKAGE_ANDROID_OS = "android.os";
private static final String PACKAGE_PARCELER = "io.requery.android";
private final Types types;
AndroidParcelableExtension(Types types) {
this.types = types;
}
@Override
public void generate(EntityDescriptor entity, TypeSpec.Builder builder) {
// if not parcelable or the class implements itself don't implement it
TypeElement typeElement = entity.element();
if (entity.isImmutable() ||
!Mirrors.isInstance(types, typeElement, PACKAGE_ANDROID_OS + ".Parcelable") ||
Mirrors.overridesMethod(types, typeElement, "writeToParcel")) {
return;
}
ClassName className = ClassName.bestGuess(entity.typeName().toString());
// implement the parcelable interface
TypeName creatorType = ParameterizedTypeName.get(
ClassName.get(PACKAGE_ANDROID_OS, "Parcelable.Creator"), className);
ClassName parcelName = ClassName.get(PACKAGE_ANDROID_OS, "Parcel");
ClassName parcelableName = ClassName.get(PACKAGE_ANDROID_OS, "Parcelable");
builder.addSuperinterface(parcelableName);
TypeSpec.Builder creatorBuilder = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(creatorType)
.addMethod(CodeGeneration.overridePublicMethod("createFromParcel")
.addParameter(ParameterSpec.builder(parcelName, "source").build())
.addStatement("return PARCELER.readFromParcel(source)")
.returns(className).build())
.addMethod(CodeGeneration.overridePublicMethod("newArray")
.addParameter(TypeName.INT, "size")
.addStatement("return new $T[size]", className)
.returns(ArrayTypeName.of(className)).build());
builder.addField(
FieldSpec.builder(creatorType, "CREATOR",
Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.initializer("$L", creatorBuilder.build()).build());
builder.addMethod(
CodeGeneration.overridePublicMethod("describeContents")
.returns(TypeName.INT)
.addStatement("return 0").build());
builder.addMethod(
CodeGeneration.overridePublicMethod("writeToParcel")
.returns(TypeName.VOID)
.addParameter(parcelName, "dest")
.addParameter(TypeName.INT, "flags")
.addStatement("PARCELER.writeToParcel(this, dest)").build());
// add the parceler instance which uses the proxy to parcel the field data
TypeName parcelerType = ParameterizedTypeName.get(
ClassName.get(PACKAGE_PARCELER, "EntityParceler"), className);
builder.addField(
FieldSpec.builder(parcelerType, "PARCELER",
Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
.initializer("new $T($L)", parcelerType,
EntityGenerator.TYPE_NAME).build());
}
}