ctakes-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From seanfi...@apache.org
Subject svn commit: r1660963 [6/19] - in /ctakes/sandbox/timelanes: META-INF/ edu/ edu/mayo/ edu/mayo/bmi/ edu/mayo/bmi/annotation/ edu/mayo/bmi/annotation/knowtator/ org/ org/chboston/ org/chboston/cnlp/ org/chboston/cnlp/anafora/ org/chboston/cnlp/anafora/an...
Date Thu, 19 Feb 2015 18:06:17 GMT
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/DefaultAttribute.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/DefaultAttribute.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/DefaultAttribute.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/DefaultAttribute.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,98 @@
+package org.chboston.cnlp.nlp.annotation.attribute;
+
+import net.jcip.annotations.Immutable;
+
+/**
+ * Immutable Attribute
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 5/11/12
+ */
+@Immutable
+final public class DefaultAttribute implements Attribute {
+
+   private final AttributeType _attributeType;
+// TODO - swap out value from String to AttributeValue
+//   private final AttributeValue _attributeValue;
+   private final String _value;
+
+
+   /**
+    * @param attributeTypeName name of the type of this attribute
+    * @param value             of this attribute
+    */
+   public DefaultAttribute( final String attributeTypeName, final String value ) {
+      this( AttributeTypeFactory.getAttributeForName( attributeTypeName ), value );
+   }
+
+   /**
+    * @param attributeType for this attribute
+    * @param value         of this attribute
+    */
+   public DefaultAttribute( final AttributeType attributeType, final String value ) {
+      _attributeType = attributeType;
+      _value = value;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return _attributeType.getName();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AttributeType getAttributeType() {
+      return _attributeType;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getValue() {
+      return _value;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean hasAttributeValue( final AttributeValue attributeValue ) {
+      return attributeValue != null && attributeValue.isAttributeValue( getValue() );
+   }
+
+   /**
+    * @param object possible attribute
+    * @return true if an Attribute with the same name (case insensitive), and the same value (case sensitive)
+    */
+   @Override
+   public boolean equals( final Object object ) {
+      return (object instanceof Attribute
+//            && getName().equalsIgnoreCase( ((Attribute) object).getName() )
+              && _attributeType.equals( ((Attribute)object).getAttributeType() )
+              && _value.equals( ((Attribute)object).getValue() ));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      // Careful - two attribute types will match even if names are different case
+      return _attributeType.hashCode() + _value.hashCode();
+   }
+
+   /**
+    * @return "Annotation Attribute [name] = [value]
+    */
+   @Override
+   public String toString() {
+      return "Annotation Attribute " + getName() + " = " + _value;
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/DefinedAttributeType.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/DefinedAttributeType.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/DefinedAttributeType.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/DefinedAttributeType.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,72 @@
+package org.chboston.cnlp.nlp.annotation.attribute;
+
+/**
+ * Predefined types of attributes
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 5/21/12
+ */
+public enum DefinedAttributeType implements AttributeType {
+   UNIQUE_ID( "Unique ID", "id" ),
+   CUI( "Associated Code (CUI)", "associatedcode", "associatecode", "cui" ),
+   TUI( "Associated Type (TUI)", "tui" ),
+   SEVERITY( "Severity", "severity_normalization" ),
+   UNCERTAINTY( "Uncertainty", "uncertainty_indicator_normalization" ),
+   GENERIC( "Generic", "generic_normalization" ),
+   SUBJECT( "Subject", "subject_normalization_cu" ),
+   NEGATION( "Negation", "negation_indicator_normalization" ),
+   HISTORY_OF( "History of", "historyof_normalization", "historyof" ),
+   STATUS( "Status" ),
+   CONDITIONAL( "Conditional", "conditional_normalization" ),
+   RELATION_NEGATION( "Relation Negation", "umls_relation_negation", "relation_negation" ),
+   REALITY( "Reality" ),
+   CONTEXT_ASPECT( "Contextual Aspect", "contextualaspect" ),
+   CONTEXT_MODALITY( "Contextual Modality", "contextualmoduality", "contextual modularity", "contextualmodality" ),
+   DEGREE( "Degree" ),
+   DOC_TIME_REL( "Document Relative Time", "doctimerel" ),
+   PERMANENCE( "Permanence" ),
+   POLARITY( "Polarity" ),
+   RELATION_TYPE( "Relation Type" ),
+   TYPE( "Type" ),
+   SEMANTIC_TYPE( "Type" ),
+   CLASS( "Class" ),
+   SENTENCE( "Sentence" ),
+   // The original source of the annotation.  Can be Annotator, System, Closure, etc.
+   CREATOR( "Creator" );
+
+
+   private final String _name;
+   private final String[] _codes;
+
+   private DefinedAttributeType( final String name, final String... codes ) {
+      _name = name;
+      _codes = codes;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return _name;
+   }
+
+
+   static public DefinedAttributeType getDefinedAttibuteType( final String possibleCode ) {
+      for ( DefinedAttributeType type : DefinedAttributeType.values() ) {
+         if ( type._name.equalsIgnoreCase( possibleCode ) ) {
+            return type;
+         }
+         if ( type._codes != null ) {
+            for ( String code : type._codes ) {
+               if ( code.equalsIgnoreCase( possibleCode ) ) {
+                  return type;
+               }
+            }
+         }
+      }
+      return null;
+   }
+
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/EventAttributeValue.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/EventAttributeValue.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/EventAttributeValue.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/EventAttributeValue.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,52 @@
+package org.chboston.cnlp.nlp.annotation.attribute;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 8/8/13
+ */
+public enum EventAttributeValue implements AttributeValue {
+
+   // Polarity is "POS" or "NEG" for THYME
+   POSITIVE( "Positive", "POS" ),
+   NEGATIVE( "Negative", "NEG" ),
+   NEGATED( "Negated", "NEG" ),
+   // Contextual Modality is "ACTUAL" "HYPOTHETICAL" "HEDGED" or "GENERIC" for THYME
+   ACTUAL( "Actual", "ACTUAL" ),
+   HYPOTHETICAL( "Hypothetical", "HYPOTHETICAL" ),
+   HEDGED( "Hedged", "HEDGED" ),
+   GENERIC( "Generic", "GENERIC" ),
+   // DocTimeRel
+   DOC_TIME_REL( "Document Time Relation", "DOCTIMEREL" );
+
+
+   private final String _name;
+   private final Collection<String> _keys;
+
+   private EventAttributeValue( final String name, final String... keys ) {
+      _name = name;
+      _keys = new HashSet<>( keys.length );
+      _keys.addAll( Arrays.asList( keys ) );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return _name;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean isAttributeValue( final String key ) {
+      return key != null && _keys.contains( key.toUpperCase() );
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/TlinkAttributeValue.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/TlinkAttributeValue.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/TlinkAttributeValue.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/TlinkAttributeValue.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,51 @@
+package org.chboston.cnlp.nlp.annotation.attribute;
+
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 8/8/13
+ */
+public enum TlinkAttributeValue implements AttributeValue {
+
+   // TODO refactor everywhere to use this
+
+   BEFORE( "Before", "BEFORE" ),
+   AFTER( "After", "AFTER" ),
+   CONTAINS( "Contains", "CONTAINS" ),
+   CONTAINED_BY( "Within", "CONTAINED-BY" ),
+   BEGINS_ON( "Begins on", "BEGINS-ON" ),
+   ENDS_ON( "Ends on", "ENDS-ON" ),
+   OVERLAP( "Overlaps", "OVERLAP" );
+
+   private final String _name;
+   private final Collection<String> _keys;
+
+   private TlinkAttributeValue( final String name, final String... keys ) {
+      _name = name;
+      _keys = new HashSet<>( keys.length );
+      _keys.addAll( Arrays.asList( keys ) );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return _name;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean isAttributeValue( final String key ) {
+      return key != null && _keys.contains( key.toUpperCase() );
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/UnknownAttributeType.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/UnknownAttributeType.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/UnknownAttributeType.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/attribute/UnknownAttributeType.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,33 @@
+package org.chboston.cnlp.nlp.annotation.attribute;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 3/28/13
+ */
+public enum UnknownAttributeType implements AttributeType {
+   INSTANCE;
+
+   static public UnknownAttributeType getInstance() {
+      return INSTANCE;
+   }
+
+   static final private String NAME = "Unknown Attribute Type";
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return NAME;
+   }
+
+   /**
+    * @return the result of <code>getName()</code>
+    */
+   @Override
+   public String toString() {
+      return NAME;
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ClassType.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ClassType.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ClassType.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ClassType.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,15 @@
+package org.chboston.cnlp.nlp.annotation.classtype;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 5/9/12
+ */
+public interface ClassType {
+
+   /**
+    * @return Human-Understandable Description of the Class Type
+    */
+   public String getName();
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ClassTypeFactory.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ClassTypeFactory.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ClassTypeFactory.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ClassTypeFactory.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,67 @@
+package org.chboston.cnlp.nlp.annotation.classtype;
+
+import java.util.logging.Logger;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/11/2014
+ */
+final public class ClassTypeFactory {
+
+   private ClassTypeFactory() {
+   }
+
+   static private final Logger LOGGER = Logger.getLogger( "ClassTypeFactory" );
+
+   static public ClassType getClassType( final String description ) {
+      if ( description == null || description.isEmpty() ) {
+         return UnknownClassType.getInstance();
+      }
+      final String classTypeName = description.toLowerCase();
+      switch ( classTypeName ) {
+         case "event":
+            return TemporalClassType.EVENT;
+         case "timex3":
+            return TemporalClassType.TIMEX;
+         case "sign_symptom":
+            return SemanticClassType.SIGN_OR_SYMPTOM;
+         case "disease_disorder":
+            return SemanticClassType.DISEASE_DISORDER;
+         case "anatomical_site":
+            return SemanticClassType.ANATOMICAL_SITE;
+         case "medications/drugs":
+            return SemanticClassType.MEDICATION;
+         case "medication":
+            return SemanticClassType.MEDICATION;
+         case "procedure":
+            return SemanticClassType.PROCEDURE;
+         case "lab":
+            return SemanticClassType.PROCEDURE;
+         case "phenomena":
+            return SemanticClassType.PHENOMENA;
+         case "clinical_attribute":
+            return SemanticClassType.CLINICAL_ATTRIBUTE;
+         case "generic_class":
+            return SemanticClassType.MISC;
+         case "historyof_indicator_class":
+            return ModifierClassType.HISTORY_OF;
+         case "conditional_class":
+            return ModifierClassType.CONDITIONAL;
+         case "uncertainty_indicator_class":
+            return ModifierClassType.UNCERTAINTY;
+         case "negation_indicator_class":
+            return ModifierClassType.NEGATION;
+         case "doctime":
+            return TemporalClassType.DOCTIME;
+         case "tlink":
+            return TemporalClassType.TLINK;
+         case "alink":
+            return TemporalClassType.ALINK;
+      }
+      // TODO:  add known person : semantic class types or other?
+      return new CustomClassType( description );
+   }
+
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/CustomClassType.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/CustomClassType.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/CustomClassType.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/CustomClassType.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,61 @@
+package org.chboston.cnlp.nlp.annotation.classtype;
+
+import net.jcip.annotations.Immutable;
+
+/**
+ * For a Class Type that is not predefined
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 5/9/12
+ */
+@Immutable
+final public class CustomClassType implements ClassType {
+
+
+   private final String _name;
+
+   /**
+    * @param name name / name of this class type
+    */
+   public CustomClassType( final String name ) {
+      _name = (name != null ? name : "Unknown Class Type");
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return _name;
+   }
+
+   /**
+    * @return the result of <code>getName()</code>
+    */
+   @Override
+   public String toString() {
+      return getName();
+   }
+
+   /**
+    * @return true if the Semantic Types have the same description
+    */
+   @Override
+   public boolean equals( final Object object ) {
+      if ( !(object instanceof ClassType) ) {
+         return false;
+      }
+      final ClassType classType = (ClassType)object;
+      return classType.getName().equals( _name );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return _name.hashCode();
+   }
+
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ModifierClassType.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ModifierClassType.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ModifierClassType.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/ModifierClassType.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,38 @@
+package org.chboston.cnlp.nlp.annotation.classtype;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 11/23/12
+ */
+public enum ModifierClassType implements ClassType {
+
+   HISTORY_OF( "History of" ),
+
+   CONDITIONAL( "Conditional" ),
+   UNCERTAINTY( "Uncertainty" ),
+   NEGATION( "Negation" );
+
+   private final String _name;
+
+   private ModifierClassType( final String name ) {
+      _name = name;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return _name;
+   }
+
+   /**
+    * @return the result of <code>getName()</code>
+    */
+   @Override
+   public String toString() {
+      return getName();
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/SemanticClassType.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/SemanticClassType.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/SemanticClassType.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/SemanticClassType.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,42 @@
+package org.chboston.cnlp.nlp.annotation.classtype;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 5/8/12
+ */
+public enum SemanticClassType implements ClassType {
+
+   SIGN_OR_SYMPTOM( "Sign or Symptom" ),
+   PROCEDURE( "Procedure" ),
+   DISEASE_DISORDER( "Disease or Disorder" ),
+   MEDICATION( "Medication" ),
+   ANATOMICAL_SITE( "Anatomical Site" ),
+   CLINICAL_ATTRIBUTE( "Clinical Attribute" ),
+   PHENOMENA( "Phenomena" ),
+   MISC( "Miscellaneous" ),
+   UNKNOWN( "Unknown" );
+
+   private final String _name;
+
+   private SemanticClassType( final String name ) {
+      _name = name;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return _name;
+   }
+
+   /**
+    * @return the result of <code>getName()</code>
+    */
+   @Override
+   public String toString() {
+      return getName();
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/TemporalClassType.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/TemporalClassType.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/TemporalClassType.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/TemporalClassType.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,38 @@
+package org.chboston.cnlp.nlp.annotation.classtype;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/1/2014
+ */
+public enum TemporalClassType implements ClassType {
+
+   DOCTIME( "Document Time" ),
+   EVENT( "Temporal Event" ),
+   TIMEX( "Temporal Expression" ),
+   TLINK( "Temporal Relation" ),
+   ALINK( "Aspectual Link" );
+
+   private final String _name;
+
+   private TemporalClassType( final String name ) {
+      _name = name;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return _name;
+   }
+
+   /**
+    * @return the result of <code>getName()</code>
+    */
+   @Override
+   public String toString() {
+      return getName();
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/UnknownClassType.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/UnknownClassType.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/UnknownClassType.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/classtype/UnknownClassType.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,33 @@
+package org.chboston.cnlp.nlp.annotation.classtype;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 3/28/13
+ */
+public enum UnknownClassType implements ClassType {
+   INSTANCE;
+
+   static public UnknownClassType getInstance() {
+      return INSTANCE;
+   }
+
+   static private final String NAME = "Unknown Class Type";
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getName() {
+      return NAME;
+   }
+
+   /**
+    * @return the result of <code>getName()</code>
+    */
+   @Override
+   public String toString() {
+      return NAME;
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChain.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChain.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChain.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChain.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,24 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 6/5/13
+ */
+public interface CoreferenceChain extends Entity, Iterable<Entity> {
+
+
+   /**
+    * @return number of Elements in the chain
+    */
+   public int getChainLength();
+
+   /**
+    * @param entity some Entity that may or may not be an element in the chain
+    * @return true if the given Entity is in the chain
+    */
+   public boolean contains( Entity entity );
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChainComparator.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChainComparator.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChainComparator.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChainComparator.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,49 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+
+import java.util.Collection;
+import java.util.Comparator;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 11/5/2014
+ */
+public enum CoreferenceChainComparator implements Comparator<Collection<Entity>> {
+   INSTANCE;
+
+   public static CoreferenceChainComparator getInstance() {
+      return INSTANCE;
+   }
+
+   private CoreferenceChainComparator() {
+   }
+
+   /**
+    * Sorts as if each coreference chain were a single span
+    * <p/>
+    * {@inheritDoc}
+    */
+   @Override
+   public int compare( final Collection<Entity> coreferenceEntities1,
+                       final Collection<Entity> coreferenceEntities2 ) {
+      int min1 = Integer.MAX_VALUE;
+      int max1 = Integer.MIN_VALUE;
+      for ( Entity entity1 : coreferenceEntities1 ) {
+         min1 = Math.min( min1, entity1.getTextSpan().getStartIndex() );
+         max1 = Math.max( max1, entity1.getTextSpan().getEndIndex() );
+      }
+      int min2 = Integer.MAX_VALUE;
+      int max2 = Integer.MIN_VALUE;
+      for ( Entity entity2 : coreferenceEntities2 ) {
+         min2 = Math.min( min2, entity2.getTextSpan().getStartIndex() );
+         max2 = Math.max( max2, entity2.getTextSpan().getEndIndex() );
+      }
+      if ( min1 != min2 ) {
+         return min1 - min2;
+      }
+      return max1 - max2;
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChainSpanComparator.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChainSpanComparator.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChainSpanComparator.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceChainSpanComparator.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,49 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.textspan.TextSpan;
+
+import java.util.Collection;
+import java.util.Comparator;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 11/5/2014
+ */
+public enum CoreferenceChainSpanComparator implements Comparator<Collection<TextSpan>> {
+   INSTANCE;
+
+   public static CoreferenceChainSpanComparator getInstance() {
+      return INSTANCE;
+   }
+
+   private CoreferenceChainSpanComparator() {
+   }
+
+   /**
+    * Sorts as if each coreference chain were a single span
+    * <p/>
+    * {@inheritDoc}
+    */
+   @Override
+   public int compare( final Collection<TextSpan> coreferenceTextSpans1,
+                       final Collection<TextSpan> coreferenceTextSpans2 ) {
+      int min1 = Integer.MAX_VALUE;
+      int max1 = Integer.MIN_VALUE;
+      for ( TextSpan textSpan : coreferenceTextSpans1 ) {
+         min1 = Math.min( min1, textSpan.getStartIndex() );
+         max1 = Math.max( max1, textSpan.getEndIndex() );
+      }
+      int min2 = Integer.MAX_VALUE;
+      int max2 = Integer.MIN_VALUE;
+      for ( TextSpan textSpan : coreferenceTextSpans2 ) {
+         min2 = Math.min( min2, textSpan.getStartIndex() );
+         max2 = Math.max( max2, textSpan.getEndIndex() );
+      }
+      if ( min1 != min2 ) {
+         return min1 - min2;
+      }
+      return max1 - max2;
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceCollection.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceCollection.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceCollection.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceCollection.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,74 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.annotation.store.AnnotationStore;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+
+import java.util.*;
+import java.util.logging.Logger;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 6/17/13
+ */
+final public class CoreferenceCollection {
+
+   static private final Logger LOGGER = Logger.getLogger( CoreferenceCollection.class.getName() );
+
+
+   private final Map<Entity, Integer> _referenceIdMap;
+   private final Map<Integer, CoreferenceChain> _coreferenceChainMap;
+
+
+   public CoreferenceCollection( final AnnotationStore annotationStore ) {
+      final List<CoreferenceChain> coreferenceChains = annotationStore.getCoreferenceChains();
+      _referenceIdMap = new HashMap<>();
+      _coreferenceChainMap = new HashMap<>( coreferenceChains.size() );
+      for ( CoreferenceChain coreferenceChain : coreferenceChains ) {
+         final int hashCode = coreferenceChain.hashCode();
+         _coreferenceChainMap.put( hashCode, coreferenceChain );
+         for ( Entity entity : coreferenceChain ) {
+            final Integer oldValue = _referenceIdMap.put( entity, hashCode );
+            if ( oldValue != null && oldValue != hashCode ) {
+               LOGGER.severe(
+                     "Coreference for " + entity.getTextSpan() + " exists as " + oldValue + " and " + hashCode );
+            }
+         }
+      }
+   }
+
+   public Set<Integer> getReferenceIds() {
+      return _coreferenceChainMap.keySet();
+   }
+
+   public int getReferenceId( final Entity entity ) {
+      final Integer id = _referenceIdMap.get( entity );
+      if ( id != null ) {
+         return id;
+      }
+      return Integer.MIN_VALUE;
+   }
+
+   public Iterator<Entity> getEntities( final int referenceId ) {
+      final CoreferenceChain chain = _coreferenceChainMap.get( referenceId );
+      if ( chain != null ) {
+         return chain.iterator();
+      }
+      return EMPTY_ITERATOR;
+   }
+
+
+   static private final Iterator<Entity> EMPTY_ITERATOR = new Iterator<Entity>() {
+      public boolean hasNext() {
+         return false;
+      }
+
+      public Entity next() {
+         return null;
+      }
+
+      public void remove() {
+      }
+   };
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceFactory.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceFactory.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceFactory.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/CoreferenceFactory.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,538 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.annotation.Annotation;
+import org.chboston.cnlp.nlp.annotation.annotation.AnnotationSpanComparator;
+import org.chboston.cnlp.nlp.annotation.attribute.AttributeUtil;
+import org.chboston.cnlp.nlp.annotation.classtype.ClassType;
+import org.chboston.cnlp.nlp.annotation.classtype.SemanticClassType;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+import org.chboston.cnlp.nlp.annotation.event.DocTimeRel;
+import org.chboston.cnlp.nlp.annotation.textspan.TextSpan;
+import org.chboston.cnlp.nlp.util.ArrayListMap;
+import org.chboston.cnlp.nlp.util.CollectionMap;
+import org.chboston.cnlp.nlp.util.HashSetMap;
+
+import java.util.*;
+
+import static org.chboston.cnlp.nlp.annotation.classtype.SemanticClassType.*;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 6/20/13
+ */
+final public class CoreferenceFactory {
+
+   private CoreferenceFactory() {
+   }
+
+
+   // Anatomical Sites (and Clinical Attributes?) should not be associated directly with Events
+   // Sign/Symptom, Test/Procedure, Disease/Disorder, Medication, Phenomena can have associated Events
+   static public final SemanticClassType[] VALID_EVENT_CLASSES = { SIGN_OR_SYMPTOM, PROCEDURE, DISEASE_DISORDER,
+                                                                   MEDICATION, PHENOMENA, CLINICAL_ATTRIBUTE, MISC };
+
+
+   static public List<CoreferenceChain> createCoreferenceChainsOld( final Iterable<Collection<TextSpan>> textSpanChains,
+                                                                 final Collection<Entity> namedEntities,
+                                                                 final Collection<Entity> events,
+                                                                 final Collection<Entity> times ) {
+      if ( namedEntities.isEmpty() && events.isEmpty() ) {
+         return Collections.emptyList();
+      }
+//      final List<CoreferenceChain> coreferenceChainList = new ArrayList<>();
+//      coreferenceChainList.addAll( createCoreferenceChains( textSpanChains, namedEntities, events, times, true ) );
+//      coreferenceChainList.addAll( createCoreferenceChains( textSpanChains, namedEntities, events, times, false ) );
+//      return Collections.unmodifiableList( coreferenceChainList );
+
+      ////////////////   Named Entities to Semantic Groups   ////////////
+      // create a collection of all named entities sorted by semantic type
+      final ArrayListMap<ClassType, Entity> semanticEntityMap = getClassEntities( namedEntities );
+      ////////////////   Named Entities to Chains   ////////////
+      // Get Coreference chains of Named Entities by class type
+      final ArrayListMap<ClassType, Collection<Entity>> semanticEntityChainMap = new ArrayListMap<>();
+      final Collection<Entity> usedNamedEntities1 = new HashSet<>();
+      for ( ClassType semanticType : SemanticClassType.values() ) {
+         final Collection<Entity> semanticEntities = semanticEntityMap.obtain( semanticType );
+         if ( semanticEntities == null || semanticEntities.isEmpty() ) {
+            continue;
+         }
+         // for each coreference chain, see if there are any entities of the current semantic type that intersect
+         final Collection<Collection<Entity>> entityCorefChains
+               = createEntityCorefChains( semanticEntities, textSpanChains, usedNamedEntities1 );
+         // combine overlapping coreference chains
+         final Collection<Collection<Entity>> combinedCorefChains = getCombinedCorefChains( entityCorefChains );
+         semanticEntityChainMap.addAll( semanticType, combinedCorefChains );
+         // cTakes can create multiple overlapping same-semantic entities (multiple cuis).  Make chains.  10-31-2014 spf
+         // These would be chains of -one- text span but multiple entities of the same semantic type
+         final Collection<Collection<Entity>> overlappingEntities
+               = combineOverlappingEntities( semanticEntities, usedNamedEntities1 );
+         semanticEntityChainMap.addAll( semanticType, overlappingEntities );
+      }
+      ////////////////   Events to DocTimeRel Groups   ////////////
+      // Split Events by docTimeRel
+      final CollectionMap<DocTimeRel, Entity> docTimeRelEventMap = new HashSetMap<>();
+      for ( Entity event : events ) {
+         final DocTimeRel docTimeRel = DocTimeRel.getDocTimeRel( event );
+         if ( docTimeRel != null ) {
+            docTimeRelEventMap.place( docTimeRel, event );
+         }
+      }
+      ////////////////   Semantic Group Chains and DocTimeRel Events to Semantic DocTimeRel Chains  ////////////
+      final Collection<Collection<Entity>> semanticDocTimeRelChains = new ArrayList<>();
+      for ( ClassType semanticType : VALID_EVENT_CLASSES ) {
+         final Collection<Collection<Entity>> semanticEntityChains = semanticEntityChainMap.obtain( semanticType );
+         // add events to chains
+         semanticDocTimeRelChains.addAll( createSemanticDocTimeRelChains( semanticEntityChains, docTimeRelEventMap ) );
+      }
+      semanticDocTimeRelChains.addAll( semanticEntityChainMap.obtain( ANATOMICAL_SITE ) );
+      final Collection<Entity> usedNamedEntities2 = new HashSet<>();
+      for ( Collection<Entity> usedChainLinks : semanticDocTimeRelChains ) {
+         usedNamedEntities2.addAll( usedChainLinks );
+      }
+      ////////////////   Semantic Group Lone Entities and DocTimeRel Events to Semantic DocTimeRel Chains  ////////////
+      for ( ClassType semanticType : VALID_EVENT_CLASSES ) {
+         final Collection<Entity> semanticEntities = semanticEntityMap.obtain( semanticType );
+         final Collection<Collection<Entity>> entityEvents = combineOverlappingEntityEvents( semanticEntities,
+               usedNamedEntities2, events );
+         semanticDocTimeRelChains.addAll( entityEvents );
+      }
+      ////////////////   Semantic DocTimeRel Chains to Coreference Objects  ////////////
+      // Turn the chains of entities and events into actual coreference objects
+      final Collection<CoreferenceChain> coreferenceChains = createCoreferenceChains( semanticDocTimeRelChains );
+      // sort the coreference objects by text span
+      final List<CoreferenceChain> coreferenceChainList = new ArrayList<>( coreferenceChains );
+      Collections.sort( coreferenceChainList, AnnotationSpanComparator.getInstance() );
+      return Collections.unmodifiableList( coreferenceChainList );
+   }
+
+   /**
+    * Incorporates negation
+    * @param textSpanChains -
+    * @param namedEntities -
+    * @param events -
+    * @param times -
+    * @return Coreference Chains built with Semantic Type, DocTimeRel, and Negation state
+    */
+   static public List<CoreferenceChain> createCoreferenceChains( final Iterable<Collection<TextSpan>> textSpanChains,
+                                                                 final Collection<Entity> namedEntities,
+                                                                 final Collection<Entity> events,
+                                                                 final Collection<Entity> times ) {
+      if ( namedEntities.isEmpty() && events.isEmpty() ) {
+         return Collections.emptyList();
+      }
+      ////////////////   Named Entities to Semantic Groups   ////////////
+      // create a collection of all named entities sorted by semantic type
+      // misses corefs
+//      final ArrayListMap<ClassType, Entity> semanticEntityMap = getClassEntities( namedEntities, wantNegated );
+      // Generates good corefs, but many repeats of same event
+      final ArrayListMap<ClassType, Entity> semanticEntityMap = getClassEntities( namedEntities );
+      ////////////////   Named Entities to Chains   ////////////
+      // Get Coreference chains of Named Entities by class type
+      final ArrayListMap<ClassType, Collection<Entity>> semanticEntityChainMap = new ArrayListMap<>();
+      final Collection<Entity> usedNamedEntities1 = new HashSet<>();
+      for ( ClassType semanticType : SemanticClassType.values() ) {
+         final Collection<Entity> semanticEntities = semanticEntityMap.obtain( semanticType );
+         if ( semanticEntities == null || semanticEntities.isEmpty() ) {
+            continue;
+         }
+         // for each coreference chain, see if there are any entities of the current semantic type that intersect
+         final Collection<Collection<Entity>> entityCorefChains
+               = createEntityCorefChains( semanticEntities, textSpanChains, usedNamedEntities1 );
+         // combine overlapping coreference chains
+         final Collection<Collection<Entity>> combinedCorefChains = getCombinedCorefChains( entityCorefChains );
+         semanticEntityChainMap.addAll( semanticType, combinedCorefChains );
+         // cTakes can create multiple overlapping same-semantic entities (multiple cuis).  Make chains.  10-31-2014 spf
+         // These would be chains of -one- text span but multiple entities of the same semantic type
+         final Collection<Collection<Entity>> overlappingEntities
+               = combineOverlappingEntities( semanticEntities, usedNamedEntities1 );
+         semanticEntityChainMap.addAll( semanticType, overlappingEntities );
+      }
+      ////////////////   Events to DocTimeRel Groups   ////////////
+      // Split Events by docTimeRel
+      final CollectionMap<DocTimeRel, Entity> posDocTimeRelEventMap = getDocTimeRelEvents( events, false );
+      final CollectionMap<DocTimeRel, Entity> negDocTimeRelEventMap = getDocTimeRelEvents( events, true );
+////////////////   Semantic Group Chains and DocTimeRel Events to Semantic DocTimeRel Chains  ////////////
+      final Collection<Collection<Entity>> semanticDocTimeRelChains = new ArrayList<>();
+      for ( ClassType semanticType : VALID_EVENT_CLASSES ) {
+         final Collection<Collection<Entity>> semanticEntityChains = semanticEntityChainMap.obtain( semanticType );
+         // add events to chains
+         semanticDocTimeRelChains.addAll( createSemanticDocTimeRelChains( semanticEntityChains, posDocTimeRelEventMap, negDocTimeRelEventMap ) );
+      }
+      semanticDocTimeRelChains.addAll( semanticEntityChainMap.obtain( ANATOMICAL_SITE ) );
+      final Collection<Entity> usedNamedEntities2 = new HashSet<>();
+      for ( Collection<Entity> usedChainLinks : semanticDocTimeRelChains ) {
+         usedNamedEntities2.addAll( usedChainLinks );
+      }
+      ////////////////   Semantic Group Lone Entities and DocTimeRel Events to Semantic DocTimeRel Chains  ////////////
+      for ( ClassType semanticType : VALID_EVENT_CLASSES ) {
+         final Collection<Entity> semanticEntities = semanticEntityMap.obtain( semanticType );
+         final Collection<Collection<Entity>> entityEvents = combineOverlappingEntityEvents( semanticEntities,
+               usedNamedEntities2, events );
+         semanticDocTimeRelChains.addAll( entityEvents );
+      }
+      ////////////////   Semantic DocTimeRel Chains to Coreference Objects  ////////////
+      // Turn the chains of entities and events into actual coreference objects
+      final Collection<CoreferenceChain> coreferenceChains = createCoreferenceChains( semanticDocTimeRelChains );
+      // sort the coreference objects by text span
+      final List<CoreferenceChain> coreferenceChainList = new ArrayList<>( coreferenceChains );
+      Collections.sort( coreferenceChainList, AnnotationSpanComparator.getInstance() );
+      return Collections.unmodifiableList( coreferenceChainList );
+   }
+
+//   static public List<CoreferenceChain> createCoreferenceChains( final Iterable<Collection<TextSpan>> textSpanChains,
+//                                                                 final Collection<Entity> namedEntities,
+//                                                                 final Collection<Entity> events,
+//                                                                 final Collection<Entity> times,
+//                                                                 final boolean wantNegated ) {
+//      if ( namedEntities.isEmpty() && events.isEmpty() ) {
+//         return Collections.emptyList();
+//      }
+//      ////////////////   Named Entities to Semantic Groups   ////////////
+//      // create a collection of all named entities sorted by semantic type
+//      // misses corefs
+////      final ArrayListMap<ClassType, Entity> semanticEntityMap = getClassEntities( namedEntities, wantNegated );
+//      // Generates good corefs, but many repeats of same event
+//      final ArrayListMap<ClassType, Entity> semanticEntityMap = getClassEntities( namedEntities, wantNegated );
+//      ////////////////   Named Entities to Chains   ////////////
+//      // Get Coreference chains of Named Entities by class type
+//      final ArrayListMap<ClassType, Collection<Entity>> semanticEntityChainMap = new ArrayListMap<>();
+//      final Collection<Entity> usedNamedEntities1 = new HashSet<>();
+//      for ( ClassType semanticType : SemanticClassType.values() ) {
+//         final Collection<Entity> semanticEntities = semanticEntityMap.obtain( semanticType );
+//         if ( semanticEntities == null || semanticEntities.isEmpty() ) {
+//            continue;
+//         }
+//         // for each coreference chain, see if there are any entities of the current semantic type that intersect
+//         final Collection<Collection<Entity>> entityCorefChains
+//               = createEntityCorefChains( semanticEntities, textSpanChains, usedNamedEntities1 );
+//         // combine overlapping coreference chains
+//         final Collection<Collection<Entity>> combinedCorefChains = getCombinedCorefChains( entityCorefChains );
+//         semanticEntityChainMap.addAll( semanticType, combinedCorefChains );
+//         // cTakes can create multiple overlapping same-semantic entities (multiple cuis).  Make chains.  10-31-2014 spf
+//         // These would be chains of -one- text span but multiple entities of the same semantic type
+//         final Collection<Collection<Entity>> overlappingEntities
+//               = combineOverlappingEntities( semanticEntities, usedNamedEntities1 );
+//         semanticEntityChainMap.addAll( semanticType, overlappingEntities );
+//      }
+//      ////////////////   Events to DocTimeRel Groups   ////////////
+//      // Split Events by docTimeRel
+//      final CollectionMap<DocTimeRel, Entity> docTimeRelEventMap = getDocTimeRelEvents( events, wantNegated );
+//      ////////////////   Semantic Group Chains and DocTimeRel Events to Semantic DocTimeRel Chains  ////////////
+//      final Collection<Collection<Entity>> semanticDocTimeRelChains = new ArrayList<>();
+//      for ( ClassType semanticType : VALID_EVENT_CLASSES ) {
+//         final Collection<Collection<Entity>> semanticEntityChains = semanticEntityChainMap.obtain( semanticType );
+//         // add events to chains
+//         semanticDocTimeRelChains.addAll( createSemanticDocTimeRelChains( semanticEntityChains, docTimeRelEventMap ) );
+//      }
+//      semanticDocTimeRelChains.addAll( semanticEntityChainMap.obtain( ANATOMICAL_SITE ) );
+//      final Collection<Entity> usedNamedEntities2 = new HashSet<>();
+//      for ( Collection<Entity> usedChainLinks : semanticDocTimeRelChains ) {
+//         usedNamedEntities2.addAll( usedChainLinks );
+//      }
+//      ////////////////   Semantic Group Lone Entities and DocTimeRel Events to Semantic DocTimeRel Chains  ////////////
+//      for ( ClassType semanticType : VALID_EVENT_CLASSES ) {
+//         final Collection<Entity> semanticEntities = semanticEntityMap.obtain( semanticType );
+//         final Collection<Collection<Entity>> entityEvents = combineOverlappingEntityEvents( semanticEntities,
+//               usedNamedEntities2, events );
+//         semanticDocTimeRelChains.addAll( entityEvents );
+//      }
+//      ////////////////   Semantic DocTimeRel Chains to Coreference Objects  ////////////
+//      // Turn the chains of entities and events into actual coreference objects
+//      final Collection<CoreferenceChain> coreferenceChains = createCoreferenceChains( semanticDocTimeRelChains );
+//      // sort the coreference objects by text span
+//      final List<CoreferenceChain> coreferenceChainList = new ArrayList<>( coreferenceChains );
+//      Collections.sort( coreferenceChainList, AnnotationSpanComparator.getInstance() );
+//      return Collections.unmodifiableList( coreferenceChainList );
+//   }
+
+   static private Collection<Collection<Entity>> createEntityCorefChains( final Iterable<Entity> semanticEntities,
+                                                                          final Iterable<Collection<TextSpan>> textSpanChains,
+                                                                          final Collection<Entity> usedNamedEntities ) {
+      final Collection<Collection<Entity>> entityCorefChains = new ArrayList<>();
+      if ( textSpanChains == null ) {
+         return entityCorefChains;
+      }
+      for ( Collection<TextSpan> textSpanChain : textSpanChains ) {
+         final Collection<Entity> intersectEntities = getIntersectEntities( textSpanChain, semanticEntities );
+         if ( intersectEntities.isEmpty() ) {
+            continue;
+         }
+         entityCorefChains.add( intersectEntities );
+         usedNamedEntities.addAll( intersectEntities );
+      }
+      return entityCorefChains;
+   }
+
+
+   static private Collection<Collection<Entity>> combineOverlappingEntities(
+         final Collection<Entity> semanticEntities, final Collection<Entity> usedNamedEntities ) {
+      final List<Entity> entityList = new ArrayList<>( semanticEntities );
+      // cTakes creates overlapping coreference chains.  Attempt to combine them'
+      final Collection<Collection<Entity>> intersectionEntityChains = new ArrayList<>();
+      for ( int i = 0; i < entityList.size() - 1; i++ ) {
+         final Entity entityI = entityList.get( i );
+         if ( usedNamedEntities.contains( entityI ) ) {
+            continue;
+         }
+         TextSpan currentTextSpan = entityI.getTextSpan();
+         final Collection<Entity> intersectionChain = new ArrayList<>();
+         for ( int j = i + 1; j < entityList.size(); j++ ) {
+            final Entity entityJ = entityList.get( j );
+            if ( usedNamedEntities.contains( entityJ ) ) {
+               continue;
+            }
+            if ( currentTextSpan.intersects( entityJ.getTextSpan() ) ) {
+               intersectionChain.add( entityI );
+               intersectionChain.add( entityJ );
+               currentTextSpan = currentTextSpan.getPossibleUnionSpan( entityJ.getTextSpan() );
+            }
+         }
+         if ( !intersectionChain.isEmpty() ) {
+            intersectionEntityChains.add( intersectionChain );
+            usedNamedEntities.addAll( intersectionChain );
+         }
+      }
+      return intersectionEntityChains;
+   }
+
+
+   static private Collection<Collection<Entity>> getCombinedCorefChains(
+         final Collection<Collection<Entity>> entityCorefChains ) {
+      final List<Collection<Entity>> combinedCorefChains = new ArrayList<>();
+      final List<Collection<Entity>> chainsList = new ArrayList<>( entityCorefChains );
+      final Collection<Collection<Entity>> usedChains = new HashSet<>();
+      final Collection<Entity> currentChain = new HashSet<>();
+      for ( int i = 0; i < chainsList.size() - 1; i++ ) {
+         if ( usedChains.contains( chainsList.get( i ) ) ) {
+            continue;
+         }
+         boolean chainIntersected = false;
+         currentChain.clear();
+         currentChain.addAll( chainsList.get( i ) );
+         for ( int j = i + 1; j < chainsList.size(); j++ ) {
+            if ( usedChains.contains( chainsList.get( j ) ) ) {
+               continue;
+            }
+            if ( doChainsIntersect( currentChain, chainsList.get( j ) ) ) {
+               chainIntersected = true;
+               currentChain.addAll( chainsList.get( j ) );
+               usedChains.add( chainsList.get( j ) );
+            }
+         }
+         if ( chainIntersected ) {
+            final List<Entity> combinedChain = new ArrayList<>( currentChain );
+            Collections.sort( combinedChain, AnnotationSpanComparator.getInstance() );
+            combinedCorefChains.add( combinedChain );
+         } else {
+            combinedCorefChains.add( chainsList.get( i ) );
+         }
+      }
+      Collections.sort( combinedCorefChains, CoreferenceChainComparator.getInstance() );
+      return combinedCorefChains;
+   }
+
+
+   static private Collection<Collection<Entity>> createSemanticDocTimeRelChains(
+         final Iterable<Collection<Entity>> semanticChains,
+         final CollectionMap<DocTimeRel, Entity> posDocTimeRelEventMap,
+         final CollectionMap<DocTimeRel, Entity> negDocTimeRelEventMap ) {
+      final Collection<Entity> chainLinksToRemove = new ArrayList<>();
+      final Collection<Collection<Entity>> semanticDocTimeRelChains = new ArrayList<>();
+      for ( Collection<Entity> semanticChain : semanticChains ) {
+         chainLinksToRemove.clear();
+         for ( DocTimeRel docTimeRel : DocTimeRel.values() ) {
+            final Collection<Entity> negIntersectEvents
+                  = getAllIntersectEntities( semanticChain, negDocTimeRelEventMap.obtain( docTimeRel ) );
+            if ( !negIntersectEvents.isEmpty() ) {
+               chainLinksToRemove.addAll( negIntersectEvents );
+               semanticDocTimeRelChains.add( negIntersectEvents );
+            }
+            final Collection<Entity> posIntersectEvents
+                  = getAllIntersectEntities( semanticChain, posDocTimeRelEventMap.obtain( docTimeRel ) );
+            if ( posIntersectEvents.isEmpty() ) {
+               continue;
+            }
+            posIntersectEvents.removeAll( negIntersectEvents );
+            chainLinksToRemove.addAll( posIntersectEvents );
+            semanticDocTimeRelChains.add( posIntersectEvents );
+         }
+         semanticChain.removeAll( chainLinksToRemove );
+         if ( semanticChain.size() > 1 ) {
+            // No Event in remaining chain links, add them to the full collection as-is
+            semanticDocTimeRelChains.add( semanticChain );
+         }
+      }
+      return semanticDocTimeRelChains;
+   }
+
+
+   static private Collection<Collection<Entity>> createSemanticDocTimeRelChains(
+         final Iterable<Collection<Entity>> semanticChains,
+         final CollectionMap<DocTimeRel, Entity> docTimeRelEventMap ) {
+      final Collection<Entity> chainLinksToRemove = new ArrayList<>();
+      final Collection<Collection<Entity>> semanticDocTimeRelChains = new ArrayList<>();
+      for ( Collection<Entity> semanticChain : semanticChains ) {
+         chainLinksToRemove.clear();
+         for ( DocTimeRel docTimeRel : DocTimeRel.values() ) {
+            final Collection<Entity> allIntersectEvents
+                  = getAllIntersectEntities( semanticChain, docTimeRelEventMap.obtain( docTimeRel ) );
+            if ( allIntersectEvents.isEmpty() ) {
+               continue;
+            }
+            chainLinksToRemove.addAll( allIntersectEvents );
+            semanticDocTimeRelChains.add( allIntersectEvents );
+         }
+         semanticChain.removeAll( chainLinksToRemove );
+         if ( semanticChain.size() > 1 ) {
+            // No Event in remaining chain links, add them to the full collection as-is
+            semanticDocTimeRelChains.add( semanticChain );
+         }
+      }
+      return semanticDocTimeRelChains;
+   }
+
+
+   static private Collection<Collection<Entity>> combineOverlappingEntityEvents(
+         final Iterable<Entity> semanticEntities,
+         final Collection<Entity> usedNamedEntities,
+         final Iterable<Entity> events ) {
+      final Collection<Collection<Entity>> entityEvents = new ArrayList<>();
+      for ( Entity semanticEntity : semanticEntities ) {
+         if ( usedNamedEntities.contains( semanticEntity ) ) {
+            continue;
+         }
+         final Collection<Entity> intersectEvents = getIntersectEvents( semanticEntity, events );
+         if ( !intersectEvents.isEmpty() ) {
+            usedNamedEntities.add( semanticEntity );
+            intersectEvents.add( semanticEntity );
+            entityEvents.add( intersectEvents );
+         }
+      }
+      return entityEvents;
+   }
+
+
+   static private Collection<CoreferenceChain> createCoreferenceChains(
+         final Iterable<Collection<Entity>> entityChains ) {
+      final Collection<CoreferenceChain> coreferenceChains = new ArrayList<>();
+      // Create CoreferenceChains
+      for ( Collection<Entity> entityChain : entityChains ) {
+         final Entity[] entityArray = entityChain.toArray( new Entity[ entityChain.size() ] );
+         final CoreferenceChain namedEntityChain = new DefaultEntityChain( "Factory", entityArray );
+         coreferenceChains.add( namedEntityChain );
+      }
+      return coreferenceChains;
+   }
+
+
+   static private <T extends Entity> ArrayListMap<ClassType, Entity> getClassEntities( final Iterable<T> entities ) {
+      final ArrayListMap<ClassType, Entity> classEntities = new ArrayListMap<>();
+      for ( T entity : entities ) {
+         classEntities.place( entity.getClassType(), entity );
+      }
+      return classEntities;
+   }
+
+   static private <T extends Entity> ArrayListMap<ClassType, Entity> getClassEntities( final Iterable<T> entities,
+                                                                                       final boolean wantNegated ) {
+      final ArrayListMap<ClassType, Entity> classEntities = new ArrayListMap<>();
+      for ( T entity : entities ) {
+         if ( AttributeUtil.hasNegativePolarity( entity ) == wantNegated ) {
+            classEntities.place( entity.getClassType(), entity );
+         }
+      }
+      return classEntities;
+   }
+
+
+   static private CollectionMap<DocTimeRel, Entity> getDocTimeRelEvents( final Iterable<Entity> events,
+                                                                         final boolean wantNegated ) {
+      // Split Events by docTimeRel
+      final CollectionMap<DocTimeRel, Entity> docTimeRelEventMap = new HashSetMap<>();
+      for ( Entity event : events ) {
+         final DocTimeRel docTimeRel = DocTimeRel.getDocTimeRel( event );
+         if ( docTimeRel != null && AttributeUtil.hasNegativePolarity( event ) == wantNegated ) {
+            docTimeRelEventMap.place( docTimeRel, event );
+         }
+      }
+      return docTimeRelEventMap;
+   }
+
+
+   static private Collection<Entity> getAllIntersectEntities( final Iterable<Entity> entityChain,
+                                                              final Collection<Entity> entities ) {
+      if ( entities == null || entities.isEmpty() ) {
+         return Collections.emptyList();
+      }
+      final Collection<Entity> allIntersectEntities = new ArrayList<>();
+      final Collection<Entity> usedEntities = new HashSet<>();
+      for ( Entity chainLink : entityChain ) {
+         TextSpan currentTextSpan = chainLink.getTextSpan();
+         for ( Entity entity : entities ) {
+            if ( currentTextSpan.intersects( entity.getTextSpan() ) ) {
+               currentTextSpan = currentTextSpan.getPossibleUnionSpan( entity.getTextSpan() );
+               if ( !usedEntities.contains( chainLink ) ) {
+                  allIntersectEntities.add( chainLink );
+                  usedEntities.add( chainLink );
+               }
+               if ( !usedEntities.contains( entity ) ) {
+                  allIntersectEntities.add( entity );
+                  usedEntities.add( entity );
+               }
+            }
+         }
+      }
+      return allIntersectEntities;
+   }
+
+   static private Collection<Entity> getIntersectEvents( final Annotation entity,
+                                                         final Iterable<Entity> events ) {
+      final Collection<Entity> intersectEvents = new ArrayList<>();
+      final Collection<Entity> usedEvents = new HashSet<>();
+      TextSpan currentTextSpan = entity.getTextSpan();
+      for ( Entity event : events ) {
+         if ( currentTextSpan.intersects( event.getTextSpan() ) ) {
+            currentTextSpan = currentTextSpan.getPossibleUnionSpan( event.getTextSpan() );
+            if ( !usedEvents.contains( event ) ) {
+               intersectEvents.add( event );
+               usedEvents.add( event );
+            }
+         }
+      }
+      return intersectEvents;
+   }
+
+   static private Collection<Entity> getIntersectEntities( final Iterable<TextSpan> textSpans,
+                                                           final Iterable<Entity> entities ) {
+      final Collection<Entity> intersectEntities = new ArrayList<>();
+      final Collection<Entity> usedEntities = new HashSet<>();
+      for ( TextSpan textSpan : textSpans ) {
+         TextSpan currentTextSpan = textSpan;
+         for ( Entity entity : entities ) {
+            if ( currentTextSpan.intersects( entity.getTextSpan() ) ) {
+               currentTextSpan = currentTextSpan.getPossibleUnionSpan( entity.getTextSpan() );
+               if ( !usedEntities.contains( entity ) ) {
+                  // Don't add an entity more than once
+                  intersectEntities.add( entity );
+                  usedEntities.add( entity );
+               }
+            }
+         }
+      }
+      return intersectEntities;
+   }
+
+   static private boolean doChainsIntersect( final Iterable<Entity> chain1, final Iterable<Entity> chain2 ) {
+      for ( Entity entity1 : chain1 ) {
+         for ( Entity entity2 : chain2 ) {
+            if ( entity1.getTextSpan().intersects( entity2.getTextSpan() ) ) {
+               return true;
+            }
+         }
+      }
+      return false;
+   }
+
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/DefaultEntityChain.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/DefaultEntityChain.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/DefaultEntityChain.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/DefaultEntityChain.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,348 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.annotation.Annotation;
+import org.chboston.cnlp.nlp.annotation.annotation.AnnotationSpanComparator;
+import org.chboston.cnlp.nlp.annotation.annotation.DefaultAnnotation;
+import org.chboston.cnlp.nlp.annotation.attribute.Attribute;
+import org.chboston.cnlp.nlp.annotation.attribute.AttributeType;
+import org.chboston.cnlp.nlp.annotation.attribute.DefaultAttribute;
+import org.chboston.cnlp.nlp.annotation.attribute.DefinedAttributeType;
+import org.chboston.cnlp.nlp.annotation.classtype.ClassType;
+import org.chboston.cnlp.nlp.annotation.classtype.CustomClassType;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+import org.chboston.cnlp.nlp.annotation.textspan.DefaultDiscontiguousTextSpan;
+import org.chboston.cnlp.nlp.annotation.textspan.TextSpan;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 6/5/13
+ */
+final public class DefaultEntityChain implements CoreferenceChain {
+
+   static private final Pattern SPACE_PATTERN = Pattern.compile( "\\s\\s\\s+" );
+
+   // Chains of a single entity are handled differently
+   private final boolean _isSingleton;
+   private final Annotation _annotation;
+
+   private final List<Entity> _chain;
+
+   private final int _hashcode;
+
+
+   public DefaultEntityChain( final String annotatorName, final Entity... elements ) {
+      if ( elements.length == 1 ) {
+         _isSingleton = true;
+         _annotation = elements[ 0 ];
+         _chain = Collections.unmodifiableList( Arrays.asList( elements ) );
+         _hashcode = _chain.hashCode();
+         return;
+      }
+      _isSingleton = false;
+      // sort the chain by text span for consistency in future operations
+      final List<Entity> entities = Arrays.asList( elements );
+      Collections.sort( entities, AnnotationSpanComparator.getInstance() );
+      _chain = Collections.unmodifiableList( entities );
+      _hashcode = _chain.hashCode();
+      // Annotation requirements
+      TextSpan runningTextSpan = null;
+      String runningSpannedText = null;
+      Set<TextSpan> textSpans = new HashSet<>();
+      final Set<ClassType> classTypes = new HashSet<>();
+      final Map<String, Set<String>> attributeMap = new HashMap<>();
+      boolean isFirst = true;
+      for ( Entity entity : _chain ) {
+         final TextSpan textSpan = entity.getTextSpan();
+         if ( isFirst ) {
+            runningTextSpan = textSpan;
+            runningSpannedText = entity.getSpannedText();
+         }
+         final boolean isNew = textSpans.add( textSpan );
+         if ( !isFirst && isNew ) {
+            // Create the spanned text - text of the elements with whitespace between
+            runningSpannedText = DefaultAnnotation.expandText( runningTextSpan, textSpan,
+                  runningSpannedText, entity.getSpannedText() );
+            runningTextSpan = new DefaultDiscontiguousTextSpan( textSpans.toArray( new TextSpan[ textSpans.size() ] ) );
+         }
+         isFirst = false;
+         classTypes.add( entity.getClassType() );
+         final List<String> attributeNames = entity.getAttributeNames();
+         for ( String attributeName : attributeNames ) {
+            Set<String> attributeValues = attributeMap.get( attributeName );
+            if ( attributeValues == null ) {
+               attributeValues = new HashSet<>( 1 );
+               attributeMap.put( attributeName, attributeValues );
+            }
+            attributeValues.add( entity.getAttribute( attributeName ).getValue() );
+         }
+      }
+      final StringBuilder sb = new StringBuilder( "Coreference Chain" );
+      if ( !classTypes.isEmpty() ) {
+         sb.append( " of" );
+         for ( ClassType classType : classTypes ) {
+            sb.append( " " ).append( classType.getName() );
+         }
+      }
+      // Need to make sure that we don't loose any attribute values
+      final Set<Attribute> attributes = new HashSet<>( attributeMap.size() );
+      for ( Map.Entry<String, Set<String>> attributeDef : attributeMap.entrySet() ) {
+         final Set<String> values = attributeDef.getValue();
+         attributes.add( createAttribute( attributeDef.getKey(), values.toArray( new String[ values.size() ] ) ) );
+      }
+      attributes.add( new DefaultAttribute( DefinedAttributeType.CREATOR, annotatorName ) );
+      _annotation = new DefaultAnnotation( runningTextSpan, runningSpannedText, new CustomClassType( sb.toString() ),
+            attributes.toArray( new Attribute[ attributes.size() ] ) );
+   }
+
+   // Need to make sure that we don't loose any attribute values
+   static private Attribute createAttribute( final String name, final String... values ) {
+      if ( values.length == 1 ) {
+         return new DefaultAttribute( name, values[ 0 ] );
+      }
+      final StringBuilder sb = new StringBuilder();
+      for ( String value : values ) {
+         sb.append( value ).append( " , " );
+      }
+      sb.setLength( sb.length() - 3 );
+      return new DefaultAttribute( name, sb.toString() );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int getChainLength() {
+      return _chain.size();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean contains( final Entity element ) {
+      return _chain.contains( element );
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public TextSpan getTextSpan() {
+      return _annotation.getTextSpan();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getSpannedText() {
+      return _annotation.getSpannedText();
+   }
+
+   /**
+    * a chain of "text | text | text"
+    * {@inheritDoc}
+    */
+   @Override
+   public String getSpannedTextRepresentation() {
+      final String[] texts = SPACE_PATTERN.split( getSpannedText() );
+      if ( texts.length == 1 ) {
+         return texts[ 0 ];
+      }
+      final StringBuilder sb = new StringBuilder();
+      for ( String text : texts ) {
+         sb.append( '[' ).append( text ).append( "] ... " );
+      }
+      sb.setLength( sb.length() - 5 );
+      return sb.toString();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public ClassType getClassType() {
+      return _annotation.getClassType();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean isClassType( final ClassType classType ) {
+      for ( Entity entity : _chain ) {
+         if ( entity.isClassType( classType ) ) {
+            return true;
+         }
+      }
+      return false;
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public List<String> getAttributeNames() {
+      return _annotation.getAttributeNames();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Attribute getAttribute( final String key ) {
+      return _annotation.getAttribute( key );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Attribute getAttribute( final AttributeType attributeType ) {
+      return _annotation.getAttribute( attributeType );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Collection<AttributeType> getAttributeTypes() {
+      return _annotation.getAttributeTypes();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Collection<Attribute> getAttributes() {
+      return _annotation.getAttributes();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean hasAttribute( final String key ) {
+      return _annotation.hasAttribute( key );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean hasAttribute( final AttributeType attributeType ) {
+      return _annotation.hasAttribute( attributeType );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getAttributeValue( final String key ) {
+      return _annotation.getAttributeValue( key );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getAttributeValue( final AttributeType attributeType ) {
+      return _annotation.getAttributeValue( attributeType );
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String getAnnotatorName() {
+      return _annotation.getAnnotatorName();
+   }
+
+   /**
+    * Does NOT check entities to make sure that their values are equal
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean areValuesEqual( final Annotation annotation ) {
+      if ( _isSingleton ) {
+         return _annotation.areValuesEqual( annotation );
+      }
+      if ( !annotation.getTextSpan().equals( getTextSpan() )
+           || !annotation.getSpannedTextRepresentation().equals( getSpannedTextRepresentation() )
+           || !annotation.getClassType().equals( getClassType() ) ) {
+         return false;
+      }
+      final Collection<String> annotationAttributeNames = annotation.getAttributeNames();
+      final Collection<String> attributeNames = getAttributeNames();
+      if ( annotationAttributeNames.size() != attributeNames.size() ) {
+         return false;
+      }
+      for ( String key : attributeNames ) {
+         if ( !getAttribute( key ).equals( annotation.getAttribute( key ) ) ) {
+            return false;
+         }
+      }
+      return true;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Iterator<Entity> iterator() {
+      return _chain.iterator();
+   }
+
+
+   /**
+    * @return "Coreference Chain: {@link org.chboston.cnlp.nlp.annotation.annotation.DefaultAnnotation#toString()}"
+    */
+   @Override
+   public String toString() {
+      if ( _isSingleton ) {
+         return _annotation.toString();
+      }
+      return "Coreference Chain: " + _annotation.toString();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals( final Object object ) {
+      if ( !(object instanceof CoreferenceChain) ) {
+         return false;
+      }
+      if ( !areValuesEqual( (CoreferenceChain)object ) ) {
+         return false;
+      }
+      // Don't need textspan or direction, they are handled by entities
+      final CoreferenceChain coreferenceChain = (CoreferenceChain)object;
+      if ( coreferenceChain.getChainLength() != getChainLength() ) {
+         return false;
+      }
+      for ( Entity element : _chain ) {
+         if ( !coreferenceChain.contains( element ) ) {
+            return false;
+         }
+      }
+      return true;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return _hashcode;
+   }
+
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/EntityIdCollection.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/EntityIdCollection.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/EntityIdCollection.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/EntityIdCollection.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,164 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.annotation.store.AnnotationStore;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+import org.chboston.cnlp.nlp.annotation.textspan.TextSpan;
+
+import java.util.*;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 6/17/13
+ */
+// TODO move to AnnotationStore
+public class EntityIdCollection {
+
+   static public final int NO_ENTITY_ID = Integer.MIN_VALUE;
+
+
+   // Key = Entity (named, event, timex), Value = id number for each "unique" reference.
+   // Co-referent entities will have the same id number
+   private final Map<Entity, Integer> _entityIdMap;
+   // Key = id number for each "unique" reference, value = primary entity
+   private final Map<Integer, Entity> _idEntityMap;
+
+//   private final Map<Entity,Collection<Integer>> _entityIdsMap;
+
+
+//    TODO refactor to use the following   - basically move UniqueEntityIdStore stuff here
+//   private final Map<TextSpan,Integer> _uniqueTextSpanIdMap;   -- instead of entity,integer map _entityIdMap
+//   private final SetMap<Integer,Integer> _uniqueIdTextSpanIdsMap;
+
+
+   public EntityIdCollection( final AnnotationStore annotationStore ) {
+      _entityIdMap = new HashMap<>();
+      _idEntityMap = new HashMap<>();
+
+      int id = 0;
+      for ( Entity entity : annotationStore.getNamedEntities() ) {
+         _entityIdMap.put( entity, id );
+         _idEntityMap.put( id, entity );
+         id++;
+      }
+      for ( Entity entity : annotationStore.getTimes() ) {
+         _entityIdMap.put( entity, id );
+         _idEntityMap.put( id, entity );
+         id++;
+      }
+      for ( Entity entity : annotationStore.getEvents() ) {
+         _entityIdMap.put( entity, id );
+         _idEntityMap.put( id, entity );
+         id++;
+      }
+      for ( CoreferenceChain chain : annotationStore.getCoreferenceChains() ) {
+         for ( Entity entity : chain ) {
+            _entityIdMap.put( entity, id );
+         }
+         _entityIdMap.put( chain, id );
+         _idEntityMap.put( id, chain );
+         id++;
+      }
+   }
+
+   public <T extends Entity> EntityIdCollection( final Iterable<T> allEntities ) {
+      _entityIdMap = new HashMap<>();
+      _idEntityMap = new HashMap<>();
+      int id = 0;
+      for ( Entity entity : allEntities ) {
+         if ( _entityIdMap.containsKey( entity ) ) {
+            // Already placed as a coreference link
+            continue;
+         }
+         _entityIdMap.put( entity, id );
+         _idEntityMap.put( id, entity );
+         if ( entity instanceof CoreferenceChain ) {
+            for ( Entity chainEntity : (CoreferenceChain)entity ) {
+               _entityIdMap.put( chainEntity, id );
+            }
+         }
+         id++;
+      }
+   }
+
+   /**
+    * @return a collection of unique ids for all unique entities
+    */
+   public Set<Integer> getEntityIds() {
+//      return Collections.unmodifiableSet( _idEntityMap.keySet() );
+      return Collections.unmodifiableSet( new HashSet<>( _entityIdMap.values() ) );
+   }
+
+//   /**
+//    * @param entity some entity, be it unique on its own or part of a coreference chain
+//    * @return an id for the entity
+//    */
+//   public Collection<Integer> getEntityIds( final Entity entity ) {
+//      final Collection<Integer> entityIds = _entityIdsMap.get( entity );
+//      if ( entityIds != null ) {
+//         return entityIds;
+//      }
+//      return Collections.emptySet();
+////      return getIdByEntityEqual( entity );
+//   }
+
+   /**
+    * @param entity some entity, be it unique on its own or part of a coreference chain
+    * @return an id for the entity
+    */
+   public int getEntityId( final Entity entity ) {
+      final Integer id = _entityIdMap.get( entity );
+      if ( id != null ) {
+         return id;
+      }
+      return getIdByEntityEqual( entity );
+   }
+
+
+   private int getIdByEntityEqual( final Entity entity ) {
+      for ( Entity referenceEntity : _entityIdMap.keySet() ) {
+         if ( referenceEntity.areValuesEqual( entity ) ) {
+            final int id = _entityIdMap.get( referenceEntity );
+            // Prevent future iteration searches
+            _entityIdMap.put( entity, id );
+            return id;
+         }
+      }
+      return getIdByTextSpan( entity.getTextSpan() );
+   }
+
+   private int getIdByTextSpan( final TextSpan textSpan ) {
+      for ( Map.Entry<Entity, Integer> referenceEntry : _entityIdMap.entrySet() ) {
+         if ( referenceEntry.getKey().getTextSpan().equals( textSpan ) ) {
+            return referenceEntry.getValue();
+         }
+         // TODO necessary?
+         if ( referenceEntry.getKey() instanceof CoreferenceChain ) {
+            for ( Entity coreference : (CoreferenceChain)referenceEntry.getKey() ) {
+               if ( coreference.getTextSpan().equals( textSpan ) ) {
+                  return referenceEntry.getValue();
+               }
+            }
+         }
+      }
+      return NO_ENTITY_ID;
+   }
+
+
+   /**
+    * @param entityId some id
+    * @return the NamedEntity, Event, Timex, or CoreferenceChain with the given referenceId
+    */
+   public Entity getEntity( final int entityId ) {
+      return _idEntityMap.get( entityId );
+   }
+
+   public Entity getEntity( final Entity entity ) {
+      final int id = getEntityId( entity );
+      if ( id != NO_ENTITY_ID ) {
+         return getEntity( id );
+      }
+      return null;
+   }
+
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/EntityIdStore.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/EntityIdStore.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/EntityIdStore.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/EntityIdStore.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,37 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+
+import java.util.Collection;
+
+/**
+ * @author SPF , chip-nlp
+ * @version %I%
+ * @since 12/1/2014
+ */
+public interface EntityIdStore {
+   /**
+    * @return a collection of unique ids for all unique entities
+    */
+   Collection<Integer> getAllUniqueEntityIds();
+
+   /**
+    * @param entity some entity, be it unique on its own or part of a coreference chain
+    * @return an id for the entity
+    */
+   int getUniqueEntityId( Entity entity );
+
+   Collection<Integer> getAllUniqueEntityIds( Integer uniqueEntityID );
+
+   /**
+    * @param uniqueEntityID some id
+    * @return the NamedEntity, Event, Timex, or CoreferenceChain with the given referenceId
+    */
+   Collection<Entity> getAllEntities( int uniqueEntityID );
+
+   Collection<Entity> getAllEntities( Entity entity );
+
+   Collection<Entity> getUniqueEntities( Collection<Integer> uniqueIds );
+
+   Collection<Entity> getUniqueEntities( Integer uniqueId );
+}

Added: ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/UniqueEntityIdStore.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/UniqueEntityIdStore.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/UniqueEntityIdStore.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/nlp/annotation/coreference/UniqueEntityIdStore.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,142 @@
+package org.chboston.cnlp.nlp.annotation.coreference;
+
+import org.chboston.cnlp.nlp.annotation.annotation.Annotation;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+import org.chboston.cnlp.nlp.annotation.textspan.TextSpan;
+import org.chboston.cnlp.nlp.util.HashSetMap;
+import org.chboston.cnlp.nlp.util.SetMap;
+
+import java.util.*;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 6/17/13
+ */
+final public class UniqueEntityIdStore implements EntityIdStore {
+
+   static public final int NO_ENTITY_ID = Integer.MIN_VALUE;
+
+   // Key = id number for each "unique" reference, value = primary entity text span
+   private final Map<Integer, Entity> _idEntityMap;
+
+   private final Map<TextSpan, Integer> _uniqueTextSpanIdMap;
+   private final SetMap<Integer, Integer> _uniqueIdTextSpanIdsMap;
+
+
+   public <T extends Entity> UniqueEntityIdStore( final Iterable<T> allEntities ) {
+      // Each Unique Text Span can be part of one or many entities,
+      // store collection of associated entity IDs for each text span
+      // Key = Entity (named, event, timex) text span, Value = id number for each "unique" reference.
+      // Co-referent and overlapping entities will have the same id number
+      final SetMap<TextSpan, Integer> textSpanEntityIdsMap = new HashSetMap<>();
+      // Each Entity has a unique ID
+      _idEntityMap = new HashMap<>();
+      int id = 0;
+      for ( T entity : allEntities ) {
+         textSpanEntityIdsMap.place( entity.getTextSpan(), id );
+         _idEntityMap.put( id, entity );
+         if ( entity instanceof CoreferenceChain ) {
+            for ( Annotation chainLink : (CoreferenceChain)entity ) {
+               textSpanEntityIdsMap.place( chainLink.getTextSpan(), id );
+            }
+         }
+         id++;
+      }
+      // Each Unique Text Span should have an id
+      _uniqueTextSpanIdMap = new HashMap<>( textSpanEntityIdsMap.size() );
+      // Skipping a reference step (uniqueID > TextSpan; TextSpan > EntityIds; EntityIds : Entities,
+      // each unique text span (by ID) has multiple entityIds
+      _uniqueIdTextSpanIdsMap = new HashSetMap<>();
+      int uniqueId = 0;
+      for ( TextSpan textSpan : textSpanEntityIdsMap.keySet() ) {
+         _uniqueTextSpanIdMap.put( textSpan, uniqueId );
+         _uniqueIdTextSpanIdsMap.put( uniqueId, textSpanEntityIdsMap.get( textSpan ) );
+         uniqueId++;
+      }
+   }
+
+   @Override
+   public Collection<Integer> getAllUniqueEntityIds() {
+      return Collections.unmodifiableCollection( _uniqueIdTextSpanIdsMap.keySet() );
+   }
+
+   @Override
+   public int getUniqueEntityId( final Entity entity ) {
+      final Integer uniqueId = _uniqueTextSpanIdMap.get( entity.getTextSpan() );
+      if ( uniqueId != null ) {
+         return uniqueId;
+      }
+      return NO_ENTITY_ID;
+   }
+
+
+   @Override
+   public Collection<Integer> getAllUniqueEntityIds( final Integer uniqueEntityID ) {
+      final Collection<Integer> allUniqueIds = new ArrayList<>();
+      final Collection<Entity> allEntities = getAllEntities( uniqueEntityID );
+      for ( Entity entity : allEntities ) {
+         allUniqueIds.add( getUniqueEntityId( entity ) );
+         if ( entity instanceof CoreferenceChain ) {
+            for ( Entity chainLink : (CoreferenceChain)entity ) {
+               allUniqueIds.add( getUniqueEntityId( chainLink ) );
+            }
+         }
+      }
+      return allUniqueIds;
+   }
+
+   @Override
+   public Collection<Entity> getAllEntities( final int uniqueEntityID ) {
+      final Collection<Integer> entityIds = _uniqueIdTextSpanIdsMap.get( uniqueEntityID );
+      if ( entityIds == null || entityIds.isEmpty() ) {
+         return Collections.emptyList();
+      }
+      final Collection<Entity> entities = new HashSet<>( entityIds.size() );
+      for ( Integer entityId : entityIds ) {
+         entities.add( _idEntityMap.get( entityId ) );
+      }
+      return entities;
+   }
+
+   @Override
+   public Collection<Entity> getAllEntities( final Entity entity ) {
+      final int uniqueId = getUniqueEntityId( entity );
+      if ( uniqueId != NO_ENTITY_ID ) {
+         return getAllEntities( uniqueId );
+      }
+      return null;
+   }
+
+
+   @Override
+   public Collection<Entity> getUniqueEntities( final Collection<Integer> uniqueIds ) {
+      final Collection<Entity> uniqueEntities = new HashSet<>();
+      for ( Integer uniqueId : uniqueIds ) {
+         final Collection<Entity> uniqueIdEntities = getUniqueEntities( uniqueId );
+         if ( !uniqueIdEntities.isEmpty() ) {
+            uniqueEntities.addAll( uniqueIdEntities );
+         }
+      }
+      return uniqueEntities;
+   }
+
+   @Override
+   public Collection<Entity> getUniqueEntities( final Integer uniqueId ) {
+      final Collection<Entity> idEntities = getAllEntities( uniqueId );
+      if ( idEntities == null || idEntities.isEmpty() ) {
+         return Collections.emptyList();
+      }
+      final Collection<Entity> uniqueEntities = new HashSet<>( idEntities );
+      for ( Entity entity : idEntities ) {
+         if ( entity instanceof CoreferenceChain ) {
+            for ( Entity chainLink : (CoreferenceChain)entity ) {
+               uniqueEntities.remove( chainLink );
+            }
+         }
+      }
+      return uniqueEntities;
+   }
+
+
+}



Mime
View raw message