001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2001, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.referencing;
018:
019: // J2SE dependencies
020: import java.util.Locale;
021: import java.util.Set;
022: import java.util.Arrays;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.io.PrintWriter;
026: import java.io.IOException;
027: import java.text.NumberFormat;
028:
029: // OpenGIS dependencies
030: import org.opengis.util.InternationalString;
031: import org.opengis.metadata.citation.Citation;
032: import org.opengis.referencing.IdentifiedObject;
033: import org.opengis.referencing.AuthorityFactory;
034: import org.opengis.referencing.FactoryException;
035: import org.opengis.referencing.NoSuchAuthorityCodeException;
036: import org.opengis.referencing.crs.CRSAuthorityFactory;
037: import org.opengis.referencing.crs.CoordinateReferenceSystem;
038: import org.opengis.referencing.operation.CoordinateOperation;
039: import org.opengis.referencing.operation.CoordinateOperationFactory;
040: import org.opengis.referencing.operation.OperationNotFoundException;
041: import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory;
042:
043: // Geotools dependencies
044: import org.geotools.factory.Hints;
045: import org.geotools.io.TableWriter;
046: import org.geotools.referencing.wkt.Parser;
047: import org.geotools.referencing.datum.BursaWolfParameters;
048: import org.geotools.referencing.datum.DefaultGeodeticDatum;
049: import org.geotools.referencing.factory.AbstractAuthorityFactory;
050: import org.geotools.referencing.factory.FactoryDependencies;
051: import org.geotools.resources.Arguments;
052: import org.geotools.resources.CRSUtilities;
053: import org.geotools.resources.i18n.Errors;
054: import org.geotools.resources.i18n.ErrorKeys;
055: import org.geotools.resources.i18n.Vocabulary;
056: import org.geotools.resources.i18n.VocabularyKeys;
057:
058: /**
059: * Implementation of the {@link CRS#main} method. Exists as a separated class in order
060: * to reduce the class loading for applications that don't want to run this main method.
061: *
062: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/Command.java $
063: * @version $Id: Command.java 25477 2007-05-10 13:01:00Z desruisseaux $
064: * @author Martin Desruisseaux
065: */
066: final class Command {
067: /**
068: * The hints for the factory to fetch. Null for now, but may be different in a future version.
069: */
070: private static final Hints HINTS = null;
071:
072: /**
073: * The authority factory.
074: */
075: private final AuthorityFactory factory;
076:
077: /**
078: * The object to use for formatting objects.
079: */
080: private final Parser formatter;
081:
082: /**
083: * Creates an instance of the specified authority.
084: */
085: private Command(final String authority) {
086: factory = (authority == null) ? CRS.getAuthorityFactory(false)
087: : ReferencingFactoryFinder.getCRSAuthorityFactory(
088: authority, HINTS);
089: formatter = new Parser();
090: }
091:
092: /**
093: * The separator to put between WKT.
094: */
095: private static char[] getSeparator() {
096: final char[] separator = new char[79];
097: Arrays.fill(separator, '\u2500');
098: return separator;
099: }
100:
101: /**
102: * Prints usage.
103: */
104: private static void help(final PrintWriter out) {
105: out
106: .println("Display informations about CRS identified by authority codes.");
107: out
108: .println("Usage: java org.geotools.referencing.CRS [options] [codes]");
109: out.println("Options:");
110: out
111: .println(" -authority=ARG : Uses the specified authority factory (default to all).");
112: out
113: .println(" -bursawolfs : Lists Bursa-Wolf parameters for the specified CRS.");
114: out
115: .println(" -codes : Lists all available CRS codes with their description.");
116: out
117: .println(" -colors : Enable syntax coloring on ANSI X3.64 compatible terminal.");
118: out
119: .println(" -dependencies : Lists authority factory dependencies as a tree.");
120: out
121: .println(" -factories : Lists all availables CRS authority factories.");
122: out
123: .println(" -forcexy : Force \"longitude first\" axis order.");
124: out.println(" -help : Prints this message.");
125: out
126: .println(" -locale=ARG : Formats texts in the specified locale.");
127: out
128: .println(" -operations : Prints all available coordinate operations between a pair of CRS.");
129: out
130: .println(" -transform : Prints the preferred math transform between a pair of CRS.");
131: }
132:
133: /**
134: * Prints all objects as WKT. This is the default behavior when no option is specified.
135: */
136: private void list(final PrintWriter out, final String[] args)
137: throws FactoryException {
138: char[] separator = null;
139: for (int i = 0; i < args.length; i++) {
140: if (separator == null) {
141: separator = getSeparator();
142: } else {
143: out.println(separator);
144: }
145: out
146: .println(formatter.format(factory
147: .createObject(args[i])));
148: final String warning = formatter.getWarning();
149: if (warning != null) {
150: out.println();
151: out.print(Vocabulary.format(VocabularyKeys.WARNING));
152: out.print(": ");
153: out.println(warning);
154: }
155: }
156: }
157:
158: /**
159: * Lists all authority codes.
160: */
161: private void codes(final PrintWriter out) throws FactoryException {
162: final Set codes = factory
163: .getAuthorityCodes(CoordinateReferenceSystem.class);
164: final TableWriter table = new TableWriter(out);
165: table.writeHorizontalSeparator();
166: table.write(Vocabulary.format(VocabularyKeys.CODE));
167: table.nextColumn();
168: table.write(Vocabulary.format(VocabularyKeys.DESCRIPTION));
169: table.writeHorizontalSeparator();
170: for (final Iterator it = codes.iterator(); it.hasNext();) {
171: final String code = (String) it.next();
172: table.write(code);
173: table.nextColumn();
174: try {
175: final InternationalString description = factory
176: .getDescriptionText(code);
177: if (description != null) {
178: table.write(description.toString());
179: }
180: } catch (NoSuchAuthorityCodeException e) {
181: table.write(e.getLocalizedMessage());
182: }
183: table.nextLine();
184: }
185: table.writeHorizontalSeparator();
186: try {
187: table.flush();
188: } catch (IOException e) {
189: // Should never happen, since we are backed by PrintWriter
190: throw new AssertionError(e);
191: }
192: }
193:
194: /**
195: * Lists all CRS authority factories.
196: */
197: private static void factories(final PrintWriter out) {
198: final Set/*<Citation>*/done = new HashSet();
199: final TableWriter table = new TableWriter(out, " \u2502 ");
200: final TableWriter notes = new TableWriter(out, " ");
201: int noteCount = 0;
202: notes.setMultiLinesCells(true);
203: table.setMultiLinesCells(true);
204: table.writeHorizontalSeparator();
205: table.write(Vocabulary.format(VocabularyKeys.AUTHORITY));
206: table.nextColumn();
207: table.write(Vocabulary.format(VocabularyKeys.DESCRIPTION));
208: table.nextColumn();
209: table.write(Vocabulary.format(VocabularyKeys.NOTE));
210: table.writeHorizontalSeparator();
211: for (final Iterator it = ReferencingFactoryFinder
212: .getCRSAuthorityFactories(HINTS).iterator(); it
213: .hasNext();) {
214: AuthorityFactory factory = (AuthorityFactory) it.next();
215: final Citation authority = factory.getAuthority();
216: final Iterator identifiers = authority.getIdentifiers()
217: .iterator();
218: if (!identifiers.hasNext()) {
219: // No identifier. Scan next authorities.
220: continue;
221: }
222: if (!done.add(authority)) {
223: // Already done. Scans next authorities.
224: continue;
225: }
226: table.write((String) identifiers.next());
227: table.nextColumn();
228: table.write(authority.getTitle().toString().trim());
229: if (factory instanceof AbstractAuthorityFactory) {
230: String description;
231: try {
232: description = ((AbstractAuthorityFactory) factory)
233: .getBackingStoreDescription();
234: } catch (FactoryException e) {
235: description = e.getLocalizedMessage();
236: }
237: if (description != null) {
238: final String n = String.valueOf(++noteCount);
239: table.nextColumn();
240: table.write('(');
241: table.write(n);
242: table.write(')');
243: notes.write('(');
244: notes.write(n);
245: notes.write(')');
246: notes.nextColumn();
247: notes.write(description.trim());
248: notes.nextLine();
249: }
250: }
251: table.nextLine();
252: }
253: table.writeHorizontalSeparator();
254: try {
255: table.flush();
256: notes.flush();
257: } catch (IOException e) {
258: // Should never happen, since we are backed by PrintWriter.
259: throw new AssertionError(e);
260: }
261: }
262:
263: /**
264: * Prints the bursa-wolfs parameters for the specified CRS.
265: */
266: private void bursaWolfs(final PrintWriter out, final String[] args)
267: throws FactoryException {
268: final NumberFormat nf = NumberFormat.getNumberInstance();
269: nf.setMinimumFractionDigits(3);
270: nf.setMaximumFractionDigits(3);
271: final TableWriter table = new TableWriter(out);
272: table.writeHorizontalSeparator();
273: final String[] titles = {
274: Vocabulary.format(VocabularyKeys.TARGET), "dx", "dy",
275: "dz", "ex", "ey", "ez", "ppm" };
276: for (int i = 0; i < titles.length; i++) {
277: table.write(titles[i]);
278: table.nextColumn();
279: table.setAlignment(TableWriter.ALIGN_CENTER);
280: }
281: table.writeHorizontalSeparator();
282: for (int i = 0; i < args.length; i++) {
283: IdentifiedObject object = factory.createObject(args[i]);
284: if (object instanceof CoordinateReferenceSystem) {
285: object = CRSUtilities
286: .getDatum((CoordinateReferenceSystem) object);
287: }
288: if (object instanceof DefaultGeodeticDatum) {
289: final BursaWolfParameters[] params = ((DefaultGeodeticDatum) object)
290: .getBursaWolfParameters();
291: for (int j = 0; j < params.length; j++) {
292: final BursaWolfParameters p = params[j];
293: table.setAlignment(TableWriter.ALIGN_LEFT);
294: table.write(p.targetDatum.getName().getCode());
295: table.nextColumn();
296: table.setAlignment(TableWriter.ALIGN_RIGHT);
297: double v;
298: for (int k = 0; k < 7; k++) {
299: switch (k) {
300: case 0:
301: v = p.dx;
302: break;
303: case 1:
304: v = p.dy;
305: break;
306: case 2:
307: v = p.dz;
308: break;
309: case 3:
310: v = p.ex;
311: break;
312: case 4:
313: v = p.ey;
314: break;
315: case 5:
316: v = p.ez;
317: break;
318: case 6:
319: v = p.ppm;
320: break;
321: default:
322: throw new AssertionError(k);
323: }
324: table.write(nf.format(v));
325: table.nextColumn();
326: }
327: table.nextLine();
328: }
329: table.writeHorizontalSeparator();
330: }
331: }
332: try {
333: table.flush();
334: } catch (IOException e) {
335: // Should never happen, since we are backed by PrintWriter
336: throw new AssertionError(e);
337: }
338: }
339:
340: /**
341: * Prints the operations between every pairs of the specified authority code.
342: */
343: private void operations(final PrintWriter out, final String[] args)
344: throws FactoryException {
345: if (!(factory instanceof CoordinateOperationAuthorityFactory)) {
346: return;
347: }
348: final CoordinateOperationAuthorityFactory factory = (CoordinateOperationAuthorityFactory) this .factory;
349: char[] separator = null;
350: for (int i = 0; i < args.length; i++) {
351: for (int j = i + 1; j < args.length; j++) {
352: final Set/*<CoordinateOperation>*/op;
353: op = factory.createFromCoordinateReferenceSystemCodes(
354: args[i], args[j]);
355: for (final Iterator it = op.iterator(); it.hasNext();) {
356: final CoordinateOperation operation = (CoordinateOperation) it
357: .next();
358: if (separator == null) {
359: separator = getSeparator();
360: } else {
361: out.println(separator);
362: }
363: out.println(formatter.format(operation));
364: }
365: }
366: }
367: }
368:
369: /**
370: * Prints the math transforms between every pairs of the specified authority code.
371: */
372: private void transform(final PrintWriter out, final String[] args)
373: throws FactoryException {
374: if (!(factory instanceof CRSAuthorityFactory)) {
375: return;
376: }
377: final CRSAuthorityFactory factory = (CRSAuthorityFactory) this .factory;
378: final CoordinateOperationFactory opFactory = ReferencingFactoryFinder
379: .getCoordinateOperationFactory(HINTS);
380: char[] separator = null;
381: for (int i = 0; i < args.length; i++) {
382: final CoordinateReferenceSystem crs1 = factory
383: .createCoordinateReferenceSystem(args[i]);
384: for (int j = i + 1; j < args.length; j++) {
385: final CoordinateReferenceSystem crs2 = factory
386: .createCoordinateReferenceSystem(args[j]);
387: final CoordinateOperation op;
388: try {
389: op = opFactory.createOperation(crs1, crs2);
390: } catch (OperationNotFoundException exception) {
391: out.println(exception.getLocalizedMessage());
392: continue;
393: }
394: if (separator == null) {
395: separator = getSeparator();
396: } else {
397: out.println(separator);
398: }
399: out.println(formatter.format(op.getMathTransform()));
400: }
401: }
402: }
403:
404: /**
405: * Prints all {@linkplain AuthorityFactory authority factory} dependencies as a tree.
406: */
407: private static void printAuthorityFactoryDependencies(
408: final PrintWriter out, final boolean colors) {
409: final FactoryDependencies printer = new FactoryDependencies(CRS
410: .getAuthorityFactory(false));
411: printer.setAttributeEnabled(true);
412: printer.setColorEnabled(colors);
413: printer.print(out);
414: out.flush();
415: }
416:
417: /**
418: * Dispose the factory.
419: */
420: private void dispose() throws FactoryException {
421: if (factory instanceof AbstractAuthorityFactory) {
422: ((AbstractAuthorityFactory) factory).dispose();
423: }
424: }
425:
426: /**
427: * Implementation of {@link CRS#main}.
428: */
429: public static void execute(String[] args) {
430: final Arguments arguments = new Arguments(args);
431: final PrintWriter out = arguments.out;
432: Locale.setDefault(arguments.locale);
433: if (arguments.getFlag("-forcexy")) {
434: Hints.putSystemDefault(
435: Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER,
436: Boolean.TRUE);
437: }
438: if (arguments.getFlag("-help")) {
439: args = arguments.getRemainingArguments(0);
440: help(out);
441: return;
442: }
443: if (arguments.getFlag("-factories")) {
444: args = arguments.getRemainingArguments(0);
445: factories(out);
446: return;
447: }
448: if (arguments.getFlag("-dependencies")) {
449: final boolean colors = arguments.getFlag("-colors");
450: args = arguments.getRemainingArguments(0);
451: printAuthorityFactoryDependencies(out, colors);
452: return;
453: }
454: final String authority = arguments
455: .getOptionalString("-authority");
456: final Command command = new Command(authority);
457: command.formatter.setColorEnabled(arguments.getFlag("-colors"));
458: try {
459: if (arguments.getFlag("-codes")) {
460: args = arguments.getRemainingArguments(0);
461: command.codes(out);
462: } else if (arguments.getFlag("-bursawolfs")) {
463: args = arguments.getRemainingArguments(
464: Integer.MAX_VALUE, '-');
465: command.bursaWolfs(out, args);
466: } else if (arguments.getFlag("-operations")) {
467: args = arguments.getRemainingArguments(2, '-');
468: command.operations(out, args);
469: } else if (arguments.getFlag("-transform")) {
470: args = arguments.getRemainingArguments(2, '-');
471: command.transform(out, args);
472: } else {
473: args = arguments.getRemainingArguments(
474: Integer.MAX_VALUE, '-');
475: command.list(out, args);
476: }
477: out.flush();
478: command.dispose();
479: } catch (FactoryException exception) {
480: out.flush();
481: arguments.err.println(exception.getLocalizedMessage());
482: } catch (Exception exception) {
483: out.flush();
484: exception.printStackTrace(arguments.err);
485: }
486: }
487: }
|