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.referencing; 033 034import java.util.Date; 035import javax.measure.Unit; 036import javax.measure.quantity.Angle; 037import javax.measure.quantity.Length; 038 039import org.opengis.referencing.datum.*; 040import org.opengis.test.ValidatorContainer; 041import static org.opengis.test.Assert.*; 042 043 044/** 045 * Validates {@link Datum} and related objects from the {@code org.opengis.datum} package. 046 * 047 * <p>This class is provided for users wanting to override the validation methods. When the default 048 * behavior is sufficient, the {@link org.opengis.test.Validators} static methods provide a more 049 * convenient way to validate various kinds of objects.</p> 050 * 051 * @author Martin Desruisseaux (Geomatys) 052 * @version 3.1 053 * @since 2.2 054 */ 055public class DatumValidator extends ReferencingValidator { 056 /** 057 * Creates a new validator instance. 058 * 059 * @param container the set of validators to use for validating other kinds of objects 060 * (see {@linkplain #container field javadoc}). 061 */ 062 public DatumValidator(ValidatorContainer container) { 063 super(container, "org.opengis.referencing.datum"); 064 } 065 066 /** 067 * For each interface implemented by the given object, invokes the corresponding 068 * {@code validate(…)} method defined in this class (if any). 069 * 070 * @param object the object to dispatch to {@code validate(…)} methods, or {@code null}. 071 * @return number of {@code validate(…)} methods invoked in this class for the given object. 072 */ 073 public int dispatch(final Datum object) { 074 int n = 0; 075 if (object != null) { 076 if (object instanceof GeodeticDatum) {validate((GeodeticDatum) object); n++;} 077 if (object instanceof VerticalDatum) {validate((VerticalDatum) object); n++;} 078 if (object instanceof TemporalDatum) {validate((TemporalDatum) object); n++;} 079 if (object instanceof ImageDatum) {validate((ImageDatum) object); n++;} 080 if (object instanceof EngineeringDatum) {validate((EngineeringDatum) object); n++;} 081 if (n == 0) { 082 validateIdentifiedObject(object); 083 } 084 } 085 return n; 086 } 087 088 /** 089 * Validates the given prime meridian. 090 * 091 * @param object the object to validate, or {@code null}. 092 */ 093 public void validate(final PrimeMeridian object) { 094 if (object == null) { 095 return; 096 } 097 validateIdentifiedObject(object); 098 final Unit<Angle> unit = object.getAngularUnit(); 099 mandatory("PrimeMeridian: shall have a unit of measurement.", unit); 100 double longitude = object.getGreenwichLongitude(); 101 if (unit != null) { 102 final Unit<Angle> degree = units.degree(); 103 assertTrue("PrimeMeridian: unit must be compatible with degrees.", unit.isCompatible(degree)); 104 longitude = unit.getConverterTo(degree).convert(longitude); 105 } 106 assertBetween("PrimeMeridian: expected longitude in [-180 … +180]° range.", -180, +180, longitude); 107 } 108 109 /** 110 * Validates the given ellipsoid. 111 * This method checks the following conditions: 112 * 113 * <ul> 114 * <li>{@linkplain Ellipsoid#getAxisUnit() Axis unit} is defined and is linear.</li> 115 * <li>{@linkplain Ellipsoid#getSemiMinorAxis() semi-minor} <= {@linkplain Ellipsoid#getSemiMajorAxis() semi-major}.</li> 116 * <li>{@linkplain Ellipsoid#getInverseFlattening() inverse flattening} > 0.</li> 117 * <li>Consistency of semi-minor axis length with inverse flattening factor.</li> 118 * </ul> 119 * 120 * @param object the object to validate, or {@code null}. 121 */ 122 public void validate(final Ellipsoid object) { 123 if (object == null) { 124 return; 125 } 126 validateIdentifiedObject(object); 127 final Unit<Length> unit = object.getAxisUnit(); 128 mandatory("Ellipsoid: shall have a unit of measurement.", unit); 129 if (unit != null) { 130 assertTrue("Ellipsoid: unit must be compatible with metres.", unit.isCompatible(units.metre())); 131 } 132 final double semiMajor = object.getSemiMajorAxis(); 133 final double semiMinor = object.getSemiMinorAxis(); 134 final double inverseFlattening = object.getInverseFlattening(); 135 assertTrue("Ellipsoid: expected semi-major axis length > 0.", semiMajor > 0); 136 assertTrue("Ellipsoid: expected semi-minor axis length > 0.", semiMinor > 0); 137 assertTrue("Ellipsoid: expected semi-minor <= semi-major axis length.", semiMinor <= semiMajor); 138 assertTrue("Ellipsoid: expected inverse flattening > 0.", inverseFlattening > 0); 139 if (!object.isSphere()) { 140 assertEquals("Ellipsoid: inconsistent semi-major axis length.", 141 semiMajor - semiMajor/inverseFlattening, semiMinor, semiMinor*DEFAULT_TOLERANCE); 142 assertEquals("Ellipsoid: inconsistent inverse flattening.", 143 semiMajor / (semiMajor-semiMinor), inverseFlattening, inverseFlattening*DEFAULT_TOLERANCE); 144 } 145 } 146 147 /** 148 * Validates the given datum. 149 * 150 * @param object the object to validate, or {@code null}. 151 */ 152 public void validate(final GeodeticDatum object) { 153 if (object == null) { 154 return; 155 } 156 validateIdentifiedObject(object); 157 final PrimeMeridian meridian = object.getPrimeMeridian(); 158 mandatory("GeodeticDatum: shall have a prime meridian.", meridian); 159 validate(meridian); 160 161 final Ellipsoid ellipsoid = object.getEllipsoid(); 162 mandatory("GeodeticDatum: shall have an ellipsoid.", ellipsoid); 163 validate(ellipsoid); 164 } 165 166 /** 167 * Validates the given datum. 168 * 169 * @param object the object to validate, or {@code null}. 170 */ 171 public void validate(final VerticalDatum object) { 172 if (object == null) { 173 return; 174 } 175 validateIdentifiedObject(object); 176 final VerticalDatumType type = object.getVerticalDatumType(); 177 mandatory("VerticalDatum: shall have a datum type.", type); 178 } 179 180 /** 181 * Validates the given datum. 182 * 183 * @param object the object to validate, or {@code null}. 184 */ 185 public void validate(final TemporalDatum object) { 186 if (object == null) { 187 return; 188 } 189 validateIdentifiedObject(object); 190 final Date origin = object.getOrigin(); 191 mandatory("TemporalDatum: expected an origin.", origin); 192 forbidden("TemporalDatum: should not have anchor point.", object.getAnchorPoint()); 193 forbidden("TemporalDatum: should not have realization epoch.", object.getRealizationEpoch()); 194 } 195 196 /** 197 * Validates the given datum. 198 * 199 * @param object the object to validate, or {@code null}. 200 */ 201 public void validate(final ImageDatum object) { 202 if (object == null) { 203 return; 204 } 205 validateIdentifiedObject(object); 206 final PixelInCell pc = object.getPixelInCell(); 207 mandatory("ImageDatum: shall specify PixelInCell.", pc); 208 } 209 210 /** 211 * Validates the given datum. 212 * 213 * @param object the object to validate, or {@code null}. 214 */ 215 public void validate(final EngineeringDatum object) { 216 if (object == null) { 217 return; 218 } 219 validateIdentifiedObject(object); 220 } 221}