Package com.codereligion.hammock.compiler.model

Source Code of com.codereligion.hammock.compiler.model.Type

package com.codereligion.hammock.compiler.model;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;

import javax.annotation.Generated;
import javax.annotation.Nullable;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.removeIf;

public class Type {

    private static final Pattern GENERICS = Pattern.compile("<.+>");

    private final List<Closure> closures = new ArrayList<>();
    private final List<Type> types = new ArrayList<>();
    private final TypeElement element;

    public Type(TypeElement element) {
        this.element = element;
    }

    public TypeElement getElement() {
        return element;
    }

    public String getPackage() {
        Element parent = element.getEnclosingElement();
       
        while (true) {
            if (parent instanceof PackageElement) {
                final PackageElement packageElement = (PackageElement) parent;
                return packageElement.getQualifiedName().toString();
            } else {
                parent = parent.getEnclosingElement();
            }
        }
    }
   
    public Name getName() {
        return new Name(element.getQualifiedName() + "_");
    }

    public Iterable<String> getImports() {
        final Set<String> imports = new TreeSet<>();

        for (Closure closure : closures) {
            for (Argument argument : closure.getArguments()) {
                imports.add(argument.getType().getQualified());
            }

            imports.add(closure.getInput().getType().getQualified());
            imports.add(closure.getReturnType().getQualified());
        }

        if (any(closures, Is.PREDICATE)) {
            imports.add(Predicate.class.getName());
        }

        if (any(closures, Is.FUNCTION)) {
            imports.add(Function.class.getName());
        }

        imports.add(Nullable.class.getName());
        imports.add(Generated.class.getName());

        for (Type type : types) {
            Iterables.addAll(imports, type.getImports());
        }

        removeIf(imports, Exclude.JAVA_LANG);
        removeIf(imports, Exclude.PRIMITIVES);

        final String samePackage = getPackage();
        removeIf(imports, startsWith(samePackage));

        // are in the same package, but still need to get imported explicitly
        for (Type type : getTypes()) {
            addNestedToImports(type, imports);
        }

        return ungenerify(imports);
    }

    private void addNestedToImports(Type type, Set<String> imports) {
        if (!type.getClosures().isEmpty()) {
            imports.add(type.element.getQualifiedName().toString());
        }
       
        for (Type subtype : type.getTypes()) {
            addNestedToImports(subtype, imports);
        }
    }

    private Set<String> ungenerify(Set<String> imports) {
        final Set<String> ungenerified = new TreeSet<>();

        for (String name : imports) {
            final Matcher matcher = GENERICS.matcher(name);
            ungenerified.add(matcher.replaceAll(""));
        }

        return ungenerified;
    }

    public List<Closure> getClosures() {
        return closures;
    }

    public List<Type> getTypes() {
        return types;
    }

    private enum Is implements Predicate<Closure> {

        PREDICATE {
            @Override
            public boolean apply(@Nullable Closure input) {
                return input != null && input.isPredicate();
            }

        },

        FUNCTION {
            @Override
            public boolean apply(@Nullable Closure input) {
                return input != null && !input.isPredicate();
            }

        }

    }

    private enum Exclude implements Predicate<String> {

        JAVA_LANG {
           
            @Override
            public boolean apply(@Nullable String input) {
                return input != null && input.startsWith("java.lang.");
            }

        },

        PRIMITIVES {

            private final Set<String> primitives = ImmutableSet.of(
                    "byte", "short", "int", "long",
                    "float", "double",
                    "boolean",
                    "char"
            );

            @Override
            public boolean apply(@Nullable String input) {
                return primitives.contains(input);
            }

        }

    }

    private static Predicate<String> startsWith(final String prefix) {
        return new Predicate<String>() {
            @Override
            public boolean apply(@Nullable String input) {
                return input != null && input.startsWith(prefix);
            }
        };
    }

}
TOP

Related Classes of com.codereligion.hammock.compiler.model.Type

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.