All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.langion.creator.Explorer Maven / Gradle / Ivy

package com.github.langion.creator;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.EnumDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.langion.creator.creators.AnnotationCreator;
import com.github.langion.creator.creators.ArgumentCreator;
import com.github.langion.creator.creators.ClassCreator;
import com.github.langion.creator.creators.EntityCreator;
import com.github.langion.creator.creators.EnumCreator;
import com.github.langion.creator.creators.FieldCreator;
import com.github.langion.creator.creators.GenericCreator;
import com.github.langion.creator.creators.InterfaceCreator;
import com.github.langion.creator.creators.LangionCreator;
import com.github.langion.creator.creators.MethodCreator;
import com.github.langion.creator.creators.ModifierCreator;
import com.github.langion.creator.creators.TypeCreator;
import com.github.langion.creator.creators.ValueCreator;
import com.github.langion.creator.creators.VariableCreator;
import com.github.langion.creator.creators.WildcardCreator;
import com.github.langion.form.AnnotationEntity;
import com.github.langion.form.ArgumentEntity;
import com.github.langion.form.FieldEntity;
import com.github.langion.form.GenericEntity;
import com.github.langion.form.MethodEntity;
import com.github.langion.form.ModifierEntity;
import com.github.langion.form.ModuleEntity;
import com.github.langion.form.TypeEntity;
import com.github.langion.form.ValueEntity;
import com.github.langion.form.VariableEntity;
import com.github.langion.form.WildcardEntity;

import javassist.Modifier;

public class Explorer {

	private LangionCreator langion;
	private Configuration config;

	private List> introspected = new ArrayList>();
	private Map, TypeEntity> types = new HashMap, TypeEntity>();

	public Explorer(LangionCreator langion, Configuration config) {
		this.langion = langion;
		this.config = config;
	}

	public TypeEntity make(Class clazz) {
		Boolean hasBeenIntrospected = this.introspected.contains(clazz);

		if (hasBeenIntrospected) {
			return this.types.get(clazz);
		} else {
			this.introspected.add(clazz);
		}

		CompilationUnit cu = this.elicitCompilationUnit(clazz);
		EntityCreator creator;

		if (clazz.isInterface()) {
			Optional dec = cu == null ? Optional.empty()
					: cu.getInterfaceByName(clazz.getSimpleName());

			creator = new InterfaceCreator(dec, clazz, this);
		} else if (clazz.isEnum()) {
			Optional dec = cu == null ? Optional.empty() : cu.getEnumByName(clazz.getSimpleName());
			creator = new EnumCreator(dec, clazz, this);
		} else {
			Optional dec = null;

			try {
				dec = cu == null ? Optional.empty() : cu.getClassByName(clazz.getSimpleName());
			} catch (Exception e) {
				dec = Optional.empty();
			}

			creator = new ClassCreator(dec, clazz, this);
		}

		if (!this.isPrimitive(clazz)) {
			ModuleEntity module = this.langion.getModuleEntity(clazz);
			module.Exports.put(creator.entity.Name, creator.entity);
		}

		TypeEntity type = this.make((Type) clazz);
		this.types.put(clazz, type);

		creator.decode();

		return type;
	}

	public TypeEntity make(Type type) {
		TypeCreator creator = new TypeCreator(type, this);
		creator.decode();
		return creator.entity;
	}

	public TypeEntity make(Type type, Class clazz) {
		TypeCreator creator = new TypeCreator(type, clazz, this);
		creator.decode();
		return creator.entity;
	}

	public FieldEntity make(Field field, Optional dec) {
		FieldCreator creator = new FieldCreator(dec, field, this);
		creator.decode();
		return creator.entity;
	}

	public GenericEntity make(Type generic, Integer position) {
		GenericCreator creator = new GenericCreator(generic, position, this);
		creator.decode();
		return creator.entity;
	}

	public VariableEntity make(TypeVariable variable, Integer position) {
		VariableCreator creator = new VariableCreator(variable, position, this);
		creator.decode();
		return creator.entity;
	}

	public WildcardEntity make(WildcardType wildcard) {
		WildcardCreator creator = new WildcardCreator(wildcard, this);
		creator.decode();
		return creator.entity;
	}

	public ModifierEntity make(Integer modifiers) {
		ModifierCreator creator = new ModifierCreator(modifiers, this);
		creator.decode();
		return creator.entity;
	}

	public AnnotationEntity make(Annotation annotation, Optional dec) {
		AnnotationCreator creator = new AnnotationCreator(dec, annotation, this);
		creator.decode();
		return creator.entity;
	}

	public MethodEntity make(Method method, Optional> optionalList) {
		Optional dec = Optional.empty();

		if (optionalList.isPresent()) {
			List list = optionalList.get();

			dec = list.stream()
					.filter(m -> Stream.of(method.getParameters()).allMatch(p -> m.hasParametersOfType(p.getType())))
					.findFirst();
		}

		MethodCreator creator = new MethodCreator(dec, method, this);
		creator.decode();
		return creator.entity;
	}

	public ArgumentEntity make(Parameter parameter, Integer position,
			Optional dec) {
		ArgumentCreator creator = new ArgumentCreator(dec, parameter, position, this);
		creator.decode();
		return creator.entity;
	}

	public ValueEntity make(Object result) {
		ValueCreator creator = new ValueCreator(result, this);
		creator.decode();
		return creator.entity;
	}

	public String elicitCanonical(Object result) {
		try {
			String name = result.getClass().getCanonicalName();
			return name;
		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(Parameter parameter) {
		try {
			return parameter.getName();
		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(Class clazz) {
		try {
			return clazz.getCanonicalName();
		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(Field field) {
		try {
			return field.getName();
		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(Type type) {
		try {
			Boolean isClazz = type instanceof Class;

			if (!isClazz) {
				if (type == null) {
					return "";
				} else {

					return type.getTypeName();

				}
			}

			Class clazz = (Class) type;

			if (this.isStringType(clazz)) {
				return "string";
			} else if (this.isDate(clazz)) {
				return "Date";
			} else if (this.isLogical(clazz)) {
				return "boolean";
			} else if (this.isNumericType(clazz)) {
				return "number";
			} else {
				return this.elicitCanonical(clazz);
			}

		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(TypeVariable variable) {
		try {
			return variable.getName();
		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(WildcardType wildcard) {
		try {
			return wildcard.getTypeName();
		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(Annotation annotation) {
		try {
			return annotation.annotationType().getName();
		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(Method method) {
		try {
			return method.getName();
		} catch (Throwable e) {
			e.printStackTrace();
			return "";
		}
	}

	public String elicitCanonical(Integer modifiers) {
		return "Modifiers";
	}

	public Boolean isPrimitive(Class type) {
		return type.isPrimitive() || this.isStringType(type) || this.isDate(type) || this.isLogical(type)
				|| this.isNumericType(type);
	}

	public Boolean isStringType(Class type) {
		return Stream.of(String.class).anyMatch(t -> t.isAssignableFrom(type));
	}

	public Boolean isDate(Class type) {
		return Stream.of(Date.class, LocalDate.class).anyMatch(t -> t.isAssignableFrom(type));
	}

	public Boolean isLogical(Class type) {
		return Stream.of(Boolean.class, boolean.class).anyMatch(t -> t.isAssignableFrom(type));
	}

	public Boolean isNumericType(Class type) {
		return Stream
				.of(int.class, long.class, float.class, double.class, byte.class, short.class, Integer.class,
						Long.class, Float.class, Double.class, Byte.class, Short.class, Long.class, BigDecimal.class)
				.anyMatch(t -> t.isAssignableFrom(type));
	}

	private CompilationUnit elicitCompilationUnit(Class clazz) {

		if (!this.config.srcBaseJavaFolders.isPresent()) {
			return null;
		}

		Optional cu = this.getCompilationUnit(clazz);

		if (cu.isPresent()) {
			return cu.get();
		} else {
			CompilationUnit unit = this.getComilationUnitOfInternalClass(clazz);
			return unit;
		}
	}

	private Optional getCompilationUnit(Class clazz) {
		String canonicalName = this.elicitCanonical(clazz);

		if (canonicalName == null) {
			return Optional.empty();
		}

		String clazzPath = canonicalName.replaceAll("\\.", "\\" + File.separator);
		List srcBaseJavaFolders = this.config.srcBaseJavaFolders.get();

		Optional cu = srcBaseJavaFolders.stream().map(s -> {
			String path = s + File.separator + clazzPath + ".java";

			File file = new File(path);

			try {
				return JavaParser.parse(file);
			} catch (FileNotFoundException e) {
				return null;
			}

		}).filter(s -> s != null).findFirst();

		return cu;
	}

	private CompilationUnit getComilationUnitOfInternalClass(Class clazz) {
		Package pack = clazz.getPackage();

		if (pack == null) {
			return null;
		}

		String packageName = pack.getName();
		Stream> classes = this.langion.getClassFromPackageName(packageName);
		Stream> publicClasses = classes.filter(v -> Modifier.isPublic(v.getModifiers()));

		Stream declarations = publicClasses.map(v -> {
			Optional optionalUnit = this.getCompilationUnit(v);

			if (!optionalUnit.isPresent()) {
				return null;
			}

			CompilationUnit unit = optionalUnit.get();
			String name = clazz.getSimpleName();
			Optional unitOfInternalClazz = unit.getClassByName(name);

			if (unitOfInternalClazz.isPresent()) {
				return unit;
			} else {
				return null;
			}
		});

		Optional result = declarations.filter(d -> d != null).findFirst();

		if (result.isPresent()) {
			CompilationUnit unit = result.get();
			return unit;
		} else {
			return null;
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy