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 2019/11/30 19:05:57 UTC

svn commit: r1870640 [1/4] - in /ctakes/trunk/ctakes-dockhand: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/ctakes/ src/main/java/org/apache/ctakes/dockhand/ src/main/java/org/apache/ctakes/dock...

Author: seanfinan
Date: Sat Nov 30 19:05:56 2019
New Revision: 1870640

URL: http://svn.apache.org/viewvc?rev=1870640&view=rev
Log:
Simple ctakes installer gui.
Right now it can create a docker rest installation and a local binary installation.
Rest installation needs more testing.
Possible future types are docker binary and local rest.
Installations have user-definable simple common pipelines.
Pipelines can be expanded in the future.
The jar is completely standalone and the sole needed distributable.  Double-click the jar to launch the gui.

Added:
    ctakes/trunk/ctakes-dockhand/   (with props)
    ctakes/trunk/ctakes-dockhand/pom.xml
    ctakes/trunk/ctakes-dockhand/src/
    ctakes/trunk/ctakes-dockhand/src/main/
    ctakes/trunk/ctakes-dockhand/src/main/java/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/BaseInstaller.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/InstallHelper.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/LocalInstallBuilder.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/MavenHelper.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/RestDockerBuilder.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/DisablerPane.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/MainPanel.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/SinglePackageFabricator.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Feature.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/FeatureComponent.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/GoalPom.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Option.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/Output.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/OutputComponent.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DescriptionStep.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardController.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardStep.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/FeaturesStep.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/InstallTypeStep.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/OutputStep.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/progress/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/progress/NoteMarkupProgressUI.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/progress/NoteProgressDialog.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/progress/ProgressNote.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/AbstractWizardStep.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/ContentsPanel.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/NavigationPanel.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/SummaryStep.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/TocPanel.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/WizardController.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/WizardPanel.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/WizardStep.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/util/
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/util/DialogUtil.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/util/RunnerUtil.java
    ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/gui/wizard/util/SystemUtil.java
    ctakes/trunk/ctakes-dockhand/src/main/resources/
    ctakes/trunk/ctakes-dockhand/src/main/resources/LICENSE
    ctakes/trunk/ctakes-dockhand/src/main/resources/NOTICE
    ctakes/trunk/ctakes-dockhand/src/main/resources/log4j.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/binary/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/binary/RunPipeline.bat
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/binary/RunPipeline.sh
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/docker/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/docker/Dockerfile
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/attribute_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/build.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/coreference_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/entity_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/relation_coref_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/relation_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/relation_temporal_coreference_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/relation_temporal_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/temporal_coref_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/temporal_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/local/pom/token_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/attribute_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/coreference_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/entity_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/relation_coref_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/relation_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/relation_temporal_coreference_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/relation_temporal_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/temporal_coref_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/temporal_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/goal/rest/pom/token_pom.xml
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/rest/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/dockhand/rest/TinyRestPipeline.piper
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/ctakes_logo.jpg   (with props)
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/progress/
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/progress/TextProcess_200g_0.gif   (with props)
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/progress/TextProcess_200g_1.gif   (with props)
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/progress/TextProcess_200g_2.gif   (with props)
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/progress/TextProcess_200g_3.gif   (with props)
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/progress/TextProcess_200g_4.gif   (with props)
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/progress/TextProcess_200g_5.gif   (with props)
    ctakes/trunk/ctakes-dockhand/src/main/resources/org/apache/ctakes/image/progress/TextProcess_200g_6.gif   (with props)

Propchange: ctakes/trunk/ctakes-dockhand/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Sat Nov 30 19:05:56 2019
@@ -0,0 +1 @@
+target

Added: ctakes/trunk/ctakes-dockhand/pom.xml
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/pom.xml?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/pom.xml (added)
+++ ctakes/trunk/ctakes-dockhand/pom.xml Sat Nov 30 19:05:56 2019
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+   <artifactId>ctakes-dockhand</artifactId>
+   <name>Apache cTAKES Dockhand</name>
+   <parent>
+      <groupId>org.apache.ctakes</groupId>
+      <artifactId>ctakes</artifactId>
+      <version>4.0.1-SNAPSHOT</version>
+   </parent>
+   <dependencies>
+
+   </dependencies>
+   <build>
+      <plugins>
+
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-jar-plugin</artifactId>
+            <version>2.4</version>
+            <configuration>
+               <archive>
+                  <manifest>
+                     <mainClass>org.apache.ctakes.dockhand.gui.SinglePackageFabricator</mainClass>
+                  </manifest>
+               </archive>
+            </configuration>
+         </plugin>
+
+      </plugins>
+   </build>
+</project>

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/BaseInstaller.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/BaseInstaller.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/BaseInstaller.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/BaseInstaller.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,84 @@
+package org.apache.ctakes.dockhand.build;
+
+
+import org.apache.ctakes.gui.wizard.util.DialogUtil;
+import org.apache.ctakes.gui.wizard.util.RunnerUtil;
+import org.apache.ctakes.gui.wizard.util.SystemUtil;
+
+import java.io.*;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+
+import static org.apache.ctakes.gui.wizard.util.SystemUtil.NO_FILE;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 11/10/2019
+ */
+final public class BaseInstaller implements Callable<File> {
+
+   static private final String PIPER_NAME = "DockhandPipeline.piper";
+
+   private final String _installType;
+   private final String _sourceDirUrl;
+   private final String _goalPomFile;
+   private final String _piperCommands;
+   private final String[] _extraFiles;
+   private File _installDir;
+
+   public BaseInstaller( final String installType,
+                         final String sourceDirUrl,
+                         final String goalPomFile,
+                         final Collection<String> piperCommands,
+                         final String... extraFiles ) {
+      _installType = installType;
+      _sourceDirUrl = sourceDirUrl;
+      _goalPomFile = goalPomFile;
+      _piperCommands = String.join( "\n", piperCommands );
+      _extraFiles = extraFiles;
+   }
+
+
+   public boolean install() {
+      final File installDir = InstallHelper.getInstance().chooseInstallDir();
+      if ( installDir.equals( NO_FILE ) ) {
+         DialogUtil.showInstallCanceled( _installType );
+         return false;
+      }
+      _installDir = installDir;
+
+      RunnerUtil.runWithProgress( "Installing " + _installType + " ...", this );
+      return true;
+   }
+
+   public File call() {
+      final String installPath = _installDir.getAbsolutePath();
+      new File( installPath ).mkdirs();
+
+      final String piperPath = installPath + "/" + PIPER_NAME;
+      try ( Writer writer = new BufferedWriter( new FileWriter( piperPath ) ) ) {
+         writer.write( _piperCommands + "\n" );
+      } catch ( IOException ioE ) {
+         DialogUtil.showError( ioE.getMessage() );
+      }
+      copyToDisk( _sourceDirUrl + "pom/" + _goalPomFile, installPath + "/pom.xml" );
+      copyToDisk( "/log4j.xml", installPath + "/log4j.xml" );
+      copyToDisk( "/LICENSE", installPath + "/LICENSE" );
+      copyToDisk( "/NOTICE", installPath + "/NOTICE" );
+
+      for ( String file : _extraFiles ) {
+         final String name = new File( file ).getName();
+         copyToDisk( file, installPath + "/" + name );
+      }
+
+      return _installDir;
+   }
+
+   private void copyToDisk( final String source, final String filePath ) {
+      SystemUtil.copyToDisk( getClass().getResourceAsStream( source ), Paths.get( filePath ) );
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/InstallHelper.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/InstallHelper.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/InstallHelper.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/InstallHelper.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,40 @@
+package org.apache.ctakes.dockhand.build;
+
+import org.apache.ctakes.gui.wizard.util.DialogUtil;
+
+import java.io.File;
+
+import static org.apache.ctakes.gui.wizard.util.SystemUtil.NO_FILE;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 11/3/2019
+ */
+public enum InstallHelper {
+   INSTANCE;
+
+   static public InstallHelper getInstance() {
+      return INSTANCE;
+   }
+
+
+   private File _installDir = new File( System.getProperty( "user.dir" ) );
+
+   public File getInstallDir() {
+      return _installDir;
+   }
+
+
+   public File chooseInstallDir() {
+      final File installDir = DialogUtil.chooseSaveDir();
+      if ( installDir == null ) {
+         return NO_FILE;
+      }
+      _installDir = installDir;
+      return _installDir;
+   }
+
+
+}
+

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/LocalInstallBuilder.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/LocalInstallBuilder.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/LocalInstallBuilder.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/LocalInstallBuilder.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,71 @@
+package org.apache.ctakes.dockhand.build;
+
+import org.apache.ctakes.dockhand.gui.feature.GoalPom;
+import org.apache.ctakes.dockhand.gui.wizard.DhWizardController;
+import org.apache.ctakes.gui.wizard.util.DialogUtil;
+
+import java.util.Collection;
+
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/26/2019
+ */
+final public class LocalInstallBuilder implements Runnable {
+
+   static private final String INSTALL_TYPE = "Apache cTAKES Local";
+
+   static private final String BINARY_DIR = "/org/apache/ctakes/dockhand/binary/";
+   static private final String SOURCE_URLDIR = "/org/apache/ctakes/dockhand/goal/local/";
+
+
+   private final DhWizardController _wizardController;
+
+   public LocalInstallBuilder( final DhWizardController wizardController ) {
+      _wizardController = wizardController;
+   }
+
+   public void run() {
+      final GoalPom goalPom = _wizardController.getGoalPom();
+      final Collection<String> piperCommands = _wizardController.getPiperCommands();
+
+      final BaseInstaller baseInstaller
+            = new BaseInstaller( INSTALL_TYPE,
+            SOURCE_URLDIR, goalPom.getPomFile(), piperCommands,
+            SOURCE_URLDIR + "pom/build.xml",
+            BINARY_DIR + "RunPipeline.sh",
+            BINARY_DIR + "RunPipeline.bat" );
+
+      final boolean install = baseInstaller.install();
+      if ( !install ) {
+         return;
+      }
+
+      final boolean maven = MavenHelper.getInstance().installMaven();
+      if ( !maven ) {
+         return;
+      }
+
+      final String installPath = InstallHelper.getInstance().getInstallDir().getAbsolutePath();
+      final boolean finished = MavenHelper.getInstance().packagePom( installPath );
+      if ( finished ) {
+         DialogUtil.showInstalledDialog( INSTALL_TYPE, installPath );
+      }
+   }
+
+   // TODO  Local src/bin Installation, Local Rest WAR, Installation Docker, Rest Docker.
+
+
+   // TODO  For local source installations, instead of doing svn etc., ask which ide.
+   //  Then go step-by-step opening the web page with help on that step and indicating svn repo address.
+   //  :
+   //  Follow the instructions at:
+   //    https://www.jetbrains.com/help/idea/checking-out-files-from-subversion-repository.html
+   //  using the svn repository
+   //    https://svn.apache.org/repos/asf/ctakes/trunk/
+   //    or
+   //    https://www.eclipse.org/subversive/
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/MavenHelper.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/MavenHelper.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/MavenHelper.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/MavenHelper.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,132 @@
+package org.apache.ctakes.dockhand.build;
+
+import org.apache.ctakes.gui.wizard.util.DialogUtil;
+import org.apache.ctakes.gui.wizard.util.RunnerUtil;
+
+import java.io.File;
+
+import static org.apache.ctakes.gui.wizard.util.SystemUtil.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 11/3/2019
+ */
+public enum MavenHelper {
+   INSTANCE;
+
+   static public MavenHelper getInstance() {
+      return INSTANCE;
+   }
+
+   static private final String MAVEN_TITLE = "Apache Maven";
+
+   static private final String MAVEN_URL
+         = "https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.3.1/apache-maven-3.3.1-bin.zip";
+
+
+   private File _mavenDir;
+
+   public File getMavenDir() {
+      if ( _mavenDir != null ) {
+         final String mavenDirPath = _mavenDir.getAbsolutePath();
+         if ( !mavenDirPath.endsWith( File.pathSeparator + "bin" + File.pathSeparator ) ) {
+            return new File( _mavenDir, "apache-maven-3.3.1/bin" );
+         }
+         return _mavenDir;
+      }
+      return NO_FILE;
+   }
+
+
+//   public void installMaven() {
+//      if ( !getMavenPath().equals( FILE_NOT_FOUND ) ) {
+//         return;
+//      }
+//      DialogUtil.initInstall();
+//      final boolean doInstall = DialogUtil.chooseSecondaryInstall( "Apache Maven" );
+//      if ( !doInstall ) {
+//         DialogUtil.showInstallCanceled( "Apache Maven" );
+//         return;
+//      }
+//      final File mavenInstallDir = MavenHelper.getInstance().chooseMavenDir();
+//      if ( mavenInstallDir.equals( NO_FILE ) ) {
+//         DialogUtil.showInstallCanceled( "Apache Maven" );
+//         return;
+//      }
+//      // TODO Progress Dialog.
+//      try {
+//         final File mavenZip = SystemUtil.downloadZipFile( MAVEN_URL );
+//         unzipit( mavenZip, mavenInstallDir );
+//      } catch ( IOException ioE ) {
+//         DialogUtil.showError( ioE.getMessage() );
+//         return;
+//      }
+//      _mavenDir = mavenInstallDir;
+//      DialogUtil.showInstallComplete( "Apache Maven", mavenInstallDir.getAbsolutePath() );
+//   }
+
+   public boolean installMaven() {
+      if ( !getMavenPath().equals( FILE_NOT_FOUND ) ) {
+         return true;
+      }
+      final boolean doInstall = DialogUtil.chooseSecondaryInstall( MAVEN_TITLE );
+      if ( !doInstall ) {
+         DialogUtil.showCanceledDialog( MAVEN_TITLE );
+         return false;
+      }
+      final File mavenInstallDir = MavenHelper.getInstance().chooseMavenDir();
+      if ( mavenInstallDir.equals( NO_FILE ) ) {
+         DialogUtil.showCanceledDialog( MAVEN_TITLE );
+         return false;
+      }
+      try {
+         final FileDownloader downloader = new FileDownloader( MAVEN_URL );
+         final File mavenZip = RunnerUtil.runWithProgress( "Downloading " + MAVEN_TITLE + " ...", downloader );
+
+         final FileUnzipper unzipper = new FileUnzipper( mavenZip, mavenInstallDir );
+         final File installedDir = RunnerUtil.runWithProgress( "Unzipping " + MAVEN_TITLE + " ...", unzipper );
+      } catch ( Exception e ) {
+         DialogUtil.showError( e.getMessage() );
+         return false;
+      }
+      _mavenDir = mavenInstallDir;
+      DialogUtil.showInstalledDialog( MAVEN_TITLE, mavenInstallDir.getAbsolutePath() );
+      return true;
+   }
+
+
+   public File chooseMavenDir() {
+      final File mavenDir = DialogUtil.chooseSaveDir();
+      if ( mavenDir == null ) {
+         return NO_FILE;
+      }
+      _mavenDir = mavenDir;
+      return _mavenDir;
+   }
+
+
+   static private String getMavenPath() {
+      final String os = System.getProperty( "os.name" );
+      if ( os.toLowerCase().contains( "windows" ) ) {
+         return findExecutableOnPath( "mvn.cmd" );
+      }
+      return findExecutableOnPath( "mvn" );
+   }
+
+
+   public boolean packagePom( final String pomDirectory ) {
+      try {
+         final CommandRunner packager
+               = new CommandRunner( pomDirectory, getMavenDir().getAbsolutePath() + "/mvn package" );
+         final Boolean packaged = RunnerUtil.runWithProgress( "Running " + MAVEN_TITLE + " ...", packager );
+      } catch ( Exception e ) {
+         DialogUtil.showError( e.getMessage() );
+         return false;
+      }
+      return true;
+   }
+
+
+}
+

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/RestDockerBuilder.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/RestDockerBuilder.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/RestDockerBuilder.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/build/RestDockerBuilder.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,54 @@
+package org.apache.ctakes.dockhand.build;
+
+import org.apache.ctakes.dockhand.gui.feature.GoalPom;
+import org.apache.ctakes.dockhand.gui.wizard.DhWizardController;
+import org.apache.ctakes.gui.wizard.util.DialogUtil;
+
+import java.util.Collection;
+
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/26/2019
+ */
+final public class RestDockerBuilder implements Runnable {
+
+   static private final String INSTALL_TYPE = "Apache cTAKES Rest Docker";
+
+   static private final String DOCKER_DIR = "/org/apache/ctakes/dockhand/docker/";
+   static private final String REST_DIR = "/org/apache/ctakes/dockhand/rest/";
+   static private final String SOURCE_URLDIR = "/org/apache/ctakes/dockhand/goal/rest/";
+
+
+   private final DhWizardController _wizardController;
+
+   public RestDockerBuilder( final DhWizardController wizardController ) {
+      _wizardController = wizardController;
+   }
+
+   public void run() {
+      final GoalPom goalPom = _wizardController.getGoalPom();
+      final Collection<String> piperCommands = _wizardController.getPiperCommands();
+
+      final BaseInstaller baseInstaller
+            = new BaseInstaller( INSTALL_TYPE,
+            SOURCE_URLDIR, goalPom.getPomFile(), piperCommands,
+            DOCKER_DIR + "Dockerfile",
+            REST_DIR + "TinyRestPipeline.piper" );
+
+      final boolean finished = baseInstaller.install();
+      if ( finished ) {
+         final String installPath = InstallHelper.getInstance().getInstallDir().getAbsolutePath();
+         DialogUtil.showInstalledDialog( INSTALL_TYPE, installPath );
+      }
+   }
+
+   // TODO   Maybe the rest could output html if the css and js are specified in index.jsp ??
+
+   // TODO  Local src/bin Installation, Local Rest WAR, Installation Docker, Rest Docker.
+
+   // TODO set the Buildable boolean supplier in wizard controller
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/DisablerPane.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/DisablerPane.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/DisablerPane.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/DisablerPane.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,228 @@
+package org.apache.ctakes.dockhand.gui;
+
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.logging.Logger;
+
+/**
+ * A Panel that makes everything on the GUI "disabled".
+ * Useful when there is a resource-heavy thread running and GUI interaction is undesirable.
+ * <p>
+ * Though I normally wouldn't do so ... this was copied from ctakes-gui.
+ *
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 11/29/2016
+ */
+public final class DisablerPane extends JPanel implements MouseListener,
+                                                          MouseMotionListener,
+                                                          FocusListener {
+
+   static public DisablerPane getInstance() {
+      return InstanceHolder.INSTANCE;
+   }
+
+   static private final class InstanceHolder {
+      static private final DisablerPane INSTANCE = new DisablerPane();
+   }
+
+   static private final Logger LOGGER = Logger.getLogger( "DisablerPane" );
+
+   private JMenuBar _menuBar;
+   private Container _contentPane;
+
+   private boolean _dragging = false;
+   private boolean _needToRedispatch = false;
+
+   private DisablerPane() {
+      addMouseListener( this );
+      addMouseMotionListener( this );
+      addFocusListener( this );
+      setOpaque( false );
+      setVisible( false );
+   }
+
+   /**
+    * The DisablerPane must be initialized before it can be used
+    *
+    * @param frame -
+    */
+   public void initialize( final JFrame frame ) {
+      _menuBar = frame.getJMenuBar();
+      _contentPane = frame.getContentPane();
+      frame.setGlassPane( this );
+   }
+
+   /**
+    * We only need to redispatch if we're not visible, but having full control
+    * over this might prove handy.
+    */
+   public void setNeedToRedispatch( final boolean need ) {
+      _needToRedispatch = need;
+   }
+
+   /**
+    * Paint partially transparent grey over the frame
+    * {@inheritDoc}
+    */
+   @Override
+   protected void paintComponent( final Graphics g ) {
+      if ( !isVisible() ) {
+         return;
+      }
+      g.setColor( new Color( 127, 127, 127, 83 ) );
+      g.fillRect( 0, 0, getWidth(), getHeight() );
+   }
+
+   /**
+    * Blocks input if visible
+    * {@inheritDoc}
+    */
+   @Override
+   public void setVisible( final boolean visible ) {
+      // Make sure we grab the focus so that key events don't go astray.
+      if ( visible ) {
+         requestFocus();
+      }
+      super.setVisible( visible );
+   }
+
+   /**
+    * Once we have focus, keep it if we're visible
+    * {@inheritDoc}
+    */
+   @Override
+   public void focusLost( final FocusEvent event ) {
+      if ( isVisible() ) {
+         requestFocus();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void focusGained( final FocusEvent event ) {
+   }
+
+   /*
+    * (Based on code from the Java Tutorial) We must forward at least the mouse
+    * drags that started with mouse presses over the check box. Otherwise, when
+    * the user presses the check box then drags off, the check box isn't
+    * disarmed -- it keeps its dark gray background or whatever its L&F uses to
+    * indicate that the button is currently being pressed.
+    */
+   @Override
+   public void mouseDragged( final MouseEvent event ) {
+      if ( _needToRedispatch ) {
+         forwardMouseEvent( event );
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void mouseMoved( final MouseEvent event ) {
+      if ( _needToRedispatch ) {
+         forwardMouseEvent( event );
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void mouseClicked( final MouseEvent event ) {
+      if ( _needToRedispatch ) {
+         forwardMouseEvent( event );
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void mouseEntered( final MouseEvent event ) {
+      if ( _needToRedispatch ) {
+         forwardMouseEvent( event );
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void mouseExited( final MouseEvent event ) {
+      if ( _needToRedispatch ) {
+         forwardMouseEvent( event );
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void mousePressed( final MouseEvent event ) {
+      if ( _needToRedispatch ) {
+         forwardMouseEvent( event );
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void mouseReleased( final MouseEvent event ) {
+      if ( _needToRedispatch ) {
+         forwardMouseEvent( event );
+         _dragging = false;
+      }
+   }
+
+   /**
+    * If there is a mouse event, forward to an underlying component
+    *
+    * @param event -
+    */
+   private void forwardMouseEvent( final MouseEvent event ) {
+      if ( _contentPane == null || _menuBar == null ) {
+         LOGGER.severe( "DisablerPane has not been initialized with a Frame" );
+         return;
+      }
+      boolean inMenuBar = false;
+      final Point point = event.getPoint();
+      Component component;
+      Container container = _contentPane;
+      Point containerPoint = SwingUtilities.convertPoint( this, point, _contentPane );
+      final int eventID = event.getID();
+
+      if ( containerPoint.y < 0 ) {
+         inMenuBar = true;
+         container = _menuBar;
+         containerPoint = SwingUtilities.convertPoint( this, point, _menuBar );
+         isDragging( eventID );
+      }
+      component = SwingUtilities.getDeepestComponentAt( container, containerPoint.x, containerPoint.y );
+      if ( component == null ) {
+         return;
+      } else {
+         isDragging( eventID );
+      }
+      if ( inMenuBar || _dragging ) {
+         final Point componentPoint = SwingUtilities.convertPoint( this, point, component );
+         component.dispatchEvent( new MouseEvent( component, eventID, event.getWhen(), event.getModifiers(),
+               componentPoint.x, componentPoint.y, event.getClickCount(), event.isPopupTrigger() ) );
+      }
+   }
+
+   private void isDragging( final int eventID ) {
+      if ( eventID == MouseEvent.MOUSE_PRESSED ) {
+         _dragging = true;
+      }
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/MainPanel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/MainPanel.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/MainPanel.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/MainPanel.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,36 @@
+package org.apache.ctakes.dockhand.gui;
+
+
+import org.apache.ctakes.dockhand.gui.wizard.*;
+import org.apache.ctakes.gui.wizard.SummaryStep;
+import org.apache.ctakes.gui.wizard.WizardPanel;
+
+import javax.swing.*;
+
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 9/27/2019
+ */
+final public class MainPanel {
+
+
+   private final DhWizardController _wizardController;
+
+
+   public MainPanel( final DhWizardController wizardController ) {
+      _wizardController = wizardController;
+      _wizardController.addStep( new InstallTypeStep( wizardController ) );
+      _wizardController.addStep( new DescriptionStep() );
+      _wizardController.addStep( new FeaturesStep() );
+      _wizardController.addStep( new OutputStep() );
+      _wizardController.addStep( new SummaryStep( wizardController ) );
+   }
+
+   public JComponent createPanel() {
+      return new WizardPanel().createPanel( _wizardController );
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/SinglePackageFabricator.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/SinglePackageFabricator.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/SinglePackageFabricator.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/SinglePackageFabricator.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,68 @@
+package org.apache.ctakes.dockhand.gui;
+
+
+import org.apache.ctakes.dockhand.gui.wizard.DhWizardController;
+
+import javax.swing.*;
+import java.awt.*;
+
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/19/2018
+ */
+final public class SinglePackageFabricator {
+
+
+   // TODO : Copy basic elements (name, packaging, war plugin) from entity pom to other poms.
+
+
+   private SinglePackageFabricator() {
+   }
+
+   static private JFrame createFrame() {
+      final JFrame frame = new JFrame( "cTAKES Single Package Fabricator" );
+      frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
+      // Use 1024 x 768 as the minimum required resolution (XGA)
+      // iPhone 3 : 480 x 320 (3:2, HVGA)
+      // iPhone 4 : 960 x 640  (3:2, unique to Apple)
+      // iPhone 5 : 1136 x 640 (under 16:9, unique to Apple)
+      // iPad 3&4 : 2048 x 1536 (4:3, QXGA)
+      // iPad Mini: 1024 x 768 (4:3, XGA)
+      final Dimension size = new Dimension( 800, 600 );
+      frame.setSize( size );
+      frame.setMinimumSize( size );
+      // TODO - make save/load installation types?
+//      final JMenuBar menuBar = new JMenuBar();
+//      final JMenu fileMenu = new JMenu( "File" );
+//      menuBar.add( fileMenu );
+//
+//      frame.setJMenuBar( menuBar );
+      System.setProperty( "apple.laf.useScreenMenuBar", "true" );
+//      JFrame.setDefaultLookAndFeelDecorated( true );
+      return frame;
+   }
+
+   static private JComponent createMainPanel() {
+      return new MainPanel( new DhWizardController() ).createPanel();
+   }
+
+
+   public static void main( final String... args ) {
+      try {
+         UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
+         UIManager.getDefaults().put( "SplitPane.border", BorderFactory.createEmptyBorder() );
+      } catch ( ClassNotFoundException | InstantiationException
+            | IllegalAccessException | UnsupportedLookAndFeelException multE ) {
+//         LOGGER.severe( multE.getLocalizedMessage() );
+      }
+      final JFrame frame = createFrame();
+      final JComponent mainPanel = createMainPanel();
+      frame.add( mainPanel );
+      frame.pack();
+      frame.setVisible( true );
+      DisablerPane.getInstance().initialize( frame );
+   }
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Feature.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Feature.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Feature.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Feature.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,79 @@
+package org.apache.ctakes.dockhand.gui.feature;
+
+
+import java.util.*;
+
+import static org.apache.ctakes.dockhand.gui.feature.Option.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 9/27/2019
+ */
+public enum Feature {
+   SECTIONS( "Sections", "Split Document by Sections.", SIMPLE_SEGMENT, SPLIT_SECTION ),
+   SENTENCES( "Sentences", "Split Document Text by Sentences.", OPEN_NLP_SENTENCE, PROSE_SENTENCE ),
+   PARAGRAPHS( "Paragraphs", "Split Document Text by Paragraphs.", PARAGRAPH ),
+   LISTS( "Lists", "Detect Formatted Lists and Tables.", LIST ),
+   TOKENS( "Tokens", "Detect Word, Number and other distinct Token Types.", TOKEN ),
+   ENTITIES( "Entities", "Normalize Named Entities.", ENTITY ),
+   ATTRIBUTES( "Attributes", "Add Attributes such as Negation to Entities.", ML_ATTRIBUTE ),
+   EVENTS( "Events", "Detect Temporal Events.", EVENT ),
+   TIMES( "Times", "Detect Time and Date Expressions.", TIME ),
+   DOCTIMEREL( "Relative Event Times", "Determine Relation between Temporal Events and the Time at which the Document was Written.", DOC_TIME_REL ),
+   E_T_LINKS( "Event Times", "Determine Relations between Temporal Events and Times.", E_T_LINK ),
+   E_E_LINKS( "Event Relations", "Determine Relations between Temporal Events and other Events.", E_E_LINK ),
+   LOCATIONS( "Locations", "Determine Locations between Entities.", LOCATION ),
+   SEVERITIES( "Severities", "Determine Severity of Entities.", SEVERITY ),
+   COREFERENCES( "Coreferences", "Determine which Entity mentions refer to the same World Entity.", COREFERENT );
+
+   // TODO Giant file Attributes ?  Uses Windowed ***
+   // TODO Dictionary : Default, Custom.  Allow Custom to either select existing or launch dictionary creator.
+
+   static public final Map<Feature, Collection<Feature>> REQUIREMENTS = new EnumMap<>( Feature.class );
+
+   static {
+      REQUIREMENTS.put( SECTIONS, Collections.emptyList() );
+      REQUIREMENTS.put( SENTENCES, Collections.singleton( SECTIONS ) );
+      REQUIREMENTS.put( PARAGRAPHS, Arrays.asList( SECTIONS, SENTENCES ) );
+      REQUIREMENTS.put( LISTS, Arrays.asList( SECTIONS, SENTENCES ) );
+      REQUIREMENTS.put( TOKENS, Arrays.asList( SECTIONS, SENTENCES ) );
+      REQUIREMENTS.put( ENTITIES, Arrays.asList( SECTIONS, SENTENCES, TOKENS ) );
+      REQUIREMENTS.put( ATTRIBUTES, Arrays.asList( SECTIONS, SENTENCES, TOKENS, ENTITIES ) );
+      REQUIREMENTS.put( LOCATIONS, Arrays.asList( SECTIONS, SENTENCES, TOKENS, ENTITIES ) );
+      REQUIREMENTS.put( SEVERITIES, Arrays.asList( SECTIONS, SENTENCES, TOKENS, ENTITIES ) );
+      REQUIREMENTS.put( EVENTS, Arrays.asList( SECTIONS, SENTENCES, TOKENS, ENTITIES ) );
+      REQUIREMENTS.put( TIMES, Arrays.asList( SECTIONS, SENTENCES, TOKENS, ENTITIES, EVENTS ) );
+      REQUIREMENTS.put( E_T_LINKS, Arrays.asList( SECTIONS, SENTENCES, TOKENS, ENTITIES, EVENTS, TIMES ) );
+      REQUIREMENTS.put( E_E_LINKS, Arrays.asList( SECTIONS, SENTENCES, TOKENS, ENTITIES, EVENTS, TIMES ) );
+      REQUIREMENTS.put( COREFERENCES, Arrays.asList( SECTIONS, SENTENCES, TOKENS, ENTITIES ) );
+   }
+
+
+   private final String _name;
+   private final String _description;
+   private final List<Option> _options;
+
+   Feature( final String name, final String description, final Option... options ) {
+      _name = name;
+      _description = description;
+      _options = Arrays.asList( options );
+   }
+
+   public String getName() {
+      return _name;
+   }
+
+   public String getDescription() {
+      return _description;
+   }
+
+   public List<Option> getOptions() {
+      return _options;
+   }
+
+   public Collection<Feature> getRequirements() {
+      return REQUIREMENTS.getOrDefault( this, Collections.emptyList() );
+   }
+
+}
\ No newline at end of file

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/FeatureComponent.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/FeatureComponent.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/FeatureComponent.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/FeatureComponent.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,84 @@
+package org.apache.ctakes.dockhand.gui.feature;
+
+import org.apache.ctakes.dockhand.gui.wizard.FeaturesStep;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.EnumMap;
+import java.util.Map;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/8/2019
+ */
+final public class FeatureComponent extends JPanel {
+
+   private final Feature _feature;
+   private final JCheckBox _checkBox;
+   private final Map<Option, JRadioButton> _optionButtons = new EnumMap<>( Option.class );
+
+
+   public FeatureComponent( final FeaturesStep.FeatureCheckController controller, final Feature feature ) {
+      super( new BorderLayout() );
+      setBackground( Color.WHITE );
+      _feature = feature;
+      _checkBox = new JCheckBox( feature.getName() );
+      _checkBox.setBackground( Color.WHITE );
+      _checkBox.setToolTipText( feature.getDescription() );
+      add( _checkBox, BorderLayout.NORTH );
+      final java.util.List<Option> options = feature.getOptions();
+      if ( options.size() > 1 ) {
+         final JLabel spacer = new JLabel( "     " );
+         spacer.setMinimumSize( new Dimension( 100, 10 ) );
+         spacer.setSize( new Dimension( 100, 10 ) );
+         add( spacer, BorderLayout.WEST );
+         final JPanel optionPanel = new JPanel( new GridLayout( options.size(), 1 ) );
+         final ButtonGroup optionGroup = new ButtonGroup();
+         for ( Option option : options ) {
+            final JRadioButton radioButton = new JRadioButton( option.getName() );
+            radioButton.setBackground( Color.WHITE );
+            radioButton.setToolTipText( option.getDescription() );
+            optionGroup.add( radioButton );
+            optionPanel.add( radioButton );
+            _optionButtons.put( option, radioButton );
+         }
+         add( optionPanel, BorderLayout.CENTER );
+         _optionButtons.get( options.get( 0 ) ).setSelected( true );
+         if ( options.size() == 1 ) {
+            _optionButtons.get( options.get( 0 ) ).setEnabled( false );
+         }
+      }
+      controller.addFeature( feature, this );
+      _checkBox.addActionListener( controller );
+   }
+
+   public Feature getFeature() {
+      return _feature;
+   }
+
+   public void setSelected( final boolean selected ) {
+      _checkBox.setSelected( selected );
+   }
+
+   public boolean isSelected() {
+      return _checkBox.isSelected();
+   }
+
+   public void setEnabled( final boolean enable ) {
+      _checkBox.setEnabled( enable );
+      _optionButtons.values().forEach( b -> b.setEnabled( enable ) );
+   }
+
+   public Option getSelectedOption() {
+      if ( _feature.getOptions().size() == 1 ) {
+         return _feature.getOptions().get( 0 );
+      }
+      return _optionButtons.entrySet().stream()
+                           .filter( e -> e.getValue().isSelected() )
+                           .map( Map.Entry::getKey )
+                           .findAny()
+                           .orElse( null );
+   }
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/GoalPom.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/GoalPom.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/GoalPom.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/GoalPom.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,64 @@
+package org.apache.ctakes.dockhand.gui.feature;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.apache.ctakes.dockhand.gui.feature.Feature.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 9/27/2019
+ */
+public enum GoalPom {
+   CORE( "token", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS ),
+   LOOKUP( "entity", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES ),
+   ASSERTION( "attribute", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES, ATTRIBUTES ),
+   RELATION( "relation", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES, ATTRIBUTES, LOCATIONS, SEVERITIES ),
+   TEMPORAL( "temporal", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES, ATTRIBUTES, LOCATIONS, SEVERITIES,
+         EVENTS, TIMES, DOCTIMEREL, E_T_LINKS, E_E_LINKS ),
+   COREFERENCE( "coreference", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES, ATTRIBUTES, COREFERENCES ),
+   RELATION_COREF( "relation_coref", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES, ATTRIBUTES, LOCATIONS,
+         SEVERITIES, COREFERENCES ),
+   RELATION_TEMPORAL( "relation_temporal", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES, ATTRIBUTES, LOCATIONS,
+         SEVERITIES, COREFERENCES ),
+   TEMPORAL_COREF( "temporal_coref", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES, ATTRIBUTES,
+         EVENTS, TIMES, DOCTIMEREL, E_T_LINKS, E_E_LINKS, COREFERENCES ),
+   RELATION_TEMPORAL_COREF( "relation_temporal_coref", 10, SECTIONS, SENTENCES, PARAGRAPHS, LISTS, TOKENS, ENTITIES, ATTRIBUTES,
+         LOCATIONS, SEVERITIES, EVENTS, TIMES, DOCTIMEREL, E_T_LINKS, E_E_LINKS, COREFERENCES );
+
+   private final String _goal;
+   private final int _mb;
+   private final Feature[] _layersHandled;
+
+   GoalPom( final String goal, final int mb, final Feature... layersHandled ) {
+      _goal = goal;
+      _mb = mb;
+      _layersHandled = layersHandled;
+   }
+
+   public String getPomFile() {
+      return _goal + "_pom.xml";
+   }
+
+   public int getMegaBytes() {
+      return _mb;
+   }
+
+   public Collection<Feature> getLayersHandled() {
+      return Arrays.asList( _layersHandled );
+   }
+
+   static public GoalPom getAppropriatePom( final Collection<Feature> features ) {
+      GoalPom simplestPom = GoalPom.CORE;
+      for ( GoalPom goalPom : values() ) {
+         if ( goalPom.getLayersHandled().containsAll( features ) ) {
+            simplestPom = goalPom;
+            break;
+         }
+      }
+      return simplestPom;
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Option.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Option.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Option.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/feature/Option.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,191 @@
+package org.apache.ctakes.dockhand.gui.feature;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 9/27/2019
+ */
+public enum Option {
+   SIMPLE_SEGMENT( "Single Section",
+         "Create a single Section that covers the entire document.",
+         "add SimpleSegmentAnnotator" ),
+
+   SPLIT_SECTION( "Multiple Sections",
+         "Create multiple Sections based upon discovered Section Headers.",
+         "add BsvRegexSectionizer" ),
+
+   VALID_SECTION( "Only Valid Sections",
+         "Filter Sections based upon discovered Section Headers.",
+         "add SectionFilter" ),
+
+
+   OPEN_NLP_SENTENCE( "Simple Sentences",
+         "Create Sentences relying upon End of Line characters.",
+         "add SentenceDetector" ),
+
+   PROSE_SENTENCE( "Prose Sentences",
+         "Create Sentences when End of Line characters may not indicate sentence boundaries.",
+         "add SentenceDetectorAnnotatorBIO" //,
+//         "add EolSentenceFixer"
+   ),
+
+
+   PARAGRAPH( "Paragraphs",
+         "Create Paragraphs based upon Whitespace.",
+         "add ParagraphAnnotator",
+         "add ParagraphSentenceFixer" ),
+
+
+   LIST( "Lists",
+         "Create Lists based upon formatted Sections.",
+         "add ListAnnotator",
+//         "add ListParagraphFixer",
+         "add ListSentenceFixer" ),
+
+
+   TOKEN( "Tokens",
+         "Create Word and other Penn TreeBank Tokens.",
+         "add TokenizerAnnotatorPTB" ),
+
+
+   ENTITY( "Entities",
+         "Create Named Entites based upon Dictionary Lookup.",
+         "add ContextDependentTokenizerAnnotator",
+         "addDescription POSTagger",
+         "add Chunker",
+         "addDescription adjuster.ChunkAdjuster NP,NP 1",
+         "addDescription adjuster.ChunkAdjuster NP,PP,NP 2",
+         "// path to the xml file containing information for dictionary lookup configuration.",
+//         "cli LookupXml=l",
+         "// umls credentials",
+         "cli umlsUser=user",
+         "cli umlsPass=pass",
+         "add DefaultJCasTermAnnotator" ),
+
+//   CUSTOM_ENTITY( "Custom Entities",
+//         "Create Custom Named Entites based upon Dictionary Lookup.",
+//         "add ContextDependentTokenizerAnnotator",
+//         "addDescription POSTagger",
+//         "add Chunker",
+//         "addDescription adjuster.ChunkAdjuster NP,NP 1",
+//         "addDescription adjuster.ChunkAdjuster NP,PP,NP 2",
+//         "add DefaultJCasTermAnnotator " + someSpecifiedDictionaryConfigurationXml ),
+
+
+   ML_ATTRIBUTE( "ML Attributes",
+         "Assign Negation, Uncertainty, Historic, Generic, Subject using Machine Learning generated models.",
+         "addDescription ClearNLPDependencyParserAE",
+         "addLogged ClearNLPSemanticRoleLabelerAE",
+         "package org.apache.ctakes.assertion.medfacts.cleartk",
+         "addDescription PolarityCleartkAnalysisEngine",
+         "addDescription UncertaintyCleartkAnalysisEngine",
+         "addDescription HistoryCleartkAnalysisEngine",
+         "addDescription ConditionalCleartkAnalysisEngine",
+         "addDescription GenericCleartkAnalysisEngine",
+         "addDescription SubjectCleartkAnalysisEngine",
+         "add SubjectSectionFixer" ),
+
+//   RULE_ATTRIBUTE( "RULE Attributes",
+//         "Assign Negation, Uncertainty, Historic, Generic, Subject using Machine Learning generated models.",
+//         "load AssertionSubPipe" ),
+
+
+   LOCATION( "Locations",
+         "Connect Entity Locations based upon a Machine Learning Model.",
+         "addLogged ModifierExtractorAnnotator classifierJarPath=/org/apache/ctakes/relationextractor/models/modifier_extractor/model.jar",
+         "addLogged LocationOfRelationExtractorAnnotator classifierJarPath=/org/apache/ctakes/relationextractor/models/location_of/model.jar" ),
+
+
+   SEVERITY( "Severities",
+         "Connect Entity Severities based upon a Machine Learning Model.",
+         "addLogged ModifierExtractorAnnotator classifierJarPath=/org/apache/ctakes/relationextractor/models/modifier_extractor/model.jar",
+         "addLogged DegreeOfRelationExtractorAnnotator classifierJarPath=/org/apache/ctakes/relationextractor/models/degree_of/model.jar" ),
+
+
+   EVENT( "Events",
+         "Create Temporal Events based upon a Machine Learning Model.",
+         "addDescription EventAnnotator" ),
+
+   TIME( "Times",
+         "Create Time Mentions based upon a Machine Learning Model.",
+         "add BackwardsTimeAnnotator classifierJarPath=/org/apache/ctakes/temporal/ae/timeannotator/model.jar" ),
+
+   DOC_TIME_REL( "Relative Event Times",
+         "Assign Event Occurrence Relative to Document Creation based upon a Machine Learning Model.",
+         "add DocTimeRelAnnotator classifierJarPath=/org/apache/ctakes/temporal/ae/doctimerel/model.jar" ),
+
+   E_T_LINK( "Event Times",
+         "Assign Event Occurrence Relative to Times based upon a Machine Learning Model.",
+         "add EventTimeRelationAnnotator classifierJarPath=/org/apache/ctakes/temporal/ae/eventtime/model.jar" ),
+
+   E_E_LINK( "Relative Event Timing",
+         "Assign Event Occurrence Relative to other Events based upon a Machine Learning Model.",
+         "add EventEventRelationAnnotator classifierJarPath=/org/apache/ctakes/temporal/ae/eventevent/model.jar" ),
+
+
+   COREFERENT( "Coreferences",
+         "Assign Coreferent Entities based upon a Machine Learning Model.",
+         "add ConstituencyParser",
+         "add DeterministicMarkableAnnotator",
+         "addDescription MarkableSalienceAnnotator /org/apache/ctakes/temporal/ae/salience/model.jar",
+         "addDescription MentionClusterCoreferenceAnnotator /org/apache/ctakes/coreference/models/mention-cluster/model.jar" );
+
+   private final String _name;
+   private final String _description;
+   private final String[] _piperLines;
+
+   Option( final String name, final String description, final String... piperLines ) {
+      _name = name;
+      _description = description;
+      _piperLines = piperLines;
+   }
+
+   public String getName() {
+      return _name;
+   }
+
+   public String getDescription() {
+      return _description;
+   }
+
+   // TODO make some sort of "enabled" list, so that a piper command is only added if previous piper commands exist.
+   public enum PiperLineRequirements {
+      LIST_PARAGRAPH_FIXER( "add ListParagraphFixer", "add ParagraphAnnotator", "add ListAnnotator" ),
+      SECTION_FILTER( "add SectionFilter", "add BsvRegexSectionizer" ),
+      SUBJECT_SECTION_FIXER( "add SubjectSectionFixer", "add BsvRegexSectionizer" ),
+      LIST_SENTENCE_FIXER( "add ListSentenceFixer", "add SentenceDetectorAnnotatorBIO", "add ListAnnotator" ),
+      PARAGRAPH_SENTENCE_FIXER( "add ParagraphSentenceFixer", "add SentenceDetectorAnnotatorBIO", "add ParagraphAnnotator" );
+
+      private final String _addable;
+      private final String[] _requirements;
+
+      PiperLineRequirements( final String piperAddable, final String... piperRequirements ) {
+         _addable = piperAddable;
+         _requirements = piperRequirements;
+      }
+
+      static public boolean hasRequirements( final String piperLine, final Collection<String> previousLines ) {
+         for ( PiperLineRequirements value : values() ) {
+            if ( value._addable.equals( piperLine ) ) {
+               return previousLines.containsAll( Arrays.asList( value._requirements ) );
+            }
+         }
+         return true;
+      }
+   }
+
+
+   public List<String> getPiperLines() {
+      final List<String> piperLines = new ArrayList<>();
+      piperLines.add( "" );
+      piperLines.add( "//   " + _description );
+      piperLines.addAll( Arrays.asList( _piperLines ) );
+      return piperLines;
+   }
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/Output.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/Output.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/Output.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/Output.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,63 @@
+package org.apache.ctakes.dockhand.gui.output;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 11/1/2019
+ */
+public enum Output {
+   FHIR( "FHIR",
+         "Fast Healthcare Interoperability Resources.",
+         "package org.apache.ctakes.fhir.cc",
+         "add FhirJsonFileWriter SubDirectory=FHIR" ),
+   TEXT( "Text",
+         "Text of the note with CUI, semantic group, POS marked.",
+         "add pretty.plaintext.PrettyTextWriterFit SubDirectory=TEXT" ),
+   PROPERTIES( "Properties",
+         "List of the note sentences with entities and relations.",
+         "add property.plaintext.PropertyTextWriterFit SubDirectory=PROP" ),
+   HTML( "HTML",
+         "Web Page of the note with visual information.",
+         "add pretty.html.HtmlTextWriter SubDirectory=HTML" ),
+   XMI( "XMI",
+         "UIMA XML.  Extremely verbose.",
+         "add FileTreeXmiWriter SubDirectory=XMI" ),
+   CUI_LIST( "CUI List",
+         "List of CUIs in the note.",
+         "add CuiLookupLister SubDirectory=CUI" ),
+   FINISHED( "Run Summary",
+         "Summary Information Log after run completion.",
+         "addLast util.FinishedLogger" );
+
+   private final String _name;
+   private final String _description;
+   private final String[] _piperLines;
+
+   Output( final String name, final String description, final String... piperLines ) {
+      _name = name;
+      _description = description;
+      _piperLines = piperLines;
+   }
+
+   public String getName() {
+      return _name;
+   }
+
+   public String getDescription() {
+      return _description;
+   }
+
+
+   public List<String> getPiperLines() {
+      final List<String> piperLines = new ArrayList<>();
+      piperLines.add( "" );
+      piperLines.add( "//   " + _description );
+      piperLines.addAll( Arrays.asList( _piperLines ) );
+      return piperLines;
+   }
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/OutputComponent.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/OutputComponent.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/OutputComponent.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/output/OutputComponent.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,45 @@
+package org.apache.ctakes.dockhand.gui.output;
+
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/8/2019
+ */
+final public class OutputComponent extends JPanel {
+
+   private final Output _output;
+   private final JCheckBox _checkBox;
+
+
+   public OutputComponent( final Output output ) {
+      super( new BorderLayout() );
+      setBackground( Color.WHITE );
+      _output = output;
+      _checkBox = new JCheckBox( output.getName() );
+      _checkBox.setBackground( Color.WHITE );
+      _checkBox.setToolTipText( output.getDescription() );
+      add( _checkBox, BorderLayout.NORTH );
+   }
+
+   public Output getOutput() {
+      return _output;
+   }
+
+   public void setSelected( final boolean selected ) {
+      _checkBox.setSelected( selected );
+   }
+
+   public boolean isSelected() {
+      return _checkBox.isSelected();
+   }
+
+   public void setEnabled( final boolean enable ) {
+      _checkBox.setEnabled( enable );
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DescriptionStep.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DescriptionStep.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DescriptionStep.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DescriptionStep.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,85 @@
+package org.apache.ctakes.dockhand.gui.wizard;
+
+
+import org.apache.ctakes.gui.wizard.AbstractWizardStep;
+
+import javax.swing.*;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+import java.awt.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/9/2019
+ */
+final public class DescriptionStep extends AbstractWizardStep implements DhWizardStep {
+
+
+   static private final String TYPE_DESCRIPTION = "Type the pipeline description.";
+
+   private JTextArea _textArea;
+
+   public DescriptionStep() {
+      super( "Pipeline Description", "Type a Description for your Pipeline." );
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   protected JComponent createPanel() {
+      _textArea = new JTextArea( 0, 60 );
+      _textArea.setBorder( new CompoundBorder( new LineBorder( Color.LIGHT_GRAY, 2, true ),
+            new EmptyBorder( 10, 10, 10, 10 ) ) );
+      _textArea.setText( TYPE_DESCRIPTION );
+      final JPanel panel = new JPanel( new BorderLayout() );
+      panel.add( _textArea, BorderLayout.CENTER );
+      return wrapInScrollPane( panel );
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Collection<String> getPiperCommands() {
+      if ( _textArea == null ) {
+         return Collections.emptyList();
+      }
+      final String description = _textArea.getText();
+      if ( description.trim().isEmpty() ) {
+         return Collections.emptyList();
+      }
+
+      final String[] lines = description.split( "\\r?\\n" );
+
+      final Function<String, String> ensureComment
+            = s -> (s.startsWith( "//" ) || s.startsWith( "#" )) ? s : "// " + s;
+
+      return Arrays.stream( lines )
+                   .map( ensureComment )
+                   .collect( Collectors.toList() );
+   }
+
+
+   public String getSummaryInfo() {
+      if ( _textArea == null ) {
+         return "";
+      }
+      final String text = _textArea.getText();
+      if ( text.equals( TYPE_DESCRIPTION ) ) {
+         return "";
+      }
+      return "<HTML>" + text.replace( "\n", "<BR>" ) + "</HTML>";
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardController.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardController.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardController.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardController.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,61 @@
+package org.apache.ctakes.dockhand.gui.wizard;
+
+import org.apache.ctakes.dockhand.gui.feature.GoalPom;
+import org.apache.ctakes.gui.wizard.WizardController;
+import org.apache.ctakes.gui.wizard.WizardStep;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/14/2019
+ */
+final public class DhWizardController extends WizardController {
+
+
+   public GoalPom getGoalPom() {
+      return getWizardSteps().stream()
+                             .filter( s -> s instanceof FeaturesStep )
+                             .findAny()
+                             .map( s -> (FeaturesStep)s )
+                             .map( FeaturesStep::getSelectedFeatures )
+                             .map( GoalPom::getAppropriatePom )
+                             .get();
+   }
+
+
+   private String createHeader() {
+      final DateFormat dateFormatter = new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss" );
+      final String date = dateFormatter.format( new Date() );
+      String hostname;
+      try {
+         hostname = InetAddress.getLocalHost().getHostName();
+      } catch ( UnknownHostException uhE ) {
+         hostname = "UnknownHost";
+      }
+      final String userName = System.getProperty( "user.name" );
+      return "// Piper File created " + date + " by " + userName + " on " + hostname;
+   }
+
+
+   public Collection<String> getPiperCommands() {
+      final Collection<String> piperCommands = new ArrayList<>();
+      piperCommands.add( createHeader() );
+      for ( WizardStep wizardStep : getWizardSteps() ) {
+         if ( wizardStep instanceof DhWizardStep ) {
+            piperCommands.add( "" );
+            piperCommands.addAll( ((DhWizardStep)wizardStep).getPiperCommands() );
+         }
+      }
+      return piperCommands;
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardStep.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardStep.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardStep.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/DhWizardStep.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,21 @@
+package org.apache.ctakes.dockhand.gui.wizard;
+
+import org.apache.ctakes.gui.wizard.WizardStep;
+
+import java.util.Collection;
+import java.util.Collections;
+
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/11/2019
+ */
+public interface DhWizardStep extends WizardStep {
+
+   default Collection<String> getPiperCommands() {
+      return Collections.emptyList();
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/FeaturesStep.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/FeaturesStep.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/FeaturesStep.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/FeaturesStep.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,141 @@
+package org.apache.ctakes.dockhand.gui.wizard;
+
+import org.apache.ctakes.dockhand.gui.feature.Feature;
+import org.apache.ctakes.dockhand.gui.feature.FeatureComponent;
+import org.apache.ctakes.dockhand.gui.feature.Option;
+import org.apache.ctakes.gui.wizard.AbstractWizardStep;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/9/2019
+ */
+final public class FeaturesStep extends AbstractWizardStep implements DhWizardStep {
+
+
+   private final Map<Feature, FeatureComponent> _featureComponents = new EnumMap<>( Feature.class );
+
+
+   public FeaturesStep() {
+      super( "Pipeline Features",
+            "Select the pipeline Features." );
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   protected JComponent createPanel() {
+      final JComponent panel = new JPanel();
+      panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ) );
+      final FeatureCheckController featureCheckController = new FeatureCheckController();
+      for ( Feature feature : Feature.values() ) {
+         final FeatureComponent featureComponent = new FeatureComponent( featureCheckController, feature );
+         _featureComponents.put( feature, featureComponent );
+         panel.add( featureComponent );
+      }
+
+      // Sections are always required
+      _featureComponents.get( Feature.SECTIONS ).setSelected( true );
+
+      return wrapInScrollPane( panel );
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Collection<String> getPiperCommands() {
+      if ( _featureComponents.isEmpty() ) {
+         return Collections.emptyList();
+      }
+
+      final Collection<String> unfilteredCommands =
+            Arrays.stream( Feature.values() )
+                  .map( _featureComponents::get )
+                  .filter( FeatureComponent::isSelected )
+                  .map( FeatureComponent::getSelectedOption )
+                  .map( Option::getPiperLines )
+                  .flatMap( Collection::stream )
+                  .collect( Collectors.toList() );
+
+      final Collection<String> piperCommands = new ArrayList<>();
+      for ( String command : unfilteredCommands ) {
+         if ( !command.isEmpty() ) {
+            if ( piperCommands.contains( command )
+                 || !Option.PiperLineRequirements.hasRequirements( command, piperCommands ) ) {
+               continue;
+            }
+         }
+         piperCommands.add( command );
+      }
+      return piperCommands;
+   }
+
+   public String getSummaryInfo() {
+      final Collection<String> summaryLines = new ArrayList<>();
+      for ( FeatureComponent featureComponent : _featureComponents.values() ) {
+         if ( !featureComponent.isSelected() ) {
+            continue;
+         }
+         summaryLines.add( featureComponent.getSelectedOption().getDescription() );
+      }
+      return "<HTML>" + String.join( "<BR>", summaryLines ) + "</HTML>";
+   }
+
+   public Collection<Feature> getSelectedFeatures() {
+      return _featureComponents.entrySet().stream()
+                               .filter( e -> e.getValue().isSelected() )
+                               .map( Map.Entry::getKey )
+                               .collect( Collectors.toList() );
+   }
+
+
+   static public final class FeatureCheckController implements ActionListener {
+      private boolean _activating;
+      private final Map<Feature, FeatureComponent> _featureComponentMap = new EnumMap<>( Feature.class );
+      private final Collection<Feature> _requiredFeatures = new HashSet<>();
+
+      public void addFeature( final Feature feature, final FeatureComponent featureComponent ) {
+         _featureComponentMap.put( feature, featureComponent );
+      }
+
+      private void forceActivate() {
+         _requiredFeatures.clear();
+         _featureComponentMap.entrySet().stream()
+                             .filter( e -> e.getValue().isSelected() )
+                             .map( Map.Entry::getKey )
+                             .map( Feature::getRequirements )
+                             .forEach( _requiredFeatures::addAll );
+         _featureComponentMap.forEach( this::forceActivate );
+      }
+
+      private void forceActivate( final Feature feature, final FeatureComponent featureComponent ) {
+         if ( _requiredFeatures.contains( feature ) ) {
+            featureComponent.setSelected( true );
+            featureComponent.setEnabled( false );
+         } else {
+            featureComponent.setEnabled( true );
+         }
+      }
+
+      public void actionPerformed( final ActionEvent event ) {
+         if ( _activating ) {
+            return;
+         }
+         _activating = true;
+         forceActivate();
+         _activating = false;
+      }
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/InstallTypeStep.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/InstallTypeStep.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/InstallTypeStep.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/InstallTypeStep.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,128 @@
+package org.apache.ctakes.dockhand.gui.wizard;
+
+
+import org.apache.ctakes.dockhand.build.LocalInstallBuilder;
+import org.apache.ctakes.dockhand.build.RestDockerBuilder;
+import org.apache.ctakes.gui.wizard.AbstractWizardStep;
+import org.apache.ctakes.gui.wizard.WizardController;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/9/2019
+ */
+final public class InstallTypeStep extends AbstractWizardStep implements DhWizardStep {
+
+
+   static private final String LOCAL_BINARY = "Local Installation";
+   static private final String LOCAL_BINARY_DESCRIPTION = "Create a Local Installation of the application.";
+
+   static private final String REST_DOCKER = "Rest Server Docker Bundle";
+   static private final String REST_DOCKER_DESCRIPTION = "Create a Docker File and Supporting Files for a Rest Server.";
+
+   private final DhWizardController _wizardController;
+   private Collection<AbstractButton> _radios;
+
+   public InstallTypeStep( final DhWizardController wizardController ) {
+      super( "Installation Type", "Select the installation Type." );
+      _wizardController = wizardController;
+   }
+
+   public String getInstallationType() {
+      if ( _radios == null ) {
+         return "";
+      }
+      return _radios.stream()
+                    .filter( AbstractButton::isSelected )
+                    .map( AbstractButton::getText )
+                    .findFirst()
+                    .orElse( "" );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   protected JComponent createPanel() {
+      final JComponent panel = new JPanel();
+      panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ) );
+
+      panel.add( Box.createVerticalStrut( 100 ) );
+      _radios = new ArrayList<>();
+      final ButtonGroup buttonGroup = new ButtonGroup();
+
+      final Runnable localBinaryBuilder = new LocalInstallBuilder( _wizardController );
+      final JRadioButton localBinary = createRadio( _wizardController,
+            LOCAL_BINARY, LOCAL_BINARY_DESCRIPTION, localBinaryBuilder );
+      _wizardController.setBuildProcess( localBinaryBuilder );
+      buttonGroup.add( localBinary );
+      panel.add( localBinary );
+      localBinary.setSelected( true );
+      _radios.add( localBinary );
+
+      final JRadioButton restDocker = createRadio( _wizardController,
+            REST_DOCKER, REST_DOCKER_DESCRIPTION, new RestDockerBuilder( _wizardController ) );
+      buttonGroup.add( restDocker );
+      panel.add( restDocker );
+      _radios.add( restDocker );
+
+
+      panel.add( Box.createVerticalStrut( 100 ) );
+      _radios.forEach( b -> b.setBackground( Color.WHITE ) );
+      return wrapInScrollPane( panel );
+   }
+
+
+   static private JRadioButton createRadio( final WizardController wizardController,
+                                            final String name,
+                                            final String description,
+                                            final Runnable builder ) {
+      final JRadioButton radio = new JRadioButton( name );
+      radio.setToolTipText( description );
+      radio.setActionCommand( name );
+      radio.addActionListener( new BuilderActioner( name, builder, wizardController ) );
+      return radio;
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getSummaryInfo() {
+      return getInstallationType();
+   }
+
+
+   static private class BuilderActioner implements ActionListener {
+      private final String _type;
+      private final Runnable _builder;
+      private final WizardController _wizardController;
+
+      private BuilderActioner( final String type,
+                               final Runnable builder,
+                               final WizardController wizardController ) {
+         _type = type;
+         _builder = builder;
+         _wizardController = wizardController;
+      }
+
+      public void actionPerformed( final ActionEvent event ) {
+         if ( _type.equals( event.getActionCommand() ) ) {
+            final Object source = event.getSource();
+            if ( source instanceof AbstractButton && ((AbstractButton)source).isSelected() ) {
+               _wizardController.setBuildProcess( _builder );
+            }
+         }
+      }
+   }
+
+
+}

Added: ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/OutputStep.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/OutputStep.java?rev=1870640&view=auto
==============================================================================
--- ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/OutputStep.java (added)
+++ ctakes/trunk/ctakes-dockhand/src/main/java/org/apache/ctakes/dockhand/gui/wizard/OutputStep.java Sat Nov 30 19:05:56 2019
@@ -0,0 +1,97 @@
+package org.apache.ctakes.dockhand.gui.wizard;
+
+import org.apache.ctakes.dockhand.gui.feature.Option;
+import org.apache.ctakes.dockhand.gui.output.Output;
+import org.apache.ctakes.dockhand.gui.output.OutputComponent;
+import org.apache.ctakes.gui.wizard.AbstractWizardStep;
+
+import javax.swing.*;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 10/9/2019
+ */
+final public class OutputStep extends AbstractWizardStep implements DhWizardStep {
+
+
+   private final Map<Output, OutputComponent> _outputComponents = new EnumMap<>( Output.class );
+
+
+   public OutputStep() {
+      super( "Pipeline Outputs",
+            "Select the pipeline Outputs." );
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   protected JComponent createPanel() {
+      final JComponent panel = new JPanel();
+      panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ) );
+      panel.add( Box.createVerticalStrut( 100 ) );
+      for ( Output output : Output.values() ) {
+         final OutputComponent outputComponent = new OutputComponent( output );
+         _outputComponents.put( output, outputComponent );
+         panel.add( outputComponent );
+      }
+      panel.add( Box.createVerticalStrut( 100 ) );
+      return wrapInScrollPane( panel );
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Collection<String> getPiperCommands() {
+      if ( _outputComponents.isEmpty() ) {
+         return Collections.emptyList();
+      }
+
+      final Collection<String> unfilteredCommands =
+            Arrays.stream( Output.values() )
+                  .map( _outputComponents::get )
+                  .filter( OutputComponent::isSelected )
+                  .map( OutputComponent::getOutput )
+                  .map( Output::getPiperLines )
+                  .flatMap( Collection::stream )
+                  .collect( Collectors.toList() );
+
+      final Collection<String> piperCommands = new ArrayList<>();
+      for ( String command : unfilteredCommands ) {
+         if ( !command.isEmpty() ) {
+            if ( piperCommands.contains( command )
+                 || !Option.PiperLineRequirements.hasRequirements( command, piperCommands ) ) {
+               continue;
+            }
+         }
+         piperCommands.add( command );
+      }
+      return piperCommands;
+   }
+
+   public String getSummaryInfo() {
+      final Collection<String> summaryLines = new ArrayList<>();
+      for ( OutputComponent outputComponent : _outputComponents.values() ) {
+         if ( !outputComponent.isSelected() ) {
+            continue;
+         }
+         summaryLines.add( outputComponent.getOutput().getDescription() );
+      }
+      return "<HTML>" + String.join( "<BR>", summaryLines ) + "</HTML>";
+   }
+
+   public Collection<Output> getSelectedOutputs() {
+      return _outputComponents.entrySet().stream()
+                              .filter( e -> e.getValue().isSelected() )
+                              .map( Map.Entry::getKey )
+                              .collect( Collectors.toList() );
+   }
+
+
+}