001    /*
002     *    GeoAPI - Java interfaces for OGC/ISO standards
003     *    http://www.geoapi.org
004     *
005     *    Copyright (C) 2008-2013 Open Geospatial Consortium, Inc.
006     *    All Rights Reserved. http://www.opengeospatial.org/ogc/legal
007     *
008     *    Permission to use, copy, and modify this software and its documentation, with
009     *    or without modification, for any purpose and without fee or royalty is hereby
010     *    granted, provided that you include the following on ALL copies of the software
011     *    and documentation or portions thereof, including modifications, that you make:
012     *
013     *    1. The full text of this NOTICE in a location viewable to users of the
014     *       redistributed or derivative work.
015     *    2. Notice of any changes or modifications to the OGC files, including the
016     *       date changes were made.
017     *
018     *    THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE
019     *    NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
020     *    TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
021     *    THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
022     *    PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
023     *
024     *    COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
025     *    CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
026     *
027     *    The name and trademarks of copyright holders may NOT be used in advertising or
028     *    publicity pertaining to the software without specific, written prior permission.
029     *    Title to copyright in this software and any associated documentation will at all
030     *    times remain with copyright holders.
031     */
032    package org.opengis.test.referencing;
033    
034    import java.util.Set;
035    import java.util.List;
036    
037    import org.opengis.parameter.*;
038    import org.opengis.test.ValidatorContainer;
039    import static org.opengis.test.Assert.*;
040    
041    
042    /**
043     * Validates {@link ParameterValue} and related objects from the {@code org.opengis.parameter}
044     * package.
045     *
046     * <p>This class is provided for users wanting to override the validation methods. When the default
047     * behavior is sufficient, the {@link org.opengis.test.Validators} static methods provide a more
048     * convenient way to validate various kinds of objects.</p>
049     *
050     * @author  Martin Desruisseaux (Geomatys)
051     * @version 3.1
052     * @since   2.2
053     */
054    public class ParameterValidator extends ReferencingValidator {
055        /**
056         * Creates a new validator instance.
057         *
058         * @param container The set of validators to use for validating other kinds of objects
059         *                  (see {@linkplain #container field javadoc}).
060         */
061        public ParameterValidator(final ValidatorContainer container) {
062            super(container, "org.opengis.parameter");
063        }
064    
065        /**
066         * For each interface implemented by the given object, invokes the corresponding
067         * {@code validate(...)} method defined in this class (if any).
068         *
069         * @param  object The object to dispatch to {@code validate(...)} methods, or {@code null}.
070         * @return Number of {@code validate(...)} methods invoked in this class for the given object.
071         */
072        public int dispatch(final GeneralParameterDescriptor object) {
073            int n = 0;
074            if (object != null) {
075                if (object instanceof ParameterDescriptor<?>)   {validate((ParameterDescriptor<?>)   object); n++;}
076                if (object instanceof ParameterDescriptorGroup) {validate((ParameterDescriptorGroup) object); n++;}
077                if (n == 0) {
078                    validateIdentifiedObject(object);
079                }
080            }
081            return n;
082        }
083    
084        /**
085         * For each interface implemented by the given object, invokes the corresponding
086         * {@code validate(...)} method defined in this class (if any).
087         *
088         * @param  object The object to dispatch to {@code validate(...)} methods, or {@code null}.
089         * @return Number of {@code validate(...)} methods invoked in this class for the given object.
090         */
091        public int dispatch(final GeneralParameterValue object) {
092            int n = 0;
093            if (object != null) {
094                if (object instanceof ParameterValue<?>)   {validate((ParameterValue<?>)   object); n++;}
095                if (object instanceof ParameterValueGroup) {validate((ParameterValueGroup) object); n++;}
096                if (n == 0) {
097                    dispatch(object.getDescriptor());
098                }
099            }
100            return n;
101        }
102    
103        /**
104         * Validates the given descriptor.
105         *
106         * @param <T> The class of parameter values.
107         * @param object The object to validate, or {@code null}.
108         */
109        public <T> void validate(final ParameterDescriptor<T> object) {
110            if (object == null) {
111                return;
112            }
113            validateIdentifiedObject(object);
114            final Class<T> valueClass = object.getValueClass();
115            mandatory("ParameterDescriptor: getValueClass() can not return null.", valueClass);
116            Set<T> validValues = object.getValidValues();
117            if (validValues != null) {
118                validate(validValues);
119                for (final T value : validValues) {
120                    if (value != null) {
121                        assertInstanceOf("ParameterDescriptor: getValidValues() has unexpected element.", valueClass, value);
122                    }
123                }
124            }
125            final Comparable<T> min = object.getMinimumValue();
126            if (min != null) {
127                assertInstanceOf("ParameterDescriptor: getMinimumValue() returns unexpected value.", valueClass, min);
128            }
129            final Comparable<T> max = object.getMaximumValue();
130            if (max != null) {
131                assertInstanceOf("ParameterDescriptor: getMaximumValue() returns unexpected value.", valueClass, max);
132            }
133            assertValidRange("ParameterDescriptor: inconsistent minimum and maximum values.", min, max);
134            final T def = object.getDefaultValue();
135            if (def != null) {
136                assertInstanceOf("ParameterDescriptor: getDefaultValue() returns unexpected value.", valueClass, def);
137                assertBetween("ParameterDescriptor: getDefaultValue() out of range.", min, max, def);
138            }
139            assertBetween("ParameterDescriptor: getMinimumOccurs() shall returns 0 or 1.", 0, 1, object.getMinimumOccurs());
140            assertEquals("ParameterDescriptor: getMaximumOccurs() shall returns exactly 1.", 1, object.getMaximumOccurs());
141        }
142    
143        /**
144         * Validates the given descriptor.
145         *
146         * @param object The object to validate, or {@code null}.
147         */
148        public void validate(final ParameterDescriptorGroup object) {
149            if (object == null) {
150                return;
151            }
152            validateIdentifiedObject(object);
153            final List<GeneralParameterDescriptor> descriptors = object.descriptors();
154            if (requireMandatoryAttributes) {
155                // Do not invoke mandatory(...) because we allow empty collections.
156                assertNotNull("ParameterDescriptorGroup: descriptors() should not return null.", descriptors);
157            }
158            if (descriptors != null) {
159                validate(descriptors);
160                for (final GeneralParameterDescriptor descriptor : descriptors) {
161                    assertNotNull("ParameterDescriptorGroup: descriptors() can not contain null element.", descriptor);
162                    dispatch(descriptor);
163                    final GeneralParameterDescriptor byName = object.descriptor(descriptor.getName().getCode());
164                    mandatory("ParameterDescriptorGroup: descriptor(String) should returns a value.", byName);
165                    if (byName != null) {
166                        assertEquals("ParameterDescriptorGroup: descriptor(String) inconsistent with descriptors().",
167                                descriptor, byName);
168                    }
169                }
170            }
171            final int minOccurs = object.getMinimumOccurs();
172            assertPositive("ParameterDescriptor: getMinimumOccurs() can not be negative.", minOccurs);
173            assertValidRange("ParameterDescriptor: getMaximumOccurs() gives inconsistent range.",
174                    minOccurs, object.getMaximumOccurs());
175        }
176    
177        /**
178         * Validates the given parameter value.
179         *
180         * @param <T> The class of parameter values.
181         * @param object The object to validate, or {@code null}.
182         */
183        public <T> void validate(final ParameterValue<T> object) {
184            if (object == null) {
185                return;
186            }
187            final ParameterDescriptor<T> descriptor = object.getDescriptor();
188            mandatory("ParameterValue: must have a descriptor.", descriptor);
189            validate(descriptor);
190            final T value = object.getValue();
191            if (value != null) {
192                if (descriptor != null) {
193                    final Class<T> valueClass = descriptor.getValueClass();
194                    assertInstanceOf("ParameterValue: getValue() returns unexpected value.", valueClass, value);
195                    final Set<T> validValues = descriptor.getValidValues();
196                    if (validValues != null) {
197                        validate(validValues);
198                        assertContains("ParameterValue: getValue() not a member of getValidValues() set.",
199                                validValues, value);
200                    }
201                    assertBetween("ParameterValue: getValue() is out of bounds.",
202                            descriptor.getMinimumValue(), descriptor.getMaximumValue(), value);
203                }
204            }
205        }
206    
207        /**
208         * Validates the given coordinate system.
209         *
210         * @param object The object to validate, or {@code null}.
211         */
212        public void validate(final ParameterValueGroup object) {
213            if (object == null) {
214                return;
215            }
216            final ParameterDescriptorGroup descriptors = object.getDescriptor();
217            mandatory("ParameterValueGroup: must have a descriptor.", descriptors);
218            validate(descriptors);
219            final List<GeneralParameterValue> values = object.values();
220            if (requireMandatoryAttributes) {
221                // Do not invoke mandatory(...) because we allow empty collections.
222                assertNotNull("ParameterValueGroup: values() should not return null.", values);
223            }
224            if (values == null) {
225                return;
226            }
227            validate(values);
228            for (final GeneralParameterValue value : values) {
229                assertNotNull("ParameterValueGroup: values() can not contain null element.", value);
230                dispatch(value);
231                final GeneralParameterDescriptor descriptor = value.getDescriptor();
232                mandatory("GeneralParameterValue: expected a descriptor.", descriptor);
233                if (descriptor == null) {
234                    continue;
235                }
236                final String name = descriptor.getName().getCode();
237                mandatory("GeneralParameterDescriptor: expected a name.", name);
238                if (name == null) {
239                    continue;
240                }
241                if (descriptors != null) {
242                    final GeneralParameterDescriptor byName = descriptors.descriptor(name);
243                    mandatory("ParameterDescriptorGroup: should never return null.", byName);
244                    if (byName != null) {
245                        assertEquals("ParameterValueGroup: descriptor(String) inconsistent" +
246                                " with value.getDescriptor().", descriptor, byName);
247                    }
248                }
249                if (value instanceof ParameterValue<?>) {
250                    final ParameterValue<?> byName = object.parameter(name);
251                    mandatory("ParameterValueGroup: parameter(String) should returns a value.", byName);
252                    if (byName != null) {
253                        assertEquals("ParameterValueGroup: value(String) inconsistent with values().", value, byName);
254                    }
255                }
256            }
257        }
258    }