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); }
/** 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 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 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 "); } } }
protected void updateTraitDefinition(TypeDeclaration type, Class concrete, boolean asTrait) { ClassDefinitionFactory.populateDefinitionFromClass( type.getTypeClassDef(), type.getResource(), concrete, asTrait); }
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())); } }
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."); }