
br.com.objectos.code.CodeResources Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2016 Objectos, Fábrica de Software LTDA.
*
* 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 br.com.objectos.code;
import java.lang.annotation.Annotation;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.tools.JavaFileObject;
import br.com.objectos.core.util.ArrayListMultimap;
import br.com.objectos.core.util.ImmutableList;
import br.com.objectos.core.util.ImmutableMap;
import br.com.objectos.core.util.Multimap;
import com.google.common.truth.Truth;
import com.google.testing.compile.JavaFileObjects;
import com.google.testing.compile.JavaSourcesSubjectFactory;
/**
* @author [email protected] (Marcio Endo)
*/
public class CodeResources {
private final List methodInfoList;
private final List packageInfoList;
private final Map typeInfoMap;
private CodeResources(List methodInfoList,
List packageInfoList,
Map typeInfoMap) {
this.methodInfoList = methodInfoList;
this.packageInfoList = packageInfoList;
this.typeInfoMap = typeInfoMap;
}
public static CodeResourcesBuilder builder() {
return new Builder();
}
public List methodInfoList() {
return methodInfoList;
}
public PackageInfo packageInfo(String qualifiedName) {
return packageInfoList.stream()
.filter(pkg -> pkg.name().equals(qualifiedName))
.findFirst()
.orElseThrow(() -> new NoSuchElementException(qualifiedName));
}
public List packageInfoList() {
return packageInfoList;
}
public TypeInfo typeInfo(String qualifiedName) {
TypeInfo typeInfo = typeInfoMap.get(qualifiedName);
if (typeInfo == null) {
throw new NoSuchElementException(qualifiedName);
}
return typeInfo;
}
@FunctionalInterface
public static interface MethodInfoListener {
void onMethodInfo(MethodInfo methodInfo);
}
@FunctionalInterface
public static interface PackageInfoListener {
void onPackageInfo(PackageInfo packageInfo);
}
@FunctionalInterface
public static interface TypeInfoListener {
void onTypeInfo(TypeInfo typeInfo);
}
private static class Builder
extends AbstractAnnotationProcessor
implements
CodeResourcesBuilder,
CodeResourcesBuilder.AddAnnotationType,
CodeResourcesBuilder.AddListener,
CodeResourcesBuilder.AddResource,
CodeResourcesBuilder.AddIsSubtype {
private final Set annotationTypeSet = new HashSet<>();
private final Set methodInfoListenerSet = new LinkedHashSet<>(2);
private final Set packageInfoListenerSet = new LinkedHashSet<>(2);
private final Set typeInfoListenerSet = new LinkedHashSet<>(2);
private final List resourceNameList = new ArrayList<>();
private final ImmutableList.Builder methodInfoList = ImmutableList.builder();
private final ImmutableList.Builder packageInfoList = ImmutableList.builder();
private final Multimap, String> subtypeMap = ArrayListMultimap.create();
private final ImmutableMap.Builder typeInfoMap = ImmutableMap.builder();
@Override
public AddAnnotationType addAnnotationType(Class extends Annotation> annotationType) {
Objects.requireNonNull(annotationType);
annotationTypeSet.add(annotationType.getName());
return this;
}
@Override
public AddIsSubtype addSubType(Class> superType, Class> subType) {
TypeVariable>[] typeParameters = subType.getTypeParameters();
int length = typeParameters.length;
switch (length) {
case 0:
return addSubType(superType, subType.getCanonicalName());
case 1:
return addSubType(superType, subType.getCanonicalName() + ">");
default:
StringBuilder rawName = new StringBuilder(subType.getCanonicalName());
rawName.append("");
for (int i = 1; i < length; i++) {
rawName.append(",?");
}
rawName.append('>');
return addSubType(superType, rawName.toString());
}
}
@Override
public AddIsSubtype addSubType(Class> superType, String subTypeName) {
Objects.requireNonNull(superType);
Objects.requireNonNull(subTypeName);
subtypeMap.put(superType, subTypeName);
return this;
}
@Override
public AddListener addMethodInfoListener(MethodInfoListener listener) {
Objects.requireNonNull(listener);
methodInfoListenerSet.add(listener);
return this;
}
@Override
public AddListener addPackageInfoListener(PackageInfoListener listener) {
Objects.requireNonNull(listener);
packageInfoListenerSet.add(listener);
return this;
}
@Override
public AddListener addTypeInfoListener(TypeInfoListener listener) {
Objects.requireNonNull(listener);
typeInfoListenerSet.add(listener);
return this;
}
@Override
public AddResource addResource(String resourceName) {
Objects.requireNonNull(resourceName);
String name = resourceName.startsWith("/")
? resourceName.substring(1)
: resourceName;
resourceNameList.add(name);
return this;
}
@Override
public CodeResources build() {
List objectList = resourceNameList.stream()
.map(name -> JavaFileObjects.forResource(name))
.collect(Collectors.toList());
Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
.that(objectList)
.processedWith(this)
.compilesWithoutError();
return new CodeResources(
methodInfoList.build(),
packageInfoList.build(),
typeInfoMap.build());
}
@Override
protected Configuration configuration() {
return Configuration.builder()
.addAllAnnotationTypesByName(annotationTypeSet)
.addMethodInfoArtifactGenerator(this::methodInfo)
.addPackageInfoArtifactGenerator(this::packageInfo)
.addTypeInfoArtifactGenerator(this::typeInfo)
.listener(new TestingProcessorListener(subtypeMap))
.build();
}
private Artifact methodInfo(TypeInfo typeInfo, MethodInfo methodInfo) {
methodInfoList.add(methodInfo);
methodInfoListenerSet.forEach(listener -> listener.onMethodInfo(methodInfo));
return Artifact.empty();
}
private Artifact packageInfo(PackageInfo packageInfo) {
packageInfoList.add(ForwardingPackageInfo.of(packageInfo));
packageInfoListenerSet.forEach(listener -> listener.onPackageInfo(packageInfo));
return Artifact.empty();
}
private Artifact typeInfo(TypeInfo typeInfo) {
typeInfoMap.put(typeInfo.qualifiedName(), typeInfo);
typeInfoListenerSet.forEach(listener -> listener.onTypeInfo(typeInfo));
return Artifact.empty();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy