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/03/27 14:37:46 UTC

svn commit: r1788936 [6/7] - in /ctakes/trunk: ctakes-gui-res/ ctakes-gui-res/src/ ctakes-gui-res/src/main/ ctakes-gui-res/src/main/resources/ ctakes-gui-res/src/main/resources/org/ ctakes-gui-res/src/main/resources/org/apache/ ctakes-gui-res/src/main/...

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/MainPanel2.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/MainPanel2.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/MainPanel2.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/MainPanel2.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,266 @@
+package org.apache.ctakes.gui.pipeline;
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.gui.component.DisablerPane;
+import org.apache.ctakes.gui.component.LoggerPanel;
+import org.apache.ctakes.gui.component.PositionedSplitPane;
+import org.apache.ctakes.gui.component.SmoothTipList;
+import org.apache.ctakes.gui.pipeline.bit.PipeBitFinder;
+import org.apache.ctakes.gui.pipeline.bit.available.AvailablesListModel;
+import org.apache.ctakes.gui.pipeline.bit.info.*;
+import org.apache.ctakes.gui.pipeline.piper.PiperTextFilter;
+import org.apache.ctakes.gui.util.IconLoader;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import javax.swing.table.JTableHeader;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultStyledDocument;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+import static javax.swing.JOptionPane.PLAIN_MESSAGE;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/20/2016
+ */
+final class MainPanel2 extends JPanel {
+
+   static private final Logger LOGGER = Logger.getLogger( "MainPanel" );
+
+   private final JFileChooser _chooser = new JFileChooser();
+
+   private final AvailablesListModel _availablesListModel = new AvailablesListModel();
+   private JList<PipeBitInfo> _availablesList;
+
+   private DefaultStyledDocument _piperDocument;
+
+   private JButton _newButton;
+   private JButton _openButton;
+   private JButton _saveButton;
+   private JButton _runButton;
+   private JButton _helpButton;
+
+
+   MainPanel2() {
+      super( new BorderLayout() );
+
+      final JSplitPane logSplit = new PositionedSplitPane( JSplitPane.VERTICAL_SPLIT );
+      logSplit.setTopComponent( createMainPanel() );
+      logSplit.setBottomComponent( LoggerPanel.createLoggerPanel() );
+      logSplit.setDividerLocation( 0.6d );
+
+      add( createToolBar(), BorderLayout.NORTH );
+
+      add( logSplit, BorderLayout.CENTER );
+      SwingUtilities.invokeLater( new ButtonIconLoader() );
+   }
+
+
+   private JComponent createWestPanel() {
+      final JTable fakeTable = new JTable();
+      final JTableHeader fakeHeader = fakeTable.getTableHeader();
+      final Component header = fakeHeader.getDefaultRenderer().getTableCellRendererComponent( null,
+            "Available Pipe Bits", false, false, -1, -1 );
+      ((JLabel)header).setHorizontalAlignment( SwingConstants.CENTER );
+
+      _availablesList = createPipeBitList( _availablesListModel );
+      final JScrollPane scroll = new JScrollPane( _availablesList );
+      scroll.setColumnHeaderView( header );
+      final JList<PipeBitInfo> rowHeaders = new JList<>( _availablesListModel );
+      rowHeaders.setFixedCellHeight( 20 );
+      rowHeaders.setCellRenderer( new RoleRenderer() );
+      scroll.setRowHeaderView( rowHeaders );
+      scroll.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );
+
+      final JSplitPane split = new PositionedSplitPane();
+      split.setLeftComponent( scroll );
+      split.setRightComponent( createBitInfoPanel( _availablesList ) );
+      split.setDividerLocation( 0.3d );
+      return split;
+   }
+
+
+   private JComponent createEastPanel() {
+      _piperDocument = new DefaultStyledDocument();
+      new PiperTextFilter( _piperDocument );
+      final JTextPane textPane = new JTextPane( _piperDocument );
+      return new JScrollPane( textPane );
+   }
+
+
+   private JComponent createMainPanel() {
+      final JComponent westPanel = createWestPanel();
+      final JComponent eastPanel = createEastPanel();
+      return new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, westPanel, eastPanel );
+   }
+
+   private JToolBar createToolBar() {
+      final JToolBar toolBar = new JToolBar();
+      toolBar.setFloatable( false );
+      toolBar.setRollover( true );
+      _newButton = addButton( toolBar, "Create New Piper File" );
+      _newButton.addActionListener( new NewPiperAction() );
+      _openButton = addButton( toolBar, "Open Existing Piper File" );
+      _openButton.addActionListener( new OpenPiperAction() );
+      _saveButton = addButton( toolBar, "Save Current Piper File" );
+      _saveButton.addActionListener( new SavePiperAction() );
+      toolBar.addSeparator( new Dimension( 20, 0 ) );
+      _helpButton = addButton( toolBar, "Help" );
+      _helpButton.addActionListener( new HelpAction() );
+      toolBar.add( Box.createHorizontalGlue() );
+      _runButton = addButton( toolBar, "Run Current Piper File" );
+      toolBar.addSeparator( new Dimension( 10, 0 ) );
+      return toolBar;
+   }
+
+   static private JButton addButton( final JToolBar toolBar, final String toolTip ) {
+      toolBar.addSeparator( new Dimension( 10, 0 ) );
+      final JButton button = new JButton();
+      button.setFocusPainted( false );
+      // prevents first button from having a painted border
+      button.setFocusable( false );
+      button.setToolTipText( toolTip );
+      toolBar.add( button );
+      return button;
+   }
+
+   static private JList<PipeBitInfo> createPipeBitList( final ListModel<PipeBitInfo> model ) {
+      final JList<PipeBitInfo> bitList = new SmoothTipList<>( model );
+      bitList.setCellRenderer( new PipeBitInfoRenderer() );
+      bitList.setFixedCellHeight( 20 );
+      return bitList;
+   }
+
+   static private PipeBitInfoPanel createBitInfoPanel( final JList<PipeBitInfo> list ) {
+      final PipeBitInfoPanel pipeBitInfoPanel = new PipeBitInfoPanel();
+      pipeBitInfoPanel.setPipeBitInfoList( list );
+      pipeBitInfoPanel.setBorder( UIManager.getBorder( "ScrollPane.border" ) );
+      return pipeBitInfoPanel;
+   }
+
+   void findPipeBits() {
+      final ExecutorService executor = Executors.newSingleThreadExecutor();
+      executor.execute( new PiperBitParser() );
+   }
+
+   private class PiperBitParser implements Runnable {
+      @Override
+      public void run() {
+         final JFrame frame = (JFrame)SwingUtilities.getRoot( MainPanel2.this );
+         frame.setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );
+         DisablerPane.getInstance().setVisible( true );
+         PipeBitFinder.getInstance().scan();
+         _availablesListModel.setPipeBits( PipeBitFinder.getInstance().getPipeBits() );
+         DisablerPane.getInstance().setVisible( false );
+         frame.setCursor( Cursor.getDefaultCursor() );
+      }
+   }
+
+
+   /**
+    * Simple Runnable that loads an icon
+    */
+   private final class ButtonIconLoader implements Runnable {
+      @Override
+      public void run() {
+         final String dir = "org/apache/ctakes/gui/pipeline/icon/";
+         final String newFile = "NewPiper.png";
+         final String openFile = "OpenPiper.png";
+         final String saveFile = "SavePiper.png";
+         final String runFile = "RunPiper.png";
+         final String helpFile = "Help_32.png";
+         final Icon newIcon = IconLoader.loadIcon( dir + newFile );
+         final Icon openIcon = IconLoader.loadIcon( dir + openFile );
+         final Icon saveIcon = IconLoader.loadIcon( dir + saveFile );
+         final Icon runIcon = IconLoader.loadIcon( dir + runFile );
+         final Icon helpIcon = IconLoader.loadIcon( dir + helpFile );
+         _newButton.setIcon( newIcon );
+         _openButton.setIcon( openIcon );
+         _saveButton.setIcon( saveIcon );
+         _runButton.setIcon( runIcon );
+         _helpButton.setIcon( helpIcon );
+      }
+   }
+
+   private final class NewPiperAction implements ActionListener {
+      @Override
+      public void actionPerformed( final ActionEvent event ) {
+         try {
+            _piperDocument.remove( 0, _piperDocument.getLength() );
+         } catch ( BadLocationException blE ) {
+            LOGGER.warn( blE.getMessage() );
+         }
+      }
+   }
+
+   private final class OpenPiperAction implements ActionListener {
+      @Override
+      public void actionPerformed( final ActionEvent event ) {
+         final int option = _chooser.showOpenDialog( null );
+         if ( option != JFileChooser.APPROVE_OPTION ) {
+            return;
+         }
+         String text = "";
+         final File file = _chooser.getSelectedFile();
+         try {
+            text = Files.lines( Paths.get( file.getPath() ) ).collect( Collectors.joining() );
+         } catch ( IOException ioE ) {
+            LOGGER.error( ioE.getMessage() );
+            return;
+         }
+         try {
+            _piperDocument.remove( 0, _piperDocument.getLength() );
+            _piperDocument.insertString( 0, text, null );
+         } catch ( BadLocationException blE ) {
+            LOGGER.warn( blE.getMessage() );
+         }
+      }
+   }
+
+   private final class SavePiperAction implements ActionListener {
+      @Override
+      public void actionPerformed( final ActionEvent event ) {
+         if ( _piperDocument.getLength() == 0 ) {
+            return;
+         }
+         final int option = _chooser.showSaveDialog( null );
+         if ( option != JFileChooser.APPROVE_OPTION ) {
+            return;
+         }
+         final File file = _chooser.getSelectedFile();
+         try {
+            final String text = _piperDocument.getText( 0, _piperDocument.getLength() );
+            Files.write( Paths.get( file.getPath() ), text.getBytes() );
+            _piperDocument.remove( 0, _piperDocument.getLength() );
+            _piperDocument.insertString( 0, text, null );
+         } catch ( BadLocationException | IOException multE ) {
+            LOGGER.warn( multE.getMessage() );
+         }
+      }
+   }
+
+   static private final class HelpAction implements ActionListener {
+      @Override
+      public void actionPerformed( final ActionEvent event ) {
+         final JPanel panel = new JPanel( new BorderLayout() );
+         panel.add( new JLabel( "Dependency and Product Types." ), BorderLayout.NORTH );
+         final JList<PipeBitInfo.TypeProduct> list = new JList<>( new TypeProductListModel() );
+         list.setCellRenderer( new TypeProductRenderer() );
+         panel.add( list, BorderLayout.CENTER );
+         panel.add( new JLabel( "Types are associated with Pipe Bits." ), BorderLayout.SOUTH );
+         JOptionPane.showMessageDialog( null, panel, "Type Products Help", PLAIN_MESSAGE, null );
+      }
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperCreator.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperCreator.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperCreator.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperCreator.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,84 @@
+package org.apache.ctakes.gui.pipeline;
+
+import org.apache.ctakes.gui.component.DisablerPane;
+import org.apache.ctakes.gui.pipeline.bit.PipeBitPainter;
+import org.apache.ctakes.gui.util.IconLoader;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/20/2016
+ */
+final public class PiperCreator {
+
+   static private final Logger LOGGER = Logger.getLogger( "PiperCreator" );
+
+   private PiperCreator() {
+   }
+
+   static private JFrame createFrame() {
+      final JFrame frame = new JFrame( "cTAKES Simple Pipeline 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 );
+      final JMenuBar menuBar = new JMenuBar();
+//      final JMenu fileMenu = new JMenu( "File" );
+//      menuBar.add( fileMenu );
+
+      frame.setJMenuBar( menuBar );
+      System.setProperty( "apple.laf.useScreenMenuBar", "true" );
+      return frame;
+   }
+
+   static private MainPanel2 createMainPanel() {
+      return new MainPanel2();
+   }
+
+   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.error( multE.getLocalizedMessage() );
+      }
+      final JFrame frame = createFrame();
+      final MainPanel2 mainPanel = createMainPanel();
+      frame.add( mainPanel );
+      frame.pack();
+      frame.setVisible( true );
+      DisablerPane.getInstance().initialize( frame );
+      PipeBitPainter.getInstance().loadIcons();
+      LOGGER.info( "1. Select your Apache cTAKES root directory." );
+      LOGGER.info( "   It can be a pre-built binary installation or a developer sandbox." );
+      LOGGER.info( "2. Select your Unified Medical Language System (UMLS) root directory." );
+      LOGGER.info( "   Once selected, your UMLS database will be parsed for available content." );
+      LOGGER.info( "3. Select your desired Vocabulary sources in the left table." );
+      LOGGER.info( "   Recommended Vocabulary sources are pre-selected." );
+      LOGGER.info( "4. Select your desired Semantic Types in the right table." );
+      LOGGER.info( "   Recommended Semantic types are pre-selected." );
+      LOGGER.info( "5. Type a name for your dictionary." );
+      LOGGER.info( "6. Click \'Build Dictionary\'" );
+      LOGGER.info( "-  You can resize this log panel by clicking the top and dragging up or down." );
+
+      final Object[] options = { "Scan" };
+      final Icon scanIcon = IconLoader.loadIcon( "org/apache/ctakes/gui/pipeline/icon/" + "FindOnPc_48.png" );
+      JOptionPane.showOptionDialog( frame, "A Scan must be performed to find available Pipe Bits.\n" +
+                                           "Pipe Bits are used to assemble a cTAKES Pipeline.",
+            "Find Pipe Bits", JOptionPane.YES_OPTION, JOptionPane.PLAIN_MESSAGE, scanIcon, options, options[ 0 ] );
+      mainPanel.findPipeBits();
+
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperDisplayModel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperDisplayModel.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperDisplayModel.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/PiperDisplayModel.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,13 @@
+package org.apache.ctakes.gui.pipeline;
+
+import java.util.logging.Logger;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/13/2017
+ */
+public class PiperDisplayModel {
+
+   static private final Logger LOGGER = Logger.getLogger( "PiperDisplayModel" );
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/BitCellRenderer.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/BitCellRenderer.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/BitCellRenderer.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/BitCellRenderer.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,34 @@
+package org.apache.ctakes.gui.pipeline.bit;
+
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.logging.Logger;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/13/2017
+ */
+final public class BitCellRenderer implements ListCellRenderer<Object> {
+
+   static private final Logger LOGGER = Logger.getLogger( "BitCellRenderer" );
+
+
+   private final ListCellRenderer<Object> _delegate = new DefaultListCellRenderer();
+
+   @Override
+   public Component getListCellRendererComponent(
+         final JList<?> list,
+         final Object value,
+         final int index,
+         final boolean isSelected,
+         final boolean cellHasFocus ) {
+      final Component renderer = _delegate.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
+
+      PipeBitPainter.getInstance().paintObject( renderer, value, isSelected );
+
+      return renderer;
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/BitInfoPanel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/BitInfoPanel.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/BitInfoPanel.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/BitInfoPanel.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,120 @@
+package org.apache.ctakes.gui.pipeline.bit;
+
+import org.apache.ctakes.gui.component.SmoothTipTable;
+import org.apache.ctakes.gui.pipeline.bit.parameter.ParameterCellRenderer;
+import org.apache.ctakes.gui.pipeline.bit.parameter.ParameterInfoPanel;
+import org.apache.ctakes.gui.pipeline.bit.parameter.ParameterTableModel;
+import org.apache.log4j.Logger;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.table.TableModel;
+import javax.swing.table.TableRowSorter;
+import java.awt.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/19/2017
+ */
+abstract public class BitInfoPanel extends JPanel {
+
+   static private final Logger LOGGER = Logger.getLogger( "BitInfoPanel" );
+
+   protected JComponent _name;
+   protected JLabel _description;
+   protected JLabel _dependencies;
+   protected JLabel _usables;
+   protected JLabel _outputs;
+
+   protected ParameterTableModel _parameterTableModel;
+   protected ParameterInfoPanel _parameterInfoPanel;
+
+   public BitInfoPanel() {
+      super( new BorderLayout( 5, 5 ) );
+
+      add( createMainPanel(), BorderLayout.NORTH );
+
+      _parameterTableModel = new ParameterTableModel();
+      final JTable parameterTable = createParameterTable( _parameterTableModel );
+      add( new JScrollPane( parameterTable ), BorderLayout.CENTER );
+
+      _parameterInfoPanel = createParameterInfoPanel();
+      _parameterInfoPanel.setParameterTable( parameterTable );
+      add( _parameterInfoPanel, BorderLayout.SOUTH );
+   }
+
+   abstract protected String getNameLabelPrefix();
+
+   abstract protected JComponent createNameEditor();
+
+   abstract protected void setBitName( final String text );
+
+   abstract protected ParameterInfoPanel createParameterInfoPanel();
+
+   protected void clear() {
+      setBitName( "" );
+      _description.setText( "" );
+      _dependencies.setText( "" );
+      _usables.setText( "" );
+      _outputs.setText( "" );
+      _parameterTableModel.setParameterHolder( null );
+      _parameterInfoPanel.setParameterHolder( null );
+   }
+
+   private JComponent createMainPanel() {
+      _name = createNameEditor();
+      final JComponent namePanel = createNamePanel( getNameLabelPrefix() + " Bit Name:", _name );
+      _description = new JLabel();
+      final JComponent descPanel = createNamePanel( "Description:", _description );
+      _dependencies = new JLabel();
+      final JComponent inPanel = createNamePanel( "Dependencies:", _dependencies );
+      _usables = new JLabel();
+      final JComponent usablePanel = createNamePanel( "Usable:", _usables );
+      _outputs = new JLabel();
+      final JComponent outPanel = createNamePanel( "Products:", _outputs );
+
+      final JPanel panel = new JPanel( new GridLayout( 5, 1 ) );
+      panel.add( namePanel );
+      panel.add( descPanel );
+      panel.add( inPanel );
+      panel.add( usablePanel );
+      panel.add( outPanel );
+      return panel;
+   }
+
+   static private JTable createParameterTable( final TableModel model ) {
+      final JTable table = new SmoothTipTable( model );
+      table.setRowHeight( 20 );
+      table.setAutoResizeMode( JTable.AUTO_RESIZE_LAST_COLUMN );
+      table.getColumnModel().getColumn( 0 ).setPreferredWidth( 100 );
+      final TableRowSorter<TableModel> sorter = new TableRowSorter<>( model );
+      table.setAutoCreateRowSorter( true );
+      table.setRowSorter( sorter );
+      table.setRowSelectionAllowed( true );
+      table.setCellSelectionEnabled( true );
+      table.setDefaultRenderer( ConfigurationParameter.class, new ParameterCellRenderer() );
+      ListSelectionModel selectionModel = table.getSelectionModel();
+      selectionModel.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+      return table;
+   }
+
+   static private JComponent createNamePanel( final String name, final JComponent nameLabel ) {
+      final JPanel panel = new JPanel( new BorderLayout( 10, 10 ) );
+      panel.setBorder( new EmptyBorder( 2, 10, 2, 10 ) );
+      final JLabel label = new JLabel( name );
+      label.setPreferredSize( new Dimension( 90, 20 ) );
+      label.setHorizontalAlignment( SwingConstants.TRAILING );
+      final Border emptyBorder = new EmptyBorder( 0, 10, 0, 0 );
+      final Border border
+            = new CompoundBorder( UIManager.getLookAndFeelDefaults().getBorder( "TextField.border" ), emptyBorder );
+      nameLabel.setBorder( border );
+      panel.add( label, BorderLayout.WEST );
+      panel.add( nameLabel, BorderLayout.CENTER );
+      return panel;
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/PipeBitFinder.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/PipeBitFinder.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/PipeBitFinder.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/PipeBitFinder.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,95 @@
+package org.apache.ctakes.gui.pipeline.bit;
+
+
+import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
+import io.github.lukehutch.fastclasspathscanner.ScanInterruptedException;
+import io.github.lukehutch.fastclasspathscanner.matchprocessor.SubclassMatchProcessor;
+import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult;
+import org.apache.log4j.Logger;
+import org.apache.uima.analysis_component.Annotator_ImplBase;
+import org.apache.uima.analysis_component.JCasAnnotator_ImplBase;
+import org.apache.uima.collection.CasConsumer_ImplBase;
+import org.apache.uima.collection.CollectionReader_ImplBase;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Finds Collection Readers, Annotators, Cas Consumers (Writers), and their metadata
+ *
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/22/2016
+ */
+public enum PipeBitFinder {
+   INSTANCE;
+
+   static public PipeBitFinder getInstance() {
+      return INSTANCE;
+   }
+
+   private final Logger LOGGER = Logger.getLogger( "PipeBitFinder" );
+
+   private final Collection<Class<?>> _pipeBits = new ArrayList<>();
+   private boolean _didScan = false;
+
+   synchronized public void reset() {
+      _pipeBits.clear();
+      _didScan = false;
+   }
+
+   synchronized public Collection<Class<?>> getPipeBits() {
+      scan();
+      return _pipeBits;
+   }
+
+   static private boolean isPipeBit( final Class<?> clazz ) {
+      final String className = clazz.getName();
+      return !className.startsWith( "org.apache.uima.tutorial" )
+             && !className.startsWith( "org.apache.uima.examples" )
+             && !Modifier.isAbstract( clazz.getModifiers() );
+   }
+
+   synchronized public void scan() {
+      if ( _didScan ) {
+         return;
+      }
+      final SubclassMatchProcessor<CollectionReader_ImplBase> readerAdder = r -> {
+         if ( isPipeBit( r ) ) {
+            _pipeBits.add( r );
+         }
+      };
+      final SubclassMatchProcessor<Annotator_ImplBase> annotatorAdder = a -> {
+         if ( isPipeBit( a ) ) {
+            _pipeBits.add( a );
+         }
+      };
+      final SubclassMatchProcessor<CasConsumer_ImplBase> writerAdder = w -> {
+         if ( isPipeBit( w ) ) {
+            _pipeBits.add( w );
+         }
+      };
+      // Don't want super-primitive cleartk or uima classes
+      final FastClasspathScanner scanner = new FastClasspathScanner();
+      LOGGER.info( "Starting Scan for Pipeline Bits" );
+      try {
+         scanner.matchSubclassesOf( CollectionReader_ImplBase.class, readerAdder )
+               .matchSubclassesOf( Annotator_ImplBase.class, annotatorAdder )
+               .matchSubclassesOf( CasConsumer_ImplBase.class, writerAdder );
+         final ScanResult result = scanner.scan();
+      } catch ( ScanInterruptedException siE ) {
+         LOGGER.error( siE.getMessage() );
+      }
+      // Get rid of the abstract classes
+      _pipeBits.remove( CollectionReader_ImplBase.class );
+      _pipeBits.remove( JCasAnnotator_ImplBase.class );
+      _pipeBits.remove( CasConsumer_ImplBase.class );
+      // FastClassPathScanner blacklisting doesn't work, so we need to remove unwanted packages manually
+      _pipeBits.removeIf( c -> c.getPackage().getName().startsWith( "org.cleartk" )
+                               || c.getPackage().getName().startsWith( "org.apache.uima" ) );
+      LOGGER.info( "Scan Finished" );
+      _didScan = true;
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/PipeBitPainter.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/PipeBitPainter.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/PipeBitPainter.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/PipeBitPainter.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,145 @@
+package org.apache.ctakes.gui.pipeline.bit;
+
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.gui.util.IconLoader;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/13/2017
+ */
+public enum PipeBitPainter {
+   INSTANCE;
+
+   static public PipeBitPainter getInstance() {
+      return INSTANCE;
+   }
+
+   static private final Logger LOGGER = Logger.getLogger( "PipeBitPainter" );
+
+   static private final Color READER_COLOR = Color.GREEN.darker().darker();
+   static private final Color ANNOTATOR_COLOR = Color.CYAN.darker().darker();
+   static private final Color WRITER_COLOR = Color.BLUE;
+   static private final Color SPECIAL_COLOR = Color.MAGENTA.darker();
+   static private final String READER_ICON_FILE = "GreenArrowIn.png";
+   static private final String ANNOTATOR_ICON_FILE = "BlueGear.png";
+   static private final String WRITER_ICON_FILE = "BlueArrowOut.png";
+   static private final String SPECIAL_ICON_FILE = "Utilities.png";
+
+   static private final Border EMPTY_BORDER = new EmptyBorder( 0, 5, 0, 0 );
+
+
+   private Icon READER_ICON = null;
+   private Icon ANNOTATOR_ICON = null;
+   private Icon WRITER_ICON = null;
+   private Icon SPECIAL_ICON = null;
+   private boolean _iconLoadAttempted;
+
+
+   synchronized public void loadIcons() {
+      if ( _iconLoadAttempted ) {
+         return;
+      }
+      _iconLoadAttempted = true;
+      SwingUtilities.invokeLater( new PipeBitIconLoader() );
+   }
+
+   public void paintObject( final Component renderer, final Object value, final boolean isSelected ) {
+      if ( PipeBitInfo.class.isInstance( value ) ) {
+         paintPipeBitInfo( renderer, (PipeBitInfo)value, isSelected );
+      } else {
+         LOGGER.error( value.getClass().getName() + " is not a PipeBitInfo" );
+         renderer.setBackground( Color.DARK_GRAY );
+         setText( renderer, "Invalid" );
+         setToolTipText( renderer, "Invalid Information" );
+      }
+   }
+
+   public void paintPipeBitInfo( final Component renderer, final PipeBitInfo info, final boolean isSelected ) {
+      if ( !isSelected ) {
+         switch ( info.role() ) {
+            case READER:
+               renderer.setForeground( READER_COLOR );
+               break;
+            case ANNOTATOR:
+               renderer.setForeground( ANNOTATOR_COLOR );
+               break;
+            case WRITER:
+               renderer.setForeground( WRITER_COLOR );
+               break;
+            case SPECIAL:
+               renderer.setForeground( SPECIAL_COLOR );
+               break;
+         }
+      }
+      setIcon( renderer, info );
+      setText( renderer, info.name() );
+      setToolTipText( renderer, info.description() );
+   }
+
+   private void setIcon( final Component renderer, final PipeBitInfo info ) {
+      if ( !JLabel.class.isInstance( renderer ) ) {
+         return;
+      }
+      ((JLabel)renderer).setBorder( EMPTY_BORDER );
+      switch ( info.role() ) {
+         case READER:
+            ((JLabel)renderer).setIcon( READER_ICON );
+            break;
+         case ANNOTATOR:
+            ((JLabel)renderer).setIcon( ANNOTATOR_ICON );
+            break;
+         case WRITER:
+            ((JLabel)renderer).setIcon( WRITER_ICON );
+            break;
+         case SPECIAL:
+            ((JLabel)renderer).setIcon( SPECIAL_ICON );
+            break;
+      }
+   }
+
+   static private void setText( final Component renderer, final String text ) {
+      if ( !JLabel.class.isInstance( renderer ) ) {
+         LOGGER.error( "Renderer " + renderer.getClass().getName() + " is not a JLabel" );
+         return;
+      }
+      ((JLabel)renderer).setText( text );
+   }
+
+   static private void setToolTipText( final Component renderer, final String text ) {
+      if ( !JComponent.class.isInstance( renderer ) ) {
+         LOGGER.error( "Renderer " + renderer.getClass().getName() + " is not a JComponent" );
+         return;
+      }
+      ((JComponent)renderer).setToolTipText( text );
+   }
+
+
+   /**
+    * Simple Callable that loads and resizes an icon
+    */
+   private final class PipeBitIconLoader implements Runnable {
+      static private final int ICON_SIZE = 16;
+      static private final String ICON_DIR = "org/apache/ctakes/gui/pipeline/icon/";
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public void run() {
+         READER_ICON = IconLoader.loadIcon( ICON_DIR + READER_ICON_FILE, ICON_SIZE );
+         ANNOTATOR_ICON = IconLoader.loadIcon( ICON_DIR + ANNOTATOR_ICON_FILE, ICON_SIZE );
+         WRITER_ICON = IconLoader.loadIcon( ICON_DIR + WRITER_ICON_FILE, ICON_SIZE );
+         SPECIAL_ICON = IconLoader.loadIcon( ICON_DIR + SPECIAL_ICON_FILE, ICON_SIZE );
+      }
+   }
+
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/available/AvailablesListModel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/available/AvailablesListModel.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/available/AvailablesListModel.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/available/AvailablesListModel.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,76 @@
+package org.apache.ctakes.gui.pipeline.bit.available;
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.core.pipeline.PipeBitInfoUtil;
+import org.apache.ctakes.gui.pipeline.bit.info.PipeBitInfoComparator;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import java.util.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/13/2017
+ */
+final public class AvailablesListModel extends AbstractListModel<PipeBitInfo> {
+
+   static private final Logger LOGGER = Logger.getLogger( "AvailablesListModel" );
+
+
+   private final List<PipeBitInfo> _pipeBitInfos = new ArrayList<>();
+
+   private final Map<PipeBitInfo, Class<?>> _pipeBitMap = new HashMap<>();
+
+   /**
+    * Populate the list
+    *
+    * @param bits -
+    */
+   public void setPipeBits( final Collection<Class<?>> bits ) {
+      final int oldSize = _pipeBitInfos.size();
+      if ( oldSize > 0 ) {
+         _pipeBitInfos.clear();
+         _pipeBitMap.clear();
+      }
+      if ( bits == null || bits.isEmpty() ) {
+         if ( oldSize > 0 ) {
+            fireIntervalRemoved( this, 0, oldSize - 1 );
+         }
+         return;
+      }
+      for ( Class<?> bit : bits ) {
+         final PipeBitInfo info = PipeBitInfoUtil.getInfo( bit );
+         _pipeBitInfos.add( info );
+         _pipeBitMap.put( info, bit );
+      }
+      _pipeBitInfos.sort( PipeBitInfoComparator.getInstance() );
+      fireContentsChanged( this, 0, _pipeBitInfos.size() );
+   }
+
+   /**
+    * @param pipeBitInfo -
+    * @return the actual pipeline bit class
+    */
+   public Class<?> getPipeBit( final PipeBitInfo pipeBitInfo ) {
+      return _pipeBitMap.get( pipeBitInfo );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int getSize() {
+      return _pipeBitInfos.size();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public PipeBitInfo getElementAt( final int index ) {
+      return _pipeBitInfos.get( index );
+   }
+
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/available/AvailablesRenderer.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/available/AvailablesRenderer.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/available/AvailablesRenderer.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/available/AvailablesRenderer.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,84 @@
+package org.apache.ctakes.gui.pipeline.bit.available;
+
+import org.apache.ctakes.gui.component.CellRendererPanel;
+import org.apache.ctakes.gui.pipeline.bit.PipeBitPainter;
+import org.apache.ctakes.gui.util.IconLoader;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+import java.awt.*;
+import java.util.logging.Logger;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/23/2017
+ */
+final public class AvailablesRenderer implements ListCellRenderer<Object> {
+
+   static private final Logger LOGGER = Logger.getLogger( "AvailablesRenderer" );
+
+   static private final Border SELECTED_BORDER = new LineBorder( Color.DARK_GRAY, 1, true );
+   static private final Border UNSELECTED_BORDER = new EmptyBorder( 0, 0, 0, 5 );
+
+   private final ListCellRenderer<Object> _delegate = new DefaultListCellRenderer();
+   private JLabel _arrowLabel;
+
+   private final JPanel _focusRenderer;
+
+
+   public AvailablesRenderer() {
+      _focusRenderer = new CellRendererPanel( new BorderLayout() );
+      _focusRenderer.setBorder( new EmptyBorder( 0, 0, 0, 5 ) );
+      _arrowLabel = new JLabel();
+      _focusRenderer.add( _arrowLabel, BorderLayout.EAST );
+      SwingUtilities.invokeLater( new RightArrowIconLoader() );
+   }
+
+   @Override
+   public Component getListCellRendererComponent(
+         final JList<?> list,
+         final Object value,
+         final int index,
+         final boolean isSelected,
+         final boolean cellHasFocus ) {
+      final Component renderer = _delegate.getListCellRendererComponent( list, value, index, false, false );
+
+      PipeBitPainter.getInstance().paintObject( renderer, value, false );
+
+      final Point p = list.getMousePosition();
+      if ( p != null ) {
+         final int hoverIndex = list.locationToIndex( p );
+         if ( hoverIndex == index ) {
+            _focusRenderer.add( renderer, BorderLayout.CENTER );
+            if ( isSelected ) {
+               _focusRenderer.setBorder( SELECTED_BORDER );
+            } else {
+               _focusRenderer.setBorder( UNSELECTED_BORDER );
+            }
+            return _focusRenderer;
+         }
+      }
+      if ( isSelected && renderer instanceof JComponent ) {
+         ((JComponent)renderer).setBorder( SELECTED_BORDER );
+      }
+      return renderer;
+   }
+
+
+   /**
+    * Simple Runnable that loads an icon
+    */
+   private final class RightArrowIconLoader implements Runnable {
+      @Override
+      public void run() {
+         final String dir = "org/apache/ctakes/gui/pipeline/icon/";
+         final String file = "BlueRightArrow.png";
+         final Icon icon = IconLoader.loadIcon( dir + file );
+         _arrowLabel.setIcon( icon );
+      }
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoComparator.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoComparator.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoComparator.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoComparator.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,98 @@
+package org.apache.ctakes.gui.pipeline.bit.info;
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.EnumMap;
+import java.util.Map;
+
+import static org.apache.ctakes.core.pipeline.PipeBitInfo.Role.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/23/2016
+ */
+public enum PipeBitInfoComparator implements Comparator<PipeBitInfo> {
+   INSTANCE;
+
+   static public PipeBitInfoComparator getInstance() {
+      return INSTANCE;
+   }
+
+   static private final Map<PipeBitInfo.Role, Integer> ROLE_ORDER = new EnumMap<>( PipeBitInfo.Role.class );
+
+   static {
+      ROLE_ORDER.put( READER, 1 );
+      ROLE_ORDER.put( ANNOTATOR, 2 );
+      ROLE_ORDER.put( WRITER, 3 );
+      ROLE_ORDER.put( SPECIAL, 4 );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int compare( final PipeBitInfo info1, final PipeBitInfo info2 ) {
+      if ( info1.role() != info2.role() ) {
+         return compareByRole( info1, info2 );
+      }
+      final int depends = compareByDependency( info1, info2 );
+      if ( depends != 0 ) {
+         return depends;
+      }
+      final int usable = compareByMax( info1.usables(), info2.usables() );
+      if ( usable != 0 ) {
+         return usable;
+      }
+      return info1.name().compareTo( info2.name() );
+   }
+
+   static private int compareByRole( final PipeBitInfo info1, final PipeBitInfo info2 ) {
+      return ROLE_ORDER.get( info1.role() ) - ROLE_ORDER.get( info2.role() );
+   }
+
+   static private int compareByMax( final PipeBitInfo.TypeProduct[] types1, final PipeBitInfo.TypeProduct[] types2 ) {
+      final int max1 = Arrays.stream( types1 ).mapToInt( Enum::ordinal ).max().orElse( 0 );
+      final int max2 = Arrays.stream( types2 ).mapToInt( Enum::ordinal ).max().orElse( 0 );
+      return max1 - max2;
+   }
+
+   static private int compareBySum( final PipeBitInfo.TypeProduct[] types1, final PipeBitInfo.TypeProduct[] types2 ) {
+      final int sum1 = Arrays.stream( types1 ).mapToInt( Enum::ordinal ).sum();
+      final int sum2 = Arrays.stream( types2 ).mapToInt( Enum::ordinal ).sum();
+      return sum1 - sum2;
+   }
+
+   static private int compareByDependency( final PipeBitInfo info1, final PipeBitInfo info2 ) {
+      // The info with the lower dependency should go first
+      final int dependMax = compareByMax( info1.dependencies(), info2.dependencies() );
+      if ( dependMax != 0 ) {
+         return dependMax;
+      }
+      // The info with the lower production should go first
+      final int produceMax = compareByMax( info1.products(), info2.products() );
+      if ( produceMax != 0 ) {
+         return produceMax;
+      }
+      // The info with the lowest sum dependencies should go first
+      final int dependSum = compareBySum( info1.dependencies(), info2.dependencies() );
+      if ( dependSum != 0 ) {
+         return dependSum;
+      }
+      // The info with the lowest sum products should go first
+      final int produceSum = compareBySum( info1.products(), info2.products() );
+      if ( produceSum != 0 ) {
+         return produceSum;
+      }
+      // The info with the lower number of dependencies should go first
+      if ( info1.dependencies().length != info2.dependencies().length ) {
+         return info1.dependencies().length - info2.dependencies().length;
+      }
+      // The info with the lower number of products should go first
+      return info1.products().length - info2.products().length;
+   }
+
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoPanel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoPanel.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoPanel.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoPanel.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,90 @@
+package org.apache.ctakes.gui.pipeline.bit.info;
+
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.gui.pipeline.bit.BitInfoPanel;
+import org.apache.ctakes.gui.pipeline.bit.available.AvailablesListModel;
+import org.apache.ctakes.gui.pipeline.bit.parameter.DefaultParameterHolder;
+import org.apache.ctakes.gui.pipeline.bit.parameter.ParameterHolder;
+import org.apache.ctakes.gui.pipeline.bit.parameter.ParameterInfoPanel;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/5/2017
+ */
+final public class PipeBitInfoPanel extends BitInfoPanel {
+
+   static private final Logger LOGGER = Logger.getLogger( "PipeBitInfoPanel" );
+
+   public void setPipeBitInfoList( final JList<PipeBitInfo> pipeBitList ) {
+      pipeBitList.getSelectionModel().addListSelectionListener( new PipeBitListListener( pipeBitList ) );
+   }
+
+   @Override
+   protected String getNameLabelPrefix() {
+      return "Pipe";
+   }
+
+   @Override
+   protected JComponent createNameEditor() {
+      return new JLabel();
+   }
+
+   @Override
+   protected void setBitName( final String text ) {
+      ((JLabel)_name).setText( text );
+   }
+
+   @Override
+   protected ParameterInfoPanel createParameterInfoPanel() {
+      return new ParameterInfoPanel();
+   }
+
+
+   private void setPipeBit( final PipeBitInfo info, final Class<?> pipeBitClass ) {
+      if ( info == null ) {
+         clear();
+         return;
+      }
+      setBitName( info.name() );
+      _description.setText( info.description() );
+      _dependencies.setText( Arrays.stream( info.dependencies() )
+            .map( PipeBitInfo.TypeProduct::toString )
+            .collect( Collectors.joining( ", " ) ) );
+      _usables.setText( Arrays.stream( info.usables() )
+            .map( PipeBitInfo.TypeProduct::toString )
+            .collect( Collectors.joining( ", " ) ) );
+      _outputs.setText( Arrays.stream( info.products() )
+            .map( PipeBitInfo.TypeProduct::toString )
+            .collect( Collectors.joining( ", " ) ) );
+      final ParameterHolder holder = new DefaultParameterHolder( pipeBitClass );
+      _parameterTableModel.setParameterHolder( holder );
+      _parameterInfoPanel.setParameterHolder( holder );
+   }
+
+   private class PipeBitListListener implements ListSelectionListener {
+      private final JList<PipeBitInfo> __pipeBitList;
+
+      private PipeBitListListener( final JList<PipeBitInfo> pipeBitList ) {
+         __pipeBitList = pipeBitList;
+      }
+
+      @Override
+      public void valueChanged( final ListSelectionEvent event ) {
+         if ( event.getValueIsAdjusting() ) {
+            return;
+         }
+         final PipeBitInfo pipeBitInfo = __pipeBitList.getSelectedValue();
+         setPipeBit( pipeBitInfo, ((AvailablesListModel)__pipeBitList.getModel()).getPipeBit( pipeBitInfo ) );
+      }
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoRenderer.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoRenderer.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoRenderer.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/PipeBitInfoRenderer.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,109 @@
+package org.apache.ctakes.gui.pipeline.bit.info;
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.gui.component.CellRendererLabel;
+import org.apache.ctakes.gui.component.CellRendererPanel;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Arrays;
+import java.util.Objects;
+
+import static org.apache.ctakes.core.pipeline.PipeBitInfo.TypeProduct;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/24/2017
+ */
+final public class PipeBitInfoRenderer implements ListCellRenderer<Object> {
+
+   static private final Logger LOGGER = Logger.getLogger( "PipeBitInfoRenderer" );
+
+   static private final Color READER_COLOR = Color.GREEN.darker().darker();
+   static private final Color ANNOTATOR_COLOR = Color.CYAN.darker().darker();
+   static private final Color WRITER_COLOR = Color.BLUE;
+   static private final Color SPECIAL_COLOR = Color.MAGENTA.darker();
+
+   static private final LayoutManager EMPTY_LAYOUT = new GridLayout( 1, 1 );
+
+   private final JPanel _renderer = new CellRendererPanel( new BorderLayout( 5, 0 ) );
+   private final JPanel _dependencies = new CellRendererPanel( EMPTY_LAYOUT );
+   private final JLabel _textLabel = new CellRendererLabel();
+   private final JPanel _products = new CellRendererPanel( EMPTY_LAYOUT );
+
+
+   public PipeBitInfoRenderer() {
+      _dependencies.setBackground( null );
+      _textLabel.setBackground( null );
+      _products.setBackground( null );
+      _renderer.add( _dependencies, BorderLayout.WEST );
+      _renderer.add( _textLabel, BorderLayout.CENTER );
+      _renderer.add( _products, BorderLayout.EAST );
+   }
+
+   @Override
+   public Component getListCellRendererComponent(
+         final JList<?> list,
+         final Object value,
+         final int index,
+         final boolean isSelected,
+         final boolean cellHasFocus ) {
+      _dependencies.removeAll();
+      _products.removeAll();
+
+      if ( isSelected ) {
+         _renderer.setBackground( list.getSelectionBackground() );
+         _textLabel.setForeground( list.getSelectionForeground() );
+      } else {
+         _renderer.setBackground( list.getBackground() );
+      }
+      if ( !PipeBitInfo.class.isInstance( value ) ) {
+         LOGGER.error( value.getClass().getName() + " is not a PipeBitInfo" );
+         _dependencies.setLayout( EMPTY_LAYOUT );
+         _products.setLayout( EMPTY_LAYOUT );
+         _textLabel.setText( "Invalid" );
+         _renderer.setBackground( Color.DARK_GRAY );
+         _renderer.setToolTipText( "Invalid Information" );
+         return _renderer;
+      }
+      final PipeBitInfo info = (PipeBitInfo)value;
+
+      if ( !isSelected ) {
+         final Color color = getColor( info.role() );
+         _textLabel.setForeground( color );
+      }
+      _textLabel.setText( info.name() );
+
+      createTypeIcons( _dependencies, info.dependencies() );
+      createTypeIcons( _products, info.products() );
+
+      return _renderer;
+   }
+
+   static private Color getColor( final PipeBitInfo.Role role ) {
+      switch ( role ) {
+         case READER:
+            return READER_COLOR;
+         case ANNOTATOR:
+            return ANNOTATOR_COLOR;
+         case WRITER:
+            return WRITER_COLOR;
+         case SPECIAL:
+            return SPECIAL_COLOR;
+      }
+      return Color.GRAY;
+   }
+
+   static private void createTypeIcons( final JPanel panel, final TypeProduct... types ) {
+      panel.setLayout( new GridLayout( 1, types.length ) );
+      Arrays.stream( types )
+            .map( ProductIconFactory.getInstance()::getIcon )
+            .filter( Objects::nonNull )
+            .map( CellRendererLabel::new )
+            .forEach( panel::add );
+   }
+
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/ProductIconFactory.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/ProductIconFactory.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/ProductIconFactory.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/ProductIconFactory.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,79 @@
+package org.apache.ctakes.gui.pipeline.bit.info;
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.gui.util.ColorFactory;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.geom.GeneralPath;
+import java.awt.image.BufferedImage;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.Map;
+
+import static org.apache.ctakes.core.pipeline.PipeBitInfo.TypeProduct;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/25/2017
+ */
+public enum ProductIconFactory {
+   INSTANCE;
+
+   public static ProductIconFactory getInstance() {
+      return INSTANCE;
+   }
+
+
+   private final Map<TypeProduct, Icon> _typeProductIcons = new EnumMap<>( TypeProduct.class );
+
+   ProductIconFactory() {
+//      SwingUtilities.invokeLater( new ProductIconMaker() );
+      new ProductIconMaker().run();
+   }
+
+   public Icon getIcon( final TypeProduct typeProduct ) {
+      return _typeProductIcons.get( typeProduct );
+   }
+
+   private final class ProductIconMaker implements Runnable {
+      private final Stroke LINE_STROKE = new BasicStroke( 4.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND );
+      private final Font HINT_FONT = new Font( "Dialog", Font.BOLD, 12 );
+
+      @Override
+      public void run() {
+         Arrays.stream( PipeBitInfo.TypeProduct.values() )
+               .forEach( tp -> _typeProductIcons.put( tp, createIcon( tp ) ) );
+      }
+
+      private Icon createIcon( final PipeBitInfo.TypeProduct typeProduct ) {
+         final Image image = new BufferedImage( 20, 20, BufferedImage.TYPE_3BYTE_BGR );
+         final Graphics2D g2 = (Graphics2D)image.getGraphics();
+         g2.setColor( UIManager.getColor( "List.background" ) );
+         g2.fillRect( 0, 0, 20, 20 );
+
+         g2.setColor( Color.LIGHT_GRAY );
+         g2.drawOval( 2, 2, 17, 17 );
+
+         final String name = typeProduct.name();
+         final Color color = ColorFactory.getColor( name );
+         g2.setColor( ColorFactory.addTransparency( color, 159 ) );
+         g2.setFont( HINT_FONT );
+         g2.drawString( typeProduct.name().charAt( 0 ) + "", 4, 15 );
+
+         final GeneralPath linePath = new GeneralPath( GeneralPath.WIND_EVEN_ODD, 3 );
+         final int[] xArray = { 11, 17, 11 };
+         final int[] yArray = { 3, 9, 17 };
+         linePath.moveTo( xArray[ 0 ], yArray[ 0 ] );
+         for ( int i = 1; i < xArray.length; i++ ) {
+            linePath.lineTo( xArray[ i ], yArray[ i ] );
+         }
+         g2.setStroke( LINE_STROKE );
+         g2.draw( linePath );
+
+         return new ImageIcon( image );
+      }
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/RoleRenderer.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/RoleRenderer.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/RoleRenderer.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/RoleRenderer.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,97 @@
+package org.apache.ctakes.gui.pipeline.bit.info;
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.gui.component.CellRendererLabel;
+import org.apache.ctakes.gui.util.IconLoader;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/24/2017
+ */
+final public class RoleRenderer implements ListCellRenderer<Object> {
+
+   static private final Logger LOGGER = Logger.getLogger( "RoleRenderer" );
+
+   static private final String READER_ICON_FILE = "GreenArrowIn.png";
+   static private final String ANNOTATOR_ICON_FILE = "BlueGear.png";
+   static private final String WRITER_ICON_FILE = "BlueArrowOut.png";
+   static private final String SPECIAL_ICON_FILE = "Utilities.png";
+
+   private final JLabel _reader = new CellRendererLabel();
+   private final JLabel _annotator = new CellRendererLabel();
+   private final JLabel _writer = new CellRendererLabel();
+   private final JLabel _special = new CellRendererLabel();
+
+   public RoleRenderer() {
+      decorate( _reader );
+      decorate( _annotator );
+      decorate( _writer );
+      decorate( _special );
+      SwingUtilities.invokeLater( new RoleIconLoader() );
+   }
+
+   static private void decorate( final JLabel renderer ) {
+      final Color background = UIManager.getColor( "List.background" );
+      renderer.setBackground( background );
+      renderer.setBorder( new EmptyBorder( 0, 2, 0, 2 ) );
+   }
+
+   @Override
+   public Component getListCellRendererComponent(
+         final JList<?> list,
+         final Object value,
+         final int index,
+         final boolean isSelected,
+         final boolean cellHasFocus ) {
+      if ( !PipeBitInfo.class.isInstance( value ) ) {
+         LOGGER.error( value.getClass().getName() + " is not a PipeBitInfo" );
+         final JLabel renderer = new JLabel( "Invalid" );
+         renderer.setBackground( Color.DARK_GRAY );
+         renderer.setToolTipText( "Invalid Information" );
+         return renderer;
+      }
+      final PipeBitInfo info = (PipeBitInfo)value;
+      switch ( info.role() ) {
+         case READER:
+            return _reader;
+         case ANNOTATOR:
+            return _annotator;
+         case WRITER:
+            return _writer;
+         case SPECIAL:
+            return _special;
+      }
+      return new JLabel();
+   }
+
+   /**
+    * Simple Callable that loads and resizes an icon
+    */
+   private final class RoleIconLoader implements Runnable {
+      static private final int ICON_SIZE = 16;
+      static private final String ICON_DIR = "org/apache/ctakes/gui/pipeline/icon/";
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public void run() {
+         final Icon reader = IconLoader.loadIcon( ICON_DIR + READER_ICON_FILE, ICON_SIZE );
+         _reader.setIcon( reader );
+         final Icon annotator = IconLoader.loadIcon( ICON_DIR + ANNOTATOR_ICON_FILE, ICON_SIZE );
+         _annotator.setIcon( annotator );
+         final Icon writer = IconLoader.loadIcon( ICON_DIR + WRITER_ICON_FILE, ICON_SIZE );
+         _writer.setIcon( writer );
+         final Icon special = IconLoader.loadIcon( ICON_DIR + SPECIAL_ICON_FILE, ICON_SIZE );
+         _special.setIcon( special );
+      }
+   }
+
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/TypeProductListModel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/TypeProductListModel.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/TypeProductListModel.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/TypeProductListModel.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,65 @@
+package org.apache.ctakes.gui.pipeline.bit.info;
+
+import javax.swing.*;
+import javax.swing.event.ListDataListener;
+import java.util.logging.Logger;
+
+import static org.apache.ctakes.core.pipeline.PipeBitInfo.TypeProduct;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/25/2017
+ */
+final public class TypeProductListModel implements ListModel<TypeProduct> {
+
+   static private final Logger LOGGER = Logger.getLogger( "TypeProductListModel" );
+
+   private final TypeProduct[] _typeProducts;
+
+   public TypeProductListModel() {
+      _typeProducts = new TypeProduct[ TypeProduct.values().length - 1 ];
+      int i = 0;
+      for ( TypeProduct typeProduct : TypeProduct.values() ) {
+         if ( typeProduct != TypeProduct.TOP ) {
+            _typeProducts[ i ] = typeProduct;
+            i++;
+         }
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int getSize() {
+      return _typeProducts.length;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public TypeProduct getElementAt( final int index ) {
+      return _typeProducts[ index ];
+   }
+
+   /**
+    * does nothing.
+    *
+    * @param l -
+    */
+   @Override
+   public void addListDataListener( final ListDataListener l ) {
+   }
+
+   /**
+    * does nothing.
+    *
+    * @param l -
+    */
+   @Override
+   public void removeListDataListener( final ListDataListener l ) {
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/TypeProductRenderer.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/TypeProductRenderer.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/TypeProductRenderer.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/info/TypeProductRenderer.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,54 @@
+package org.apache.ctakes.gui.pipeline.bit.info;
+
+
+import org.apache.ctakes.gui.component.CellRendererLabel;
+import org.apache.ctakes.gui.util.ColorFactory;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import java.awt.*;
+
+import static org.apache.ctakes.core.pipeline.PipeBitInfo.TypeProduct;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/25/2017
+ */
+final public class TypeProductRenderer implements ListCellRenderer<Object> {
+
+   static private final Logger LOGGER = Logger.getLogger( "TypeProductRenderer" );
+
+   private final JLabel _delegate = new CellRendererLabel();
+
+   public TypeProductRenderer() {
+      _delegate.setBackground( UIManager.getColor( "List.background" ) );
+   }
+
+   @Override
+   public Component getListCellRendererComponent(
+         final JList<?> list,
+         final Object value,
+         final int index,
+         final boolean isSelected,
+         final boolean cellHasFocus ) {
+      if ( !TypeProduct.class.isInstance( value ) ) {
+         LOGGER.error( value.getClass().getName() + " is not a TypeProduct" );
+         _delegate.setIcon( null );
+         _delegate.setText( "Invalid" );
+         _delegate.setToolTipText( "Invalid Information" );
+         return _delegate;
+      }
+
+      final TypeProduct typeProduct = (TypeProduct)value;
+      final Icon icon = ProductIconFactory.getInstance().getIcon( typeProduct );
+      _delegate.setIcon( icon );
+      final String name = typeProduct.name();
+      final Color color = ColorFactory.getColor( name );
+      _delegate.setForeground( color );
+      final String prettyName = name.charAt( 0 ) + name.substring( 1, name.length() );
+      _delegate.setText( prettyName );
+      return _delegate;
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/DefaultParameterHolder.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/DefaultParameterHolder.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/DefaultParameterHolder.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/DefaultParameterHolder.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,90 @@
+package org.apache.ctakes.gui.pipeline.bit.parameter;
+
+
+import org.apache.log4j.Logger;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+
+import javax.annotation.concurrent.Immutable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/20/2017
+ */
+@Immutable
+final public class DefaultParameterHolder implements ParameterHolder {
+
+   static private final Logger LOGGER = Logger.getLogger( "DefaultParameterHolder" );
+
+   private final List<ConfigurationParameter> _parameters;
+   private final Map<ConfigurationParameter, String> _typeMap;
+
+   /**
+    * @param pipeBitClass -
+    */
+   public DefaultParameterHolder( final Class<?> pipeBitClass ) {
+      _typeMap = ParameterMapper.createParameterTypeMap( pipeBitClass );
+      _parameters = new ArrayList<>( _typeMap.keySet() );
+      _parameters.sort( ( p1, p2 ) -> p1.name().compareToIgnoreCase( p2.name() ) );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int getParameterCount() {
+      return _parameters.size();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public ConfigurationParameter getParameter( final int index ) {
+      return _parameters.get( index );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getParameterClass( final int index ) {
+      return _typeMap.get( getParameter( index ) );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getParameterName( final int index ) {
+      return _parameters.get( index ).name();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getParameterDescription( final int index ) {
+      return _parameters.get( index ).description();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean isParameterMandatory( final int index ) {
+      return _parameters.get( index ).mandatory();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String[] getParameterValue( final int index ) {
+      return _parameters.get( index ).defaultValue();
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterCellRenderer.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterCellRenderer.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterCellRenderer.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterCellRenderer.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,33 @@
+package org.apache.ctakes.gui.pipeline.bit.parameter;
+
+import org.apache.log4j.Logger;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+
+import javax.swing.*;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellRenderer;
+import java.awt.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/20/2017
+ */
+final public class ParameterCellRenderer implements TableCellRenderer {
+
+   static private final Logger LOGGER = Logger.getLogger( "ParameterCellRenderer" );
+
+   private final TableCellRenderer _delegate = new DefaultTableCellRenderer();
+
+   public Component getTableCellRendererComponent( final JTable table, final Object value,
+                                                   final boolean isSelected, final boolean hasFocus,
+                                                   final int row, final int column ) {
+      final Component renderer = _delegate
+            .getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
+      if ( renderer instanceof JLabel && value instanceof ConfigurationParameter ) {
+         ((JLabel)renderer).setText( ((ConfigurationParameter)value).name() );
+      }
+      return renderer;
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterHolder.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterHolder.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterHolder.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterHolder.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,27 @@
+package org.apache.ctakes.gui.pipeline.bit.parameter;
+
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/20/2017
+ */
+public interface ParameterHolder {
+
+   int getParameterCount();
+
+   ConfigurationParameter getParameter( int index );
+
+   String getParameterClass( int index );
+
+   String getParameterName( int index );
+
+   String getParameterDescription( int index );
+
+   boolean isParameterMandatory( int index );
+
+   String[] getParameterValue( int index );
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterInfoPanel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterInfoPanel.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterInfoPanel.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterInfoPanel.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,137 @@
+package org.apache.ctakes.gui.pipeline.bit.parameter;
+
+import org.apache.log4j.Logger;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import java.awt.*;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/20/2017
+ */
+public class ParameterInfoPanel extends JPanel {
+
+   static private final Logger LOGGER = Logger.getLogger( "ParameterInfoPanel" );
+
+
+   private JLabel _name;
+   private JLabel _type;
+   private JLabel _description;
+   private JLabel _mandatory;
+   protected JComponent _values;
+
+   private ParameterHolder _holder;
+
+   public ParameterInfoPanel() {
+      super( new GridLayout( 5, 1 ) );
+
+      _name = new JLabel();
+      final JComponent namePanel = createNamePanel( "Parameter Name:", _name );
+      _type = new JLabel();
+      final JComponent typePanel = createNamePanel( "Parameter Type:", _type );
+      _description = new JLabel();
+      final JComponent descPanel = createNamePanel( "Description:", _description );
+      _mandatory = new JLabel();
+      final JComponent mandatoryPanel = createNamePanel( "Mandatory:", _mandatory );
+      _values = createValuesEditor();
+      final JComponent valuesPanel = createNamePanel( getValueLabelPrefix() + " Values:", _values );
+
+      add( namePanel );
+      add( typePanel );
+      add( descPanel );
+      add( mandatoryPanel );
+      add( valuesPanel );
+   }
+
+   protected String getValueLabelPrefix() {
+      return "Default";
+   }
+
+   protected JComponent createValuesEditor() {
+      return new JLabel();
+   }
+
+   protected void setParameterValues( final String values ) {
+      ((JLabel)_values).setText( values );
+   }
+
+   private JComponent createNamePanel( final String name, final JComponent namedLabel ) {
+      final JPanel panel = new JPanel( new BorderLayout( 10, 10 ) );
+      panel.setBorder( new EmptyBorder( 2, 10, 2, 10 ) );
+      final JLabel label = new JLabel( name );
+      label.setPreferredSize( new Dimension( 90, 20 ) );
+      label.setHorizontalAlignment( SwingConstants.TRAILING );
+      final Border emptyBorder = new EmptyBorder( 0, 10, 0, 0 );
+      final Border border
+            = new CompoundBorder( UIManager.getLookAndFeelDefaults().getBorder( "TextField.border" ), emptyBorder );
+      namedLabel.setBorder( border );
+      panel.add( label, BorderLayout.WEST );
+      panel.add( namedLabel, BorderLayout.CENTER );
+      return panel;
+   }
+
+   private void clear() {
+      _name.setText( "" );
+      _type.setText( "" );
+      _description.setText( "" );
+      _mandatory.setText( "" );
+      setParameterValues( "" );
+   }
+
+   public void setParameterHolder( final ParameterHolder holder ) {
+      _holder = holder;
+      clear();
+   }
+
+   private void setParameterIndex( final int index ) {
+      if ( index < 0 || _holder == null ) {
+         clear();
+         return;
+      }
+      _name.setText( _holder.getParameterName( index ) );
+      _type.setText( _holder.getParameterClass( index ) );
+      _description.setText( _holder.getParameterDescription( index ) );
+      _mandatory.setText( Boolean.toString( _holder.isParameterMandatory( index ) ) );
+      final String values = Arrays.stream( _holder.getParameterValue( index ) )
+            .filter( v -> !ConfigurationParameter.NO_DEFAULT_VALUE.equals( v ) )
+            .collect( Collectors.joining( " , " ) );
+      setParameterValues( values );
+   }
+
+   public void setParameterTable( final JTable parameterTable ) {
+      ListSelectionModel selectionModel = parameterTable.getSelectionModel();
+      selectionModel.addListSelectionListener( new ParameterTableListener( parameterTable ) );
+   }
+
+   private class ParameterTableListener implements ListSelectionListener {
+      private final JTable __parameterTable;
+
+      private ParameterTableListener( final JTable parameterTable ) {
+         __parameterTable = parameterTable;
+      }
+
+      @Override
+      public void valueChanged( final ListSelectionEvent event ) {
+         if ( event.getValueIsAdjusting() ) {
+            return;
+         }
+         final int[] selectedRows = __parameterTable.getSelectedRows();
+         if ( selectedRows.length == 0 ) {
+            setParameterIndex( -1 );
+         } else {
+            setParameterIndex( selectedRows[ 0 ] );
+         }
+      }
+   }
+
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterMapper.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterMapper.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterMapper.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterMapper.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,69 @@
+package org.apache.ctakes.gui.pipeline.bit.parameter;
+
+
+import org.apache.log4j.Logger;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 3/19/2017
+ */
+final public class ParameterMapper {
+
+   static private final Logger LOGGER = Logger.getLogger( "ParameterMapper" );
+
+   private ParameterMapper() {
+   }
+
+   /**
+    * @param pipeBitClass -
+    * @return Configuration Parameters and Field class types for the Pipe Bit and all of its parent classes
+    */
+   static public Map<ConfigurationParameter, String> createParameterTypeMap( final Class<?> pipeBitClass ) {
+      final Map<ConfigurationParameter, String> parameterMap = new HashMap<>();
+      final Collection<Class<?>> inheritables = new ArrayList<>();
+      final Class<?>[] interfaces = pipeBitClass.getInterfaces();
+      if ( interfaces != null && interfaces.length > 0 ) {
+         inheritables.addAll( Arrays.asList( interfaces ) );
+      }
+      if ( pipeBitClass.getSuperclass() != null ) {
+         inheritables.add( pipeBitClass.getSuperclass() );
+      }
+      inheritables.stream().map( ParameterMapper::createParameterTypeMap ).forEach( parameterMap::putAll );
+      final Field[] fields = pipeBitClass.getDeclaredFields();
+      Arrays.stream( fields )
+            .filter( f -> f.getAnnotation( ConfigurationParameter.class ) != null )
+            .forEach( f -> parameterMap
+                  .put( f.getAnnotation( ConfigurationParameter.class ), f.getType().getSimpleName() ) );
+      return parameterMap;
+   }
+
+
+   /**
+    * @param pipeBitClass -
+    * @return Configuration Parameters and default values for the Pipe Bit and all of its parent classes
+    */
+   static public Map<ConfigurationParameter, String[]> createParameterDefaultsMap( final Class<?> pipeBitClass ) {
+      final Map<ConfigurationParameter, String[]> parameterMap = new HashMap<>();
+      final Collection<Class<?>> inheritables = new ArrayList<>();
+      final Class<?>[] interfaces = pipeBitClass.getInterfaces();
+      if ( interfaces != null && interfaces.length > 0 ) {
+         inheritables.addAll( Arrays.asList( interfaces ) );
+      }
+      if ( pipeBitClass.getSuperclass() != null ) {
+         inheritables.add( pipeBitClass.getSuperclass() );
+      }
+      inheritables.stream().map( ParameterMapper::createParameterDefaultsMap ).forEach( parameterMap::putAll );
+      final Field[] fields = pipeBitClass.getDeclaredFields();
+      Arrays.stream( fields )
+            .map( f -> f.getAnnotation( ConfigurationParameter.class ) )
+            .filter( Objects::nonNull )
+            .forEach( cp -> parameterMap.put( cp, cp.defaultValue() ) );
+      return parameterMap;
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterTableModel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterTableModel.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterTableModel.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/parameter/ParameterTableModel.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,157 @@
+package org.apache.ctakes.gui.pipeline.bit.parameter;
+
+
+import org.apache.log4j.Logger;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+
+import javax.swing.event.EventListenerList;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.TableModel;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/5/2017
+ */
+final public class ParameterTableModel implements TableModel {
+
+   static private final Logger LOGGER = Logger.getLogger( "ParameterTableModel" );
+
+   static private final String[] COLUMN_NAMES = { "Parameter Name", "Value" };
+   static private final Class<?>[] COLUMN_CLASSES = { ConfigurationParameter.class, String[].class };
+
+   private final EventListenerList _listenerList = new EventListenerList();
+
+   private ParameterHolder _parameterHolder;
+
+   /**
+    * Populate the list
+    *
+    * @param holder - holder with all parameter information
+    */
+   public void setParameterHolder( final ParameterHolder holder ) {
+      final int oldSize = _parameterHolder == null ? 0 : _parameterHolder.getParameterCount();
+      _parameterHolder = holder;
+      if ( holder == null ) {
+         if ( oldSize > 0 ) {
+            fireTableChanged(
+                  new TableModelEvent( this, 0, oldSize - 1, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE ) );
+         }
+         return;
+      }
+      if ( holder.getParameterCount() > 0 ) {
+         fireTableChanged( new TableModelEvent( this ) );
+      } else if ( oldSize > 0 ) {
+         fireTableChanged(
+               new TableModelEvent( this, 0, oldSize - 1, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE ) );
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int getRowCount() {
+      if ( _parameterHolder == null ) {
+         return 0;
+      }
+      return _parameterHolder.getParameterCount();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int getColumnCount() {
+      return COLUMN_NAMES.length;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getColumnName( final int columnIndex ) {
+      return COLUMN_NAMES[ columnIndex ];
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Class<?> getColumnClass( final int columnIndex ) {
+      return COLUMN_CLASSES[ columnIndex ];
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean isCellEditable( final int rowIndex, final int columnIndex ) {
+      return false;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Object getValueAt( final int rowIndex, final int columnIndex ) {
+      switch ( columnIndex ) {
+         case 0:
+            return _parameterHolder.getParameter( rowIndex );
+         case 1:
+            return Arrays.stream( _parameterHolder.getParameterValue( rowIndex ) )
+                  .filter( v -> !ConfigurationParameter.NO_DEFAULT_VALUE.equals( v ) )
+                  .collect( Collectors.joining( " , " ) );
+      }
+      return "ERROR";
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void setValueAt( final Object aValue, final int rowIndex, final int columnIndex ) {
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void addTableModelListener( final TableModelListener listener ) {
+      _listenerList.add( TableModelListener.class, listener );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void removeTableModelListener( final TableModelListener listener ) {
+      _listenerList.remove( TableModelListener.class, listener );
+   }
+
+   /**
+    * Forwards the given notification event to all
+    * <code>TableModelListeners</code> that registered
+    * themselves as listeners for this table model.
+    *
+    * @param event the event to be forwarded
+    * @see #addTableModelListener
+    * @see TableModelEvent
+    * @see EventListenerList
+    */
+   private void fireTableChanged( final TableModelEvent event ) {
+      // Guaranteed to return a non-null array
+      Object[] listeners = _listenerList.getListenerList();
+      // Process the listeners last to first, notifying
+      // those that are interested in this event
+      for ( int i = listeners.length - 2; i >= 0; i -= 2 ) {
+         if ( listeners[ i ] == TableModelListener.class ) {
+            ((TableModelListener)listeners[ i + 1 ]).tableChanged( event );
+         }
+      }
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/user/DefaultUserBit.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/user/DefaultUserBit.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/user/DefaultUserBit.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/user/DefaultUserBit.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,137 @@
+package org.apache.ctakes.gui.pipeline.bit.user;
+
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.gui.pipeline.bit.parameter.ParameterMapper;
+import org.apache.log4j.Logger;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/19/2017
+ */
+final public class DefaultUserBit implements UserBit {
+
+   static private final Logger LOGGER = Logger.getLogger( "DefaultUserBit" );
+
+   private final PipeBitInfo _pipeBitInfo;
+   private final Class<?> _pipeBitClass;
+   private String _name;
+   private final List<ConfigurationParameter> _parameters;
+   private final Map<ConfigurationParameter, String> _typeMap;
+   private final Map<ConfigurationParameter, String[]> _parameterValues;
+
+   public DefaultUserBit( final PipeBitInfo pipeBitInfo, final Class<?> pipeBitClass ) {
+      _pipeBitInfo = pipeBitInfo;
+      _pipeBitClass = pipeBitClass;
+      _typeMap = ParameterMapper.createParameterTypeMap( pipeBitClass );
+      _parameterValues = ParameterMapper.createParameterDefaultsMap( pipeBitClass );
+      _parameters = new ArrayList<>( _typeMap.keySet() );
+      _parameters.sort( ( p1, p2 ) -> p1.name().compareToIgnoreCase( p2.name() ) );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getBitName() {
+      if ( _name == null || _name.isEmpty() ) {
+         return _pipeBitInfo.name();
+      }
+      return _name;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void setBitName( final String name ) {
+      _name = name;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public PipeBitInfo getPipeBitInfo() {
+      return _pipeBitInfo;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Class<?> getPipeBitClass() {
+      return _pipeBitClass;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int getParameterCount() {
+      return _parameters.size();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public ConfigurationParameter getParameter( final int index ) {
+      return _parameters.get( index );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getParameterClass( final int index ) {
+      return _typeMap.get( getParameter( index ) );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getParameterName( final int index ) {
+      return _parameters.get( index ).name();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getParameterDescription( final int index ) {
+      return _parameters.get( index ).description();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean isParameterMandatory( final int index ) {
+      return _parameters.get( index ).mandatory();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String[] getParameterValue( final int index ) {
+      return _parameterValues.get( getParameter( index ) );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void setParameterValue( final int index, final String... values ) {
+      _parameterValues.put( getParameter( index ), values );
+   }
+
+}

Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/user/UserBit.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/user/UserBit.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/user/UserBit.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/bit/user/UserBit.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,39 @@
+package org.apache.ctakes.gui.pipeline.bit.user;
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.gui.pipeline.bit.parameter.ParameterHolder;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 1/20/2017
+ */
+public interface UserBit extends ParameterHolder {
+
+   /**
+    * @return Human-readable name of the Reader, Annotator, or Writer
+    */
+   String getBitName();
+
+   /**
+    * @param name Human-readable name of the Reader, Annotator, or Writer
+    */
+   void setBitName( String name );
+
+   /**
+    * @return PipeBitInfo associated with this UserBit
+    */
+   PipeBitInfo getPipeBitInfo();
+
+   /**
+    * @return Reader, AE, Writer associated with this UserBit
+    */
+   Class<?> getPipeBitClass();
+
+   /**
+    * @param index  -
+    * @param values User Values for Configuration parameter at index
+    */
+   void setParameterValue( int index, String... values );
+
+}