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

org.reflections.serializers.JavaCodeSerializer Maven / Gradle / Ivy

There is a newer version: 0.10.2
Show newest version
package org.reflections.serializers;

import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
import org.reflections.ReflectionsException;
import org.reflections.scanners.TypeElementsScanner;
import org.reflections.util.Utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static org.reflections.Reflections.log;
import static org.reflections.util.Utils.*;

/** Serialization of Reflections to java code
 * 

Serializes types and types elements into interfaces respectively to fully qualified name, *

For example, after saving with JavaCodeSerializer: *

 *   reflections.save(filename, new JavaCodeSerializer());
 * 
*

Saved file should look like: *

 *     public interface MyModel {
 *      public interface my {
 *       public interface package1 {
 *        public interface MyClass1 {
 *         public interface fields {
 *          public interface f1 {}
 *          public interface f2 {}
 *         }
 *         public interface methods {
 *          public interface m1 {}
 *          public interface m2 {}
 *         }
 *	...
 * }
 * 
*

Use the different resolve methods to resolve the serialized element into Class, Field or Method. for example: *

 *  Class m1Ref = MyModel.my.package1.MyClass1.methods.m1.class;
 *  Method method = JavaCodeSerializer.resolve(m1Ref);
 * 
*

The {@link #save(org.reflections.Reflections, String)} method filename should be in the pattern: path/path/path/package.package.classname *

depends on Reflections configured with {@link org.reflections.scanners.TypeElementsScanner} * */ public class JavaCodeSerializer implements Serializer { private static final String pathSeparator = "_"; private static final String doubleSeparator = "__"; private static final String dotSeparator = "."; private static final String arrayDescriptor = "$$"; private static final String tokenSeparator = "_"; public Reflections read(InputStream inputStream) { throw new UnsupportedOperationException("read is not implemented on JavaCodeSerializer"); } /** * name should be in the pattern: path/path/path/package.package.classname, * for example

/data/projects/my/src/main/java/org.my.project.MyStore
* would create class MyStore in package org.my.project in the path /data/projects/my/src/main/java */ public File save(Reflections reflections, String name) { if (name.endsWith("/")) { name = name.substring(0, name.length() - 1); //trim / at the end } //prepare file String filename = name.replace('.', '/').concat(".java"); File file = prepareFile(filename); //get package and class names String packageName; String className; int lastDot = name.lastIndexOf('.'); if (lastDot == -1) { packageName = ""; className = name.substring(name.lastIndexOf('/') + 1); } else { packageName = name.substring(name.lastIndexOf('/') + 1, lastDot); className = name.substring(lastDot + 1); } //generate try { StringBuilder sb = new StringBuilder(); sb.append("//generated using Reflections JavaCodeSerializer") .append(" [").append(new Date()).append("]") .append("\n"); if (packageName.length() != 0) { sb.append("package ").append(packageName).append(";\n"); sb.append("\n"); } sb.append("public interface ").append(className).append(" {\n\n"); sb.append(toString(reflections)); sb.append("}\n"); Files.write(new File(filename).toPath(), sb.toString().getBytes(Charset.defaultCharset())); } catch (IOException e) { throw new RuntimeException(); } return file; } public String toString(Reflections reflections) { if (reflections.getStore().keys(index(TypeElementsScanner.class)).isEmpty()) { if (log != null) log.warn("JavaCodeSerializer needs TypeElementsScanner configured"); } StringBuilder sb = new StringBuilder(); List prevPaths = new ArrayList<>(); int indent = 1; List keys = new ArrayList<>(reflections.getStore().keys(index(TypeElementsScanner.class))); Collections.sort(keys); for (String fqn : keys) { List typePaths = Arrays.asList(fqn.split("\\.")); //skip indention int i = 0; while (i < Math.min(typePaths.size(), prevPaths.size()) && typePaths.get(i).equals(prevPaths.get(i))) { i++; } //indent left for (int j = prevPaths.size(); j > i; j--) { sb.append(repeat("\t", --indent)).append("}\n"); } //indent right - add packages for (int j = i; j < typePaths.size() - 1; j++) { sb.append(repeat("\t", indent++)).append("public interface ").append(getNonDuplicateName(typePaths.get(j), typePaths, j)).append(" {\n"); } //indent right - add class String className = typePaths.get(typePaths.size() - 1); //get fields and methods List annotations = new ArrayList<>(); List fields = new ArrayList<>(); List methods = new ArrayList<>(); Iterable members = reflections.getStore().get(index(TypeElementsScanner.class), fqn); List sorted = StreamSupport.stream(members.spliterator(), false).sorted().collect(Collectors.toList()); for (String element : sorted) { if (element.startsWith("@")) { annotations.add(element.substring(1)); } else if (element.contains("(")) { //method if (!element.startsWith("<")) { int i1 = element.indexOf('('); String name = element.substring(0, i1); String params = element.substring(i1 + 1, element.indexOf(")")); String paramsDescriptor = ""; if (params.length() != 0) { paramsDescriptor = tokenSeparator + params.replace(dotSeparator, tokenSeparator).replace(", ", doubleSeparator).replace("[]", arrayDescriptor); } String normalized = name + paramsDescriptor; if (!methods.contains(name)) { methods.add(name); } else { methods.add(normalized); } } } else if (!Utils.isEmpty(element)) { //field fields.add(element); } } //add class and it's fields and methods sb.append(repeat("\t", indent++)).append("public interface ").append(getNonDuplicateName(className, typePaths, typePaths.size() - 1)).append(" {\n"); //add fields if (!fields.isEmpty()) { sb.append(repeat("\t", indent++)).append("public interface fields {\n"); for (String field : fields) { sb.append(repeat("\t", indent)).append("public interface ").append(getNonDuplicateName(field, typePaths)).append(" {}\n"); } sb.append(repeat("\t", --indent)).append("}\n"); } //add methods if (!methods.isEmpty()) { sb.append(repeat("\t", indent++)).append("public interface methods {\n"); for (String method : methods) { String methodName = getNonDuplicateName(method, fields); sb.append(repeat("\t", indent)).append("public interface ").append(getNonDuplicateName(methodName, typePaths)).append(" {}\n"); } sb.append(repeat("\t", --indent)).append("}\n"); } //add annotations if (!annotations.isEmpty()) { sb.append(repeat("\t", indent++)).append("public interface annotations {\n"); for (String annotation : annotations) { String nonDuplicateName = annotation; nonDuplicateName = getNonDuplicateName(nonDuplicateName, typePaths); sb.append(repeat("\t", indent)).append("public interface ").append(nonDuplicateName).append(" {}\n"); } sb.append(repeat("\t", --indent)).append("}\n"); } prevPaths = typePaths; } //close indention for (int j = prevPaths.size(); j >= 1; j--) { sb.append(repeat("\t", j)).append("}\n"); } return sb.toString(); } private String getNonDuplicateName(String candidate, List prev, int offset) { String normalized = normalize(candidate); for (int i = 0; i < offset; i++) { if (normalized.equals(prev.get(i))) { return getNonDuplicateName(normalized + tokenSeparator, prev, offset); } } return normalized; } private String normalize(String candidate) { return candidate.replace(dotSeparator, pathSeparator); } private String getNonDuplicateName(String candidate, List prev) { return getNonDuplicateName(candidate, prev, prev.size()); } // public static Class resolveClassOf(final Class element) throws ClassNotFoundException { Class cursor = element; LinkedList ognl = new LinkedList<>(); while (cursor != null) { ognl.addFirst(cursor.getSimpleName()); cursor = cursor.getDeclaringClass(); } String classOgnl = join(ognl.subList(1, ognl.size()), ".").replace(".$", "$"); return Class.forName(classOgnl); } public static Class resolveClass(final Class aClass) { try { return resolveClassOf(aClass); } catch (Exception e) { throw new ReflectionsException("could not resolve to class " + aClass.getName(), e); } } public static Field resolveField(final Class aField) { try { String name = aField.getSimpleName(); Class declaringClass = aField.getDeclaringClass().getDeclaringClass(); return resolveClassOf(declaringClass).getDeclaredField(name); } catch (Exception e) { throw new ReflectionsException("could not resolve to field " + aField.getName(), e); } } public static Annotation resolveAnnotation(Class annotation) { try { String name = annotation.getSimpleName().replace(pathSeparator, dotSeparator); Class declaringClass = annotation.getDeclaringClass().getDeclaringClass(); Class aClass = resolveClassOf(declaringClass); Class aClass1 = (Class) ReflectionUtils.forName(name); Annotation annotation1 = aClass.getAnnotation(aClass1); return annotation1; } catch (Exception e) { throw new ReflectionsException("could not resolve to annotation " + annotation.getName(), e); } } public static Method resolveMethod(final Class aMethod) { String methodOgnl = aMethod.getSimpleName(); try { String methodName; Class[] paramTypes; if (methodOgnl.contains(tokenSeparator)) { methodName = methodOgnl.substring(0, methodOgnl.indexOf(tokenSeparator)); String[] params = methodOgnl.substring(methodOgnl.indexOf(tokenSeparator) + 1).split(doubleSeparator); paramTypes = new Class[params.length]; for (int i = 0; i < params.length; i++) { String typeName = params[i].replace(arrayDescriptor, "[]").replace(pathSeparator, dotSeparator); paramTypes[i] = ReflectionUtils.forName(typeName); } } else { methodName = methodOgnl; paramTypes = null; } Class declaringClass = aMethod.getDeclaringClass().getDeclaringClass(); return resolveClassOf(declaringClass).getDeclaredMethod(methodName, paramTypes); } catch (Exception e) { throw new ReflectionsException("could not resolve to method " + aMethod.getName(), e); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy