TypeDeclarationDescr typeDescr) {
Map<String, TypeFieldDescr> fieldMap = new LinkedHashMap<String, TypeFieldDescr>();
PackageRegistry registry = this.pkgRegistryMap.get( superTypePackageName );
Package pack;
if ( registry != null ) {
pack = registry.getPackage();
} else {
// If there is no regisrty the type isn't a DRL-declared type, which is forbidden.
// Avoid NPE JIRA-3041 when trying to access the registry. Avoid subsequent problems.
this.results.add( new TypeDeclarationError( typeDescr, "Cannot extend supertype '" + fullSuper + "' (not a declared type)" ) );
typeDescr.setType( null, null );
return false;
}
// if a class is declared in DRL, its package can't be null? The default package is replaced by "defaultpkg"
boolean isSuperClassTagged = false;
boolean isSuperClassDeclared = true; //in the same package, or in a previous one
if ( pack != null ) {
// look for the supertype declaration in available packages
TypeDeclaration superTypeDeclaration = pack.getTypeDeclaration( simpleSuperTypeName );
if ( superTypeDeclaration != null ) {
ClassDefinition classDef = superTypeDeclaration.getTypeClassDef();
// inherit fields
for ( FactField fld : classDef.getFields() ) {
TypeFieldDescr inheritedFlDescr = buildInheritedFieldDescrFromDefinition( fld );
fieldMap.put( inheritedFlDescr.getFieldName(),
inheritedFlDescr );
}
// new classes are already distinguished from tagged external classes
isSuperClassTagged = !superTypeDeclaration.isNovel();
} else {
isSuperClassDeclared = false;
}
} else {
isSuperClassDeclared = false;
}
// look for the class externally
if ( !isSuperClassDeclared || isSuperClassTagged ) {
try {
Class superKlass = registry.getTypeResolver().resolveType( fullSuper );
ClassFieldInspector inspector = new ClassFieldInspector( superKlass );
for ( String name : inspector.getGetterMethods().keySet() ) {
// classFieldAccessor requires both getter and setter
if ( inspector.getSetterMethods().containsKey( name ) ) {
if ( !inspector.isNonGetter( name ) && !"class".equals( name ) ) {
TypeFieldDescr inheritedFlDescr = new TypeFieldDescr(
name,
new PatternDescr(
inspector.getFieldTypes().get( name ).getName() ) );
inheritedFlDescr.setInherited( !Modifier.isAbstract( inspector.getGetterMethods().get( name ).getModifiers() ) );
inheritedFlDescr.setIndex( inspector.getFieldNames().size() + inspector.getFieldNames().get( name ) );
if ( !fieldMap.containsKey( inheritedFlDescr.getFieldName() ) ) fieldMap.put( inheritedFlDescr.getFieldName(),
inheritedFlDescr );
}
}
}
} catch ( ClassNotFoundException cnfe ) {
throw new RuntimeDroolsException( "Unable to resolve Type Declaration superclass '" + fullSuper + "'" );
} catch ( IOException e ) {
}
}
// finally, locally declared fields are merged. The map swap ensures that super-fields are added in order, before the subclass' ones
// notice that it is not possible to override a field changing its type
for ( String fieldName : typeDescr.getFields().keySet() ) {
if ( fieldMap.containsKey( fieldName ) ) {
String type1 = fieldMap.get( fieldName ).getPattern().getObjectType();
String type2 = typeDescr.getFields().get( fieldName ).getPattern().getObjectType();
if ( type2.lastIndexOf( "." ) < 0 ) {
try {
TypeResolver typeResolver = pkgRegistryMap.get( pack.getName() ).getTypeResolver();
type1 = typeResolver.resolveType( type1 ).getName();
type2 = typeResolver.resolveType( type2 ).getName();
// now that we are at it... this will be needed later anyway
fieldMap.get( fieldName ).getPattern().setObjectType( type1 );
typeDescr.getFields().get( fieldName ).getPattern().setObjectType( type2 );