Browse Source

Builder for TypeView

type-view-builder
parent
commit
c6bc2fc3af
4 changed files with 148 additions and 1 deletions
  1. +16
    -0
      src/main/java/org/perfectable/introspection/type/ArrayTypeView.java
  2. +58
    -1
      src/main/java/org/perfectable/introspection/type/ParameterizedTypeView.java
  3. +37
    -0
      src/main/java/org/perfectable/introspection/type/TypeVariableView.java
  4. +37
    -0
      src/main/java/org/perfectable/introspection/type/WildcardTypeView.java

+ 16
- 0
src/main/java/org/perfectable/introspection/type/ArrayTypeView.java View File

@@ -16,6 +16,22 @@ public final class ArrayTypeView extends AbstractTypeView<GenericArrayType> {
super(type);
}

public static ArrayTypeView build(TypeView componentType) {
return build(componentType.unwrap());
}

public static ArrayTypeView build(Type componentType) {
return new ArrayTypeView(buildUnwrapped(componentType));
}

public static GenericArrayType buildUnwrapped(TypeView componentType) {
return buildUnwrapped(componentType.unwrap());
}

public static GenericArrayType buildUnwrapped(Type componentType) {
return new SyntheticGenericArrayType(componentType);
}

/**
* Creates view over provided type.
*


+ 58
- 1
src/main/java/org/perfectable/introspection/type/ParameterizedTypeView.java View File

@@ -6,16 +6,21 @@ import java.lang.reflect.TypeVariable;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import kotlin.annotations.jvm.ReadOnly;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

/**
@@ -40,6 +45,10 @@ public final class ParameterizedTypeView extends AbstractTypeView<ParameterizedT
return new ParameterizedTypeView(parameterized);
}

public static Builder builder(Class<?> baseType) {
return new Builder(baseType);
}

@Override
public Class<?> erasure() {
return (Class<?>) type.getRawType();
@@ -343,4 +352,52 @@ public final class ParameterizedTypeView extends AbstractTypeView<ParameterizedT
}
return builder.build();
}

public static final class Builder {
private final Class<?> baseType;

@Nullable
private Type ownerType;

private Type[] typeArguments;

Builder(Class<?> baseType) {
this.baseType = baseType;
typeArguments = baseType.getTypeParameters().clone();
}

@CanIgnoreReturnValue
public Builder withOwner(Type newOwnerType) {
ownerType = newOwnerType;
return this;
}

@CanIgnoreReturnValue
public Builder withSubstitution(String parameterName, Type substitute) {
TypeVariable<? extends Class<?>>[] typeParameters = baseType.getTypeParameters();
int parameterNumber = IntStream.range(0, typeParameters.length)
.filter(i -> typeParameters[i].getName().equals(parameterName))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No parameter with name " + parameterName));
return withSubstitution(parameterNumber, substitute);
}

@CanIgnoreReturnValue
public Builder withSubstitution(int parameterNumber, Type substitute) {
checkArgument(parameterNumber > 0, "Parameter number must be non-negative");
checkArgument(parameterNumber < typeArguments.length, "Type %s has no parameter %s", baseType, parameterNumber);
typeArguments[parameterNumber] = substitute;
return this;
}

public ParameterizedTypeView build() {
ParameterizedType parameterizedType = buildUnwrapped();
return new ParameterizedTypeView(parameterizedType);
}

@Nonnull
public ParameterizedType buildUnwrapped() {
return new SyntheticParameterizedType(baseType, ownerType, typeArguments);
}
}
}

+ 37
- 0
src/main/java/org/perfectable/introspection/type/TypeVariableView.java View File

@@ -4,9 +4,13 @@ import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.google.errorprone.annotations.CanIgnoreReturnValue;

/**
* {@link TypeView} that handles {@link TypeVariable}.
*
@@ -28,6 +32,10 @@ public final class TypeVariableView<D extends GenericDeclaration> extends Abstra
return new TypeVariableView<>(variable);
}

public static <D extends GenericDeclaration> Builder<D> builder(String name, D declaration) {
return new Builder(name, declaration);
}

@Override
public Class<?> erasure() {
Type[] bounds = type.getBounds();
@@ -191,4 +199,33 @@ public final class TypeVariableView<D extends GenericDeclaration> extends Abstra
return Stream.of(type.getBounds())
.map(TypeView::of);
}

public static final class Builder<D extends GenericDeclaration> {
private final D declaration;
private final String name;

private final Set<Type> bounds = new HashSet<>();

Builder(String name, D declaration) {
this.name = name;
this.declaration = declaration;
}

@CanIgnoreReturnValue
public Builder withUpperBound(Type addedBound) {
bounds.add(addedBound);
return this;
}

public TypeVariableView<D> build() {
return new TypeVariableView<>(buildUnwrapped());
}

public TypeVariable<D> buildUnwrapped() {
Type[] finalBounds = bounds.toArray(new Type[0]);
return new SyntheticTypeVariable<>(name, declaration, finalBounds);
}


}
}

+ 37
- 0
src/main/java/org/perfectable/introspection/type/WildcardTypeView.java View File

@@ -6,10 +6,13 @@ import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import kotlin.annotations.jvm.ReadOnly;

/**
@@ -30,6 +33,10 @@ public final class WildcardTypeView extends AbstractTypeView<WildcardType> {
return new WildcardTypeView(wildcard);
}

public static Builder builder() {
return new Builder();
}

@Override
public Class<?> erasure() {
Type[] bounds = type.getUpperBounds();
@@ -237,4 +244,34 @@ public final class WildcardTypeView extends AbstractTypeView<WildcardType> {
private static Type[] removeObjectClass(Type[] upperBounds) {
return Stream.of(upperBounds).filter(bound -> !Object.class.equals(bound)).toArray(Type[]::new);
}

public static final class Builder {
private final Set<Type> lowerBounds = new HashSet<>();
private final Set<Type> upperBounds = new HashSet<>();

Builder() {
}

@CanIgnoreReturnValue
public Builder withLowerBound(Type addedBound) {
lowerBounds.add(addedBound);
return this;
}

@CanIgnoreReturnValue
public Builder withUpperBound(Type addedBound) {
upperBounds.add(addedBound);
return this;
}

public WildcardTypeView build() {
return new WildcardTypeView(buildUnwrapped());
}

public WildcardType buildUnwrapped() {
Type[] finalLowerBounds = lowerBounds.toArray(new Type[0]);
Type[] finalUpperBounds = upperBounds.toArray(new Type[0]);
return new SyntheticWildcardType(finalLowerBounds, finalUpperBounds);
}
}
}

Loading…
Cancel
Save