Author: desruisseaux
Date: Sun Apr 24 15:50:56 2016
New Revision: 1740703

URL: http://svn.apache.org/viewvc?rev=1740703&view=rev
Log:
Split the implementation of "metadata", "crs" and "identifier" sub-commands 
into 3 separated classes.
Begin implementation of "transform" sub-command.

Added:
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CRSCommand.java
      - copied, changed from r1740562, 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/IdentifierCommand.java
      - copied, changed from r1740562, 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
   (with props)
Removed:
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/IdentifierRow.java
Modified:
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CommandRunner.java
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/HelpCommand.java
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/InvalidOptionException.java
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
    
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Option.java
    
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands.properties
    
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands_fr.properties
    
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options.properties
    
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options_fr.properties
    
sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java

Copied: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CRSCommand.java
 (from r1740562, 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java)
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CRSCommand.java?p2=sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CRSCommand.java&p1=sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java&r1=1740562&r2=1740703&rev=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CRSCommand.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -16,43 +16,18 @@
  */
 package org.apache.sis.console;
 
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Set;
-import java.io.Console;
 import java.io.IOException;
-import javax.xml.bind.Marshaller;
 import javax.xml.bind.JAXBException;
 import org.opengis.metadata.Metadata;
-import org.opengis.metadata.Identifier;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.apache.sis.io.wkt.WKTFormat;
-import org.apache.sis.io.wkt.Convention;
-import org.apache.sis.io.wkt.Colors;
-import org.apache.sis.metadata.MetadataStandard;
-import org.apache.sis.metadata.ValueExistencePolicy;
-import org.apache.sis.metadata.iso.DefaultMetadata;
-import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.referencing.CRS;
-import org.apache.sis.storage.DataStore;
-import org.apache.sis.storage.DataStores;
 import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.util.collection.TableColumn;
-import org.apache.sis.util.collection.TreeTable;
-import org.apache.sis.util.collection.TreeTableFormat;
-import org.apache.sis.util.resources.Errors;
-import org.apache.sis.xml.MarshallerPool;
-import org.apache.sis.xml.XML;
+import org.apache.sis.io.wkt.Convention;
 
 
 /**
- * The "metadata", "crs" and "identifier" subcommands.
+ * The "crs" sub-command.
  * CRS are considered as a kind of metadata here.
  *
  * @author  Martin Desruisseaux (Geomatys)
@@ -60,139 +35,16 @@ import org.apache.sis.xml.XML;
  * @version 0.7
  * @module
  */
-final class MetadataCommand extends CommandRunner {
-    /**
-     * The protocol part of the filename to be recognized as a CRS authority.
-     * In such case, this class will delegate to {@link CRS#forCode(String)}
-     * instead of opening the file.
-     */
-    static final Set<String> AUTHORITIES = new HashSet<>(Arrays.asList("URN", 
"EPSG", "CRS", "AUTO", "AUTO2"));
-
-    /**
-     * Length of the longest authority name declared in {@link #AUTHORITIES}.
-     */
-    static final int MAX_AUTHORITY_LENGTH = 5;
-
-    /**
-     * The desired information.
-     */
-    static enum Info {
-        METADATA, CRS, IDENTIFIER
-    }
-
-    /**
-     * The output format.
-     */
-    private static enum Format {
-        TEXT, WKT, XML
-    }
-
-    /**
-     * The sub-command: {@code "metadata"}, {@code "crs"} or {@code 
"identifier"}.
-     */
-    private final Info command;
-
-    /**
-     * The output format.
-     */
-    private Format outputFormat;
-
-    /**
-     * The WKT convention, or {@code null} if it does not apply.
-     */
-    private Convention convention;
-
+final class CRSCommand extends MetadataCommand {
     /**
      * Creates the {@code "metadata"}, {@code "crs"} or {@code "identifier"} 
sub-command.
      */
-    MetadataCommand(final Info command, final int commandIndex, final 
String... args) throws InvalidOptionException {
-        super(commandIndex, args, EnumSet.of(Option.FORMAT, Option.LOCALE, 
Option.TIMEZONE, Option.ENCODING,
-                Option.COLORS, Option.HELP, Option.DEBUG));
-        this.command = command;
-    }
-
-    /**
-     * Parses the command-line arguments and initializes the {@link 
#outputFormat} and {@link #convention} fields
-     * accordingly. This method verifies the parameter validity.
-     */
-    private void parseArguments() throws InvalidOptionException {
-        /*
-         * Output format can be either "text" (the default) or "xml".
-         * In the case of "crs" sub-command, we accept also WKT variants.
-         */
-        final String format = options.get(Option.FORMAT);
-        if (format == null || format.equalsIgnoreCase("text")) {
-            if (command == Info.CRS) {
-                outputFormat = Format.WKT;
-                convention = Convention.WKT2_SIMPLIFIED;
-            } else {
-                outputFormat = Format.TEXT;
-            }
-        } else if (format.equalsIgnoreCase("wkt") || 
format.equalsIgnoreCase("wkt2")) {
-            outputFormat = Format.WKT;
-            convention = Convention.WKT2;
-        } else if (format.equalsIgnoreCase("wkt1")) {
-            outputFormat = Format.WKT;
-            convention = Convention.WKT1;
-        } else if (format.equalsIgnoreCase("xml")) {
-            outputFormat = Format.XML;
-        } else {
-            throw new InvalidOptionException(Errors.format(
-                    Errors.Keys.IllegalOptionValue_2, "format", format), 
format);
-        }
-        final boolean isFormatCompatible;
-        switch (command) {
-            case CRS: {
-                isFormatCompatible = true;
-                break;
-            }
-            case IDENTIFIER: {
-                isFormatCompatible = (outputFormat == Format.TEXT);
-                break;
-            }
-            default: {
-                isFormatCompatible = (convention == null);
-                break;
-            }
-        }
-        if (!isFormatCompatible) {
-            throw new 
InvalidOptionException(Errors.format(Errors.Keys.IncompatibleFormat_2,
-                    command.name().toLowerCase(locale), format), format);
-        }
-    }
+    CRSCommand(final int commandIndex, final String... args) throws 
InvalidOptionException {
+        super(commandIndex, args);
 
-    /**
-     * If the given argument begins with one of the known authorities ("URN", 
"EPSG", "CRS", "AUTO", <i>etc.</i>),
-     * delegates to {@link CRS#forCode(String)} and wraps in a metadata 
object. Otherwise returns {@code null}.
-     */
-    private static Metadata fromDatabase(final String code) throws 
FactoryException {
-        final char[] authority = new char[MAX_AUTHORITY_LENGTH];
-        final int length = code.length();
-        int p = 0, i = 0;
-        while (i < length) {
-            final int c = code.codePointAt(i);
-            if (c == ':') {
-                if (!AUTHORITIES.contains(new String(authority, 0, p))) {
-                    break;
-                }
-                final DefaultMetadata metadata = new DefaultMetadata();
-                
metadata.setReferenceSystemInfo(Collections.singleton(CRS.forCode(code)));
-                return metadata;
-            }
-            if (!Character.isWhitespace(c)) {
-                if (p >= MAX_AUTHORITY_LENGTH || 
!Character.isLetterOrDigit(c)) {
-                    break;
-                }
-                /*
-                 * Casting to char is okay because AUTHORITIES contains only 
ASCII values.
-                 * If 'c' was a supplemental Unicode value, then the result of 
the cast
-                 * will not match any AUTHORITIES value anyway.
-                 */
-                authority[p++] = (char) Character.toUpperCase(c);
-            }
-            i += Character.charCount(c);
-        }
-        return null;
+        // Default output format.
+        outputFormat = Format.WKT;
+        convention = Convention.WKT2_SIMPLIFIED;
     }
 
     /**
@@ -204,118 +56,24 @@ final class MetadataCommand extends Comm
      * @throws IOException should never happen, since we are appending to a 
print writer.
      */
     @Override
-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
     public int run() throws InvalidOptionException, DataStoreException, 
JAXBException, FactoryException, IOException {
         parseArguments();
-        /*
-         * Read metadata from the data storage only after we verified that the 
arguments are valid.
-         * The input can be a file given on the command line, or the standard 
input stream.
-         */
-        Metadata metadata;
-        if (useStandardInput()) {
-            try (DataStore store = DataStores.open(System.in)) {
-                metadata = store.getMetadata();
-            }
-        } else {
-            if (hasUnexpectedFileCount(1, 1)) {
-                return Command.INVALID_ARGUMENT_EXIT_CODE;
-            }
-            final String file = files.get(0);
-            metadata = fromDatabase(file);
-            if (metadata == null) {
-                try (DataStore store = DataStores.open(file)) {
-                    metadata = store.getMetadata();
-                }
-            }
-        }
-        if (metadata == null) {
-            return 0;
-        }
-        /*
-         * If we are executing the "identifier" sub-command, then show the 
metadata identifier (if any)
-         * and the identifier of all referencing systems found. Otherwise if 
we are executing the "crs"
-         * sub-command, extract only the first CRS. That CRS will be displayed 
after the switch statement.
-         */
-        Object object = metadata;
-choice: switch (command) {
-            case IDENTIFIER: {
-                final List<IdentifierRow> rows = new ArrayList<>();
-                final Identifier id = metadata.getMetadataIdentifier();
-                if (id != null) {
-                    CharSequence desc = id.getDescription();
-                    if (desc != null && !files.isEmpty()) desc = files.get(0);
-                    rows.add(new IdentifierRow(IdentifierRow.State.VALID, 
IdentifiedObjects.toString(id), desc));
-                }
-                for (final ReferenceSystem rs : 
metadata.getReferenceSystemInfo()) {
-                    rows.add(IdentifierRow.create(rs));
-                }
-                IdentifierRow.print(rows, out, locale, colors);
-                return 0;
-            }
-            case CRS: {
-                for (final ReferenceSystem rs : 
metadata.getReferenceSystemInfo()) {
+        final Object metadata = readMetadataOrCRS();
+        if (hasUnexpectedFileCount) {
+            return Command.INVALID_ARGUMENT_EXIT_CODE;
+        }
+        if (metadata != null) {
+            if (metadata instanceof CoordinateReferenceSystem) {
+                format(metadata);
+            } else {
+                for (final ReferenceSystem rs : ((Metadata) 
metadata).getReferenceSystemInfo()) {
                     if (rs instanceof CoordinateReferenceSystem) {
-                        object = rs;
-                        break choice;
+                        format(rs);
+                        break;
                     }
                 }
-                return 0;
             }
         }
-        /*
-         * Format metadata to the standard output stream.
-         */
-        switch (outputFormat) {
-            case TEXT: {
-                final TreeTable tree = 
MetadataStandard.ISO_19115.asTreeTable(object, ValueExistencePolicy.NON_EMPTY);
-                final TreeTableFormat tf = new TreeTableFormat(locale, 
timezone);
-                tf.setColumns(TableColumn.NAME, TableColumn.VALUE);
-                tf.format(tree, out);
-                break;
-            }
-
-            case WKT: {
-                final WKTFormat f = new WKTFormat(locale, timezone);
-                if (convention != null) {
-                    f.setConvention(convention);
-                }
-                if (colors) {
-                    f.setColors(Colors.DEFAULT);
-                }
-                f.format(object, out);
-                out.println();
-                break;
-            }
-
-            case XML: {
-                final MarshallerPool pool = new MarshallerPool(null);
-                final Marshaller marshaller = pool.acquireMarshaller();
-                marshaller.setProperty(XML.LOCALE,   locale);
-                marshaller.setProperty(XML.TIMEZONE, timezone);
-                if (isConsole()) {
-                    marshaller.marshal(object, out);
-                } else {
-                    out.flush();
-                    marshaller.setProperty(Marshaller.JAXB_ENCODING, 
encoding.name());
-                    marshaller.marshal(object, System.out);     // 
Intentionally use OutputStream instead than Writer.
-                    System.out.flush();
-                }
-                break;
-            }
-        }
-        out.flush();
         return 0;
     }
-
-    /**
-     * Returns {@code true} if {@link #out} is sending its output to the 
console.
-     * If not, then we are probably writing to a file or the user specified 
his own encoding.
-     * In such case, we will send the XML output to an {@code OutputStream} 
instead than to a
-     * {@code Writer} and let the marshaller apply the encoding itself.
-     */
-    private boolean isConsole() {
-        if (outputBuffer != null) return true;                      // Special 
case for JUnit tests only.
-        final Console console = System.console();
-        return (console != null) && console.writer() == out;
-    }
 }

Modified: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -41,20 +41,23 @@ import org.apache.sis.util.logging.Monol
  * <tr><td>{@code metadata}   </td><td>Show metadata information for the given 
file.</td></tr>
  * <tr><td>{@code crs}        </td><td>Show Coordinate Reference System 
information for the given file or code.</td></tr>
  * <tr><td>{@code identifier} </td><td>Show identifiers for metadata and 
referencing systems in the given file.</td></tr>
+ * <tr><td>{@code transform}  </td><td>Convert or transform coordinates from 
given source CRS to target CRS.</td></tr>
  * </table></blockquote>
  *
- * Each command can accepts an arbitrary amount of the following options:
+ * Each command can accepts some of the following options:
  *
  * <blockquote><table class="compact" summary="Supported command-line 
options.">
- * <tr><td>{@code --format}   </td><td>The output format: {@code xml}, {@code 
wkt}, {@code wkt1} or {@code text}.</td></tr>
- * <tr><td>{@code --locale}   </td><td>The locale to use for the command 
output.</td></tr>
- * <tr><td>{@code --timezone} </td><td>The timezone for the dates to be 
formatted.</td></tr>
- * <tr><td>{@code --encoding} </td><td>The encoding to use for the command 
output.</td></tr>
- * <tr><td>{@code --colors}   </td><td>Whether colorized output shall be 
enabled.</td></tr>
- * <tr><td>{@code --brief}    </td><td>Whether the output should contains only 
brief information.</td></tr>
- * <tr><td>{@code --verbose}  </td><td>Whether the output should contains more 
detailed information.</td></tr>
- * <tr><td>{@code --debug}    </td><td>Prints full stack trace in case of 
failure.</td></tr>
- * <tr><td>{@code --help}     </td><td>Lists the options available for a 
specific command.</td></tr>
+ * <tr><td>{@code --sourceCRS} </td><td>The Coordinate Reference System of 
input data.</td></tr>
+ * <tr><td>{@code --targetCRS} </td><td>The Coordinate Reference System of 
output data.</td></tr>
+ * <tr><td>{@code --format}    </td><td>The output format: {@code xml}, {@code 
wkt}, {@code wkt1} or {@code text}.</td></tr>
+ * <tr><td>{@code --locale}    </td><td>The locale to use for the command 
output.</td></tr>
+ * <tr><td>{@code --timezone}  </td><td>The timezone for the dates to be 
formatted.</td></tr>
+ * <tr><td>{@code --encoding}  </td><td>The encoding to use for the command 
output.</td></tr>
+ * <tr><td>{@code --colors}    </td><td>Whether colorized output shall be 
enabled.</td></tr>
+ * <tr><td>{@code --brief}     </td><td>Whether the output should contains 
only brief information.</td></tr>
+ * <tr><td>{@code --verbose}   </td><td>Whether the output should contains 
more detailed information.</td></tr>
+ * <tr><td>{@code --debug}     </td><td>Prints full stack trace in case of 
failure.</td></tr>
+ * <tr><td>{@code --help}      </td><td>Lists the options available for a 
specific command.</td></tr>
  * </table></blockquote>
  *
  * The {@code --locale}, {@code --timezone} and {@code --encoding} options 
apply to the command output sent
@@ -136,14 +139,9 @@ public final class Command {
             final String arg = args[i];
             if (arg.startsWith(Option.PREFIX)) {
                 final String name = arg.substring(Option.PREFIX.length());
-                final Option option;
-                try {
-                    option = Option.valueOf(name.toUpperCase(Locale.US));
-                } catch (IllegalArgumentException e) {
-                    throw new 
InvalidOptionException(Errors.format(Errors.Keys.UnknownOption_1, name), e, 
name);
-                }
+                final Option option = Option.forLabel(name);
                 if (option.hasValue) {
-                    i++; // Skip the next argument.
+                    i++;                        // Skip the next argument.
                 }
             } else {
                 // Takes the first non-argument option as the command name.
@@ -157,12 +155,13 @@ public final class Command {
         } else {
             commandName = commandName.toLowerCase(Locale.US);
             switch (commandName) {
-                case "help":       command = new HelpCommand    (commandIndex, 
args); break;
-                case "about":      command = new AboutCommand   (commandIndex, 
args); break;
-                case "mime-type":  command = new MimeTypeCommand(commandIndex, 
args); break;
-                case "identifier": command = new 
MetadataCommand(MetadataCommand.Info.IDENTIFIER, commandIndex, args); break;
-                case "metadata":   command = new 
MetadataCommand(MetadataCommand.Info.METADATA,   commandIndex, args); break;
-                case "crs":        command = new 
MetadataCommand(MetadataCommand.Info.CRS,        commandIndex, args); break;
+                case "help":       command = new HelpCommand      
(commandIndex, args); break;
+                case "about":      command = new AboutCommand     
(commandIndex, args); break;
+                case "mime-type":  command = new MimeTypeCommand  
(commandIndex, args); break;
+                case "metadata":   command = new MetadataCommand  
(commandIndex, args); break;
+                case "crs":        command = new CRSCommand       
(commandIndex, args); break;
+                case "identifier": command = new 
IdentifierCommand(commandIndex, args); break;
+                case "transform":  command = new TransformCommand 
(commandIndex, args); break;
                 default: throw new InvalidCommandException(Errors.format(
                             Errors.Keys.UnknownCommand_1, commandName), 
commandName);
             }

Modified: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CommandRunner.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CommandRunner.java?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CommandRunner.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/CommandRunner.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -149,10 +149,10 @@ abstract class CommandRunner {
      * The argument at index {@code commandIndex} is the name of this command, 
and will be ignored except for
      * the special {@value #TEST} value which is used only at JUnit testing 
time.
      *
-     * @param  commandIndex Index of the {@code args} element containing the 
sub-command name.
-     * @param  arguments    The command-line arguments provided by the user.
-     * @param  validOptions The command-line options allowed by this 
sub-command.
-     * @throws InvalidOptionException If an illegal option has been provided, 
or the option has an illegal value.
+     * @param  commandIndex  index of the {@code args} element containing the 
sub-command name.
+     * @param  arguments     the command-line arguments provided by the user.
+     * @param  validOptions  the command-line options allowed by this 
sub-command.
+     * @throws InvalidOptionException if an illegal option has been provided, 
or the option has an illegal value.
      */
     @SuppressWarnings("UseOfSystemOutOrSystemErr")
     protected CommandRunner(final int commandIndex, final String[] arguments, 
final EnumSet<Option> validOptions)
@@ -170,12 +170,7 @@ abstract class CommandRunner {
             }
             if (arg.startsWith(Option.PREFIX)) {
                 final String name = arg.substring(Option.PREFIX.length());
-                final Option option;
-                try {
-                    option = Option.valueOf(name.toUpperCase(Locale.US));
-                } catch (IllegalArgumentException e) {
-                    throw new 
InvalidOptionException(Errors.format(Errors.Keys.UnknownOption_1, name), e, 
name);
-                }
+                final Option option = Option.forLabel(name);
                 if (!validOptions.contains(option)) {
                     throw new 
InvalidOptionException(Errors.format(Errors.Keys.UnknownOption_1, name), name);
                 }
@@ -197,7 +192,7 @@ abstract class CommandRunner {
         /*
          * Process the --locale, --encoding and --colors options.
          */
-        Option option = null; // In case of IllegalArgumentException.
+        Option option = null;                                           // In 
case of IllegalArgumentException.
         String value  = null;
         final Console console;
         final boolean explicitEncoding;
@@ -219,7 +214,7 @@ abstract class CommandRunner {
             colors = (value != null) ? Option.COLORS.parseBoolean(value) : 
(console != null) && X364.isAnsiSupported();
         } catch (RuntimeException e) {
             @SuppressWarnings("null")                                   // 
'option' has been assigned in 'get' argument.
-            final String name = option.name().toLowerCase(Locale.US);
+            final String name = option.label();
             throw new 
InvalidOptionException(Errors.format(Errors.Keys.IllegalOptionValue_2, name, 
value), name);
         }
         /*
@@ -254,7 +249,7 @@ abstract class CommandRunner {
      *
      * <p>An example of a pair of mutually exclusive options is {@code 
--brief} and {@code --verbose}.</p>
      *
-     * @param  exclusive Pairs of mutually exclusive options.
+     * @param  exclusive  pairs of mutually exclusive options.
      * @return {@code true} if two mutually exclusive options exist.
      */
     final boolean hasContradictoryOptions(final Option... exclusive) {
@@ -262,9 +257,7 @@ abstract class CommandRunner {
             final Option o1 = exclusive[i++];
             final Option o2 = exclusive[i++];
             if (options.containsKey(o1) && options.containsKey(o2)) {
-                
err.println(Errors.format(Errors.Keys.MutuallyExclusiveOptions_2,
-                        o1.name().toLowerCase(Locale.US),
-                        o2.name().toLowerCase(Locale.US)));
+                
err.println(Errors.format(Errors.Keys.MutuallyExclusiveOptions_2, o1.label(), 
o2.label()));
                 return true;
             }
         }
@@ -275,8 +268,8 @@ abstract class CommandRunner {
      * Checks the size of the {@link #files} list. If the list has an 
unexpected size,
      * then this method prints an error message to {@link #err} and returns 
{@code true}.
      *
-     * @param  min Minimal number of files.
-     * @param  max Maximum number of files.
+     * @param  min  minimal number of files.
+     * @param  max  maximum number of files.
      * @return {@code true} if the list size is not in the expected bounds.
      */
     final boolean hasUnexpectedFileCount(final int min, final int max) {
@@ -306,8 +299,8 @@ abstract class CommandRunner {
     /**
      * Prints the <cite>"Can not open …"</cite> error message followed by the 
message in the given exception.
      *
-     * @param fileIndex Index in the {@link #files} list of the file that can 
not be opened.
-     * @param e The exception which occurred.
+     * @param fileIndex  index in the {@link #files} list of the file that can 
not be opened.
+     * @param e          the exception which occurred.
      */
     final void canNotOpen(final int fileIndex, final Exception e) {
         error(Errors.format(Errors.Keys.CanNotOpen_1, files.get(fileIndex)), 
e);
@@ -316,8 +309,8 @@ abstract class CommandRunner {
     /**
      * Prints the given error message followed by the message in the given 
exception.
      *
-     * @param message The message to print before the exception, or {@code 
null}.
-     * @param e The exception which occurred.
+     * @param message  the message to print before the exception, or {@code 
null}.
+     * @param e        the exception which occurred.
      */
     final void error(final String message, final Exception e) {
         out.flush();
@@ -332,7 +325,7 @@ abstract class CommandRunner {
      * Shows the help instructions for a specific command. This method is 
invoked
      * instead of {@link #run()} if the the user provided the {@code --help} 
option.
      *
-     * @param commandName The command name converted to lower cases.
+     * @param commandName  the command name converted to lower cases.
      */
     protected void help(final String commandName) {
         new HelpCommand(this).help(false, new String[] {commandName}, 
validOptions);
@@ -342,7 +335,7 @@ abstract class CommandRunner {
      * Executes the sub-command.
      *
      * @return 0 on success, or an exit code if the command failed for a 
reason other than a Java exception.
-     * @throws Exception If an error occurred while executing the sub-command.
+     * @throws Exception if an error occurred while executing the sub-command.
      */
     public abstract int run() throws Exception;
 }

Modified: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/HelpCommand.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/HelpCommand.java?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/HelpCommand.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/HelpCommand.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -17,7 +17,6 @@
 package org.apache.sis.console;
 
 import java.util.EnumSet;
-import java.util.Locale;
 import java.util.ResourceBundle;
 import java.io.IOException;
 import org.apache.sis.io.TableAppender;
@@ -42,7 +41,8 @@ final class HelpCommand extends CommandR
         "mime-type",
         "metadata",
         "crs",
-        "identifier"
+        "identifier",
+        "transform"
     };
 
     /**
@@ -110,7 +110,7 @@ final class HelpCommand extends CommandR
             out.print(vocabulary.getString(Vocabulary.Keys.Options));
             out.println(':');
             for (final Option option : validOptions) {
-                final String name = option.name().toLowerCase(Locale.US);
+                final String name = option.label();
                 table.append("  ").append(Option.PREFIX).append(name);
                 table.nextColumn();
                 table.append(options.getString(name));

Copied: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/IdentifierCommand.java
 (from r1740562, 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java)
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/IdentifierCommand.java?p2=sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/IdentifierCommand.java&p1=sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java&r1=1740562&r2=1740703&rev=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/IdentifierCommand.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -18,185 +18,87 @@ package org.apache.sis.console;
 
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.Set;
-import java.io.Console;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.ResourceBundle;
 import java.io.IOException;
-import javax.xml.bind.Marshaller;
 import javax.xml.bind.JAXBException;
 import org.opengis.metadata.Metadata;
 import org.opengis.metadata.Identifier;
+import org.opengis.referencing.NoSuchAuthorityCodeException;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.ReferenceSystem;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.apache.sis.io.wkt.WKTFormat;
-import org.apache.sis.io.wkt.Convention;
-import org.apache.sis.io.wkt.Colors;
-import org.apache.sis.metadata.MetadataStandard;
-import org.apache.sis.metadata.ValueExistencePolicy;
-import org.apache.sis.metadata.iso.DefaultMetadata;
-import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.internal.util.X364;
 import org.apache.sis.referencing.CRS;
-import org.apache.sis.storage.DataStore;
-import org.apache.sis.storage.DataStores;
+import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.util.collection.TableColumn;
-import org.apache.sis.util.collection.TreeTable;
-import org.apache.sis.util.collection.TreeTableFormat;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.xml.MarshallerPool;
-import org.apache.sis.xml.XML;
+import org.apache.sis.util.resources.Vocabulary;
 
 
 /**
- * The "metadata", "crs" and "identifier" subcommands.
- * CRS are considered as a kind of metadata here.
+ * The "identifier" sub-command.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
  * @version 0.7
  * @module
  */
-final class MetadataCommand extends CommandRunner {
-    /**
-     * The protocol part of the filename to be recognized as a CRS authority.
-     * In such case, this class will delegate to {@link CRS#forCode(String)}
-     * instead of opening the file.
-     */
-    static final Set<String> AUTHORITIES = new HashSet<>(Arrays.asList("URN", 
"EPSG", "CRS", "AUTO", "AUTO2"));
-
-    /**
-     * Length of the longest authority name declared in {@link #AUTHORITIES}.
-     */
-    static final int MAX_AUTHORITY_LENGTH = 5;
-
+final class IdentifierCommand extends MetadataCommand {
     /**
-     * The desired information.
+     * The state to write in the left margin before the identifier.
+     *
+     * <b>MAINTENANCE NOTE:</b> if this enumeration is modified,
+     * update {@code IdentifierState.properties} accordingly.
      */
-    static enum Info {
-        METADATA, CRS, IDENTIFIER
-    }
+    private static enum State {
+        VALID("   "), APPROXIMATIVE("~  "), AXIS_ORDER("!  "), MISMATCH("!! 
"), UNKNOWN("?  ");
 
-    /**
-     * The output format.
-     */
-    private static enum Format {
-        TEXT, WKT, XML
+        /** The string representation. */ final String text;
+        private State(final String p) {this.text = p;};
     }
 
     /**
-     * The sub-command: {@code "metadata"}, {@code "crs"} or {@code 
"identifier"}.
+     * A row containing a metadata or CRS identifier, its name and a status 
flag.
      */
-    private final Info command;
-
-    /**
-     * The output format.
-     */
-    private Format outputFormat;
+    private static class Row {
+        /**
+         * The two-letters state to write before the identifier.
+         */
+        final State state;
 
-    /**
-     * The WKT convention, or {@code null} if it does not apply.
-     */
-    private Convention convention;
+        /**
+         * The identifier.
+         */
+        final String identifier;
 
-    /**
-     * Creates the {@code "metadata"}, {@code "crs"} or {@code "identifier"} 
sub-command.
-     */
-    MetadataCommand(final Info command, final int commandIndex, final 
String... args) throws InvalidOptionException {
-        super(commandIndex, args, EnumSet.of(Option.FORMAT, Option.LOCALE, 
Option.TIMEZONE, Option.ENCODING,
-                Option.COLORS, Option.HELP, Option.DEBUG));
-        this.command = command;
-    }
+        /**
+         * A description to write after the identifier.
+         */
+        final CharSequence description;
 
-    /**
-     * Parses the command-line arguments and initializes the {@link 
#outputFormat} and {@link #convention} fields
-     * accordingly. This method verifies the parameter validity.
-     */
-    private void parseArguments() throws InvalidOptionException {
-        /*
-         * Output format can be either "text" (the default) or "xml".
-         * In the case of "crs" sub-command, we accept also WKT variants.
+        /**
+         * Creates a row for the given elements.
          */
-        final String format = options.get(Option.FORMAT);
-        if (format == null || format.equalsIgnoreCase("text")) {
-            if (command == Info.CRS) {
-                outputFormat = Format.WKT;
-                convention = Convention.WKT2_SIMPLIFIED;
-            } else {
-                outputFormat = Format.TEXT;
-            }
-        } else if (format.equalsIgnoreCase("wkt") || 
format.equalsIgnoreCase("wkt2")) {
-            outputFormat = Format.WKT;
-            convention = Convention.WKT2;
-        } else if (format.equalsIgnoreCase("wkt1")) {
-            outputFormat = Format.WKT;
-            convention = Convention.WKT1;
-        } else if (format.equalsIgnoreCase("xml")) {
-            outputFormat = Format.XML;
-        } else {
-            throw new InvalidOptionException(Errors.format(
-                    Errors.Keys.IllegalOptionValue_2, "format", format), 
format);
-        }
-        final boolean isFormatCompatible;
-        switch (command) {
-            case CRS: {
-                isFormatCompatible = true;
-                break;
-            }
-            case IDENTIFIER: {
-                isFormatCompatible = (outputFormat == Format.TEXT);
-                break;
-            }
-            default: {
-                isFormatCompatible = (convention == null);
-                break;
-            }
-        }
-        if (!isFormatCompatible) {
-            throw new 
InvalidOptionException(Errors.format(Errors.Keys.IncompatibleFormat_2,
-                    command.name().toLowerCase(locale), format), format);
+        Row(final State state, final String identifier, final CharSequence 
description) {
+            this.state       = state;
+            this.identifier  = identifier;
+            this.description = description;
         }
     }
 
     /**
-     * If the given argument begins with one of the known authorities ("URN", 
"EPSG", "CRS", "AUTO", <i>etc.</i>),
-     * delegates to {@link CRS#forCode(String)} and wraps in a metadata 
object. Otherwise returns {@code null}.
+     * Creates the {@code "metadata"}, {@code "crs"} or {@code "identifier"} 
sub-command.
      */
-    private static Metadata fromDatabase(final String code) throws 
FactoryException {
-        final char[] authority = new char[MAX_AUTHORITY_LENGTH];
-        final int length = code.length();
-        int p = 0, i = 0;
-        while (i < length) {
-            final int c = code.codePointAt(i);
-            if (c == ':') {
-                if (!AUTHORITIES.contains(new String(authority, 0, p))) {
-                    break;
-                }
-                final DefaultMetadata metadata = new DefaultMetadata();
-                
metadata.setReferenceSystemInfo(Collections.singleton(CRS.forCode(code)));
-                return metadata;
-            }
-            if (!Character.isWhitespace(c)) {
-                if (p >= MAX_AUTHORITY_LENGTH || 
!Character.isLetterOrDigit(c)) {
-                    break;
-                }
-                /*
-                 * Casting to char is okay because AUTHORITIES contains only 
ASCII values.
-                 * If 'c' was a supplemental Unicode value, then the result of 
the cast
-                 * will not match any AUTHORITIES value anyway.
-                 */
-                authority[p++] = (char) Character.toUpperCase(c);
-            }
-            i += Character.charCount(c);
-        }
-        return null;
+    IdentifierCommand(final int commandIndex, final String... args) throws 
InvalidOptionException {
+        super(commandIndex, args);
     }
 
     /**
-     * Prints metadata or CRS information.
+     * Prints identifier information.
      *
      * @throws DataStoreException if an error occurred while reading the file.
      * @throws JAXBException if an error occurred while producing the XML 
output.
@@ -204,118 +106,142 @@ final class MetadataCommand extends Comm
      * @throws IOException should never happen, since we are appending to a 
print writer.
      */
     @Override
-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
     public int run() throws InvalidOptionException, DataStoreException, 
JAXBException, FactoryException, IOException {
         parseArguments();
+        if (outputFormat != Format.TEXT) {
+            final String format = outputFormat.name();
+            throw new 
InvalidOptionException(Errors.format(Errors.Keys.IncompatibleFormat_2, 
"identifier", format), format);
+        }
         /*
          * Read metadata from the data storage only after we verified that the 
arguments are valid.
          * The input can be a file given on the command line, or the standard 
input stream.
          */
-        Metadata metadata;
-        if (useStandardInput()) {
-            try (DataStore store = DataStores.open(System.in)) {
-                metadata = store.getMetadata();
-            }
-        } else {
-            if (hasUnexpectedFileCount(1, 1)) {
-                return Command.INVALID_ARGUMENT_EXIT_CODE;
-            }
-            final String file = files.get(0);
-            metadata = fromDatabase(file);
-            if (metadata == null) {
-                try (DataStore store = DataStores.open(file)) {
-                    metadata = store.getMetadata();
-                }
-            }
-        }
-        if (metadata == null) {
-            return 0;
-        }
-        /*
-         * If we are executing the "identifier" sub-command, then show the 
metadata identifier (if any)
-         * and the identifier of all referencing systems found. Otherwise if 
we are executing the "crs"
-         * sub-command, extract only the first CRS. That CRS will be displayed 
after the switch statement.
-         */
-        Object object = metadata;
-choice: switch (command) {
-            case IDENTIFIER: {
-                final List<IdentifierRow> rows = new ArrayList<>();
-                final Identifier id = metadata.getMetadataIdentifier();
+        Object metadata = readMetadataOrCRS();
+        if (hasUnexpectedFileCount) {
+            return Command.INVALID_ARGUMENT_EXIT_CODE;
+        }
+        if (metadata != null) {
+            final List<Row> rows;
+            if (metadata instanceof Metadata) {
+                rows = new ArrayList<>();
+                final Identifier id = ((Metadata) 
metadata).getMetadataIdentifier();
                 if (id != null) {
                     CharSequence desc = id.getDescription();
                     if (desc != null && !files.isEmpty()) desc = files.get(0);
-                    rows.add(new IdentifierRow(IdentifierRow.State.VALID, 
IdentifiedObjects.toString(id), desc));
+                    rows.add(new Row(State.VALID, 
IdentifiedObjects.toString(id), desc));
                 }
-                for (final ReferenceSystem rs : 
metadata.getReferenceSystemInfo()) {
-                    rows.add(IdentifierRow.create(rs));
+                for (final ReferenceSystem rs : ((Metadata) 
metadata).getReferenceSystemInfo()) {
+                    rows.add(create(rs));
                 }
-                IdentifierRow.print(rows, out, locale, colors);
-                return 0;
+            } else {
+                rows = Collections.singletonList(create((ReferenceSystem) 
metadata));
             }
-            case CRS: {
-                for (final ReferenceSystem rs : 
metadata.getReferenceSystemInfo()) {
-                    if (rs instanceof CoordinateReferenceSystem) {
-                        object = rs;
-                        break choice;
-                    }
+            print(rows);
+        }
+        return 0;
+    }
+
+    /**
+     * Creates an identifier row for the given CRS.
+     * This method gives precedence to {@code "urn:ogc:def:"} identifiers if 
possible.
+     *
+     * @return The row, or {@code null} if no identifier has been found.
+     */
+    static Row create(ReferenceSystem rs) throws FactoryException {
+        String identifier = IdentifiedObjects.lookupURN(rs, null);
+        if (identifier == null) {
+            /*
+             * If we can not find an identifier matching the EPSG or WMS 
definitions,
+             * look at the identifiers declared in the CRS and verify their 
validity.
+             */
+            for (final Identifier id : rs.getIdentifiers()) {
+                final String c = IdentifiedObjects.toURN(rs.getClass(), id);
+                if (c != null) {
+                    identifier = c;
+                    break;                                          // Stop at 
the first "urn:ogc:def:…".
                 }
-                return 0;
+                if (identifier == null) {
+                    identifier = IdentifiedObjects.toString(id);    // 
"AUTHORITY:CODE" as a fallback if no URN.
+                }
+            }
+            if (identifier == null) {
+                return null;                                        // No 
identifier found.
             }
         }
         /*
-         * Format metadata to the standard output stream.
+         * The CRS provided by the user contains identifier, but the 
'lookupURN' operation above failed to
+         * find it. The most likely cause is that the user-provided CRS does 
not use the same axis order.
          */
-        switch (outputFormat) {
-            case TEXT: {
-                final TreeTable tree = 
MetadataStandard.ISO_19115.asTreeTable(object, ValueExistencePolicy.NON_EMPTY);
-                final TreeTableFormat tf = new TreeTableFormat(locale, 
timezone);
-                tf.setColumns(TableColumn.NAME, TableColumn.VALUE);
-                tf.format(tree, out);
-                break;
-            }
-
-            case WKT: {
-                final WKTFormat f = new WKTFormat(locale, timezone);
-                if (convention != null) {
-                    f.setConvention(convention);
+        State state;
+        try {
+            final ReferenceSystem def = CRS.forCode(identifier);
+            final ComparisonMode c = ComparisonMode.equalityLevel(def, rs);
+            if (c == null) {
+                state = State.MISMATCH;
+            } else switch (c) {
+                case ALLOW_VARIANT: {
+                    state = State.AXIS_ORDER;
+                    break;
                 }
-                if (colors) {
-                    f.setColors(Colors.DEFAULT);
+                case APPROXIMATIVE: {
+                    state = State.APPROXIMATIVE;
+                    rs = def;
+                    break;
                 }
-                f.format(object, out);
-                out.println();
-                break;
-            }
-
-            case XML: {
-                final MarshallerPool pool = new MarshallerPool(null);
-                final Marshaller marshaller = pool.acquireMarshaller();
-                marshaller.setProperty(XML.LOCALE,   locale);
-                marshaller.setProperty(XML.TIMEZONE, timezone);
-                if (isConsole()) {
-                    marshaller.marshal(object, out);
-                } else {
-                    out.flush();
-                    marshaller.setProperty(Marshaller.JAXB_ENCODING, 
encoding.name());
-                    marshaller.marshal(object, System.out);     // 
Intentionally use OutputStream instead than Writer.
-                    System.out.flush();
+                default: {
+                    state = State.VALID;
+                    rs = def;
+                    break;
                 }
-                break;
             }
+        } catch (NoSuchAuthorityCodeException e) {
+            state = State.UNKNOWN;
         }
-        out.flush();
-        return 0;
+        return new Row(state, identifier, rs.getName().getCode());
     }
 
     /**
-     * Returns {@code true} if {@link #out} is sending its output to the 
console.
-     * If not, then we are probably writing to a file or the user specified 
his own encoding.
-     * In such case, we will send the XML output to an {@code OutputStream} 
instead than to a
-     * {@code Writer} and let the marshaller apply the encoding itself.
+     * Prints all non-null rows.
      */
-    private boolean isConsole() {
-        if (outputBuffer != null) return true;                      // Special 
case for JUnit tests only.
-        final Console console = System.console();
-        return (console != null) && console.writer() == out;
+    private void print(final Iterable<Row> rows) {
+        int width = 0;
+        for (final Row row : rows) {
+            if (row != null) {
+                width = Math.max(width, row.identifier.length());
+            }
+        }
+        width += 4;
+        final Set<State> states = EnumSet.noneOf(State.class);
+        for (final Row row : rows) {
+            if (row != null) {
+                states.add(row.state);
+                final boolean warning = colors && 
row.state.text.startsWith("!");
+                if (warning) out.print(X364.FOREGROUND_RED.sequence());
+                out.print(row.state.text);
+                out.print(' ');
+                out.print(row.identifier);
+                if (warning) out.print(X364.FOREGROUND_DEFAULT.sequence());
+                if (colors)  out.print(X364.FOREGROUND_GRAY.sequence());
+                out.print(CharSequences.spaces(width - 
row.identifier.length()));
+                out.print("| ");
+                out.println(row.description);
+                if (colors) out.print(X364.FOREGROUND_DEFAULT.sequence());
+            }
+        }
+        states.remove(State.VALID);
+        if (!states.isEmpty()) {
+            out.println();
+            
out.println(Vocabulary.getResources(locale).getLabel(Vocabulary.Keys.Legend));
+            final ResourceBundle resources = 
ResourceBundle.getBundle("org.apache.sis.console.IdentifierState", locale);
+            for (final State state : states) {
+                final boolean warning = colors && state.text.startsWith("!");
+                if (warning) out.print(X364.FOREGROUND_RED.sequence());
+                out.print(state.text);
+                if (warning) out.print(X364.FOREGROUND_DEFAULT.sequence());
+                out.print(' ');
+                out.println(resources.getString(state.name()));
+            }
+        }
+        out.flush();
     }
 }

Modified: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/InvalidOptionException.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/InvalidOptionException.java?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/InvalidOptionException.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/InvalidOptionException.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -39,8 +39,8 @@ public class InvalidOptionException exte
     /**
      * Constructs an exception with the specified detail message.
      *
-     * @param message The detail message.
-     * @param option The name of the invalid option.
+     * @param message  the detail message.
+     * @param option   the name of the invalid option.
      */
     public InvalidOptionException(final String message, final String option) {
         super(message);
@@ -50,9 +50,9 @@ public class InvalidOptionException exte
     /**
      * Constructs an exception with the specified detail message and cause.
      *
-     * @param message The detail message.
-     * @param cause   The cause of this exception.
-     * @param option  The name of the invalid option.
+     * @param message  the detail message.
+     * @param cause    the cause of this exception.
+     * @param option   the name of the invalid option.
      */
     public InvalidOptionException(final String message, final Throwable cause, 
final String option) {
         super(message, cause);
@@ -62,7 +62,7 @@ public class InvalidOptionException exte
     /**
      * Returns the name of the invalid option.
      *
-     * @return The name of the invalid option.
+     * @return the name of the invalid option.
      */
     public String getOption() {
         return option;

Modified: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -16,8 +16,6 @@
  */
 package org.apache.sis.console;
 
-import java.util.List;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -28,17 +26,15 @@ import java.io.IOException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.JAXBException;
 import org.opengis.metadata.Metadata;
-import org.opengis.metadata.Identifier;
-import org.opengis.util.FactoryException;
 import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.util.FactoryException;
 import org.apache.sis.io.wkt.WKTFormat;
 import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.io.wkt.Colors;
 import org.apache.sis.metadata.MetadataStandard;
 import org.apache.sis.metadata.ValueExistencePolicy;
 import org.apache.sis.metadata.iso.DefaultMetadata;
-import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStores;
@@ -52,15 +48,15 @@ import org.apache.sis.xml.XML;
 
 
 /**
- * The "metadata", "crs" and "identifier" subcommands.
- * CRS are considered as a kind of metadata here.
+ * The "metadata" sub-command. This class is also used as the base class of 
other sub-commands
+ * that perform most of their work on the basis of metadata information.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
  * @version 0.7
  * @module
  */
-final class MetadataCommand extends CommandRunner {
+class MetadataCommand extends CommandRunner {
     /**
      * The protocol part of the filename to be recognized as a CRS authority.
      * In such case, this class will delegate to {@link CRS#forCode(String)}
@@ -74,98 +70,82 @@ final class MetadataCommand extends Comm
     static final int MAX_AUTHORITY_LENGTH = 5;
 
     /**
-     * The desired information.
-     */
-    static enum Info {
-        METADATA, CRS, IDENTIFIER
-    }
-
-    /**
      * The output format.
      */
-    private static enum Format {
+    static enum Format {
         TEXT, WKT, XML
     }
 
     /**
-     * The sub-command: {@code "metadata"}, {@code "crs"} or {@code 
"identifier"}.
+     * The output format. Default value can be overridden by {@link 
#parseArguments()}.
      */
-    private final Info command;
+    Format outputFormat = Format.TEXT;
 
     /**
-     * The output format.
+     * The WKT convention, or {@code null} if it does not apply.
      */
-    private Format outputFormat;
+    Convention convention;
 
     /**
-     * The WKT convention, or {@code null} if it does not apply.
+     * Sets to {@code true} by {@link #readMetadata()} if the users provided 
an unexpected number of file arguments.
+     * In such case, the {@link #run()} should terminate with exit code {@link 
Command#INVALID_ARGUMENT_EXIT_CODE}.
      */
-    private Convention convention;
+    boolean hasUnexpectedFileCount;
 
     /**
-     * Creates the {@code "metadata"}, {@code "crs"} or {@code "identifier"} 
sub-command.
+     * Creates the {@code "metadata"} sub-command.
      */
-    MetadataCommand(final Info command, final int commandIndex, final 
String... args) throws InvalidOptionException {
+    MetadataCommand(final int commandIndex, final String... args) throws 
InvalidOptionException {
         super(commandIndex, args, EnumSet.of(Option.FORMAT, Option.LOCALE, 
Option.TIMEZONE, Option.ENCODING,
                 Option.COLORS, Option.HELP, Option.DEBUG));
-        this.command = command;
+    }
+
+    /**
+     * Creates a new sub-command with the given command-line arguments.
+     * This constructor is for {@code MetadataCommand} subclasses only.
+     *
+     * @param  commandIndex  index of the {@code args} element containing the 
sub-command name.
+     * @param  arguments     the command-line arguments provided by the user.
+     * @param  validOptions  the command-line options allowed by this 
sub-command.
+     * @throws InvalidOptionException if an illegal option has been provided, 
or the option has an illegal value.
+     */
+    MetadataCommand(final int commandIndex, final String[] args, final 
EnumSet<Option> validOptions)
+            throws InvalidOptionException
+    {
+        super(commandIndex, args, validOptions);
     }
 
     /**
      * Parses the command-line arguments and initializes the {@link 
#outputFormat} and {@link #convention} fields
-     * accordingly. This method verifies the parameter validity.
+     * accordingly.
      */
-    private void parseArguments() throws InvalidOptionException {
+    final void parseArguments() throws InvalidOptionException {
         /*
          * Output format can be either "text" (the default) or "xml".
          * In the case of "crs" sub-command, we accept also WKT variants.
          */
         final String format = options.get(Option.FORMAT);
-        if (format == null || format.equalsIgnoreCase("text")) {
-            if (command == Info.CRS) {
+        if (format != null && !format.equalsIgnoreCase("text")) {
+            if (format.equalsIgnoreCase("wkt") || 
format.equalsIgnoreCase("wkt2")) {
                 outputFormat = Format.WKT;
-                convention = Convention.WKT2_SIMPLIFIED;
+                convention = Convention.WKT2;
+            } else if (format.equalsIgnoreCase("wkt1")) {
+                outputFormat = Format.WKT;
+                convention = Convention.WKT1;
+            } else if (format.equalsIgnoreCase("xml")) {
+                outputFormat = Format.XML;
             } else {
-                outputFormat = Format.TEXT;
-            }
-        } else if (format.equalsIgnoreCase("wkt") || 
format.equalsIgnoreCase("wkt2")) {
-            outputFormat = Format.WKT;
-            convention = Convention.WKT2;
-        } else if (format.equalsIgnoreCase("wkt1")) {
-            outputFormat = Format.WKT;
-            convention = Convention.WKT1;
-        } else if (format.equalsIgnoreCase("xml")) {
-            outputFormat = Format.XML;
-        } else {
-            throw new InvalidOptionException(Errors.format(
-                    Errors.Keys.IllegalOptionValue_2, "format", format), 
format);
-        }
-        final boolean isFormatCompatible;
-        switch (command) {
-            case CRS: {
-                isFormatCompatible = true;
-                break;
-            }
-            case IDENTIFIER: {
-                isFormatCompatible = (outputFormat == Format.TEXT);
-                break;
-            }
-            default: {
-                isFormatCompatible = (convention == null);
-                break;
+                throw new InvalidOptionException(Errors.format(
+                        Errors.Keys.IllegalOptionValue_2, "format", format), 
format);
             }
         }
-        if (!isFormatCompatible) {
-            throw new 
InvalidOptionException(Errors.format(Errors.Keys.IncompatibleFormat_2,
-                    command.name().toLowerCase(locale), format), format);
-        }
     }
 
     /**
-     * If the given argument begins with one of the known authorities ("URN", 
"EPSG", "CRS", "AUTO", <i>etc.</i>),
-     * delegates to {@link CRS#forCode(String)} and wraps in a metadata 
object. Otherwise returns {@code null}.
+     * Returns {@code true} if the given argument begins with one of the known 
authorities
+     * ("URN", "EPSG", "CRS", "AUTO", <i>etc.</i>).
      */
-    private static Metadata fromDatabase(final String code) throws 
FactoryException {
+    static boolean isAuthorityCode(final String code) {
         final char[] authority = new char[MAX_AUTHORITY_LENGTH];
         final int length = code.length();
         int p = 0, i = 0;
@@ -175,9 +155,7 @@ final class MetadataCommand extends Comm
                 if (!AUTHORITIES.contains(new String(authority, 0, p))) {
                     break;
                 }
-                final DefaultMetadata metadata = new DefaultMetadata();
-                
metadata.setReferenceSystemInfo(Collections.singleton(CRS.forCode(code)));
-                return metadata;
+                return true;
             }
             if (!Character.isWhitespace(c)) {
                 if (p >= MAX_AUTHORITY_LENGTH || 
!Character.isLetterOrDigit(c)) {
@@ -186,13 +164,39 @@ final class MetadataCommand extends Comm
                 /*
                  * Casting to char is okay because AUTHORITIES contains only 
ASCII values.
                  * If 'c' was a supplemental Unicode value, then the result of 
the cast
-                 * will not match any AUTHORITIES value anyway.
+                 * would not match any AUTHORITIES value anyway.
                  */
                 authority[p++] = (char) Character.toUpperCase(c);
             }
             i += Character.charCount(c);
         }
-        return null;
+        return false;
+    }
+
+    /**
+     * If the given argument begins with one of the known authorities ("URN", 
"EPSG", "CRS", "AUTO", <i>etc.</i>),
+     * delegates to {@link CRS#forCode(String)}. Otherwise reads the metadata 
using a datastore.
+     *
+     * @return A {@link Metadata} or {@link CoordinateReferenceSystem} 
instance, or {@code null} if none.
+     */
+    final Object readMetadataOrCRS() throws DataStoreException, 
FactoryException {
+        if (useStandardInput()) {
+            try (DataStore store = DataStores.open(System.in)) {
+                return store.getMetadata();
+            }
+        } else if (hasUnexpectedFileCount(1, 1)) {
+            hasUnexpectedFileCount = true;
+            return null;
+        } else {
+            final String file = files.get(0);
+            if (isAuthorityCode(file)) {
+                return CRS.forCode(file);
+            } else {
+                try (DataStore store = DataStores.open(file)) {
+                    return store.getMetadata();
+                }
+            }
+        }
     }
 
     /**
@@ -204,67 +208,37 @@ final class MetadataCommand extends Comm
      * @throws IOException should never happen, since we are appending to a 
print writer.
      */
     @Override
-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
     public int run() throws InvalidOptionException, DataStoreException, 
JAXBException, FactoryException, IOException {
         parseArguments();
+        if (convention != null) {
+            final String format = outputFormat.name();
+            throw new 
InvalidOptionException(Errors.format(Errors.Keys.IncompatibleFormat_2, 
"metadata", format), format);
+        }
         /*
          * Read metadata from the data storage only after we verified that the 
arguments are valid.
          * The input can be a file given on the command line, or the standard 
input stream.
          */
-        Metadata metadata;
-        if (useStandardInput()) {
-            try (DataStore store = DataStores.open(System.in)) {
-                metadata = store.getMetadata();
-            }
-        } else {
-            if (hasUnexpectedFileCount(1, 1)) {
-                return Command.INVALID_ARGUMENT_EXIT_CODE;
-            }
-            final String file = files.get(0);
-            metadata = fromDatabase(file);
-            if (metadata == null) {
-                try (DataStore store = DataStores.open(file)) {
-                    metadata = store.getMetadata();
-                }
-            }
+        Object metadata = readMetadataOrCRS();
+        if (hasUnexpectedFileCount) {
+            return Command.INVALID_ARGUMENT_EXIT_CODE;
         }
-        if (metadata == null) {
-            return 0;
-        }
-        /*
-         * If we are executing the "identifier" sub-command, then show the 
metadata identifier (if any)
-         * and the identifier of all referencing systems found. Otherwise if 
we are executing the "crs"
-         * sub-command, extract only the first CRS. That CRS will be displayed 
after the switch statement.
-         */
-        Object object = metadata;
-choice: switch (command) {
-            case IDENTIFIER: {
-                final List<IdentifierRow> rows = new ArrayList<>();
-                final Identifier id = metadata.getMetadataIdentifier();
-                if (id != null) {
-                    CharSequence desc = id.getDescription();
-                    if (desc != null && !files.isEmpty()) desc = files.get(0);
-                    rows.add(new IdentifierRow(IdentifierRow.State.VALID, 
IdentifiedObjects.toString(id), desc));
-                }
-                for (final ReferenceSystem rs : 
metadata.getReferenceSystemInfo()) {
-                    rows.add(IdentifierRow.create(rs));
-                }
-                IdentifierRow.print(rows, out, locale, colors);
-                return 0;
-            }
-            case CRS: {
-                for (final ReferenceSystem rs : 
metadata.getReferenceSystemInfo()) {
-                    if (rs instanceof CoordinateReferenceSystem) {
-                        object = rs;
-                        break choice;
-                    }
-                }
-                return 0;
+        if (metadata != null) {
+            if (!(metadata instanceof Metadata)) {
+                final DefaultMetadata md = new DefaultMetadata();
+                
md.setReferenceSystemInfo(Collections.singleton((ReferenceSystem) metadata));
+                metadata = md;
             }
+            format(metadata);
         }
-        /*
-         * Format metadata to the standard output stream.
-         */
+        return 0;
+    }
+
+    /**
+     * Format the given metadata or CRS object to the standard output stream.
+     * The format is determined by {@link #outputFormat} and (in WKT case 
only) {@link #convention}.
+     */
+    @SuppressWarnings("UseOfSystemOutOrSystemErr")
+    final void format(final Object object) throws IOException, JAXBException {
         switch (outputFormat) {
             case TEXT: {
                 final TreeTable tree = 
MetadataStandard.ISO_19115.asTreeTable(object, ValueExistencePolicy.NON_EMPTY);
@@ -304,7 +278,6 @@ choice: switch (command) {
             }
         }
         out.flush();
-        return 0;
     }
 
     /**

Modified: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Option.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Option.java?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Option.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Option.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -30,6 +30,16 @@ import org.apache.sis.util.resources.Err
  */
 enum Option {
     /**
+     * The Coordinate Reference System of input data.
+     */
+    SOURCE_CRS(true),
+
+    /**
+     * The Coordinate Reference System of input data.
+     */
+    TARGET_CRS(true),
+
+    /**
      * The output format. Examples: {@code "xml"}, {@code "text"}.
      */
     FORMAT(true),
@@ -95,6 +105,14 @@ enum Option {
     };
 
     /**
+     * The string representation of this option, as used on the command line.
+     * This is usually the lower-case version of {@link #name()}.
+     *
+     * @see #label()
+     */
+    private String label;
+
+    /**
      * Whether this option expects a value.
      */
     final boolean hasValue;
@@ -102,13 +120,43 @@ enum Option {
     /**
      * Creates a new option.
      *
-     * @param hasValue Whether this option expects a value.
+     * @param hasValue  whether this option expects a value.
      */
     private Option(final boolean hasValue) {
         this.hasValue = hasValue;
     }
 
     /**
+     * Special case for which {@code label()} should not be only the 
lower-case of enum name.
+     */
+    static {
+        SOURCE_CRS.label = "sourceCRS";
+        TARGET_CRS.label = "targetCRS";
+    }
+
+    /**
+     * Return the string representation as used on the command line.
+     */
+    String label() {
+        if (label == null) {
+            label = name().toLowerCase(Locale.US);
+        }
+        return label;
+    }
+
+    /**
+     * Returns the option for the given string.
+     */
+    static Option forLabel(final String label) throws InvalidOptionException {
+        for (final Option option : values()) {
+            if (label.equalsIgnoreCase(option.name().replace("_", ""))) {
+                return option;
+            }
+        }
+        throw new 
InvalidOptionException(Errors.format(Errors.Keys.UnknownOption_1, label), 
label);
+    }
+
+    /**
      * Parses the given value as a boolean.
      *
      * @param  value The value to parse.

Added: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java?rev=1740703&view=auto
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
 (added)
+++ 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.console;
+
+import java.util.EnumSet;
+import org.opengis.metadata.Metadata;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.ReferenceSystem;
+import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.apache.sis.internal.referencing.Formulas;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.internal.util.X364;
+import org.apache.sis.storage.DataStore;
+import org.apache.sis.storage.DataStores;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * The "transform" subcommand.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+final class TransformCommand extends MetadataCommand {
+    /**
+     * The coordinate operation from the given source CRS to target CRS.
+     */
+    private CoordinateOperation operation;
+
+    /**
+     * Creates the {@code "transform"} sub-command.
+     */
+    TransformCommand(final int commandIndex, final String... args) throws 
InvalidOptionException {
+        super(commandIndex, args, EnumSet.of(Option.SOURCE_CRS, 
Option.TARGET_CRS,
+                Option.LOCALE, Option.TIMEZONE, Option.ENCODING, 
Option.COLORS, Option.HELP, Option.DEBUG));
+    }
+
+    /**
+     * Fetches the source or target coordinate reference system from the value 
given to the specified option.
+     *
+     * @param  option  either {@link Option#SOURCE_CRS} or {@link 
Option#TARGET_CRS}.
+     * @return the coordinate reference system for the given option.
+     * @throws InvalidOptionException if the given option is missing or have 
an invalid value.
+     * @throws FactoryException if the operation failed for another reason.
+     */
+    private CoordinateReferenceSystem fetchCRS(final Option option) throws 
InvalidOptionException, FactoryException, DataStoreException {
+        final String identifier = options.get(option);
+        if (identifier == null) {
+            final String name = option.label();
+            throw new 
InvalidOptionException(Errors.format(Errors.Keys.MissingValueForOption_1, 
name), name);
+        }
+        if (isAuthorityCode(identifier)) try {
+            return CRS.forCode(identifier);
+        } catch (NoSuchAuthorityCodeException e) {
+            final String name = option.label();
+            throw new 
InvalidOptionException(Errors.format(Errors.Keys.IllegalOptionValue_2, name, 
identifier), e, name);
+        } else {
+            final Metadata metadata;
+            try (DataStore store = DataStores.open(identifier)) {
+                metadata = store.getMetadata();
+            }
+            if (metadata != null) {
+                for (final ReferenceSystem rs : 
metadata.getReferenceSystemInfo()) {
+                    if (rs instanceof CoordinateReferenceSystem) {
+                        return (CoordinateReferenceSystem) rs;
+                    }
+                }
+            }
+            throw new 
InvalidOptionException(Errors.format(Errors.Keys.UnspecifiedCRS), 
option.label());
+        }
+    }
+
+    /**
+     * Transforms coordinates from the files given in argument or from the 
standard input stream.
+     */
+    @Override
+    public int run() throws InvalidOptionException, DataStoreException, 
FactoryException {
+        parseArguments();
+        operation = CRS.findOperation(fetchCRS(Option.SOURCE_CRS), 
fetchCRS(Option.TARGET_CRS), null);
+        if (!operation.getIdentifiers().isEmpty()) {
+            print("Coordinate operation", operation);
+        } else {
+            print("Source CRS", operation.getSourceCRS());
+            print("Target CRS", operation.getTargetCRS());
+        }
+        double accuracy = CRS.getLinearAccuracy(operation);
+        if (accuracy >= 0) {
+            if (accuracy == 0) {
+                accuracy = Formulas.LINEAR_TOLERANCE;
+            }
+            printHeader("Accuracy");
+            out.print(accuracy);
+            out.println(" metres");
+        }
+        return 0;
+    }
+
+    /**
+     * Prints the given string in bold characters. This is used for formatting
+     * some metadata in the header before to print transformed coordinates.
+     */
+    private void printHeader(final String header) {
+        if (colors) {
+            out.print(X364.BOLD.sequence());
+        }
+        out.print(header);
+        out.print(':');
+        if (colors) {
+            out.print(X364.NORMAL.sequence());
+        }
+        out.print(' ');
+    }
+
+    /**
+     * Prints the name and authority code (if any) of the given object.
+     */
+    private void print(final String header, final IdentifiedObject object) {
+        printHeader(header);
+        out.print(object.getName().getCode());
+        final String identifier = 
IdentifiedObjects.toString(IdentifiedObjects.getIdentifier(object, null));
+        if (identifier != null) {
+            out.print(' ');
+            if (colors) {
+                out.print(X364.FOREGROUND_YELLOW.sequence());
+            }
+            out.print('(');
+            out.print(identifier);
+            out.print(')');
+            if (colors) {
+                out.print(X364.FOREGROUND_DEFAULT.sequence());
+            }
+        }
+        out.println();
+    }
+}

Propchange: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands.properties
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands.properties?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands.properties
 [ISO-8859-1] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands.properties
 [ISO-8859-1] Sun Apr 24 15:50:56 2016
@@ -8,3 +8,4 @@ mime-type=Show MIME type for the given f
 metadata=Show metadata information for the given file.
 crs=Show Coordinate Reference System (CRS) information for the given file.
 identifier=Show identifiers for metadata and referencing systems in the given 
file.
+transform=Convert or transform coordinates from given source CRS to target CRS.

Modified: 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands_fr.properties
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands_fr.properties?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands_fr.properties
 [ISO-8859-1] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Commands_fr.properties
 [ISO-8859-1] Sun Apr 24 15:50:56 2016
@@ -8,3 +8,4 @@ mime-type=Affiche le type MIME du fichie
 metadata=Affiche les méta-données du fichier spécifié.
 crs=Affiche le système de référence des coordonnées du fichier spécifié.
 identifier=Affiche les identifiants des méta-données et des systèmes de 
références du fichier spécifié.
+transform=Transforme des coordonnées du système de référence source vers le 
système destination donné.

Modified: 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options.properties
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options.properties?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options.properties
 [ISO-8859-1] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options.properties
 [ISO-8859-1] Sun Apr 24 15:50:56 2016
@@ -1,4 +1,6 @@
 # Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.
+sourceCRS=The Coordinate Reference System of input data.
+targetCRS=The Coordinate Reference System of output data.
 format=The output format: xml, wkt, wkt1 or text.
 locale=The locale to use for the command output.
 timezone=The timezone for the dates to be formatted.

Modified: 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options_fr.properties
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options_fr.properties?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options_fr.properties
 [ISO-8859-1] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/main/resources/org/apache/sis/console/Options_fr.properties
 [ISO-8859-1] Sun Apr 24 15:50:56 2016
@@ -1,4 +1,6 @@
 # Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.
+sourceCRS=Le système de référence des coordonnées source.
+targetCRS=Le système de référence des coordonnées destination.
 format=Le format de sortie: xml, wkt, wkt1 ou text.
 locale=Les paramètres régionaux à utiliser pour la sortie de la commande.
 timezone=Le fuseau horaire des dates à écrire.

Modified: 
sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java?rev=1740703&r1=1740702&r2=1740703&view=diff
==============================================================================
--- 
sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java
 [UTF-8] Sun Apr 24 15:50:56 2016
@@ -58,7 +58,7 @@ public final strictfp class MetadataComm
     public void testNetCDF() throws Exception {
         final URL url = IOTestCase.class.getResource(IOTestCase.NCEP);
         assertNotNull(IOTestCase.NCEP, url);
-        final MetadataCommand test = new 
MetadataCommand(MetadataCommand.Info.METADATA, 0, CommandRunner.TEST, 
url.toString());
+        final MetadataCommand test = new MetadataCommand(0, 
CommandRunner.TEST, url.toString());
         test.run();
         verifyNetCDF("Metadata", test.outputBuffer.toString());
     }
@@ -84,8 +84,7 @@ public final strictfp class MetadataComm
     @DependsOnMethod("testNetCDF")
     public void testFormatXML() throws Exception {
         final URL url = IOTestCase.class.getResource(IOTestCase.NCEP);
-        final MetadataCommand test = new 
MetadataCommand(MetadataCommand.Info.METADATA,
-                0, CommandRunner.TEST, url.toString(), "--format", "XML");
+        final MetadataCommand test = new MetadataCommand(0, 
CommandRunner.TEST, url.toString(), "--format", "XML");
         test.run();
         verifyNetCDF("<?xml", test.outputBuffer.toString());
     }


Reply via email to