src/test/java/ucar/geoapi/ContentVerifier.java
private void addPropertyValue(Class<?> type, final Object obj) throws InvocationTargetException, IllegalAccessException {
        if (InternationalString.class.isAssignableFrom(type) ||        // Most common case first.
                       CodeList.class.isAssignableFrom(type) ||
                           Enum.class.isAssignableFrom(type) ||
                    GenericName.class.isAssignableFrom(type) ||
                       !type.isAnnotationPresent(UML.class))
        {
            final String key = path.toString();
            final Object previous = metadataValues.put(key, obj);
            if (previous != null && !previous.equals(obj)) {
                throw new IllegalStateException(String.format("Metadata element \"%s\" is specified twice "
                        + "with two different values:%nValue 1: %s%nValue 2: %s%n", key, previous, obj));
            }
        } else {
            final Element recursivityGuard = new Element(type, obj);
            if (visited.add(recursivityGuard)) {
                final int pathElementPosition = path.length();
                type = specialized(type, obj.getClass());               // Example: Identification may actually be DataIdentification
                for (final Method getter : type.getMethods()) {
                    if (getter.getParameterCount() != 0) {
                        continue;
                    }
                    if (getter.isAnnotationPresent(Deprecated.class)) {
                        continue;
                    }
                    final UML spec = getter.getAnnotation(UML.class);
                    if (spec == null || isIgnored(type, spec)) {
                        continue;
                    }
                    Class<?> valueType = getter.getReturnType();
                    if (Void.TYPE.equals(valueType)) {
                        continue;
                    }
                    final Object value = getter.invoke(obj, (Object[]) null);
                    if (value == null) {
                        continue;
                    }
                    final Iterator<?> values;
                    if (Map.class.isAssignableFrom(valueType)) {
                        values = ((Map<?,?>) value).keySet().iterator();
                        if (!values.hasNext()) continue;
                    } else if (Iterable.class.isAssignableFrom(valueType)) {
                        values = ((Collection<?>) value).iterator();
                        if (!values.hasNext()) continue;
                    } else {
                        values = null;
                    }
                    if (pathElementPosition != 0) {
                        path.append('.');
                    }
                    path.append(spec.identifier());
                    if (values == null) {
                        addPropertyValue(valueType, value);
                    } else {
                        valueType = boundOfParameterizedProperty(getter.getGenericReturnType());
                        final int indexPosition = path.append('[').length();
                        int i = 0;
                        do {
                            path.append(i++).append(']');
                            addPropertyValue(valueType, values.next());
                            path.setLength(indexPosition);
                        } while (values.hasNext());
                    }
                    path.setLength(pathElementPosition);
                }
                if (!visited.remove(recursivityGuard)) {
                    // Should never happen unless the map is modified concurrently in another thread.
                    throw new ConcurrentModificationException();
                }
            }
        }
    }
/**
     * Adds the given value in the {@link #metadataValues} map. If the given value is another metadata object,
     * then this method iterates recursively over all elements in that metadata. The key is the current value
     * of {@link #path}.
     *
     * @param  type  the GeoAPI interface implemented by the given object, or the standard Java class if not a metadata type.
     * @param  obj   non-null instance of {@code type} to add in the map.
     * @throws InvocationTargetException if an error occurred while invoking client code.
     * @throws IllegalStateException if a different metadata value is already presents for the current {@link #path} key.
     */
Adds the given value in the  #metadataValues map. If the given value is another metadata object,
then this method iterates recursively over all elements in that metadata. The key is the current value
of  #path.

@param  type  the GeoAPI interface implemented by the given object, or the standard Java class if not a metadata type.
@param  obj   non-null instance of  type to add in the map.
@throws InvocationTargetException if an error occurred while invoking client code.
@throws IllegalStateException if a different metadata value is already presents for the current  #path key.
Adds the given value in the #metadataValues map . If the given value is another metadata object then this method iterates recursively over all elements in that metadata . The key is the current value of #path . @param type the GeoAPI interface implemented by the given object or the standard Java class if not a metadata type . @param obj non - null instance of type to add in the map . @throws InvocationTargetException if an error occurred while invoking client code . @throws IllegalStateException if a different metadata value is already presents for the current #path key .
private void addPropertyValue(Class<?> type, final Object obj) throws InvocationTargetException, IllegalAccessException {
        if (InternationalString.class.isAssignableFrom(type) ||        
                       CodeList.class.isAssignableFrom(type) ||
                           Enum.class.isAssignableFrom(type) ||
                    GenericName.class.isAssignableFrom(type) ||
                       !type.isAnnotationPresent(UML.class))
        {
            final String key = path.toString();
            final Object previous = metadataValues.put(key, obj);
            if (previous != null && !previous.equals(obj)) {
                throw new IllegalStateException(String.format("Metadata element \"%s\" is specified twice "
                        + "with two different values:%nValue 1: %s%nValue 2: %s%n", key, previous, obj));
            }
        } else {
            final Element recursivityGuard = new Element(type, obj);
            if (visited.add(recursivityGuard)) {
                final int pathElementPosition = path.length();
                type = specialized(type, obj.getClass());               
                for (final Method getter : type.getMethods()) {
                    if (getter.getParameterCount() != 0) {
                        continue;
                    }
                    if (getter.isAnnotationPresent(Deprecated.class)) {
                        continue;
                    }
                    final UML spec = getter.getAnnotation(UML.class);
                    if (spec == null || isIgnored(type, spec)) {
                        continue;
                    }
                    Class<?> valueType = getter.getReturnType();
                    if (Void.TYPE.equals(valueType)) {
                        continue;
                    }
                    final Object value = getter.invoke(obj, (Object[]) null);
                    if (value == null) {
                        continue;
                    }
                    final Iterator<?> values;
                    if (Map.class.isAssignableFrom(valueType)) {
                        values = ((Map<?,?>) value).keySet().iterator();
                        if (!values.hasNext()) continue;
                    } else if (Iterable.class.isAssignableFrom(valueType)) {
                        values = ((Collection<?>) value).iterator();
                        if (!values.hasNext()) continue;
                    } else {
                        values = null;
                    }
                    if (pathElementPosition != 0) {
                        path.append('.');
                    }
                    path.append(spec.identifier());
                    if (values == null) {
                        addPropertyValue(valueType, value);
                    } else {
                        valueType = boundOfParameterizedProperty(getter.getGenericReturnType());
                        final int indexPosition = path.append('[').length();
                        int i = 0;
                        do {
                            path.append(i++).append(']');
                            addPropertyValue(valueType, values.next());
                            path.setLength(indexPosition);
                        } while (values.hasNext());
                    }
                    path.setLength(pathElementPosition);
                }
                if (!visited.remove(recursivityGuard)) {
                    throw new ConcurrentModificationException();
                }
            }
        }
    }
private void addPropertyValue ( Class < ? > type , final Object obj ) throws InvocationTargetException , IllegalAccessException { if ( InternationalString . class . isAssignableFrom ( type ) || CodeList . class . isAssignableFrom ( type ) || Enum . class . isAssignableFrom ( type ) || GenericName . class . isAssignableFrom ( type ) || ! type . isAnnotationPresent ( UML . class ) ) { final String key = path . toString ( ) ; final Object previous = metadataValues . put ( key , obj ) ; if ( previous != null && ! previous . equals ( obj ) ) { throw new IllegalStateException ( String . format ( "Metadata element \"%s\" is specified twice " + "with two different values:%nValue 1: %s%nValue 2: %s%n" , key , previous , obj ) ) ; } } else { final Element recursivityGuard = new Element ( type , obj ) ; if ( visited . add ( recursivityGuard ) ) { final int pathElementPosition = path . length ( ) ; type = specialized ( type , obj . getClass ( ) ) ; for ( final Method getter : type . getMethods ( ) ) { if ( getter . getParameterCount ( ) != 0 ) { continue ; } if ( getter . isAnnotationPresent ( Deprecated . class ) ) { continue ; } final UML spec = getter . getAnnotation ( UML . class ) ; if ( spec == null || isIgnored ( type , spec ) ) { continue ; } Class < ? > valueType = getter . getReturnType ( ) ; if ( Void . TYPE . equals ( valueType ) ) { continue ; } final Object value = getter . invoke ( obj , ( Object [ ] ) null ) ; if ( value == null ) { continue ; } final Iterator < ? > values ; if ( Map . class . isAssignableFrom ( valueType ) ) { values = ( ( Map < ? , ? > ) value ) . keySet ( ) . iterator ( ) ; if ( ! values . hasNext ( ) ) continue ; } else if ( Iterable . class . isAssignableFrom ( valueType ) ) { values = ( ( Collection < ? > ) value ) . iterator ( ) ; if ( ! values . hasNext ( ) ) continue ; } else { values = null ; } if ( pathElementPosition != 0 ) { path . append ( '.' ) ; } path . append ( spec . identifier ( ) ) ; if ( values == null ) { addPropertyValue ( valueType , value ) ; } else { valueType = boundOfParameterizedProperty ( getter . getGenericReturnType ( ) ) ; final int indexPosition = path . append ( '[' ) . length ( ) ; int i = 0 ; do { path . append ( i ++ ) . append ( ']' ) ; addPropertyValue ( valueType , values . next ( ) ) ; path . setLength ( indexPosition ) ; } while ( values . hasNext ( ) ) ; } path . setLength ( pathElementPosition ) ; } if ( ! visited . remove ( recursivityGuard ) ) { throw new ConcurrentModificationException ( ) ; } } } }
Adds the given value in the {@link #metadataValues} map.
Adds the given value in the { @link #metadataValues } map .
// Most common case first. // Example: Identification may actually be DataIdentification // Should never happen unless the map is modified concurrently in another thread.