Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#109 decouple specimen from specimen type #110

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/main/java/com/github/nylle/javafixture/ISpecimen.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@ public interface ISpecimen<T> {

T create(final CustomizationContext customizationContext, Annotation[] annotations);

interface IMeta {

<T> boolean supports(SpecimenType<T> type);

<T> ISpecimen<T> create(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory);
}
}

66 changes: 20 additions & 46 deletions src/main/java/com/github/nylle/javafixture/SpecimenFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,65 +13,39 @@
import com.github.nylle.javafixture.specimen.SpecialSpecimen;
import com.github.nylle.javafixture.specimen.TimeSpecimen;

import java.util.List;

public class SpecimenFactory {
private final static List<ISpecimen.IMeta> specimenCandidates = List.of(
SpecialSpecimen.meta(),
PrimitiveSpecimen.meta(),
EnumSpecimen.meta(),
CollectionSpecimen.meta(),
MapSpecimen.meta(),
GenericSpecimen.meta(),
ArraySpecimen.meta(),
TimeSpecimen.meta(),
InterfaceSpecimen.meta(),
AbstractSpecimen.meta()
);

private final Context context;

public SpecimenFactory(Context context) {
this.context = context;
}

public <T> ISpecimen<T> build(final SpecimenType<T> type) {
public <T> ISpecimen<T> build(SpecimenType<T> type) {

if (context.isCached(type)) {
return new PredefinedSpecimen<>(type, context);
}

if (type.isPrimitive() || type.isBoxed() || type.asClass() == String.class) {
return new PrimitiveSpecimen<>(type, context);
}

if (type.isEnum()) {
return new EnumSpecimen<>(type);
}

if (type.isCollection()) {
return new CollectionSpecimen<>(type, context, this);
}

if (type.isMap()) {
return new MapSpecimen<>(type, context, this);
}

if (type.isParameterized() && !type.isInterface() && !type.isAbstract()) {
return new GenericSpecimen<>(type, context, this);
}

if (type.isParameterized() && (type.isInterface() || type.isAbstract())) {
return new GenericSpecimen<>(type, context, this);
}

if (type.isArray()) {
return new ArraySpecimen<>(type, context, this);
}

if (type.isTimeType()) {
return new TimeSpecimen<>(type, context);
}

if (type.isInterface()) {
return new InterfaceSpecimen<>(type, context, this);
}

if (type.isAbstract()) {
return new AbstractSpecimen<>(type, context, this);
}

if (type.isSpecialType()) {
return new SpecialSpecimen<>(type, context);
}

return new ObjectSpecimen<>(type, context, this);
return specimenCandidates.stream()
.filter(x -> x.supports(type))
.map(x -> x.create(type, context, this))
.findFirst()
.orElseGet(() -> new ObjectSpecimen<>(type, context, this));
}
}

48 changes: 0 additions & 48 deletions src/main/java/com/github/nylle/javafixture/SpecimenType.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.time.ZoneId;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAmount;
import java.util.Collection;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -143,50 +139,6 @@ public boolean isMap() {
return Map.class.isAssignableFrom(asClass());
}

public boolean isTimeType() {
if (Temporal.class.isAssignableFrom(asClass())) {
return true;
}

if (TemporalAdjuster.class.isAssignableFrom(asClass())) {
return true;
}

if (TemporalAmount.class.isAssignableFrom(asClass())) {
return true;
}

if (asClass().equals(ZoneId.class)) {
return true;
}

if (asClass().equals(java.util.Date.class)) {
return true;
}

if (asClass().equals(java.sql.Date.class)) {
return true;
}

return false;
}

public boolean isSpecialType() {
if (asClass().equals(java.math.BigInteger.class)) {
return true;
}
if (asClass().equals(java.math.BigDecimal.class)) {
return true;
}
if (asClass().equals(java.io.File.class)) {
return true;
}
if (asClass().equals(java.net.URI.class)) {
return true;
}
return false;
}

public boolean isPrimitive() {
return asClass().isPrimitive();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class AbstractSpecimen<T> implements ISpecimen<T> {
private final SpecimenFactory specimenFactory;
private final InstanceFactory instanceFactory;

public AbstractSpecimen(final SpecimenType<T> type, final Context context, final SpecimenFactory specimenFactory) {
public AbstractSpecimen(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {

if (type == null) {
throw new IllegalArgumentException("type: null");
Expand All @@ -34,7 +34,7 @@ public AbstractSpecimen(final SpecimenType<T> type, final Context context, final
throw new IllegalArgumentException("specimenFactory: null");
}

if (!type.isAbstract() || type.isMap() || type.isCollection()) {
if (!supportsType(type)) {
throw new IllegalArgumentException("type: " + type.getName());
}

Expand All @@ -44,6 +44,24 @@ public AbstractSpecimen(final SpecimenType<T> type, final Context context, final
this.instanceFactory = new InstanceFactory(specimenFactory);
}

public static <T> boolean supportsType(SpecimenType<T> type) {
return type.isAbstract() && !type.isMap() && !type.isCollection();
}

public static IMeta meta() {
return new IMeta() {
@Override
public <T> boolean supports(SpecimenType<T> type) {
return supportsType(type);
}

@Override
public <T> ISpecimen<T> create(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {
return new AbstractSpecimen<>(type, context, specimenFactory);
}
};
}

@Override
public T create(final CustomizationContext customizationContext, Annotation[] annotations) {
if (context.isCached(type)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class ArraySpecimen<T> implements ISpecimen<T> {
private final Context context;
private final SpecimenFactory specimenFactory;

public ArraySpecimen(final SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {
public ArraySpecimen(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {
if (type == null) {
throw new IllegalArgumentException("type: null");
}
Expand All @@ -28,7 +28,7 @@ public ArraySpecimen(final SpecimenType<T> type, Context context, SpecimenFactor
throw new IllegalArgumentException("specimenFactory: null");
}

if (!type.isArray()) {
if (!supportsType(type)) {
throw new IllegalArgumentException("type: " + type.getName());
}

Expand All @@ -37,8 +37,26 @@ public ArraySpecimen(final SpecimenType<T> type, Context context, SpecimenFactor
this.specimenFactory = specimenFactory;
}

public static <T> boolean supportsType(SpecimenType<T> type) {
return type.isArray();
}

public static IMeta meta() {
return new IMeta() {
@Override
public <T> boolean supports(SpecimenType<T> type) {
return supportsType(type);
}

@Override
public <T> ISpecimen<T> create(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {
return new ArraySpecimen<>(type, context, specimenFactory);
}
};
}

@Override
public T create(final CustomizationContext customizationContext, Annotation[] annotations) {
public T create(CustomizationContext customizationContext, Annotation[] annotations) {
if (context.isCached(type)) {
return context.cached(type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class CollectionSpecimen<T, G> implements ISpecimen<T> {
private ISpecimen<G> specimen;
private final InstanceFactory instanceFactory;

public CollectionSpecimen(final SpecimenType<T> type, final Context context, final SpecimenFactory specimenFactory) {
public CollectionSpecimen(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {

if (type == null) {
throw new IllegalArgumentException("type: null");
Expand All @@ -35,7 +35,7 @@ public CollectionSpecimen(final SpecimenType<T> type, final Context context, fin
throw new IllegalArgumentException("specimenFactory: null");
}

if (!type.isCollection()) {
if (!supportsType(type)) {
throw new IllegalArgumentException("type: " + type.getName());
}

Expand All @@ -48,6 +48,24 @@ public CollectionSpecimen(final SpecimenType<T> type, final Context context, fin
this.instanceFactory = new InstanceFactory(specimenFactory);
}

public static <T> boolean supportsType(SpecimenType<T> type) {
return type.isCollection();
}

public static IMeta meta() {
return new IMeta() {
@Override
public <T> boolean supports(SpecimenType<T> type) {
return supportsType(type);
}

@Override
public <T> ISpecimen<T> create(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {
return new CollectionSpecimen<>(type, context, specimenFactory);
}
};
}

@Override
public T create(final CustomizationContext customizationContext, Annotation[] annotations) {
if (context.isCached(type)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.github.nylle.javafixture.specimen;

import com.github.nylle.javafixture.Context;
import com.github.nylle.javafixture.CustomizationContext;
import com.github.nylle.javafixture.ISpecimen;
import com.github.nylle.javafixture.SpecimenFactory;
import com.github.nylle.javafixture.SpecimenType;

import java.lang.annotation.Annotation;
Expand All @@ -12,20 +14,38 @@ public class EnumSpecimen<T> implements ISpecimen<T> {
private final SpecimenType<T> type;
private final Random random;

public EnumSpecimen(final SpecimenType<T> type) {
public EnumSpecimen(SpecimenType<T> type) {

if (type == null) {
throw new IllegalArgumentException("type: null");
}

if (!type.isEnum()) {
if (!supportsType(type)) {
throw new IllegalArgumentException("type: " + type.getName());
}

this.type = type;
this.random = new Random();
}

public static <T> boolean supportsType(SpecimenType<T> type) {
return type.isEnum();
}

public static IMeta meta() {
return new IMeta() {
@Override
public <T> boolean supports(SpecimenType<T> type) {
return supportsType(type);
}

@Override
public <T> ISpecimen<T> create(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {
return new EnumSpecimen<>(type);
}
};
}

@Override
public T create(CustomizationContext customizationContext, Annotation[] annotations) {
return type.getEnumConstants()[random.nextInt(type.getEnumConstants().length)];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,12 @@ public GenericSpecimen(SpecimenType<T> type, Context context, SpecimenFactory sp
throw new IllegalArgumentException("context: null");
}

if (specimenFactory == null) {
throw new IllegalArgumentException("specimenFactory: null");
}

if (!type.isParameterized()) {
if (!supportsType(type)) {
throw new IllegalArgumentException("type: " + type.getName());
}

if (type.isCollection() || type.isMap()) {
throw new IllegalArgumentException("type: " + type.getName());
if (specimenFactory == null) {
throw new IllegalArgumentException("specimenFactory: null");
}

this.type = type;
Expand All @@ -50,6 +46,24 @@ public GenericSpecimen(SpecimenType<T> type, Context context, SpecimenFactory sp
this.specimens = type.getTypeParameterNamesAndTypes(x -> specimenFactory.build(x));
}

public static <T> boolean supportsType(SpecimenType<T> type) {
return type.isParameterized() && !type.isCollection() && !type.isMap();
}

public static IMeta meta() {
return new IMeta() {
@Override
public <T> boolean supports(SpecimenType<T> type) {
return supportsType(type);
}

@Override
public <T> ISpecimen<T> create(SpecimenType<T> type, Context context, SpecimenFactory specimenFactory) {
return new GenericSpecimen<>(type, context, specimenFactory);
}
};
}

@Override
public T create(CustomizationContext customizationContext, Annotation[] annotations) {
if (type.asClass().equals(Class.class)) {
Expand All @@ -61,6 +75,7 @@ public T create(CustomizationContext customizationContext, Annotation[] annotati
}

if (type.isInterface()) {
//TODO: shouldn't this be covered by InterfaceSpecimen?
return (T) instanceFactory.proxy(type, specimens);
}

Expand Down
Loading
Loading