001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2008-2024 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.test.referencing;
019
020import java.util.Optional;
021import org.opengis.referencing.*;
022import org.opengis.referencing.cs.*;
023import org.opengis.referencing.crs.*;
024import org.opengis.referencing.datum.*;
025import org.opengis.referencing.operation.*;
026import org.opengis.parameter.GeneralParameterDescriptor;
027import org.opengis.metadata.extent.Extent;
028import org.opengis.metadata.Identifier;
029import org.opengis.util.InternationalString;
030
031import org.opengis.test.Units;
032import org.opengis.test.Validator;
033import org.opengis.test.ValidatorContainer;
034import static org.junit.jupiter.api.Assertions.assertNotNull;
035
036
037/**
038 * Base class for validators of {@link IdentifiedObject} and related objects from the
039 * {@code org.opengis.referencing} package.
040 *
041 * <p>This class is provided for users wanting to override the validation methods. When the default
042 * behavior is sufficient, the {@link org.opengis.test.Validators} static methods provide a more
043 * convenient way to validate various kinds of objects.</p>
044 *
045 * @author  Martin Desruisseaux (Geomatys)
046 * @version 3.1
047 * @since   2.2
048 */
049public abstract class ReferencingValidator extends Validator {
050    /**
051     * Provider of units of measurement (degree, metre, second, <i>etc</i>).
052     * This field is set to the {@linkplain Units#getDefault() default provider} for now
053     * (it may be revisited in a future GeoAPI-conformance version).
054     */
055    final Units units = Units.getDefault();
056
057    /**
058     * Creates a new validator instance.
059     *
060     * @param container    the set of validators to use for validating other kinds of objects
061     *                     (see {@linkplain #container field javadoc}).
062     * @param packageName  the name of the package containing the classes to be validated.
063     */
064    protected ReferencingValidator(final ValidatorContainer container, final String packageName) {
065        super(container, packageName);
066    }
067
068    /**
069     * For each interface implemented by the given object, invokes the corresponding
070     * {@code validate(…)} method defined in this package (if any).
071     *
072     * @param  object  the object to dispatch to {@code validate(…)} methods, or {@code null}.
073     */
074    public final void dispatchObject(final IdentifiedObject object) {
075        int n = 0;
076        if (object != null) {
077            if (object instanceof CoordinateReferenceSystem)  {container.validate((CoordinateReferenceSystem)  object); n++;}
078            if (object instanceof CoordinateSystem)           {container.validate((CoordinateSystem)           object); n++;}
079            if (object instanceof CoordinateSystemAxis)       {container.validate((CoordinateSystemAxis)       object); n++;}
080            if (object instanceof Datum)                      {container.validate((Datum)                      object); n++;}
081            if (object instanceof Ellipsoid)                  {container.validate((Ellipsoid)                  object); n++;}
082            if (object instanceof PrimeMeridian)              {container.validate((PrimeMeridian)              object); n++;}
083            if (object instanceof GeneralParameterDescriptor) {container.validate((GeneralParameterDescriptor) object); n++;}
084            if (object instanceof CoordinateOperation)        {container.validate((CoordinateOperation)        object); n++;}
085            if (object instanceof OperationMethod)            {container.validate((OperationMethod)            object); n++;}
086            if (n == 0) {
087                validateIdentifiedObject(object);
088            }
089        }
090    }
091
092    /**
093     * Ensures that the given domain has a scope and a domain of validity.
094     *
095     * @param  object  the object to validate, or {@code null}.
096     *
097     * @since 3.1
098     */
099    public void validate(final ObjectDomain object) {
100        if (object == null) {
101            return;
102        }
103        final InternationalString scope = object.getScope();
104        mandatory(scope, "ObjectDomain: shall have a scope.");
105        final Extent domain = object.getDomainOfValidity();
106        mandatory(domain, "ObjectDomain: shall have a domain of validity.");
107        container.validate(scope);
108        container.validate(domain);
109    }
110
111    /**
112     * Performs the validation that are common to all identified objects. This method is
113     * invoked by {@code validate} methods after they have determined the type of their
114     * argument.
115     *
116     * @param  object  the object to validate (cannot be null).
117     */
118    final void validateIdentifiedObject(final IdentifiedObject object) {
119        final Identifier name = object.getName();
120        mandatory(name, "IdentifiedObject: shall have a name.");
121        container.validate(name);
122        validate("identifier", object.getIdentifiers(), ValidatorContainer::validate, false);
123        validate("alias",      object.getAlias(),       ValidatorContainer::validate, false);
124        validate("domain",     object.getDomains(),     ValidatorContainer::validate, false);
125        container.validate(getRemarks(object));
126    }
127
128    /**
129     * Returns the remarks of the given object.
130     *
131     * @param  object  the object for which to get the remarks.
132     * @return the remarks, or {@code null} if none.
133     */
134    static InternationalString getRemarks(final IdentifiedObject object) {
135        return object.getRemarks();
136    }
137}