
org.hyperledger.composer.bna.util.JavaParser Maven / Gradle / Ivy
The newest version!
/*
* Copyright IBM Corp. 2017 All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.composer.bna.util;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hyperledger.composer.ComposerException;
import org.hyperledger.composer.annotation.DataField;
import org.hyperledger.composer.annotation.Pointer;
import org.hyperledger.composer.annotation.Query;
import org.hyperledger.composer.bna.model.EnumModel;
import org.hyperledger.composer.bna.model.FieldModel;
import org.hyperledger.composer.bna.model.FunctionModel;
import org.hyperledger.composer.bna.model.Model;
import org.hyperledger.composer.bna.model.QueryModel;
import org.hyperledger.composer.bna.part.CtoPart;
import org.hyperledger.composer.bna.part.QueryPart;
import org.hyperledger.composer.query.QueryBuilder;
import org.hyperledger.composer.query.SelectQuery;
import org.reflections.Reflections;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JavaParser {
protected static final Logger logger = LoggerFactory.getLogger(JavaParser.class);
private Reflections reflections;
protected JavaParser(Reflections reflections) {
this.reflections = reflections;
}
public JavaParser(List sourceClassFiles) {
this(sourceClassFiles, null);
}
/**
* constructor.
*
* @param sourceClassFiles source class files
* @param parent parent {@code ClassLoader}
*/
public JavaParser(List sourceClassFiles, ClassLoader parent) {
this(new Reflections(getClassloaderForReflections(sourceClassFiles, parent),
new TypeAnnotationsScanner(), new FieldAnnotationsScanner(),
new SubTypesScanner(), new MethodAnnotationsScanner()));
}
static URLClassLoader getClassloaderForReflections(List sourceClassFiles,
ClassLoader parentClassLoader) {
List sourceClassUrls = new LinkedList<>();
Set loadedUrl = new HashSet<>();
if (parentClassLoader instanceof URLClassLoader) {
loadedUrl.addAll(Arrays.asList(((URLClassLoader) parentClassLoader).getURLs()));
}
for (File file : sourceClassFiles) {
try {
URL url = file.toURI().toURL();
logger.info("find {}", url.toString());
if (!loadedUrl.contains(url)) {
sourceClassUrls.add(url);
loadedUrl.add(url);
}
} catch (MalformedURLException e) {
logger.warn("fail to get uri of {}: {}", file.getAbsolutePath(), e.getMessage());
}
}
return new URLClassLoader(sourceClassUrls.toArray(new URL[sourceClassUrls.size()]),
parentClassLoader);
}
protected QueryPart parseQueryModel() throws ComposerException {
QueryPart manager = new QueryPart();
for (Method m : getMethodsAnnotatedWith(Query.class)) {
if (m.getParameterCount() != 1) {
throw new ComposerException(ComposerException.INVALID_INPUT_ERROR,
"expect 1 parameters for transaction processor:" + m);
}
Class> selectQueryClass = m.getParameterTypes()[0];
if (!SelectQuery.class.isAssignableFrom(selectQueryClass)) {
throw new ComposerException(ComposerException.INVALID_INPUT_ERROR,
"expect the 1nd parameter typeof SelectQuery for " + m);
}
if (!QueryBuilder.class.isAssignableFrom(m.getReturnType())) {
throw new ComposerException(ComposerException.INVALID_INPUT_ERROR,
"expect the return value typeof QueryBuilder for " + m);
}
FunctionModel model = new FunctionModel(m);
logger.debug("Found QueryBuilderFunction {}", model);
final Query query = m.getAnnotation(Query.class);
final QueryBuilder builder;
try {
builder = (QueryBuilder) model.invoke(selectQueryClass.newInstance());
} catch (Throwable e) {
throw new ComposerException(ComposerException.INVALID_INPUT_ERROR,
"fail to build query " + m + ":" + e.getMessage());
}
manager.addEntry(new QueryModel(query.description(), builder.build().getSql()));
}
return manager;
}
protected Collection parseCtoModel() throws ComposerException {
Map result = new HashMap<>();
for (Class extends Annotation> annotation : Model.MODEL_ANNOTATIONS) {
for (Class c : getTypesAnnotatedWith(annotation)) {
parseCtoModel(result, annotation, c);
}
}
return result.values();
}
protected void parseCtoModel(Map result, Class extends Annotation> annotation,
Class c) throws ComposerException {
String namespace = c.getPackage().getName();
if ("org.hyperledger.composer.system".equals(namespace)) {
return;
}
Model model = new Model(result.computeIfAbsent(namespace, CtoPart::new))
.namespace(namespace).type(annotation).name(c.getSimpleName());
Class superClass = c.getSuperclass();
if (!Object.class.equals(superClass)) {
if (!superClass.isAnnotationPresent(annotation)) {
throw new ComposerException(ComposerException.INVALID_INPUT_ERROR,
"parent of '" + c.getName() + "' is '" + superClass.getName()
+ "', not annotated with @" + annotation.getSimpleName());
} else {
model.parent(superClass.getPackage().getName(), superClass.getSimpleName());
}
}
for (Field field : c.getDeclaredFields()) {
FieldModel fieldModel = null;
DataField dataField = field.getAnnotation(DataField.class);
if (dataField != null) {
fieldModel = new FieldModel(field, dataField.optional(), dataField.embedded(),
dataField.regex(), dataField.range(), dataField.defaultValue(),
dataField.genericType());
model.addField(fieldModel, dataField.primary());
}
Pointer pointerField = field.getAnnotation(Pointer.class);
if (pointerField != null) {
fieldModel = new FieldModel(field, pointerField.optional(), false, null,
null, null, pointerField.genericType());
model.addField(fieldModel, false);
}
if (fieldModel == null) {
continue;
}
if (fieldModel.isEnum()) {
Class> enumType = field.getType();
new EnumModel(result.computeIfAbsent(enumType.getPackage().getName(), CtoPart::new),
enumType);
}
}
}
protected Set getMethodsAnnotatedWith(Class extends Annotation> annotation) {
return reflections.getMethodsAnnotatedWith(annotation);
}
protected Set getTypesAnnotatedWith(Class extends Annotation>... annotations) {
Set result = new HashSet<>();
for (Class extends Annotation> annotation : annotations) {
result.addAll(reflections.getTypesAnnotatedWith(annotation));
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy