private void processTypeAnnotations( AbstractClassTypeDeclarationDescr typeDescr, TypeDeclaration type) { try { Role role = typeDescr.getTypedAnnotation(Role.class); if (role != null) { type.setRole(role.value()); } TypeSafe typeSafe = typeDescr.getTypedAnnotation(TypeSafe.class); if (typeSafe != null) { type.setTypesafe(typeSafe.value()); } if (typeDescr instanceof EnumDeclarationDescr) { type.setKind(TypeDeclaration.Kind.ENUM); } else if (typeDescr instanceof TypeDeclarationDescr && ((TypeDeclarationDescr) typeDescr).isTrait()) { type.setKind(TypeDeclaration.Kind.TRAIT); } type.setDynamic(typeDescr.hasAnnotation(PropertyChangeSupport.class)); } catch (Exception e) { kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, e.getMessage())); } }
public ClassObjectTypeConf( final EntryPointId entryPoint, final Class<?> clazz, final InternalKnowledgeBase kBase) { this.cls = (Activation.class.isAssignableFrom(clazz)) ? ClassObjectType.Match_ObjectType.getClassType() : clazz; this.kBase = kBase; this.entryPoint = entryPoint; this.typeDecl = kBase.getTypeDeclaration(clazz); isEvent = typeDecl != null && typeDecl.getRole() == Role.Type.EVENT; if (isEvent) { expirationOffset = typeDecl.getExpirationOffset(); } isTrait = determineTraitStatus(); this.objectType = kBase .getClassFieldAccessorCache() .getClassObjectType(new ClassObjectType(clazz, isEvent), false); this.concreteObjectTypeNode = kBase.getRete().getObjectTypeNodes(entryPoint).get(objectType); this.supportsPropertyListeners = checkPropertyListenerSupport(clazz); Traitable ttbl = cls.getAnnotation(Traitable.class); this.traitTmsEnabled = ttbl != null && ttbl.logical(); }
protected boolean determineTraitStatus() { return typeDecl != null && (typeDecl.getKind() == TypeDeclaration.Kind.TRAIT || typeDecl.getTypeClassDef().isTraitable() || typeDecl.getTypeClass().getAnnotation(Traitable.class) != null) || Thing.class.isAssignableFrom(cls) || TraitableBean.class.isAssignableFrom(cls); }
/** * Returns true if clazz is imported as an Event class in this package * * @param clazz * @return true if clazz is imported as an Event class in this package */ public boolean isEvent(Class clazz) { TypeDeclaration typeDeclaration = getTypeDeclaration(clazz); if (typeDeclaration != null) { return typeDeclaration.getRole() == Role.Type.EVENT; } Role role = (Role) clazz.getAnnotation(Role.class); return role != null && role.value() == Role.Type.EVENT; }
private List<TypeDeclaration> getTypesGeneratedFromResource(Resource resource) { List<TypeDeclaration> typesFromResource = new ArrayList<TypeDeclaration>(); for (TypeDeclaration type : typeDeclarations.values()) { if (resource.equals(type.getResource())) { typesFromResource.add(type); } } return typesFromResource; }
public Collection<FactType> getFactTypes() { if (typeDeclarations.isEmpty()) { return Collections.emptyList(); } List<FactType> list = new ArrayList<FactType>(); for (TypeDeclaration typeDeclaration : typeDeclarations.values()) { list.add(typeDeclaration.getTypeClassDef()); } return Collections.unmodifiableCollection(list); }
protected boolean determineTraitStatus() { return typeDecl != null // if cls implements an interface and cls is never actually used, typeDecl will // reference the interface // rather than the actual class, but this may not reflect the actual traitability && typeDecl.getTypeClass() == cls && (typeDecl.getKind() == TypeDeclaration.Kind.TRAIT || typeDecl.getTypeClassDef().isTraitable() || typeDecl.getTypeClass().getAnnotation(Traitable.class) != null) || Thing.class.isAssignableFrom(cls) || cls.getAnnotation(Traitable.class) != null || TraitableBean.class.isAssignableFrom(cls); }
public TypeDeclaration getTypeDeclaration(Class<?> clazz) { if (clazz == null) { return null; } TypeDeclaration typeDeclaration = getTypeDeclaration(clazz.getSimpleName()); if (typeDeclaration == null) { // check if clazz is resolved by any of the type declarations for (TypeDeclaration type : this.typeDeclarations.values()) { if (type.isValid() && type.matches(clazz)) { typeDeclaration = type; break; } } } return typeDeclaration; }
/** Merges all the missing FactFields from oldDefinition into newDeclaration. */ protected void mergeTypeDeclarations( TypeDeclaration oldDeclaration, TypeDeclaration newDeclaration) { if (oldDeclaration == null) { return; } // add the missing fields (if any) to newDeclaration for (FieldDefinition oldFactField : oldDeclaration.getTypeClassDef().getFieldsDefinitions()) { FieldDefinition newFactField = newDeclaration.getTypeClassDef().getField(oldFactField.getName()); if (newFactField == null) { newDeclaration.getTypeClassDef().addField(oldFactField); } } // copy the defined class newDeclaration.setTypeClass(oldDeclaration.getTypeClass()); }
public List<TypeDeclaration> removeTypesGeneratedFromResource(Resource resource) { List<TypeDeclaration> typesToBeRemoved = getTypesGeneratedFromResource(resource); if (!typesToBeRemoved.isEmpty()) { JavaDialectRuntimeData dialect = (JavaDialectRuntimeData) getDialectRuntimeRegistry().getDialectData("java"); for (TypeDeclaration type : typesToBeRemoved) { if (type.getTypeClassName() != null) { // the type declaration might not have been built up to actual class, if an error was // found first // in this case, no accessor would have been wired classFieldAccessorStore.removeType(type); dialect.remove(type.getTypeClassName()); } removeTypeDeclaration(type.getTypeName()); } dialect.reload(); } return typesToBeRemoved; }
public TypeDeclaration processTypeDeclaration( PackageRegistry pkgRegistry, AbstractClassTypeDeclarationDescr typeDescr) { TypeDeclaration type = kbuilder.getTypeBuilder().getExistingTypeDeclaration(typeDescr.getFullTypeName()); if (type == null) { type = new TypeDeclaration(typeDescr.getTypeName()); type.setResource(typeDescr.getResource()); // if is not new, search the already existing declaration and // compare them o see if they are at least compatibles // check whether it is necessary to build the class or not type.setNovel(TypeDeclarationUtils.isNovelClass(typeDescr, pkgRegistry)); type.setNature( type.isNovel() ? TypeDeclaration.Nature.DEFINITION : TypeDeclaration.Nature.DECLARATION); } processTypeAnnotations(typeDescr, type); return type; }
public FactType getFactType(final String typeName) { if (typeName == null || (this.name != null && !typeName.startsWith(this.name + "."))) { return null; } // in case the package name is != null, remove the package name from the // beginning of the type name String key = this.name == null ? typeName : typeName.substring(this.name.length() + 1); TypeDeclaration decl = this.typeDeclarations.get(key); if (decl == null) { return null; } else { if (decl.isDefinition()) { return decl.getTypeClassDef(); } else { throw new UnsupportedOperationException( "KieBase.getFactType should only be used to retrieve declared beans. Class " + typeName + " exists outside DRL "); } } }
public ClassObjectTypeConf( final EntryPointId entryPoint, final Class<?> clazz, final InternalKnowledgeBase kBase) { this.cls = (Activation.class.isAssignableFrom(clazz)) ? ClassObjectType.Match_ObjectType.getClassType() : clazz; this.kBase = kBase; this.entryPoint = entryPoint; this.typeDecl = kBase.getTypeDeclaration(clazz); isEvent = typeDecl != null && typeDecl.getRole() == TypeDeclaration.Role.EVENT; isTrait = determineTraitStatus(); ObjectType objectType = kBase.getClassFieldAccessorCache().getClassObjectType(new ClassObjectType(clazz, isEvent)); this.concreteObjectTypeNode = kBase.getRete().getObjectTypeNodes(entryPoint).get(objectType); if (this.concreteObjectTypeNode == null) { BuildContext context = new BuildContext(kBase, kBase.getReteooBuilder().getIdGenerator()); context.setCurrentEntryPoint(entryPoint); if (DroolsQuery.class == clazz) { context.setTupleMemoryEnabled(false); context.setObjectTypeNodeMemoryEnabled(false); } else if (context.getKnowledgeBase().getConfiguration().isSequential()) { // We are in sequential mode, so no nodes should have memory // context.setTupleMemoryEnabled( false ); // context.setObjectTypeNodeMemoryEnabled( false ); context.setTupleMemoryEnabled(true); context.setObjectTypeNodeMemoryEnabled(true); } else { context.setTupleMemoryEnabled(true); context.setObjectTypeNodeMemoryEnabled(true); } // there must exist an ObjectTypeNode for this concrete class this.concreteObjectTypeNode = PatternBuilder.attachObjectTypeNode(context, objectType); } this.supportsPropertyListeners = checkPropertyListenerSupport(clazz); Traitable ttbl = cls.getAnnotation(Traitable.class); this.traitTmsEnabled = ttbl != null && ttbl.logical(); }
public void addTypeDeclaration(final TypeDeclaration typeDecl) { this.typeDeclarations.put(typeDecl.getTypeName(), typeDecl); }
protected void checkRedeclaration( AbstractClassTypeDeclarationDescr typeDescr, TypeDeclaration type, PackageRegistry pkgRegistry) { TypeDeclaration previousTypeDeclaration = kbuilder .getPackageRegistry(typeDescr.getNamespace()) .getPackage() .getTypeDeclaration(typeDescr.getTypeName()); try { // if there is no previous declaration, then the original declaration was a POJO // to the behavior previous these changes if (previousTypeDeclaration == null) { // 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 = new ClassFieldInspector(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.getFieldTypes().get(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 { 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); } // if they are "equal" -> no problem // in the case of a declaration, we need to copy all the // 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())); } }
public boolean isDynamic() { return typeDecl != null && typeDecl.isDynamic(); }
protected int compareTypeDeclarations( TypeDeclaration oldDeclaration, TypeDeclaration newDeclaration) throws IncompatibleClassChangeError { // different formats -> incompatible if (!oldDeclaration.getFormat().equals(newDeclaration.getFormat())) { throw new IncompatibleClassChangeError( "Type Declaration " + newDeclaration.getTypeName() + " has a different" + " format that its previous definition: " + newDeclaration.getFormat() + "!=" + oldDeclaration.getFormat()); } // different superclasses -> Incompatible (TODO: check for hierarchy) if (!oldDeclaration .getTypeClassDef() .getSuperClass() .equals(newDeclaration.getTypeClassDef().getSuperClass())) { if (oldDeclaration.getNature() == TypeDeclaration.Nature.DEFINITION && newDeclaration.getNature() == TypeDeclaration.Nature.DECLARATION && Object.class.getName().equals(newDeclaration.getTypeClassDef().getSuperClass())) { // actually do nothing. The new declaration just recalls the previous definition, probably // to extend it. } else { throw new IncompatibleClassChangeError( "Type Declaration " + newDeclaration.getTypeName() + " has a different" + " superclass that its previous definition: " + newDeclaration.getTypeClassDef().getSuperClass() + " != " + oldDeclaration.getTypeClassDef().getSuperClass()); } } // different duration -> Incompatible if (!nullSafeEqualityComparison( oldDeclaration.getDurationAttribute(), newDeclaration.getDurationAttribute())) { throw new IncompatibleClassChangeError( "Type Declaration " + newDeclaration.getTypeName() + " has a different" + " duration: " + newDeclaration.getDurationAttribute() + " != " + oldDeclaration.getDurationAttribute()); } // //different masks -> incompatible if (newDeclaration.getNature().equals(TypeDeclaration.Nature.DEFINITION)) { if (oldDeclaration.getSetMask() != newDeclaration.getSetMask()) { throw new IncompatibleClassChangeError( "Type Declaration " + newDeclaration.getTypeName() + " is incompatible with" + " the previous definition: " + newDeclaration + " != " + oldDeclaration); } } // TODO: further comparison? // Field comparison List<FactField> oldFields = oldDeclaration.getTypeClassDef().getFields(); Map<String, FactField> newFieldsMap = new HashMap<String, FactField>(); for (FactField factField : newDeclaration.getTypeClassDef().getFields()) { newFieldsMap.put(factField.getName(), factField); } // each of the fields in the old definition that are also present in the // new definition must have the same type. If not -> Incompatible boolean allFieldsInOldDeclarationAreStillPresent = true; for (FactField oldFactField : oldFields) { FactField newFactField = newFieldsMap.get(oldFactField.getName()); if (newFactField != null) { // we can't use newFactField.getType() since it throws a NPE at this point. String newFactType = ((FieldDefinition) newFactField).getTypeName(); if (!newFactType.equals(((FieldDefinition) oldFactField).getTypeName())) { throw new IncompatibleClassChangeError( "Type Declaration " + newDeclaration.getTypeName() + "." + newFactField.getName() + " has a different" + " type that its previous definition: " + newFactType + " != " + oldFactField.getType().getCanonicalName()); } } else { allFieldsInOldDeclarationAreStillPresent = false; } } // If the old declaration has less fields than the new declaration, oldDefinition < // newDefinition if (oldFields.size() < newFieldsMap.size()) { return -1; } // If the old declaration has more fields than the new declaration, oldDefinition > // newDefinition if (oldFields.size() > newFieldsMap.size()) { return 1; } // If the old declaration has the same fields as the new declaration, // and all the fieds present in the old declaration are also present in // the new declaration, then they are considered "equal", otherwise // they are incompatible if (allFieldsInOldDeclarationAreStillPresent) { return 0; } // Both declarations have the same number of fields, but not all the // fields in the old declaration are present in the new declaration. throw new IncompatibleClassChangeError( newDeclaration.getTypeName() + " introduces" + " fields that are not present in its previous version."); }
public TypeDeclarationError(TypeDeclaration typeDeclaration, String errorMessage) { super(typeDeclaration.getResource()); this.errorMessage = errorMessage; this.line = new int[0]; this.namespace = typeDeclaration.getNamespace(); }
protected void updateTraitDefinition(TypeDeclaration type, Class concrete, boolean asTrait) { ClassDefinitionFactory.populateDefinitionFromClass( type.getTypeClassDef(), type.getResource(), concrete, asTrait); }
protected void updateTraitInformation( AbstractClassTypeDeclarationDescr typeDescr, TypeDeclaration type, ClassDefinition def, PackageRegistry pkgRegistry) { if (typeDescr.hasAnnotation(Traitable.class) || (!type.getKind().equals(TypeDeclaration.Kind.TRAIT) && kbuilder.getPackageRegistry().containsKey(def.getSuperClass()) && kbuilder .getPackageRegistry(def.getSuperClass()) .getTraitRegistry() .getTraitables() .containsKey(def.getSuperClass()))) { // traitable if (type.isNovel()) { try { PackageRegistry reg = kbuilder.getPackageRegistry(typeDescr.getNamespace()); String availableName = typeDescr.getType().getFullName(); Class<?> resolvedType = reg.getTypeResolver().resolveType(availableName); updateTraitDefinition(type, resolvedType, false); } catch (ClassNotFoundException cnfe) { // we already know the class exists } } pkgRegistry.getTraitRegistry().addTraitable(def); } else if (type.getKind().equals(TypeDeclaration.Kind.TRAIT) || typeDescr.hasAnnotation(Trait.class)) { // trait if (!type.isNovel()) { try { PackageRegistry reg = kbuilder.getPackageRegistry(typeDescr.getNamespace()); String availableName = typeDescr.getType().getFullName(); Class<?> resolvedType = reg.getTypeResolver().resolveType(availableName); if (!Thing.class.isAssignableFrom(resolvedType)) { if (!resolvedType.isInterface()) { kbuilder.addBuilderResult( new TypeDeclarationError( typeDescr, "Unable to redeclare concrete class " + resolvedType.getName() + " as a trait.")); return; } updateTraitDefinition(type, resolvedType, false); String target = typeDescr.getTypeName() + TraitFactory.SUFFIX; TypeDeclarationDescr tempDescr = new TypeDeclarationDescr(); tempDescr.setNamespace(typeDescr.getNamespace()); tempDescr.setFields(typeDescr.getFields()); tempDescr.setType(target, typeDescr.getNamespace()); tempDescr.setTrait(true); tempDescr.addSuperType(typeDescr.getType()); tempDescr.setResource(type.getResource()); TypeDeclaration tempDeclr = new TypeDeclaration(target); tempDeclr.setKind(TypeDeclaration.Kind.TRAIT); tempDeclr.setTypesafe(type.isTypesafe()); tempDeclr.setNovel(true); tempDeclr.setTypeClassName(tempDescr.getType().getFullName()); tempDeclr.setResource(type.getResource()); ClassDefinition tempDef = new ClassDefinition(target); tempDef.setClassName(tempDescr.getType().getFullName()); tempDef.setTraitable(false); for (FieldDefinition fld : def.getFieldsDefinitions()) { tempDef.addField(fld); } tempDef.setInterfaces(def.getInterfaces()); tempDef.setSuperClass(def.getClassName()); tempDef.setDefinedClass(resolvedType); tempDef.setAbstrakt(true); tempDeclr.setTypeClassDef(tempDef); declaredClassBuilder.generateBeanFromDefinition( tempDescr, tempDeclr, pkgRegistry, tempDef); try { Class<?> clazz = pkgRegistry.getTypeResolver().resolveType(tempDescr.getType().getFullName()); tempDeclr.setTypeClass(clazz); pkgRegistry .getTraitRegistry() .addTrait(tempDef.getClassName().replace(TraitFactory.SUFFIX, ""), tempDef); } catch (ClassNotFoundException cnfe) { kbuilder.addBuilderResult( new TypeDeclarationError( typeDescr, "Internal Trait extension Class '" + target + "' could not be generated correctly'")); } finally { pkgRegistry.getPackage().addTypeDeclaration(tempDeclr); } } else { updateTraitDefinition(type, resolvedType, true); pkgRegistry.getTraitRegistry().addTrait(def); } } catch (ClassNotFoundException cnfe) { // we already know the class exists } } else { if (def.getClassName().endsWith(TraitFactory.SUFFIX)) { pkgRegistry .getTraitRegistry() .addTrait(def.getClassName().replace(TraitFactory.SUFFIX, ""), def); } else { pkgRegistry.getTraitRegistry().addTrait(def); } } } }
protected void createBean( AbstractClassTypeDeclarationDescr typeDescr, PackageRegistry pkgRegistry, ClassHierarchyManager hierarchyManager, List<TypeDefinition> unresolvedTypes, Map<String, AbstractClassTypeDeclarationDescr> unprocesseableDescrs) { // descriptor needs fields inherited from superclass if (typeDescr instanceof TypeDeclarationDescr) { hierarchyManager.inheritFields( pkgRegistry, typeDescr, hierarchyManager.getSortedDescriptors(), unresolvedTypes, unprocesseableDescrs); } TypeDeclaration type = typeDeclarationFactory.processTypeDeclaration(pkgRegistry, typeDescr); boolean success = !kbuilder.hasErrors(); try { // the type declaration is generated in any case (to be used by subclasses, if any) // the actual class will be generated only if needed ClassDefinition def = null; if (success) { def = classDefinitionFactory.generateDeclaredBean( typeDescr, type, pkgRegistry, unresolvedTypes, unprocesseableDescrs); // now use the definition to compare redeclarations, if any // this has to be done after the classDef has been generated if (!type.isNovel()) { typeDeclarationFactory.checkRedeclaration(typeDescr, type, pkgRegistry); } } success = (def != null) && (!kbuilder.hasErrors()); if (success) { updateTraitInformation(typeDescr, type, def, pkgRegistry); } success = !kbuilder.hasErrors(); if (success) { declaredClassBuilder.generateBeanFromDefinition(typeDescr, type, pkgRegistry, def); } success = !kbuilder.hasErrors(); if (success) { Class<?> clazz = pkgRegistry.getTypeResolver().resolveType(typeDescr.getType().getFullName()); type.setTypeClass(clazz); type.setValid(true); } else { unprocesseableDescrs.put(typeDescr.getType().getFullName(), typeDescr); type.setValid(false); } typeDeclarationConfigurator.finalize( type, typeDescr, pkgRegistry, kbuilder.getPackageRegistry(), hierarchyManager); } catch (final ClassNotFoundException e) { unprocesseableDescrs.put(typeDescr.getType().getFullName(), typeDescr); kbuilder.addBuilderResult( new TypeDeclarationError( typeDescr, "Class '" + type.getTypeClassName() + "' not found for type declaration of '" + type.getTypeName() + "'")); } if (!success) { unresolvedTypes.add(new TypeDefinition(type, typeDescr)); } else { registerGeneratedType(typeDescr); } }