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 org.opengis.util.Record; 021import org.opengis.metadata.citation.Citation; 022import org.opengis.metadata.content.RangeDimension; 023import org.opengis.metadata.quality.*; 024import org.opengis.metadata.maintenance.Scope; 025import org.opengis.test.ValidatorContainer; 026 027import static org.junit.jupiter.api.Assertions.*; 028 029 030/** 031 * Validates {@link DataQuality} and related objects from the {@code org.opengis.metadata.quality} package. 032 * 033 * <p>This class is provided for users wanting to override the validation methods. 034 * When the default behavior is sufficient, the {@link org.opengis.test.Validators} 035 * static methods provide a more convenient way to validate various kinds of objects.</p> 036 * 037 * @author Martin Desruisseaux (Geomatys) 038 * @version 3.1 039 * @since 3.1 040 */ 041public class QualityValidator extends MetadataValidator { 042 /** 043 * Creates a new validator instance. 044 * 045 * @param container the set of validators to use for validating other kinds of objects 046 * (see {@linkplain #container field javadoc}). 047 */ 048 public QualityValidator(final ValidatorContainer container) { 049 super(container, "org.opengis.metadata.quality"); 050 } 051 052 /** 053 * For each interface implemented by the given object, invokes the corresponding 054 * {@code validate(…)} method defined in this class (if any). 055 * 056 * @param object the object to dispatch to {@code validate(…)} methods, or {@code null}. 057 * @return number of {@code validate(…)} methods invoked in this class for the given object. 058 */ 059 public int dispatch(final Element object) { 060 int n = 0; 061 if (object != null) { 062 if (object instanceof PositionalAccuracy) {validate((PositionalAccuracy) object); n++;} 063 if (n == 0) { 064 validateElement(object); 065 } 066 } 067 return n; 068 } 069 070 /** 071 * For each interface implemented by the given object, invokes the corresponding 072 * {@code validate(…)} method defined in this class (if any). 073 * 074 * @param object the object to dispatch to {@code validate(…)} methods, or {@code null}. 075 * @return number of {@code validate(…)} methods invoked in this class for the given object. 076 */ 077 public int dispatch(final Result object) { 078 int n = 0; 079 if (object != null) { 080 if (object instanceof DescriptiveResult) {validate((DescriptiveResult) object); n++;} 081 if (object instanceof ConformanceResult) {validate((ConformanceResult) object); n++;} 082 if (object instanceof QuantitativeResult) {validate((QuantitativeResult) object); n++;} 083 if (object instanceof CoverageResult) {validate((CoverageResult) object); n++;} 084 if (n == 0) { 085 validateResult(object); 086 } 087 } 088 return n; 089 } 090 091 /** 092 * Validates the data quality. 093 * 094 * @param object the object to validate, or {@code null}. 095 */ 096 public void validate(final DataQuality object) { 097 if (object == null) { 098 return; 099 } 100 final Scope scope = object.getScope(); 101 mandatory(scope, "DataQuality: must have a scope."); 102 container.validate(scope); 103 final Element[] reports = toArray(Element.class, object.getReports()); 104 if (requireMandatoryAttributes) { 105 assertNotEquals(0, reports.length, "DataQuality: must have at least one report."); 106 } 107 for (final Element element : reports) { 108 dispatch(element); 109 } 110 } 111 112 /** 113 * Validates the positional accuracy. 114 * 115 * @param object the object to validate, or {@code null}. 116 */ 117 public void validate(final PositionalAccuracy object) { 118 if (object == null) { 119 return; 120 } 121 validateElement(object); 122 } 123 124 /** 125 * Validates the properties common to all elements. 126 * 127 * @param object the object to validate. 128 */ 129 private void validateElement(final Element object) { 130 container.validate(object.getStandaloneQualityReportDetails()); 131 for (final Result result : toArray(Result.class, object.getResults())) { 132 dispatch(result); 133 } 134 } 135 136 /** 137 * Validates the descriptive result. 138 * 139 * @param object the object to validate, or {@code null}. 140 */ 141 public void validate(final DescriptiveResult object) { 142 if (object == null) { 143 return; 144 } 145 validateResult(object); 146 validateMandatory(object.getStatement()); 147 } 148 149 /** 150 * Validates the conformance result. 151 * 152 * @param object the object to validate, or {@code null}. 153 */ 154 public void validate(final ConformanceResult object) { 155 if (object == null) { 156 return; 157 } 158 validateResult(object); 159 Citation specification = object.getSpecification(); 160 mandatory(specification, "ConformanceResult: must have a specification."); 161 container.validate(specification); 162 container.validate(object.getExplanation()); 163 mandatory(object.pass(), "ConformanceResult: must have a Boolean."); 164 } 165 166 /** 167 * Validates the quantitative result. 168 * 169 * @param object the object to validate, or {@code null}. 170 */ 171 public void validate(final QuantitativeResult object) { 172 if (object == null) { 173 return; 174 } 175 validateResult(object); 176 int count = toArray(Record.class, object.getValues()).length; 177 if (requireMandatoryAttributes) { 178 assertNotEquals(0, count, "QuantitativeResult: must have at least one value."); 179 } 180 } 181 182 /** 183 * Validates the coverage result. 184 * 185 * @param object the object to validate, or {@code null}. 186 */ 187 public void validate(final CoverageResult object) { 188 if (object == null) { 189 return; 190 } 191 validateResult(object); 192 mandatory(object.getSpatialRepresentationType(), "CoverageResult: must have a spatial representation type."); 193 mandatory(object.getResultSpatialRepresentation(), "CoverageResult: must have a result spatial representation."); 194 final RangeDimension[] ranges = toArray(RangeDimension.class, object.getResultContent()); 195 if (object.getResultFormat() == null && object.getResultFile() == null && requireMandatoryAttributes) { 196 assertNotEquals(0, ranges.length, "CoverageResult: must have at least one range dimension" 197 + " when result format and result file are not provided."); 198 } 199 } 200 201 /** 202 * Validates the properties common to all results. 203 * 204 * @param object the object to validate. 205 */ 206 private void validateResult(final Result object) { 207 container.validate(object.getResultScope()); 208 } 209}