Search in sources :

Example 1 with ClassFieldInspector

use of org.drools.core.base.ClassFieldInspector in project drools by kiegroup.

the class ClassFieldAccessorFactory method getClassFieldReader.

@Override
public BaseClassFieldReader getClassFieldReader(Class<?> clazz, String fieldName, CacheEntry cache) {
    try {
        // if it is a self reference
        if (SELF_REFERENCE_FIELD.equals(fieldName)) {
            // then just create an instance of the special class field extractor
            return new SelfReferenceClassFieldReader(clazz);
        } else {
            // otherwise, bytecode generate a specific extractor
            ClassFieldInspector inspector = getClassFieldInspector(clazz, cache);
            Method getterMethod = inspector.getGetterMethods().get(fieldName);
            Integer index = inspector.getFieldNames().get(fieldName);
            Class<?> fieldType = inspector.getFieldType(fieldName);
            if (fieldType == null && fieldName.length() > 1 && Character.isLowerCase(fieldName.charAt(0)) && Character.isUpperCase(fieldName.charAt(1))) {
                // it might be that odd case of javabeans naming conventions that does not use lower case first letters if the second is uppercase
                String altFieldName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
                fieldType = inspector.getFieldType(altFieldName);
                if (fieldType != null) {
                    // it seems it is the corner case indeed.
                    getterMethod = inspector.getGetterMethods().get(altFieldName);
                    index = inspector.getFieldNames().get(altFieldName);
                }
            }
            if (fieldType != null && getterMethod != null) {
                final String className = ClassFieldAccessorFactory.BASE_PACKAGE + "/" + Type.getInternalName(clazz) + Math.abs((long) System.identityHashCode(clazz)) + "$" + getterMethod.getName();
                // generating byte array to create target class
                final byte[] bytes = dumpReader(clazz, className, getterMethod, fieldType);
                // use bytes to get a class
                ByteArrayClassLoader byteArrayClassLoader = cache.getByteArrayClassLoader();
                final Class<?> newClass = byteArrayClassLoader.defineClass(className.replace('/', '.'), bytes, PROTECTION_DOMAIN);
                // instantiating target class
                final ValueType valueType = ValueType.determineValueType(fieldType);
                final Object[] params = { index, fieldType, valueType };
                return (BaseClassFieldReader) newClass.getConstructors()[0].newInstance(params);
            } else {
                // must be a public field
                return null;
            }
        }
    } catch (final RuntimeException e) {
        throw e;
    } catch (final Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : ValueType(org.drools.core.base.ValueType) ByteArrayClassLoader(org.drools.wiring.api.util.ByteArrayClassLoader) Method(java.lang.reflect.Method) BaseClassFieldReader(org.drools.core.base.BaseClassFieldReader) SelfReferenceClassFieldReader(org.drools.core.base.extractors.SelfReferenceClassFieldReader) ClassFieldAccessorStore.getClassFieldInspector(org.drools.mvel.accessors.ClassFieldAccessorStore.getClassFieldInspector) ClassFieldInspector(org.drools.core.base.ClassFieldInspector)

Example 2 with ClassFieldInspector

use of org.drools.core.base.ClassFieldInspector 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 = CoreComponentsBuilder.get().createClassFieldInspector(concrete);
        Map<String, Method> methods = inspector.getGetterMethods();
        Map<String, Method> setters = inspector.getSetterMethods();
        Map<String, TypeFieldDescr> fields = new HashMap<>();
        for (String fieldName : methods.keySet()) {
            if (asTrait && ("core".equals(fieldName) || "fields".equals(fieldName))) {
                continue;
            }
            if (!inspector.isNonGetter(fieldName) && setters.containsKey(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<>();
        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();
    }
}
Also used : PatternDescr(org.drools.drl.ast.descr.PatternDescr) HashMap(java.util.HashMap) Position(org.kie.api.definition.type.Position) FieldDefinition(org.drools.core.factmodel.FieldDefinition) Method(java.lang.reflect.Method) IOException(java.io.IOException) Field(java.lang.reflect.Field) TypeFieldDescr(org.drools.drl.ast.descr.TypeFieldDescr) ClassFieldInspector(org.drools.core.base.ClassFieldInspector) HashSet(java.util.HashSet)

Example 3 with ClassFieldInspector

use of org.drools.core.base.ClassFieldInspector in project drools by kiegroup.

the class ClassHierarchyManager method buildDescrsFromFields.

private static void buildDescrsFromFields(Class klass, TypeDeclarationDescr typeDescr, Map<String, TypeFieldDescr> fieldMap) {
    ClassFieldInspector inspector;
    try {
        inspector = CoreComponentsBuilder.get().createClassFieldInspector(klass);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    for (String name : inspector.getGetterMethods().keySet()) {
        // classFieldAccessor requires both getter and setter
        if (inspector.getSetterMethods().containsKey(name)) {
            if (!inspector.isNonGetter(name) && !"class".equals(name)) {
                Resource resource = typeDescr.getResource();
                PatternDescr patternDescr = new PatternDescr(inspector.getFieldType(name).getName());
                patternDescr.setResource(resource);
                TypeFieldDescr inheritedFlDescr = new TypeFieldDescr(name, patternDescr);
                inheritedFlDescr.setResource(resource);
                inheritedFlDescr.setInherited(!Modifier.isAbstract(inspector.getGetterMethods().get(name).getModifiers()));
                if (!fieldMap.containsKey(inheritedFlDescr.getFieldName()))
                    fieldMap.put(inheritedFlDescr.getFieldName(), inheritedFlDescr);
            }
        }
    }
}
Also used : PatternDescr(org.drools.drl.ast.descr.PatternDescr) TypeFieldDescr(org.drools.drl.ast.descr.TypeFieldDescr) Resource(org.kie.api.io.Resource) IOException(java.io.IOException) ClassFieldInspector(org.drools.core.base.ClassFieldInspector)

Example 4 with ClassFieldInspector

use of org.drools.core.base.ClassFieldInspector in project drools by kiegroup.

the class TypeDeclarationFactory method checkRedeclaration.

protected void checkRedeclaration(AbstractClassTypeDeclarationDescr typeDescr, TypeDeclaration type, PackageRegistry pkgRegistry) {
    TypeDeclaration previousTypeDeclaration = kbuilder.getPackageRegistry(typeDescr.getNamespace()).getPackage().getTypeDeclaration(typeDescr.getTypeName());
    try {
        // to the behavior previous these changes
        if (!type.isDefinition()) {
            // new declarations of a POJO can't declare new fields,
            // except if the POJO was previously generated/compiled and saved into the kjar
            Class<?> existingDeclarationClass = TypeDeclarationUtils.getExistingDeclarationClass(typeDescr, pkgRegistry);
            if (!kbuilder.getBuilderConfiguration().isPreCompiled() && !GeneratedFact.class.isAssignableFrom(existingDeclarationClass) && !type.getTypeClassDef().getFields().isEmpty()) {
                try {
                    Class existingClass = pkgRegistry.getPackage().getTypeResolver().resolveType(typeDescr.getType().getFullName());
                    ClassFieldInspector cfi = CoreComponentsBuilder.get().createClassFieldInspector(existingClass);
                    int fieldCount = 0;
                    for (String existingFieldName : cfi.getFieldTypesField().keySet()) {
                        if (!cfi.isNonGetter(existingFieldName) && !"class".equals(existingFieldName) && cfi.getSetterMethods().containsKey(existingFieldName) && cfi.getGetterMethods().containsKey(existingFieldName)) {
                            if (!typeDescr.getFields().containsKey(existingFieldName)) {
                                type.setValid(false);
                                kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "New declaration of " + typeDescr.getType().getFullName() + " does not include field " + existingFieldName));
                            } else {
                                String fldType = cfi.getFieldType(existingFieldName).getName();
                                fldType = TypeDeclarationUtils.toBuildableType(fldType, kbuilder.getRootClassLoader());
                                TypeFieldDescr declaredField = typeDescr.getFields().get(existingFieldName);
                                if (!fldType.equals(type.getTypeClassDef().getField(existingFieldName).getTypeName())) {
                                    type.setValid(false);
                                    kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "New declaration of " + typeDescr.getType().getFullName() + " redeclared field " + existingFieldName + " : \n" + "existing : " + fldType + " vs declared : " + declaredField.getPattern().getObjectType()));
                                } else {
                                    fieldCount++;
                                }
                            }
                        }
                    }
                    if (fieldCount != typeDescr.getFields().size()) {
                        kbuilder.addBuilderResult(reportDeclarationDiff(cfi, typeDescr));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    type.setValid(false);
                    kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Unable to redeclare " + typeDescr.getType().getFullName() + " : " + e.getMessage()));
                } catch (ClassNotFoundException e) {
                    type.setValid(false);
                    kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Unable to redeclare " + typeDescr.getType().getFullName() + " : " + e.getMessage()));
                }
            }
        } else if (previousTypeDeclaration != null) {
            // previous declaration can be null during an incremental compilation
            int typeComparisonResult = this.compareTypeDeclarations(previousTypeDeclaration, type);
            if (typeComparisonResult < 0) {
                // oldDeclaration is "less" than newDeclaration -> error
                kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, typeDescr.getType().getFullName() + " declares more fields than the already existing version"));
                type.setValid(false);
            } else if (typeComparisonResult > 0 && !type.getTypeClassDef().getFields().isEmpty()) {
                // oldDeclaration is "grater" than newDeclaration -> error
                kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, typeDescr.getType().getFullName() + " declares less fields than the already existing version"));
                type.setValid(false);
            }
            // fields present in the previous declaration
            if (type.getNature() == TypeDeclaration.Nature.DECLARATION) {
                mergeTypeDeclarations(previousTypeDeclaration, type);
            }
        }
    } catch (IncompatibleClassChangeError error) {
        // if the types are incompatible -> error
        kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, error.getMessage()));
    }
}
Also used : TypeDeclarationError(org.drools.compiler.compiler.TypeDeclarationError) TypeFieldDescr(org.drools.drl.ast.descr.TypeFieldDescr) IOException(java.io.IOException) TypeDeclaration(org.drools.core.rule.TypeDeclaration) GeneratedFact(org.drools.core.factmodel.GeneratedFact) ClassFieldInspector(org.drools.core.base.ClassFieldInspector)

Example 5 with ClassFieldInspector

use of org.drools.core.base.ClassFieldInspector in project drools by kiegroup.

the class TypeDeclarationUtils method isCompatible.

public static boolean isCompatible(Class<?> typeClass, AbstractClassTypeDeclarationDescr typeDescr) {
    try {
        if (typeDescr.getFields().isEmpty()) {
            return true;
        }
        Class<?> sup = typeClass.getSuperclass();
        if (sup == null) {
            return true;
        }
        if (!sup.getName().equals(typeDescr.getSupertTypeFullName())) {
            return false;
        }
        ClassFieldInspector cfi = CoreComponentsBuilder.get().createClassFieldInspector(typeClass, false);
        if (cfi.getGetterMethods().size() != typeDescr.getFields().size()) {
            return false;
        }
        for (String fieldName : cfi.getFieldTypes().keySet()) {
            if (!typeDescr.getFields().containsKey(fieldName)) {
                return false;
            }
            String fieldTypeName = typeDescr.getFields().get(fieldName).getPattern().getObjectType();
            Class fieldType = cfi.getFieldTypes().get(fieldName);
            if (!fieldTypeName.equals(fieldType.getName()) || !fieldTypeName.equals(fieldType.getSimpleName())) {
                return false;
            }
        }
    } catch (IOException e) {
        return false;
    }
    return true;
}
Also used : IOException(java.io.IOException) ClassFieldInspector(org.drools.core.base.ClassFieldInspector)

Aggregations

ClassFieldInspector (org.drools.core.base.ClassFieldInspector)8 IOException (java.io.IOException)5 Method (java.lang.reflect.Method)3 TypeFieldDescr (org.drools.drl.ast.descr.TypeFieldDescr)3 ValueType (org.drools.core.base.ValueType)2 PatternDescr (org.drools.drl.ast.descr.PatternDescr)2 ClassFieldAccessorStore.getClassFieldInspector (org.drools.mvel.accessors.ClassFieldAccessorStore.getClassFieldInspector)2 ByteArrayClassLoader (org.drools.wiring.api.util.ByteArrayClassLoader)2 UncheckedIOException (java.io.UncheckedIOException)1 Field (java.lang.reflect.Field)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 TypeDeclarationError (org.drools.compiler.compiler.TypeDeclarationError)1 BaseClassFieldReader (org.drools.core.base.BaseClassFieldReader)1 BaseClassFieldWriter (org.drools.core.base.BaseClassFieldWriter)1 ClassFieldAccessorCache (org.drools.core.base.ClassFieldAccessorCache)1 SelfReferenceClassFieldReader (org.drools.core.base.extractors.SelfReferenceClassFieldReader)1 FieldDefinition (org.drools.core.factmodel.FieldDefinition)1 GeneratedFact (org.drools.core.factmodel.GeneratedFact)1 TypeDeclaration (org.drools.core.rule.TypeDeclaration)1