001/* 002 * GeoAPI - Java interfaces for OGC/ISO standards 003 * http://www.geoapi.org 004 * 005 * Copyright (C) 2016-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; 033 034import javax.measure.Unit; 035import javax.measure.quantity.Time; 036import javax.measure.quantity.Angle; 037import javax.measure.quantity.Length; 038import javax.measure.quantity.Pressure; 039import javax.measure.quantity.Dimensionless; 040import javax.measure.spi.ServiceProvider; 041import javax.measure.spi.SystemOfUnits; 042import org.opengis.test.util.PseudoFactory; 043 044 045/** 046 * Pre-defined constants for the units of measurement used by the conformance tests. 047 * This pseudo-factory provides separated methods for all units needed by {@code geoapi-conformance}. 048 * 049 * @author Martin Desruisseaux (Geomatys) 050 * @version 3.1 051 * @since 3.0.1 052 */ 053public class Units extends PseudoFactory { 054 /** 055 * The default instance, created when first needed. 056 * 057 * @see #getDefault() 058 */ 059 private static Units DEFAULT; 060 061 /** 062 * Linear units used in the tests. 063 */ 064 private final Unit<Length> metre, kilometre, foot, footSurveyUS; 065 066 /** 067 * Angular units used in the tests. 068 */ 069 private final Unit<Angle> radian, microradian, degree, grad, arcSecond; 070 071 /** 072 * Temporal units used in the tests. 073 */ 074 private final Unit<Time> second, day; 075 076 /** 077 * Pressure units used in the tests. 078 */ 079 private final Unit<Pressure> pascal, hectopascal; 080 081 /** 082 * Scale units used in the tests. 083 */ 084 private final Unit<Dimensionless> one, ppm; 085 086 /** 087 * Creates a new factory which will use the given system of units. 088 * 089 * @param system the system of units to use for creating base units. 090 */ 091 public Units(final SystemOfUnits system) { 092 metre = system.getUnit(Length.class); 093 radian = system.getUnit(Angle.class); 094 second = system.getUnit(Time.class); 095 pascal = system.getUnit(Pressure.class); 096 one = getDimensionless(system); 097 kilometre = metre .multiply(1000); 098 foot = metre .multiply(0.3048); 099 footSurveyUS = metre .multiply(12 / 39.37); 100 degree = radian.multiply(Math.PI / 180); 101 grad = radian.multiply(Math.PI / 200); 102 arcSecond = radian.multiply(Math.PI / (180*60*60)); 103 microradian = radian.divide(1E6); 104 day = second.multiply(24*60*60); 105 hectopascal = pascal.multiply(100); 106 ppm = one .divide(1000000); 107 } 108 109 /** 110 * Returns the default units factory. This factory uses the unit service provider which is 111 * {@linkplain ServiceProvider#current() current} at the time of the first invocation of this method. 112 * 113 * @return the default units factory. 114 */ 115 public static synchronized Units getDefault() { 116 if (DEFAULT == null) { 117 DEFAULT = new Units(ServiceProvider.current().getSystemOfUnitsService().getSystemOfUnits()); 118 } 119 return DEFAULT; 120 } 121 122 /** 123 * Returns the dimensionless unit. This is a workaround for what seems to be a bug 124 * in the reference implementation 1.0.1 of unit API. 125 */ 126 private static Unit<Dimensionless> getDimensionless(final SystemOfUnits system) { 127 Unit<Dimensionless> unit = system.getUnit(Dimensionless.class); 128 if (unit == null) try { 129 unit = ((Unit<?>) Class.forName("tec.units.ri.AbstractUnit").getField("ONE").get(null)).asType(Dimensionless.class); 130 } catch (ReflectiveOperationException | ClassCastException e) { 131 throw new IllegalArgumentException("Can not create a dimensionless unit from the given provider."); 132 } 133 return unit; 134 } 135 136 /** Base unit of measurement for lengths. */ public Unit<Length> metre() {return metre;} 137 /** Unit of measurement defined as 1000 metres. */ public Unit<Length> kilometre() {return kilometre;} 138 /** Unit of measurement defined as 0.3048 metres. */ public Unit<Length> foot() {return foot;} 139 /** Unit of measurement defined as 12/39.37 metres. */ public Unit<Length> footSurveyUS() {return footSurveyUS;} 140 /** Base unit of measurement for angle. */ public Unit<Angle> radian() {return radian;} 141 /** Unit of measurement defined as 1E-6 radians. */ public Unit<Angle> microradian() {return microradian;} 142 /** Unit of measurement defined as π/180 radians. */ public Unit<Angle> degree() {return degree;} 143 /** Unit of measurement defined as π/200 radians. */ public Unit<Angle> grad() {return grad;} 144 /** Unit of measurement defined as 1/(60×60) degree. */ public Unit<Angle> arcSecond() {return arcSecond;} 145 /** Base unit of measurement for durations. */ public Unit<Time> second() {return second;} 146 /** Unit of measurement defined as 24×60×60 seconds. */ public Unit<Time> day() {return day;} 147 /** Base unit of measurement for pressure. */ public Unit<Pressure> pascal() {return pascal;} 148 /** Unit of measurement defined as 100 pascals. */ public Unit<Pressure> hectopascal() {return hectopascal;} 149 /** Dimensionless unit for scale measurements. */ public Unit<Dimensionless> one() {return one;} 150 /** The "parts per million" unit. */ public Unit<Dimensionless> ppm() {return ppm;} 151}