001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    http://www.geoapi.org
004 *
005 *    Copyright (C) 2008-2019 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 */
032package org.opengis.test.metadata;
033
034import org.opengis.metadata.*;
035import org.opengis.metadata.extent.*;
036import org.opengis.geometry.Geometry;
037import org.opengis.test.ValidatorContainer;
038import static org.opengis.test.Assert.*;
039
040
041/**
042 * Validates {@link Extent} and related objects from the
043 * {@code org.opengis.metadata.extent} package.
044 *
045 * <p>This class is provided for users wanting to override the validation methods. When the default
046 * behavior is sufficient, the {@link org.opengis.test.Validators} static methods provide a more
047 * convenient way to validate various kinds of objects.</p>
048 *
049 * @author  Martin Desruisseaux (Geomatys)
050 * @version 3.1
051 * @since   2.2
052 */
053public class ExtentValidator extends MetadataValidator {
054    /**
055     * Creates a new validator instance.
056     *
057     * @param container  the set of validators to use for validating other kinds of objects
058     *                   (see {@linkplain #container field javadoc}).
059     */
060    public ExtentValidator(final ValidatorContainer container) {
061        super(container, "org.opengis.metadata.extent");
062    }
063
064    /**
065     * For each interface implemented by the given object, invokes the corresponding
066     * {@code validate(…)} method defined in this class (if any).
067     *
068     * @param  object  the object to dispatch to {@code validate(…)} methods, or {@code null}.
069     * @return number of {@code validate(…)} methods invoked in this class for the given object.
070     */
071    public int dispatch(final GeographicExtent object) {
072        int n = 0;
073        if (object != null) {
074            if (object instanceof GeographicDescription) {validate((GeographicDescription) object); n++;}
075            if (object instanceof GeographicBoundingBox) {validate((GeographicBoundingBox) object); n++;}
076            if (object instanceof BoundingPolygon)       {validate((BoundingPolygon)       object); n++;}
077        }
078        return n;
079    }
080
081    /**
082     * Validates the geographic description.
083     *
084     * @param  object  the object to validate, or {@code null}.
085     */
086    public void validate(final GeographicDescription object) {
087        if (object == null) {
088            return;
089        }
090        final Identifier identifier = object.getGeographicIdentifier();
091        mandatory("GeographicDescription: must have an identifier.", identifier);
092    }
093
094    /**
095     * Validates the bounding polygon.
096     *
097     * @param  object  the object to validate, or {@code null}.
098     *
099     * @todo Not yet implemented.
100     */
101    public void validate(final BoundingPolygon object) {
102        if (object == null) {
103            return;
104        }
105        for (final Geometry e : toArray(Geometry.class, object.getPolygons())) {
106            // TODO
107        }
108    }
109
110    /**
111     * Validates the geographic bounding box.
112     *
113     * @param  object  the object to validate, or {@code null}.
114     */
115    public void validate(final GeographicBoundingBox object) {
116        if (object == null) {
117            return;
118        }
119        final double west  = object.getWestBoundLongitude();
120        final double east  = object.getEastBoundLongitude();
121        final double south = object.getSouthBoundLatitude();
122        final double north = object.getNorthBoundLatitude();
123        assertBetween("GeographicBoundingBox: illegal west bound.",  -180, +180, west);
124        assertBetween("GeographicBoundingBox: illegal east bound.",  -180, +180, east);
125        assertBetween("GeographicBoundingBox: illegal south bound.", -90,   +90, south);
126        assertBetween("GeographicBoundingBox: illegal north bound.", -90,   +90, north);
127        assertFalse("GeographicBoundingBox: invalid range of latitudes.",  south > north);          // Accept NaN.
128        // Do not require west <= east, as this condition is not specified in ISO 19115.
129        // Some implementations may use west > east for box spanning the anti-meridian.
130    }
131
132    /**
133     * Validates the vertical extent.
134     *
135     * @param  object  the object to validate, or {@code null}.
136     */
137    public void validate(final VerticalExtent object) {
138        if (object == null) {
139            return;
140        }
141        final Double minimum = object.getMinimumValue();
142        final Double maximum = object.getMaximumValue();
143        mandatory("VerticalExtent: must have a minimum value.", minimum);
144        mandatory("VerticalExtent: must have a maximum value.", maximum);
145        if (minimum != null && maximum != null) {
146            assertTrue("VerticalExtent: invalid range.", minimum <= maximum);
147        }
148        container.validate(object.getVerticalCRS());
149    }
150
151    /**
152     * Validates the temporal extent.
153     *
154     * @param  object  the object to validate, or {@code null}.
155     *
156     * @todo Validation of temporal primitives not yet implemented.
157     */
158    public void validate(final TemporalExtent object) {
159        if (object == null) {
160            return;
161        }
162        if (object instanceof SpatialTemporalExtent) {
163            for (final GeographicExtent e : toArray(GeographicExtent.class, ((SpatialTemporalExtent) object).getSpatialExtent())) {
164                dispatch(e);
165            }
166        }
167    }
168
169    /**
170     * Validates the given extent.
171     *
172     * @param  object  the object to validate, or {@code null}.
173     */
174    public void validate(final Extent object) {
175        if (object == null) {
176            return;
177        }
178        validateOptional(object.getDescription());
179        for (GeographicExtent e : toArray(GeographicExtent.class, object.getGeographicElements())) dispatch(e);
180        for (VerticalExtent   e : toArray(VerticalExtent  .class, object.getVerticalElements  ())) validate(e);
181        for (TemporalExtent   e : toArray(TemporalExtent  .class, object.getTemporalElements  ())) validate(e);
182    }
183}