use of org.kie.api.definition.type.Position in project drools by kiegroup.
the class ClassDefinitionFactory method populateDefinitionFromClass.
public static void populateDefinitionFromClass(ClassDefinition def, Resource resource, Class<?> concrete, boolean asTrait) {
try {
def.setClassName(concrete.getName());
if (concrete.getSuperclass() != null) {
def.setSuperClass(concrete.getSuperclass().getName());
}
ClassFieldInspector inspector = new ClassFieldInspector(concrete);
Map<String, Method> methods = inspector.getGetterMethods();
Map<String, Method> setters = inspector.getSetterMethods();
int j = 0;
Map<String, TypeFieldDescr> fields = new HashMap<String, TypeFieldDescr>();
for (String fieldName : methods.keySet()) {
if (asTrait && ("core".equals(fieldName) || "fields".equals(fieldName))) {
continue;
}
if (!inspector.isNonGetter(fieldName) && setters.keySet().contains(fieldName)) {
Position position = null;
if (!concrete.isInterface()) {
try {
Field fld = concrete.getDeclaredField(fieldName);
position = fld.getAnnotation(Position.class);
} catch (NoSuchFieldException nsfe) {
// @Position can only annotate fields. This x means that a getter/setter pair was found with no field
}
}
Class ret = methods.get(fieldName).getReturnType();
TypeFieldDescr field = new TypeFieldDescr();
field.setResource(resource);
field.setFieldName(fieldName);
field.setPattern(new PatternDescr(ret.getName()));
field.setIndex(position != null ? position.value() : -1);
fields.put(fieldName, field);
}
}
if (!fields.isEmpty()) {
List<FieldDefinition> fieldDefs = sortFields(fields, null, null);
int i = 0;
for (FieldDefinition fieldDef : fieldDefs) {
fieldDef.setIndex(i++);
def.addField(fieldDef);
}
}
Set<String> interfaces = new HashSet<String>();
Collections.addAll(interfaces, def.getInterfaces());
for (Class iKlass : ClassUtils.getAllImplementedInterfaceNames(concrete)) {
interfaces.add(iKlass.getName());
}
def.setInterfaces(interfaces.toArray(new String[interfaces.size()]));
def.setDefinedClass(concrete);
} catch (IOException e) {
e.printStackTrace();
}
}
use of org.kie.api.definition.type.Position in project drools by kiegroup.
the class AnnotationsTest method annotationTest.
@Test
public void annotationTest() {
String drl = "package org.drools.compiler.test;\n " + "" + "import org.kie.api.definition.type.Position; \n " + "import " + AnnotationsTest.class.getCanonicalName() + "; \n" + "import " + AnnotationsTest.Annot.class.getCanonicalName() + "; \n" + "" + "declare AnnotatedBean \n" + " @Deprecated \n" + "" + " @Annot( intProp=7 " + " ,typeProp=String.class " + " ,strProp=\"hello world\" " + " ,enumProp=AnnPropEnum.THREE " + " ,dblArrProp={1.0,2.0} " + " ,typeArrProp={String.class, AnnotationsTest.class} " + " ,strArrProp={\"x1\",\"x2\"} " + " ,enumArrProp={AnnPropEnum.ONE, AnnPropEnum.THREE} " + " ) \n " + " \n " + " @role(event) \n " + " " + " age : int \n" + " name : String @key @Position(0) @Deprecated \n" + " end \n " + " " + " \n\n" + " " + "declare SecondBean \n " + " @NonexistingAnnotation" + " \n" + " field : String @Annot \n" + "end \n";
KieBase kbase = loadKnowledgeBaseFromString(drl);
Class clazz = kbase.getFactType("org.drools.compiler.test", "AnnotatedBean").getFactClass();
assertNotNull(clazz);
try {
Field fld = clazz.getDeclaredField("name");
assertEquals(3, fld.getAnnotations().length);
assertNotNull(fld.getAnnotation(Deprecated.class));
assertNotNull(fld.getAnnotation(Position.class));
assertNotNull(fld.getAnnotation(Key.class));
Position pos = fld.getAnnotation(Position.class);
assertEquals(0, pos.value());
} catch (NoSuchFieldException nsfe) {
fail("field name has not been generated correctly : " + nsfe.getMessage());
}
Annotation[] anns = clazz.getAnnotations();
assertEquals(3, anns.length);
assertNotNull(clazz.getAnnotation(Deprecated.class));
assertNotNull(clazz.getAnnotation(Annot.class));
assertNotNull(clazz.getAnnotation(Role.class));
Annot ann = (Annot) clazz.getAnnotation(Annot.class);
assertEquals(7, ann.intProp());
assertEquals(String.class, ann.typeProp());
assertEquals("hello world", ann.strProp());
assertEquals(AnnPropEnum.THREE, ann.enumProp());
assertArrayEquals(new double[] { 1.0, 2.0 }, ann.dblArrProp(), 1e-16);
assertArrayEquals(new Class[] { String.class, AnnotationsTest.class }, ann.typeArrProp());
assertArrayEquals(new String[] { "x1", "x2" }, ann.strArrProp());
assertArrayEquals(new AnnPropEnum[] { AnnPropEnum.ONE, AnnPropEnum.THREE }, ann.enumArrProp());
Class clazz2 = kbase.getFactType("org.drools.compiler.test", "SecondBean").getFactClass();
assertNotNull(clazz2);
Annotation[] anns2 = clazz2.getAnnotations();
assertEquals(0, anns2.length);
Annot ann2 = null;
try {
Field fld2 = clazz2.getDeclaredField("field");
assertEquals(1, fld2.getAnnotations().length);
assertNotNull(fld2.getAnnotation(Annot.class));
ann2 = fld2.getAnnotation(Annot.class);
} catch (NoSuchFieldException nsfe) {
fail("field name has not been generated correctly : " + nsfe.getMessage());
}
assertNotNull(ann2);
assertEquals(0, ann2.intProp());
assertEquals("foo", ann2.strProp());
assertEquals(AnnPropEnum.ONE, ann2.enumProp());
assertArrayEquals(new double[] { 0.4, 0.5 }, ann2.dblArrProp(), 1e-16);
assertArrayEquals(new String[] { "a", "b", "c" }, ann2.strArrProp());
assertArrayEquals(new AnnPropEnum[] { AnnPropEnum.TWO, AnnPropEnum.THREE }, ann2.enumArrProp());
}
use of org.kie.api.definition.type.Position in project drools by kiegroup.
the class POJOGenerator method toClassDeclaration.
/**
* @param packageDescr
*/
public static ClassOrInterfaceDeclaration toClassDeclaration(TypeDeclarationDescr typeDeclaration, PackageDescr packageDescr) {
EnumSet<Modifier> classModifiers = EnumSet.of(Modifier.PUBLIC);
String generatedClassName = typeDeclaration.getTypeName();
ClassOrInterfaceDeclaration generatedClass = new ClassOrInterfaceDeclaration(classModifiers, false, generatedClassName);
generatedClass.addImplementedType(GeneratedFact.class.getName());
// Ref: {@link org.drools.core.factmodel.DefaultBeanClassBuilder} by default always receive is Serializable.
generatedClass.addImplementedType(Serializable.class.getName());
boolean hasSuper = typeDeclaration.getSuperTypeName() != null;
if (hasSuper) {
generatedClass.addExtendedType(typeDeclaration.getSuperTypeName());
}
List<AnnotationDescr> softAnnotations = new ArrayList<>();
for (AnnotationDescr ann : typeDeclaration.getAnnotations()) {
final String annFqn = Optional.ofNullable(ann.getFullyQualifiedName()).orElse(Optional.ofNullable(predefinedClassLevelAnnotation.get(ann.getName())).map(Class::getCanonicalName).orElse(null));
if (annFqn != null) {
NormalAnnotationExpr annExpr = generatedClass.addAndGetAnnotation(annFqn);
ann.getValueMap().forEach((k, v) -> annExpr.addPair(k, getAnnotationValue(annFqn, k, v.toString())));
} else {
softAnnotations.add(ann);
}
}
if (softAnnotations.size() > 0) {
String softAnnDictionary = softAnnotations.stream().map(a -> "<dt>" + a.getName() + "</dt><dd>" + a.getValuesAsString() + "</dd>").collect(Collectors.joining());
JavadocComment generatedClassJavadoc = new JavadocComment("<dl>" + softAnnDictionary + "</dl>");
generatedClass.setJavadocComment(generatedClassJavadoc);
}
// No-args ctor
generatedClass.addConstructor(Modifier.PUBLIC);
List<Statement> equalsFieldStatement = new ArrayList<>();
List<Statement> hashCodeFieldStatement = new ArrayList<>();
List<String> toStringFieldStatement = new ArrayList<>();
List<TypeFieldDescr> keyFields = new ArrayList<>();
Collection<TypeFieldDescr> inheritedFields = findInheritedDeclaredFields(typeDeclaration, packageDescr);
Collection<TypeFieldDescr> typeFields = typeDeclaration.getFields().values();
if (!inheritedFields.isEmpty() || !typeDeclaration.getFields().isEmpty()) {
ConstructorDeclaration fullArgumentsCtor = generatedClass.addConstructor(Modifier.PUBLIC);
NodeList<Statement> ctorFieldStatement = NodeList.nodeList();
MethodCallExpr superCall = new MethodCallExpr(null, "super");
for (TypeFieldDescr typeFieldDescr : inheritedFields) {
String fieldName = typeFieldDescr.getFieldName();
addCtorArg(fullArgumentsCtor, typeFieldDescr.getPattern().getObjectType(), fieldName);
superCall.addArgument(fieldName);
if (typeFieldDescr.getAnnotation("key") != null) {
keyFields.add(typeFieldDescr);
}
}
ctorFieldStatement.add(new ExpressionStmt(superCall));
int position = inheritedFields.size();
for (TypeFieldDescr typeFieldDescr : typeFields) {
String fieldName = typeFieldDescr.getFieldName();
Type returnType = addCtorArg(fullArgumentsCtor, typeFieldDescr.getPattern().getObjectType(), fieldName);
FieldDeclaration field = generatedClass.addField(returnType, fieldName, Modifier.PRIVATE);
field.createSetter();
field.addAndGetAnnotation(Position.class.getName()).addPair("value", "" + position++);
MethodDeclaration getter = field.createGetter();
equalsFieldStatement.add(generateEqualsForField(getter, fieldName));
hashCodeFieldStatement.addAll(generateHashCodeForField(getter, fieldName));
ctorFieldStatement.add(replaceFieldName(parseStatement("this.__fieldName = __fieldName;"), fieldName));
toStringFieldStatement.add(format("+ {0}+{1}", quote(fieldName + "="), fieldName));
if (typeFieldDescr.getAnnotation("key") != null) {
keyFields.add(typeFieldDescr);
}
}
fullArgumentsCtor.setBody(new BlockStmt(ctorFieldStatement));
if (!keyFields.isEmpty() && keyFields.size() != inheritedFields.size() + typeFields.size()) {
ConstructorDeclaration keyArgumentsCtor = generatedClass.addConstructor(Modifier.PUBLIC);
NodeList<Statement> ctorKeyFieldStatement = NodeList.nodeList();
MethodCallExpr keySuperCall = new MethodCallExpr(null, "super");
ctorKeyFieldStatement.add(new ExpressionStmt(keySuperCall));
for (TypeFieldDescr typeFieldDescr : keyFields) {
String fieldName = typeFieldDescr.getFieldName();
addCtorArg(keyArgumentsCtor, typeFieldDescr.getPattern().getObjectType(), fieldName);
if (typeDeclaration.getFields().get(fieldName) != null) {
ctorKeyFieldStatement.add(replaceFieldName(parseStatement("this.__fieldName = __fieldName;"), fieldName));
} else {
keySuperCall.addArgument(fieldName);
}
}
keyArgumentsCtor.setBody(new BlockStmt(ctorKeyFieldStatement));
}
if (hasSuper) {
generatedClass.addMember(generateEqualsMethod(generatedClassName, equalsFieldStatement));
generatedClass.addMember(generateHashCodeMethod(hashCodeFieldStatement));
}
}
generatedClass.addMember(generateToStringMethod(generatedClassName, toStringFieldStatement));
return generatedClass;
}
use of org.kie.api.definition.type.Position in project drools by kiegroup.
the class ClassDefinitionFactory method sortFields.
private static List<FieldDefinition> sortFields(Map<String, TypeFieldDescr> fields, TypeResolver typeResolver, KnowledgeBuilderImpl kbuilder) {
List<FieldDefinition> fieldDefs = new ArrayList<FieldDefinition>(fields.size());
int maxDeclaredPos = 0;
BitSet occupiedPositions = new BitSet(fields.size());
for (TypeFieldDescr field : fields.values()) {
String typeName = field.getPattern().getObjectType();
String typeNameKey = typeName;
String fullFieldType = kbuilder != null ? TypeDeclarationUtils.toBuildableType(typeNameKey, kbuilder.getRootClassLoader()) : typeNameKey;
FieldDefinition fieldDef = new FieldDefinition(field.getFieldName(), fullFieldType);
fieldDefs.add(fieldDef);
if (field.hasOverride()) {
fieldDef.setOverriding(field.getOverriding().getPattern().getObjectType());
}
fieldDef.setInherited(field.isInherited());
fieldDef.setRecursive(field.isRecursive());
fieldDef.setInitExpr(TypeDeclarationUtils.rewriteInitExprWithImports(field.getInitExpr(), typeResolver));
if (field.getIndex() >= 0) {
int pos = field.getIndex();
occupiedPositions.set(pos);
maxDeclaredPos = Math.max(maxDeclaredPos, pos);
fieldDef.addMetaData("position", pos);
} else {
Position position = field.getTypedAnnotation(Position.class);
if (position != null) {
int pos = position.value();
field.setIndex(pos);
occupiedPositions.set(pos);
maxDeclaredPos = Math.max(maxDeclaredPos, pos);
fieldDef.addMetaData("position", pos);
}
}
if (field.hasAnnotation(Key.class)) {
fieldDef.setKey(true);
fieldDef.addMetaData("key", null);
}
for (AnnotationDescr annotationDescr : field.getAnnotations()) {
if (annotationDescr.getFullyQualifiedName() == null) {
if (annotationDescr.isStrict()) {
kbuilder.addBuilderResult(new TypeDeclarationError(field, "Unknown annotation @" + annotationDescr.getName() + " on field " + field.getFieldName()));
} else {
// Annotation is custom metadata
fieldDef.addMetaData(annotationDescr.getName(), annotationDescr.getSingleValue());
continue;
}
}
Annotation annotation = AnnotationFactory.buildAnnotation(typeResolver, annotationDescr);
if (annotation != null) {
try {
AnnotationDefinition annotationDefinition = AnnotationDefinition.build(annotation.annotationType(), field.getAnnotation(annotationDescr.getFullyQualifiedName()).getValueMap(), typeResolver);
fieldDef.addAnnotation(annotationDefinition);
} catch (Exception e) {
kbuilder.addBuilderResult(new TypeDeclarationError(field, "Annotated field " + field.getFieldName() + " - undefined property in @annotation " + annotationDescr.getName() + ": " + e.getMessage() + ";"));
}
} else {
if (annotationDescr.isStrict()) {
kbuilder.addBuilderResult(new TypeDeclarationError(field, "Unknown annotation @" + annotationDescr.getName() + " on field " + field.getFieldName()));
}
}
}
fieldDef.setDeclIndex(field.getIndex());
}
int curr = 0;
for (FieldDefinition fieldDef : fieldDefs) {
if (fieldDef.getDeclIndex() < 0) {
int freePos = occupiedPositions.nextClearBit(0);
if (freePos < maxDeclaredPos) {
occupiedPositions.set(freePos);
} else {
freePos = maxDeclaredPos + 1;
}
fieldDef.setPriority(freePos * 256 + curr++);
} else {
fieldDef.setPriority(fieldDef.getDeclIndex() * 256 + curr++);
}
}
Collections.sort(fieldDefs);
return fieldDefs;
}
use of org.kie.api.definition.type.Position in project drools by kiegroup.
the class TypeDeclarationCache method processFieldsPosition.
private void processFieldsPosition(Class<?> cls, ClassDefinition clsDef, TypeDeclaration typeDeclaration) {
// it's a new type declaration, so generate the @Position for it
Collection<Field> fields = new LinkedList<Field>();
Class<?> tempKlass = cls;
while (tempKlass != null && tempKlass != Object.class) {
Collections.addAll(fields, tempKlass.getDeclaredFields());
tempKlass = tempKlass.getSuperclass();
}
FieldDefinition[] orderedFields = new FieldDefinition[fields.size()];
for (Field fld : fields) {
Position pos = fld.getAnnotation(Position.class);
if (pos != null) {
if (pos.value() < 0 || pos.value() >= fields.size()) {
kbuilder.addBuilderResult(new TypeDeclarationError(typeDeclaration, "Out of range position " + pos.value() + " for field '" + fld.getName() + "' on class " + cls.getName()));
continue;
}
if (orderedFields[pos.value()] != null) {
kbuilder.addBuilderResult(new TypeDeclarationError(typeDeclaration, "Duplicated position " + pos.value() + " for field '" + fld.getName() + "' on class " + cls.getName()));
continue;
}
FieldDefinition fldDef = clsDef.getField(fld.getName());
if (fldDef == null) {
fldDef = new FieldDefinition(fld.getName(), fld.getType().getName());
}
fldDef.setIndex(pos.value());
orderedFields[pos.value()] = fldDef;
}
}
for (FieldDefinition fld : orderedFields) {
if (fld != null) {
// it's null if there is no @Position
clsDef.addField(fld);
}
}
}
Aggregations