Search in sources :

Example 1 with MethodBuilder

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;
}
Also used : INIT(io.sundr.model.Attributeable.INIT) Arrays(java.util.Arrays) TypeParamDefBuilder(io.sundr.model.TypeParamDefBuilder) Descendants(io.sundr.builder.internal.functions.Descendants) Optionals(io.sundr.model.utils.Optionals) TypeElement(javax.lang.model.element.TypeElement) Attributeable(io.sundr.model.Attributeable) Nameable(io.sundr.model.Nameable) ClassRef(io.sundr.model.ClassRef) Getter(io.sundr.model.utils.Getter) STRING_REF(io.sundr.model.utils.Types.STRING_REF) Map(java.util.Map) MirroredTypeException(javax.lang.model.type.MirroredTypeException) BuildableRepository(io.sundr.builder.internal.BuildableRepository) Path(java.nio.file.Path) Collections(io.sundr.model.utils.Collections) BuilderContext(io.sundr.builder.internal.BuilderContext) DefinitionRepository(io.sundr.model.repo.DefinitionRepository) Collection(java.util.Collection) Set(java.util.Set) Element(javax.lang.model.element.Element) Method(io.sundr.model.Method) Construct(io.sundr.builder.internal.functions.Construct) Collectors(java.util.stream.Collectors) io.sundr.builder.annotations(io.sundr.builder.annotations) ALSO_IMPORT(io.sundr.model.Attributeable.ALSO_IMPORT) List(java.util.List) ClassRefBuilder(io.sundr.model.ClassRefBuilder) Stream(java.util.stream.Stream) MethodBuilder(io.sundr.model.MethodBuilder) BuilderContextManager(io.sundr.builder.internal.BuilderContextManager) TypeParamDef(io.sundr.model.TypeParamDef) Strings.capitalizeFirst(io.sundr.utils.Strings.capitalizeFirst) StringStatement(io.sundr.model.StringStatement) TypeParamRef(io.sundr.model.TypeParamRef) GetDefinition(io.sundr.model.functions.GetDefinition) TypeDefBuilder(io.sundr.model.TypeDefBuilder) AdapterContext(io.sundr.adapter.api.AdapterContext) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) INIT_FUNCTION(io.sundr.model.Attributeable.INIT_FUNCTION) Assignable(io.sundr.model.functions.Assignable) Types(io.sundr.model.utils.Types) LinkedHashSet(java.util.LinkedHashSet) Constants(io.sundr.builder.Constants) AptContext(io.sundr.adapter.apt.AptContext) TypedVisitor(io.sundr.builder.TypedVisitor) Adapters(io.sundr.adapter.api.Adapters) LAZY_INIT(io.sundr.model.Attributeable.LAZY_INIT) TypeRef(io.sundr.model.TypeRef) Types.isAbstract(io.sundr.model.utils.Types.isAbstract) AnnotationRef(io.sundr.model.AnnotationRef) Kind(io.sundr.model.Kind) Property(io.sundr.model.Property) File(java.io.File) LAZY_COLLECTIONS_INIT_ENABLED(io.sundr.builder.Constants.LAZY_COLLECTIONS_INIT_ENABLED) Statement(io.sundr.model.Statement) TypeDef(io.sundr.model.TypeDef) DEFAULT_VALUE(io.sundr.model.Attributeable.DEFAULT_VALUE) PropertyBuilder(io.sundr.model.PropertyBuilder) TypeAs(io.sundr.builder.internal.functions.TypeAs) DESCENDANTS(io.sundr.builder.Constants.DESCENDANTS) ClassRef(io.sundr.model.ClassRef) TypeRef(io.sundr.model.TypeRef) Method(io.sundr.model.Method) MethodBuilder(io.sundr.model.MethodBuilder) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 2 with MethodBuilder

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();
}
Also used : TypedVisitor(io.sundr.builder.TypedVisitor) ClassRef(io.sundr.model.ClassRef) TypeRef(io.sundr.model.TypeRef) ClassRefBuilder(io.sundr.model.ClassRefBuilder) ArrayList(java.util.ArrayList) Method(io.sundr.model.Method) TypeDefBuilder(io.sundr.model.TypeDefBuilder) MethodBuilder(io.sundr.model.MethodBuilder) RichTypeDef(io.sundr.model.RichTypeDef) TypeDef(io.sundr.model.TypeDef) Property(io.sundr.model.Property) PropertyBuilder(io.sundr.model.PropertyBuilder)

Example 3 with MethodBuilder

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();
}
Also used : AndTransitionFilter(io.sundr.dsl.internal.element.functions.filter.AndTransitionFilter) TypeParamDef(io.sundr.model.TypeParamDef) Multiple(io.sundr.dsl.annotations.Multiple) TypeRef(io.sundr.model.TypeRef) ArrayList(java.util.ArrayList) EntryPoint(io.sundr.dsl.annotations.EntryPoint) Method(io.sundr.model.Method) TypeDefBuilder(io.sundr.model.TypeDefBuilder) MethodBuilder(io.sundr.model.MethodBuilder) OrTransitionFilter(io.sundr.dsl.internal.element.functions.filter.OrTransitionFilter) AndTransitionFilter(io.sundr.dsl.internal.element.functions.filter.AndTransitionFilter) TransitionFilter(io.sundr.dsl.internal.element.functions.filter.TransitionFilter) OrTransitionFilter(io.sundr.dsl.internal.element.functions.filter.OrTransitionFilter) Begin(io.sundr.dsl.annotations.Begin) InterfaceName(io.sundr.dsl.annotations.InterfaceName) End(io.sundr.dsl.annotations.End) MethodName(io.sundr.dsl.annotations.MethodName) AnnotationRef(io.sundr.model.AnnotationRef) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 4 with MethodBuilder

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;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) Types(javax.lang.model.util.Types) ClassRef(io.sundr.model.ClassRef) TypeElement(javax.lang.model.element.TypeElement) TypeRef(io.sundr.model.TypeRef) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) ExecutableElement(javax.lang.model.element.ExecutableElement) Node(io.sundr.dsl.internal.graph.Node) ArrayList(java.util.ArrayList) Method(io.sundr.model.Method) Elements(javax.lang.model.util.Elements) TypeDefBuilder(io.sundr.model.TypeDefBuilder) MethodBuilder(io.sundr.model.MethodBuilder) TypeDef(io.sundr.model.TypeDef) InterfaceName(io.sundr.dsl.annotations.InterfaceName)

Example 5 with MethodBuilder

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);
                }
            }
        }
    };
}
Also used : TypedVisitor(io.sundr.builder.TypedVisitor) TypeParamRef(io.sundr.model.TypeParamRef) TypeRef(io.sundr.model.TypeRef) MethodBuilder(io.sundr.model.MethodBuilder)

Aggregations

MethodBuilder (io.sundr.model.MethodBuilder)11 Method (io.sundr.model.Method)9 ArrayList (java.util.ArrayList)9 ClassRef (io.sundr.model.ClassRef)8 TypeRef (io.sundr.model.TypeRef)8 TypeDefBuilder (io.sundr.model.TypeDefBuilder)7 AnnotationRef (io.sundr.model.AnnotationRef)6 Property (io.sundr.model.Property)6 AttributeKey (io.sundr.model.AttributeKey)5 TypeDef (io.sundr.model.TypeDef)5 TypeParamDef (io.sundr.model.TypeParamDef)5 HashMap (java.util.HashMap)5 HashSet (java.util.HashSet)5 TypedVisitor (io.sundr.builder.TypedVisitor)4 PropertyBuilder (io.sundr.model.PropertyBuilder)4 Adapters (io.sundr.adapter.api.Adapters)2 AptContext (io.sundr.adapter.apt.AptContext)2 BuilderContext (io.sundr.builder.internal.BuilderContext)2 ClassRefBuilder (io.sundr.model.ClassRefBuilder)2 LinkedHashSet (java.util.LinkedHashSet)2