use of io.sundr.model.MethodBuilder in project sundrio by sundrio.
the class BuilderUtils method getInlineableConstructors.
public static Set<Method> getInlineableConstructors(Property property) {
Set<Method> result = new HashSet<Method>();
TypeRef typeRef = property.getTypeRef();
TypeRef unwrapped = TypeAs.combine(TypeAs.UNWRAP_COLLECTION_OF, TypeAs.UNWRAP_ARRAY_OF, TypeAs.UNWRAP_OPTIONAL_OF).apply(typeRef);
if (unwrapped instanceof ClassRef) {
ClassRef classRef = (ClassRef) unwrapped;
// We need to handle `new String(String str)` as a special case of Inlineable constructor and deprecate Inlineables of it before we acutally remove it, so here goes...
if (STRING_REF.equals(typeRef)) {
result.add(new MethodBuilder().withName("String").addNewArgument().withName("s").withTypeRef(classRef).endArgument().build());
return result;
}
// We only want to inline non java types
String pkg = Nameable.getPackageName(((ClassRef) unwrapped).getFullyQualifiedName());
if (!Stream.of(NON_INLINABLE_PACKAGES).filter(s -> pkg.startsWith(s)).findAny().isPresent()) {
for (Method candidate : GetDefinition.of((ClassRef) unwrapped).getConstructors()) {
if (isInlineable(candidate)) {
result.add(candidate);
}
}
}
}
return result;
}
use of io.sundr.model.MethodBuilder in project sundrio by sundrio.
the class AbstractBuilderProcessor method inlineableOf.
static TypeDef inlineableOf(BuilderContext ctx, TypeDef type, Inline inline) {
final String inlineableName = !inline.name().isEmpty() ? inline.name() : inline.prefix() + type.getName() + inline.suffix();
List<Method> constructors = new ArrayList<Method>();
final TypeDef builderType = TypeAs.BUILDER.apply(type);
TypeDef inlineType = BuilderUtils.getInlineType(ctx, inline);
TypeDef returnType = BuilderUtils.getInlineReturnType(ctx, inline, type);
final ClassRef inlineTypeRef = inlineType.toReference(returnType.toReference());
// Use the builder as the base of the inlineable. Just add interface and change name.
final TypeDef shallowInlineType = new TypeDefBuilder(builderType).withName(inlineableName).withImplementsList(inlineTypeRef).withProperties().withMethods().withConstructors().build();
TypeRef functionType = Constants.FUNCTION.toReference(type.toInternalReference(), returnType.toInternalReference());
Property builderProperty = new PropertyBuilder().withTypeRef(TypeAs.BUILDER.apply(type).toInternalReference()).withName(BUILDER).withModifiers(Types.modifiersToInt(Modifier.PRIVATE, Modifier.FINAL)).build();
Property functionProperty = new PropertyBuilder().withTypeRef(functionType).withName(FUNCTION).withModifiers(Types.modifiersToInt(Modifier.PRIVATE, Modifier.FINAL)).build();
Method inlineMethod = new MethodBuilder().withReturnType(returnType.toInternalReference()).withName(inline.value()).withNewBlock().addNewStringStatementStatement(BUILD_AND_APPLY_FUNCTION).endBlock().withModifiers(Types.modifiersToInt(Modifier.PUBLIC)).build();
constructors.add(new MethodBuilder().withReturnType(inlineTypeRef).withName(EMPTY).addNewArgument().withName(FUNCTION).withTypeRef(functionType).and().withModifiers(Types.modifiersToInt(Modifier.PUBLIC)).withNewBlock().addNewStringStatementStatement(String.format(NEW_BULDER_AND_SET_FUNCTION_FORMAT, builderType.getName())).endBlock().build());
constructors.add(new MethodBuilder().withReturnType(inlineTypeRef).withName(EMPTY).addNewArgument().withName(ITEM).withTypeRef(type.toInternalReference()).and().addNewArgument().withName(FUNCTION).withTypeRef(functionType).and().withModifiers(Types.modifiersToInt(Modifier.PUBLIC)).withNewBlock().addNewStringStatementStatement(String.format(NEW_BULDER_WITH_ITEM_AND_SET_FUNCTION_FORMAT, builderType.getName())).endBlock().build());
if (type.equals(returnType)) {
constructors.add(new MethodBuilder().withReturnType(inlineTypeRef).withName(EMPTY).addNewArgument().withName(ITEM).withTypeRef(type.toInternalReference()).and().withModifiers(Types.modifiersToInt(Modifier.PUBLIC)).withNewBlock().addNewStringStatementStatement(String.format(NEW_BUILDER_AND_EMTPY_FUNCTION_FORMAT, builderType.getName(), String.format(EMPTY_FUNCTION_TEXT, type.toInternalReference(), returnType.toInternalReference(), returnType.toInternalReference(), type.toInternalReference()))).endBlock().build());
}
return new TypeDefBuilder(shallowInlineType).withAnnotations().withModifiers(Types.modifiersToInt(Modifier.PUBLIC)).withConstructors(constructors).addToProperties(builderProperty, functionProperty).addToMethods(inlineMethod).accept(new TypedVisitor<ClassRefBuilder>() {
@Override
public void visit(ClassRefBuilder builder) {
List<TypeRef> updatedArguments = new ArrayList<TypeRef>();
for (TypeRef arg : builder.getArguments()) {
if (arg.equals(builderType.toInternalReference())) {
updatedArguments.add(shallowInlineType.toInternalReference());
} else {
updatedArguments.add(arg);
}
}
builder.withArguments(updatedArguments);
}
}).build();
}
use of io.sundr.model.MethodBuilder in project sundrio by sundrio.
the class TypeDefUtils method executableToInterface.
/**
* Convert an {@link javax.lang.model.element.ExecutableElement} to a {@link io.sundr.model.TypeDef}
*
* @param context The context of the operation.
* @param executableElement The target element.
* @return An instance of {@link io.sundr.model.TypeDef} that describes the interface.
*/
public static TypeDef executableToInterface(DslContext context, ExecutableElement executableElement) {
// Do generate the interface
Boolean multiple = executableElement.getAnnotation(Multiple.class) != null;
Boolean isEntryPoint = executableElement.getAnnotation(EntryPoint.class) != null;
Boolean isTerminal = executableElement.getAnnotation(Terminal.class) != null || !isVoid(executableElement);
Set<String> classes = new HashSet<String>();
Set<String> keywords = new HashSet<String>();
Set<String> methods = new HashSet<String>();
TransitionFilter filter = executableElement.getAnnotation(Or.class) != null ? new OrTransitionFilter(context.getToRequiresAll().apply(executableElement), context.getToRequiresAny().apply(executableElement), context.getToRequiresOnly().apply(executableElement), context.getToRequiresNoneOf().apply(executableElement)) : new AndTransitionFilter(context.getToRequiresAll().apply(executableElement), context.getToRequiresAny().apply(executableElement), context.getToRequiresOnly().apply(executableElement), context.getToRequiresNoneOf().apply(executableElement));
for (String clazz : context.getToClasses().apply(executableElement)) {
classes.add(clazz);
}
for (String keyword : context.getToKeywords().apply(executableElement)) {
keywords.add(keyword);
}
// Let's add the name of the method as a keyword to make things simpler
methods.add(executableElement.getSimpleName().toString());
TypeRef returnType;
if (isTerminal(executableElement)) {
returnType = isVoid(executableElement) ? VOID_REF : Adapters.adaptReference(executableElement.getReturnType(), context.getAptContext());
} else {
returnType = TRANSPARENT_REF;
}
InterfaceName targetInterfaceName = executableElement.getAnnotation(InterfaceName.class);
MethodName tagetMethodName = executableElement.getAnnotation(MethodName.class);
Begin begin = executableElement.getAnnotation(Begin.class);
End end = executableElement.getAnnotation(End.class);
if (begin != null) {
keywords.add(begin.value());
}
if (end != null) {
keywords.add(end.value());
}
String methodName = tagetMethodName != null ? tagetMethodName.value() : executableElement.getSimpleName().toString();
String beginScope = begin != null ? begin.value() : null;
String endScope = end != null ? end.value() : null;
TypeParamDef paremeterType = Generics.MAP.apply(returnType);
Method sourceMethod = Adapters.adaptMethod(executableElement, context.getAptContext());
List<AnnotationRef> annotations = new ArrayList<AnnotationRef>();
for (AnnotationRef candidate : sourceMethod.getAnnotations()) {
if (!candidate.getClassRef().getFullyQualifiedName().startsWith("io.sundr")) {
annotations.add(candidate);
}
}
Method targetMethod = new MethodBuilder(sourceMethod).withAnnotations(annotations).withModifiers(Types.modifiersToInt(Modifier.PUBLIC)).withReturnType(paremeterType.toReference()).withName(methodName).build();
String interfaceName = targetInterfaceName != null ? targetInterfaceName.value() : toInterfaceName(targetMethod.getName());
return new TypeDefBuilder().withPackageName(Apt.getPackageElement(executableElement).toString()).withName(interfaceName).withParameters(paremeterType).withKind(Kind.INTERFACE).withModifiers(Types.modifiersToInt(Modifier.PUBLIC)).addToAttributes(ORIGINAL_RETURN_TYPE, returnType).addToAttributes(IS_ENTRYPOINT, isEntryPoint).addToAttributes(IS_TERMINAL, isTerminal).addToAttributes(IS_GENERIC, Boolean.FALSE).addToAttributes(CLASSES, classes).addToAttributes(KEYWORDS, keywords).addToAttributes(METHODS, methods).addToAttributes(BEGIN_SCOPE, beginScope).addToAttributes(END_SCOPE, endScope).addToAttributes(FILTER, filter).addToAttributes(CARDINALITY_MULTIPLE, multiple).addToAttributes(METHOD_NAME, methodName).addToMethods(targetMethod).build();
}
use of io.sundr.model.MethodBuilder in project sundrio by sundrio.
the class DslProcessor method process.
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
Elements elements = processingEnv.getElementUtils();
Types types = processingEnv.getTypeUtils();
DslContext context = DslContextManager.create(elements, types);
for (TypeElement annotation : annotations) {
for (Element element : env.getElementsAnnotatedWith(annotation)) {
if (element instanceof TypeElement) {
Generics.clear();
TypeElement typeElement = (TypeElement) element;
InterfaceName interfaceName = element.getAnnotation(InterfaceName.class);
String targetInterface = interfaceName.value();
Set<TypeDef> interfacesToGenerate = new LinkedHashSet<TypeDef>();
Collection<ExecutableElement> sorted = ElementFilter.methodsIn(typeElement.getEnclosedElements());
// 1st step generate generic interface for all types.
Set<TypeDef> genericInterfaces = executablesToInterfaces(context, sorted);
Set<TypeDef> genericAndScopeInterfaces = Nodes.TO_SCOPE.apply(genericInterfaces);
for (TypeDef clazz : genericAndScopeInterfaces) {
if (!TypeDefUtils.isEntryPoint(clazz)) {
interfacesToGenerate.add(clazz);
}
}
// 2nd step create dependency graph.
List<Method> methods = new ArrayList<Method>();
Set<Node<TypeDef>> graph = Nodes.TO_GRAPH.apply(genericAndScopeInterfaces);
for (Node<TypeDef> root : graph) {
Node<TypeDef> uncyclic = Nodes.TO_UNCYCLIC.apply(root);
Node<TypeDef> unwrapped = Nodes.TO_UNWRAPPED.apply(NodeContext.builder().withItem(uncyclic.getItem()).build());
TypeDef current = unwrapped.getItem();
// Just add the method with the direct return type.
if (unwrapped.getTransitions().isEmpty()) {
for (Method m : current.getMethods()) {
TypeRef returnType = m.getReturnType();
if (returnType instanceof ClassRef) {
TypeDef toUnwrap = GetDefinition.of((ClassRef) returnType);
methods.add(new MethodBuilder(m).withReturnType(Generics.UNWRAP.apply(toUnwrap).toInternalReference()).build());
} else if (returnType.getAttributes().containsKey(ORIGINAL_REF)) {
methods.add(new MethodBuilder(m).withReturnType((TypeRef) returnType.getAttributes().get(ORIGINAL_REF)).build());
} else {
methods.add(new MethodBuilder(m).withReturnType(returnType).build());
}
}
} else {
for (Method m : current.getMethods()) {
methods.add(new MethodBuilder(m).withReturnType(current.toUnboundedReference()).build());
}
interfacesToGenerate.add(Nodes.TO_ROOT.apply(unwrapped));
}
}
// Do generate the DSL interface
interfacesToGenerate.add(new TypeDefBuilder().withComments("Generated").withPackageName(Apt.getPackageElement(element).toString()).withName(targetInterface).withKind(Kind.INTERFACE).withModifiers(modifiersToInt(Modifier.PUBLIC)).withMethods(methods).build());
interfacesToGenerate.addAll(context.getDefinitionRepository().getDefinitions(IS_GENERATED));
for (TypeDef clazz : interfacesToGenerate) {
generate(clazz);
}
}
}
}
return true;
}
use of io.sundr.model.MethodBuilder in project sundrio by sundrio.
the class BindDefinition method mapGenericReturnTypes.
/**
* Map generic properties to known {@link TypeRef} based on the specified mappings.
* Example: Given a property {@code T size} and a map containing {@code T -> Integer} the final
* property will be: {@code Integer type}.
*
* @param mappings A map that maps class arguments names to types.
* @return a visitors that performs the actual mapping.
*/
private static TypedVisitor<MethodBuilder> mapGenericReturnTypes(Map<String, TypeRef> mappings) {
return new TypedVisitor<MethodBuilder>() {
@Override
public void visit(MethodBuilder method) {
TypeRef typeRef = method.buildReturnType();
if (typeRef instanceof TypeParamRef) {
TypeParamRef typeParamRef = (TypeParamRef) typeRef;
String key = typeParamRef.getName();
TypeRef paramRef = mappings.get(key);
if (paramRef != null) {
method.withReturnType(paramRef);
}
}
}
};
}
Aggregations