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 [5/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/dictionary/umls/UmlsTermUtil.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/umls/UmlsTermUtil.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/umls/UmlsTermUtil.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/umls/UmlsTermUtil.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,325 @@
+package org.apache.ctakes.gui.dictionary.umls;
+
+import org.apache.ctakes.gui.dictionary.util.FileUtil;
+import org.apache.ctakes.gui.dictionary.util.RareWordUtil;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.function.Consumer;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+
+/**
+ * Contains all the methods used to parse individual text definitions of umls terms
+ * <p/>
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 1/16/14
+ */
+final public class UmlsTermUtil {
+
+
+ private enum DATA_FILE {
+ REMOVAL_PREFIX_TRIGGERS( "RemovalPrefixTriggers.txt" ),
+ REMOVAL_SUFFIX_TRIGGERS( "RemovalSuffixTriggers.txt" ),
+ REMOVAL_FUNCTION_TRIGGERS( "RemovalFunctionTriggers.txt" ),
+ REMOVAL_COLON_TRIGGERS( "RemovalColonTriggers.txt" ),
+ UNWANTED_PREFIXES( "UnwantedPrefixes.txt" ),
+ UNWANTED_SUFFIXES( "UnwantedSuffixes.txt" ),
+ UNWANTED_TEXTS( "UnwantedTexts.txt" ),
+ MODIFIER_SUFFIXES( "ModifierSuffixes.txt" ),
+ RIGHT_ABBREVIATIONS( "RightAbbreviations.txt" ),
+ KEEP_PREFIX_TRIGGERS( "KeepPrefixTriggers.txt" );
+ final private String __name;
+
+ DATA_FILE( final String name ) {
+ __name = name;
+ }
+ }
+
+ static private final Pattern WHITESPACE = Pattern.compile( "\\s+" );
+ static private final Pattern AUTO_NOTE = Pattern.compile( "@" );
+
+ static private String getDataPath( final String dataDir, final DATA_FILE dataFile ) {
+ return dataDir + '/' + dataFile.__name;
+ }
+
+ final private Collection<String> _removalPrefixTriggers;
+ final private Collection<String> _removalSuffixTriggers;
+ final private Collection<String> _removalColonTriggers;
+ final private Collection<String> _removalFunctionTriggers;
+ final private Collection<String> _unwantedPrefixes;
+ final private Collection<String> _unwantedSuffixes;
+ final private Collection<String> _unwantedTexts;
+ final private Collection<String> _modifierSuffixes;
+ final private Collection<String> _abbreviations;
+ final private Collection<String> _unwantedPosTexts;
+ final private Collection<String> _keepPrefixTriggers;
+
+ public UmlsTermUtil( final String dataDir ) {
+ this( getDataPath( dataDir, DATA_FILE.REMOVAL_PREFIX_TRIGGERS ),
+ getDataPath( dataDir, DATA_FILE.REMOVAL_SUFFIX_TRIGGERS ),
+ getDataPath( dataDir, DATA_FILE.REMOVAL_COLON_TRIGGERS ),
+ getDataPath( dataDir, DATA_FILE.REMOVAL_FUNCTION_TRIGGERS ),
+ getDataPath( dataDir, DATA_FILE.UNWANTED_PREFIXES ),
+ getDataPath( dataDir, DATA_FILE.UNWANTED_SUFFIXES ),
+ getDataPath( dataDir, DATA_FILE.UNWANTED_TEXTS ),
+ getDataPath( dataDir, DATA_FILE.MODIFIER_SUFFIXES ),
+ getDataPath( dataDir, DATA_FILE.RIGHT_ABBREVIATIONS ),
+ getDataPath( dataDir, DATA_FILE.KEEP_PREFIX_TRIGGERS ) );
+ }
+
+ public UmlsTermUtil( final String removalPrefixTriggersPath, final String removalSuffixTriggersPath,
+ final String removalColonTriggersPath, final String removalFunctionTriggersPath,
+ final String unwantedPrefixesPath, final String unwantedSuffixesPath,
+ final String unwantedTextsPath,
+ final String modifierSuffixesPath, final String abbreviationsPath,
+ final String keepPrefixTriggersPath ) {
+ _removalPrefixTriggers = FileUtil.readOneColumn( removalPrefixTriggersPath, "term removal Prefix Triggers" );
+ _removalSuffixTriggers = FileUtil.readOneColumn( removalSuffixTriggersPath, "term removal Suffix Triggers" );
+ _removalColonTriggers = FileUtil.readOneColumn( removalColonTriggersPath, "term removal Colon Triggers" );
+ _removalFunctionTriggers = FileUtil
+ .readOneColumn( removalFunctionTriggersPath, "term removal Function Triggers" );
+ _unwantedPrefixes = FileUtil.readOneColumn( unwantedPrefixesPath, "unwanted Prefixes" );
+ _unwantedSuffixes = FileUtil.readOneColumn( unwantedSuffixesPath, "unwanted Suffixes" );
+ _unwantedTexts = FileUtil.readOneColumn( unwantedTextsPath, "unwanted Texts" );
+ _modifierSuffixes = FileUtil.readOneColumn( modifierSuffixesPath, "modifier Suffixes" );
+ _abbreviations = FileUtil.readOneColumn( abbreviationsPath, "Abbreviations to expand" );
+ _keepPrefixTriggers = FileUtil.readOneColumn( keepPrefixTriggersPath, "term keep Prefix Triggers" );
+ _unwantedPosTexts = RareWordUtil.getUnwantedPosTexts();
+ }
+
+ public boolean isTextValid( final String text ) {
+ if ( _keepPrefixTriggers.stream().anyMatch( text::startsWith ) ) {
+ return true;
+ }
+
+ if ( text.startsWith( "fh " ) || text.startsWith( "no fh " )
+ || text.startsWith( "family " ) || text.startsWith( "history " ) ) {
+ return true;
+ }
+ // Check for illegal characters
+ boolean haveChar = false;
+ for ( int i = 0; i < text.length(); i++ ) {
+ if ( text.charAt( i ) < ' ' || text.charAt( i ) > '~' ) {
+ return false;
+ }
+ if ( !haveChar && Character.isAlphabetic( text.charAt( i ) ) ) {
+ haveChar = true;
+ }
+ }
+ if ( !haveChar ) {
+ return false;
+ }
+ if ( text.length() == 3 && text.charAt( 0 ) == '(' ) {
+ return false;
+ }
+ // Check for auto-created note form
+ if ( AUTO_NOTE.split( text ).length > 2 ) {
+ return false;
+ }
+ if ( _unwantedTexts.contains( text ) ) {
+ return false;
+ }
+ if ( _unwantedPosTexts.contains( text ) ) {
+ return false;
+ }
+ if ( _removalPrefixTriggers.stream().anyMatch( text::startsWith ) ) {
+ return false;
+ }
+ if ( _removalSuffixTriggers.stream().anyMatch( text::endsWith ) ) {
+ return false;
+ }
+ if ( _removalColonTriggers.stream().anyMatch( text::contains ) ) {
+ return false;
+ }
+ if ( _removalFunctionTriggers.stream().anyMatch( text::contains ) ) {
+ return false;
+ }
+ return true;
+ }
+
+ static public boolean isTextTooShort( final String text, final int minCharLength ) {
+ return text.length() < minCharLength;
+ }
+
+
+ static public boolean isTextTooLong( final String text, final int maxCharLength,
+ final int maxWordCount, final int maxSymCount ) {
+ final String[] splits = WHITESPACE.split( text );
+ int wordCount = 0;
+ int symCount = 0;
+ for ( String split : splits ) {
+ if ( split.length() > maxCharLength ) {
+ return true;
+ }
+ if ( split.length() > 2 ) {
+ wordCount++;
+ } else {
+ symCount++;
+ }
+ }
+ return wordCount > maxWordCount || symCount > maxSymCount;
+ }
+
+
+ public Collection<String> getFormattedTexts( final String strippedText, final boolean extractAbbreviations,
+ final int minCharLength, final int maxCharLength,
+ final int maxWordCount, final int maxSymCount ) {
+ Collection<String> extractedTerms = Collections.emptySet();
+ if ( extractAbbreviations ) {
+ // add embedded abbreviations
+ extractedTerms = extractAbbreviations( strippedText );
+ }
+ if ( extractedTerms.isEmpty() ) {
+ extractedTerms = extractModifiers( strippedText );
+ }
+ if ( !extractedTerms.isEmpty() ) {
+ extractedTerms.add( strippedText );
+ return getFormattedTexts( getPluralTerms( getStrippedTexts( extractedTerms ) ), minCharLength, maxCharLength, maxWordCount, maxSymCount );
+ }
+ Collection<String> texts = new HashSet<>( 1 );
+ texts.add( strippedText );
+ return getFormattedTexts( getPluralTerms( getStrippedTexts( texts ) ), minCharLength, maxCharLength, maxWordCount, maxSymCount );
+ }
+
+
+ static private Collection<String> getFormattedTexts( final Collection<String> extractedTerms,
+ final int minCharLength, final int maxCharLength,
+ final int maxWordCount, final int maxSymCount ) {
+ return extractedTerms.stream()
+ .filter( t -> !isTextTooShort( t, minCharLength ) )
+ .filter( t -> !isTextTooLong( t, maxCharLength, maxWordCount, maxSymCount ) )
+ .collect( Collectors.toList() );
+ }
+
+ static private Collection<String> getPluralTerms( final Collection<String> texts ) {
+ final Collection<String> plurals = texts.stream()
+ .filter( t -> t.endsWith( "( s )" ) )
+ .collect( Collectors.toList() );
+ if ( plurals.isEmpty() ) {
+ return texts;
+ }
+ texts.removeAll( plurals );
+ final Consumer<String> addPlural = t -> {
+ texts.add( t );
+ texts.add( t + "s" );
+ };
+ plurals.stream()
+ .map( t -> t.substring( 0, t.length() - 5 ) )
+ .forEach( addPlural );
+ return texts;
+ }
+
+ private Collection<String> getStrippedTexts( final Collection<String> texts ) {
+ return texts.stream()
+ .map( this::getStrippedText )
+ .filter( t -> !t.isEmpty() )
+ .collect( Collectors.toSet() );
+ }
+
+ public String getStrippedText( final String text ) {
+ // remove form underlines
+// if ( text.contains( "_ _ _" ) ) {
+// final int lastParen = text.lastIndexOf( '(' );
+// final int lastDash = text.indexOf( "_ _ _" );
+// final int deleteIndex = Math.max( 0, Math.min( lastParen, lastDash ) );
+// if ( deleteIndex > 0 ) {
+// return getStrippedText( text.substring( 0, deleteIndex - 1 ).trim() );
+// }
+// }
+ // remove unmatched parentheses, brackets, etc.
+ // if ( text.startsWith( "(" ) && !text.contains( ")" ) ) {
+ // return getStrippedText( text.substring( 1 ).trim() );
+ // }
+ // if ( text.startsWith( "[" ) && !text.contains( "]" ) ) {
+ // return getStrippedText( text.substring( 1 ).trim() );
+ // }
+ // if ( text.startsWith( "(" ) && text.endsWith( ") or" ) ) {
+ // return getStrippedText( text.substring( 1, text.length() - 4 ).trim() );
+ // }
+ // if ( text.startsWith( "or (" ) ) {
+ // return getStrippedText( text.substring( 2 ).trim() );
+ // }
+ // if ( text.startsWith( "\"" ) && text.endsWith( "\"" ) ) {
+ // return getStrippedText( text.substring( 1 ).trim() );
+ // }
+ // if ( text.startsWith( "(" ) && text.endsWith( ")" ) ) {
+ // return getStrippedText( text.substring( 1, text.length() - 2 ).trim() );
+ // }
+ // if ( text.startsWith( "[" ) && text.endsWith( "]" ) ) {
+ // return getStrippedText( text.substring( 1, text.length() - 2 ).trim() );
+ // }
+ // if ( text.startsWith( "&" ) ) {
+ // return getStrippedText( text.substring( 1 ).trim() );
+ // }
+ // if ( text.endsWith( "]" ) && !text.contains( "[" ) ) {
+ // return getStrippedText( text.substring( 0, text.length() - 2 ).trim() );
+ // }
+ // if ( text.endsWith( ")" ) && !text.contains( "(" ) ) {
+ // return getStrippedText( text.substring( 0, text.length() - 2 ).trim() );
+ // }
+ String strippedText = text.trim();
+ // Text in umls can have multiple suffixes and/or prefixes. Stripping just once doesn't do the trick
+ int lastLength = Integer.MAX_VALUE;
+ while ( lastLength != strippedText.length() ) {
+ lastLength = strippedText.length();
+ for ( String prefix : _unwantedPrefixes ) {
+ if ( strippedText.startsWith( prefix ) ) {
+ strippedText = strippedText.substring( prefix.length() ).trim();
+ }
+ }
+ for ( String suffix : _unwantedSuffixes ) {
+ if ( strippedText.endsWith( suffix ) ) {
+ strippedText = strippedText.substring( 0, strippedText.length() - suffix.length() ).trim();
+ }
+ }
+ if ( !isTextValid( strippedText ) ) {
+ return "";
+ }
+ }
+ if ( strippedText.contains( "(" ) && strippedText.contains( "[" ) ) {
+ return "";
+ }
+ return strippedText;
+ }
+
+
+ private Collection<String> extractAbbreviations( final String tokenizedText ) {
+ for ( String abbreviation : _abbreviations ) {
+ if ( tokenizedText.endsWith( abbreviation )
+ && !tokenizedText.contains( ":" ) && !tokenizedText.contains( " of " )
+ && !tokenizedText.contains( " for " ) ) {
+ final String noAbbrTerm
+ = tokenizedText.substring( 0, tokenizedText.length() - abbreviation.length() ).trim();
+ final String abbrTerm
+ = abbreviation.replace( ":", "" ).replace( "(", "" ).replace( ")", "" ).replace( "-", "" )
+ .replace( "[", "" ).replace( "]", "" ).replace( "&", "" ).trim();
+ final Collection<String> extractedAbbreviations = new HashSet<>( 2 );
+ extractedAbbreviations.add( noAbbrTerm );
+ extractedAbbreviations.add( abbrTerm );
+ return extractedAbbreviations;
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private Collection<String> extractModifiers( final String tokenizedText ) {
+ for ( String modifier : _modifierSuffixes ) {
+ if ( tokenizedText.endsWith( modifier ) ) {
+ final String mainText = tokenizedText.substring( 0, tokenizedText.length() - modifier.length() ).trim();
+ final String modifierText
+ = modifier.replace( "(", "" ).replace( ")", "" ).replace( "-", "" ).replace( ",", "" ).trim();
+ final Collection<String> modifiedTexts = new HashSet<>( 2 );
+ modifiedTexts.add( tokenizedText );
+ modifiedTexts.add( modifierText + " " + mainText );
+ return modifiedTexts;
+ }
+ }
+ return Collections.emptyList();
+ }
+
+
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/umls/VocabularyStore.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/umls/VocabularyStore.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/umls/VocabularyStore.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/umls/VocabularyStore.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,105 @@
+package org.apache.ctakes.gui.dictionary.umls;
+
+import org.apache.log4j.Logger;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/12/2015
+ */
+public enum VocabularyStore {
+ INSTANCE;
+
+ static public VocabularyStore getInstance() {
+ return INSTANCE;
+ }
+
+ private final Logger LOGGER = Logger.getLogger( "Vocabulary" );
+
+ private final Map<String, Class<?>> _vocabularyClasses = new HashMap<>();
+
+ public Collection<String> getAllVocabularies() {
+ return _vocabularyClasses.keySet();
+ }
+
+ public Class<?> getVocabularyClass( final String vocabulary ) {
+ return _vocabularyClasses.get( vocabulary );
+ }
+
+ public void addVocabulary( final String vocabulary, final String code ) {
+ final Class<?> vocabularyClass = _vocabularyClasses.get( vocabulary );
+ if ( String.class.equals( vocabularyClass ) ) {
+ return;
+ }
+ _vocabularyClasses.put( vocabulary, getBestClass( code ) );
+ }
+
+ public String getJdbcClass( final String vocabulary ) {
+ final Class<?> vocabularyClass = _vocabularyClasses.get( vocabulary );
+ if ( String.class.equals( vocabularyClass ) ) {
+ return "VARCHAR(48)";
+ } else if ( Double.class.equals( vocabularyClass ) ) {
+ return "FLOAT";
+ } else if ( Long.class.equals( vocabularyClass ) ) {
+ return "BIGINT";
+ } else if ( Integer.class.equals( vocabularyClass ) ) {
+ return "INTEGER";
+ } else {
+ LOGGER.error( "Could not derive database class for " + vocabularyClass.getName() );
+ }
+ return "VARCHAR(48)";
+ }
+
+ public String getCtakesClass( final String vocabulary ) {
+ final Class<?> vocabularyClass = _vocabularyClasses.get( vocabulary );
+ if ( String.class.equals( vocabularyClass ) ) {
+ return "text";
+ } else if ( Double.class.equals( vocabularyClass ) ) {
+ return "double";
+ } else if ( Long.class.equals( vocabularyClass ) ) {
+ return "long";
+ } else if ( Integer.class.equals( vocabularyClass ) ) {
+ return "int";
+ } else {
+ LOGGER.error( "Could not derive database class for " + vocabularyClass.getName() );
+ }
+ return "text";
+ }
+
+ static private Class<?> getBestClassFuture( final String code, final Class<?> currentClass ) {
+ boolean haveDot = false;
+ for ( char c : code.toCharArray() ) {
+ if ( !Character.isDigit( c ) ) {
+ if ( c == '.' ) {
+ if ( haveDot ) {
+ return String.class;
+ }
+ haveDot = true;
+ }
+ return String.class;
+ }
+ }
+ if ( haveDot || Double.class.equals( currentClass ) ) {
+ return Double.class;
+ }
+ if ( code.length() > 9 || Long.class.equals( currentClass ) ) {
+ return Long.class;
+ }
+ return Integer.class;
+ }
+
+ // TODO replace with getBestClassFuture when ctakes is upgraded to accept double and int
+ static private Class<?> getBestClass( final String code ) {
+ for ( char c : code.toCharArray() ) {
+ if ( !Character.isDigit( c ) ) {
+ return String.class;
+ }
+ }
+ return Long.class;
+ }
+
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/FileUtil.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/FileUtil.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/FileUtil.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/FileUtil.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,247 @@
+package org.apache.ctakes.gui.dictionary.util;
+
+
+import org.apache.ctakes.core.resource.FileLocator;
+import org.apache.log4j.Logger;
+
+import javax.swing.filechooser.FileSystemView;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 1/15/14
+ */
+final public class FileUtil {
+
+ private FileUtil() {
+ }
+
+ static private final Logger LOGGER = Logger.getLogger( "FileUtil" );
+
+ static public String parseDirText( final String dirPath ) {
+ if ( dirPath == null || dirPath.isEmpty() ) {
+ return parseDirText( "." );
+ } else if ( dirPath.startsWith( "~" ) ) {
+ return parseDirText( dirPath.replaceAll( "~", System.getProperty( "user.home" ) ) );
+ } else if ( dirPath.equals( "." ) ) {
+ final String userDir = System.getProperty( "user.dir" );
+ if ( userDir == null || userDir.isEmpty() ) {
+ return FileSystemView.getFileSystemView().getDefaultDirectory().getPath();
+ }
+ return userDir;
+ } else if ( dirPath.startsWith( ".." ) ) {
+ final String userDirPath = parseDirText( "." );
+ File cwd = new File( userDirPath );
+ String cwdPath = dirPath;
+ while ( cwdPath.startsWith( ".." ) ) {
+ if ( !cwd.isDirectory() ) {
+ LOGGER.error( "Invalid directory " + dirPath );
+ System.exit( 1 );
+ }
+ cwd = cwd.getParentFile();
+ if ( cwdPath.equals( ".." ) ) {
+ return cwd.getPath();
+ }
+ cwdPath = cwdPath.substring( 3 );
+ }
+ return cwd.getPath();
+ }
+ return dirPath;
+ }
+
+
+ static public BufferedReader createReader( final String filePath ) {
+// final String formattedPath = parseDirText( filePath );
+// final File file = new File( formattedPath );
+ try {
+ final File file = FileLocator.locateFile( filePath );
+ if ( !file.canRead() ) {
+ LOGGER.error( "Cannot read file " + filePath );
+ System.exit( 1 );
+ }
+ return new BufferedReader( new FileReader( file ) );
+ } catch ( IOException ioE ) {
+ LOGGER.error( "Cannot create Reader for " + filePath );
+ LOGGER.error( ioE.getMessage() );
+ System.exit( 1 );
+ }
+ return null;
+ }
+
+ static private BufferedWriter createWriter( final String filePath ) {
+// final String formattedPath = parseDirText( filePath );
+// final File file = new File( formattedPath );
+ try {
+ final File file = FileLocator.locateFile( filePath );
+ if ( file.getParentFile() != null && !file.getParentFile().isDirectory() ) {
+ file.getParentFile().mkdirs();
+ }
+ return new BufferedWriter( new FileWriter( file, true ) );
+ } catch ( IOException ioE ) {
+ LOGGER.error( "Cannot create Writer for " + filePath );
+ LOGGER.error( ioE.getMessage() );
+ System.exit( 1 );
+ }
+ return null;
+ }
+
+ static private String readLine( final BufferedReader reader, final String filePath ) {
+ try {
+ String line = reader.readLine();
+ while ( line != null ) {
+ if ( !line.trim().isEmpty() && !line.trim().startsWith( "//" ) ) {
+ return line;
+ }
+ line = reader.readLine();
+ }
+ } catch ( IOException ioE ) {
+ LOGGER.error( "Error reading from file " + filePath );
+ }
+ return null;
+ }
+
+ static public List<String> readBsvTokens( final BufferedReader reader, final String filePath ) {
+ final String line = readLine( reader, filePath );
+ if ( line == null ) {
+ return null;
+ }
+ return TokenUtil.getBsvItems( line );
+ }
+
+ static public List<String> readCsvTokens( final BufferedReader reader, final String filePath ) {
+ final String line = readLine( reader, filePath );
+ if ( line == null ) {
+ return null;
+ }
+ return TokenUtil.getCsvItems( line );
+ }
+
+ static public List<String> readTildeTokens( final BufferedReader reader, final String filePath ) {
+ final String line = readLine( reader, filePath );
+ if ( line == null ) {
+ return null;
+ }
+ return TokenUtil.getTildeItems( line );
+ }
+
+ static public void writeOneColumn( final String filePath, final String description,
+ final Collection<String> list ) {
+ LOGGER.info( "Writing " + description + " to " + filePath );
+ long lineCount = 0;
+ try ( BufferedWriter writer = createWriter( filePath ) ) {
+ for ( String item : list ) {
+ lineCount++;
+ writer.write( item );
+ writer.newLine();
+ if ( lineCount % 100000 == 0 ) {
+ LOGGER.info( "File Line " + lineCount );
+ }
+ }
+ } catch ( IOException ioE ) {
+ LOGGER.error( "Error writing " + description + " on line " + lineCount + " in file " + filePath );
+ }
+ LOGGER.info( "Wrote " + lineCount + " " + description + " to " + filePath );
+ }
+
+
+ static public Collection<String> readOneColumn( final String listFilePath, final String description ) {
+ LOGGER.info( "Reading " + description + " from " + listFilePath );
+ final Collection<String> listItems = new HashSet<>();
+ long lineCount = 0;
+ try ( BufferedReader reader = createReader( listFilePath ) ) {
+ String line = readLine( reader, listFilePath );
+ while ( line != null ) {
+ lineCount++;
+ listItems.add( line );
+ if ( lineCount % 100000 == 0 ) {
+ LOGGER.info( "File Line " + lineCount );
+ }
+ line = readLine( reader, listFilePath );
+ }
+ } catch ( IOException ioE ) {
+ LOGGER.error( ioE.getMessage() );
+ }
+ LOGGER.info( "File Lines " + lineCount + "\t " + description + " " + listItems.size() );
+ return listItems;
+ }
+
+// static public void writeNamedSets( final String filePath, final String description,
+// final HashSetMap<String, String> namedSets ) {
+// LOGGER.info( "Writing " + description + " to " + filePath );
+// long lineCount = 0;
+// try {
+// final BufferedWriter writer = createWriter( filePath );
+// for ( Map.Entry<String, Set<String>> namedSet : namedSets.entrySet() ) {
+// lineCount++;
+// writer.write( TokenUtil.createBsvLine( namedSet.getKey(),
+// TokenUtil.createCsvLine( namedSet.getParameterValue() ) ) );
+// writer.newLine();
+// if ( lineCount % 100000 == 0 ) {
+// LOGGER.info( "File Line " + lineCount );
+// }
+// }
+// writer.close();
+// } catch ( IOException ioE ) {
+// LOGGER.error( "Error writing " + description + " on line " + lineCount + " in file " + filePath );
+// }
+// LOGGER.info( "Wrote " + lineCount + " " + description + " to " + filePath );
+// }
+
+ /**
+ * @deprecated
+ */
+ static public void writeNamedSets( final String filePath, final String description,
+ final Map<String, Collection<String>> namedSets ) {
+ LOGGER.info( "Writing " + description + " to " + filePath );
+ long lineCount = 0;
+ try ( BufferedWriter writer = createWriter( filePath ) ) {
+ for ( Map.Entry<String, Collection<String>> namedSet : namedSets.entrySet() ) {
+ lineCount++;
+ writer.write( TokenUtil.createBsvLine( namedSet.getKey(),
+ TokenUtil.createCsvLine( namedSet.getValue() ) ) );
+ writer.newLine();
+ if ( lineCount % 100000 == 0 ) {
+ LOGGER.info( "File Line " + lineCount );
+ }
+ }
+ } catch ( IOException ioE ) {
+ LOGGER.error( "Error writing " + description + " on line " + lineCount + " in file " + filePath );
+ }
+ LOGGER.info( "Wrote " + lineCount + " " + description + " to " + filePath );
+ }
+
+ /**
+ * @deprecated
+ */
+ @Deprecated
+ static public Map<String, Collection<String>> readNamedSetsOld( final String filePath, final String description ) {
+ final Collection<String> lines = readOneColumn( filePath, description );
+ final Map<String, Collection<String>> namedSets = new HashMap<>( lines.size() );
+ for ( String line : lines ) {
+ final List<String> nameAndList = TokenUtil.getBsvItems( line );
+ if ( nameAndList == null || nameAndList.size() != 2 ) {
+ LOGGER.error( "Bad line " + line );
+ continue;
+ }
+ namedSets.put( nameAndList.get( 0 ), TokenUtil.getCsvItems( nameAndList.get( 1 ) ) );
+ }
+ return namedSets;
+ }
+
+// static public HashSetMap<String, String> readNamedSets( final String filePath, final String description ) {
+// final Collection<String> lines = readOneColumn( filePath, description );
+// final HashSetMap<String, String> namedSets = new HashSetMap<>( lines.size() );
+// for ( String line : lines ) {
+// final List<String> nameAndList = TokenUtil.getBsvItems( line );
+// if ( nameAndList == null || nameAndList.size() != 2 ) {
+// LOGGER.error( "Bad line " + line );
+// continue;
+// }
+// namedSets.addAll( nameAndList.get( 0 ), TokenUtil.getCsvItems( nameAndList.get( 1 ) ) );
+// }
+// return namedSets;
+// }
+
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/HsqlUtil.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/HsqlUtil.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/HsqlUtil.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/HsqlUtil.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,110 @@
+package org.apache.ctakes.gui.dictionary.util;
+
+
+import org.apache.ctakes.gui.dictionary.umls.VocabularyStore;
+import org.apache.log4j.Logger;
+
+import java.io.*;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/12/2015
+ */
+final public class HsqlUtil {
+
+ static private final Logger LOGGER = Logger.getLogger( "HsqlUtil" );
+
+ static public final String URL_PREFIX = "jdbc:hsqldb:file:";
+
+ private HsqlUtil() {
+ }
+
+
+ static public boolean createDatabase( final String databasePath, final String databaseName ) {
+ final File databaseDir = new File( databasePath, databaseName );
+ if ( databaseDir.isFile() ) {
+ LOGGER.error( databaseDir.getPath() + " exists as a file. Hsqldb requires that path to be a directory" );
+ return false;
+ }
+ databaseDir.mkdirs();
+ return writePropertiesFile( databaseDir, databaseName )
+ && writeScriptFile( databaseDir, databaseName )
+ && writeRcFile( databaseDir, databaseName );
+ }
+
+ static private boolean writePropertiesFile( final File databaseDir, final String databaseName ) {
+ final File propertiesFile = new File( databaseDir, databaseName + ".properties" );
+ try ( final Writer writer = new BufferedWriter( new FileWriter( propertiesFile ) ) ) {
+ writer.write( "#HSQL Database Engine 1.8.0.10\n" );
+ writer.write( "#Thu Sep 04 09:49:09 EDT 2014\n" );
+ writer.write( "hsqldb.script_format=0\n" );
+ writer.write( "runtime.gc_interval=0\n" );
+ writer.write( "sql.enforce_strict_size=false\n" );
+ writer.write( "hsqldb.cache_size_scale=8\n" );
+ writer.write( "readonly=false\n" );
+ writer.write( "hsqldb.nio_data_file=true\n" );
+ writer.write( "hsqldb.cache_scale=14\n" );
+ writer.write( "version=1.8.0\n" );
+ writer.write( "hsqldb.default_table_type=memory\n" );
+ writer.write( "hsqldb.cache_file_scale=1\n" );
+ writer.write( "hsqldb.log_size=200\n" );
+ writer.write( "modified=no\n" );
+ writer.write( "hsqldb.cache_version=1.7.0\n" );
+ writer.write( "hsqldb.original_version=1.8.0\n" );
+ writer.write( "hsqldb.compatible_version=1.8.0\n\n" );
+ } catch ( IOException ioE ) {
+ LOGGER.error( ioE.getMessage() );
+ return false;
+ }
+ return true;
+ }
+
+ static private boolean writeScriptFile( final File databaseDir, final String databaseName ) {
+ final File scriptFile = new File( databaseDir, databaseName + ".script" );
+ try ( final Writer writer = new BufferedWriter( new FileWriter( scriptFile ) ) ) {
+ writer.write( "CREATE SCHEMA PUBLIC AUTHORIZATION DBA\n" );
+ // main table
+ writer.write( "CREATE MEMORY TABLE CUI_TERMS(CUI BIGINT,RINDEX INTEGER,TCOUNT INTEGER,TEXT VARCHAR(255),RWORD VARCHAR(48))\n" );
+ writer.write( "CREATE INDEX IDX_CUI_TERMS ON CUI_TERMS(RWORD)\n" );
+ // tui table
+ writer.write( "CREATE MEMORY TABLE TUI(CUI BIGINT,TUI INTEGER)\n" );
+ writer.write( "CREATE INDEX IDX_TUI ON TUI(CUI)\n" );
+ // preferred term table
+ writer.write( "CREATE MEMORY TABLE PREFTERM(CUI BIGINT,PREFTERM VARCHAR(255))\n" );
+ writer.write( "CREATE INDEX IDX_PREFTERM ON PREFTERM(CUI)\n" );
+ // vocabulary tables
+ for ( String vocabulary : VocabularyStore.getInstance().getAllVocabularies() ) {
+ final String jdbcClass = VocabularyStore.getInstance().getJdbcClass( vocabulary );
+ final String tableName = vocabulary.replace( '.', '_' ).replace( '-', '_' );
+ writer.write( "CREATE MEMORY TABLE " + tableName + "(CUI BIGINT," + tableName + " " + jdbcClass + ")\n" );
+ writer.write( "CREATE INDEX IDX_" + tableName + " ON " + tableName + "(CUI)\n" );
+ }
+ writer.write( "CREATE USER SA PASSWORD \"\"\n" );
+ writer.write( "GRANT DBA TO SA\n" );
+ writer.write( "SET WRITE_DELAY 10\n" );
+ } catch ( IOException ioE ) {
+ LOGGER.error( ioE.getMessage() );
+ return false;
+ }
+ return true;
+ }
+
+ static private boolean writeRcFile( final File databaseDir, final String databaseName ) {
+ final File scriptFile = new File( databaseDir, databaseName + ".rc" );
+ final String url = HsqlUtil.URL_PREFIX + databaseDir.getPath().replace( '\\', '/' )
+ + "/" + databaseName;
+ try ( final Writer writer = new BufferedWriter( new FileWriter( scriptFile ) ) ) {
+ writer.write( "urlid " + databaseName + "\n" );
+ writer.write( "url " + url + ";shutdown=true\n" );
+ writer.write( "username sa\n" );
+ writer.write( "password\n" );
+ } catch ( IOException ioE ) {
+ LOGGER.error( ioE.getMessage() );
+ return false;
+ }
+ return true;
+ }
+
+
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/JdbcUtil.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/JdbcUtil.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/JdbcUtil.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/JdbcUtil.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,85 @@
+package org.apache.ctakes.gui.dictionary.util;
+
+import org.apache.log4j.Logger;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 1/21/14
+ */
+final public class JdbcUtil {
+
+ static private final Logger LOGGER = Logger.getLogger( "JdbcUtil" );
+
+ private JdbcUtil() {
+ }
+
+ static private final String JDBC_DRIVER = "org.hsqldb.jdbcDriver";
+
+
+ static public void registerDriver() {
+ try {
+ Driver driver = (Driver)Class.forName( JDBC_DRIVER ).newInstance();
+ DriverManager.registerDriver( driver );
+ } catch ( Exception e ) {
+ // TODO At least four different exceptions are thrown here, and should be caught and handled individually
+ LOGGER.error( "Could not register Driver " + JDBC_DRIVER );
+ LOGGER.error( e.getMessage() );
+ System.exit( 1 );
+ }
+ }
+
+ static public Connection createDatabaseConnection( final String url, final String user, final String pass ) {
+ registerDriver();
+ LOGGER.info( "Connecting to " + url + " as " + user );
+ Connection connection = null;
+ try {
+ connection = DriverManager.getConnection( url, user, pass );
+ } catch ( SQLException sqlE ) {
+ // thrown by Connection.prepareStatement(..) and getTotalRowCount(..)
+ LOGGER.error( "Could not establish connection to " + url + " as " + user );
+ LOGGER.error( sqlE.getMessage() );
+ System.exit( 1 );
+ }
+ return connection;
+ }
+
+ // static public String createRowInsertSql( final String tableName, final int valueCount ) {
+ static public String createRowInsertSql( final String tableName, final Enum... fields ) {
+ final String[] fieldNames = new String[ fields.length ];
+ int i = 0;
+ for ( Enum field : fields ) {
+ fieldNames[ i ] = field.name();
+ i++;
+ }
+ return createRowInsertSql( tableName, fieldNames );
+ }
+
+ static public String createCodeInsertSql( final String vocabulary ) {
+ return createRowInsertSql( vocabulary.toLowerCase().replace( '.', '_' ).replace( '-', '_' ), "CUI", vocabulary );
+ }
+
+ static public String createRowInsertSql( final String tableName, final String... fieldNames ) {
+ final StringBuilder sb = new StringBuilder( "insert into" );
+ sb.append( " " ).append( tableName );
+ sb.append( " (" );
+ for ( String fieldName : fieldNames ) {
+ sb.append( fieldName ).append( ',' );
+ }
+ // remove last comma
+ sb.setLength( sb.length() - 1 );
+ sb.append( ") " );
+ sb.append( " values (" );
+ for ( int i = 0; i < fieldNames.length - 1; i++ ) {
+ sb.append( "?," );
+ }
+ sb.append( "?)" );
+ return sb.toString();
+ }
+
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/RareWordDbWriter.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/RareWordDbWriter.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/RareWordDbWriter.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/RareWordDbWriter.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,201 @@
+package org.apache.ctakes.gui.dictionary.util;
+
+import org.apache.ctakes.gui.dictionary.umls.Concept;
+import org.apache.ctakes.gui.dictionary.umls.Tui;
+import org.apache.ctakes.gui.dictionary.umls.VocabularyStore;
+import org.apache.log4j.Logger;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 1/15/14
+ */
+final public class RareWordDbWriter {
+
+ static private final Logger LOGGER = Logger.getLogger( "RareWordDbWriter" );
+
+
+ private RareWordDbWriter() {
+ }
+
+ private enum CuiTermsField {
+ CUI( 1, Long.class ), RINDEX( 2, Integer.class ), TCOUNT( 3, Integer.class ),
+ TEXT( 4, String.class ), RWORD( 5, String.class );
+ final private int __index;
+ final private Class __classType;
+
+ CuiTermsField( final int index, final Class classType ) {
+ __index = index;
+ __classType = classType;
+ }
+ }
+
+
+ static public boolean writeConcepts( final Map<Long, Concept> concepts,
+ final String url, final String user, final String pass ) {
+ // Get Count of appearance in dictionary per term token
+ final Map<String, Long> tokenCounts = RareWordUtil.getTokenCounts( concepts.values() );
+ // Create insert sql statements
+ final String mainTableSql = JdbcUtil.createRowInsertSql( "CUI_TERMS", CuiTermsField.values() );
+ final String tuiTableSql = JdbcUtil.createCodeInsertSql( "tui" );
+ final String preftermTableSql = JdbcUtil.createCodeInsertSql( "prefterm" );
+ final Map<String, String> insertCodeSqls = createCodeInsertSqls();
+
+ long mainTableCount = 0;
+ long tuiTableCount = 0;
+ long preftermTableCount = 0;
+ final Map<String, Long> codeTableCounts = createCodeCounts();
+ final Connection connection = JdbcUtil.createDatabaseConnection( url, user, pass );
+ try {
+ // Create PreparedStatements from insert sql statements
+ final PreparedStatement mainTableStatement = connection.prepareStatement( mainTableSql );
+ final PreparedStatement tuiStatement = connection.prepareStatement( tuiTableSql );
+ final PreparedStatement preftermStatement = connection.prepareStatement( preftermTableSql );
+ final Map<String, PreparedStatement> codeStatements = createCodeStatements( connection, insertCodeSqls );
+
+ for ( Map.Entry<Long, Concept> conceptEntry : concepts.entrySet() ) {
+ final long cui = conceptEntry.getKey();
+ final Concept concept = conceptEntry.getValue();
+ // write main term table
+ boolean conceptOk = false;
+ for ( String text : conceptEntry.getValue().getTexts() ) {
+ final RareWordUtil.IndexedRareWord indexedRareWord = RareWordUtil.getIndexedRareWord( text,
+ tokenCounts );
+ if ( RareWordUtil.NULL_RARE_WORD.equals( indexedRareWord ) ) {
+ continue;
+ }
+ conceptOk = true;
+ mainTableStatement.setLong( CuiTermsField.CUI.__index, cui );
+ mainTableStatement.setInt( CuiTermsField.RINDEX.__index, indexedRareWord.__index );
+ mainTableStatement.setInt( CuiTermsField.TCOUNT.__index, indexedRareWord.__tokenCount );
+ mainTableStatement.setString( CuiTermsField.TEXT.__index, text );
+ mainTableStatement.setString( CuiTermsField.RWORD.__index, indexedRareWord.__word );
+ mainTableStatement.executeUpdate();
+ mainTableCount = incrementCount( "Main", mainTableCount );
+ }
+ if ( !conceptOk ) {
+ continue;
+ }
+ // write tui table
+ for ( Tui tui : concept.getTuis() ) {
+ tuiStatement.setLong( CuiTermsField.CUI.__index, cui );
+ tuiStatement.setInt( 2, tui.getIntValue() );
+ tuiStatement.executeUpdate();
+ tuiTableCount = incrementCount( "Tui", tuiTableCount );
+ }
+ // write preferred term table
+ final String preferredText = concept.getPreferredText();
+ if ( preferredText != null
+ && !preferredText.isEmpty()
+ && !preferredText.equals( Concept.PREFERRED_TERM_UNKNOWN ) ) {
+ preftermStatement.setLong( CuiTermsField.CUI.__index, cui );
+ preftermStatement.setString( 2, preferredText );
+ preftermStatement.executeUpdate();
+ preftermTableCount = incrementCount( "Preferred Term", preftermTableCount );
+ }
+ // write extra vocabulary code tables
+ final Collection<String> vocabularies = concept.getVocabularies();
+ for ( String vocabulary : vocabularies ) {
+ final PreparedStatement statement = codeStatements.get( vocabulary );
+ statement.setLong( CuiTermsField.CUI.__index, cui );
+ for ( String code : concept.getCodes( vocabulary ) ) {
+ setCodeAppropriately( statement, code, VocabularyStore.getInstance()
+ .getVocabularyClass( vocabulary ) );
+ statement.executeUpdate();
+ codeTableCounts.put( vocabulary, incrementCount( vocabulary, codeTableCounts.get( vocabulary ) ) );
+ }
+ }
+ }
+ connection.commit();
+ mainTableStatement.close();
+ tuiStatement.close();
+ preftermStatement.close();
+ preftermStatement.close();
+ for ( PreparedStatement codeStatement : codeStatements.values() ) {
+ codeStatement.close();
+ }
+ final Statement writeDelayStatement = connection.createStatement();
+ writeDelayStatement.execute( "SET WRITE_DELAY FALSE" );
+ writeDelayStatement.close();
+ final Statement setBinaryStatement = connection.createStatement();
+ setBinaryStatement.execute( "SET SCRIPTFORMAT BINARY" );
+ setBinaryStatement.close();
+ final Statement readOnlyStatement = connection.createStatement();
+ readOnlyStatement.execute( "SET READONLY TRUE" );
+ readOnlyStatement.close();
+ final Statement shutdownStatement = connection.createStatement();
+ shutdownStatement.execute( "SHUTDOWN" );
+ shutdownStatement.close();
+ connection.commit();
+ connection.close();
+ } catch ( SQLException sqlE ) {
+ LOGGER.error( sqlE.getMessage() );
+ return false;
+ }
+ LOGGER.info( "Main Table Rows " + mainTableCount );
+ LOGGER.info( "Tui Table Rows " + tuiTableCount );
+ LOGGER.info( "Preferred Term Table Rows " + preftermTableCount );
+ final Function<String, String> vocabCount = v -> v + " Table Rows " + codeTableCounts.get( v );
+ VocabularyStore.getInstance().getAllVocabularies().stream()
+ .map( vocabCount )
+ .forEach( LOGGER::info );
+ return true;
+ }
+
+
+ static private Map<String, String> createCodeInsertSqls() {
+ return VocabularyStore.getInstance().getAllVocabularies().stream()
+ .collect( Collectors.toMap( Function.identity(), JdbcUtil::createCodeInsertSql ) );
+ }
+
+ static private Map<String, PreparedStatement> createCodeStatements( final Connection connection,
+ final Map<String, String> insertCodeSqls )
+ throws SQLException {
+ final Map<String, PreparedStatement> codeStatements = new HashMap<>( insertCodeSqls.size() );
+ for ( Map.Entry<String, String> codeSql : insertCodeSqls.entrySet() ) {
+ codeStatements.put( codeSql.getKey(), connection.prepareStatement( codeSql.getValue() ) );
+ }
+ return codeStatements;
+ }
+
+ static private Map<String, Long> createCodeCounts() {
+ return VocabularyStore.getInstance().getAllVocabularies().stream()
+ .collect( Collectors.toMap( Function.identity(), v -> 0L ) );
+ }
+
+ static private void setCodeAppropriately( final PreparedStatement statement, final String code,
+ final Class<?> type ) throws SQLException {
+ if ( String.class.equals( type ) ) {
+ statement.setString( 2, code );
+ } else if ( Double.class.equals( type ) ) {
+ statement.setDouble( 2, Double.valueOf( code ) );
+ } else if ( Long.class.equals( type ) ) {
+ statement.setLong( 2, Long.valueOf( code ) );
+ } else if ( Integer.class.equals( type ) ) {
+ statement.setInt( 2, Integer.valueOf( code ) );
+ } else {
+ LOGGER.error( "Could not set code for " + type.getName() );
+ statement.setString( 2, code );
+ }
+ }
+
+ static private long incrementCount( final String name, long count ) {
+ count++;
+ if ( count % 100000 == 0 ) {
+ LOGGER.info( name + " Table Rows " + count );
+ }
+ return count;
+ }
+
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/RareWordUtil.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/RareWordUtil.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/RareWordUtil.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/RareWordUtil.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,178 @@
+package org.apache.ctakes.gui.dictionary.util;
+
+import org.apache.ctakes.gui.dictionary.umls.Concept;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 1/17/14
+ */
+final public class RareWordUtil {
+
+ private RareWordUtil() {
+ }
+
+ // LookupDesc for the standard excluded pos tags are
+ // VB,VBD,VBG,VBN,VBP,VBZ,CC,CD,DT,EX,LS,MD,PDT,POS,PP,PP$,PRP,PRP$,RP,TO,WDT,WP,WPS,WRB
+ // Listing every verb in the language seems a pain, but listing the others is possible.
+ // Verbs should be rare in the dictionaries, excepting perhaps the activity and concept dictionaries
+ // CD, CC, DT, EX, MD, PDT, PP, PP$, PRP, PRP$, RP, TO, WDT, WP, WPS, WRB
+ // why not WP$ (possessive wh- pronoun "whose")
+ // PP$ is a Brown POS tag, not Penn Treebank (as are the rest)
+
+ static private final Set<String> BAD_POS_TERM_SET;
+
+ static {
+ final String[] BAD_POS_TERMS = {
+ // VB verb
+ "be", "has", "have", "had", "do", "does", "did", "is", "isn", "am", "are", "was", "were",
+ // CD cardinal number
+ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
+ // CC coordinating conjunction
+ "and", "or", "but", "for", "nor", "so", "yet", "while", "because",
+ // DT determiner
+ "this", "that", "these", "those", "the", "an", "a",
+ // EX existential there
+ "there",
+ // MD modal
+ "can", "should", "will", "may", "shall", "might", "must", "could", "would",
+ // PDT predeterminer
+ "some", "many", "any", "each", "all", "few", "most", "both", "half", "none", "twice",
+ // PP prepositional phrase (preposition)
+ "at", "before", "after", "behind", "beneath", "beside", "between", "into", "through", "across", "of",
+ "concerning", "like", "unlike", "except", "with", "within", "without", "toward", "to", "past", "against",
+ "during", "until", "throughout", "below", "besides", "beyond", "from", "inside", "near", "outside", "since",
+ "upon",
+ // PP$ possessive personal pronoun - Brown POS tag, not Penn TreeBank
+ "my", "our", "your", "her", "their", "whose",
+ // PRP personal pronoun, plurals added
+ "i", "you", "he", "she", "it", "them", "they", "we", "us",
+ // PRP$ possesive pronoun
+ "mine", "yours", "his", "hers", "its", "ours", "theirs",
+ // RP particle - this contains some prepositions
+ "about", "off", "up", "along", "away", "back", "by", "down", "forward", "in", "on", "out",
+ "over", "around", "under",
+ // TO to - also a preposition
+ "to",
+ // WDT wh- determiner
+ "what", "whatever", "which", "whichever",
+ // WP, WPS wh- pronoun, nominative wh- pronoun
+ "who", "whom", "which", "that", "whoever", "whomever",
+ // WRB
+ "how", "where", "when", "however", "wherever", "whenever",
+ // Mine ... some correlative conjunctions, etc.
+ "no", "not", "oh", "mr", "mrs", "miss", "dr", "as", "only", "also", "either", "neither", "whether",
+ // additional numbers
+ "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
+ "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety",
+ "hundred", "thousand", "million", "billion", "trillion",
+ };
+ BAD_POS_TERM_SET = new HashSet<>( Arrays.asList( BAD_POS_TERMS ) );
+ }
+
+ static private final Pattern SPACE_PATTERN = Pattern.compile( "\\s+" );
+
+ static public Collection<String> getUnwantedPosTexts() {
+ return Collections.unmodifiableCollection( BAD_POS_TERM_SET );
+ }
+
+ static public boolean isRarableToken( final String token ) {
+ if ( token.length() <= 1 ) {
+ return false;
+ }
+ boolean hasLetter = false;
+ for ( int i = 0; i < token.length(); i++ ) {
+ if ( Character.isLetter( token.charAt( i ) ) ) {
+ hasLetter = true;
+ break;
+ }
+ }
+ return hasLetter && !BAD_POS_TERM_SET.contains( token );
+ }
+
+
+ static public Map<String, Long> getTokenCounts( final Collection<Concept> concepts ) {
+ return concepts.stream()
+ .map( Concept::getTexts )
+ .flatMap( Collection::stream )
+ .map( SPACE_PATTERN::split )
+ .flatMap( Arrays::stream )
+ .filter( RareWordUtil::isRarableToken )
+ .collect( Collectors.groupingBy( Function.identity(), Collectors.counting() ) );
+ }
+
+ static private void incrementCount( final Map<String, Integer> tokenCounts, final String token ) {
+ Integer count = tokenCounts.get( token );
+ if ( count == null ) {
+ count = 0;
+ }
+ tokenCounts.put( token, (count + 1) );
+ }
+
+ // static public String getRareToken( final Map<String,Integer> tokenCounts, final String text ) {
+ // final String[] tokens = text.split( "\\s+" );
+ // int bestIndex = 0;
+ // int bestCount = Integer.MAX_VALUE;
+ // for ( int i = 0; i < tokens.length; i++ ) {
+ // Integer count = tokenCounts.get( tokens[i] );
+ // if ( count != null && count < bestCount ) {
+ // bestIndex = i;
+ // bestCount = count;
+ // }
+ // }
+ // return tokens[bestIndex];
+ // }
+ //
+ // static public int getRareTokenIndex( final Map<String,Integer> tokenCounts, final String text ) {
+ // final String[] tokens = text.split( "\\s+" );
+ // int bestIndex = 0;
+ // int bestCount = Integer.MAX_VALUE;
+ // for ( int i = 0; i < tokens.length; i++ ) {
+ // Integer count = tokenCounts.get( tokens[i] );
+ // if ( count != null && count < bestCount ) {
+ // bestIndex = i;
+ // bestCount = count;
+ // }
+ // }
+ // return bestIndex;
+ // }
+
+
+ static public final class IndexedRareWord {
+ final public String __word;
+ final public int __index;
+ final public int __tokenCount;
+
+ private IndexedRareWord( final String word, final int index, final int tokenCount ) {
+ __word = word;
+ __index = index;
+ __tokenCount = tokenCount;
+ }
+ }
+
+ static public final IndexedRareWord NULL_RARE_WORD = new IndexedRareWord( null, -1, -1 );
+
+ static public IndexedRareWord getIndexedRareWord( final String text,
+ final Map<String, Long> tokenCounts ) {
+ final String[] tokens = SPACE_PATTERN.split( text );
+ int bestIndex = 0;
+ long bestCount = Long.MAX_VALUE;
+ for ( int i = 0; i < tokens.length; i++ ) {
+ Long count = tokenCounts.get( tokens[ i ] );
+ if ( count != null && count < bestCount ) {
+ bestIndex = i;
+ bestCount = count;
+ }
+ }
+ if ( bestCount == Long.MAX_VALUE ) {
+ return NULL_RARE_WORD;
+ }
+ return new IndexedRareWord( tokens[ bestIndex ], bestIndex, tokens.length );
+ }
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/TextTokenizer.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/TextTokenizer.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/TextTokenizer.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/TextTokenizer.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,198 @@
+package org.apache.ctakes.gui.dictionary.util;
+
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 1/16/14
+ */
+final public class TextTokenizer {
+
+ private TextTokenizer() {
+ }
+
+ static private final String[] PREFIXES = {
+ "e-",
+ "a-",
+ "u-",
+ "x-",
+ "agro-",
+ "ante-",
+ "anti-",
+ "arch-",
+ "be-",
+ "bi-",
+ "bio-",
+ "co-",
+ "counter-",
+ "cross-",
+ "cyber-",
+ "de-",
+ "eco-",
+ "ex-",
+ "extra-",
+ "inter-",
+ "intra-",
+ "macro-",
+ "mega-",
+ "micro-",
+ "mid-",
+ "mini-",
+ "multi-",
+ "neo-",
+ "non-",
+ "over-",
+ "pan-",
+ "para-",
+ "peri-",
+ "post-",
+ "pre-",
+ "pro-",
+ "pseudo-",
+ "quasi-",
+ "re-",
+ "semi-",
+ "sub-",
+ "super-",
+ "tri-",
+ "ultra-",
+ "un-",
+ "uni-",
+ "vice-",
+ // From email from Colin Warner <co...@ldc.upenn.edu> on 7/25/2010
+ "electro-",
+ "gasto-",
+ "homo-",
+ "hetero-",
+ "ortho-",
+ "phospho-",
+ };
+
+ static private final String[] SUFFIXES = { "-esque", "-ette", "-fest", "-fold", "-gate", "-itis", "-less", "-most",
+ "-o-torium", "-rama", "-wise" };
+
+ static private final Set<String> PREFIX_SET = new HashSet<>( Arrays.asList( PREFIXES ) );
+ static private final Set<String> SUFFIX_SET = new HashSet<>( Arrays.asList( SUFFIXES ) );
+
+ static private Pattern WHITESPACE = Pattern.compile( "\\s+" );
+
+ static private String getNextCharTerm( final String word ) {
+ final StringBuilder sb = new StringBuilder();
+ final int count = word.length();
+ for ( int i = 0; i < count; i++ ) {
+ final char c = word.charAt( i );
+ if ( !Character.isLetterOrDigit( c ) ) {
+ return sb.toString();
+ }
+ sb.append( c );
+ }
+ return sb.toString();
+ }
+
+ static private boolean isPrefix( final String word ) {
+ final String prefixQ = word + "-";
+ return PREFIX_SET.contains( prefixQ );
+ }
+
+ static private boolean isSuffix( final String word, final int startIndex ) {
+ if ( word.length() <= startIndex ) {
+ return false;
+ }
+ final String nextCharTerm = getNextCharTerm( word.substring( startIndex ) );
+ if ( nextCharTerm.isEmpty() ) {
+ return false;
+ }
+ final String suffixQ = "-" + nextCharTerm;
+ return SUFFIX_SET.contains( suffixQ );
+ }
+
+ static private boolean isOwnerApostrophe( final CharSequence word, final int startIndex ) {
+ return word.length() == startIndex + 1 && word.charAt( startIndex ) == 's';
+ }
+
+ static private boolean isNumberDecimal( final CharSequence word, final int startIndex ) {
+ // Bizarre scenario in which ctakes tokenizes ".2" as a fraction, but not ".22"
+ return word.length() == startIndex + 1 && Character.isDigit( word.charAt( startIndex ) );
+ }
+
+ static public List<String> getTokens( final String word ) {
+ return getTokens( word, false );
+ }
+
+ static public List<String> getTokens( final String word, final boolean separateDigits ) {
+ final List<String> tokens = new ArrayList<>();
+ final StringBuilder sb = new StringBuilder();
+ final int count = word.length();
+ boolean wasDigit = false;
+ for ( int i = 0; i < count; i++ ) {
+ final char c = word.charAt( i );
+ if ( Character.isLetterOrDigit( c ) ) {
+ if ( sb.length() != 0 && separateDigits && (wasDigit && !Character.isDigit( c )) ) {
+ // separating characters from digits, add the current word
+ tokens.add( sb.toString() );
+ sb.setLength( 0 );
+ }
+ wasDigit = Character.isDigit( c );
+ // Appending character to current word
+ sb.append( c );
+ continue;
+ }
+ wasDigit = false;
+ if ( c == '-' && (isPrefix( sb.toString() ) || isSuffix( word, i + 1 )) ) {
+ // what precedes is a prefix or what follows is a suffix so append the dash to the current word and move on
+ sb.append( c );
+ continue;
+ }
+ if ( (c == '\'' && isOwnerApostrophe( word, i + 1 ))
+ || (c == '.' && isNumberDecimal( word, i + 1 )) ) {
+ // what follows is an 's or .# so add the preceding and move on
+ if ( sb.length() != 0 ) {
+ tokens.add( sb.toString() );
+ sb.setLength( 0 );
+ }
+ sb.append( c );
+ continue;
+ }
+ // Wasn't a special symbol for consideration, so add the previous and symbol separately
+ if ( sb.length() != 0 ) {
+ tokens.add( sb.toString() );
+ sb.setLength( 0 );
+ }
+ tokens.add( "" + c );
+ }
+ if ( sb.length() != 0 ) {
+ // add the final word
+ tokens.add( sb.toString() );
+ }
+ return tokens;
+ }
+
+ static public String getTokenizedText( final String text ) {
+ return getTokenizedText( text, false );
+ }
+
+
+ static public String getTokenizedText( final String text, final boolean separateDigits ) {
+ if ( text.isEmpty() ) {
+ return text;
+ }
+ final String[] splits = WHITESPACE.split( text.toLowerCase() );
+ if ( splits.length == 0 ) {
+ return "";
+ }
+ final String lastSplit = splits[ splits.length - 1 ];
+ if ( lastSplit.endsWith( "," ) || lastSplit.endsWith( ";" ) || lastSplit.endsWith( "." ) ) {
+ // get rid of last comma or semicolon or period
+ splits[ splits.length - 1 ] = lastSplit.substring( 0, lastSplit.length() - 1 );
+ }
+ return Arrays.stream( splits )
+ .map( s -> getTokens( s, separateDigits ) )
+ .flatMap( Collection::stream )
+ .collect( Collectors.joining( " " ) );
+ }
+
+
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/TokenUtil.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/TokenUtil.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/TokenUtil.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/dictionary/util/TokenUtil.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,89 @@
+package org.apache.ctakes.gui.dictionary.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 1/15/14
+ */
+final public class TokenUtil {
+
+ private TokenUtil() {
+ }
+
+ static public List<String> getBsvItems( final String line ) {
+ return getSeparatedValueItems( line, '|' );
+ }
+
+ static public List<String> getTildeItems( final String line ) {
+ return getSeparatedValueItems( line, '~' );
+ }
+
+ static public List<String> getCsvItems( final String line ) {
+ return getSeparatedValueItems( line, ',' );
+ }
+
+ static private List<String> getSeparatedValueItems( final String line, final char separator ) {
+ if ( line == null || line.trim().isEmpty() ) {
+ return Collections.emptyList();
+ }
+ final List<String> tokens = new ArrayList<>();
+ int startIndex = 0;
+ int stopIndex = line.indexOf( separator );
+ while ( stopIndex > 0 && stopIndex < line.length() ) {
+ tokens.add( line.substring( startIndex, stopIndex ) );
+ startIndex = stopIndex + 1;
+ stopIndex = line.indexOf( separator, startIndex );
+ }
+ if ( startIndex < line.length() - 1 ) {
+ tokens.add( line.substring( startIndex ) );
+ } else {
+ tokens.add( "" );
+ }
+ return tokens;
+ }
+
+
+ static public String createBsvLine( final Collection<String> values ) {
+ if ( values == null ) {
+ return "";
+ }
+ return createBsvLine( values.toArray( new String[ values.size() ] ) );
+ }
+
+ static public String createBsvLine( final String... values ) {
+ if ( values.length == 0 ) {
+ return "";
+ }
+ final StringBuilder sb = new StringBuilder();
+ for ( String value : values ) {
+ sb.append( value ).append( "|" );
+ }
+ sb.setLength( sb.length() - 1 );
+ return sb.toString();
+ }
+
+ static public String createCsvLine( final Collection<String> values ) {
+ if ( values == null ) {
+ return "";
+ }
+ return createCsvLine( values.toArray( new String[ values.size() ] ) );
+ }
+
+ static public String createCsvLine( final String... values ) {
+ if ( values.length == 0 ) {
+ return "";
+ }
+ final StringBuilder sb = new StringBuilder();
+ for ( String value : values ) {
+ sb.append( value ).append( "," );
+ }
+ sb.setLength( sb.length() - 1 );
+ return sb.toString();
+ }
+
+}
Added: ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/MainPanel.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/MainPanel.java?rev=1788936&view=auto
==============================================================================
--- ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/MainPanel.java (added)
+++ ctakes/trunk/ctakes-gui/src/main/java/org/apache/ctakes/gui/pipeline/MainPanel.java Mon Mar 27 14:37:44 2017
@@ -0,0 +1,316 @@
+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.BitCellRenderer;
+import org.apache.ctakes.gui.pipeline.bit.PipeBitFinder;
+import org.apache.ctakes.gui.pipeline.bit.available.AvailablesListModel;
+import org.apache.ctakes.gui.pipeline.bit.available.AvailablesRenderer;
+import org.apache.ctakes.gui.pipeline.bit.info.PipeBitInfoPanel;
+import org.apache.ctakes.gui.pipeline.bit.user.*;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * TODO this interface is completely graphical and needs a lot of attention to be done well
+ *
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/20/2016
+ */
+final class MainPanel extends JPanel {
+
+ static private final Logger LOGGER = Logger.getLogger( "MainPanel" );
+
+
+ private final AvailablesListModel _availablesListModel = new AvailablesListModel();
+ private JList<PipeBitInfo> _availablesList;
+ private JList<UserBit> _userBitsList;
+
+ MainPanel() {
+ super( new BorderLayout( 10, 10 ) );
+
+ final JSplitPane logSplit = new PositionedSplitPane( JSplitPane.VERTICAL_SPLIT );
+ logSplit.setTopComponent( createMainPanel() );
+ logSplit.setBottomComponent( LoggerPanel.createLoggerPanel() );
+ logSplit.setDividerLocation( 0.6d );
+
+ add( logSplit, BorderLayout.CENTER );
+ }
+
+
+ private JComponent createWestPanel() {
+ final JLabel header = new JLabel( "Available Pipe Bits" );
+ header.setPreferredSize( new Dimension( 100, 30 ) );
+ header.setHorizontalAlignment( SwingConstants.CENTER );
+ _availablesList = createPipeBitList( _availablesListModel );
+
+ final ListCellRenderer<Object> availableRenderer = new AvailablesRenderer();
+ _availablesList.setCellRenderer( availableRenderer );
+ final JScrollPane scroll = new JScrollPane( _availablesList );
+ scroll.setColumnHeaderView( header );
+ 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() {
+ final JLabel header = new JLabel( "User Pipeline" );
+ header.setPreferredSize( new Dimension( 100, 30 ) );
+ header.setHorizontalAlignment( SwingConstants.CENTER );
+ final UserBitListModel userBitListModel = new UserBitListModel();
+ _userBitsList = createUserBitList( userBitListModel );
+ final ListCellRenderer<Object> usersRenderer = new UserBitRenderer();
+ _userBitsList.setCellRenderer( usersRenderer );
+ final JScrollPane scroll = new JScrollPane( _userBitsList );
+ scroll.setColumnHeaderView( header );
+
+ // Listener for mouse clicks and float-over in availables list
+ final AvailablesMouseListener availablesMouse = new AvailablesMouseListener( _availablesList, userBitListModel );
+ _availablesList.addMouseListener( availablesMouse );
+ _availablesList.addMouseMotionListener( availablesMouse );
+
+ // Listener for mouse clicks and float-over in users list
+ final UsersMouseListener usersMouse = new UsersMouseListener( _userBitsList, userBitListModel );
+ _userBitsList.addMouseListener( usersMouse );
+ _userBitsList.addMouseMotionListener( usersMouse );
+
+ final JSplitPane split = new PositionedSplitPane();
+ split.setLeftComponent( scroll );
+ split.setRightComponent( createUserBitPanel( _userBitsList ) );
+ split.setDividerLocation( 0.3d );
+ return split;
+ }
+
+
+ private JComponent createMainPanel() {
+ final JComponent westPanel = createWestPanel();
+ final JComponent eastPanel = createEastPanel();
+ return new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, westPanel, eastPanel );
+ }
+
+
+// private JComponent createCenterPanel() {
+// final JPanel panel = new JPanel( new BorderLayout() );
+// final JList<PipeBitInfo> pipeBitList = createPipeBitList( _availablesListModel );
+// final JSplitPane centerSplit = new PositionedSplitPane();
+// centerSplit.setLeftComponent( new JScrollPane( pipeBitList ) );
+// final PipeBitInfoPanel pipeBitInfoPanel = createPipeBitPanel();
+// centerSplit.setRightComponent( pipeBitInfoPanel );
+// centerSplit.setDividerLocation( 0.25d );
+// panel.add( centerSplit, BorderLayout.CENTER );
+// panel.add( createGoPanel(), BorderLayout.SOUTH );
+// pipeBitInfoPanel.addPipeBitListListener( pipeBitList );
+// return panel;
+// }
+
+ static private JList<PipeBitInfo> createPipeBitList( final ListModel<PipeBitInfo> model ) {
+ final JList<PipeBitInfo> bitList = new SmoothTipList<>( model );
+ bitList.setCellRenderer( new BitCellRenderer() );
+ bitList.setFixedCellHeight( 20 );
+ return bitList;
+ }
+
+ static private JList<UserBit> createUserBitList( final ListModel<UserBit> model ) {
+ final JList<UserBit> bitList = new SmoothTipList<>( model );
+ bitList.setFixedCellHeight( 20 );
+ return bitList;
+ }
+
+ static private PipeBitInfoPanel createBitInfoPanel( final JList<PipeBitInfo> list ) {
+ final PipeBitInfoPanel pipeBitInfoPanel = new PipeBitInfoPanel();
+ pipeBitInfoPanel.setPipeBitInfoList( list );
+ return pipeBitInfoPanel;
+ }
+
+ static private UserBitInfoPanel createUserBitPanel( final JList<UserBit> list ) {
+ final UserBitInfoPanel userBitPanelPanel = new UserBitInfoPanel();
+ userBitPanelPanel.setUserBitList( list );
+ return userBitPanelPanel;
+ }
+
+
+ private JComponent createGoPanel() {
+ return new JButton( new FindPipeBitsAction() );
+ }
+
+
+ public 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( MainPanel.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() );
+ }
+ }
+
+
+ /**
+ * Builds the dictionary
+ */
+ private class FindPipeBitsAction extends AbstractAction {
+ private FindPipeBitsAction() {
+ super( "Find Readers, Annotators and Writers" );
+ }
+
+ @Override
+ public void actionPerformed( final ActionEvent event ) {
+ final ExecutorService executor = Executors.newSingleThreadExecutor();
+ executor.execute( new PiperBitParser() );
+ }
+ }
+
+ static private final class AvailablesMouseListener extends MouseAdapter {
+ private final JList<PipeBitInfo> _list;
+ private final UserBitListModel __userBitListModel;
+ private int _currentFocusIndex = -1;
+
+ private AvailablesMouseListener( final JList<PipeBitInfo> list, final UserBitListModel userBitListModel ) {
+ _list = list;
+ __userBitListModel = userBitListModel;
+ }
+
+ @Override
+ public void mouseReleased( final MouseEvent event ) {
+ final Point p = _list.getMousePosition();
+ if ( p.getX() < _list.getWidth() - 37 ) {
+ return;
+ }
+ final int index = _list.locationToIndex( p );
+ final AvailablesListModel availablesModel = (AvailablesListModel)_list.getModel();
+ final PipeBitInfo pipeBitInfo = availablesModel.getElementAt( index );
+ final UserBit userBit = new DefaultUserBit( pipeBitInfo, availablesModel.getPipeBit( pipeBitInfo ) );
+ __userBitListModel.addUserBit( userBit );
+ }
+
+ @Override
+ public void mouseEntered( final MouseEvent event ) {
+ setFocus( _list.getMousePosition() );
+ }
+
+ @Override
+ public void mouseExited( final MouseEvent event ) {
+ setFocus( _list.getMousePosition() );
+ }
+
+ @Override
+ public void mouseDragged( final MouseEvent event ) {
+ setFocus( _list.getMousePosition() );
+ }
+
+ @Override
+ public void mouseMoved( final MouseEvent event ) {
+ setFocus( _list.getMousePosition() );
+ }
+
+ private void setFocus( final Point p ) {
+ if ( p == null ) {
+ if ( _currentFocusIndex >= 0 ) {
+ _currentFocusIndex = -1;
+ _list.repaint();
+ }
+ return;
+ }
+ final int index = _list.locationToIndex( p );
+ if ( index == _currentFocusIndex ) {
+ return;
+ }
+ _currentFocusIndex = index;
+ _list.repaint();
+ }
+ }
+
+ static private final class UsersMouseListener extends MouseAdapter {
+ private final JList<UserBit> _list;
+ private final UserBitListModel __userBitListModel;
+ private int _currentFocusIndex = -1;
+
+ private UsersMouseListener( final JList<UserBit> list, final UserBitListModel userBitListModel ) {
+ _list = list;
+ __userBitListModel = userBitListModel;
+ }
+
+ @Override
+ public void mouseReleased( final MouseEvent event ) {
+ final Point p = _list.getMousePosition();
+ final int widthMinusX = _list.getWidth() - p.x;
+ if ( widthMinusX > 65 ) {
+ return;
+ }
+ _list.getSelectionModel().clearSelection();
+ UserBitRenderer.SUSPEND_BUTTONS = true;
+ final int index = _list.locationToIndex( p );
+ if ( widthMinusX > 45 ) {
+ __userBitListModel.moveUserBitUp( index );
+ } else if ( widthMinusX > 25 ) {
+ __userBitListModel.moveUserBitDown( index );
+ } else {
+ __userBitListModel.removeUserBit( index );
+ }
+ UserBitRenderer.SUSPEND_BUTTONS = false;
+ _list.repaint();
+ }
+
+ @Override
+ public void mouseEntered( final MouseEvent event ) {
+ setFocus( _list.getMousePosition() );
+ }
+
+ @Override
+ public void mouseExited( final MouseEvent event ) {
+ setFocus( _list.getMousePosition() );
+ }
+
+ @Override
+ public void mouseDragged( final MouseEvent event ) {
+ setFocus( _list.getMousePosition() );
+ }
+
+ @Override
+ public void mouseMoved( final MouseEvent event ) {
+ setFocus( _list.getMousePosition() );
+ }
+
+ private void setFocus( final Point p ) {
+ if ( p == null ) {
+ if ( _currentFocusIndex >= 0 ) {
+ _currentFocusIndex = -1;
+ _list.repaint();
+ }
+ return;
+ }
+ final int index = _list.locationToIndex( p );
+ if ( index == _currentFocusIndex ) {
+ return;
+ }
+ _currentFocusIndex = index;
+ _list.repaint();
+ }
+ }
+
+
+}