use of org.immutables.value.processor.encode.Type in project immutables by immutables.
the class CriteriaModelProcessorTest method assertAttribute.
private void assertAttribute(String name, String expected) {
ValueAttribute attribute = findAttribute(name);
final Type element = attribute.criteria().matcher().matcherType();
final UnaryOperator<String> stripFn = str -> str.replaceAll("\\s+", "");
assertEquals(String.format("for attribute %s", name), stripFn.apply(expected), stripFn.apply(element.toString()));
}
use of org.immutables.value.processor.encode.Type in project immutables by immutables.
the class FromSupertypesModel method isEligibleFromType.
private boolean isEligibleFromType(TypeElement typeElement, ValueAttribute attr) {
@Nullable ExecutableElement accessor = findMethod(typeElement, attr.names.get);
if (accessor == null) {
// it can be now as we've changed upper loop
return false;
}
if (!typeElement.getTypeParameters().isEmpty()) {
TypeElement containingTypeElement = (TypeElement) attr.containingType.originalElement();
// bail early if types don't both have 1 parameter
if ((typeElement.getTypeParameters().size() != 1) || (containingTypeElement.getTypeParameters().size() != 1)) {
return false;
}
// ensure this is a direct ancestor
if (!isDirectAncestor(typeElement, containingTypeElement)) {
return false;
}
// confirm bounds match
for (int i = 0; i < typeElement.getTypeParameters().size(); i++) {
if (!boundsMatch(typeElement.getTypeParameters().get(i).getBounds(), containingTypeElement.getTypeParameters().get(i).getBounds())) {
return false;
}
}
}
try {
String ownType = accessor.getReturnType().toString();
String inheritedType = attr.returnType.toString();
// This kind of parsing normalizes and ignores type annotations
Type.Producer tf = new Type.Producer();
Type.Parser parser = new Type.Parser(tf, tf.parameters());
if (parser.parse(ownType).equals(parser.parse(inheritedType))) {
attr.initNullabilitySupertype(accessor);
return true;
}
} catch (Exception typeParseException) {
if (typeParseExceptionReported.compareAndSet(false, true)) {
reporter.warning("Type parsing problem in FromSupertypesModel: %s", typeParseException);
}
}
reporter.warning(About.FROM, "Generated builder '.from' method will not copy from attribute '%s'" + " because it has different return type in supertype" + " (And we cannot handle generic specialization or covariant overrides yet)." + " Sometimes it is possible to avoid this by providing abstract override method in this value object", attr.name());
return false;
}
use of org.immutables.value.processor.encode.Type in project immutables by immutables.
the class CriteriaModel method matcherType.
private Type.Parameterized matcherType(IntrospectedType introspected) {
final TypeMirror type = introspected.type;
String name;
if (introspected.useOptional()) {
IntrospectedType param = introspected.optionalParameter();
// use optional intersection-types ?
if (param.isString()) {
name = "org.immutables.criteria.matcher.OptionalStringMatcher.Template";
} else if (param.isBoolean()) {
name = "org.immutables.criteria.matcher.OptionalBooleanMatcher.Template";
} else if (param.isNumber()) {
if (param.isInteger()) {
name = "org.immutables.criteria.matcher.OptionalIntegerMatcher.Template";
} else if (param.isLong()) {
name = "org.immutables.criteria.matcher.OptionalLongMatcher.Template";
} else if (param.isDouble()) {
name = "org.immutables.criteria.matcher.OptionalDoubleMatcher.Template";
} else if (param.isBigInteger()) {
name = "org.immutables.criteria.matcher.OptionalBigIntegerMatcher.Template";
} else if (param.isBigDecimal()) {
name = "org.immutables.criteria.matcher.OptionalBigDecimalMatcher.Template";
} else {
// generic number
name = "org.immutables.criteria.matcher.OptionalNumberMatcher.Template";
}
} else if (param.isComparable()) {
name = "org.immutables.criteria.matcher.OptionalComparableMatcher.Template";
} else {
name = "org.immutables.criteria.matcher.OptionalObjectMatcher.Template";
}
} else if (introspected.hasCriteria()) {
name = topLevelCriteriaClassName(type);
} else if (introspected.isBoolean()) {
name = "org.immutables.criteria.matcher.BooleanMatcher.Template";
} else if (introspected.isNumber()) {
if (introspected.isInteger()) {
name = "org.immutables.criteria.matcher.IntegerMatcher.Template";
} else if (introspected.isLong()) {
name = "org.immutables.criteria.matcher.LongMatcher.Template";
} else if (introspected.isDouble()) {
name = "org.immutables.criteria.matcher.DoubleMatcher.Template";
} else if (introspected.isBigInteger()) {
name = "org.immutables.criteria.matcher.BigIntegerMatcher.Template";
} else if (introspected.isBigDecimal()) {
name = "org.immutables.criteria.matcher.BigDecimalMatcher.Template";
} else {
// generic number
name = "org.immutables.criteria.matcher.NumberMatcher.Template";
}
} else if (introspected.isString()) {
name = "org.immutables.criteria.matcher.StringMatcher.Template";
} else if (introspected.isIterable() || introspected.isArray()) {
name = "org.immutables.criteria.matcher.IterableMatcher.Template";
} else if (introspected.isComparable()) {
name = "org.immutables.criteria.matcher.ComparableMatcher.Template";
} else {
name = "org.immutables.criteria.matcher.ObjectMatcher.Template";
}
final Element element = elements.getTypeElement(name);
final Type.Parameterized matcherType;
if (element == null) {
// means type not found in classpath. probably not yet generated criteria
// create PersonCriteria<R> manually with Type.Parameterized
final Type.Variable variable = factory.parameters().introduce("R", NO_BOUNDS).variable("R");
matcherType = factory.parameterized(factory.reference(name), Collections.singleton(variable));
} else {
matcherType = (Type.Parameterized) toType(element.asType());
}
return matcherType;
}
use of org.immutables.value.processor.encode.Type in project immutables by immutables.
the class CriteriaModel method buildMatcher.
private Type.Parameterized buildMatcher(IntrospectedType introspected) {
Preconditions.checkNotNull(introspected, introspected);
final TypeMirror type = introspected.type;
final Type.Parameterized matcher = matcherType(introspected);
if (matcher.arguments.size() > 1) {
// replace second and maybe third argument
// first type argument R unchanged
Type.VariableResolver resolver = Type.VariableResolver.empty();
final Type valueType;
final Type.Variable arg1 = (Type.Variable) matcher.arguments.get(1);
// resolve P (which is projection type) for Optional
for (Type.Nonprimitive arg : matcher.arguments) {
if (arg instanceof Type.Variable && ((Type.Variable) arg).name.equals("P")) {
// resolve projection type (P) for .Template<R, P>.
// projection type is identical to attribute type
// Example .Template<R, Optional<Boolean>>
resolver = resolver.bind((Type.Variable) arg, factory.reference(type.toString()));
}
}
if (introspected.useOptional()) {
final IntrospectedType newType = introspected.optionalParameter();
valueType = toType(newType.type());
if (newType.hasOptionalMatcher()) {
// don't recurse if optional matcher is present like OptionalComparableMatcher
resolver = resolver.bind(arg1, (Type.Nonprimitive) valueType);
} else {
resolver = resolver.bind(arg1, buildMatcher(newType));
}
} else if (introspected.isScalar()) {
// this is leaf no need to recurse
valueType = toType(introspected.box());
resolver = resolver.bind(arg1, (Type.Nonprimitive) valueType);
} else if (introspected.isArray()) {
final TypeMirror mirror = MoreTypes.asArray(type).getComponentType();
valueType = toType(mirror);
resolver = resolver.bind(arg1, buildMatcher(introspected.withType(mirror)));
} else {
final TypeMirror mirror = MoreTypes.asDeclared(type).getTypeArguments().get(0);
valueType = toType(mirror);
resolver = resolver.bind(arg1, buildMatcher(introspected.withType(mirror)));
}
if (matcher.arguments.size() > 2 && ((Type.Variable) matcher.arguments.get(2)).name.equals("V")) {
// parameter called V is usually value type
resolver = resolver.bind((Type.Variable) matcher.arguments.get(2), (Type.Nonprimitive) valueType);
}
// resolve P (which is projection type) for Array / Iterable
if (introspected.isArray() || introspected.isIterable()) {
for (Type.Nonprimitive arg : matcher.arguments) {
if (arg instanceof Type.Variable && ((Type.Variable) arg).name.equals("P")) {
// resolve projection type (P) for .Template<R, P>.
// projection type is identical to attribute type
// Example .Template<R, Optional<Boolean>>
resolver = resolver.bind((Type.Variable) arg, factory.reference(type.toString()));
}
}
}
return (Type.Parameterized) matcher.accept(resolver);
}
return matcher;
}
Aggregations