/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2001-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.referencing; import java.util.Locale; import java.util.Set; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.io.PrintWriter; import java.io.IOException; import java.text.NumberFormat; import org.opengis.util.InternationalString; import org.opengis.metadata.Identifier; import org.opengis.metadata.citation.Citation; import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.AuthorityFactory; import org.opengis.referencing.FactoryException; import org.opengis.referencing.NoSuchAuthorityCodeException; import org.opengis.referencing.crs.CRSAuthorityFactory; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.CoordinateOperation; import org.opengis.referencing.operation.CoordinateOperationFactory; import org.opengis.referencing.operation.OperationNotFoundException; import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory; import org.geotools.factory.Hints; import org.geotools.io.TableWriter; import org.geotools.referencing.wkt.Parser; import org.geotools.referencing.datum.BursaWolfParameters; import org.geotools.referencing.datum.DefaultGeodeticDatum; import org.geotools.referencing.factory.AbstractAuthorityFactory; import org.geotools.referencing.factory.FactoryDependencies; import org.geotools.resources.Arguments; import org.geotools.resources.CRSUtilities; import org.geotools.resources.i18n.Vocabulary; import org.geotools.resources.i18n.VocabularyKeys; /** * Implementation of the {@link CRS#main} method. Exists as a separated class in order * to reduce the class loading for applications that don't want to run this main method. * * @source $URL$ * @version $Id$ * @author Martin Desruisseaux (IRD) */ final class Command { /** * The hints for the factory to fetch. Null for now, but may be different in a future version. */ private static final Hints HINTS = null; /** * The authority factory. */ private final AuthorityFactory factory; /** * The object to use for formatting objects. */ private final Parser formatter; /** * Creates an instance of the specified authority. */ private Command(final String authority) { factory = (authority == null) ? CRS.getAuthorityFactory(false) : ReferencingFactoryFinder.getCRSAuthorityFactory(authority, HINTS); formatter = new Parser(); } /** * The separator to put between WKT. */ private static char[] getSeparator() { final char[] separator = new char[79]; Arrays.fill(separator, '\u2500'); return separator; } /** * Prints usage. */ private static void help(final PrintWriter out) { out.println("Display informations about CRS identified by authority codes."); out.println("Usage: java org.geotools.referencing.CRS [options] [codes]"); out.println("Options:"); out.println(" -authority=ARG : Uses the specified authority factory (default to all)."); out.println(" -bursawolfs : Lists Bursa-Wolf parameters for the specified CRS."); out.println(" -codes : Lists all available CRS codes with their description."); out.println(" -colors : Enable syntax coloring on ANSI X3.64 compatible terminal."); out.println(" -dependencies : Lists authority factory dependencies as a tree."); out.println(" -factories : Lists all availables CRS authority factories."); out.println(" -forcexy : Force \"longitude first\" axis order."); out.println(" -help : Prints this message."); out.println(" -locale=ARG : Formats texts in the specified locale."); out.println(" -operations : Prints all available coordinate operations between a pair of CRS."); out.println(" -transform : Prints the preferred math transform between a pair of CRS."); } /** * Prints all objects as WKT. This is the default behavior when no option is specified. */ private void list(final PrintWriter out, final String[] args) throws FactoryException { char[] separator = null; for (int i=0; i<args.length; i++) { if (separator == null) { separator = getSeparator(); } else { out.println(separator); } out.println(formatter.format(factory.createObject(args[i]))); final String warning = formatter.getWarning(); if (warning != null) { out.println(); out.print(Vocabulary.format(VocabularyKeys.WARNING)); out.print(": "); out.println(warning); } } } /** * Lists all authority codes. */ private void codes(final PrintWriter out) throws FactoryException { final Set<String> codes = factory.getAuthorityCodes(CoordinateReferenceSystem.class); final TableWriter table = new TableWriter(out); table.writeHorizontalSeparator(); table.write(Vocabulary.format(VocabularyKeys.CODE)); table.nextColumn(); table.write(Vocabulary.format(VocabularyKeys.DESCRIPTION)); table.writeHorizontalSeparator(); for (final String code : codes) { table.write(code); table.nextColumn(); try { final InternationalString description = factory.getDescriptionText(code); if (description != null) { table.write(description.toString()); } } catch (NoSuchAuthorityCodeException e) { table.write(e.getLocalizedMessage()); } table.nextLine(); } table.writeHorizontalSeparator(); try { table.flush(); } catch (IOException e) { // Should never happen, since we are backed by PrintWriter throw new AssertionError(e); } } /** * Lists all CRS authority factories. */ private static void factories(final PrintWriter out) { final Set<Citation> done = new HashSet<Citation>(); final TableWriter table = new TableWriter(out, TableWriter.SINGLE_VERTICAL_LINE); final TableWriter notes = new TableWriter(out, " "); int noteCount = 0; notes.setMultiLinesCells(true); table.setMultiLinesCells(true); table.writeHorizontalSeparator(); table.write(Vocabulary.format(VocabularyKeys.AUTHORITY)); table.nextColumn(); table.write(Vocabulary.format(VocabularyKeys.DESCRIPTION)); table.nextColumn(); table.write(Vocabulary.format(VocabularyKeys.NOTE)); table.writeHorizontalSeparator(); for (AuthorityFactory factory : ReferencingFactoryFinder.getCRSAuthorityFactories(HINTS)) { final Citation authority = factory.getAuthority(); final Iterator<? extends Identifier> identifiers = authority.getIdentifiers().iterator(); if (!identifiers.hasNext()) { // No identifier. Scan next authorities. continue; } if (!done.add(authority)) { // Already done. Scans next authorities. continue; } table.write(identifiers.next().getCode()); table.nextColumn(); table.write(authority.getTitle().toString().trim()); if (factory instanceof AbstractAuthorityFactory) { String description; try { description = ((AbstractAuthorityFactory) factory).getBackingStoreDescription(); } catch (FactoryException e) { description = e.getLocalizedMessage(); } if (description != null) { final String n = String.valueOf(++noteCount); table.nextColumn(); table.write('('); table.write(n); table.write(')'); notes.write('('); notes.write(n); notes.write(')'); notes.nextColumn(); notes.write(description.trim()); notes.nextLine(); } } table.nextLine(); } table.writeHorizontalSeparator(); try { table.flush(); notes.flush(); } catch (IOException e) { // Should never happen, since we are backed by PrintWriter. throw new AssertionError(e); } } /** * Prints the bursa-wolfs parameters for the specified CRS. */ private void bursaWolfs(final PrintWriter out, final String[] args) throws FactoryException { final NumberFormat nf = NumberFormat.getNumberInstance(); nf.setMinimumFractionDigits(3); nf.setMaximumFractionDigits(3); final TableWriter table = new TableWriter(out); table.writeHorizontalSeparator(); final String[] titles = { Vocabulary.format(VocabularyKeys.TARGET), "dx", "dy", "dz", "ex", "ey", "ez", "ppm" }; for (int i=0; i<titles.length; i++) { table.write(titles[i]); table.nextColumn(); table.setAlignment(TableWriter.ALIGN_CENTER); } table.writeHorizontalSeparator(); for (int i=0; i<args.length; i++) { IdentifiedObject object = factory.createObject(args[i]); if (object instanceof CoordinateReferenceSystem) { object = CRSUtilities.getDatum((CoordinateReferenceSystem) object); } if (object instanceof DefaultGeodeticDatum) { final BursaWolfParameters[] params = ((DefaultGeodeticDatum) object).getBursaWolfParameters(); for (int j=0; j<params.length; j++) { final BursaWolfParameters p = params[j]; table.setAlignment(TableWriter.ALIGN_LEFT); table.write(p.targetDatum.getName().getCode()); table.nextColumn(); table.setAlignment(TableWriter.ALIGN_RIGHT); double v; for (int k=0; k<7; k++) { switch (k) { case 0: v = p.dx; break; case 1: v = p.dy; break; case 2: v = p.dz; break; case 3: v = p.ex; break; case 4: v = p.ey; break; case 5: v = p.ez; break; case 6: v = p.ppm; break; default: throw new AssertionError(k); } table.write(nf.format(v)); table.nextColumn(); } table.nextLine(); } table.writeHorizontalSeparator(); } } try { table.flush(); } catch (IOException e) { // Should never happen, since we are backed by PrintWriter throw new AssertionError(e); } } /** * Prints the operations between every pairs of the specified authority code. */ private void operations(final PrintWriter out, final String[] args) throws FactoryException { if (!(factory instanceof CoordinateOperationAuthorityFactory)) { return; } final CoordinateOperationAuthorityFactory factory = (CoordinateOperationAuthorityFactory) this.factory; char[] separator = null; for (int i=0; i<args.length; i++) { for (int j=i+1; j<args.length; j++) { final Set<CoordinateOperation> op; op = factory.createFromCoordinateReferenceSystemCodes(args[i], args[j]); for (final CoordinateOperation operation : op) { if (separator == null) { separator = getSeparator(); } else { out.println(separator); } out.println(formatter.format(operation)); } } } } /** * Prints the math transforms between every pairs of the specified authority code. */ private void transform(final PrintWriter out, final String[] args) throws FactoryException { if (!(factory instanceof CRSAuthorityFactory)) { return; } final CRSAuthorityFactory factory = (CRSAuthorityFactory) this.factory; final CoordinateOperationFactory opFactory = ReferencingFactoryFinder.getCoordinateOperationFactory(HINTS); char[] separator = null; for (int i=0; i<args.length; i++) { final CoordinateReferenceSystem crs1 = factory.createCoordinateReferenceSystem(args[i]); for (int j=i+1; j<args.length; j++) { final CoordinateReferenceSystem crs2 = factory.createCoordinateReferenceSystem(args[j]); final CoordinateOperation op; try { op = opFactory.createOperation(crs1, crs2); } catch (OperationNotFoundException exception) { out.println(exception.getLocalizedMessage()); continue; } if (separator == null) { separator = getSeparator(); } else { out.println(separator); } out.println(formatter.format(op.getMathTransform())); } } } /** * Prints all {@linkplain AuthorityFactory authority factory} dependencies as a tree. */ private static void printAuthorityFactoryDependencies(final PrintWriter out, final boolean colors) { final FactoryDependencies printer = new FactoryDependencies(CRS.getAuthorityFactory(false)); printer.setAttributeEnabled(true); printer.setColorEnabled(colors); printer.print(out); out.flush(); } /** * Dispose the factory. */ private void dispose() throws FactoryException { if (factory instanceof AbstractAuthorityFactory) { ((AbstractAuthorityFactory) factory).dispose(); } } /** * Implementation of {@link CRS#main}. */ public static void execute(String[] args) { final Arguments arguments = new Arguments(args); final PrintWriter out = arguments.out; Locale.setDefault(arguments.locale); if (arguments.getFlag("-forcexy")) { Hints.putSystemDefault(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE); } if (arguments.getFlag("-help")) { args = arguments.getRemainingArguments(0); help(out); return; } if (arguments.getFlag("-factories")) { args = arguments.getRemainingArguments(0); factories(out); return; } if (arguments.getFlag("-dependencies")) { final boolean colors = arguments.getFlag("-colors"); args = arguments.getRemainingArguments(0); printAuthorityFactoryDependencies(out, colors); return; } final String authority = arguments.getOptionalString("-authority"); final Command command = new Command(authority); command.formatter.setColorEnabled(arguments.getFlag("-colors")); try { if (arguments.getFlag("-codes")) { args = arguments.getRemainingArguments(0); command.codes(out); } else if (arguments.getFlag("-bursawolfs")) { args = arguments.getRemainingArguments(Integer.MAX_VALUE, '-'); command.bursaWolfs(out, args); } else if (arguments.getFlag("-operations")) { args = arguments.getRemainingArguments(2, '-'); command.operations(out, args); } else if (arguments.getFlag("-transform")) { args = arguments.getRemainingArguments(2, '-'); command.transform(out, args); } else { args = arguments.getRemainingArguments(Integer.MAX_VALUE, '-'); command.list(out, args); } out.flush(); command.dispose(); } catch (FactoryException exception) { out.flush(); arguments.err.println(exception.getLocalizedMessage()); } catch (Exception exception) { out.flush(); exception.printStackTrace(arguments.err); } } }