/*
* Copyright 2016 Victor Albertos
*
* 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.rx_cache2;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import io.reactivex.Observable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import javax.lang.model.element.Modifier;
final class BrewJavaFile {
JavaFile from(ProvidersClass providersClass) throws IOException {
List<MethodSpec> methodSpecs = new ArrayList<>();
for (ProvidersClass.Method method : providersClass.methods) {
methodSpecs.add(getActionProvider(providersClass.className, method));
}
TypeSpec typeSpec = classProviders(providersClass.className, methodSpecs);
return JavaFile.builder(providersClass.className.packageName(), typeSpec)
.build();
}
private MethodSpec getActionProvider(ClassName providersClassName, ProvidersClass.Method method) {
String methodName = method.name;
TypeName list = ClassName.get(method.enclosingTypeObservable);
TypeName enclosingTypeList = ClassName
.get(method.enclosingTypeObservable.getTypeArguments().get(0));
String enclosingTypeListName = enclosingTypeList.toString();
ParameterizedTypeName action =
ParameterizedTypeName.get(ClassName.get(ActionsList.class), enclosingTypeList);
ParameterizedTypeName evict =
ParameterizedTypeName.get(ClassName.get(ActionsList.Evict.class), enclosingTypeList);
ParameterizedTypeName arrayList =
ParameterizedTypeName.get(ClassName.get(ArrayList.class), enclosingTypeList);
ParameterizedTypeName observable =
ParameterizedTypeName.get(ClassName.get(Observable.class), list);
ParameterSpec rxProvidersInstance = ParameterSpec
.builder(providersClassName, "proxy")
.addModifiers(Modifier.FINAL)
.build();
MethodSpec.Builder builder = MethodSpec.methodBuilder(methodName)
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(rxProvidersInstance)
.returns(action);
if (method.hasDynamicKey) {
builder.addParameter(DynamicKey.class, "dynamicKey", Modifier.FINAL);
} else if (method.hasDynamicKeyGroup) {
builder.addParameter(DynamicKeyGroup.class, "dynamicKeyGroup", Modifier.FINAL);
}
builder.beginControlFlow("$T evict = new $T()", evict, evict)
.beginControlFlow("@Override public $T call($T elements)", observable, observable);
if (method.hasDynamicKey) {
setReturnEvictForEvictDynamicKey(builder, methodName);
} else if (method.hasDynamicKeyGroup) {
setReturnEvictForEvictDynamicKeyGroup(builder, methodName);
} else {
setReturnEvictForEvictProvider(builder, methodName);
}
builder.endControlFlow().endControlFlow(";");
if (method.hasDynamicKey) {
setCacheForEvictDynamicKey(builder, observable, arrayList, methodName, enclosingTypeListName);
} else if (method.hasDynamicKeyGroup) {
setCacheForEvictDynamicKeyGroup(builder, observable, arrayList, methodName, enclosingTypeListName);
} else {
setCacheForEvictProvider(builder, observable, arrayList, methodName, enclosingTypeListName);
}
builder.addStatement("return ActionsList.with(evict, oCache)");
return builder.build();
}
private void setReturnEvictForEvictProvider(MethodSpec.Builder builder, String methodName) {
builder.addStatement("return proxy."+methodName+"(elements, new $T(true))", EvictProvider.class);
}
private void setReturnEvictForEvictDynamicKey(MethodSpec.Builder builder, String methodName) {
builder.addStatement("return proxy."+methodName+"(elements, dynamicKey, new $T(true))", EvictDynamicKey.class);
}
private void setReturnEvictForEvictDynamicKeyGroup(MethodSpec.Builder builder, String methodName) {
builder.addStatement("return proxy."+methodName+"(elements, dynamicKeyGroup, new $T(true))", EvictDynamicKeyGroup.class);
}
private void setCacheForEvictProvider(MethodSpec.Builder builder, ParameterizedTypeName observable, ParameterizedTypeName arrayList, String methodName, String typeName) {
builder.addStatement("$T oCache = proxy."+methodName+"(Observable.<List<"+typeName+">>just(new $T()), new EvictProvider(false))", observable, arrayList);
}
private void setCacheForEvictDynamicKey(MethodSpec.Builder builder, ParameterizedTypeName observable, ParameterizedTypeName arrayList, String methodName, String typeName) {
builder.addStatement("$T oCache = proxy."+methodName+"(Observable.<List<"+typeName+">>just(new $T()), dynamicKey, new EvictDynamicKey(false))", observable, arrayList);
}
private void setCacheForEvictDynamicKeyGroup(MethodSpec.Builder builder, ParameterizedTypeName observable, ParameterizedTypeName arrayList, String methodName, String typeName) {
builder.addStatement("$T oCache = proxy."+methodName+"(Observable.<List<"+typeName+">>just(new $T()), dynamicKeyGroup, new EvictDynamicKeyGroup(false))", observable, arrayList);
}
private TypeSpec classProviders(ClassName className, List<MethodSpec> methodSpecs) {
return TypeSpec.classBuilder(className.simpleName() + "Actionable")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(AnnotationSpec.builder(Generated.class)
.addMember("value", "$S", ActionsProcessor.class.getCanonicalName())
.addMember("comments", "$S", "Generated code from RxCache. Don't modify. Or modify. It doesn't matter.")
.build())
.addMethods(methodSpecs)
.build();
}
}