You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ctakes.apache.org by se...@apache.org on 2017/08/09 14:34:36 UTC

svn commit: r1804533 - in /ctakes/trunk: ctakes-clinical-pipeline-res/src/main/resources/org/apache/ctakes/clinical/pipeline/ ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/ ctakes-dictionary-lookup-fast-res/src/main/resources/org/apache/cta...

Author: seanfinan
Date: Wed Aug  9 14:34:35 2017
New Revision: 1804533

URL: http://svn.apache.org/viewvc?rev=1804533&view=rev
Log:
DefaultFastPipeline switch to new DictionarySubPipe.piper
CliOptionalsHandler now takes care of standard cli options
PiperFileReader added .fast to packages for piper loading
PiperFileRunner moved standard cli options to CliOptionalsHander
UmlsUserApprover check CHANGE_ME, use context to find umlsUser
DictionarySubPipe.piper handles fast dictionary, using cli options
Examples pom from clinical-pipeline to coref so that more examples can be made
FileChooserPanel check cwd with Paths before user.dir
FileTableCellEditor check cwd with Paths before user.dir
PiperRunnerPanel handle String cli (for user, pass), set initial filechooser dir to cwd, removed all standard cli options except -i and -o

Added:
    ctakes/trunk/ctakes-dictionary-lookup-fast-res/src/main/resources/org/apache/ctakes/dictionary/lookup/fast/pipeline/
    ctakes/trunk/ctakes-dictionary-lookup-fast-res/src/main/resources/org/apache/ctakes/dictionary/lookup/fast/pipeline/DictionarySubPipe.piper
Modified:
    ctakes/trunk/ctakes-clinical-pipeline-res/src/main/resources/org/apache/ctakes/clinical/pipeline/DefaultFastPipeline.piper
    ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java
    ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileReader.java
    ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileRunner.java
    ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java
    ctakes/trunk/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/util/UmlsUserApprover.java
    ctakes/trunk/ctakes-examples/pom.xml
    ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileChooserPanel.java
    ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileTableCellEditor.java
    ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperRunnerPanel.java

Modified: ctakes/trunk/ctakes-clinical-pipeline-res/src/main/resources/org/apache/ctakes/clinical/pipeline/DefaultFastPipeline.piper
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-clinical-pipeline-res/src/main/resources/org/apache/ctakes/clinical/pipeline/DefaultFastPipeline.piper?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-clinical-pipeline-res/src/main/resources/org/apache/ctakes/clinical/pipeline/DefaultFastPipeline.piper (original)
+++ ctakes/trunk/ctakes-clinical-pipeline-res/src/main/resources/org/apache/ctakes/clinical/pipeline/DefaultFastPipeline.piper Wed Aug  9 14:34:35 2017
@@ -11,7 +11,7 @@ addDescription POSTagger
 load ChunkerSubPipe.piper
 
 // Default fast dictionary lookup
-add DefaultJCasTermAnnotator
+load DictionarySubPipe.piper
 
 // Add Cleartk Entity Attribute annotators
 load AttributeCleartkSubPipe.piper

Modified: ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java (original)
+++ ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java Wed Aug  9 14:34:35 2017
@@ -23,6 +23,20 @@ final public class CliOptionalsHandler {
     */
    static public String getCliOptionalValue( final CliOptionals optionals, final String optionChar ) {
       switch ( optionChar ) {
+         case "i":
+            return optionals.getInputDirectory();
+         case "o":
+            return optionals.getOutputDirectory();
+         case "s":
+            return optionals.getSubDirectory();
+         case "l":
+            return optionals.getLookupXml();
+         case "user":
+            return optionals.getUmlsUserName();
+         case "pass":
+            return optionals.getUmlsPassword();
+         case "xmiOut":
+            return optionals.getXmiOutDirectory();
          case "a":
             return optionals.getOption_a();
          case "b":

Modified: ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileReader.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileReader.java?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileReader.java (original)
+++ ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileReader.java Wed Aug  9 14:34:35 2017
@@ -59,6 +59,7 @@ final public class PiperFileReader {
          "contexttokenizer",
          "postagger",
          "chunker",
+         "dictionary.lookup.fast",
          "assertion",
          "dictionary.lookup2",
              "clinicalpipeline",

Modified: ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileRunner.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileRunner.java?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileRunner.java (original)
+++ ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PiperFileRunner.java Wed Aug  9 14:34:35 2017
@@ -44,11 +44,6 @@ final public class PiperFileRunner {
          }
          // set the output directory parameter if needed
          final String outputDir = options.getOutputDirectory();
-         // set the subdirectory parameter if needed
-         final String subDir = options.getSubDirectory();
-         if ( !subDir.isEmpty() ) {
-            builder.set( ConfigParameterConstants.PARAM_SUBDIR, subDir );
-         }
          // if xmi output directory is set but standard output directory is not, use xmi out as standard out
          final String xmiOutDir = options.getXmiOutDirectory();
          if ( !outputDir.isEmpty() ) {
@@ -56,22 +51,6 @@ final public class PiperFileRunner {
          } else if ( !xmiOutDir.isEmpty() ) {
             builder.set( ConfigParameterConstants.PARAM_OUTPUTDIR, xmiOutDir );
          }
-         // set the dictionary lookup descriptor xml
-         final String lookupXml = options.getLookupXml();
-         if ( !lookupXml.isEmpty() ) {
-            builder.set( ConfigParameterConstants.PARAM_LOOKUP_XML, lookupXml );
-         }
-         // set the umls user and password parameters if needed
-         final String umlsUser = options.getUmlsUserName();
-         if ( !umlsUser.isEmpty() ) {
-            builder.set( "umlsUser", umlsUser );
-            builder.set( "ctakes.umlsuser", umlsUser );
-         }
-         final String umlsPass = options.getUmlsPassword();
-         if ( !umlsPass.isEmpty() ) {
-            builder.set( "umlsPass", umlsPass );
-            builder.set( "ctakes.umlspw", umlsPass );
-         }
          // load the piper file
          reader.setCliOptionals( options );
          reader.loadPipelineFile( options.getPiperPath() );

Modified: ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java (original)
+++ ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java Wed Aug  9 14:34:35 2017
@@ -34,7 +34,7 @@ interface StandardCliOptions {
    @Option(
          shortName = "s",
          longName = "subDir",
-         description = "path to a subdirectory for input and/or output.",
+         description = "path to a subdirectory for output files.",
          defaultValue = "" )
    String getSubDirectory();
 

Added: ctakes/trunk/ctakes-dictionary-lookup-fast-res/src/main/resources/org/apache/ctakes/dictionary/lookup/fast/pipeline/DictionarySubPipe.piper
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dictionary-lookup-fast-res/src/main/resources/org/apache/ctakes/dictionary/lookup/fast/pipeline/DictionarySubPipe.piper?rev=1804533&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dictionary-lookup-fast-res/src/main/resources/org/apache/ctakes/dictionary/lookup/fast/pipeline/DictionarySubPipe.piper (added)
+++ ctakes/trunk/ctakes-dictionary-lookup-fast-res/src/main/resources/org/apache/ctakes/dictionary/lookup/fast/pipeline/DictionarySubPipe.piper Wed Aug  9 14:34:35 2017
@@ -0,0 +1,10 @@
+//  Commands and parameters to create a default dictionary lookup sub-pipeline.  This is not a full pipeline.
+
+// path to the xml file containing information for dictionary lookup configuration.
+cli LookupXml=l
+// umls credentials
+cli umlsUser=user
+cli umlsPass=pass
+
+// Default fast dictionary lookup
+add DefaultJCasTermAnnotator

Modified: ctakes/trunk/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/util/UmlsUserApprover.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/util/UmlsUserApprover.java?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/util/UmlsUserApprover.java (original)
+++ ctakes/trunk/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/util/UmlsUserApprover.java Wed Aug  9 14:34:35 2017
@@ -63,7 +63,8 @@ public enum UmlsUserApprover {
    static final private Logger LOGGER = Logger.getLogger( "UmlsUserApprover" );
 
    static final private String CHANGEME = "CHANGEME";
-   
+   static final private String CHANGE_ME = "CHANGE_ME";
+
    // cache of valid users
    static private final Collection<String> _validUsers = new ArrayList<>();
 
@@ -84,12 +85,18 @@ public enum UmlsUserApprover {
          vendor = properties.getProperty( VENDOR_PARAM );
       }
       String user = EnvironmentVariable.getEnv( UMLSUSER_PARAM, uimaContext );
-      if ( user == null || user.equals( EnvironmentVariable.NOT_PRESENT ) ) {
-         user = properties.getProperty( USER_PARAM );
+      if ( user == null || user.equals( EnvironmentVariable.NOT_PRESENT ) || user.equals( CHANGEME ) || user.equals( CHANGE_ME ) ) {
+         user = EnvironmentVariable.getEnv( USER_PARAM, uimaContext );
+         if ( user == null || user.equals( EnvironmentVariable.NOT_PRESENT ) || user.equals( CHANGEME ) || user.equals( CHANGE_ME ) ) {
+            user = properties.getProperty( USER_PARAM );
+         }
       }
       String pass = EnvironmentVariable.getEnv( UMLSPW_PARAM, uimaContext );
-      if ( pass == null || pass.equals( EnvironmentVariable.NOT_PRESENT ) ) {
-         pass = properties.getProperty( PASS_PARAM );
+      if ( pass == null || pass.equals( EnvironmentVariable.NOT_PRESENT ) || pass.equals( CHANGEME ) || pass.equals( CHANGE_ME ) ) {
+         pass = EnvironmentVariable.getEnv( PASS_PARAM, uimaContext );
+         if ( pass == null || pass.equals( EnvironmentVariable.NOT_PRESENT ) || pass.equals( CHANGEME ) || pass.equals( CHANGE_ME ) ) {
+            pass = properties.getProperty( PASS_PARAM );
+         }
       }
       return isValidUMLSUser( umlsUrl, vendor, user, pass );
    }
@@ -109,6 +116,19 @@ public enum UmlsUserApprover {
       if ( _validUsers.contains( cacheCode ) ) {
          return true;
       }
+      // Potentially someone could have a user ID of CHANGEME or a password of CHANGEME but don't allow those
+      // to make it easy for us to detect that the user or password was not set correctly.
+      if ( user.equals( CHANGEME ) || user.equals( CHANGE_ME ) ) {
+         LOGGER.info( "Not checking UMLS Account for user " + user + ":" );
+         LOGGER.error( "  User " + user + " not allowed, verify you are setting " + USER_PARAM + " or " + UMLSUSER_PARAM + " properly." );
+         return false;
+      }
+      if ( pass.equals( CHANGEME ) || pass.equals( CHANGE_ME ) ) {
+         LOGGER.info( "Not checking UMLS Account for user " + user + " password " + pass );
+         LOGGER.error( "  Password " + pass + " not allowed, verify you are setting " + PASS_PARAM + " or " + UMLSPW_PARAM + " properly." );
+         return false;
+      }
+
       String data;
       try {
          data = URLEncoder.encode( "licenseCode", "UTF-8" ) + "=" + URLEncoder.encode( vendor, "UTF-8" );
@@ -118,19 +138,6 @@ public enum UmlsUserApprover {
          LOGGER.error( "Could not encode URL for " + user + " with vendor license " + vendor );
          return false;
       }
-      
-      // Potentially someone could have a user ID of CHANGEME or a password of CHANGEME but don't allow those
-      // to make it easy for us to detect that the user or password was not set correctly.
-      if (user.equals(CHANGEME)) {
-    	  LOGGER.info( "Not checking UMLS Account for user " + user + ":" );
-    	  LOGGER.error("  User " + CHANGEME + " not allowed, verify you are setting " + USER_PARAM + " or " + UMLSUSER_PARAM + " properly.");
-    	  return false;
-      }
-      if (pass.equals(CHANGEME)) {
-    	  LOGGER.info( "Not checking UMLS Account for user " + user + " password " + pass );
-    	  LOGGER.error("  Password " + CHANGEME + " not allowed, verify you are setting " + PASS_PARAM + " or " + UMLSPW_PARAM + " properly.");
-    	  return false;
-      }
 
       try ( DotLogger dotter = new DotLogger() ) {
          LOGGER.info( "Checking UMLS Account at " + umlsUrl + " for user " + user + ":" );

Modified: ctakes/trunk/ctakes-examples/pom.xml
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-examples/pom.xml?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-examples/pom.xml (original)
+++ ctakes/trunk/ctakes-examples/pom.xml Wed Aug  9 14:34:35 2017
@@ -30,9 +30,10 @@
   <name>ctakes-examples</name>
   <description>Apache cTAKES Examples</description>
   <dependencies>
+      <!--  coreference module has dependencies on almost everything, use it to maximize example possibilities.  -->
     <dependency>
       <groupId>org.apache.ctakes</groupId>
-      <artifactId>ctakes-clinical-pipeline</artifactId>
+        <artifactId>ctakes-coreference</artifactId>
     </dependency>
      <dependency>
         <groupId>org.apache.ctakes</groupId>

Modified: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileChooserPanel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileChooserPanel.java?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileChooserPanel.java (original)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileChooserPanel.java Wed Aug  9 14:34:35 2017
@@ -15,6 +15,7 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Paths;
 
 /**
  * @author SPF , chip-nlp
@@ -63,7 +64,10 @@ final public class FileChooserPanel exte
          super( "Select " + (selectDir ? "Directory" : "File") );
          __textComponent = textComponent;
          __chooser = new JFileChooser();
-         final String cwdPath = System.getProperty( "user.dir" );
+         String cwdPath = Paths.get( "" ).toAbsolutePath().toFile().getPath();
+         if ( cwdPath.isEmpty() ) {
+            cwdPath = System.getProperty( "user.dir" );
+         }
          if ( cwdPath != null && !cwdPath.isEmpty() ) {
             __chooser.setCurrentDirectory( new File( cwdPath ) );
          }

Modified: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileTableCellEditor.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileTableCellEditor.java?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileTableCellEditor.java (original)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/FileTableCellEditor.java Wed Aug  9 14:34:35 2017
@@ -10,6 +10,7 @@ import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.File;
+import java.nio.file.Paths;
 
 /**
  * @author SPF , chip-nlp
@@ -33,7 +34,10 @@ final public class FileTableCellEditor e
       _button.setToolTipText( "Select File" );
       _button.addActionListener( this );
       _chooser = new JFileChooser();
-      final String cwdPath = System.getProperty( "user.dir" );
+      String cwdPath = Paths.get( "" ).toAbsolutePath().toFile().getPath();
+      if ( cwdPath.isEmpty() ) {
+         cwdPath = System.getProperty( "user.dir" );
+      }
       if ( cwdPath != null && !cwdPath.isEmpty() ) {
          _chooser.setCurrentDirectory( new File( cwdPath ) );
       }

Modified: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperRunnerPanel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperRunnerPanel.java?rev=1804533&r1=1804532&r2=1804533&view=diff
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperRunnerPanel.java (original)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperRunnerPanel.java Wed Aug  9 14:34:35 2017
@@ -61,20 +61,25 @@ final public class PiperRunnerPanel exte
    private JButton _parmButton;
    private JButton _runButton;
 
-   private final String[] STANDARD_CHARS = { "i", "o", "s", "l", "-user", "-pass", "-xmiOut" };
+   //   private final String[] STANDARD_CHARS = { "i", "o", "s", "l", "-user", "-pass", "-xmiOut" };
+   private final String[] STANDARD_CHARS = { "i", "o" };
+   private final String[] STANDARD_NAMES = { "InputDirectory", "OutputDirectory" };
 
    private final Map<String, String> _charToName = new HashMap<>( STANDARD_CHARS.length );
    private final Map<String, String> _charToValue = new HashMap<>( STANDARD_CHARS.length );
 
-   private final java.util.List<Character> _cliChars = new ArrayList<>();
-   private final Map<Character, String> _cliCharToName = new HashMap<>();
-   private final Map<Character, String> _cliCharToValue = new HashMap<>();
+   //   private final java.util.List<Character> _cliChars = new ArrayList<>();
+//private final Map<Character, String> _cliCharToName = new HashMap<>();
+//   private final Map<Character, String> _cliCharToValue = new HashMap<>();
+   private final java.util.List<String> _cliChars = new ArrayList<>();
+   private final Map<String, String> _cliCharToName = new HashMap<>();
+   private final Map<String, String> _cliCharToValue = new HashMap<>();
 
 
    PiperRunnerPanel() {
       super( new BorderLayout() );
-      final String[] STANDARD_NAMES = { "InputDirectory", "OutputDirectory", "SubDirectory",
-            "LookupXml", "UMLS Username", "UMLS Password", "XMI Output" };
+//      final String[] STANDARD_NAMES = { "InputDirectory", "OutputDirectory", "SubDirectory",
+//            "LookupXml", "UMLS Username", "UMLS Password", "XMI Output" };
       for ( int i = 0; i < STANDARD_CHARS.length; i++ ) {
          _charToName.put( STANDARD_CHARS[ i ], STANDARD_NAMES[ i ] );
       }
@@ -93,6 +98,14 @@ final public class PiperRunnerPanel exte
       _piperChooser.setFileView( new PiperFileView() );
       _parmChooser.setFileFilter( new FileNameExtensionFilter( "Pipeline Definition (Piper) Parameter File", CLI_EXTENSION ) );
       _parmChooser.setFileView( new PiperFileView() );
+      String cwdPath = Paths.get( "" ).toAbsolutePath().toFile().getPath();
+      if ( cwdPath.isEmpty() ) {
+         cwdPath = System.getProperty( "user.dir" );
+      }
+      if ( cwdPath != null && !cwdPath.isEmpty() ) {
+         _piperChooser.setCurrentDirectory( new File( cwdPath ) );
+         _parmChooser.setCurrentDirectory( new File( cwdPath ) );
+      }
    }
 
    private JToolBar createToolBar() {
@@ -198,13 +211,18 @@ final public class PiperRunnerPanel exte
             if ( row < STANDARD_CHARS.length ) {
                return _charToName.get( STANDARD_CHARS[ row ] );
             }
-            final Character c = _cliChars.get( row - STANDARD_CHARS.length );
+//            final Character c = _cliChars.get( row - STANDARD_CHARS.length );
+            final String c = _cliChars.get( row - STANDARD_CHARS.length );
             return _cliCharToName.getOrDefault( c, "Unknown Name" );
          } else if ( column == 1 ) {
             if ( row < STANDARD_CHARS.length ) {
                return "-" + STANDARD_CHARS[ row ];
             }
-            return "-" + _cliChars.get( row - STANDARD_CHARS.length );
+            final String cliChar = _cliChars.get( row - STANDARD_CHARS.length );
+            if ( cliChar.length() == 1 ) {
+               return "-" + cliChar;
+            }
+            return "--" + cliChar;
          } else if ( column == 2 ) {
             if ( row < STANDARD_CHARS.length ) {
                return _charToValue.getOrDefault( STANDARD_CHARS[ row ], "" );
@@ -291,6 +309,9 @@ final public class PiperRunnerPanel exte
       _cliChars.clear();
       _cliCharToName.clear();
       _cliCharToValue.clear();
+      for ( int i = 0; i < STANDARD_CHARS.length; i++ ) {
+         _charToName.put( STANDARD_CHARS[ i ], STANDARD_NAMES[ i ] );
+      }
       if ( !loadPiperCli( reader, text ) ) {
          error( "Could not load Piper File: " + path );
          return;
@@ -317,15 +338,17 @@ final public class PiperRunnerPanel exte
             final String[] allValues = line.substring( 4 ).split( "\\s+" );
             for ( String allValue : allValues ) {
                final String[] values = allValue.split( "=" );
-               if ( values.length != 2 || values[ 1 ].length() != 1 ) {
+               if ( values.length != 2 ) {
                   error( "Illegal cli values: " + line );
                   return false;
                }
-               if ( _cliCharToName.put( values[ 1 ].charAt( 0 ), values[ 0 ] ) != null ) {
+//               if ( _cliCharToName.put( values[ 1 ].charAt( 0 ), values[ 0 ] ) != null ) {
+               if ( _cliCharToName.put( values[ 1 ], values[ 0 ] ) != null ) {
                   error( "Repeated cli value: " + line );
                   return false;
                }
-               _cliChars.add( values[ 1 ].charAt( 0 ) );
+//               _cliChars.add( values[ 1 ].charAt( 0 ) );
+               _cliChars.add( values[ 1 ] );
             }
          } else if ( line.startsWith( "package " ) && line.length() > 9 ) {
             final String packagePath = line.substring( 8 );
@@ -354,6 +377,9 @@ final public class PiperRunnerPanel exte
       _cliChars.clear();
       _cliCharToName.clear();
       _cliCharToValue.clear();
+      for ( int i = 0; i < STANDARD_CHARS.length; i++ ) {
+         _charToName.put( STANDARD_CHARS[ i ], STANDARD_NAMES[ i ] );
+      }
       _runButton.setEnabled( false );
       _cliTable.revalidate();
       _cliTable.repaint();
@@ -400,8 +426,10 @@ final public class PiperRunnerPanel exte
          final String chars = values[ 0 ].substring( 1 );
          if ( _charToName.containsKey( chars ) ) {
             _charToValue.put( chars, values[ 1 ] );
-         } else if ( chars.length() == 1 && _cliChars.contains( chars.charAt( 0 ) ) ) {
-            _cliCharToValue.put( chars.charAt( 0 ), values[ 1 ] );
+//         } else if ( chars.length() == 1 && _cliChars.contains( chars.charAt( 0 ) ) ) {
+//            _cliCharToValue.put( chars.charAt( 0 ), values[ 1 ] );
+         } else if ( _cliChars.contains( chars ) ) {
+            _cliCharToValue.put( chars, values[ 1 ] );
          } else {
             LOGGER.warn( "Unknown parameter: " + values[0] );
          }
@@ -409,6 +437,7 @@ final public class PiperRunnerPanel exte
          final String chars = getStringKey( _charToName, values[ 0 ] );
          _charToValue.put( chars, values[ 1 ] );
       } else if ( _cliCharToName.containsValue( values[ 0 ] ) ) {
+//         _cliCharToValue.put( getCharKey( _cliCharToName, values[ 0 ] ), values[ 1 ] );
          _cliCharToValue.put( getCharKey( _cliCharToName, values[ 0 ] ), values[ 1 ] );
       } else {
          LOGGER.warn( "Unknown parameter: " + values[ 0 ] );
@@ -423,12 +452,20 @@ final public class PiperRunnerPanel exte
             .orElse( "" );
    }
 
-   private Character getCharKey( final Map<Character, String> map, final String value ) {
+//   private Character getCharKey( final Map<Character, String> map, final String value ) {
+//      return map.entrySet().stream()
+//            .filter( e -> value.equals( e.getValue() ) )
+//            .map( Map.Entry::getKey )
+//            .findAny()
+//            .orElse( ' ' );
+//   }
+
+   private String getCharKey( final Map<String, String> map, final String value ) {
       return map.entrySet().stream()
             .filter( e -> value.equals( e.getValue() ) )
             .map( Map.Entry::getKey )
             .findAny()
-            .orElse( ' ' );
+            .orElse( "" );
    }
 
    private final class SaveParmAction implements ActionListener {
@@ -491,10 +528,15 @@ final public class PiperRunnerPanel exte
                args.add( value );
             }
          }
-         for ( Character cli : _cliChars ) {
+//         for ( Character cli : _cliChars ) {
+         for ( String cli : _cliChars ) {
             final String value = _cliCharToValue.get( cli );
             if ( value != null && !value.isEmpty() ) {
-               args.add( "-" + cli );
+               if ( cli.length() == 1 ) {
+                  args.add( "-" + cli );
+               } else {
+                  args.add( "--" + cli );
+               }
                args.add( value );
             }
          }