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.metadata;
019
020import java.util.Collection;
021import java.lang.reflect.Array;
022import org.opengis.util.InternationalString;
023
024import org.opengis.test.Validator;
025import org.opengis.test.ValidatorContainer;
026import static org.junit.jupiter.api.Assertions.*;
027
028
029/**
030 * Base class for validators of {@code org.opengis.metadata} package and sub-packages.
031 *
032 * <p>This class is provided for users wanting to override the validation methods. When the default
033 * behavior is sufficient, the {@link org.opengis.test.Validators} static methods provide a more
034 * convenient way to validate various kinds of objects.</p>
035 *
036 * @author  Martin Desruisseaux (Geomatys)
037 * @version 3.1
038 * @since   2.2
039 */
040public abstract class MetadataValidator extends Validator {
041    /**
042     * Creates a new validator instance.
043     *
044     * @param container    the set of validators to use for validating other kinds of objects
045     *                     (see {@linkplain #container field javadoc}).
046     * @param packageName  the name of the package containing the classes to be validated.
047     */
048    protected MetadataValidator(final ValidatorContainer container, final String packageName) {
049        super(container, packageName);
050    }
051
052    /**
053     * Returns all collection elements in an array of the given type. This method ensures that
054     * all elements are non-null and of the expected type. Callers should iterate over the
055     * returned array and validate each elements, if needed.
056     *
057     * @param  <T>          the type of elements in the collection, or {@code null} if none.
058     * @param  elementType  the type of elements in the collection.
059     * @param  objects      the collection to validate (never {@code null}).
060     * @return an array of all elements in the given collection.
061     */
062    final <T> T[] toArray(final Class<T> elementType, final Collection<? extends T> objects) {
063        assertNotNull(objects, "Null collection. Should be an empty one if there is no elements.");
064        validate(objects);
065        @SuppressWarnings("unchecked")
066        final T[] array = (T[]) Array.newInstance(elementType, objects.size());
067        int count = 0;
068        for (final T element : objects) {
069            assertNotNull(element, "Collection should not contain null element.");
070            assertInstanceOf(elementType, element, "Wrong element type in the collection.");
071            array[count++] = element;
072        }
073        assertEquals(array.length, count, "Unexpected end of iteration");
074        return array;
075    }
076
077    /**
078     * Validates the given mandatory string.
079     *
080     * @param  object  the object to validate.
081     */
082    final void validateMandatory(final InternationalString object) {
083        mandatory(object, "Missing mandatory metadata attribute.");
084        container.validate(object);
085    }
086
087    /**
088     * Validates the given optional string.
089     *
090     * @param  object  the object to validate, or {@code null}.
091     */
092    final void validateOptional(final InternationalString object) {
093        container.validate(object);
094    }
095
096    /**
097     * Returns {@code true} if the given text is {@code null}, white or
098     * {@linkplain String#isEmpty() empty}.
099     *
100     * @param  text  the text to test, or {@code null}.
101     * @return {@code true} if the given text is null, white or empty.
102     *
103     * @since 3.1
104     */
105    static boolean isNullOrEmpty(final CharSequence text) {
106        return (text == null) || text.toString().trim().isEmpty();
107    }
108
109    /**
110     * Returns {@code true} if the given collection is {@code null} or
111     * {@linkplain Collection#isEmpty() empty}.
112     *
113     * @param  collection  the text to test, or {@code null}.
114     * @return {@code true} if the given collection is null or empty.
115     *
116     * @since 3.1
117     */
118    static boolean isNullOrEmpty(final Collection<?> collection) {
119        return (collection == null) || collection.isEmpty();
120    }
121}