Search in sources :

Example 1 with PropertyComparator

use of org.apache.sis.metadata.PropertyComparator in project sis by apache.

the class PropertyAccessor method getGetters.

/**
 * Returns the getters. The returned array should never be modified,
 * since it may be shared among many instances of {@code PropertyAccessor}.
 *
 * @param  type            the metadata interface.
 * @param  implementation  the class of metadata implementations, or {@code type} if none.
 * @param  standardImpl    the implementation specified by the {@link MetadataStandard}, or {@code null} if none.
 * @return the getters declared in the given interface (never {@code null}).
 */
private static Method[] getGetters(final Class<?> type, final Class<?> implementation, final Class<?> standardImpl) {
    /*
         * Indices map is used for choosing what to do in case of name collision.
         */
    Method[] getters = (MetadataStandard.IMPLEMENTATION_CAN_ALTER_API ? implementation : type).getMethods();
    final Map<String, Integer> indices = new HashMap<>(hashMapCapacity(getters.length));
    boolean hasExtraGetter = false;
    int count = 0;
    for (Method candidate : getters) {
        if (Classes.isPossibleGetter(candidate)) {
            final String name = candidate.getName();
            if (name.startsWith(SET)) {
                // Paranoiac check.
                continue;
            }
            /*
                 * The candidate method should be declared in the interface. If not, then we require it to have
                 * a @UML annotation. The later case happen when the Apache SIS implementation contains methods
                 * for a new international standard not yet reflected in the GeoAPI interfaces.
                 */
            if (MetadataStandard.IMPLEMENTATION_CAN_ALTER_API) {
                if (type == implementation) {
                    if (!type.isInterface() && !candidate.isAnnotationPresent(UML.class)) {
                        // @UML considered optional only for interfaces.
                        continue;
                    }
                } else
                    try {
                        candidate = type.getMethod(name, (Class[]) null);
                    } catch (NoSuchMethodException e) {
                        if (!candidate.isAnnotationPresent(UML.class)) {
                            // Not a method from an interface, and no @UML in implementation.
                            continue;
                        }
                    }
            }
            /*
                 * At this point, we are ready to accept the method. Before doing so, check if the method override
                 * an other method defined in a parent class with a covariant return type. The JVM considers such
                 * cases as two different methods, while from a Java developer point of view this is the same method.
                 */
            final Integer pi = indices.put(name, count);
            if (pi != null) {
                final Class<?> pt = getters[pi].getReturnType();
                final Class<?> ct = candidate.getReturnType();
                if (ct.isAssignableFrom(pt)) {
                    // Previous type was more accurate.
                    continue;
                }
                if (pt.isAssignableFrom(ct)) {
                    getters[pi] = candidate;
                    continue;
                }
                throw new ClassCastException(Errors.format(Errors.Keys.IllegalArgumentClass_3, Classes.getShortName(type) + '.' + name, ct, pt));
            }
            getters[count++] = candidate;
            if (!hasExtraGetter) {
                hasExtraGetter = name.equals(EXTRA_GETTER.getName());
            }
        }
    }
    /*
         * Sort the standard methods before to add the extra methods (if any) in order to
         * keep the extra methods last. The code checking for the extra methods require
         * them to be last.
         */
    Arrays.sort(getters, 0, count, new PropertyComparator(implementation, standardImpl));
    if (!hasExtraGetter) {
        if (getters.length == count) {
            getters = Arrays.copyOf(getters, count + 1);
        }
        getters[count++] = EXTRA_GETTER;
    }
    getters = ArraysExt.resize(getters, count);
    return getters;
}
Also used : HashMap(java.util.HashMap) PropertyComparator(org.apache.sis.metadata.PropertyComparator) Method(java.lang.reflect.Method) UML(org.opengis.annotation.UML)

Aggregations

Method (java.lang.reflect.Method)1 HashMap (java.util.HashMap)1 PropertyComparator (org.apache.sis.metadata.PropertyComparator)1 UML (org.opengis.annotation.UML)1