package restx.common;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ObjectArrays;
import com.google.common.collect.Sets;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Created by fcamblor on 13/05/16.
*/
public enum AggregateType {
ITERABLE() {
@Override
public boolean isApplicableTo(String fqcn) {
return matchesParameterizedFQCN(Iterable.class, fqcn);
}
@Override
public <T> Object createFrom(List values, Class<T> itemClass) {
return values;
}
},
LIST() {
@Override
public boolean isApplicableTo(String fqcn) {
return matchesParameterizedFQCN(List.class, fqcn);
}
@Override
public <T> Object createFrom(List values, Class<T> itemClass) {
return values;
}
},
SET() {
@Override
public boolean isApplicableTo(String fqcn) {
return matchesParameterizedFQCN(Set.class, fqcn);
}
@Override
public <T> Object createFrom(List values, Class<T> itemClass) {
return Sets.newHashSet(values);
}
},
COLLECTION() {
@Override
public boolean isApplicableTo(String fqcn) {
return matchesParameterizedFQCN(Collection.class, fqcn);
}
@Override
public <T> Object createFrom(List values, Class<T> itemClass) {
return values;
}
},
ARRAY() {
@Override
public boolean isApplicableTo(String fqcn) {
return fqcn.endsWith("[]");
}
@Override
public <T> Object createFrom(List values, Class<T> itemClass) {
return values.toArray(ObjectArrays.newArray(itemClass, values.size()));
}
};
public static Optional<AggregateType> fromType(String fqcn) {
for(AggregateType aggregateType : values()){
if(aggregateType.isApplicableTo(fqcn)) {
return Optional.of(aggregateType);
}
}
return Optional.absent();
}
public abstract boolean isApplicableTo(String fqcn);
public abstract <T> Object createFrom(List values, Class<T> itemClass);
protected static boolean matchesParameterizedFQCN(Class c, String fqcn) {
return fqcn.startsWith(c.getCanonicalName());
}
public static boolean isAggregate(String fqcn) {
return fromType(fqcn).isPresent();
}
public static Class aggregatedTypeOf(Type type) {
if(type instanceof ParameterizedType) {
return (Class)((ParameterizedType)type).getActualTypeArguments()[0];
} else if(type instanceof Class && ((Class)type).isArray()){
return ((Class)type).getComponentType();
} else {
throw new IllegalArgumentException("Call to aggregatedTypeOf() is not supported for type : "+type);
}
}
}