All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.kie.kogito.codegen.rules.RuleUnitDTOSourceClass Maven / Gradle / Ivy
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.kogito.codegen.rules;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Stream;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.stmt.BlockStmt;
import org.drools.core.util.ClassUtils;
import org.kie.kogito.codegen.FileGenerator;
import org.kie.kogito.rules.DataSource;
import org.kie.kogito.rules.DataStream;
import static org.drools.core.util.StringUtils.ucFirst;
import static org.drools.modelcompiler.util.ClassUtil.toRawClass;
public class RuleUnitDTOSourceClass implements FileGenerator {
private final Class ruleUnit;
private final String targetCanonicalName;
private final String generatedFilePath;
public RuleUnitDTOSourceClass( Class ruleUnit ) {
this.ruleUnit = ruleUnit;
this.targetCanonicalName = ruleUnit.getSimpleName() + "DTO";
this.generatedFilePath = (ruleUnit.getPackage().getName() + "." + targetCanonicalName).replace('.', '/') + ".java";
}
@Override
public String generatedFilePath() {
return generatedFilePath;
}
@Override
public String generate() {
CompilationUnit cu = new CompilationUnit();
cu.setPackageDeclaration( ruleUnit.getPackage().getName() );
ClassOrInterfaceDeclaration dtoClass = cu.addClass( targetCanonicalName, com.github.javaparser.ast.Modifier.Keyword.PUBLIC );
dtoClass.addImplementedType( "java.util.function.Supplier<" + ruleUnit.getSimpleName() + ">" );
MethodDeclaration supplier = dtoClass.addMethod( "get", com.github.javaparser.ast.Modifier.Keyword.PUBLIC );
supplier.addAnnotation( Override.class );
supplier.setType( ruleUnit.getSimpleName() );
BlockStmt supplierBlock = supplier.createBody();
supplierBlock.addStatement( ruleUnit.getSimpleName() + " unit = new " + ruleUnit.getSimpleName() + "();" );
processUnitFields(field -> processField(dtoClass, supplierBlock, field));
supplierBlock.addStatement( "return unit;" );
return cu.toString();
}
private void processUnitFields(Consumer fieldProcessor) {
Stream.of( ruleUnit.getDeclaredFields() )
.map( this::introspectField )
.filter( Objects::nonNull )
.forEach( fieldProcessor );
}
private void processField(ClassOrInterfaceDeclaration dtoClass, BlockStmt supplierBlock, FieldDescriptor field) {
Class rawType = toRawClass(field.type);
boolean isDataSource = DataSource.class.isAssignableFrom( rawType );
String typeName = field.type.toString();
String genericType = null;
if ( isDataSource ) {
int genericStart = typeName.indexOf( '<' );
if (genericStart > 0) {
genericType = typeName.substring( genericStart+1, typeName.length()-1 );
typeName = "java.util.List" + typeName.substring( genericStart );
} else {
genericType = "Object";
typeName = "java.util.List";
}
}
dtoClass.addField( typeName, field.name, com.github.javaparser.ast.Modifier.Keyword.PRIVATE );
MethodDeclaration getter = dtoClass.addMethod( "get" + ucFirst(field.name), com.github.javaparser.ast.Modifier.Keyword.PUBLIC );
getter.setType( typeName );
getter.createBody().addStatement( "return this." + field.name + ";");
String setterName = "set" + ucFirst(field.name);
MethodDeclaration setter = dtoClass.addMethod( setterName, com.github.javaparser.ast.Modifier.Keyword.PUBLIC );
setter.addParameter( typeName, field.name );
setter.createBody().addStatement( "this." + field.name + " = " + field.name + ";");
if (isDataSource) {
boolean isDataStream = DataStream.class.isAssignableFrom( rawType );
String sourceType = isDataStream ? "Stream" : "Store";
String addMethod = isDataStream ? "append" : "add";
if ( field.kind == FieldKind.GETTABLE ) {
supplierBlock.addStatement( "this." + field.name + ".forEach( unit." + field.getter + "()::" + addMethod + " );" );
return;
} else {
supplierBlock.addStatement( "org.kie.kogito.rules.Data" + sourceType + "<" + genericType + "> " + field.name + " = org.kie.kogito.rules.DataSource.create" + sourceType + "();" );
supplierBlock.addStatement( "this." + field.name + ".forEach( " + field.name + "::" + addMethod + " );" );
}
}
if (field.kind == FieldKind.PUBLIC) {
supplierBlock.addStatement( "unit." + field.name + " = " + field.name + ";" );
} else {
supplierBlock.addStatement( "unit." + setterName + "( " + field.name + " );" );
}
}
private FieldDescriptor introspectField( Field field ) {
String name = field.getName();
if ( Modifier.isPublic( field.getModifiers() ) ) {
return new FieldDescriptor( field.getGenericType(), name, FieldKind.PUBLIC );
}
Method getter = ClassUtils.getAccessor(ruleUnit, name);
if (getter == null) {
return null;
}
try {
ruleUnit.getMethod( "set" + ucFirst(name), field.getType() );
return new FieldDescriptor( field.getGenericType(), name, getter.getName(), FieldKind.SETTABLE );
} catch (NoSuchMethodException e) {
if ( DataSource.class.isAssignableFrom( field.getType() ) ) {
return new FieldDescriptor( field.getGenericType(), name, getter.getName(), FieldKind.GETTABLE );
}
}
return null;
}
private static class FieldDescriptor {
private final Type type;
private final String name;
private final String getter;
private final FieldKind kind;
private FieldDescriptor( Type type, String name, FieldKind kind ) {
this(type, name, null, kind);
}
private FieldDescriptor( Type type, String name, String getter, FieldKind kind ) {
this.type = type;
this.name = name;
this.getter = getter;
this.kind = kind;
}
@Override
public String toString() {
return "FieldDescriptor{" +
"type=" + type +
", name='" + name + '\'' +
", getter='" + getter + '\'' +
", kind=" + kind +
'}';
}
}
private enum FieldKind {
PUBLIC, GETTABLE, SETTABLE
}
}