private PropertyDescriptor[] mergeProps(PropertyDescriptor[] superDescs,
            int superDefaultIndex) throws IntrospectionException {
        // FIXME:change to OO way as EventSetD and MethodD
        HashMap<String, PropertyDescriptor> subMap = internalAsMap(properties);
        String defaultPropertyName = null;
        if (defaultPropertyIndex >= 0
                && defaultPropertyIndex < properties.length) {
            defaultPropertyName = properties[defaultPropertyIndex].getName();
        } else if (superDefaultIndex >= 0
                && superDefaultIndex < superDescs.length) {
            defaultPropertyName = superDescs[superDefaultIndex].getName();
        }

        for (int i = 0; i < superDescs.length; i++) {
            PropertyDescriptor superDesc = superDescs[i];
            String propertyName = superDesc.getName();
            if (!subMap.containsKey(propertyName)) {
                subMap.put(propertyName, superDesc);
                continue;
            }

            Object value = subMap.get(propertyName);
            // if sub and super are both PropertyDescriptor
            Method subGet = ((PropertyDescriptor) value).getReadMethod();
            Method subSet = ((PropertyDescriptor) value).getWriteMethod();
            Method superGet = superDesc.getReadMethod();
            Method superSet = superDesc.getWriteMethod();

            Class<?> superType = superDesc.getPropertyType();
            Class<?> superIndexedType = null;
            Class<?> subType = ((PropertyDescriptor) value).getPropertyType();
            Class<?> subIndexedType = null;

            if (value instanceof IndexedPropertyDescriptor) {
                subIndexedType = ((IndexedPropertyDescriptor) value)
                        .getIndexedPropertyType();
            }
            if (superDesc instanceof IndexedPropertyDescriptor) {
                superIndexedType = ((IndexedPropertyDescriptor) superDesc)
                        .getIndexedPropertyType();
            }

            // if superDesc is PropertyDescriptor
            if (superIndexedType == null) {
                PropertyDescriptor subDesc = (PropertyDescriptor) value;
                // Sub is PropertyDescriptor
                if (subIndexedType == null) {
                    // Same property type
                    if (subType != null && superType != null
                            && subType.getName() != null
                            && subType.getName().equals(superType.getName())) {
                        if (superGet != null
                                && (subGet == null || superGet.equals(subGet))) {
                            subDesc.setReadMethod(superGet);
                        }
                        if (superSet != null
                                && (subSet == null || superSet.equals(subSet))) {
                            subDesc.setWriteMethod(superSet);
                        }
                        if (subType == boolean.class && subGet != null
                                && superGet != null) {
                            if (superGet.getName().startsWith(PREFIX_IS)) {
                                subDesc.setReadMethod(superGet);
                            }
                        }
                    } else { // Different type
                        if ((subGet == null || subSet == null)
                                && (superGet != null)) {
                            subDesc = new PropertyDescriptor(propertyName,
                                    superGet, superSet);
                            if (subGet != null) {
                                String subGetName = subGet.getName();
                                Method method = null;
                                MethodDescriptor[] introspectMethods = introspectMethods();
                                for (MethodDescriptor methodDesc : introspectMethods) {
                                    method = methodDesc.getMethod();
                                    if (method != subGet
                                            && subGetName.equals(method
                                                    .getName())
                                            && method.getParameterTypes().length == 0
                                            && method.getReturnType() == superType) {
                                        subDesc.setReadMethod(method);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                } else { // Sub is IndexedPropertyDescriptor and super is PropertyDescriptor
                    if (superType != null
                            && (superType.isArray())
                            && (superType.getComponentType().getName()
                                    .equals(subIndexedType.getName()))) {
                        if ((subGet == null) && (superGet != null)) {
                            subDesc.setReadMethod(superGet);
                        }
                        if ((subSet == null) && (superSet != null)) {
                            subDesc.setWriteMethod(superSet);
                        }
                    } // different type do nothing
                    // sub is indexed pd and super is normal pd
                    if (subIndexedType == boolean.class
                            && superType == boolean.class) {
                        Method subIndexedSet = ((IndexedPropertyDescriptor) subDesc)
                                .getIndexedWriteMethod();
                        if (subGet == null && subSet == null
                                && subIndexedSet != null && superGet != null) {
                            try {
                                subSet = beanClass.getDeclaredMethod(
                                        subIndexedSet.getName(), boolean.class);
                            } catch (Exception e) {
                                // ignored
                            }
                            if (subSet != null) {
                                // Cast sub into PropertyDescriptor
                                subDesc = new PropertyDescriptor(propertyName,
                                        superGet, subSet);
                            }
                        }
                    }
                }
                subMap.put(propertyName, subDesc);
            } else { // Super is IndexedPropertyDescriptor
                if (subIndexedType == null) { // Sub is PropertyDescriptor
                    if (subType != null
                            && subType.isArray()
                            && (subType.getComponentType().getName()
                                    .equals(superIndexedType.getName()))) {
                        // Same type
                        if (subGet != null) {
                            superDesc.setReadMethod(subGet);
                        }
                        if (subSet != null) {
                            superDesc.setWriteMethod(subSet);
                        }
                        subMap.put(propertyName, superDesc);
                    } else {
                        // subDesc is PropertyDescriptor
                        // superDesc is IndexedPropertyDescriptor

                        // fill null subGet or subSet method with superClass's
                        if (subGet == null || subSet == null) {
                            Class<?> beanSuperClass = beanClass.getSuperclass();
                            String methodSuffix = capitalize(propertyName);
                            Method method = null;
                            if (subGet == null) {
                                // subGet is null
                                if (subType == boolean.class) {
                                    try {
                                        method = beanSuperClass
                                                .getDeclaredMethod(PREFIX_IS
                                                        + methodSuffix);
                                    } catch (Exception e) {
                                        // ignored
                                    }
                                } else {
                                    try {
                                        method = beanSuperClass
                                                .getDeclaredMethod(PREFIX_GET
                                                        + methodSuffix);
                                    } catch (Exception e) {
                                        // ignored
                                    }
                                }
                                if (method != null
                                        && !Modifier.isStatic(method
                                                .getModifiers())
                                        && method.getReturnType() == subType) {
                                    ((PropertyDescriptor) value)
                                            .setReadMethod(method);
                                }
                            } else {
                                // subSet is null
                                try {
                                    method = beanSuperClass.getDeclaredMethod(
                                            PREFIX_SET + methodSuffix, subType);
                                } catch (Exception e) {
                                    // ignored
                                }
                                if (method != null
                                        && !Modifier.isStatic(method
                                                .getModifiers())
                                        && method.getReturnType() == void.class) {
                                    ((PropertyDescriptor) value)
                                            .setWriteMethod(method);
                                }
                            }
                        }
                        subMap.put(propertyName, (PropertyDescriptor) value);
                    }
                } else if (subIndexedType.getName().equals(
                        superIndexedType.getName())) {
                    // Sub is IndexedPropertyDescriptor and Same type
                    IndexedPropertyDescriptor subDesc = (IndexedPropertyDescriptor) value;
                    if ((subGet == null) && (superGet != null)) {
                        subDesc.setReadMethod(superGet);
                    }
                    if ((subSet == null) && (superSet != null)) {
                        subDesc.setWriteMethod(superSet);
                    }
                    IndexedPropertyDescriptor superIndexedDesc = (IndexedPropertyDescriptor) superDesc;

                    if ((subDesc.getIndexedReadMethod() == null)
                            && (superIndexedDesc.getIndexedReadMethod() != null)) {
                        subDesc.setIndexedReadMethod(superIndexedDesc
                                .getIndexedReadMethod());
                    }

                    if ((subDesc.getIndexedWriteMethod() == null)
                            && (superIndexedDesc.getIndexedWriteMethod() != null)) {
                        subDesc.setIndexedWriteMethod(superIndexedDesc
                                .getIndexedWriteMethod());
                    }

                    subMap.put(propertyName, subDesc);
                } // Different indexed type, do nothing
            }
            mergeAttributes((PropertyDescriptor) value, superDesc);
        }

        PropertyDescriptor[] theDescs = new PropertyDescriptor[subMap.size()];
        subMap.values().toArray(theDescs);

        if (defaultPropertyName != null && !explicitProperties) {
            for (int i = 0; i < theDescs.length; i++) {
                if (defaultPropertyName.equals(theDescs[i].getName())) {
                    defaultPropertyIndex = i;
                    break;
                }
            }
        }
        return theDescs;
    }
private PropertyDescriptor [ ] mergeProps ( PropertyDescriptor [ ] superDescs , int superDefaultIndex ) throws IntrospectionException { HashMap < String , PropertyDescriptor > subMap = internalAsMap ( properties ) ; String defaultPropertyName = null ; if ( defaultPropertyIndex >= 0 && defaultPropertyIndex < properties . length ) { defaultPropertyName = properties [ defaultPropertyIndex ] . getName ( ) ; } else if ( superDefaultIndex >= 0 && superDefaultIndex < superDescs . length ) { defaultPropertyName = superDescs [ superDefaultIndex ] . getName ( ) ; } for ( int i = 0 ; i < superDescs . length ; i ++ ) { PropertyDescriptor superDesc = superDescs [ i ] ; String propertyName = superDesc . getName ( ) ; if ( ! subMap . containsKey ( propertyName ) ) { subMap . put ( propertyName , superDesc ) ; continue ; } Object value = subMap . get ( propertyName ) ; Method subGet = ( ( PropertyDescriptor ) value ) . getReadMethod ( ) ; Method subSet = ( ( PropertyDescriptor ) value ) . getWriteMethod ( ) ; Method superGet = superDesc . getReadMethod ( ) ; Method superSet = superDesc . getWriteMethod ( ) ; Class < ? > superType = superDesc . getPropertyType ( ) ; Class < ? > superIndexedType = null ; Class < ? > subType = ( ( PropertyDescriptor ) value ) . getPropertyType ( ) ; Class < ? > subIndexedType = null ; if ( value instanceof IndexedPropertyDescriptor ) { subIndexedType = ( ( IndexedPropertyDescriptor ) value ) . getIndexedPropertyType ( ) ; } if ( superDesc instanceof IndexedPropertyDescriptor ) { superIndexedType = ( ( IndexedPropertyDescriptor ) superDesc ) . getIndexedPropertyType ( ) ; } if ( superIndexedType == null ) { PropertyDescriptor subDesc = ( PropertyDescriptor ) value ; if ( subIndexedType == null ) { if ( subType != null && superType != null && subType . getName ( ) != null && subType . getName ( ) . equals ( superType . getName ( ) ) ) { if ( superGet != null && ( subGet == null || superGet . equals ( subGet ) ) ) { subDesc . setReadMethod ( superGet ) ; } if ( superSet != null && ( subSet == null || superSet . equals ( subSet ) ) ) { subDesc . setWriteMethod ( superSet ) ; } if ( subType == boolean . class && subGet != null && superGet != null ) { if ( superGet . getName ( ) . startsWith ( PREFIX_IS ) ) { subDesc . setReadMethod ( superGet ) ; } } } else { if ( ( subGet == null || subSet == null ) && ( superGet != null ) ) { subDesc = new PropertyDescriptor ( propertyName , superGet , superSet ) ; if ( subGet != null ) { String subGetName = subGet . getName ( ) ; Method method = null ; MethodDescriptor [ ] introspectMethods = introspectMethods ( ) ; for ( MethodDescriptor methodDesc : introspectMethods ) { method = methodDesc . getMethod ( ) ; if ( method != subGet && subGetName . equals ( method . getName ( ) ) && method . getParameterTypes ( ) . length == 0 && method . getReturnType ( ) == superType ) { subDesc . setReadMethod ( method ) ; break ; } } } } } } else { if ( superType != null && ( superType . isArray ( ) ) && ( superType . getComponentType ( ) . getName ( ) . equals ( subIndexedType . getName ( ) ) ) ) { if ( ( subGet == null ) && ( superGet != null ) ) { subDesc . setReadMethod ( superGet ) ; } if ( ( subSet == null ) && ( superSet != null ) ) { subDesc . setWriteMethod ( superSet ) ; } } if ( subIndexedType == boolean . class && superType == boolean . class ) { Method subIndexedSet = ( ( IndexedPropertyDescriptor ) subDesc ) . getIndexedWriteMethod ( ) ; if ( subGet == null && subSet == null && subIndexedSet != null && superGet != null ) { try { subSet = beanClass . getDeclaredMethod ( subIndexedSet . getName ( ) , boolean . class ) ; } catch ( Exception e ) { } if ( subSet != null ) { subDesc = new PropertyDescriptor ( propertyName , superGet , subSet ) ; } } } } subMap . put ( propertyName , subDesc ) ; } else { if ( subIndexedType == null ) { if ( subType != null && subType . isArray ( ) && ( subType . getComponentType ( ) . getName ( ) . equals ( superIndexedType . getName ( ) ) ) ) { if ( subGet != null ) { superDesc . setReadMethod ( subGet ) ; } if ( subSet != null ) { superDesc . setWriteMethod ( subSet ) ; } subMap . put ( propertyName , superDesc ) ; } else { if ( subGet == null || subSet == null ) { Class < ? > beanSuperClass = beanClass . getSuperclass ( ) ; String methodSuffix = capitalize ( propertyName ) ; Method method = null ; if ( subGet == null ) { if ( subType == boolean . class ) { try { method = beanSuperClass . getDeclaredMethod ( PREFIX_IS + methodSuffix ) ; } catch ( Exception e ) { } } else { try { method = beanSuperClass . getDeclaredMethod ( PREFIX_GET + methodSuffix ) ; } catch ( Exception e ) { } } if ( method != null && ! Modifier . isStatic ( method . getModifiers ( ) ) && method . getReturnType ( ) == subType ) { ( ( PropertyDescriptor ) value ) . setReadMethod ( method ) ; } } else { try { method = beanSuperClass . getDeclaredMethod ( PREFIX_SET + methodSuffix , subType ) ; } catch ( Exception e ) { } if ( method != null && ! Modifier . isStatic ( method . getModifiers ( ) ) && method . getReturnType ( ) == void . class ) { ( ( PropertyDescriptor ) value ) . setWriteMethod ( method ) ; } } } subMap . put ( propertyName , ( PropertyDescriptor ) value ) ; } } else if ( subIndexedType . getName ( ) . equals ( superIndexedType . getName ( ) ) ) { IndexedPropertyDescriptor subDesc = ( IndexedPropertyDescriptor ) value ; if ( ( subGet == null ) && ( superGet != null ) ) { subDesc . setReadMethod ( superGet ) ; } if ( ( subSet == null ) && ( superSet != null ) ) { subDesc . setWriteMethod ( superSet ) ; } IndexedPropertyDescriptor superIndexedDesc = ( IndexedPropertyDescriptor ) superDesc ; if ( ( subDesc . getIndexedReadMethod ( ) == null ) && ( superIndexedDesc . getIndexedReadMethod ( ) != null ) ) { subDesc . setIndexedReadMethod ( superIndexedDesc . getIndexedReadMethod ( ) ) ; } if ( ( subDesc . getIndexedWriteMethod ( ) == null ) && ( superIndexedDesc . getIndexedWriteMethod ( ) != null ) ) { subDesc . setIndexedWriteMethod ( superIndexedDesc . getIndexedWriteMethod ( ) ) ; } subMap . put ( propertyName , subDesc ) ; } } mergeAttributes ( ( PropertyDescriptor ) value , superDesc ) ; } PropertyDescriptor [ ] theDescs = new PropertyDescriptor [ subMap . size ( ) ] ; subMap . values ( ) . toArray ( theDescs ) ; if ( defaultPropertyName != null && ! explicitProperties ) { for ( int i = 0 ; i < theDescs . length ; i ++ ) { if ( defaultPropertyName . equals ( theDescs [ i ] . getName ( ) ) ) { defaultPropertyIndex = i ; break ; } } } return theDescs ; }
/*
merge the PropertyDescriptor with superclass