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.Set; 021import java.util.List; 022 023import org.opengis.parameter.*; 024import org.opengis.test.ValidatorContainer; 025import static org.junit.jupiter.api.Assertions.*; 026import static org.opengis.test.Assertions.assertBetween; 027import static org.opengis.test.Assertions.assertPositive; 028import static org.opengis.test.Assertions.assertContains; 029import static org.opengis.test.Assertions.assertValidRange; 030 031 032/** 033 * Validates {@link ParameterValue} and related objects from the {@code org.opengis.parameter} 034 * package. 035 * 036 * <p>This class is provided for users wanting to override the validation methods. When the default 037 * behavior is sufficient, the {@link org.opengis.test.Validators} static methods provide a more 038 * convenient way to validate various kinds of objects.</p> 039 * 040 * @author Martin Desruisseaux (Geomatys) 041 * @version 3.1 042 * @since 2.2 043 */ 044public class ParameterValidator extends ReferencingValidator { 045 /** 046 * Creates a new validator instance. 047 * 048 * @param container the set of validators to use for validating other kinds of objects 049 * (see {@linkplain #container field javadoc}). 050 */ 051 public ParameterValidator(final ValidatorContainer container) { 052 super(container, "org.opengis.parameter"); 053 } 054 055 /** 056 * For each interface implemented by the given object, invokes the corresponding 057 * {@code validate(…)} method defined in this class (if any). 058 * 059 * @param object the object to dispatch to {@code validate(…)} methods, or {@code null}. 060 * @return number of {@code validate(…)} methods invoked in this class for the given object. 061 */ 062 public int dispatch(final GeneralParameterDescriptor object) { 063 int n = 0; 064 if (object != null) { 065 if (object instanceof ParameterDescriptor<?>) {validate((ParameterDescriptor<?>) object); n++;} 066 if (object instanceof ParameterDescriptorGroup) {validate((ParameterDescriptorGroup) object); n++;} 067 if (n == 0) { 068 validateIdentifiedObject(object); 069 } 070 } 071 return n; 072 } 073 074 /** 075 * For each interface implemented by the given object, invokes the corresponding 076 * {@code validate(…)} method defined in this class (if any). 077 * 078 * @param object the object to dispatch to {@code validate(…)} methods, or {@code null}. 079 * @return number of {@code validate(…)} methods invoked in this class for the given object. 080 */ 081 public int dispatch(final GeneralParameterValue object) { 082 int n = 0; 083 if (object != null) { 084 if (object instanceof ParameterValue<?>) {validate((ParameterValue<?>) object); n++;} 085 if (object instanceof ParameterValueGroup) {validate((ParameterValueGroup) object); n++;} 086 if (n == 0) { 087 dispatch(object.getDescriptor()); 088 } 089 } 090 return n; 091 } 092 093 /** 094 * Validates the given descriptor. 095 * 096 * @param <T> the class of parameter values. 097 * @param object the object to validate, or {@code null}. 098 */ 099 public <T> void validate(final ParameterDescriptor<T> object) { 100 if (object == null) { 101 return; 102 } 103 validateIdentifiedObject(object); 104 final Class<T> valueClass = object.getValueClass(); 105 mandatory(valueClass, "ParameterDescriptor: getValueClass() cannot return null."); 106 Set<T> validValues = object.getValidValues(); 107 if (validValues != null) { 108 validate(validValues); 109 for (final T value : validValues) { 110 if (value != null) { 111 assertInstanceOf(valueClass, value, "ParameterDescriptor: getValidValues() has unexpected element."); 112 } 113 } 114 } 115 final Comparable<T> min = object.getMinimumValue(); 116 if (min != null) { 117 assertInstanceOf(valueClass, min, "ParameterDescriptor: getMinimumValue() returns unexpected value."); 118 } 119 final Comparable<T> max = object.getMaximumValue(); 120 if (max != null) { 121 assertInstanceOf(valueClass, max, "ParameterDescriptor: getMaximumValue() returns unexpected value."); 122 } 123 assertValidRange(min, max, "ParameterDescriptor: inconsistent minimum and maximum values."); 124 final T def = object.getDefaultValue(); 125 if (def != null) { 126 assertInstanceOf(valueClass, def, "ParameterDescriptor: getDefaultValue() returns unexpected value."); 127 assertBetween(min, max, def, "ParameterDescriptor: getDefaultValue() out of range."); 128 } 129 assertBetween(0, 1, object.getMinimumOccurs(), "ParameterDescriptor: getMinimumOccurs() shall returns 0 or 1."); 130 assertEquals(1, object.getMaximumOccurs(), "ParameterDescriptor: getMaximumOccurs() shall returns exactly 1."); 131 } 132 133 /** 134 * Validates the given descriptor. 135 * 136 * @param object the object to validate, or {@code null}. 137 */ 138 public void validate(final ParameterDescriptorGroup object) { 139 if (object == null) { 140 return; 141 } 142 validateIdentifiedObject(object); 143 final List<GeneralParameterDescriptor> descriptors = object.descriptors(); 144 if (requireMandatoryAttributes) { 145 // Do not invoke mandatory(…) because we allow empty collections. 146 assertNotNull(descriptors, "ParameterDescriptorGroup: descriptors() should not return null."); 147 } 148 if (descriptors != null) { 149 validate(descriptors); 150 for (final GeneralParameterDescriptor descriptor : descriptors) { 151 assertNotNull(descriptor, "ParameterDescriptorGroup: descriptors() cannot contain null element."); 152 dispatch(descriptor); 153 final GeneralParameterDescriptor byName = object.descriptor(descriptor.getName().getCode()); 154 mandatory(byName, "ParameterDescriptorGroup: descriptor(String) should returns a value."); 155 if (byName != null) { 156 assertEquals(descriptor, byName, "ParameterDescriptorGroup: descriptor(String) inconsistent with descriptors()."); 157 } 158 } 159 } 160 final int minOccurs = object.getMinimumOccurs(); 161 assertPositive(minOccurs, "ParameterDescriptor: getMinimumOccurs() cannot be negative."); 162 assertValidRange(minOccurs, object.getMaximumOccurs(), 163 "ParameterDescriptor: getMaximumOccurs() gives inconsistent range."); 164 } 165 166 /** 167 * Validates the given parameter value. 168 * 169 * @param <T> the class of parameter values. 170 * @param object the object to validate, or {@code null}. 171 */ 172 public <T> void validate(final ParameterValue<T> object) { 173 if (object == null) { 174 return; 175 } 176 final ParameterDescriptor<T> descriptor = object.getDescriptor(); 177 mandatory(descriptor, "ParameterValue: shall have a descriptor."); 178 validate(descriptor); 179 final T value = object.getValue(); 180 if (value != null) { 181 if (descriptor != null) { 182 final Class<T> valueClass = descriptor.getValueClass(); 183 assertInstanceOf(valueClass, value, "ParameterValue: getValue() returns unexpected value."); 184 final Set<T> validValues = descriptor.getValidValues(); 185 if (validValues != null) { 186 validate(validValues); 187 assertContains(validValues, value, "ParameterValue: getValue() not a member of getValidValues() set."); 188 } 189 assertBetween(descriptor.getMinimumValue(), descriptor.getMaximumValue(), value, 190 "ParameterValue: getValue() is out of bounds."); 191 } 192 } 193 } 194 195 /** 196 * Validates the given coordinate system. 197 * 198 * @param object the object to validate, or {@code null}. 199 */ 200 public void validate(final ParameterValueGroup object) { 201 if (object == null) { 202 return; 203 } 204 final ParameterDescriptorGroup descriptors = object.getDescriptor(); 205 mandatory(descriptors, "ParameterValueGroup: shall have a descriptor."); 206 validate(descriptors); 207 final List<GeneralParameterValue> values = object.values(); 208 if (requireMandatoryAttributes) { 209 // Do not invoke mandatory(…) because we allow empty collections. 210 assertNotNull(values, "ParameterValueGroup: values() should not return null."); 211 } 212 if (values == null) { 213 return; 214 } 215 validate(values); 216 for (final GeneralParameterValue value : values) { 217 assertNotNull(value, "ParameterValueGroup: values() cannot contain null element."); 218 dispatch(value); 219 final GeneralParameterDescriptor descriptor = value.getDescriptor(); 220 mandatory(descriptor, "GeneralParameterValue: expected a descriptor."); 221 if (descriptor == null) { 222 continue; 223 } 224 final String name = descriptor.getName().getCode(); 225 mandatory(name, "GeneralParameterDescriptor: expected a name."); 226 if (name == null) { 227 continue; 228 } 229 if (descriptors != null) { 230 final GeneralParameterDescriptor byName = descriptors.descriptor(name); 231 mandatory(byName, "ParameterDescriptorGroup: should never return null."); 232 if (byName != null) { 233 assertEquals(descriptor, byName, 234 "ParameterValueGroup: descriptor(String) inconsistent with value.getDescriptor()."); 235 } 236 } 237 if (value instanceof ParameterValue<?>) { 238 final ParameterValue<?> byName = object.parameter(name); 239 mandatory(byName, "ParameterValueGroup: parameter(String) should returns a value."); 240 if (byName != null) { 241 assertEquals(value, byName, "ParameterValueGroup: value(String) inconsistent with values()."); 242 } 243 } 244 } 245 } 246}