| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| AutoCRSFactory |
|
| 2.0;2 |
| 1 | /* | |
| 2 | * Geotoolkit.org - An Open Source Java GIS Toolkit | |
| 3 | * http://www.geotoolkit.org | |
| 4 | * | |
| 5 | * (C) 2004-2012, Open Source Geospatial Foundation (OSGeo) | |
| 6 | * (C) 2009-2012, Geomatys | |
| 7 | * | |
| 8 | * This library is free software; you can redistribute it and/or | |
| 9 | * modify it under the terms of the GNU Lesser General Public | |
| 10 | * License as published by the Free Software Foundation; | |
| 11 | * version 2.1 of the License. | |
| 12 | * | |
| 13 | * This library is distributed in the hope that it will be useful, | |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 16 | * Lesser General Public License for more details. | |
| 17 | */ | |
| 18 | package org.geotoolkit.referencing.factory.web; | |
| 19 | ||
| 20 | import java.util.Set; | |
| 21 | import java.util.Map; | |
| 22 | import java.util.TreeMap; | |
| 23 | import java.util.Collections; | |
| 24 | import java.util.LinkedHashSet; | |
| 25 | import net.jcip.annotations.ThreadSafe; | |
| 26 | ||
| 27 | import org.opengis.util.FactoryException; | |
| 28 | import org.opengis.util.InternationalString; | |
| 29 | import org.opengis.metadata.citation.Citation; | |
| 30 | import org.opengis.referencing.IdentifiedObject; | |
| 31 | import org.opengis.referencing.NoSuchAuthorityCodeException; | |
| 32 | import org.opengis.referencing.crs.CoordinateReferenceSystem; | |
| 33 | import org.opengis.referencing.crs.CRSAuthorityFactory; | |
| 34 | import org.opengis.referencing.crs.ProjectedCRS; | |
| 35 | ||
| 36 | import org.geotoolkit.factory.Hints; | |
| 37 | import org.geotoolkit.util.SimpleInternationalString; | |
| 38 | import org.geotoolkit.metadata.iso.citation.Citations; | |
| 39 | import org.geotoolkit.metadata.iso.citation.DefaultCitation; | |
| 40 | import org.geotoolkit.referencing.factory.DirectAuthorityFactory; | |
| 41 | ||
| 42 | // Following are for Javadoc only. | |
| 43 | import org.geotoolkit.measure.Units; | |
| 44 | import org.geotoolkit.referencing.operation.projection.Orthographic; | |
| 45 | import org.geotoolkit.referencing.operation.projection.Equirectangular; | |
| 46 | import org.geotoolkit.referencing.operation.projection.TransverseMercator; | |
| 47 | ||
| 48 | ||
| 49 | /** | |
| 50 | * The factory for {@linkplain ProjectedCRS projected CRS} in the {@code AUTO} and {@code AUTO2} | |
| 51 | * space. The expected format is {@code AUTO:code,<unit>,lon0,lat0} where the {@code AUTO} prefix | |
| 52 | * is optional. The {@code <unit>} parameter is also optional, since it was not present in the WMS | |
| 53 | * 1.0 specification (it has been added later). | |
| 54 | * <p> | |
| 55 | * The parameters are as below: | |
| 56 | * <p> | |
| 57 | * <ul> | |
| 58 | * <li>{@code code} - the projection code, as one of the following values: | |
| 59 | * <ul> | |
| 60 | * <li>42001 for the {@linkplain TransverseMercator Universal Transverse Mercator} projection.</li> | |
| 61 | * <li>42002 for the {@linkplain TransverseMercator Transverse Mercator} projection.</li> | |
| 62 | * <li>42003 for the {@linkplain Orthographic Orthographic} projection.</li> | |
| 63 | * <li>42004 for the {@linkplain Equirectangular Equirectangular} projection.</li> | |
| 64 | * <li>42005 for the Mollweide projection.</li> | |
| 65 | * </ul> | |
| 66 | * </li><li> | |
| 67 | * {@code unit} - the unit of measurement code, as one of the codes documented | |
| 68 | * in the {@link Units#valueOfEPSG(int)} method. This code is optional. If not | |
| 69 | * provided, then the default value is 9001 (<cite>metre</cite>). | |
| 70 | * </li><li> | |
| 71 | * {@code long0} - the central meridian. For UTM projections (42001), it can be computed as | |
| 72 | * (<var>zone</var>*6 - 183) where <var>zone</var> is the UTM zone in the range 1 to 60 | |
| 73 | * inclusive. | |
| 74 | * </li><li> | |
| 75 | * {@code lat0} - the latitude of origin. | |
| 76 | * </li> | |
| 77 | * </ul> | |
| 78 | * | |
| 79 | * {@section Examples} | |
| 80 | * An orthographic CRS centered at 100 degrees West longitude and 45 degrees North latitude, | |
| 81 | * with ordinates in metres. | |
| 82 | * | |
| 83 | * {@preformat text | |
| 84 | * AUTO2:42003,1,-100,45 | |
| 85 | * } | |
| 86 | * | |
| 87 | * Same CRS as above, but with conversion factor allowing ordinate values in U.S. feet: | |
| 88 | * | |
| 89 | * {@preformat text | |
| 90 | * AUTO2:42003,0.3048006096012192,-100,45 | |
| 91 | * } | |
| 92 | * | |
| 93 | * @author Martin Desruisseaux (IRD, Geomatys) | |
| 94 | * @author Jody Garnett (Refractions) | |
| 95 | * @author Rueben Schulz (UBC) | |
| 96 | * @version 3.16 | |
| 97 | * | |
| 98 | * @since 2.0 | |
| 99 | * @module | |
| 100 | */ | |
| 101 | @ThreadSafe | |
| 102 | public class AutoCRSFactory extends DirectAuthorityFactory implements CRSAuthorityFactory { | |
| 103 | /** | |
| 104 | * The authority code. We use the {@code AUTO2} title, but merge the identifiers from | |
| 105 | * {@code AUTO} and {@code AUTO2} in order to use the same factory for both authorities. | |
| 106 | */ | |
| 107 | private static final Citation AUTHORITY; | |
| 108 | static { | |
| 109 | 1 | final DefaultCitation c = new DefaultCitation(Citations.AUTO2); |
| 110 | 1 | c.getIdentifiers().addAll(Citations.AUTO.getIdentifiers()); |
| 111 | 1 | c.freeze(); |
| 112 | 1 | AUTHORITY = c; |
| 113 | 1 | } |
| 114 | ||
| 115 | /** | |
| 116 | * Map of Factlets by integer code (from {@code AUTO:code}). | |
| 117 | * | |
| 118 | * @todo Replace this with full FactorySPI system. | |
| 119 | */ | |
| 120 | 10 | private final Map<Integer,Factlet> factlets = new TreeMap<Integer,Factlet>(); |
| 121 | ||
| 122 | /** | |
| 123 | * Constructs a default factory for the {@code AUTO} authority. | |
| 124 | */ | |
| 125 | public AutoCRSFactory() { | |
| 126 | 10 | this(EMPTY_HINTS); |
| 127 | 10 | } |
| 128 | ||
| 129 | /** | |
| 130 | * Constructs a factory for the {@code AUTO} authority using the specified hints. | |
| 131 | * | |
| 132 | * @param userHints An optional set of hints, or {@code null} for the default ones. | |
| 133 | */ | |
| 134 | public AutoCRSFactory(final Hints userHints) { | |
| 135 | 10 | super(userHints); |
| 136 | 10 | add(Auto42001.DEFAULT); |
| 137 | 10 | add(Auto42002.DEFAULT); |
| 138 | 10 | add(Auto42003.DEFAULT); |
| 139 | 10 | add(Auto42004.DEFAULT); |
| 140 | 10 | add(Auto42005.DEFAULT); |
| 141 | 10 | } |
| 142 | ||
| 143 | /** | |
| 144 | * Adds the specified factlet. | |
| 145 | */ | |
| 146 | private void add(final Factlet f) { | |
| 147 | 50 | final int code = f.code(); |
| 148 | 50 | if (factlets.put(code, f) != null) { |
| 149 | 0 | throw new IllegalArgumentException(String.valueOf(code)); |
| 150 | } | |
| 151 | 50 | } |
| 152 | ||
| 153 | /** | |
| 154 | * Returns the {@link Factlet} for the given code. | |
| 155 | * | |
| 156 | * @param code The code. | |
| 157 | * @return The fatclet for the specified code. | |
| 158 | * @throws NoSuchAuthorityCodeException if no factlet has been found for the specified code. | |
| 159 | */ | |
| 160 | private Factlet findFactlet(final Code code) throws NoSuchAuthorityCodeException { | |
| 161 | 25 | if (code.authority.equalsIgnoreCase("AUTO") || |
| 162 | code.authority.equalsIgnoreCase("AUTO2")) | |
| 163 | { | |
| 164 | 25 | final Integer key = code.code; |
| 165 | 25 | final Factlet fac = factlets.get(key); |
| 166 | 25 | if (fac != null) { |
| 167 | 25 | return fac; |
| 168 | } | |
| 169 | } | |
| 170 | 0 | throw noSuchAuthorityCode(code.type, code.toString()); |
| 171 | } | |
| 172 | ||
| 173 | /** | |
| 174 | * Returns the authority for this factory. | |
| 175 | */ | |
| 176 | @Override | |
| 177 | public Citation getAuthority() { | |
| 178 | 449 | return AUTHORITY; |
| 179 | } | |
| 180 | ||
| 181 | /** | |
| 182 | * Provides a complete set of the known codes provided by this authority. | |
| 183 | * The returned set contains only numeric identifiers like {@code "42001"}, | |
| 184 | * {@code "42002"}, <i>etc</i>. The authority name ({@code "AUTO"}) | |
| 185 | * and the {@code lon0,lat0} part are not included. This is consistent with the | |
| 186 | * {@linkplain org.geotoolkit.referencing.factory.epsg.DirectEpsgFactory#getAuthorityCodes | |
| 187 | * codes returned by the EPSG factory} and avoid duplication, since the authority is the | |
| 188 | * same for every codes returned by this factory. It also make it easier for clients to | |
| 189 | * prepend whatever authority name they wish, as for example in the | |
| 190 | * {@linkplain org.geotoolkit.referencing.factory.AllAuthoritiesFactory#getAuthorityCodes | |
| 191 | * all authorities factory}. | |
| 192 | */ | |
| 193 | @Override | |
| 194 | public Set<String> getAuthorityCodes(final Class<? extends IdentifiedObject> type) | |
| 195 | throws FactoryException | |
| 196 | { | |
| 197 | 5 | if (type.isAssignableFrom(ProjectedCRS.class)) { |
| 198 | 4 | final Set<String> set = new LinkedHashSet<String>(); |
| 199 | 4 | for (final Integer code : factlets.keySet()) { |
| 200 | 20 | set.add(String.valueOf(code)); |
| 201 | } | |
| 202 | 4 | return set; |
| 203 | } else { | |
| 204 | 1 | return Collections.emptySet(); |
| 205 | } | |
| 206 | } | |
| 207 | ||
| 208 | /** | |
| 209 | * Returns the CRS name for the given code. | |
| 210 | * | |
| 211 | * @throws FactoryException if an error occurred while fetching the description. | |
| 212 | */ | |
| 213 | @Override | |
| 214 | public InternationalString getDescriptionText(final String code) throws FactoryException { | |
| 215 | 2 | final Code c = new Code(code, ProjectedCRS.class, false); |
| 216 | 2 | return new SimpleInternationalString(findFactlet(c).getName()); |
| 217 | } | |
| 218 | ||
| 219 | /** | |
| 220 | * Creates an object from the specified code. The default implementation delegates to | |
| 221 | * <code>{@linkplain #createCoordinateReferenceSystem createCoordinateReferenceSystem}(code)</code>. | |
| 222 | * | |
| 223 | * @throws FactoryException if the object creation failed. | |
| 224 | */ | |
| 225 | @Override | |
| 226 | public IdentifiedObject createObject(final String code) throws FactoryException { | |
| 227 | 13 | return createCoordinateReferenceSystem(code); |
| 228 | } | |
| 229 | ||
| 230 | /** | |
| 231 | * Creates a coordinate reference system from the specified code. The default implementation | |
| 232 | * delegates to <code>{@linkplain #createProjectedCRS createProjectedCRS}(code)</code>. | |
| 233 | * | |
| 234 | * @throws FactoryException if the object creation failed. | |
| 235 | */ | |
| 236 | @Override | |
| 237 | public CoordinateReferenceSystem createCoordinateReferenceSystem(final String code) | |
| 238 | throws FactoryException | |
| 239 | { | |
| 240 | 23 | return createProjectedCRS(code); |
| 241 | } | |
| 242 | ||
| 243 | /** | |
| 244 | * Creates a projected coordinate reference system from the specified code. | |
| 245 | * | |
| 246 | * @throws FactoryException if the object creation failed. | |
| 247 | */ | |
| 248 | @Override | |
| 249 | public ProjectedCRS createProjectedCRS(final String code) throws FactoryException { | |
| 250 | 47 | final Code c = new Code(code, ProjectedCRS.class, true); |
| 251 | 23 | return findFactlet(c).create(c, factories); |
| 252 | } | |
| 253 | } |