diff --git a/CHANGELOG.md b/CHANGELOG.md index b6177729..dfef76d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,42 @@ Issue numbers (e.g., #43) refer to GitHub issues: https://github.com/nilsreiter/CorefAnnotator/issues +## 2.0.0 + +- New: Discontinuous annotations. A single mention can now + consist of multiple spans. Mention parts, that have been used for + relative clauses and such are gone. Add a new span to a mention by + dragging it onto the mention in the tree. #293, #104 +- New: Analysis functions. From the main window, files can + now be opened in the analyzer view, which offers + visualizations and some statistics for the annotations. #292 +- New: Annotation guidelines can now be linked via a profile. They + appear directly in the Help menu. #12 +- Files are now saved with a specific file extension to avoid confusion + and accidental decompression. The file extension is .ca2 for uncompressed, + git-friendly files and .ca2z for gzip compressed files. Compression + makes the files roughly ten times smaller. #335 +- Search is now case-insensitive by default #320 +- Various UI tweaks +- Main window now shows a section if a version is opened for the first time +- Updated Dependencies + - log4j: 2.12.1 -> 2.13.3 + - guava: 28.1-jre -> 30.1-jre + - reflections: 0.9.11 -> 0.9.12 + - mockito: 3.1.0 -> 3.4.4 + - dkpro: 1.9.0 -> 2.1.0 + - uima: 2.10.2 -> 3.1.1 + - eclipse collections: 9.2.0 -> 10.2.0 + - javafx: 13.0.1 -> 14.0.2.1 + - ikonli: 2.1.1 -> 11.5.0 + - poi: 4.1.1 -> 4.1.2 + + +## 1.15.2 + +- Command line tool ExportMultipleFiles no longer tries to descend into + sub directories #367 + ## 1.15.1 - Files without segments no longer show empty parentheses in tree view #311 diff --git a/README.md b/README.md index d68ee09e..195c6ce4 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,16 @@ This is an annotation tool for coreference. It's built on top of [Apache's UIMA] ## Features - Supports annotation of long texts with many discourse entities +- Mentions can be non-continuous - Intuitive drag and drop operations - Fully operable by keyboard for fast annotation - Annotation texts can be formatted - Search function to navigate in long texts - Localisable in other languages (currently: English and German) -- Import and export in a few file formats +- Import and export in a few file formats, including Excel for easy analysis - Automatically generated candidates - Search terms (including regular expressions) can be annotated en bloc - +- Visualization and some simple quantitative analysis of the annotations ## Requirements and Installation diff --git a/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Constants.java b/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Constants.java deleted file mode 100644 index b6fde32f..00000000 --- a/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Constants.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.unistuttgart.ims.coref.annotator.plugin.creta.adorno; - -public class Constants { - static final String mentionTypeName = "de.unistuttgart.ims.type.CoRefEntity"; - - static final String entityNameFeatureName = "coref"; -} diff --git a/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Exporter.java b/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Exporter.java deleted file mode 100644 index f03a12c4..00000000 --- a/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Exporter.java +++ /dev/null @@ -1,47 +0,0 @@ -package de.unistuttgart.ims.coref.annotator.plugin.creta.adorno; - -import java.util.Map; - -import org.apache.uima.analysis_engine.AnalysisEngineProcessException; -import org.apache.uima.cas.CAS; -import org.apache.uima.cas.Feature; -import org.apache.uima.cas.Type; -import org.apache.uima.cas.text.AnnotationFS; -import org.apache.uima.fit.component.JCasAnnotator_ImplBase; -import org.apache.uima.fit.util.JCasUtil; -import org.apache.uima.jcas.JCas; -import org.eclipse.collections.impl.factory.Maps; - -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; - -public class Exporter extends JCasAnnotator_ImplBase { - - @Override - public void process(JCas jcas) throws AnalysisEngineProcessException { - CAS cas; - cas = jcas.getCas(); - Type mentionType = jcas.getTypeSystem().getType(Constants.mentionTypeName); - Feature entityFeature = mentionType.getFeatureByBaseName(Constants.entityNameFeatureName); - - Map entityLabelMap = Maps.mutable.empty(); - - for (Mention m : JCasUtil.select(jcas, Mention.class)) { - AnnotationFS a = cas.createAnnotation(mentionType, m.getBegin(), m.getEnd()); - cas.addFsToIndexes(a); - if (!entityLabelMap.containsKey(m.getEntity())) { - String label = m.getEntity().getLabel(); - int lNum = 0; - while (entityLabelMap.values().contains(label) - || entityLabelMap.values().contains(label + "." + lNum)) { - // label collision - lNum++; - } - entityLabelMap.put(m.getEntity(), (lNum > 0 ? label + "." + lNum : label)); - } - a.setFeatureValueFromString(entityFeature, entityLabelMap.get(m.getEntity())); - } - - } - -} diff --git a/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Importer.java b/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Importer.java deleted file mode 100644 index 2dc6f047..00000000 --- a/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Importer.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.unistuttgart.ims.coref.annotator.plugin.creta.adorno; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.uima.analysis_engine.AnalysisEngineProcessException; -import org.apache.uima.cas.Feature; -import org.apache.uima.cas.Type; -import org.apache.uima.cas.text.AnnotationIndex; -import org.apache.uima.fit.component.JCasAnnotator_ImplBase; -import org.apache.uima.fit.factory.AnnotationFactory; -import org.apache.uima.jcas.JCas; -import org.apache.uima.jcas.tcas.Annotation; - -import de.unistuttgart.ims.coref.annotator.ColorProvider; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; - -public class Importer extends JCasAnnotator_ImplBase { - - ColorProvider colorMap = new ColorProvider(); - - @Override - public void process(JCas jcas) throws AnalysisEngineProcessException { - Map entityMap = new HashMap(); - - Type mentionType = jcas.getTypeSystem().getType(Constants.mentionTypeName); - Feature entityFeature = mentionType.getFeatureByBaseName(Constants.entityNameFeatureName); - - AnnotationIndex idx = jcas.getAnnotationIndex(mentionType); - for (Annotation a : idx) { - String entityString = a.getFeatureValueAsString(entityFeature); - Mention m = AnnotationFactory.createAnnotation(jcas, a.getBegin(), a.getEnd(), Mention.class); - if (!entityMap.containsKey(entityString)) { - Entity e = new Entity(jcas); - e.setLabel(entityString); - e.setColor(colorMap.getNextColor().getRGB()); - e.addToIndexes(); - entityMap.put(entityString, e); - } - m.setEntity(entityMap.get(entityString)); - } - } - -} diff --git a/pom.xml b/pom.xml index 51bc083d..4f0e6850 100644 --- a/pom.xml +++ b/pom.xml @@ -4,25 +4,25 @@ 4.0.0 de.unistuttgart.ims coref.annotator - 1.15.1 + 2.0.0 jar CorefAnnotator https://github.com/nilsreiter/CorefAnnotator/ UTF-8 - 1.9.0 - 2.1.1 - 9.2.0 + 2.2.0 + 12.2.0 + 10.2.0 1.8 1.8 - 13.0.2 + 14.0.2.1 org.apache.uima jcasgen-maven-plugin - 2.8.1 + 3.1.1 1 @@ -37,28 +37,9 @@ src/main/resources/types.xml src/main/resources/types-meta.xml src/main/resources/types-v1.xml + src/main/resources/types-v2.xml src/main/resources/types-format.xml - - - - - true - - - - 2 - - generate - - - - - - - src/main/resources/creta-coref.xml + src/main/resources/types-quadrama.xml + 3.1.1 3 @@ -433,63 +373,51 @@ commons-collections4 - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.api.coref-asl - + org.dkpro.core + dkpro-core-api-coref-asl - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.api.metadata-asl - + org.dkpro.core + dkpro-core-api-metadata-asl - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.api.segmentation-asl - + org.dkpro.core + dkpro-core-api-segmentation-asl - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.api.lexmorph-asl - + org.dkpro.core + dkpro-core-api-lexmorph-asl - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.api.syntax-asl - + org.dkpro.core + dkpro-core-api-syntax-asl - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.api.semantics-asl - + org.dkpro.core + dkpro-core-api-semantics-asl org.apache.logging.log4j log4j-core - 2.12.1 org.apache.logging.log4j log4j-api - 2.12.1 - com.google.guava guava - 28.2-jre - org.kordamp.ikonli ikonli-materialdesign-pack ${version.ikonli} + + org.kordamp.ikonli + ikonli-materialdesign2-pack + ${version.ikonli} + org.kordamp.ikonli ikonli-fontawesome-pack @@ -515,22 +443,16 @@ commons-math3 - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.io.xmi-asl - + org.dkpro.core + dkpro-core-io-xmi-asl - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.io.text-asl - + org.dkpro.core + dkpro-core-io-text-asl - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.io.conll-asl - + org.dkpro.core + dkpro-core-io-conll-asl org.eclipse.collections @@ -543,16 +465,12 @@ ${version.eclipse} - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.tokit-asl - + org.dkpro.core + dkpro-core-tokit-asl - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core.stanfordnlp-gpl - + org.dkpro.core + dkpro-core-stanfordnlp-gpl org.json @@ -562,12 +480,7 @@ de.unistuttgart.ims.uima.io generic-xml-reader - 1.6.1 - - - de.unistuttgart.ims - uimautil - 1.1.0 + 2.0.0 com.lexicalscope.jewelcli @@ -590,38 +503,44 @@ javafx-swing ${version.javafx} - - org.glassfish.jaxb - jaxb-runtime - 2.3.2 - org.apache.poi poi - 4.1.1 + 4.1.2 org.apache.poi poi-ooxml - 4.1.1 + 4.1.2 + + + org.knowm.xchart + xchart + 3.6.5 + + + org.apache.commons + commons-csv + 1.8 + + + org.slf4j + slf4j-nop + 1.7.30 - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core-asl - + org.dkpro.core + dkpro-core-asl ${version.dkpro} pom import - de.tudarmstadt.ukp.dkpro.core - - de.tudarmstadt.ukp.dkpro.core-gpl - + org.dkpro.core + dkpro-core-gpl ${version.dkpro} pom import diff --git a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/MapCorefToXmlElements.java b/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/MapCorefToXmlElements.java deleted file mode 100644 index 7bb72af7..00000000 --- a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/MapCorefToXmlElements.java +++ /dev/null @@ -1,134 +0,0 @@ -package de.unistuttgart.ims.coref.annotator.plugin.quadrama.tei; - -import java.util.Collection; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.uima.analysis_engine.AnalysisEngineProcessException; -import org.apache.uima.fit.component.JCasAnnotator_ImplBase; -import org.apache.uima.fit.factory.AnnotationFactory; -import org.apache.uima.fit.util.JCasUtil; -import org.apache.uima.jcas.JCas; -import org.eclipse.collections.api.map.MutableMap; -import org.eclipse.collections.api.set.MutableSet; -import org.eclipse.collections.impl.factory.Maps; -import org.eclipse.collections.impl.factory.Sets; - -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.drama.api.Speaker; -import de.unistuttgart.ims.uima.io.xml.type.XMLElement; - -public class MapCorefToXmlElements extends JCasAnnotator_ImplBase { - - /** - * Pattern to extract xml ids from a string representation of the xml attributes - */ - Pattern pattern = Pattern.compile("xml:id=\"([^\"]+)\""); - - /** - * This will be used to ensure that ids are unique within a document - */ - MutableSet ids = null; - - @Override - public void process(JCas jcas) throws AnalysisEngineProcessException { - ids = Sets.mutable.empty(); - ids.add("e"); - - // map from xml ids to elements - MutableMap idMap = Maps.mutable.empty(); - - // contains all covering XMLElement annotations for each mention - Map> coveringXMLElement = JCasUtil.indexCovering(jcas, Mention.class, - XMLElement.class); - - // contains covering Speaker annotations for each mention - Map> coveringSpeaker = JCasUtil.indexCovering(jcas, Mention.class, Speaker.class); - - // the -element - XMLElement textElement = null; - - for (XMLElement xmlElement : JCasUtil.select(jcas, XMLElement.class)) { - - // if the xmlElement has an xml:id attribute - Matcher m = pattern.matcher(xmlElement.getAttributes()); - if (m.find()) { - String id = m.group(1); - - // store mapping of ids to elements - idMap.put(id, xmlElement); - } - - // identify -element - // we assume it's unique - if (xmlElement.getTag().equalsIgnoreCase("text")) - textElement = xmlElement; - } - - // TODO: Handle who= elements - for (Mention m : JCasUtil.select(jcas, Mention.class)) { - - // we skip all mentions in the tei header - if (!coveringXMLElement.get(m).contains(textElement)) - continue; - - // we skip mentions that are covered by speaker annotations - if (coveringSpeaker.containsKey(m)) - continue; - - // get entity - Entity e = m.getEntity(); - - // create xml id - String xid = toXmlId(e); - - // create new element annotation - XMLElement newElement = AnnotationFactory.createAnnotation(jcas, m.getBegin(), m.getEnd(), - XMLElement.class); - newElement.setTag("rs"); - newElement.setAttributes(" ref=\"#" + xid + "\""); - } - } - - /** - * This method takes an entity object and creates a valid XML id from the - * entity's label - * - * @param entity The entity - * @return A string containing a valid XML id - */ - String toXmlId(Entity entity) { - String id = null; - - if (entity.getXmlId() != null) { - id = entity.getXmlId(); - ids.add(id); - return id; - } else { - - String baseId; - if (entity.getLabel() != null) { - baseId = entity.getLabel().toLowerCase().replaceAll("[^a-z]", "_"); - } else { - baseId = "e"; - } - if (ids.contains(baseId)) { - int counter = (baseId == "e" ? 0 : 1); - do { - counter++; - id = baseId + String.valueOf(counter); - } while (ids.contains(id)); - ids.add(id); - entity.setXmlId(id); - return id; - } else { - ids.add(baseId); - entity.setXmlId(baseId); - return baseId; - } - } - } - -} diff --git a/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/MapCorefToXmlElements.java b/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/MapCorefToXmlElements.java index 4cb830ab..d5a91062 100644 --- a/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/MapCorefToXmlElements.java +++ b/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/MapCorefToXmlElements.java @@ -1,8 +1,10 @@ package de.unistuttgart.ims.coref.annotator.plugin.b06.b03; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; import org.apache.uima.analysis_engine.AnalysisEngineProcessException; import org.apache.uima.fit.component.JCasAnnotator_ImplBase; import org.apache.uima.fit.factory.AnnotationFactory; @@ -10,11 +12,13 @@ import org.apache.uima.jcas.JCas; import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.api.set.MutableSet; +import org.eclipse.collections.impl.factory.Lists; import org.eclipse.collections.impl.factory.Maps; import org.eclipse.collections.impl.factory.Sets; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.uima.io.xml.type.XMLElement; public class MapCorefToXmlElements extends JCasAnnotator_ImplBase { @@ -44,10 +48,31 @@ public void process(JCas jcas) throws AnalysisEngineProcessException { for (Mention m : JCasUtil.select(jcas, Mention.class)) { Entity e = m.getEntity(); String xid = toXmlId(e); - XMLElement newElement = AnnotationFactory.createAnnotation(jcas, m.getBegin(), m.getEnd(), - XMLElement.class); - newElement.setTag(RS); - newElement.setAttributes(" ref=\"#" + xid + "\""); + + boolean first = true; + String mentionId = UUID.randomUUID().toString(); + for (MentionSurface ms : m.getSurface()) { + XMLElement newElement = AnnotationFactory.createAnnotation(jcas, ms.getBegin(), ms.getEnd(), + XMLElement.class); + newElement.setTag("rs"); + + StringBuilder b = new StringBuilder(); + b.append(' ').append("ref=\"#").append(xid).append('"'); + if (first) { + if (m.getSurface().size() > 1) + b.append(" id=\"").append(mentionId).append('"'); + if (m.getFlags() != null && !m.getFlags().isEmpty()) + b.append(" ana=\"") + .append(StringUtils + .join(Lists.immutable.withAll(m.getFlags()).collect(f -> f.getUuid()), ",")) + .append('"'); + first = false; + } else { + b.append(' ').append("prev=\"").append(mentionId).append("\""); + } + newElement.setAttributes(b.toString()); + } + } } diff --git a/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/TeiReader.java b/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/TeiReader.java index e9d5fba7..442b31e5 100644 --- a/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/TeiReader.java +++ b/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/TeiReader.java @@ -9,28 +9,30 @@ import org.apache.uima.fit.factory.AnnotationFactory; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.FSArray; +import org.dkpro.core.api.io.ResourceCollectionReaderBase; +import org.dkpro.core.api.resources.CompressionUtils; import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.impl.factory.Maps; import org.eclipse.collections.impl.factory.Sets; -import de.tudarmstadt.ukp.dkpro.core.api.io.ResourceCollectionReaderBase; import de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData; -import de.tudarmstadt.ukp.dkpro.core.api.resources.CompressionUtils; import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.ColorProvider; import de.unistuttgart.ims.coref.annotator.TypeSystemVersion; -import de.unistuttgart.ims.coref.annotator.Util; import de.unistuttgart.ims.coref.annotator.api.format.Bold; import de.unistuttgart.ims.coref.annotator.api.format.Head; import de.unistuttgart.ims.coref.annotator.api.format.Italic; import de.unistuttgart.ims.coref.annotator.api.format.WideSpacing; import de.unistuttgart.ims.coref.annotator.api.sfb1391.LineBreak; import de.unistuttgart.ims.coref.annotator.api.sfb1391.Milestone; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Line; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Line; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; import de.unistuttgart.ims.coref.annotator.plugin.tei.TeiStylePlugin; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; import de.unistuttgart.ims.uima.io.xml.GenericXmlReader; import de.unistuttgart.ims.uima.io.xml.type.XMLElement; @@ -60,6 +62,7 @@ public void getNext(CAS aCAS) { } MutableMap entityMap = Maps.mutable.empty(); + MutableMap mentionMap = Maps.mutable.empty(); GenericXmlReader gxr = new GenericXmlReader(DocumentMetaData.class); gxr.setTextRootSelector(null); @@ -70,16 +73,40 @@ public void getNext(CAS aCAS) { gxr.addGlobalRule("langUsage[usage=100]", (d, e) -> jcas.setDocumentLanguage(e.attr("ident"))); - gxr.addRule("[ref]", Mention.class, (m, e) -> { - String id = e.attr("ref").substring(1); - Entity entity = entityMap.get(id); + gxr.addRule("[ref]", MentionSurface.class, (ms, e) -> { + // retrieve mention id + String mentionId = null; + if (e.hasAttr("prev")) + mentionId = e.attr("prev"); + else if (e.hasAttr("id")) + mentionId = e.attr("id"); + + // create or retrieve mention + Mention m = null; + if (mentionId != null) + m = mentionMap.get(mentionId); + if (m == null) { + m = new Mention(jcas); + m.addToIndexes(); + m.setSurface(new FSArray(jcas, 0)); + mentionMap.put(mentionId, m); + } + ms.setMention(m); + m.setSurface(UimaUtil.addTo(jcas, m.getSurface(), ms)); + + // retrieve entity id + String entityId = e.attr("ref").substring(1); + + // create or retrieve entity + Entity entity = entityMap.get(entityId); if (entity == null) { entity = new Entity(jcas); entity.addToIndexes(); entity.setColor(colorProvider.getNextColor().getRGB()); - entity.setLabel(m.getCoveredText()); - entity.setXmlId(id); - entityMap.put(id, entity); + // TODO: read old label from XML + entity.setLabel(UimaUtil.getCoveredText(m)); + entity.setXmlId(entityId); + entityMap.put(entityId, entity); } m.setEntity(entity); }); @@ -91,7 +118,8 @@ public void getNext(CAS aCAS) { gxr.addRule("[rend*=wide-spacing]", WideSpacing.class); gxr.addRule("lb", LineBreak.class, (lineBreak, element) -> lineBreak.setN(element.attr("n"))); gxr.addRule("milestone", Milestone.class, (ms, element) -> { - ms.setN(element.attr(N)); + if (element.hasAttr(N)) + ms.setN(element.attr(N)); ms.setMilestoneType(element.attr(TYPE)); }); gxr.addRule("teiCorpus > TEI", Segment.class, (segment, element) -> { @@ -112,8 +140,8 @@ public void getNext(CAS aCAS) { else DocumentMetaData.create(jcas).setDocumentId(documentId); - Util.getMeta(jcas).setStylePlugin(TeiStylePlugin.class.getName()); - Util.getMeta(jcas).setTypeSystemVersion(TypeSystemVersion.getCurrent().toString()); + UimaUtil.getMeta(jcas).setStylePlugin(TeiStylePlugin.class.getName()); + UimaUtil.getMeta(jcas).setTypeSystemVersion(TypeSystemVersion.getCurrent().toString()); for (XMLElement element : Sets.immutable.withAll(JCasUtil.select(jcas, XMLElement.class))) { if (element.getTag().equalsIgnoreCase(RS)) diff --git a/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/TeiWriter.java b/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/TeiWriter.java index 0ecd513b..5d8379eb 100644 --- a/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/TeiWriter.java +++ b/sfb1391/main/java/de/unistuttgart/ims/coref/annotator/plugin/b06/b03/TeiWriter.java @@ -9,8 +9,8 @@ import org.apache.uima.analysis_engine.AnalysisEngineProcessException; import org.apache.uima.fit.descriptor.ConfigurationParameter; import org.apache.uima.jcas.JCas; +import org.dkpro.core.api.io.JCasFileWriter_ImplBase; -import de.tudarmstadt.ukp.dkpro.core.api.io.JCasFileWriter_ImplBase; import de.unistuttgart.ims.uima.io.xml.GenericXmlWriter; public class TeiWriter extends JCasFileWriter_ImplBase { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/AbstractTextWindow.java b/src/main/java/de/unistuttgart/ims/coref/annotator/AbstractTextWindow.java index 899499a9..848ddbea 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/AbstractTextWindow.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/AbstractTextWindow.java @@ -1,10 +1,12 @@ package de.unistuttgart.ims.coref.annotator; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.Point; import java.awt.Rectangle; +import java.awt.event.KeyEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.Enumeration; @@ -14,6 +16,7 @@ import java.util.prefs.PreferenceChangeEvent; import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JMenu; @@ -23,6 +26,7 @@ import javax.swing.JTextPane; import javax.swing.JTree; import javax.swing.JViewport; +import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -36,8 +40,8 @@ import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; -import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.text.AnnotationTreeNode; import org.apache.uima.jcas.JCas; @@ -50,16 +54,18 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; import org.kordamp.ikonli.swing.FontIcon; +import de.unistuttgart.ims.coref.annotator.action.SelectNextMentionAction; +import de.unistuttgart.ims.coref.annotator.action.SelectPreviousMentionAction; import de.unistuttgart.ims.coref.annotator.action.ViewFontFamilySelectAction; import de.unistuttgart.ims.coref.annotator.action.ViewFontSizeDecreaseAction; import de.unistuttgart.ims.coref.annotator.action.ViewFontSizeIncreaseAction; import de.unistuttgart.ims.coref.annotator.action.ViewSetLineNumberStyle; import de.unistuttgart.ims.coref.annotator.action.ViewSetLineSpacingAction; import de.unistuttgart.ims.coref.annotator.action.ViewStyleSelectAction; -import de.unistuttgart.ims.coref.annotator.api.v1.CommentAnchor; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.CommentAnchor; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; import de.unistuttgart.ims.coref.annotator.comp.FixedTextLineNumber; import de.unistuttgart.ims.coref.annotator.comp.TextLineNumber; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModel; @@ -117,11 +123,11 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean setText(StringUtils.abbreviate(atn.get().getLabel(), 20)); } if (leaf) - setIcon(FontIcon.of(MaterialDesign.MDI_MINUS)); + setIcon(FontIcon.of(MaterialDesign.MDI_MINUS, Constants.UI_ICON_SIZE_IN_TREE)); else if (expanded) - setIcon(FontIcon.of(FontAwesome.FOLDER_OPEN_O)); + setIcon(FontIcon.of(FontAwesome.FOLDER_OPEN_O, Constants.UI_ICON_SIZE_IN_TREE)); else - setIcon(FontIcon.of(FontAwesome.FOLDER_O)); + setIcon(FontIcon.of(FontAwesome.FOLDER_O, Constants.UI_ICON_SIZE_IN_TREE)); return this; } @@ -174,6 +180,17 @@ public JCas getJCas() { return getDocumentModel().getJcas(); } + public void annotationSelected(Annotation m) { + if (m != null) { + textPane.setSelectionStart(m.getBegin()); + textPane.setSelectionEnd(m.getEnd()); + // textPane.setCaretPosition(m.getEnd()); + textPane.getCaret().setSelectionVisible(true); + } else { + textPane.getCaret().setSelectionVisible(false); + } + } + @Override public void entityEvent(FeatureStructureEvent event) { Event.Type eventType = event.getType(); @@ -206,8 +223,11 @@ protected void entityEventAdd(FeatureStructureEvent event) { Iterator iter = event.iterator(1); while (iter.hasNext()) { FeatureStructure fs = iter.next(); - if (fs instanceof Mention || fs instanceof DetachedMentionPart) { - highlightManager.underline((Annotation) fs); + if (fs instanceof MentionSurface) { + highlightManager.underline((Annotation) fs, + new Color(((Mention) event.getArgument(0)).getEntity().getColor())); + } else if (fs instanceof Mention) { + highlightManager.underline((Mention) fs); } else if (fs instanceof CommentAnchor) { highlightManager.highlight((Annotation) fs); } @@ -219,9 +239,8 @@ protected void entityEventRemove(FeatureStructureEvent event) { while (iter.hasNext()) { FeatureStructure fs = iter.next(); if (fs instanceof Mention) { - if (((Mention) fs).getDiscontinuous() != null) - highlightManager.unUnderline(((Mention) fs).getDiscontinuous()); - highlightManager.unUnderline((Annotation) fs); + + highlightManager.unUnderline((Mention) fs); } else if (fs instanceof Annotation) highlightManager.unUnderline((Annotation) fs); @@ -231,10 +250,13 @@ protected void entityEventRemove(FeatureStructureEvent event) { protected void entityEventUpdate(FeatureStructureEvent event) { for (FeatureStructure fs : event) { if (fs instanceof Mention) { - if (Util.isX(((Mention) fs).getEntity(), Constants.ENTITY_FLAG_HIDDEN)) - highlightManager.unUnderline((Annotation) fs); - else - highlightManager.underline((Annotation) fs); + Mention m = (Mention) fs; + if (((Mention) fs).getEntity().getHidden()) + highlightManager.unUnderline(m); + else { + highlightManager.unUnderline(m); + highlightManager.underline(m); + } } } } @@ -242,10 +264,8 @@ protected void entityEventUpdate(FeatureStructureEvent event) { protected void entityEventMove(FeatureStructureEvent event) { for (FeatureStructure fs : event) { if (fs instanceof Mention) { - if (Util.isX(((Mention) fs).getEntity(), Constants.ENTITY_FLAG_HIDDEN)) + if (((Mention) fs).getEntity().getHidden()) highlightManager.unUnderline((Annotation) fs); - else - highlightManager.underline((Annotation) fs); } } } @@ -262,26 +282,21 @@ protected void entityEventInit(FeatureStructureEvent event) { CoreferenceModel cm = (CoreferenceModel) event.getSource(); for (Mention m : cm.getMentions()) { highlightManager.underline(m); - if (m.getDiscontinuous() != null) - highlightManager.underline(m.getDiscontinuous()); } } public MutableSet getSelectedAnnotations(Class clazz) { - try { - MutableSet annotations = getTouchedAnnotations(clazz) - .select(a -> a.getBegin() == getTextPane().getSelectionStart() - && a.getEnd() == getTextPane().getSelectionEnd()); - return annotations.selectInstancesOf(clazz); - } catch (NullPointerException e) { - return Sets.mutable.empty(); - } + MutableSet annotations = getDocumentModel().getCoreferenceModel() + .getMentions(getTextPane().getSelectionStart()) + .select(a -> UimaUtil.getBegin(a) == getTextPane().getSelectionStart() + && UimaUtil.getEnd(a) == getTextPane().getSelectionEnd()); + return annotations.selectInstancesOf(clazz); } public MutableSet getTouchedAnnotations(Class clazz) { try { MutableSet annotations = getDocumentModel().getCoreferenceModel() - .getMentions(getTextPane().getSelectionStart()); + .getMentionSurfaces(getTextPane().getSelectionStart()); return annotations.selectInstancesOf(clazz); } catch (NullPointerException e) { return Sets.mutable.empty(); @@ -292,6 +307,7 @@ public JTextPane getTextPane() { return textPane; } + @Override public DocumentModel getDocumentModel() { if (documentModels == null || documentModels.isEmpty()) return null; @@ -309,12 +325,21 @@ public void setLineNumberStyle(LineNumberStyle lns) { case FIXED: tln = new FixedTextLineNumber(this, 5); pcs.addPropertyChangeListener(tln); + lineNumberStyleFixed.putValue(Action.SELECTED_KEY, true); + lineNumberStyleDynamic.putValue(Action.SELECTED_KEY, false); + lineNumberStyleNone.putValue(Action.SELECTED_KEY, false); break; case DYNAMIC: tln = new TextLineNumber(this, 5); pcs.addPropertyChangeListener(tln); + lineNumberStyleFixed.putValue(Action.SELECTED_KEY, false); + lineNumberStyleDynamic.putValue(Action.SELECTED_KEY, true); + lineNumberStyleNone.putValue(Action.SELECTED_KEY, false); break; default: + lineNumberStyleDynamic.putValue(Action.SELECTED_KEY, false); + lineNumberStyleFixed.putValue(Action.SELECTED_KEY, false); + lineNumberStyleNone.putValue(Action.SELECTED_KEY, true); tln = null; } textScrollPane.setRowHeaderView(tln); @@ -430,7 +455,7 @@ public void run() { styles.get(style)); getProgressBar().setValue(getProgressBar().getValue() + 10); } - Util.getMeta(getDocumentModel().getJcas()).setStylePlugin(sv.getClass().getName()); + UimaUtil.getMeta(getDocumentModel().getJcas()).setStylePlugin(sv.getClass().getName()); currentStyle = sv; styleMenuItem.get(sv).setSelected(true); getMiscLabel().setText(Annotator.getString(Strings.STATUS_STYLE) + ": " + sv.getName()); @@ -500,6 +525,15 @@ protected void initializeWindow() { textPane = new JTextPane(); textPane.setDragEnabled(true); textPane.setEditable(false); + textPane.getActionMap().put(SelectNextMentionAction.class, new SelectNextMentionAction(this)); + textPane.getActionMap().put(SelectPreviousMentionAction.class, new SelectPreviousMentionAction(this)); + textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_DOWN_MASK), + SelectNextMentionAction.class); + textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.ALT_DOWN_MASK), + SelectPreviousMentionAction.class); + + getMiscLabel().setText("Style: " + Annotator.app.getPluginManager().getDefaultStylePlugin().getName()); + getMiscLabel().setToolTipText(Annotator.app.getPluginManager().getDefaultStylePlugin().getDescription()); textScrollPane = new JScrollPane(textPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); @@ -540,6 +574,9 @@ public void preferenceChange(PreferenceChangeEvent evt) { textPanel.revalidate(); textPanel.repaint(); } + } else if (evt.getKey().equalsIgnoreCase(Constants.CFG_UNDERLINE_SINGLETONS_IN_GRAY)) { + highlightManager.clearAllAnnotations(); + entityEventInit(Event.get(getDocumentModel().getCoreferenceModel(), Event.Type.Init)); } else { super.preferenceChange(evt); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/AbstractWindow.java b/src/main/java/de/unistuttgart/ims/coref/annotator/AbstractWindow.java index ba1d3b8e..9a9cb824 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/AbstractWindow.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/AbstractWindow.java @@ -16,6 +16,7 @@ import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; +import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.SpringLayout; @@ -24,10 +25,11 @@ import org.eclipse.collections.impl.factory.Lists; import de.unistuttgart.ims.coref.annotator.UpdateCheck.Version; +import de.unistuttgart.ims.coref.annotator.action.HelpAction; import de.unistuttgart.ims.coref.annotator.action.SetAnnotatorNameAction; import de.unistuttgart.ims.coref.annotator.action.TogglePreferenceAction; -public abstract class AbstractWindow extends JFrame implements PreferenceChangeListener { +public abstract class AbstractWindow extends JFrame implements PreferenceChangeListener, HasDocumentModel { private static final long serialVersionUID = 1L; JPanel statusBar = new JPanel(); @@ -37,8 +39,8 @@ public abstract class AbstractWindow extends JFrame implements PreferenceChangeL JLabel miscLabel2 = new JLabel(); JPanel entityPanel = new JPanel(); Thread messageVoider; - JMenuBar menuBar = new JMenuBar(); - + protected JMenuBar menuBar = new JMenuBar(); + JMenu menu_help = new JMenu(Annotator.getString(Strings.MENU_HELP)); JMenu menu_settings = null; public AbstractWindow() { @@ -46,6 +48,8 @@ public AbstractWindow() { } protected void initializeWindow() { + menu_help.add(new HelpAction()); + SpringLayout springs = new SpringLayout(); statusBar = new JPanel(); statusBar.setPreferredSize(new Dimension(800, 20)); @@ -76,6 +80,12 @@ protected void initializeWindow() { versionLabel.setPreferredSize(new Dimension(220, 20)); statusBar.add(versionLabel); + // activate for debug + // miscLabel.setBorder(BorderFactory.createLineBorder(Color.cyan)); + // miscLabel2.setBorder(BorderFactory.createLineBorder(Color.cyan)); + miscLabel.setPreferredSize(new Dimension(150, 20)); + miscLabel2.setPreferredSize(new Dimension(150, 20)); + // from east springs.putConstraint(SpringLayout.EAST, versionLabel, 10, SpringLayout.EAST, statusBar); springs.putConstraint(SpringLayout.EAST, miscLabel, 10, SpringLayout.WEST, versionLabel); @@ -178,36 +188,51 @@ public JLabel getMiscLabel() { } public JMenu initialiseMenuSettings() { + JMenuItem mi; + menu_settings = new JMenu(Annotator.getString(Strings.MENU_SETTINGS)); + mi = menu_settings.add(Annotator.getString(Strings.MENU_SETTINGS_CATEGORY_ANNOTATION_BEHAVIOUR)); + mi.setEnabled(false); + menu_settings.add(new JCheckBoxMenuItem( TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_TRIM_WHITESPACE))); menu_settings.add(new JCheckBoxMenuItem( - TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_SHOW_TEXT_LABELS))); - menu_settings.add(new JCheckBoxMenuItem( - TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_SHOW_LINE_NUMBER_IN_TREE))); + TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_REPLACE_MENTION))); menu_settings.add( new JCheckBoxMenuItem(TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_FULL_TOKENS))); - menu_settings.add(new JCheckBoxMenuItem( - TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_KEEP_TREE_SORTED))); menu_settings.add(new JCheckBoxMenuItem( TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_DELETE_EMPTY_ENTITIES))); - menu_settings.add(new SetAnnotatorNameAction(Annotator.app)); + menu_settings.add( + new JCheckBoxMenuItem(TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_STICKY_FLAGS))); + + menu_settings.addSeparator(); + mi = menu_settings.add(Annotator.getString(Strings.MENU_SETTINGS_CATEGORY_USER_INTERFACE)); + mi.setEnabled(false); menu_settings.add(new JCheckBoxMenuItem( - TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_ASK_BEFORE_FILE_OVERWRITE))); + TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_SHOW_TEXT_LABELS))); menu_settings.add(new JCheckBoxMenuItem( - TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_IGNORE_SINGLETONS_WHEN_COMPARING))); + TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_SHOW_LINE_NUMBER_IN_TREE))); menu_settings.add(new JCheckBoxMenuItem( - TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_REPLACE_MENTION))); + TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_KEEP_TREE_SORTED))); menu_settings.add(new JCheckBoxMenuItem( TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_UNDERLINE_SINGLETONS_IN_GRAY))); - menu_settings.add( - new JCheckBoxMenuItem(TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_SHOW_TOC))); + + menu_settings.addSeparator(); + mi = menu_settings.add(Annotator.getString(Strings.MENU_SETTINGS_CATEGORY_COMPARE_VIEW)); + mi.setEnabled(false); menu_settings.add(new JCheckBoxMenuItem( - TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_CREATE_DEFAULT_FLAGS))); + TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_IGNORE_SINGLETONS_WHEN_COMPARING))); menu_settings.add(new JCheckBoxMenuItem( TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_COMPARE_BY_ENTITY_NAME))); + + menu_settings.addSeparator(); + mi = menu_settings.add(Annotator.getString(Strings.MENU_SETTINGS_CATEGORY_MISC)); + mi.setEnabled(false); menu_settings.add( - new JCheckBoxMenuItem(TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_STICKY_FLAGS))); + new JCheckBoxMenuItem(TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_SHOW_TOC))); + menu_settings.add(new SetAnnotatorNameAction(Annotator.app)); + menu_settings.add(new JCheckBoxMenuItem( + TogglePreferenceAction.getAction(Annotator.app, Constants.SETTING_ASK_BEFORE_FILE_OVERWRITE))); return menu_settings; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/Annotator.java b/src/main/java/de/unistuttgart/ims/coref/annotator/Annotator.java index 59441b27..1b5949c6 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/Annotator.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/Annotator.java @@ -15,20 +15,21 @@ import java.util.Set; import java.util.function.Consumer; import java.util.prefs.BackingStoreException; +import java.util.prefs.PreferenceChangeEvent; +import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; import javax.swing.JButton; -import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.SpringLayout; import javax.swing.SwingUtilities; import javax.swing.UIManager; @@ -37,6 +38,7 @@ import org.apache.uima.fit.factory.TypeSystemDescriptionFactory; import org.apache.uima.resource.ResourceInitializationException; import org.apache.uima.resource.metadata.TypeSystemDescription; +import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.factory.Lists; import org.eclipse.collections.impl.factory.Sets; @@ -50,6 +52,7 @@ import de.unistuttgart.ims.coref.annotator.action.FileCompareOpenAction; import de.unistuttgart.ims.coref.annotator.action.FileImportAction; import de.unistuttgart.ims.coref.annotator.action.FileMergeOpenAction; +import de.unistuttgart.ims.coref.annotator.action.FileSelectAnalyzeAction; import de.unistuttgart.ims.coref.annotator.action.FileSelectOpenAction; import de.unistuttgart.ims.coref.annotator.action.HelpAction; import de.unistuttgart.ims.coref.annotator.action.SelectedFileOpenAction; @@ -60,7 +63,7 @@ import javafx.application.Platform; import javafx.embed.swing.JFXPanel; -public class Annotator { +public class Annotator implements PreferenceChangeListener { public static final Logger logger = LogManager.getLogger(Annotator.class); @@ -68,13 +71,11 @@ public class Annotator { Set openFiles = Sets.mutable.empty(); - MutableList recentFiles; - TypeSystemDescription typeSystemDescription; PluginManager pluginManager = new PluginManager(); - protected JFrame opening; + JFrame opening; JPanel statusBar; JPanel recentFilesPanel; @@ -91,6 +92,9 @@ public class Annotator { static Boolean javafx = null; public static void main(String[] args) { +// Annotator.logger.error("error"); +// Annotator.logger.warn("warn"); +// Annotator.logger.info("info"); SwingUtilities.invokeLater(new Runnable() { @Override @@ -114,11 +118,11 @@ public void run() { @SuppressWarnings("unused") public Annotator() throws ResourceInitializationException { - logger.trace("Application startup. Version " + Version.get().toString()); + logger.info("Application startup. Version " + Version.get().toString()); if (Annotator.javafx()) new JFXPanel(); this.pluginManager.init(); - this.recentFiles = loadRecentFiles(); + this.preferences.addPreferenceChangeListener(this); try { if (!preferences.nodeExists(Constants.CFG_ANNOTATOR_ID)) @@ -127,6 +131,9 @@ public Annotator() throws ResourceInitializationException { else preferences.put(Constants.CFG_ANNOTATOR_ID, Defaults.CFG_ANNOTATOR_ID); + for (String key : preferences.keys()) { + Annotator.logger.info("Preference {} set to {}", key, preferences.get(key, null)); + } } catch (BackingStoreException e) { Annotator.logger.catching(e); } @@ -164,12 +171,16 @@ public void windowClosing(WindowEvent e) { handleQuitRequestWith(); } }); + opening.setContentPane(new JPanel()); + opening.getContentPane().setLayout(new BorderLayout()); JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + mainPanel.setPreferredSize(new Dimension(width, 700)); + SpringLayout mainPanelLayout = new SpringLayout(); + mainPanel.setLayout(mainPanelLayout); JPanel panel = new JPanel(); - panel.setBorder(BorderFactory.createTitledBorder(Annotator.getString("dialog.splash.default"))); + panel.setBorder(BorderFactory.createTitledBorder(Annotator.getString(Strings.DIALOG_SPLASH_DEFAULT))); panel.setPreferredSize(new Dimension(width, 130)); panel.add(new JButton(openAction)); panel.add(new JButton(quitAction)); @@ -177,18 +188,23 @@ public void windowClosing(WindowEvent e) { panel.add(new JButton(new ShowLogWindowAction(this))); panel.add(new JButton(openCompareAction)); panel.add(new JButton(new FileMergeOpenAction())); + panel.add(new JButton(new FileSelectAnalyzeAction())); mainPanel.add(panel); + mainPanelLayout.putConstraint(SpringLayout.NORTH, panel, 5, SpringLayout.NORTH, mainPanel); + mainPanelLayout.putConstraint(SpringLayout.WEST, panel, 5, SpringLayout.WEST, mainPanel); + mainPanelLayout.putConstraint(SpringLayout.EAST, panel, -5, SpringLayout.EAST, mainPanel); - mainPanel.add(Box.createVerticalStrut(10)); recentFilesPanel = new JPanel(); - recentFilesPanel.setBorder(BorderFactory.createTitledBorder(Annotator.getString("dialog.splash.recent"))); + recentFilesPanel.setBorder(BorderFactory.createTitledBorder(Annotator.getString(Strings.DIALOG_SPLASH_RECENT))); recentFilesPanel.setPreferredSize(new Dimension(width, 200)); - refreshRecents(); + preferenceChange(new PreferenceChangeEvent(preferences, Constants.PREF_RECENT, null)); mainPanel.add(recentFilesPanel); - mainPanel.add(Box.createVerticalStrut(10)); + mainPanelLayout.putConstraint(SpringLayout.NORTH, recentFilesPanel, 15, SpringLayout.SOUTH, panel); + mainPanelLayout.putConstraint(SpringLayout.WEST, recentFilesPanel, 5, SpringLayout.WEST, mainPanel); + mainPanelLayout.putConstraint(SpringLayout.EAST, recentFilesPanel, -5, SpringLayout.EAST, mainPanel); panel = new JPanel(); - panel.setBorder(BorderFactory.createTitledBorder(Annotator.getString("dialog.splash.import"))); + panel.setBorder(BorderFactory.createTitledBorder(Annotator.getString(Strings.DIALOG_SPLASH_IMPORT))); panel.setPreferredSize(new Dimension(width, 200)); pluginManager.getIOPluginObjects().selectInstancesOf(ImportPlugin.class).forEachWith((p, pan) -> { AbstractAction importAction = new FileImportAction(this, p); @@ -196,9 +212,33 @@ public void windowClosing(WindowEvent e) { }, panel); mainPanel.add(panel); + mainPanelLayout.putConstraint(SpringLayout.NORTH, panel, 15, SpringLayout.SOUTH, recentFilesPanel); + mainPanelLayout.putConstraint(SpringLayout.WEST, panel, 5, SpringLayout.WEST, mainPanel); + mainPanelLayout.putConstraint(SpringLayout.EAST, panel, -5, SpringLayout.EAST, mainPanel); + + if (isFirstLaunch()) { + JPanel lastPanel = panel; + panel = new JPanel(); + panel.setBorder(BorderFactory.createTitledBorder(Annotator.getString(Strings.DIALOG_SPLASH_FIRSTTIME))); + panel.setPreferredSize(new Dimension(width, 200)); + JLabel label = new JLabel(); + label.setIcon(FontIcon.of(MaterialDesign.MDI_INFORMATION_OUTLINE, 24)); + label.setText(Annotator.getString(Strings.DIALOG_SPLASH_FIRSTTIME_TEXT, Version.get())); + panel.add(label); + HelpAction ha = new HelpAction(HelpWindow.Topic.WHATSNEW); + ha.putValue(Action.NAME, Annotator.getString(Strings.DIALOG_SPLASH_FIRSTTIME_BUTTON)); + ha.putValue(Action.LARGE_ICON_KEY, null); + ha.putValue(Action.SMALL_ICON, null); + panel.add(new JButton(ha)); + mainPanel.add(panel); + + mainPanelLayout.putConstraint(SpringLayout.NORTH, panel, 15, SpringLayout.SOUTH, lastPanel); + mainPanelLayout.putConstraint(SpringLayout.WEST, panel, 5, SpringLayout.WEST, mainPanel); + mainPanelLayout.putConstraint(SpringLayout.EAST, panel, -5, SpringLayout.EAST, mainPanel); + } + mainPanelLayout.putConstraint(SpringLayout.SOUTH, panel, -5, SpringLayout.SOUTH, mainPanel); - for (Component c : mainPanel.getComponents()) - ((JComponent) c).setAlignmentX(Component.CENTER_ALIGNMENT); + mainPanel.validate(); JLabel versionLabel = new JLabel(Version.get().toString()); @@ -255,7 +295,7 @@ public synchronized DocumentWindow open(final File file, ImportPlugin flavor, St public void run() { openFiles.add(v); if (flavor instanceof DefaultImportPlugin) - recentFiles.add(0, file); + addRecentFile(file); v.initialise(); } @@ -270,7 +310,7 @@ public void run() { public void run() { openFiles.add(v); if (flavor instanceof DefaultImportPlugin) - recentFiles.add(0, file); + addRecentFile(file); v.initialise(); } @@ -291,12 +331,14 @@ public void close(DocumentWindow viewer) { public void handleQuitRequestWith() { for (DocumentWindow v : openFiles) this.close(v); - storeRecentFiles(); + preferences.put(Constants.PREF_LAST_VERSION, Version.get().toString()); + try { preferences.sync(); } catch (BackingStoreException e1) { logger.catching(e1); } + Annotator.logger.info("Shutting down."); System.exit(0); } @@ -368,7 +410,7 @@ public void run() { public void fileOpenDialog(Component parent, ImportPlugin flavor) { fileOpenDialog(parent, flavor, false, f -> open(f[0], flavor, Constants.X_UNSPECIFIED), o -> showOpening(), - "Open files using " + flavor.getName() + " scheme"); + Annotator.getString(Strings.DIALOG_OPEN_WITH_TITLE, flavor.getName())); } public static String getString(String key, Object... parameters) { @@ -408,22 +450,20 @@ public PluginManager getPluginManager() { return pluginManager; } - private MutableList loadRecentFiles() { + private MutableList getRecentFilesFromPreferences() { MutableList files = Lists.mutable.empty(); String listOfFiles = preferences.get(Constants.PREF_RECENT, ""); - logger.debug(listOfFiles); String[] fileNames = listOfFiles.split(File.pathSeparator); for (String fileRef : fileNames) { File file = new File(fileRef); - if (file.exists() && !files.contains(file)) { + if (file.exists() && !files.contains(file) && FileFilters.ca2.accept(file)) { files.add(file); } - } return files; } - private void storeRecentFiles() { + private void recentFiles2Preferences(MutableList recentFiles) { StringBuilder sb = new StringBuilder(); for (int index = 0; index < recentFiles.size(); index++) { File file = recentFiles.get(index); @@ -436,28 +476,14 @@ private void storeRecentFiles() { } public JMenu getRecentFilesMenu() { - JMenu m = new JMenu(Annotator.getString("menu.file.recent")); + ImmutableList recentFiles = getRecentFilesFromPreferences().toImmutable(); + JMenu m = new JMenu(Annotator.getString(Strings.MENU_FILE_RECENT)); for (int i = 0; i < Math.min(20, recentFiles.size()); i++) m.add(new SelectedFileOpenAction(this, recentFiles.get(i))); return m; } - public void refreshRecents() { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - recentFilesPanel.removeAll(); - for (int i = 0; i < Math.min(recentFiles.size(), 10); i++) { - File f = recentFiles.get(i); - recentFilesPanel.add(new JButton(new SelectedFileOpenAction(Annotator.this, f))); - } - recentFilesPanel.repaint(); - opening.validate(); - } - }); - } - public Preferences getPreferences() { return preferences; } @@ -506,14 +532,46 @@ public static boolean javafx() { * @return true, if the file was not already in the list, false otherwise. */ public boolean addRecentFile(File f) { + MutableList recentFiles = getRecentFilesFromPreferences(); Annotator.logger.debug("File {} added to list of recent files", f); - if (!recentFiles.contains(f)) { - recentFiles.add(0, f); - return true; + + boolean contains = recentFiles.contains(f); + if (contains) { + recentFiles.remove(f); } - recentFiles.remove(f); recentFiles.add(0, f); - return false; + recentFiles2Preferences(recentFiles); + return !contains; } + + public boolean isFirstLaunch() { + Version currentVersion = Version.get(); + String lastVersionString = preferences.get(Constants.PREF_LAST_VERSION, currentVersion.toString()); + Version lastVersion = Version.get(lastVersionString); + return lastVersion.compareTo(currentVersion) < 0; + } + + @Override + public void preferenceChange(PreferenceChangeEvent evt) { + if (evt.getKey() == Constants.PREF_RECENT) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ImmutableList recentFiles = getRecentFilesFromPreferences().toImmutable(); + recentFilesPanel.removeAll(); + for (int i = 0; i < Math.min(recentFiles.size(), 10); i++) { + File f = recentFiles.get(i); + recentFilesPanel.add(new JButton(new SelectedFileOpenAction(Annotator.this, f))); + } + recentFilesPanel.repaint(); + recentFilesPanel.validate(); + opening.validate(); + } + }); + + } + + } + } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/CAAbstractTreeSelectionListener.java b/src/main/java/de/unistuttgart/ims/coref/annotator/CAAbstractTreeSelectionListener.java index 1fc68524..fb0e075e 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/CAAbstractTreeSelectionListener.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/CAAbstractTreeSelectionListener.java @@ -12,10 +12,9 @@ import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.factory.Lists; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; @Deprecated public abstract class CAAbstractTreeSelectionListener implements TreeSelectionListener { @@ -71,16 +70,12 @@ public boolean isEntity() { return featureStructures.allSatisfy(f -> f instanceof Entity); } - public boolean isDetachedMentionPart() { - return featureStructures.allSatisfy(f -> f instanceof DetachedMentionPart); - } - public boolean isMention() { return featureStructures.allSatisfy(f -> f instanceof Mention); } public boolean isEntityGroup() { - return featureStructures.allSatisfy(f -> f instanceof EntityGroup); + return featureStructures.allSatisfy(f -> UimaUtil.isGroup((Entity) f)); } public boolean isLeaf() { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/CATreeNode.java b/src/main/java/de/unistuttgart/ims/coref/annotator/CATreeNode.java index 9b268dd4..6d5cd58f 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/CATreeNode.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/CATreeNode.java @@ -11,11 +11,10 @@ import org.apache.uima.cas.FeatureStructure; import org.apache.uima.jcas.tcas.Annotation; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.comp.Tooltipable; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class CATreeNode implements MutableTreeNode, Iterable, Tooltipable { @@ -107,27 +106,30 @@ public int getRank() { @Override public String getToolTip() { - if (getUserObject() instanceof EntityGroup) { - StringBuilder b = new StringBuilder(); - EntityGroup entityGroup = (EntityGroup) getUserObject(); - if (entityGroup.getMembers().size() > 0) { - if (entityGroup.getMembers(0) != null && entityGroup.getMembers(0).getLabel() != null) - b.append(entityGroup.getMembers(0).getLabel()); - else { - System.out.println(); + if (getUserObject() instanceof Entity) { + if (UimaUtil.isGroup(getUserObject())) { + StringBuilder b = new StringBuilder(); + Entity entityGroup = (Entity) getUserObject(); + if (entityGroup.getMembers().size() > 0) { + if (entityGroup.getMembers(0) != null && entityGroup.getMembers(0).getLabel() != null) + b.append(entityGroup.getMembers(0).getLabel()); + else { + System.out.println(); + } + for (int i = 1; i < entityGroup.getMembers().size(); i++) { + b.append(", "); + Entity member = entityGroup.getMembers(i); + if (member != null) + b.append(member.getLabel()); + } + return b.toString(); + } else { + return null; } - for (int i = 1; i < entityGroup.getMembers().size(); i++) { - b.append(", "); - Entity member = entityGroup.getMembers(i); - if (member != null) - b.append(member.getLabel()); - } - return b.toString(); } else { - return null; + return getEntity().getLabel(); } - } else if (getUserObject() instanceof Entity) { - return getEntity().getLabel(); + } return null; } @@ -172,10 +174,6 @@ public boolean isMention() { return userObject instanceof Mention; } - public boolean isMentionPart() { - return userObject instanceof DetachedMentionPart; - } - /** * Returns true if anotherNode is an ancestor of this node -- if it * is this node, this node's parent, or an ancestor of this node's parent. (Note diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/CompareMentionsWindow.java b/src/main/java/de/unistuttgart/ims/coref/annotator/CompareMentionsWindow.java index f5fcdfc0..7b8a1fe5 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/CompareMentionsWindow.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/CompareMentionsWindow.java @@ -2,8 +2,8 @@ import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Dimension; -import java.awt.GridLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; @@ -12,6 +12,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; +import java.util.NoSuchElementException; import java.util.Set; import java.util.function.Consumer; import java.util.prefs.PreferenceChangeEvent; @@ -29,6 +30,7 @@ import javax.swing.JPopupMenu; import javax.swing.JSplitPane; import javax.swing.KeyStroke; +import javax.swing.SpringLayout; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.border.Border; @@ -61,14 +63,16 @@ import de.unistuttgart.ims.coref.annotator.action.CopyAction; import de.unistuttgart.ims.coref.annotator.action.FileImportAction; import de.unistuttgart.ims.coref.annotator.action.FileSelectOpenAction; +import de.unistuttgart.ims.coref.annotator.action.HelpAction; import de.unistuttgart.ims.coref.annotator.action.SelectedFileOpenAction; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.coref.annotator.comp.BoundLabel; import de.unistuttgart.ims.coref.annotator.comp.ColorIcon; import de.unistuttgart.ims.coref.annotator.comp.EntityLabel; +import de.unistuttgart.ims.coref.annotator.comp.SpringUtilities; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModelListener; import de.unistuttgart.ims.coref.annotator.document.DocumentModel; import de.unistuttgart.ims.coref.annotator.document.Event; @@ -77,6 +81,7 @@ import de.unistuttgart.ims.coref.annotator.plugins.ImportPlugin; import de.unistuttgart.ims.coref.annotator.plugins.StylePlugin; import de.unistuttgart.ims.coref.annotator.profile.Profile; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; import de.unistuttgart.ims.coref.annotator.worker.DocumentModelLoader; public class CompareMentionsWindow extends AbstractTextWindow @@ -121,13 +126,13 @@ public void analyze(JCas jcas, Consumer cons) { length = jcas.getDocumentText().length(); for (Mention m : JCasUtil.select(jcas, Mention.class)) { mentions++; - if (m.getEnd() > lastMention) - lastMention = m.getEnd(); + if (UimaUtil.getEnd(m) > lastMention) + lastMention = UimaUtil.getEnd(m); cons.accept(m); } for (Entity e : JCasUtil.select(jcas, Entity.class)) { entities++; - if (e instanceof EntityGroup) + if (UimaUtil.isGroup(e)) entityGroups++; } } @@ -148,8 +153,9 @@ public void mouseClicked(MouseEvent e) { JPopupMenu pMenu = new JPopupMenu(); int offset = textPane.viewToModel2D(e.getPoint()); - ImmutableSet intersectMentions = ism.getIntersection(documentModels.getFirst()); - intersectMentions = intersectMentions.select(m -> m.getBegin() <= offset && offset <= m.getEnd()); + ImmutableSet intersectMentions = intersectModel.getIntersection(documentModels.getFirst()); + intersectMentions = intersectMentions + .select(m -> UimaUtil.getBegin(m) <= offset && offset <= UimaUtil.getEnd(m)); if (!intersectMentions.isEmpty()) { pMenu.add(Annotator.getString(Strings.COMPARE_CONTEXTMENU_INTERSECTION)); @@ -161,9 +167,10 @@ public void mouseClicked(MouseEvent e) { for (int i = 0; i < documentModels.size(); i++) { DocumentModel dm = documentModels.get(i); - RichIterable mentions = ism.spanMentionMap.get(dm) - .reject((s, m) -> ism.getSpanIntersection().contains(s)) - .select((s, m) -> m.getBegin() <= offset && offset <= m.getEnd()).valuesView(); + RichIterable mentions = intersectModel.spanMentionMap.get(dm) + .reject((s, m) -> intersectModel.getSpanIntersection().contains(s)) + .select((s, m) -> UimaUtil.getBegin(m) <= offset && offset <= UimaUtil.getEnd(m)) + .valuesView(); if (!mentions.isEmpty()) { if (!intersectMentions.isEmpty()) pMenu.addSeparator(); @@ -200,16 +207,17 @@ public void mouseReleased(MouseEvent e) { private static final long serialVersionUID = 1L; MutableList annotatorIds; - MutableList open; + MutableList openActions; AbstractAction copyAction; MutableList jcas; MutableList files; - int loadedJCas = 0; - int loadedCModels = 0; + int numberOfLoadedJCas = 0; + int numberOfLoadedDocumentModels = 0; Annotator mainApplication; - JPanel mentionsInfoPane; + JPanel rSidebar; + JLabel modeDescription; JPanel agreementPanel = null; MutableList annotatorStats; @@ -227,14 +235,20 @@ public void mouseReleased(MouseEvent e) { int size = 0; Color[] colors; JMenu fileMenu; - IntersectModel ism = new IntersectModel(); + IntersectModel intersectModel; + Mode mode; + protected SpringLayout rSidebarlayout; + + enum Mode { + Span, Span_EntityName + } public CompareMentionsWindow(Annotator mainApplication, int size) throws UIMAException { this.mainApplication = mainApplication; this.jcas = Lists.mutable.withNValues(size, () -> null); this.files = Lists.mutable.withNValues(size, () -> null); this.annotatorIds = Lists.mutable.withNValues(size, () -> null); - this.open = Lists.mutable.withNValues(size, () -> null); + this.openActions = Lists.mutable.withNValues(size, () -> null); this.annotatorStats = Lists.mutable.withNValues(size, () -> null); this.documentModels = Lists.mutable.withNValues(size, () -> null); this.entityMentionMaps = Lists.mutable.withNValues(size, () -> Multimaps.mutable.set.empty()); @@ -243,6 +257,8 @@ public CompareMentionsWindow(Annotator mainApplication, int size) throws UIMAExc for (int i = 0; i < colors.length; i++) { this.colors[i] = cp.getNextColor(); } + this.mode = (Annotator.app.getPreferences().getBoolean(Constants.CFG_COMPARE_BY_ENTITY_NAME, + Defaults.CFG_COMPARE_BY_ENTITY_NAME) ? Mode.Span_EntityName : Mode.Span); this.size = size; this.initialiseMenu(); this.initializeWindow(); @@ -258,16 +274,17 @@ protected void drawAll(JCas jcas, Color color) { } protected void drawAllAnnotations() { - if (loadedCModels < size) + if (numberOfLoadedDocumentModels < size) return; - ism.documentModels = documentModels.toImmutable(); - ism.calculateIntersection(); + intersectModel = new IntersectModel(); + intersectModel.documentModels = documentModels.toImmutable(); + intersectModel.calculateIntersection(); - Span overlapping = ism.getOverlappingPart(); + Span overlapping = intersectModel.getOverlappingPart(); - ImmutableSet intersection = ism.getSpanIntersection(); + ImmutableSet intersection = intersectModel.getSpanIntersection(); - for (Mention m : ism.getIntersection(documentModels.getFirst())) { + for (Mention m : intersectModel.getIntersection(documentModels.getFirst())) { highlightManager.underline(m, Color.gray.brighter()); } int agreed = intersection.size(); @@ -275,14 +292,13 @@ protected void drawAllAnnotations() { int totalInOverlappingPart = agreed; int index = 0; for (DocumentModel dm : documentModels) { - Set spans = ism.spanMentionMap.get(dm).keySet(); - for (Span s : spans) { + Set spans = intersectModel.spanMentionMap.get(dm).keySet(); + for (Spans s : spans) { if (!intersection.contains(s)) { - if (Annotator.app.getPreferences().getBoolean(Constants.CFG_COMPARE_BY_ENTITY_NAME, - Defaults.CFG_COMPARE_BY_ENTITY_NAME)) - highlightManager.underline(ism.spanMentionMap.get(dm).get(s)); + if (mode == Mode.Span_EntityName) + highlightManager.underline(intersectModel.spanMentionMap.get(dm).get(s)); else - highlightManager.underline(ism.spanMentionMap.get(dm).get(s), colors[index]); + highlightManager.underline(intersectModel.spanMentionMap.get(dm).get(s), colors[index]); total++; if (overlapping.contains(s)) totalInOverlappingPart++; @@ -294,7 +310,7 @@ protected void drawAllAnnotations() { stats.setTotal(total); stats.setAgreed(agreed); stats.setTotalInOverlappingPart(totalInOverlappingPart); - this.mentionsInfoPane.add(getAgreementPanel(), -1); + } protected void ensureSameTexts() throws NotComparableException { @@ -317,12 +333,16 @@ protected double getAgreementInSpan(Span s) { sel.setBegin(s.begin); sel.setEnd(s.end); - for (Mention m : JCasUtil.selectCovered(Mention.class, sel)) { + ; + for (Mention m : Lists.immutable.withAll(JCasUtil.selectCovered(MentionSurface.class, sel)) + .collect(ms -> ms.getMention())) { if (Annotator.app.getPreferences().getBoolean(Constants.CFG_IGNORE_SINGLETONS_WHEN_COMPARING, Defaults.CFG_IGNORE_SINGLETONS_WHEN_COMPARING) && entityMentionMaps.get(index).get(m.getEntity()).size() <= 1) continue; - map1.add(new Span(m)); + + // TODO: this currently only checks the first mention + map1.add(new Span(UimaUtil.getFirst(m))); total++; } mapList.add(map1); @@ -344,16 +364,18 @@ protected double getAgreementInSpan(Span s) { protected JPanel getAgreementPanel() { if (agreementPanel == null) { JPanel panel = new JPanel(); - panel.setLayout(new GridLayout(5, 2)); + SpringLayout layout = new SpringLayout(); + panel.setLayout(layout); + Border border = BorderFactory.createTitledBorder(Annotator.getString(Strings.STAT_AGR_TITLE)); panel.setBorder(border); - panel.setPreferredSize(new Dimension(200, 70)); JLabel desc; desc = new JLabel(Annotator.getString(Strings.STAT_KEY_TOTAL) + ":", SwingConstants.RIGHT); desc.setToolTipText(Annotator.getString(Strings.STAT_KEY_TOTAL_TOOLTIP)); panel.add(desc); JLabel valueLabel = new BoundLabel(stats, "total", o -> o.toString(), stats.total()); + panel.add(valueLabel); desc = new JLabel(Annotator.getString(Strings.STAT_KEY_AGREED) + ":", SwingConstants.RIGHT); @@ -366,7 +388,6 @@ protected JPanel getAgreementPanel() { panel.add(desc); JLabel percTotalLabel = new JLabel(String.format("%1$3.1f%%", 100 * stats.agreed / (double) stats.total), SwingConstants.RIGHT); - panel.add(percTotalLabel); desc = new JLabel(Annotator.getString(Strings.STAT_KEY_AGREED_PARALLEL) + ":", SwingConstants.RIGHT); @@ -403,7 +424,19 @@ public void propertyChange(PropertyChangeEvent evt) { }); - this.agreementPanel = panel; + HelpAction ha = new HelpAction(HelpWindow.Topic.COMPARE); + ha.putValue(Action.NAME, Annotator.getString(Strings.COMPARE_SHOW_AGREEMENT_HELP)); + JButton helpButton = new JButton(ha); + panel.add(helpButton); + + // empty label in the bottom right + panel.add(new JLabel()); + + SpringUtilities.makeCompactGrid(panel, 6, 2, // rows, cols + 5, 5, // initialX, initialY + 15, 3);// xPad, yPad + + agreementPanel = panel; } return agreementPanel; @@ -414,10 +447,12 @@ protected JPanel getAnnotatorPanel(int index) { AnnotatorStatistics stats = annotatorStats.get(index); JPanel panel = new JPanel(); - panel.setLayout(new GridLayout(5, 2)); + SpringLayout layout = new SpringLayout(); + panel.setLayout(layout); Border border = BorderFactory.createTitledBorder(annotatorIds.get(index)); panel.setBorder(border); - panel.setPreferredSize(new Dimension(200, 75)); + // panel.setPreferredSize(new Dimension(200, 100)); + // panel.setMinimumSize(new Dimension(200, 100)); JLabel desc; // color @@ -447,7 +482,10 @@ protected JPanel getAnnotatorPanel(int index) { SwingConstants.RIGHT)); panel.add(new JLabel(Annotator.getString(Strings.ACTION_OPEN) + ":", SwingConstants.RIGHT)); - panel.add(new JButton(open.get(index))); + panel.add(new JButton(openActions.get(index))); + + // layout + SpringUtilities.makeCompactGrid(panel, 5, 2, 5, 5, 15, 3); return panel; } @@ -491,8 +529,6 @@ protected synchronized void initialiseText(JCas jcas2) { StyleManager.styleCharacter(textPane.getStyledDocument(), StyleManager.getDefaultCharacterStyle()); StyleManager.styleParagraph(textPane.getStyledDocument(), StyleManager.getDefaultParagraphStyle()); - - drawAllAnnotations(); } @Override @@ -513,20 +549,28 @@ protected void initializeWindow() { textPane.addCaretListener(new TextCaretListener()); textPane.addMouseListener(new TextMouseListener()); - mentionsInfoPane = new JPanel(); - mentionsInfoPane.setLayout(new BoxLayout(mentionsInfoPane, BoxLayout.Y_AXIS)); - mentionsInfoPane.setPreferredSize(new Dimension(210, 750)); - mentionsInfoPane.setMaximumSize(new Dimension(250, 750)); - mentionsInfoPane.add(new JLabel()); - mentionsInfoPane.add(new JLabel()); - mentionsInfoPane.add(new JLabel()); + modeDescription = new JLabel(); + switch (mode) { + case Span_EntityName: + modeDescription.setText(Annotator.getString(Strings.COMPARE_MODE_DESCRIPTION_SPAN_ENTITYNAME)); + break; + default: + modeDescription.setText(Annotator.getString(Strings.COMPARE_MODE_DESCRIPTION_SPAN)); + break; + } + rSidebarlayout = new SpringLayout(); + + rSidebar = new JPanel(); + rSidebar.setLayout(rSidebarlayout); + rSidebar.setPreferredSize(new Dimension(210, 750)); + rSidebar.setMaximumSize(new Dimension(250, 750)); + rSidebar.add(modeDescription); - mentionsInfoPane.add(Box.createVerticalGlue()); - mentionsInfoPane.add(Box.createVerticalGlue()); - mentionsInfoPane.add(Box.createVerticalGlue()); - mentionsInfoPane.add(Box.createVerticalGlue()); + rSidebarlayout.putConstraint(SpringLayout.NORTH, modeDescription, 5, SpringLayout.NORTH, rSidebar); + rSidebarlayout.putConstraint(SpringLayout.WEST, modeDescription, 5, SpringLayout.WEST, rSidebar); + rSidebarlayout.putConstraint(SpringLayout.EAST, modeDescription, -5, SpringLayout.EAST, rSidebar); - JSplitPane mentionsPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, textPanel, mentionsInfoPane); + JSplitPane mentionsPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, textPanel, rSidebar); mentionsPane.setDividerLocation(500); // tabbedPane.add("Mentions", mentionsPane); @@ -537,8 +581,8 @@ protected void initializeWindow() { pack(); } - private void finishLoading() { - if (loadedCModels >= files.size()) { + protected void finishLoading() { + if (numberOfLoadedDocumentModels >= files.size()) { // Style StylePlugin sPlugin = null; try { @@ -567,13 +611,23 @@ private void finishLoading() { } } - public void setCoreferenceModel(DocumentModel cm, int index) { + public void setDocumentModel(DocumentModel cm, int index) { documentModels.set(index, cm); if (tableOfContents != null) tableOfContents.setModel(cm.getSegmentModel()); - loadedCModels++; + numberOfLoadedDocumentModels++; finishLoading(); drawAllAnnotations(); + + getAgreementPanel(); + rSidebar.add(agreementPanel); + rSidebarlayout.putConstraint(SpringLayout.SOUTH, agreementPanel, -5, SpringLayout.SOUTH, rSidebar); + rSidebarlayout.putConstraint(SpringLayout.WEST, agreementPanel, 5, SpringLayout.WEST, rSidebar); + rSidebarlayout.putConstraint(SpringLayout.EAST, agreementPanel, -5, SpringLayout.EAST, rSidebar); + // rSidebarlayout.putConstraint(SpringLayout.NORTH, agreementPanel, -50, + // SpringLayout.SOUTH, + // rSidebar.getComponent(rSidebar.getComponentCount() - 1)); + rSidebar.validate(); } public void setJCas(JCas jcas, String annotatorId, int index) throws NotComparableException { @@ -588,13 +642,17 @@ public void setJCas(JCas jcas, String annotatorId, int index, Profile profile) t this.annotatorStats.get(index).analyze(jcas, m -> { entityMentionMaps.get(index).put(m.getEntity(), m); }); - loadedJCas++; + numberOfLoadedJCas++; if (!textIsSet) initialiseText(jcas); - mentionsInfoPane.add(getAnnotatorPanel(index), index); - mentionsInfoPane.add(getAgreementPanel(), -1); - - DocumentModelLoader dml = new DocumentModelLoader(cm -> setCoreferenceModel(cm, index), jcas); + JPanel annotatorPanel = getAnnotatorPanel(index); + Component previousComponent = rSidebar.getComponent(rSidebar.getComponentCount() - 1); + rSidebar.add(annotatorPanel); + rSidebarlayout.putConstraint(SpringLayout.NORTH, annotatorPanel, 5, SpringLayout.SOUTH, previousComponent); + rSidebarlayout.putConstraint(SpringLayout.EAST, annotatorPanel, -5, SpringLayout.EAST, rSidebar); + rSidebarlayout.putConstraint(SpringLayout.WEST, annotatorPanel, 5, SpringLayout.WEST, rSidebar); + + DocumentModelLoader dml = new DocumentModelLoader(cm -> setDocumentModel(cm, index), jcas); dml.setProfile(profile); dml.execute(); revalidate(); @@ -636,15 +694,15 @@ protected JMenu initialiseMenuFile() { public void setFile(File file, int index) { this.files.set(index, file); - this.open.set(index, new SelectedFileOpenAction(Annotator.app, file)); + this.openActions.set(index, new SelectedFileOpenAction(Annotator.app, file)); } public void setFiles(Iterable files) { this.files = Lists.mutable.withAll(files); - this.open = this.files.collect(f -> new SelectedFileOpenAction(Annotator.app, f)); + this.openActions = this.files.collect(f -> new SelectedFileOpenAction(Annotator.app, f)); JMenu currentFilesMenu = new JMenu(Annotator.getString(Strings.ACTION_OPEN)); - this.open.forEach(a -> currentFilesMenu.add(a)); + this.openActions.forEach(a -> currentFilesMenu.add(a)); fileMenu.add(currentFilesMenu, 1); } @@ -653,11 +711,28 @@ public void preferenceChange(PreferenceChangeEvent evt) { if (evt.getKey() == Constants.CFG_IGNORE_SINGLETONS_WHEN_COMPARING) { highlightManager.hilit.removeAllHighlights(); drawAllAnnotations(); + } else if (evt.getKey() == Constants.CFG_COMPARE_BY_ENTITY_NAME) { + this.mode = (Annotator.app.getPreferences().getBoolean(Constants.CFG_COMPARE_BY_ENTITY_NAME, + Defaults.CFG_COMPARE_BY_ENTITY_NAME) ? Mode.Span_EntityName : Mode.Span); + + switch (mode) { + case Span_EntityName: + modeDescription.setText(Annotator.getString(Strings.COMPARE_MODE_DESCRIPTION_SPAN_ENTITYNAME)); + break; + default: + modeDescription.setText(Annotator.getString(Strings.COMPARE_MODE_DESCRIPTION_SPAN)); + break; + } + + entityMentionMaps = Lists.mutable.withNValues(size, () -> Multimaps.mutable.set.empty()); + highlightManager.hilit.removeAllHighlights(); + drawAllAnnotations(); + } else super.preferenceChange(evt); } - static class ExtendedSpan extends Span { + static class ExtendedSpan extends Spans { public String entityLabel; @@ -668,7 +743,7 @@ public ExtendedSpan(Mention annotation) { @Override public int hashCode() { - return Objects.hashCode(this.begin, this.end, this.entityLabel); + return Objects.hashCode(super.spans, this.entityLabel); } @Override @@ -677,7 +752,7 @@ public boolean equals(Object obj) { return false; } ExtendedSpan that = (ExtendedSpan) obj; - return this.begin == that.begin && this.end == that.end && this.entityLabel.contentEquals(that.entityLabel); + return this.spans.equals(that.spans) && this.entityLabel.contentEquals(that.entityLabel); } } @@ -718,18 +793,12 @@ protected void initialize() { add(mainLabel); if (includeEntityFlags) if (entity.getFlags() != null && documentModel != null) - for (String flagKey : entity.getFlags()) { - if (flagKey == Constants.ENTITY_FLAG_HIDDEN) - continue; - Flag flag = documentModel.getFlagModel().getFlag(flagKey); + for (Flag flag : entity.getFlags()) { addFlag(this, flag, Color.BLACK); } if (includeMentionFlags) if (mention.getFlags() != null && documentModel != null) - for (String flagKey : mention.getFlags()) { - if (flagKey == Constants.ENTITY_FLAG_HIDDEN) - continue; - Flag flag = documentModel.getFlagModel().getFlag(flagKey); + for (Flag flag : mention.getFlags()) { addFlag(this, flag, Color.BLACK); } } @@ -782,10 +851,11 @@ public void entityEvent(FeatureStructureEvent event) { } } - public static class IntersectModel { + public class IntersectModel { ImmutableList documentModels; - MutableSet spanIntersection = null; - MutableMap> spanMentionMap = Maps.mutable.empty(); + MutableSet spanIntersection = null; + MutableMap> spanMentionMap = Maps.mutable.empty(); + MutableSetMultimap spanAllMentionsMap = Multimaps.mutable.set.empty(); Span annotatedRange = new Span(Integer.MAX_VALUE, Integer.MIN_VALUE); Span overlappingPart = new Span(Integer.MIN_VALUE, Integer.MAX_VALUE); @@ -793,27 +863,28 @@ public void calculateIntersection() { for (DocumentModel dm : documentModels) { spanMentionMap.put(dm, Maps.mutable.empty()); JCas jcas = dm.getJcas(); - MutableSet spans = Sets.mutable.empty(); + MutableSet spans = Sets.mutable.empty(); for (Mention m : JCasUtil.select(jcas, Mention.class)) { if (Annotator.app.getPreferences().getBoolean(Constants.CFG_IGNORE_SINGLETONS_WHEN_COMPARING, Defaults.CFG_IGNORE_SINGLETONS_WHEN_COMPARING) && dm.getCoreferenceModel().getSingletons().contains(m.getEntity())) continue; - Span span; - if (Annotator.app.getPreferences().getBoolean(Constants.CFG_COMPARE_BY_ENTITY_NAME, - Defaults.CFG_COMPARE_BY_ENTITY_NAME)) + Spans span; + if (mode == Mode.Span_EntityName) span = new ExtendedSpan(m); else - span = new Span(m); + span = new Spans(m); + for (Span sp : span) + spanAllMentionsMap.put(sp, m); spanMentionMap.get(dm).put(span, m); spans.add(span); - if (m.getEnd() > annotatedRange.end) - annotatedRange.end = m.getEnd(); - if (m.getBegin() < annotatedRange.begin) - annotatedRange.begin = m.getBegin(); + if (UimaUtil.getEnd(m) > annotatedRange.end) + annotatedRange.end = UimaUtil.getEnd(m); + if (UimaUtil.getBegin(m) < annotatedRange.begin) + annotatedRange.begin = UimaUtil.getBegin(m); } if (spanIntersection == null) @@ -833,7 +904,7 @@ public ImmutableSet getIntersection(DocumentModel dm) { return spanIntersection.collect(s -> spanMentionMap.get(dm).get(s)).toImmutable(); } - public ImmutableSet getSpanIntersection() { + public ImmutableSet getSpanIntersection() { return spanIntersection.toImmutable(); } @@ -857,4 +928,24 @@ public NotComparableException(String string) { } + public MentionSurface getNextMentionSurface(int position) { + try { + return documentModels.collect(dm -> dm.getCoreferenceModel()) + .collect(cm -> cm.getNextMentionSurface(position)).reject(ms -> ms == null) + .minBy(m -> m.getBegin()); + } catch (NoSuchElementException e) { + return null; + } + } + + public MentionSurface getPreviousMentionSurface(int position) { + try { + return documentModels.collect(dm -> dm.getCoreferenceModel()) + .collect(cm -> cm.getPreviousMentionSurface(position)).reject(ms -> ms == null) + .maxBy(m -> m.getEnd()); + } catch (NoSuchElementException e) { + return null; + } + } + } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/Constants.java b/src/main/java/de/unistuttgart/ims/coref/annotator/Constants.java index 8296e982..c51b7a29 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/Constants.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/Constants.java @@ -4,10 +4,6 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.document.op.AddFlag; - public class Constants { /** * Annotator name or id @@ -47,6 +43,7 @@ public class Constants { * * @since 1.13 */ + @Deprecated public static final String CFG_CREATE_DEFAULT_FLAGS = "CFG_CREATE_DEFAULT_FLAGS"; /** @@ -128,35 +125,12 @@ public class Constants { */ public static final String CFG_UNDERLINE_SINGLETONS_IN_GRAY = "CFG_UNDERLINE_SINGLETONS_IN_GRAY"; - @Deprecated - public static final String ENTITY_FLAG_GENERIC = "Generic"; - @Deprecated - public static final String ENTITY_FLAG_HIDDEN = "Hidden"; - public static final int MAX_SEGMENTS_IN_SCROLLBAR = 15; - public static final AddFlag[] FLAG_COLLECTION_1 = new AddFlag[] { - new AddFlag("female", "Female", MaterialDesign.MDI_GENDER_FEMALE, Entity.class), - new AddFlag("male", "Male", MaterialDesign.MDI_GENDER_MALE, Entity.class), - new AddFlag("male-female", "Male/Female", MaterialDesign.MDI_GENDER_MALE_FEMALE, Entity.class), - new AddFlag("transgender", "Transgender", MaterialDesign.MDI_GENDER_TRANSGENDER, Entity.class) }; - - public static final AddFlag[] FLAG_COLLECTION_2 = new AddFlag[] { - new AddFlag("predicate", "Predicate", MaterialDesign.MDI_GAVEL, Mention.class), - new AddFlag("pronoun", "Pronoun", MaterialDesign.MDI_ARROW_TOP_LEFT, Mention.class), - new AddFlag("name", "Proper name", MaterialDesign.MDI_TAG, Mention.class) }; - - @Deprecated - public static final String MENTION_FLAG_AMBIGUOUS = "Ambiguous"; - - @Deprecated - public static final String MENTION_FLAG_DIFFICULT = "Difficult"; - - @Deprecated - public static final String MENTION_FLAG_NON_NOMINAL = "Non Nominal"; - public static final String PREF_RECENT = "recent_files"; + public static final String PREF_LAST_VERSION = "last_closed_version"; + public static final Random RANDOM = new Random(); public static final Setting SETTING_ASK_BEFORE_FILE_OVERWRITE = new Setting( @@ -184,7 +158,7 @@ public class Constants { Strings.ACTION_TOGGLE_IGNORE_SINGLETONS_WHEN_COMPARING_TOOLTIP, true, MaterialDesign.MDI_SETTINGS); public static final Setting SETTING_KEEP_TREE_SORTED = new Setting(CFG_KEEP_TREE_SORTED, - Strings.ACTION_TOGGLE_KEEP_TREE_SORTED, Strings.ACTION_TOGGLE_TRIM_WHITESPACE_TOOLTIP, true, + Strings.ACTION_TOGGLE_KEEP_TREE_SORTED, Strings.ACTION_TOGGLE_KEEP_TREE_SORTED_TOOLTIP, true, MaterialDesign.MDI_SORT_VARIANT); public static final Setting SETTING_SHOW_TEXT_LABELS = new Setting(CFG_SHOW_TEXT_LABELS, @@ -225,6 +199,7 @@ public class Constants { public static final int UI_MAX_STRING_WIDTH_IN_TREE = 100; public static final int UI_MAX_STRING_WIDTH_IN_MENU = 30; public static final int UI_MAX_STRING_WIDTH_IN_STATUSBAR = 30; + public static final int UI_ICON_SIZE_IN_TREE = 16; public static final String URL_LATEST_RELEASE_API = "https://api.github.com/repos/nilsreiter/CorefAnnotator/releases/latest"; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/Defaults.java b/src/main/java/de/unistuttgart/ims/coref/annotator/Defaults.java index 3839a5d9..73eaa8ea 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/Defaults.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/Defaults.java @@ -4,6 +4,7 @@ public class Defaults { public static final String CFG_ANNOTATOR_ID = "Unknown annotator"; public static final int CFG_AUTOSAVE_TIMER = 300000; public static final boolean CFG_COMPARE_BY_ENTITY_NAME = true; + @Deprecated public static final boolean CFG_CREATE_DEFAULT_FLAGS = false; public static final boolean CFG_DELETE_EMPTY_ENTITIES = false; public static final EntitySortOrder CFG_ENTITY_SORT_ORDER = EntitySortOrder.Mentions; @@ -19,5 +20,6 @@ public class Defaults { public static final boolean CFG_IGNORE_SINGLETONS_WHEN_COMPARING = true; public static final boolean CFG_UNDERLINE_SINGLETONS_IN_GRAY = false; public static final boolean CFG_STICKY_FLAGS = false; + public static final String CFG_MENTIONSURFACE_SEPARATOR = " | "; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/DocumentWindow.java b/src/main/java/de/unistuttgart/ims/coref/annotator/DocumentWindow.java index c107c963..03d717ca 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/DocumentWindow.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/DocumentWindow.java @@ -27,7 +27,6 @@ import java.util.Collection; import java.util.Enumeration; import java.util.EventObject; -import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.function.BooleanSupplier; @@ -76,7 +75,6 @@ import javax.swing.text.DefaultStyledDocument; import javax.swing.text.JTextComponent; import javax.swing.text.MutableAttributeSet; -import javax.swing.text.StyleContext; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellEditor; import javax.swing.tree.DefaultTreeCellRenderer; @@ -90,7 +88,6 @@ import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; import org.apache.uima.jcas.cas.TOP; -import org.apache.uima.jcas.tcas.Annotation; import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.api.set.ImmutableSet; @@ -101,6 +98,7 @@ import org.kordamp.ikonli.swing.FontIcon; import de.unistuttgart.ims.coref.annotator.action.AddCurrentSpanToCurrentEntity; +import de.unistuttgart.ims.coref.annotator.action.AnalyzeAction; import de.unistuttgart.ims.coref.annotator.action.ChangeColorForEntity; import de.unistuttgart.ims.coref.annotator.action.ChangeKeyForEntityAction; import de.unistuttgart.ims.coref.annotator.action.CopyAction; @@ -125,12 +123,11 @@ import de.unistuttgart.ims.coref.annotator.action.RemoveSingletons; import de.unistuttgart.ims.coref.annotator.action.RenameAllEntitiesAction; import de.unistuttgart.ims.coref.annotator.action.RenameEntityAction; -import de.unistuttgart.ims.coref.annotator.action.SelectNextMentionAction; -import de.unistuttgart.ims.coref.annotator.action.SelectPreviousMentionAction; import de.unistuttgart.ims.coref.annotator.action.SetLanguageAction; import de.unistuttgart.ims.coref.annotator.action.ShowASelectedMentionInTreeAction; import de.unistuttgart.ims.coref.annotator.action.ShowDocumentStatistics; import de.unistuttgart.ims.coref.annotator.action.ShowFlagEditor; +import de.unistuttgart.ims.coref.annotator.action.ShowGuidelinesAction; import de.unistuttgart.ims.coref.annotator.action.ShowLogWindowAction; import de.unistuttgart.ims.coref.annotator.action.ShowMentionInTreeAction; import de.unistuttgart.ims.coref.annotator.action.ShowSearchPanelAction; @@ -145,19 +142,16 @@ import de.unistuttgart.ims.coref.annotator.action.ViewSetLineNumberStyle; import de.unistuttgart.ims.coref.annotator.action.ViewSetLineSpacingAction; import de.unistuttgart.ims.coref.annotator.action.ViewStyleSelectAction; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; import de.unistuttgart.ims.coref.annotator.comp.EntityPanel; -import de.unistuttgart.ims.coref.annotator.comp.FixedTextLineNumber; import de.unistuttgart.ims.coref.annotator.comp.FlagMenu; import de.unistuttgart.ims.coref.annotator.comp.ImprovedMessageDialog; import de.unistuttgart.ims.coref.annotator.comp.SegmentedScrollBar; import de.unistuttgart.ims.coref.annotator.comp.SortingTreeModelListener; -import de.unistuttgart.ims.coref.annotator.comp.TextLineNumber; import de.unistuttgart.ims.coref.annotator.comp.Tooltipable; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModel; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModelListener; @@ -165,13 +159,11 @@ import de.unistuttgart.ims.coref.annotator.document.DocumentState; import de.unistuttgart.ims.coref.annotator.document.DocumentStateListener; import de.unistuttgart.ims.coref.annotator.document.FeatureStructureEvent; -import de.unistuttgart.ims.coref.annotator.document.FlagModel; import de.unistuttgart.ims.coref.annotator.document.FlagModelListener; import de.unistuttgart.ims.coref.annotator.document.op.AddEntityToEntityGroup; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToEntity; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToNewEntity; -import de.unistuttgart.ims.coref.annotator.document.op.AttachPart; -import de.unistuttgart.ims.coref.annotator.document.op.MoveMentionPartToMention; +import de.unistuttgart.ims.coref.annotator.document.op.AddSpanToMention; import de.unistuttgart.ims.coref.annotator.document.op.MoveMentionsToEntity; import de.unistuttgart.ims.coref.annotator.document.op.Operation; import de.unistuttgart.ims.coref.annotator.document.op.RemoveEntities; @@ -199,6 +191,8 @@ public class DocumentWindow extends AbstractTextWindow implements CaretListener, File file; + String proposedFilename; + String segmentAnnotation = null; // storing and caching @@ -208,8 +202,8 @@ public class DocumentWindow extends AbstractTextWindow implements CaretListener, ActionContainer actions = new ActionContainer(); // Window components + JToolBar controls = new JToolBar(); JTree tree; - StyleContext styleContext = new StyleContext(); JLabel selectionDetailPanel; JSplitPane splitPane; JTextField treeSearchField; @@ -222,12 +216,10 @@ public class DocumentWindow extends AbstractTextWindow implements CaretListener, JMenu windowsMenu; JPopupMenu treePopupMenu; JPopupMenu textPopupMenu; - Map styleMenuItem = new HashMap(); + // Map styleMenuItem = new + // HashMap(); FlagMenu mentionFlagsInTreePopup, entityFlagsInTreePopup, mentionFlagsInMenuBar, entityFlagsInMenuBar; - // Settings - StylePlugin currentStyle; - // sub windows SearchDialog searchPanel; @@ -322,7 +314,6 @@ protected void initializeWindow() { JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)); // tool bar - JToolBar controls = new JToolBar(); controls.setFocusable(false); controls.setRollover(true); controls.add(actions.newEntityAction); @@ -334,17 +325,13 @@ protected void initializeWindow() { controls.add(actions.mergeSelectedEntitiesAction); controls.add(actions.showSearchPanelAction); controls.add(actions.showDocumentStatistics); + controls.add(actions.analyze); getContentPane().add(controls, BorderLayout.NORTH); for (Component comp : controls.getComponents()) comp.setFocusable(false); - getMiscLabel().setText("Style: " + Annotator.app.getPluginManager().getDefaultStylePlugin().getName()); - getMiscLabel().setToolTipText(Annotator.app.getPluginManager().getDefaultStylePlugin().getDescription()); - getMiscLabel().setPreferredSize(new Dimension(150, 20)); - miscLabel2.setPreferredSize(new Dimension(150, 20)); - // initialise text view Caret caret = new Caret(); TextMouseListener textMouseListener = new TextMouseListener(); @@ -364,8 +351,6 @@ protected void initializeWindow() { textPane.getActionMap().put(DeleteAction.class, actions.deleteAction); textPane.getActionMap().put(CopyAction.class, new CopyAction(this)); textPane.getActionMap().put(DeleteAllMentionsInSelection.class, actions.deleteAllAction); - textPane.getActionMap().put(SelectNextMentionAction.class, new SelectNextMentionAction(this)); - textPane.getActionMap().put(SelectPreviousMentionAction.class, new SelectPreviousMentionAction(this)); textPane.getInputMap().put( KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()), CopyAction.class); @@ -373,10 +358,6 @@ protected void initializeWindow() { textPane.getInputMap().put( KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()), DeleteAllMentionsInSelection.class); - textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_DOWN_MASK), - SelectNextMentionAction.class); - textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.ALT_DOWN_MASK), - SelectPreviousMentionAction.class); textPane.addCaretListener(actions.showASelectedMentionInTree); @@ -421,6 +402,7 @@ protected void initialiseActions() { this.actions.sortByAlpha = SortTree.getSortByAlphabet(this); this.actions.sortByMentions = SortTree.getSortByMention(this); this.actions.sortByLastModified = SortTree.getSortByLastModified(this); + this.actions.sortByPosition = SortTree.getSortByPosition(this); this.actions.fileSaveAction = new FileSaveAction(this); this.actions.showSearchPanelAction = new ShowSearchPanelAction(Annotator.app, this); this.actions.copyAction = new CopyAction(this); @@ -439,6 +421,7 @@ protected void initialiseActions() { actions.undoAction.setEnabled(false); actions.entityStatisticsAction.setEnabled(false); actions.fileSaveAction.setEnabled(false); + actions.analyze.setEnabled(false); // connect listeners documentStateListeners.add(actions.undoAction); @@ -487,16 +470,16 @@ protected JMenu initialiseMenuView() { grp = new ButtonGroup(); JMenu lineNumbersMenu = new JMenu(Annotator.getString(Strings.MENU_VIEW_LINE_NUMBERS)); - radio = new JRadioButtonMenuItem(actions.lineNumberStyleNone); + radio = new JRadioButtonMenuItem(lineNumberStyleNone); radio.setSelected(true); grp.add(radio); lineNumbersMenu.add(radio); - radio = new JRadioButtonMenuItem(actions.lineNumberStyleFixed); + radio = new JRadioButtonMenuItem(lineNumberStyleFixed); grp.add(radio); lineNumbersMenu.add(radio); - radio = new JRadioButtonMenuItem(actions.lineNumberStyleDynamic); + radio = new JRadioButtonMenuItem(lineNumberStyleDynamic); grp.add(radio); lineNumbersMenu.add(radio); @@ -523,6 +506,27 @@ protected JMenu initialiseMenuView() { } viewMenu.add(viewStyleMenu); + + JMenu sortMenu = new JMenu(Annotator.getString(Strings.MENU_EDIT_ENTITIES_SORT)); + JRadioButtonMenuItem sortRadio1 = new JRadioButtonMenuItem(this.actions.sortByAlpha); + JRadioButtonMenuItem sortRadio2 = new JRadioButtonMenuItem(this.actions.sortByMentions); + JRadioButtonMenuItem sortRadio3 = new JRadioButtonMenuItem(this.actions.sortByLastModified); + JRadioButtonMenuItem sortRadio4 = new JRadioButtonMenuItem(this.actions.sortByPosition); + sortRadio2.setSelected(true); + ButtonGroup sortGrp = new ButtonGroup(); + sortGrp.add(sortRadio4); + sortGrp.add(sortRadio3); + sortGrp.add(sortRadio2); + sortGrp.add(sortRadio1); + + sortMenu.add(sortRadio1); + sortMenu.add(sortRadio2); + sortMenu.add(sortRadio3); + sortMenu.add(sortRadio4); + sortMenu.add(new JCheckBoxMenuItem(this.actions.sortDescending)); + + viewMenu.add(sortMenu); + return viewMenu; } @@ -609,30 +613,11 @@ protected JMenu initialiseMenuEntity() { // entityMenu.add(new JCheckBoxMenuItem(actions.toggleEntityDisplayed)); entityMenu.add(actions.entityStatisticsAction); - JMenu sortMenu = new JMenu(Annotator.getString(Strings.MENU_EDIT_ENTITIES_SORT)); - JRadioButtonMenuItem radio1 = new JRadioButtonMenuItem(this.actions.sortByAlpha); - JRadioButtonMenuItem radio2 = new JRadioButtonMenuItem(this.actions.sortByMentions); - JRadioButtonMenuItem radio3 = new JRadioButtonMenuItem(this.actions.sortByLastModified); - radio2.setSelected(true); - ButtonGroup grp = new ButtonGroup(); - grp.add(radio3); - grp.add(radio2); - grp.add(radio1); - - sortMenu.add(radio1); - sortMenu.add(radio2); - sortMenu.add(radio3); - sortMenu.add(new JCheckBoxMenuItem(this.actions.sortDescending)); - - entityMenu.add(sortMenu); return entityMenu; } protected void initialiseMenu() { - JMenu helpMenu = new JMenu(Annotator.getString(Strings.MENU_HELP)); - helpMenu.add(Annotator.app.helpAction); - menuBar.add(initialiseMenuFile()); menuBar.add(initialiseMenuEntity()); menuBar.add(initialiseMenuView()); @@ -642,7 +627,7 @@ protected void initialiseMenu() { // if (segmentAnnotation != null) // menuBar.add(documentMenu); // menuBar.add(windowsMenu); - menuBar.add(helpMenu); + menuBar.add(menu_help); setJMenuBar(menuBar); @@ -664,6 +649,8 @@ public void closeWindow(boolean quit) { public void loadFile(File file, ImportPlugin flavor, String language) { if (flavor instanceof DefaultImportPlugin) this.file = file; + else + this.proposedFilename = file.getName().replaceAll("\\.[^\\.]+$", ""); JCasLoader lai; setMessage(Annotator.getString(Strings.MESSAGE_LOADING)); @@ -738,25 +725,6 @@ public void actionPerformed(ActionEvent e) { } - @Override - public void setLineNumberStyle(LineNumberStyle lns) { - TextLineNumber tln; - switch (lns) { - case FIXED: - tln = new FixedTextLineNumber(this, 5); - pcs.addPropertyChangeListener(tln); - break; - case DYNAMIC: - tln = new TextLineNumber(this, 5); - pcs.addPropertyChangeListener(tln); - break; - default: - tln = null; - } - textScrollPane.setRowHeaderView(tln); - super.setLineNumberStyle(lns); - } - public void setWindowTitle() { String fileName = (file != null ? file.getName() : Annotator.getString(Strings.WINDOWTITLE_NEW_FILE)); @@ -787,7 +755,7 @@ protected void entityEventRemove(FeatureStructureEvent event) { protected void entityEventMove(FeatureStructureEvent event) { for (FeatureStructure fs : event) if (fs instanceof Mention) { - highlightManager.unUnderline((Annotation) fs); + highlightManager.unUnderline((Mention) fs); highlightManager.underline((Mention) fs, new Color(((Entity) event.getArgument2()).getColor())); } updateStatusBar(); @@ -796,6 +764,7 @@ protected void entityEventMove(FeatureStructureEvent event) { @Override public void setDocumentModel(DocumentModel model) { super.setDocumentModel(model); + model.setFile(getFile()); MyTreeModelListener modelHandler = new MyTreeModelListener(); @@ -805,15 +774,15 @@ public void setDocumentModel(DocumentModel model) { tableOfContents.setModel(model.getSegmentModel()); if (model.hasLineNumbers()) { - actions.lineNumberStyleFixed.setEnabled(true); - this.setLineNumberStyle(actions.lineNumberStyleFixed.getStyle()); + lineNumberStyleFixed.setEnabled(true); + lineNumberStyleFixed.actionPerformed(new ActionEvent(this, 0, null)); } else { - actions.lineNumberStyleDynamic.setEnabled(true); - this.setLineNumberStyle(actions.lineNumberStyleDynamic.getStyle()); + lineNumberStyleDynamic.actionPerformed(new ActionEvent(this, 0, null)); } - actions.newEntityAction.setEnabled(true); + actions.newEntityAction.setEnabled(false); actions.changeColorAction.setEnabled(true); actions.changeKeyAction.setEnabled(true); + actions.analyze.setEnabled(true); highlightManager.setDocumentModel(model); // listeners to the coref model @@ -895,6 +864,13 @@ public void setDocumentModel(DocumentModel model) { miscLabel2.setText(Annotator.getString(Strings.STATUS_PROFILE) + ": " + "Unknown"); miscLabel2.repaint(); + if (model.getProfile() != null && model.getProfile().getGuidelines() != null + && java.awt.Desktop.isDesktopSupported()) { + Action glAction = new ShowGuidelinesAction(model.getProfile()); + menu_help.add(glAction); + controls.add(glAction); + } + // final setMessage(""); pack(); @@ -943,7 +919,7 @@ protected void updateStatusBar() { if (getDocumentModel() != null && getDocumentModel().getCoreferenceModel() != null) { // nothing is selected: show all mentions cursor is part of - MutableSet annotations = Sets.mutable + MutableSet annotations = Sets.mutable .withAll(getDocumentModel().getCoreferenceModel().getMentions(low)); mentions = annotations.selectInstancesOf(Mention.class); @@ -962,11 +938,6 @@ protected void updateStatusBar() { } } - @Override - public void switchStyle(StylePlugin sv) { - switchStyle(sv, sv.getBaseStyle()); - } - @Override public void switchStyle(StylePlugin sv, AttributeSet baseStyle) { SwingUtilities.invokeLater(new Runnable() { @@ -996,7 +967,7 @@ public void run() { styles.get(style)); getProgressBar().setValue(getProgressBar().getValue() + 10); } - Util.getMeta(getDocumentModel().getJcas()).setStylePlugin(sv.getClass().getName()); + UimaUtil.getMeta(getDocumentModel().getJcas()).setStylePlugin(sv.getClass().getName()); currentStyle = sv; styleMenuItem.get(sv).setSelected(true); getMiscLabel().setText(Annotator.getString(Strings.STATUS_STYLE) + ": " + sv.getName()); @@ -1010,17 +981,6 @@ public void run() { } - public void annotationSelected(Annotation m) { - if (m != null) { - textPane.setSelectionStart(m.getBegin()); - textPane.setSelectionEnd(m.getEnd()); - // textPane.setCaretPosition(m.getEnd()); - textPane.getCaret().setSelectionVisible(true); - } else { - textPane.getCaret().setSelectionVisible(false); - } - } - class MyTreeTransferHandler extends TransferHandler { CATreeNode targetNode; @@ -1091,7 +1051,8 @@ public boolean importData(TransferHandler.TransferSupport info) { } else if (targetFS instanceof Entity) { operation = new AddMentionsToEntity((Entity) targetFS, paList); } else if (targetFS instanceof Mention) { - operation = new AttachPart((Mention) targetFS, paList.getFirst()); + operation = new AddSpanToMention((Mention) targetFS, paList.getFirst()); + // operation = new AttachPart((Mention) targetFS, paList.getFirst()); } if (operation != null) { getDocumentModel().edit(operation); @@ -1114,7 +1075,7 @@ public boolean importData(TransferHandler.TransferSupport info) { try { a = info.getTransferable().getTransferData(dataFlavor); @SuppressWarnings("unchecked") - ImmutableList aList = (ImmutableList) a; + ImmutableList aList = (ImmutableList) a; if (aList.anySatisfy(anno -> anno instanceof Mention) && targetFS instanceof Entity) getDocumentModel().edit( new MoveMentionsToEntity((Entity) targetFS, aList.selectInstancesOf(Mention.class))); @@ -1130,9 +1091,8 @@ protected boolean handleNodeMoving(ImmutableList moved) { Annotator.logger.debug("Moving {} things", moved.size()); Operation operation = null; if (targetFS instanceof Entity) { - if (moved.anySatisfy(n -> n.getFeatureStructure() instanceof Entity) - && targetFS instanceof EntityGroup) { - operation = new AddEntityToEntityGroup((EntityGroup) targetFS, + if (moved.anySatisfy(n -> n.getFeatureStructure() instanceof Entity) && UimaUtil.isGroup(targetFS)) { + operation = new AddEntityToEntityGroup((Entity) targetFS, moved.select(n -> n.getFeatureStructure() instanceof Entity) .collect(n -> n.getFeatureStructure())); } @@ -1140,9 +1100,7 @@ protected boolean handleNodeMoving(ImmutableList moved) { getDocumentModel().edit(new MoveMentionsToEntity((Entity) targetFS, moved.select(n -> n.getFeatureStructure() instanceof Mention) .collect(n -> n.getFeatureStructure()))); - } else if (targetFS instanceof Mention) - operation = new MoveMentionPartToMention((Mention) targetFS, moved.getFirst().getFeatureStructure()); - else + } else return false; if (operation != null) getDocumentModel().edit(operation); @@ -1160,7 +1118,7 @@ public Transferable createTransferable(JComponent comp) { ImmutableList paths = Lists.immutable.of(tree.getSelectionPaths()); ImmutableList nodes = paths.collect(tp -> (CATreeNode) tp.getLastPathComponent()) - .select(n -> n.isEntity() || n.isMention() || n.isMentionPart()); + .select(n -> n.isEntity() || n.isMention()); if (nodes.isEmpty()) return null; return new NodeListTransferable(nodes); @@ -1206,19 +1164,7 @@ protected void addFlag(JPanel panel, Flag flag, Color color) { l.setForeground(color); if (showText) l.setText(Annotator.getStringWithDefault(flag.getLabel(), flag.getLabel())); - l.setIcon(FontIcon.of(MaterialDesign.valueOf(flag.getIcon()), color)); - panel.add(Box.createRigidArea(new Dimension(5, 5))); - panel.add(l); - } - - @Deprecated - protected void addFlag(JPanel panel, String textLabel, Icon icon, Color color) { - JLabel l = new JLabel(); - if (color != null) - l.setForeground(color); - if (showText) - l.setText(textLabel); - l.setIcon(icon); + l.setIcon(FontIcon.of(MaterialDesign.valueOf(flag.getIcon()), Constants.UI_ICON_SIZE_IN_TREE, color)); panel.add(Box.createRigidArea(new Dimension(5, 5))); panel.add(l); } @@ -1226,15 +1172,16 @@ protected void addFlag(JPanel panel, String textLabel, Icon icon, Color color) { protected JPanel handleEntity(JPanel panel, JLabel lab1, Entity entity) { lab1.setText(entity.getLabel()); - boolean isGrey = Util.isX(entity, Constants.ENTITY_FLAG_HIDDEN) || treeNode.getRank() < 50; + boolean isGrey = entity.getHidden() || treeNode.getRank() < 50; Color entityColor = new Color(entity.getColor()); if (isGrey) { lab1.setForeground(Color.GRAY); - lab1.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT_OUTLINE, Color.GRAY)); + lab1.setIcon( + FontIcon.of(MaterialDesign.MDI_ACCOUNT_OUTLINE, Constants.UI_ICON_SIZE_IN_TREE, Color.GRAY)); } else { lab1.setForeground(Color.BLACK); - lab1.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT, entityColor)); + lab1.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT, Constants.UI_ICON_SIZE_IN_TREE, entityColor)); } String visLabel = StringUtils.abbreviate(entity.getLabel(), "…", Constants.UI_MAX_STRING_WIDTH_IN_TREE); @@ -1243,30 +1190,28 @@ protected JPanel handleEntity(JPanel panel, JLabel lab1, Entity entity) { lab1.setText(visLabel + " [" + entity.getKey() + "] (" + treeNode.getChildCount() + ")"); } else if (!(treeNode.getParent().isEntity())) lab1.setText(visLabel + " (" + treeNode.getChildCount() + ")"); - if (entity instanceof EntityGroup) { + if (UimaUtil.isGroup(entity)) { panel.add(Box.createRigidArea(new Dimension(5, 5))); panel.add(new JLabel(FontIcon.of(MaterialDesign.MDI_ACCOUNT_MULTIPLE))); } if (entity.getFlags() != null) - for (String flagKey : entity.getFlags()) { - Flag flag = getDocumentModel().getFlagModel().getFlag(flagKey); + for (Flag flag : entity.getFlags()) { addFlag(panel, flag, isGrey ? Color.GRAY : Color.BLACK); } return panel; } protected JPanel handleMention(JPanel panel, JLabel lab1, Mention m) { - FlagModel fm = getDocumentModel().getFlagModel(); // constructing text StringBuilder b = new StringBuilder(); if (Annotator.app.getPreferences().getBoolean(Constants.CFG_SHOW_LINE_NUMBER_IN_TREE, Defaults.CFG_SHOW_LINE_NUMBER_IN_TREE)) { - Segment segment = getDocumentModel().getSegmentModel().getSegmentAt(m.getBegin()); + Segment segment = getDocumentModel().getSegmentModel().getSegmentAt(UimaUtil.getBegin(m)); AnnotationTreeNode tn = getDocumentModel().getSegmentModel().getAnnotationTreeNode(segment); String sep = "/"; String ln = UimaUtil.toString(tn, sep, 20); - Integer lineNumber = getDocumentModel().getLineNumber(m.getBegin()); + Integer lineNumber = getDocumentModel().getLineNumber(UimaUtil.getBegin(m)); if (lineNumber != null) ln = ln + sep + lineNumber.toString(); if (ln != null) { @@ -1275,16 +1220,15 @@ protected JPanel handleMention(JPanel panel, JLabel lab1, Mention m) { b.append('(').append(ln).append(')').append(' '); } } - b.append(m.getCoveredText()); + b.append(UimaUtil.getCoveredText(m)); lab1.setText(b.toString()); if (m.getFlags() != null) - for (String flagKey : m.getFlags()) { - Flag flag = fm.getFlag(flagKey); + for (Flag flag : m.getFlags()) { addFlag(panel, flag, Color.black); } - lab1.setIcon(FontIcon.of(MaterialDesign.MDI_COMMENT_ACCOUNT)); + lab1.setIcon(FontIcon.of(MaterialDesign.MDI_COMMENT_ACCOUNT, Constants.UI_ICON_SIZE_IN_TREE)); return panel; } @@ -1318,10 +1262,7 @@ else if (treeNode.isMention()) { return this.handleMention(panel, mainLabel, treeNode.getFeatureStructure()); } else if (getDocumentModel() != null && getDocumentModel().getCoreferenceModel() != null && treeNode == tree.getModel().getRoot()) - mainLabel.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT_PLUS)); - else if (getDocumentModel() != null && getDocumentModel().getCoreferenceModel() != null - && treeNode.getFeatureStructure() instanceof DetachedMentionPart) - mainLabel.setIcon(FontIcon.of(MaterialDesign.MDI_TREE)); + mainLabel.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT_PLUS, Constants.UI_ICON_SIZE_IN_TREE)); return panel; } @@ -1348,11 +1289,11 @@ public Icon getOpenIcon() { } public Icon getMentionIcon() { - return FontIcon.of(MaterialDesign.MDI_COMMENT_ACCOUNT); + return FontIcon.of(MaterialDesign.MDI_COMMENT_ACCOUNT, Constants.UI_ICON_SIZE_IN_TREE); } public Icon getEntityIcon() { - return FontIcon.of(MaterialDesign.MDI_ACCOUNT); + return FontIcon.of(MaterialDesign.MDI_ACCOUNT, Constants.UI_ICON_SIZE_IN_TREE); } } @@ -1366,9 +1307,9 @@ public void keyTyped(KeyEvent e) { if (cModel.getKeyMap().containsKey(e.getKeyChar())) { e.consume(); if (Annotator.app.getPreferences().getBoolean(Constants.CFG_REPLACE_MENTION, false) - && getSelectedAnnotations(Mention.class).size() == 1) { - getDocumentModel().edit(new MoveMentionsToEntity(cModel.getKeyMap().get(e.getKeyChar()), - getSelectedAnnotations(Mention.class))); + && getSelectedMentions().size() == 1) { + getDocumentModel().edit( + new MoveMentionsToEntity(cModel.getKeyMap().get(e.getKeyChar()), getSelectedMentions())); } else { getDocumentModel() .edit(new AddMentionsToEntity(cModel.getKeyMap().get(e.getKeyChar()), getSelection())); @@ -1408,9 +1349,9 @@ public int getSourceActions(JComponent comp) { public Transferable createTransferable(JComponent comp) { JTextComponent t = (JTextComponent) comp; if (Annotator.app.getPreferences().getBoolean(Constants.CFG_REPLACE_MENTION, false) - && getSelectedAnnotations(Mention.class).size() == 1) { - Mention mention = getSelectedAnnotations(Mention.class).getOnly(); - return new AnnotationTransfer(mention, getDocumentModel().getTreeModel().get(mention)); + && getSelectedMentions().size() == 1) { + Mention mention = getSelectedMentions().getOnly(); + return new MentionTransfer(getDocumentModel().getTreeModel().get(mention), mention); } else return new PotentialAnnotationTransfer(textPane, t.getSelectionStart(), t.getSelectionEnd()); } @@ -1420,18 +1361,11 @@ public boolean canImport(TransferHandler.TransferSupport info) { if (info.isDataFlavorSupported(PotentialAnnotationTransfer.dataFlavor)) { JTextComponent.DropLocation dl = (javax.swing.text.JTextComponent.DropLocation) info.getDropLocation(); - Collection mentions = getDocumentModel().getCoreferenceModel().getMentions(dl.getIndex()); + Collection mentions = getDocumentModel().getCoreferenceModel().getMentions(dl.getIndex()); if (mentions.size() > 0) return true; - } else if (info.isDataFlavorSupported(AnnotationTransfer.dataFlavor)) { - try { - @SuppressWarnings("unchecked") - ImmutableList annoList = (ImmutableList) info.getTransferable() - .getTransferData(AnnotationTransfer.dataFlavor); - return annoList.anySatisfy(a -> a instanceof Mention); - } catch (UnsupportedFlavorException | IOException e) { - return false; - } + } else if (info.isDataFlavorSupported(MentionTransfer.dataFlavor)) { + return true; } return false; } @@ -1442,11 +1376,11 @@ public boolean importData(TransferHandler.TransferSupport info) { return false; } JTextComponent.DropLocation dl = (javax.swing.text.JTextComponent.DropLocation) info.getDropLocation(); - Collection mentions = getDocumentModel().getCoreferenceModel().getMentions(dl.getIndex()); - for (Annotation a : mentions) { + Collection mentions = getDocumentModel().getCoreferenceModel().getMentions(dl.getIndex()); + for (Mention a : mentions) { if (a instanceof Mention) { try { - Mention m = (Mention) a; + Mention m = a; Transferable pat = info.getTransferable(); if (info.isDataFlavorSupported(PotentialAnnotationTransfer.dataFlavor)) { @SuppressWarnings("unchecked") @@ -1597,22 +1531,16 @@ public void popupMenuWillBecomeVisible(PopupMenuEvent e) { exportActions.add(new ExampleExport(DocumentWindow.this, ExampleExport.Format.PLAINTEXT)); } - MutableSet localAnnotations = Sets.mutable + MutableSet mentions = Sets.mutable .withAll(getDocumentModel().getCoreferenceModel().getMentions(offset)); if (selection) for (int i = textPane.getSelectionStart(); i <= textPane.getSelectionEnd(); i++) - localAnnotations.addAll(getDocumentModel().getCoreferenceModel().getMentions(i)); + mentions.addAll(getDocumentModel().getCoreferenceModel().getMentions(i)); - MutableSet mentions = localAnnotations - .select(m -> m instanceof Mention || m instanceof DetachedMentionPart); - - for (Annotation anno : mentions) { + for (Mention anno : mentions) { if (anno instanceof Mention) - mentionActions.add(this.getMentionItem((Mention) anno, ((Mention) anno).getDiscontinuous())); - else if (anno instanceof DetachedMentionPart) - mentionActions - .add(getMentionItem(((DetachedMentionPart) anno).getMention(), (DetachedMentionPart) anno)); + mentionActions.add(this.getMentionItem(anno)); } Set candidates = Sets.mutable.empty(); @@ -1636,9 +1564,10 @@ else if (anno instanceof DetachedMentionPart) @Override public void actionPerformed(ActionEvent e) { if (Annotator.app.getPreferences().getBoolean(Constants.CFG_REPLACE_MENTION, false) - && getSelectedAnnotations(Mention.class).size() == 1) { - getDocumentModel().edit( - new MoveMentionsToEntity(entity, getSelectedAnnotations(Mention.class))); + && getSelectedAnnotations(MentionSurface.class).size() == 1) { + getDocumentModel().edit(new MoveMentionsToEntity(entity, + getSelectedAnnotations(MentionSurface.class) + .collect(ms -> ms.getMention()))); } else { getDocumentModel().edit(new AddMentionsToEntity(entity, getSelection())); } @@ -1677,15 +1606,13 @@ public void popupMenuCanceled(PopupMenuEvent e) { } - protected JMenu getMentionItem(Mention m, DetachedMentionPart dmp) { + protected JMenu getMentionItem(Mention m) { StringBuilder b = new StringBuilder(); b.append(m.getAddress()); - String surf = m.getCoveredText(); + String surf = UimaUtil.getCoveredText(m); surf = StringUtils.abbreviateMiddle(surf, "...", 20); - if (dmp != null) - surf += " [,] " + dmp.getCoveredText(); if (m.getEntity().getLabel() != null) b.append(": ") .append(StringUtils.abbreviateMiddle( @@ -1698,6 +1625,12 @@ protected JMenu getMentionItem(Mention m, DetachedMentionPart dmp) { mentionMenu.add('"' + surf + '"'); mentionMenu.add(a); mentionMenu.add(new DeleteAction(DocumentWindow.this, m)); + if (m.getSurface().size() > 0) + for (MentionSurface ms : m.getSurface()) { + JMenu mentionSurfaceMenu = new JMenu(StringUtils.abbreviateMiddle(ms.getCoveredText(), "...", 20)); + mentionSurfaceMenu.add(new DeleteAction(DocumentWindow.this, ms)); + mentionMenu.add(mentionSurfaceMenu); + } return mentionMenu; } @@ -1722,12 +1655,14 @@ public void valueChanged(TreeSelectionEvent e) { actions.entityStatisticsAction.setEnabled(tsu.isEntity()); - if (tsu.isSingle() && (tsu.isMention() || tsu.isDetachedMentionPart())) - annotationSelected(tsu.getAnnotation(0)); + if (tsu.isSingle() && tsu.isMention()) + annotationSelected(tsu.getMention(0).getSurface(0)); else if (tsu.isSingle() && tsu.isEntity()) { highlightManager.unHighlight(); - getDocumentModel().getCoreferenceModel().getMentions(tsu.getEntity(0)) - .forEach(m -> highlightManager.highlight(m, new Color(255, 255, 150))); + getDocumentModel().getCoreferenceModel().getMentions(tsu.getEntity(0)).forEach(m -> { + for (MentionSurface ms : m.getSurface()) + highlightManager.highlight(ms, new Color(255, 255, 150)); + }); } else annotationSelected(null); } @@ -1828,7 +1763,7 @@ public void setFile(File file) { } class ActionContainer { - + AnalyzeAction analyze = new AnalyzeAction(DocumentWindow.this); MergeAdjacentMentions mergeMentions = new MergeAdjacentMentions(DocumentWindow.this); ClearAction clearAction = new ClearAction(DocumentWindow.this); AbstractAction closeAction = new de.unistuttgart.ims.coref.annotator.action.CloseAction(); @@ -1847,6 +1782,7 @@ class ActionContainer { AbstractAction showDocumentStatistics = new ShowDocumentStatistics(DocumentWindow.this); SortTree sortByAlpha; SortTree sortByMentions; + SortTree sortByPosition; SortTree sortByLastModified; ToggleEntitySortOrder sortDescending = new ToggleEntitySortOrder(DocumentWindow.this); FormEntityGroup formGroupAction = new FormEntityGroup(DocumentWindow.this); @@ -1983,4 +1919,18 @@ public void windowClosed(WindowEvent e) { } } + + /** + * @return the proposedFilename + */ + public String getProposedFilename() { + return proposedFilename; + } + + /** + * @param proposedFilename the proposedFilename to set + */ + public void setProposedFilename(String proposedFilename) { + this.proposedFilename = proposedFilename; + } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/EntitySortOrder.java b/src/main/java/de/unistuttgart/ims/coref/annotator/EntitySortOrder.java index ffa081de..7d29af9c 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/EntitySortOrder.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/EntitySortOrder.java @@ -2,8 +2,10 @@ import java.util.Comparator; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; + public enum EntitySortOrder { - Mentions, Alphabet, LastModified, None; + Mentions, Alphabet, LastModified, Position, None; public boolean descending = true; @@ -21,6 +23,17 @@ public int compare(CATreeNode o1, CATreeNode o2) { return 0; } }; + case Position: + return new Comparator() { + @Override + public int compare(CATreeNode o1, CATreeNode o2) { + Mention m1 = o1.getChildAt(0).getFeatureStructure(); + Mention m2 = o2.getChildAt(0).getFeatureStructure(); + int l1 = m1.getSurface(0).getBegin(); + int l2 = m2.getSurface(0).getBegin(); + return (isDescending() ? -1 : 1) * Integer.compare(l1, l2); + } + }; case Mentions: return new Comparator() { @Override diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/ExtensionFilters.java b/src/main/java/de/unistuttgart/ims/coref/annotator/ExtensionFilters.java index a84dcfb4..bde50ae1 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/ExtensionFilters.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/ExtensionFilters.java @@ -10,5 +10,6 @@ public class ExtensionFilters { static public ExtensionFilter tei = new ExtensionFilter("TEI", "*.xml", "*.tei"); static public ExtensionFilter json = new ExtensionFilter("JSON", "*.json"); static public ExtensionFilter csv = new ExtensionFilter("CSV", "*.csv"); + static public ExtensionFilter ca2 = new ExtensionFilter("CorefAnnotator", "*.ca2", "*.ca2z"); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/FileFilters.java b/src/main/java/de/unistuttgart/ims/coref/annotator/FileFilters.java index 6aeeba1b..d7226ca7 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/FileFilters.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/FileFilters.java @@ -5,6 +5,18 @@ import javax.swing.filechooser.FileFilter; public class FileFilters { + static public FileFilter ca2 = new FileFilter() { + + @Override + public boolean accept(File f) { + return f.isDirectory() || f.getName().endsWith(".ca2") || f.getName().endsWith(".ca2z"); + } + + @Override + public String getDescription() { + return "CorefAnnotator"; + } + }; static public FileFilter xmi = new FileFilter() { @Override diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/FlagEditor.java b/src/main/java/de/unistuttgart/ims/coref/annotator/FlagEditor.java index f50df1e6..3db4b42a 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/FlagEditor.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/FlagEditor.java @@ -4,13 +4,11 @@ import java.awt.Color; import java.awt.Component; import java.awt.Frame; -import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.AbstractAction; -import javax.swing.Action; import javax.swing.DefaultCellEditor; import javax.swing.DefaultListCellRenderer; import javax.swing.JButton; @@ -35,13 +33,11 @@ import de.unistuttgart.ims.coref.annotator.action.CloseAction; import de.unistuttgart.ims.coref.annotator.action.DeleteFlagAction; import de.unistuttgart.ims.coref.annotator.action.UndoAction; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.comp.DefaultTableHeaderCellRenderer; import de.unistuttgart.ims.coref.annotator.document.DocumentModel; import de.unistuttgart.ims.coref.annotator.document.FlagTableModel; -import de.unistuttgart.ims.coref.annotator.document.op.AddFlag; public class FlagEditor extends AbstractWindow { @@ -72,7 +68,6 @@ protected void initializeWindow() { JComboBox> combobox = new JComboBox>(); combobox.addItem(Mention.class); combobox.addItem(Entity.class); - combobox.addItem(DetachedMentionPart.class); combobox.setRenderer(new TargetClassListCellRenderer()); JComboBox iconBox = new JComboBox(); @@ -104,13 +99,6 @@ protected void initializeWindow() { flagMenu.add(new JMenuItem(addEntityFlagAction)); flagMenu.add(new JMenuItem(addMentionFlagAction)); flagMenu.add(new JMenuItem(deleteFlagAction)); - flagMenu.addSeparator(); - flagMenu.add(new JMenuItem(new CreateFlagsFromCollections(Constants.FLAG_COLLECTION_1, - Annotator.getString(Strings.FLAG_EDITOR_FLAG_COLLECTION_1), - Annotator.getString(Strings.FLAG_EDITOR_FLAG_COLLECTION_1_TOOLTIP)))); - flagMenu.add(new JMenuItem(new CreateFlagsFromCollections(Constants.FLAG_COLLECTION_2, - Annotator.getString(Strings.FLAG_EDITOR_FLAG_COLLECTION_2), - Annotator.getString(Strings.FLAG_EDITOR_FLAG_COLLECTION_2_TOOLTIP)))); JMenu helpMenu = new JMenu(Annotator.getString(Strings.MENU_HELP)); helpMenu.add(Annotator.app.helpAction); @@ -224,7 +212,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole int row, int column) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (value != null) - setIcon(FontIcon.of((Ikon) value)); + setIcon(FontIcon.of((Ikon) value, Constants.UI_ICON_SIZE_IN_TREE)); return this; } @@ -239,7 +227,7 @@ public Component getListCellRendererComponent(JList list, Object value, int i boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value != null) - setIcon(FontIcon.of((Ikon) value)); + setIcon(FontIcon.of((Ikon) value, Constants.UI_ICON_SIZE_IN_TREE)); return this; } @@ -294,23 +282,8 @@ class MyHeaderRenderer extends DefaultTableHeaderCellRenderer { } - class CreateFlagsFromCollections extends AbstractAction { - private static final long serialVersionUID = 1L; - AddFlag[] flagCollection; - - public CreateFlagsFromCollections(AddFlag[] flagCollection, String label, String tooltip) { - super(label, FontIcon.of(MaterialDesign.MDI_FOLDER)); - this.flagCollection = flagCollection; - putValue(Action.SHORT_DESCRIPTION, tooltip); - - } - - @Override - public void actionPerformed(ActionEvent e) { - for (AddFlag af : flagCollection) { - documentModel.edit(af); - } - } - + @Override + public DocumentModel getDocumentModel() { + return documentModel; } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/HelpWindow.java b/src/main/java/de/unistuttgart/ims/coref/annotator/HelpWindow.java index c5a7df2c..129fffef 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/HelpWindow.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/HelpWindow.java @@ -37,6 +37,9 @@ public static class Topic { public static final HelpTopic FLAGS = topics[4]; public static final HelpTopic IO = topics[5]; public static final HelpTopic SEARCH = topics[6]; + public static final HelpTopic PREFERENCES = topics[7]; + public static final HelpTopic PROFILE = topics[8]; + public static final HelpTopic WHATSNEW = topics[9]; } private static final long serialVersionUID = 1L; @@ -46,7 +49,8 @@ public static class Topic { new HelpTopic("How to annotate", "howto"), new HelpTopic("Compare annotations", "compare"), new HelpTopic("Automatic processing", "processing"), new HelpTopic("Flag editing", "flags"), new HelpTopic("Input/Output", "io", s -> new JScrollPane(loadIOPlugins())), - new HelpTopic("Search", "search") }; + new HelpTopic("Search", "search"), new HelpTopic("Preferences", "preferences"), + new HelpTopic("Profiles", "profile"), new HelpTopic("What's new?", "whatsnew") }; JList topicList; @@ -80,7 +84,7 @@ public void valueChanged(ListSelectionEvent e) { } - protected static JEditorPane load(String path) { + protected static Component load(String path) { JEditorPane textArea; try { if (!path.endsWith(".html")) @@ -107,7 +111,7 @@ public void hyperlinkUpdate(HyperlinkEvent e) { } } }); - return textArea; + return new JScrollPane(textArea); } catch (IOException e) { Annotator.logger.catching(e); } @@ -159,7 +163,7 @@ public static HelpWindow show(HelpTopic topic) { hw.topicList.setSelectedIndex(0); else for (int i = 0; i < topics.length; i++) - if (topics[i].getTitle().equalsIgnoreCase(topic.getKey())) + if (topics[i].getKey().equalsIgnoreCase(topic.getKey())) hw.topicList.setSelectedIndex(i); return hw; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/HighlightManager.java b/src/main/java/de/unistuttgart/ims/coref/annotator/HighlightManager.java index f06350bb..ad66fcde 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/HighlightManager.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/HighlightManager.java @@ -10,16 +10,14 @@ import javax.swing.text.JTextComponent; import javax.swing.text.LayeredHighlighter; -import org.apache.uima.fit.util.JCasUtil; -import org.apache.uima.jcas.JCas; import org.apache.uima.jcas.tcas.Annotation; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.coref.annotator.document.DocumentModel; class HighlightManager { - Map underlineMap = new HashMap(); + Map underlineMap = new HashMap(); Map highlightMap = new HashMap(); DefaultHighlighter hilit; @@ -34,17 +32,10 @@ public HighlightManager(JTextComponent component) { textComponent.setHighlighter(hilit); } - @Deprecated - public void clearAndDrawAllAnnotations(JCas jcas) { + public void clearAllAnnotations() { hilit.removeAllHighlights(); underlineMap.clear(); spanCounter.clear(); - for (Mention m : JCasUtil.select(jcas, Mention.class)) { - highlight(m, new Color(m.getEntity().getColor()), false, false, null); - if (m.getDiscontinuous() != null) - highlight(m.getDiscontinuous(), new Color(m.getEntity().getColor()), true, false, null); - - } textComponent.repaint(); } @@ -101,19 +92,6 @@ public void highlight(Annotation a, Color c) { highlight(a, c, false, false, new DefaultHighlighter.DefaultHighlightPainter(c)); } - public void underline(Annotation a) { - if (a instanceof Mention) - underline((Mention) a); - else if (a instanceof DetachedMentionPart) - underline((DetachedMentionPart) a); - } - - public void underline(DetachedMentionPart dmp) { - hilit.setDrawsLayeredHighlights(true); - underline(dmp, new Color(dmp.getMention().getEntity().getColor()), true, true); - hilit.setDrawsLayeredHighlights(false); - } - public void underline(Mention m) { hilit.setDrawsLayeredHighlights(true); Color color = new Color(m.getEntity().getColor()); @@ -125,35 +103,21 @@ public void underline(Mention m) { dotted = false; } } - underline(m, color, dotted, true); - if (m.getDiscontinuous() != null) - underline(m.getDiscontinuous(), new Color(m.getEntity().getColor()), true, true); + for (MentionSurface ms : m.getSurface()) + underline(ms, color, dotted, true); hilit.setDrawsLayeredHighlights(false); } public void underline(Annotation m, Color color) { - if (m instanceof Mention) - underline((Mention) m, color); - else { - hilit.setDrawsLayeredHighlights(true); - underline(m, color, false, true); - hilit.setDrawsLayeredHighlights(false); - } - } - - public void underline(Mention m, Color color) { hilit.setDrawsLayeredHighlights(true); underline(m, color, false, true); - if (m.getDiscontinuous() != null) - underline(m.getDiscontinuous(), color, true, true); hilit.setDrawsLayeredHighlights(false); } - public void underline(Mention m, boolean repaint) { + public void underline(Mention m, Color color) { hilit.setDrawsLayeredHighlights(true); - underline(m, new Color(m.getEntity().getColor()), false, false); - if (m.getDiscontinuous() != null) - underline(m.getDiscontinuous(), new Color(m.getEntity().getColor()), true, false); + for (MentionSurface ms : m.getSurface()) + underline(ms, color, false, false); hilit.setDrawsLayeredHighlights(false); } @@ -167,6 +131,11 @@ public void unUnderline(Annotation a) { } + public void unUnderline(Mention a) { + for (MentionSurface ms : a.getSurface()) + unUnderline(ms); + } + public void unHighlight() { highlightMap.values().forEach(o -> hilit.removeHighlight(o)); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/MentionTransfer.java b/src/main/java/de/unistuttgart/ims/coref/annotator/MentionTransfer.java new file mode 100644 index 00000000..8456dcb9 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/MentionTransfer.java @@ -0,0 +1,51 @@ +package de.unistuttgart.ims.coref.annotator; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.impl.factory.Lists; + +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; + +public class MentionTransfer implements Transferable { + public static DataFlavor dataFlavor = new DataFlavor(MentionTransfer.class, "Mention"); + + CATreeNode treeNode; + ImmutableList mentions; + + public MentionTransfer(CATreeNode tn, Mention... mention) { + this.treeNode = tn; + this.mentions = Lists.immutable.of(mention); + } + + public MentionTransfer(CATreeNode tn, Iterable mentions) { + this.treeNode = tn; + this.mentions = Lists.immutable.ofAll(mentions); + } + + public MentionTransfer(Iterable mentions) { + this.mentions = Lists.immutable.ofAll(mentions); + } + + @Override + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { dataFlavor }; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor == dataFlavor; + } + + @Override + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + return mentions; + } + + public CATreeNode getTreeNode() { + return treeNode; + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/PluginManager.java b/src/main/java/de/unistuttgart/ims/coref/annotator/PluginManager.java index c9b5385f..a27e3363 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/PluginManager.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/PluginManager.java @@ -4,7 +4,7 @@ import java.util.HashMap; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.eclipse.collections.api.set.ImmutableSet; import org.eclipse.collections.api.set.MutableSet; import org.eclipse.collections.impl.factory.Sets; @@ -79,7 +79,7 @@ public T getPlugin(Class cl) { if (!instances.containsKey(cl)) { T p; try { - Annotator.logger.info("Creating new instance of plugin {}", cl.getName()); + Annotator.logger.debug("Creating new instance of {}", cl.getSimpleName()); p = cl.getDeclaredConstructor().newInstance(); instances.put(cl, p); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/RangedHashSetValuedHashMap.java b/src/main/java/de/unistuttgart/ims/coref/annotator/RangedHashSetValuedHashMap.java index 3381fdbf..12b26c78 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/RangedHashSetValuedHashMap.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/RangedHashSetValuedHashMap.java @@ -40,258 +40,573 @@ public void remove(V value) { remove(i, value); } + /** + * @param keyValuePair + * @return + * @see org.eclipse.collections.api.multimap.MutableMultimap#add(org.eclipse.collections.api.tuple.Pair) + */ @Override - public boolean remove(Object key, Object value) { - return map.remove(key, value); + public boolean add(Pair keyValuePair) { + return map.add(keyValuePair); + } + + /** + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#asSynchronized() + */ + @Override + public MutableSetMultimap asSynchronized() { + return map.asSynchronized(); } + /** + * + * @see org.eclipse.collections.api.multimap.MutableMultimap#clear() + */ @Override public void clear() { map.clear(); } + /** + * @param + * @param + * @param + * @param keyFunction + * @param valueFunction + * @param target + * @return + * @see org.eclipse.collections.api.multimap.Multimap#collectKeyMultiValues(org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.multimap.MutableMultimap) + */ + @Override + public > R collectKeyMultiValues( + Function keyFunction, Function valueFunction, + R target) { + return map.collectKeyMultiValues(keyFunction, valueFunction, target); + } + + /** + * @param + * @param + * @param keyFunction + * @param valueFunction + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#collectKeyMultiValues(org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.block.function.Function) + */ + @Override + public MutableBagMultimap collectKeyMultiValues( + Function keyFunction, Function valueFunction) { + return map.collectKeyMultiValues(keyFunction, valueFunction); + } + + /** + * @param + * @param + * @param + * @param function + * @param target + * @return + * @see org.eclipse.collections.api.multimap.Multimap#collectKeysValues(org.eclipse.collections.api.block.function.Function2, + * org.eclipse.collections.api.multimap.MutableMultimap) + */ @Override - public boolean isEmpty() { - return map.isEmpty(); + public > R collectKeysValues( + Function2> function, R target) { + return map.collectKeysValues(function, target); } + /** + * @param + * @param + * @param function + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#collectKeysValues(org.eclipse.collections.api.block.function.Function2) + */ @Override - public boolean notEmpty() { - return map.notEmpty(); + public MutableBagMultimap collectKeysValues( + Function2> function) { + return map.collectKeysValues(function); } + /** + * @param + * @param + * @param function + * @param target + * @return + * @see org.eclipse.collections.api.multimap.Multimap#collectValues(org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.multimap.MutableMultimap) + */ @Override - public int size() { - return map.size(); + public > R collectValues(Function function, + R target) { + return map.collectValues(function, target); } + /** + * @param + * @param function + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#collectValues(org.eclipse.collections.api.block.function.Function) + */ @Override - public int sizeDistinct() { - return map.sizeDistinct(); + public MutableBagMultimap collectValues(Function function) { + return map.collectValues(function); } + /** + * @param key + * @return + * @see org.eclipse.collections.api.multimap.Multimap#containsKey(java.lang.Object) + */ @Override public boolean containsKey(Object key) { return map.containsKey(key); } + /** + * @param key + * @param value + * @return + * @see org.eclipse.collections.api.multimap.Multimap#containsKeyAndValue(java.lang.Object, + * java.lang.Object) + */ @Override - public boolean containsValue(Object value) { - return map.containsValue(value); + public boolean containsKeyAndValue(Object key, Object value) { + return map.containsKeyAndValue(key, value); } + /** + * @param value + * @return + * @see org.eclipse.collections.api.multimap.Multimap#containsValue(java.lang.Object) + */ @Override - public boolean containsKeyAndValue(Object key, Object value) { - return map.containsKeyAndValue(key, value); + public boolean containsValue(Object value) { + return map.containsValue(value); } + /** + * @param obj + * @return + * @see org.eclipse.collections.api.multimap.Multimap#equals(java.lang.Object) + */ @Override public boolean equals(Object obj) { return map.equals(obj); } + /** + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#flip() + */ @Override - public int hashCode() { - return map.hashCode(); + public MutableSetMultimap flip() { + return map.flip(); } + /** + * @param procedure + * @see org.eclipse.collections.api.multimap.Multimap#forEachKey(org.eclipse.collections.api.block.procedure.Procedure) + */ @Override - public MutableSetMultimap flip() { - return map.flip(); + public void forEachKey(Procedure procedure) { + map.forEachKey(procedure); } + /** + * @param procedure + * @see org.eclipse.collections.api.multimap.Multimap#forEachKeyMultiValues(org.eclipse.collections.api.block.procedure.Procedure2) + */ @Override - public MutableSet replaceValues(Integer key, Iterable values) { - return map.replaceValues(key, values); + public void forEachKeyMultiValues(Procedure2> procedure) { + map.forEachKeyMultiValues(procedure); } + /** + * @param procedure + * @see org.eclipse.collections.api.multimap.Multimap#forEachKeyValue(org.eclipse.collections.api.block.procedure.Procedure2) + */ @Override - public MutableSetMultimap toMutable() { - return map.toMutable(); + public void forEachKeyValue(Procedure2 procedure) { + map.forEachKeyValue(procedure); } + /** + * @param procedure + * @see org.eclipse.collections.api.multimap.Multimap#forEachValue(org.eclipse.collections.api.block.procedure.Procedure) + */ @Override - public MutableSet removeAll(Object key) { - return map.removeAll(key); + public void forEachValue(Procedure procedure) { + map.forEachValue(procedure); } + /** + * @param key + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#get(java.lang.Object) + */ @Override - public ImmutableSetMultimap toImmutable() { - return map.toImmutable(); + public MutableSet get(Integer key) { + return map.get(key); } + /** + * @param key + * @param values + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#getIfAbsentPutAll(java.lang.Object, + * java.lang.Iterable) + */ @Override - public boolean put(Integer key, V value) { - return map.put(key, value); + public MutableSet getIfAbsentPutAll(Integer key, Iterable values) { + return map.getIfAbsentPutAll(key, values); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#hashCode() + */ @Override - public MutableSetMultimap newEmpty() { - return map.newEmpty(); + public int hashCode() { + return map.hashCode(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#isEmpty() + */ @Override - public MutableSet get(Integer key) { - return map.get(key); + public boolean isEmpty() { + return map.isEmpty(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#keyBag() + */ @Override - public MutableSetMultimap selectKeysValues(Predicate2 predicate) { - return map.selectKeysValues(predicate); + public Bag keyBag() { + return map.keyBag(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#keyMultiValuePairsView() + */ @Override - public MutableSetMultimap rejectKeysValues(Predicate2 predicate) { - return map.rejectKeysValues(predicate); + public RichIterable>> keyMultiValuePairsView() { + return map.keyMultiValuePairsView(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#keySet() + */ @Override - public MutableSetMultimap selectKeysMultiValues( - Predicate2> predicate) { - return map.selectKeysMultiValues(predicate); + public SetIterable keySet() { + return map.keySet(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#keyValuePairsView() + */ @Override - public boolean putAllPairs(@SuppressWarnings("unchecked") Pair... pairs) { - return map.putAllPairs(pairs); + public RichIterable> keyValuePairsView() { + return map.keyValuePairsView(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#keysView() + */ @Override - public MutableSetMultimap rejectKeysMultiValues( - Predicate2> predicate) { - return map.rejectKeysMultiValues(predicate); + public RichIterable keysView() { + return map.keysView(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#multiValuesView() + */ @Override - public MutableBagMultimap collectKeysValues( - Function2> function) { - return map.collectKeysValues(function); + public RichIterable> multiValuesView() { + return map.multiValuesView(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#newEmpty() + */ @Override - public boolean putAllPairs(Iterable> pairs) { - return map.putAllPairs(pairs); + public MutableSetMultimap newEmpty() { + return map.newEmpty(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#notEmpty() + */ @Override - public MutableBagMultimap collectValues(Function function) { - return map.collectValues(function); + public boolean notEmpty() { + return map.notEmpty(); } + /** + * @param key + * @param value + * @return + * @see org.eclipse.collections.api.multimap.MutableMultimap#put(java.lang.Object, + * java.lang.Object) + */ @Override - public MutableSetMultimap asSynchronized() { - return map.asSynchronized(); + public boolean put(Integer key, V value) { + return map.put(key, value); } + /** + * @param key + * @param values + * @return + * @see org.eclipse.collections.api.multimap.MutableMultimap#putAll(java.lang.Object, + * java.lang.Iterable) + */ @Override public boolean putAll(Integer key, Iterable values) { return map.putAll(key, values); } + /** + * @param + * @param + * @param multimap + * @return + * @see org.eclipse.collections.api.multimap.MutableMultimap#putAll(org.eclipse.collections.api.multimap.Multimap) + */ @Override public boolean putAll(Multimap multimap) { return map.putAll(multimap); } + /** + * @param pairs + * @return + * @see org.eclipse.collections.api.multimap.MutableMultimap#putAllPairs(java.lang.Iterable) + */ @Override - public void forEachValue(Procedure procedure) { - map.forEachValue(procedure); + public boolean putAllPairs(Iterable> pairs) { + return map.putAllPairs(pairs); } + /** + * @param pairs + * @return + * @see org.eclipse.collections.api.multimap.MutableMultimap#putAllPairs(org.eclipse.collections.api.tuple.Pair[]) + */ @Override - public void forEachKey(Procedure procedure) { - map.forEachKey(procedure); + public boolean putAllPairs(Pair... pairs) { + return map.putAllPairs(pairs); } + /** + * @param + * @param predicate + * @param target + * @return + * @see org.eclipse.collections.api.multimap.Multimap#rejectKeysMultiValues(org.eclipse.collections.api.block.predicate.Predicate2, + * org.eclipse.collections.api.multimap.MutableMultimap) + */ @Override - public void forEachKeyValue(Procedure2 procedure) { - map.forEachKeyValue(procedure); + public > R rejectKeysMultiValues( + Predicate2> predicate, R target) { + return map.rejectKeysMultiValues(predicate, target); } + /** + * @param predicate + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#rejectKeysMultiValues(org.eclipse.collections.api.block.predicate.Predicate2) + */ @Override - public void forEachKeyMultiValues(Procedure2> procedure) { - map.forEachKeyMultiValues(procedure); + public MutableSetMultimap rejectKeysMultiValues( + Predicate2> predicate) { + return map.rejectKeysMultiValues(predicate); } + /** + * @param + * @param predicate + * @param target + * @return + * @see org.eclipse.collections.api.multimap.Multimap#rejectKeysValues(org.eclipse.collections.api.block.predicate.Predicate2, + * org.eclipse.collections.api.multimap.MutableMultimap) + */ @Override - public RichIterable keysView() { - return map.keysView(); + public > R rejectKeysValues(Predicate2 predicate, + R target) { + return map.rejectKeysValues(predicate, target); } + /** + * @param predicate + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#rejectKeysValues(org.eclipse.collections.api.block.predicate.Predicate2) + */ @Override - public SetIterable keySet() { - return map.keySet(); + public MutableSetMultimap rejectKeysValues(Predicate2 predicate) { + return map.rejectKeysValues(predicate); } + /** + * @param key + * @param value + * @return + * @see org.eclipse.collections.api.multimap.MutableMultimap#remove(java.lang.Object, + * java.lang.Object) + */ @Override - public Bag keyBag() { - return map.keyBag(); + public boolean remove(Object key, Object value) { + return map.remove(key, value); } + /** + * @param key + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#removeAll(java.lang.Object) + */ @Override - public RichIterable> multiValuesView() { - return map.multiValuesView(); + public MutableSet removeAll(Object key) { + return map.removeAll(key); } + /** + * @param key + * @param values + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#replaceValues(java.lang.Object, + * java.lang.Iterable) + */ @Override - public RichIterable valuesView() { - return map.valuesView(); + public MutableSet replaceValues(Integer key, Iterable values) { + return map.replaceValues(key, values); } + /** + * @param + * @param predicate + * @param target + * @return + * @see org.eclipse.collections.api.multimap.Multimap#selectKeysMultiValues(org.eclipse.collections.api.block.predicate.Predicate2, + * org.eclipse.collections.api.multimap.MutableMultimap) + */ @Override - public RichIterable>> keyMultiValuePairsView() { - return map.keyMultiValuePairsView(); + public > R selectKeysMultiValues( + Predicate2> predicate, R target) { + return map.selectKeysMultiValues(predicate, target); } + /** + * @param predicate + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#selectKeysMultiValues(org.eclipse.collections.api.block.predicate.Predicate2) + */ @Override - public RichIterable> keyValuePairsView() { - return map.keyValuePairsView(); + public MutableSetMultimap selectKeysMultiValues( + Predicate2> predicate) { + return map.selectKeysMultiValues(predicate); } + /** + * @param + * @param predicate + * @param target + * @return + * @see org.eclipse.collections.api.multimap.Multimap#selectKeysValues(org.eclipse.collections.api.block.predicate.Predicate2, + * org.eclipse.collections.api.multimap.MutableMultimap) + */ @Override - public MutableMap> toMap() { - return map.toMap(); + public > R selectKeysValues(Predicate2 predicate, + R target) { + return map.selectKeysValues(predicate, target); } + /** + * @param predicate + * @return + * @see org.eclipse.collections.api.multimap.set.MutableSetMultimap#selectKeysValues(org.eclipse.collections.api.block.predicate.Predicate2) + */ @Override - public > MutableMap toMap(Function0 collectionFactory) { - return map.toMap(collectionFactory); + public MutableSetMultimap selectKeysValues(Predicate2 predicate) { + return map.selectKeysValues(predicate); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#size() + */ @Override - public > R selectKeysValues(Predicate2 predicate, - R target) { - return map.selectKeysValues(predicate, target); + public int size() { + return map.size(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#sizeDistinct() + */ @Override - public > R rejectKeysValues(Predicate2 predicate, - R target) { - return map.rejectKeysValues(predicate, target); + public int sizeDistinct() { + return map.sizeDistinct(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.set.UnsortedSetMultimap#toImmutable() + */ @Override - public > R selectKeysMultiValues( - Predicate2> predicate, R target) { - return map.selectKeysMultiValues(predicate, target); + public ImmutableSetMultimap toImmutable() { + return map.toImmutable(); } + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#toMap() + */ @Override - public > R rejectKeysMultiValues( - Predicate2> predicate, R target) { - return map.rejectKeysMultiValues(predicate, target); + public MutableMap> toMap() { + return map.toMap(); } + /** + * @param + * @param collectionFactory + * @return + * @see org.eclipse.collections.api.multimap.Multimap#toMap(org.eclipse.collections.api.block.function.Function0) + */ @Override - public > R collectKeysValues( - Function2> function, R target) { - return map.collectKeysValues(function, target); + public > MutableMap toMap(Function0 collectionFactory) { + return map.toMap(collectionFactory); } + /** + * @return + * @see org.eclipse.collections.api.multimap.set.UnsortedSetMultimap#toMutable() + */ @Override - public > R collectValues(Function function, - R target) { - return map.collectValues(function, target); + public MutableSetMultimap toMutable() { + return map.toMutable(); + } + + /** + * @return + * @see org.eclipse.collections.api.multimap.Multimap#valuesView() + */ + @Override + public RichIterable valuesView() { + return map.valuesView(); } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/SearchAnnotationPanel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/SearchAnnotationPanel.java index 542b8406..94af6af4 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/SearchAnnotationPanel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/SearchAnnotationPanel.java @@ -27,17 +27,18 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; import de.unistuttgart.ims.coref.annotator.action.IkonAction; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class SearchAnnotationPanel extends SearchPanel implements WindowListener { class SearchFlaggedMentions extends IkonAction { private static final long serialVersionUID = 1L; - String flag; + Flag flag; - public SearchFlaggedMentions(String s, String key, Ikon ik) { + public SearchFlaggedMentions(Flag s, String key, Ikon ik) { super(key, ik); this.flag = s; } @@ -47,10 +48,10 @@ public void actionPerformed(ActionEvent e) { clearResults(); JCas jcas = searchContainer.getDocumentWindow().getDocumentModel().getJcas(); for (Mention m : JCasUtil.select(jcas, Mention.class)) { - if (Util.isX(m, flag)) { + if (UimaUtil.isX(m, flag)) { listModel.addElement(new SearchResultMention(searchContainer, m)); try { - highlights.add(hilit.addHighlight(m.getBegin(), m.getEnd(), painter)); + highlights.add(hilit.addHighlight(UimaUtil.getBegin(m), UimaUtil.getEnd(m), painter)); } catch (BadLocationException e1) { e1.printStackTrace(); } @@ -105,7 +106,7 @@ public SearchAnnotationPanel(SearchContainer sd) { for (Flag flag : sd.getDocumentWindow().getDocumentModel().getFlagModel().getFlags()) { if (flag.getTargetClass().equalsIgnoreCase(Mention.class.getName())) { - AbstractAction action = new SearchFlaggedMentions(flag.getKey(), flag.getLabel(), + AbstractAction action = new SearchFlaggedMentions(flag, flag.getLabel(), MaterialDesign.valueOf(flag.getIcon())); JToggleButton b = new JToggleButton(action); bg.add(b); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/SearchResultMention.java b/src/main/java/de/unistuttgart/ims/coref/annotator/SearchResultMention.java index 6f255d1e..b4c057cb 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/SearchResultMention.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/SearchResultMention.java @@ -1,13 +1,14 @@ package de.unistuttgart.ims.coref.annotator; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; class SearchResultMention extends SearchResult { Mention mention; public SearchResultMention(SearchContainer c, Mention m) { - super(c, m.getBegin(), m.getEnd()); + super(c, UimaUtil.getBegin(m), UimaUtil.getEnd(m)); this.mention = m; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/SearchResultRenderer.java b/src/main/java/de/unistuttgart/ims/coref/annotator/SearchResultRenderer.java index 5ef22509..dde218da 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/SearchResultRenderer.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/SearchResultRenderer.java @@ -11,7 +11,7 @@ import org.apache.commons.lang3.StringUtils; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; class SearchResultRenderer implements ListCellRenderer { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/SearchTextPanel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/SearchTextPanel.java index 9e197eb3..b42452d2 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/SearchTextPanel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/SearchTextPanel.java @@ -39,10 +39,11 @@ import de.unistuttgart.ims.coref.annotator.action.HelpAction; import de.unistuttgart.ims.coref.annotator.action.IkonAction; import de.unistuttgart.ims.coref.annotator.action.TargetedOperationIkonAction; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.DocumentModel; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToEntity; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToNewEntity; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class SearchTextPanel extends SearchPanel implements DocumentListener, WindowListener, HasDocumentModel { @@ -98,9 +99,11 @@ public Transferable createTransferable(JComponent comp) { JList list = (JList) comp; if (Annotator.app.getPreferences().getBoolean(Constants.CFG_REPLACE_MENTION, false)) { - return new AnnotationTransfer(Lists.immutable.ofAll(list.getSelectedValuesList()) - .collect(sr -> sr.getSpan()).flatCollect(span -> searchContainer.getDocumentWindow() - .getDocumentModel().getCoreferenceModel().getMentionsBetween(span.begin, span.end))); + return new MentionTransfer( + Lists.immutable.ofAll(list.getSelectedValuesList()).collect(sr -> sr.getSpan()) + .flatCollect(span -> searchContainer.getDocumentWindow().getDocumentModel() + .getCoreferenceModel().getMentionsBetween(span.begin, span.end)) + .selectInstancesOf(Mention.class)); } else return new PotentialAnnotationTransfer(searchContainer.getDocumentWindow().getTextPane(), @@ -177,6 +180,7 @@ public void setTreeCondition(boolean treeCondition) { private static final long serialVersionUID = 1L; JTextField textField; JCheckBox restrictToMentions; + JCheckBox caseInsensitive; JList text_list; AbstractAction annotateSelectedFindings = new AnnotateSelectedFindings(), runSearch = new RunSearch(), annotateSelectedFindingsAsNew = new AnnotateSelectedFindingsAsNewEntity(); @@ -206,11 +210,25 @@ public void itemStateChanged(ItemEvent e) { } }); + + caseInsensitive = new JCheckBox(Annotator.getString(Strings.SEARCH_WINDOW_CASE_INSENSITIVE)); + caseInsensitive.setSelected(true); + caseInsensitive.setToolTipText(Annotator.getString(Strings.SEARCH_WINDOW_CASE_INSENSITIVE_TOOLTIP)); + caseInsensitive.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + search(textField.getText()); + } + + }); + JToolBar behaviourBar = new JToolBar(); behaviourBar.setFloatable(false); behaviourBar.add(runSearch); behaviourBar.add(new HelpAction(HelpWindow.Topic.SEARCH)); behaviourBar.add(restrictToMentions); + behaviourBar.add(caseInsensitive); JToolBar actionBar = new JToolBar(); actionBar.setLayout(new BoxLayout(actionBar, BoxLayout.Y_AXIS)); @@ -335,16 +353,18 @@ public void run() { annotateSelectedFindingsAsNew.setEnabled(false); clearResults(); if (searchString.length() > 0) { - Pattern p = Pattern.compile(searchString); + Pattern p = Pattern.compile(searchString, + (caseInsensitive.isSelected() ? Pattern.CASE_INSENSITIVE : 0)); if (restrictToMentions.isSelected()) { for (Mention m : searchContainer.getDocumentWindow().getDocumentModel().getCoreferenceModel() .getMentions()) { - Matcher matcher = p.matcher(m.getCoveredText()); + Matcher matcher = p.matcher(UimaUtil.getCoveredText(m)); if (matcher.find()) { try { - listModel.addElement(new SearchResult(searchContainer, m.getBegin(), m.getEnd())); - highlights.add(hilit.addHighlight(m.getBegin(), m.getEnd(), painter)); + listModel.addElement( + new SearchResult(searchContainer, UimaUtil.getBegin(m), UimaUtil.getEnd(m))); + highlights.add(hilit.addHighlight(UimaUtil.getBegin(m), UimaUtil.getEnd(m), painter)); } catch (BadLocationException e) { Annotator.logger.catching(e); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/Span.java b/src/main/java/de/unistuttgart/ims/coref/annotator/Span.java index d39b57c6..98371c59 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/Span.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/Span.java @@ -1,8 +1,10 @@ package de.unistuttgart.ims.coref.annotator; import org.apache.uima.jcas.tcas.Annotation; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.impl.factory.Lists; -import com.google.common.base.Objects; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class Span { @@ -22,7 +24,7 @@ public Span(int begin, int end) { @Override public int hashCode() { - return Objects.hashCode(this.begin, this.end); + return begin * 31 + end; } @Override @@ -43,4 +45,12 @@ public boolean contains(Span other) { return (other.begin >= begin && other.end <= end); } + public boolean contains(Spans other) { + return (other.getBegin() >= begin && other.getEnd() <= end); + } + + public static ImmutableList getSpans(Mention m) { + return Lists.immutable.withAll(m.getSurface()).collect(ms -> new Span(ms)); + } + } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/Spans.java b/src/main/java/de/unistuttgart/ims/coref/annotator/Spans.java new file mode 100644 index 00000000..a0a19a83 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/Spans.java @@ -0,0 +1,1181 @@ +package de.unistuttgart.ims.coref.annotator; + +import java.util.Collection; +import java.util.Comparator; +import java.util.DoubleSummaryStatistics; +import java.util.IntSummaryStatistics; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.LongSummaryStatistics; +import java.util.Map; +import java.util.Optional; +import java.util.Spliterator; +import java.util.concurrent.ExecutorService; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.Stream; + +import org.apache.uima.jcas.tcas.Annotation; +import org.eclipse.collections.api.LazyIterable; +import org.eclipse.collections.api.RichIterable; +import org.eclipse.collections.api.bag.ImmutableBag; +import org.eclipse.collections.api.bag.MutableBag; +import org.eclipse.collections.api.bag.MutableBagIterable; +import org.eclipse.collections.api.bag.sorted.MutableSortedBag; +import org.eclipse.collections.api.bimap.MutableBiMap; +import org.eclipse.collections.api.block.HashingStrategy; +import org.eclipse.collections.api.block.function.Function; +import org.eclipse.collections.api.block.function.Function0; +import org.eclipse.collections.api.block.function.Function2; +import org.eclipse.collections.api.block.function.primitive.BooleanFunction; +import org.eclipse.collections.api.block.function.primitive.ByteFunction; +import org.eclipse.collections.api.block.function.primitive.CharFunction; +import org.eclipse.collections.api.block.function.primitive.DoubleFunction; +import org.eclipse.collections.api.block.function.primitive.DoubleObjectToDoubleFunction; +import org.eclipse.collections.api.block.function.primitive.FloatFunction; +import org.eclipse.collections.api.block.function.primitive.FloatObjectToFloatFunction; +import org.eclipse.collections.api.block.function.primitive.IntFunction; +import org.eclipse.collections.api.block.function.primitive.IntObjectToIntFunction; +import org.eclipse.collections.api.block.function.primitive.LongFunction; +import org.eclipse.collections.api.block.function.primitive.LongObjectToLongFunction; +import org.eclipse.collections.api.block.function.primitive.ObjectIntToObjectFunction; +import org.eclipse.collections.api.block.function.primitive.ShortFunction; +import org.eclipse.collections.api.block.predicate.Predicate; +import org.eclipse.collections.api.block.predicate.Predicate2; +import org.eclipse.collections.api.block.procedure.Procedure; +import org.eclipse.collections.api.block.procedure.Procedure2; +import org.eclipse.collections.api.block.procedure.primitive.ObjectIntProcedure; +import org.eclipse.collections.api.collection.primitive.MutableBooleanCollection; +import org.eclipse.collections.api.collection.primitive.MutableByteCollection; +import org.eclipse.collections.api.collection.primitive.MutableCharCollection; +import org.eclipse.collections.api.collection.primitive.MutableDoubleCollection; +import org.eclipse.collections.api.collection.primitive.MutableFloatCollection; +import org.eclipse.collections.api.collection.primitive.MutableIntCollection; +import org.eclipse.collections.api.collection.primitive.MutableLongCollection; +import org.eclipse.collections.api.collection.primitive.MutableShortCollection; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.list.ParallelListIterable; +import org.eclipse.collections.api.list.primitive.ImmutableBooleanList; +import org.eclipse.collections.api.list.primitive.ImmutableByteList; +import org.eclipse.collections.api.list.primitive.ImmutableCharList; +import org.eclipse.collections.api.list.primitive.ImmutableDoubleList; +import org.eclipse.collections.api.list.primitive.ImmutableFloatList; +import org.eclipse.collections.api.list.primitive.ImmutableIntList; +import org.eclipse.collections.api.list.primitive.ImmutableLongList; +import org.eclipse.collections.api.list.primitive.ImmutableShortList; +import org.eclipse.collections.api.map.ImmutableMap; +import org.eclipse.collections.api.map.MutableMap; +import org.eclipse.collections.api.map.MutableMapIterable; +import org.eclipse.collections.api.map.primitive.ImmutableObjectDoubleMap; +import org.eclipse.collections.api.map.primitive.ImmutableObjectLongMap; +import org.eclipse.collections.api.map.sorted.MutableSortedMap; +import org.eclipse.collections.api.multimap.MutableMultimap; +import org.eclipse.collections.api.multimap.list.ImmutableListMultimap; +import org.eclipse.collections.api.ordered.OrderedIterable; +import org.eclipse.collections.api.partition.list.PartitionImmutableList; +import org.eclipse.collections.api.set.MutableSet; +import org.eclipse.collections.api.set.sorted.MutableSortedSet; +import org.eclipse.collections.api.stack.MutableStack; +import org.eclipse.collections.api.tuple.Pair; +import org.eclipse.collections.impl.factory.Lists; + +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; + +public class Spans implements ImmutableList { + + ImmutableList spans; + + public Spans(Annotation a) { + spans = Lists.immutable.with(new Span(a)); + } + + public Spans(Mention m) { + spans = Lists.immutable.withAll(m.getSurface()).collect(ms -> new Span(ms)); + } + + public int getBegin() { + return spans.collect(s -> s.begin).min(); + } + + public int getEnd() { + return spans.collect(s -> s.end).max(); + } + + @Override + public void forEach(Procedure procedure) { + spans.forEach(procedure); + } + + @Override + public Iterator iterator() { + return spans.iterator(); + } + + @Override + public void forEach(Consumer consumer) { + spans.forEach(consumer); + } + + @Override + @Deprecated + public void forEachWithIndex(ObjectIntProcedure objectIntProcedure) { + spans.forEachWithIndex(objectIntProcedure); + } + + @Override + public void reverseForEach(Procedure procedure) { + spans.reverseForEach(procedure); + } + + @Override + public int indexOf(Object object) { + return spans.indexOf(object); + } + + @Override + public ImmutableList newWith(Span element) { + return spans.newWith(element); + } + + @Override + public ImmutableList newWithout(Span element) { + return spans.newWithout(element); + } + + @Override + public Span get(int index) { + return spans.get(index); + } + + @Override + public ImmutableList newWithAll(Iterable elements) { + return spans.newWithAll(elements); + } + + @Override + public ImmutableList newWithoutAll(Iterable elements) { + return spans.newWithoutAll(elements); + } + + @Override + public void reverseForEachWithIndex(ObjectIntProcedure procedure) { + spans.reverseForEachWithIndex(procedure); + } + + @Override + public int lastIndexOf(Object o) { + return spans.lastIndexOf(o); + } + + @Override + public

void forEachWith(Procedure2 procedure, P parameter) { + spans.forEachWith(procedure, parameter); + } + + @Override + public ImmutableList tap(Procedure procedure) { + return spans.tap(procedure); + } + + @Override + public ImmutableList select(Predicate predicate) { + return spans.select(predicate); + } + + @Override + public

ImmutableList selectWith(Predicate2 predicate, P parameter) { + return spans.selectWith(predicate, parameter); + } + + @Override + public ImmutableList reject(Predicate predicate) { + return spans.reject(predicate); + } + + @Override + public LazyIterable asReversed() { + return spans.asReversed(); + } + + @Override + public

ImmutableList rejectWith(Predicate2 predicate, P parameter) { + return spans.rejectWith(predicate, parameter); + } + + @Override + public Optional getFirstOptional() { + return spans.getFirstOptional(); + } + + @Override + public PartitionImmutableList partition(Predicate predicate) { + return spans.partition(predicate); + } + + @Override + public

PartitionImmutableList partitionWith(Predicate2 predicate, P parameter) { + return spans.partitionWith(predicate, parameter); + } + + @Override + public ImmutableList selectInstancesOf(Class clazz) { + return spans.selectInstancesOf(clazz); + } + + @Override + public ListIterator listIterator() { + return spans.listIterator(); + } + + @Override + public int detectLastIndex(Predicate predicate) { + return spans.detectLastIndex(predicate); + } + + @Override + public ImmutableList collect(Function function) { + return spans.collect(function); + } + + @Override + public ListIterator listIterator(int index) { + return spans.listIterator(index); + } + + @Override + public ImmutableList collectWithIndex(ObjectIntToObjectFunction function) { + return spans.collectWithIndex(function); + } + + @Override + public MutableStack toStack() { + return spans.toStack(); + } + + @Override + public ImmutableList toImmutable() { + return spans.toImmutable(); + } + + @Override + public ImmutableBooleanList collectBoolean(BooleanFunction booleanFunction) { + return spans.collectBoolean(booleanFunction); + } + + @Override + public ImmutableByteList collectByte(ByteFunction byteFunction) { + return spans.collectByte(byteFunction); + } + + @Override + public int size() { + return spans.size(); + } + + @Override + public ImmutableCharList collectChar(CharFunction charFunction) { + return spans.collectChar(charFunction); + } + + @Override + public boolean isEmpty() { + return spans.isEmpty(); + } + + @Override + public ImmutableDoubleList collectDouble(DoubleFunction doubleFunction) { + return spans.collectDouble(doubleFunction); + } + + @Override + public ImmutableFloatList collectFloat(FloatFunction floatFunction) { + return spans.collectFloat(floatFunction); + } + + @Override + public boolean notEmpty() { + return spans.notEmpty(); + } + + @Override + public Optional getLastOptional() { + return spans.getLastOptional(); + } + + @Override + public ImmutableIntList collectInt(IntFunction intFunction) { + return spans.collectInt(intFunction); + } + + @Override + public ImmutableLongList collectLong(LongFunction longFunction) { + return spans.collectLong(longFunction); + } + + @Override + public Span getFirst() { + return spans.getFirst(); + } + + @Override + public ImmutableShortList collectShort(ShortFunction shortFunction) { + return spans.collectShort(shortFunction); + } + + @Override + public ImmutableList collectWith(Function2 function, P parameter) { + return spans.collectWith(function, parameter); + } + + @Override + public ImmutableList collectIf(Predicate predicate, + Function function) { + return spans.collectIf(predicate, function); + } + + @Override + public ImmutableList flatCollect(Function> function) { + return spans.flatCollect(function); + } + + @Override + public ImmutableList flatCollectWith(Function2> function, + P parameter) { + return spans.flatCollectWith(function, parameter); + } + + @Override + public ImmutableListMultimap groupBy(Function function) { + return spans.groupBy(function); + } + + @Override + public Span getLast() { + return spans.getLast(); + } + + @Override + public ImmutableListMultimap groupByEach(Function> function) { + return spans.groupByEach(function); + } + + @Override + public ImmutableList distinct() { + return spans.distinct(); + } + + @Override + public ImmutableList distinct(HashingStrategy hashingStrategy) { + return spans.distinct(hashingStrategy); + } + + @Override + public ImmutableList distinctBy(Function function) { + return spans.distinctBy(function); + } + + @Override + public ImmutableList> zip(Iterable that) { + return spans.zip(that); + } + + @Override + public ImmutableList> zipWithIndex() { + return spans.zipWithIndex(); + } + + @Override + public ImmutableList take(int count) { + return spans.take(count); + } + + @Override + public ImmutableList takeWhile(Predicate predicate) { + return spans.takeWhile(predicate); + } + + @Override + public ImmutableList drop(int count) { + return spans.drop(count); + } + + @Override + public ImmutableList dropWhile(Predicate predicate) { + return spans.dropWhile(predicate); + } + + @Override + public Span getOnly() { + return spans.getOnly(); + } + + @Override + public PartitionImmutableList partitionWhile(Predicate predicate) { + return spans.partitionWhile(predicate); + } + + @Override + public boolean corresponds(OrderedIterable other, Predicate2 predicate) { + return spans.corresponds(other, predicate); + } + + @Override + public List castToList() { + return spans.castToList(); + } + + @Override + public ImmutableObjectLongMap sumByInt(Function groupBy, + IntFunction function) { + return spans.sumByInt(groupBy, function); + } + + @Override + public ImmutableList subList(int fromIndex, int toIndex) { + return spans.subList(fromIndex, toIndex); + } + + @Override + public ImmutableObjectDoubleMap sumByFloat(Function groupBy, + FloatFunction function) { + return spans.sumByFloat(groupBy, function); + } + + @Override + public ImmutableList toReversed() { + return spans.toReversed(); + } + + @Override + public ImmutableObjectLongMap sumByLong(Function groupBy, + LongFunction function) { + return spans.sumByLong(groupBy, function); + } + + @Override + public boolean contains(Object object) { + return spans.contains(object); + } + + @Override + public ImmutableObjectDoubleMap sumByDouble(Function groupBy, + DoubleFunction function) { + return spans.sumByDouble(groupBy, function); + } + + @Override + public void forEach(int startIndex, int endIndex, Procedure procedure) { + spans.forEach(startIndex, endIndex, procedure); + } + + @Override + public boolean containsAllIterable(Iterable source) { + return spans.containsAllIterable(source); + } + + @Override + public ImmutableBag countBy(Function function) { + return spans.countBy(function); + } + + @Override + public boolean containsAll(Collection source) { + return spans.containsAll(source); + } + + @Override + public ImmutableBag countByWith(Function2 function, P parameter) { + return spans.countByWith(function, parameter); + } + + @Override + public boolean containsAllArguments(Object... elements) { + return spans.containsAllArguments(elements); + } + + @Override + public ImmutableMap groupByUniqueKey(Function function) { + return spans.groupByUniqueKey(function); + } + + @Override + public ImmutableMap aggregateInPlaceBy(Function groupBy, + Function0 zeroValueFactory, Procedure2 mutatingAggregator) { + return spans.aggregateInPlaceBy(groupBy, zeroValueFactory, mutatingAggregator); + } + + @Override + public void forEachWithIndex(int fromIndex, int toIndex, ObjectIntProcedure objectIntProcedure) { + spans.forEachWithIndex(fromIndex, toIndex, objectIntProcedure); + } + + @Override + public ImmutableMap aggregateBy(Function groupBy, + Function0 zeroValueFactory, + Function2 nonMutatingAggregator) { + return spans.aggregateBy(groupBy, zeroValueFactory, nonMutatingAggregator); + } + + @Override + public void each(Procedure procedure) { + spans.each(procedure); + } + + @Override + public Stream stream() { + return spans.stream(); + } + + @Override + public Stream parallelStream() { + return spans.parallelStream(); + } + + @Override + public Spliterator spliterator() { + return spans.spliterator(); + } + + @Override + public Collection castToCollection() { + return spans.castToCollection(); + } + + @Override + public ParallelListIterable asParallel(ExecutorService executorService, int batchSize) { + return spans.asParallel(executorService, batchSize); + } + + @Override + public int binarySearch(Span key, Comparator comparator) { + return spans.binarySearch(key, comparator); + } + + @Override + public int binarySearch(Span key) { + return spans.binarySearch(key); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Spans)) + return false; + Spans other = (Spans) o; + if (spans.size() != other.spans.size()) + return false; + for (int i = 0; i < spans.size(); i++) { + if (!spans.get(i).equals(other.spans.get(i))) + return false; + } + return true; + } + + @Override + public int hashCode() { + return spans.hashCode(); + } + + @Override + public > R select(Predicate predicate, R target) { + return spans.select(predicate, target); + } + + @Override + public > R collectWithIndex( + ObjectIntToObjectFunction function, R target) { + return spans.collectWithIndex(function, target); + } + + @Override + public > R selectWith(Predicate2 predicate, P parameter, + R targetCollection) { + return spans.selectWith(predicate, parameter, targetCollection); + } + + @Override + public int detectIndex(Predicate predicate) { + return spans.detectIndex(predicate); + } + + @Override + public > R reject(Predicate predicate, R target) { + return spans.reject(predicate, target); + } + + @Override + public > R rejectWith(Predicate2 predicate, P parameter, + R targetCollection) { + return spans.rejectWith(predicate, parameter, targetCollection); + } + + @Override + public > R collect(Function function, R target) { + return spans.collect(function, target); + } + + @Override + public R collectBoolean(BooleanFunction booleanFunction, + R target) { + return spans.collectBoolean(booleanFunction, target); + } + + @Override + public R collectByte(ByteFunction byteFunction, R target) { + return spans.collectByte(byteFunction, target); + } + + @Override + public R collectChar(CharFunction charFunction, R target) { + return spans.collectChar(charFunction, target); + } + + @Override + public R collectDouble(DoubleFunction doubleFunction, R target) { + return spans.collectDouble(doubleFunction, target); + } + + @Override + public R collectFloat(FloatFunction floatFunction, R target) { + return spans.collectFloat(floatFunction, target); + } + + @Override + public R collectInt(IntFunction intFunction, R target) { + return spans.collectInt(intFunction, target); + } + + @Override + public R collectLong(LongFunction longFunction, R target) { + return spans.collectLong(longFunction, target); + } + + @Override + public R collectShort(ShortFunction shortFunction, R target) { + return spans.collectShort(shortFunction, target); + } + + @Override + public > R collectWith(Function2 function, + P parameter, R targetCollection) { + return spans.collectWith(function, parameter, targetCollection); + } + + @Override + public > R collectIf(Predicate predicate, + Function function, R target) { + return spans.collectIf(predicate, function, target); + } + + @Override + public > R flatCollect(Function> function, + R target) { + return spans.flatCollect(function, target); + } + + @Override + public > R flatCollectWith( + Function2> function, P parameter, R target) { + return spans.flatCollectWith(function, parameter, target); + } + + @Override + public Span detect(Predicate predicate) { + return spans.detect(predicate); + } + + @Override + public

Span detectWith(Predicate2 predicate, P parameter) { + return spans.detectWith(predicate, parameter); + } + + @Override + public Optional detectOptional(Predicate predicate) { + return spans.detectOptional(predicate); + } + + @Override + public

Optional detectWithOptional(Predicate2 predicate, P parameter) { + return spans.detectWithOptional(predicate, parameter); + } + + @Override + public Span detectIfNone(Predicate predicate, Function0 function) { + return spans.detectIfNone(predicate, function); + } + + @Override + public

Span detectWithIfNone(Predicate2 predicate, P parameter, + Function0 function) { + return spans.detectWithIfNone(predicate, parameter, function); + } + + @Override + public int count(Predicate predicate) { + return spans.count(predicate); + } + + @Override + public

int countWith(Predicate2 predicate, P parameter) { + return spans.countWith(predicate, parameter); + } + + @Override + public boolean anySatisfy(Predicate predicate) { + return spans.anySatisfy(predicate); + } + + @Override + public

boolean anySatisfyWith(Predicate2 predicate, P parameter) { + return spans.anySatisfyWith(predicate, parameter); + } + + @Override + public boolean allSatisfy(Predicate predicate) { + return spans.allSatisfy(predicate); + } + + @Override + public

boolean allSatisfyWith(Predicate2 predicate, P parameter) { + return spans.allSatisfyWith(predicate, parameter); + } + + @Override + public boolean noneSatisfy(Predicate predicate) { + return spans.noneSatisfy(predicate); + } + + @Override + public

boolean noneSatisfyWith(Predicate2 predicate, P parameter) { + return spans.noneSatisfyWith(predicate, parameter); + } + + @Override + public IV injectInto(IV injectedValue, Function2 function) { + return spans.injectInto(injectedValue, function); + } + + @Override + public int injectInto(int injectedValue, IntObjectToIntFunction function) { + return spans.injectInto(injectedValue, function); + } + + @Override + public long injectInto(long injectedValue, LongObjectToLongFunction function) { + return spans.injectInto(injectedValue, function); + } + + @Override + public float injectInto(float injectedValue, FloatObjectToFloatFunction function) { + return spans.injectInto(injectedValue, function); + } + + @Override + public double injectInto(double injectedValue, DoubleObjectToDoubleFunction function) { + return spans.injectInto(injectedValue, function); + } + + @Override + public > R into(R target) { + return spans.into(target); + } + + @Override + public MutableList toList() { + return spans.toList(); + } + + @Override + public MutableList toSortedList() { + return spans.toSortedList(); + } + + @Override + public MutableList toSortedList(Comparator comparator) { + return spans.toSortedList(comparator); + } + + @Override + public > MutableList toSortedListBy( + Function function) { + return spans.toSortedListBy(function); + } + + @Override + public MutableSet toSet() { + return spans.toSet(); + } + + @Override + public MutableSortedSet toSortedSet() { + return spans.toSortedSet(); + } + + @Override + public MutableSortedSet toSortedSet(Comparator comparator) { + return spans.toSortedSet(comparator); + } + + @Override + public > MutableSortedSet toSortedSetBy( + Function function) { + return spans.toSortedSetBy(function); + } + + @Override + public MutableBag toBag() { + return spans.toBag(); + } + + @Override + public MutableSortedBag toSortedBag() { + return spans.toSortedBag(); + } + + @Override + public MutableSortedBag toSortedBag(Comparator comparator) { + return spans.toSortedBag(comparator); + } + + @Override + public > MutableSortedBag toSortedBagBy( + Function function) { + return spans.toSortedBagBy(function); + } + + @Override + public MutableMap toMap(Function keyFunction, + Function valueFunction) { + return spans.toMap(keyFunction, valueFunction); + } + + @Override + public MutableSortedMap toSortedMap(Function keyFunction, + Function valueFunction) { + return spans.toSortedMap(keyFunction, valueFunction); + } + + @Override + public MutableSortedMap toSortedMap(Comparator comparator, + Function keyFunction, Function valueFunction) { + return spans.toSortedMap(comparator, keyFunction, valueFunction); + } + + @Override + public , NK, NV> MutableSortedMap toSortedMapBy( + Function sortBy, Function keyFunction, + Function valueFunction) { + return spans.toSortedMapBy(sortBy, keyFunction, valueFunction); + } + + @Override + public LazyIterable asLazy() { + return spans.asLazy(); + } + + @Override + public Object[] toArray() { + return spans.toArray(); + } + + @Override + public T[] toArray(T[] target) { + return spans.toArray(target); + } + + @Override + public Span min(Comparator comparator) { + return spans.min(comparator); + } + + @Override + public Span max(Comparator comparator) { + return spans.max(comparator); + } + + @Override + public Optional minOptional(Comparator comparator) { + return spans.minOptional(comparator); + } + + @Override + public Optional maxOptional(Comparator comparator) { + return spans.maxOptional(comparator); + } + + @Override + public Span min() { + return spans.min(); + } + + @Override + public Span max() { + return spans.max(); + } + + @Override + public Optional minOptional() { + return spans.minOptional(); + } + + @Override + public Optional maxOptional() { + return spans.maxOptional(); + } + + @Override + public > Span minBy(Function function) { + return spans.minBy(function); + } + + @Override + public > Span maxBy(Function function) { + return spans.maxBy(function); + } + + @Override + public > Optional minByOptional( + Function function) { + return spans.minByOptional(function); + } + + @Override + public > Optional maxByOptional( + Function function) { + return spans.maxByOptional(function); + } + + @Override + public long sumOfInt(IntFunction function) { + return spans.sumOfInt(function); + } + + @Override + public double sumOfFloat(FloatFunction function) { + return spans.sumOfFloat(function); + } + + @Override + public long sumOfLong(LongFunction function) { + return spans.sumOfLong(function); + } + + @Override + public double sumOfDouble(DoubleFunction function) { + return spans.sumOfDouble(function); + } + + @Override + public IntSummaryStatistics summarizeInt(IntFunction function) { + return spans.summarizeInt(function); + } + + @Override + public DoubleSummaryStatistics summarizeFloat(FloatFunction function) { + return spans.summarizeFloat(function); + } + + @Override + public LongSummaryStatistics summarizeLong(LongFunction function) { + return spans.summarizeLong(function); + } + + @Override + public DoubleSummaryStatistics summarizeDouble(DoubleFunction function) { + return spans.summarizeDouble(function); + } + + @Override + public R reduceInPlace(Collector collector) { + return spans.reduceInPlace(collector); + } + + @Override + public R reduceInPlace(Supplier supplier, BiConsumer accumulator) { + return spans.reduceInPlace(supplier, accumulator); + } + + @Override + public Optional reduce(BinaryOperator accumulator) { + return spans.reduce(accumulator); + } + + @Override + public String makeString() { + return spans.makeString(); + } + + @Override + public String makeString(String separator) { + return spans.makeString(separator); + } + + @Override + public String makeString(String start, String separator, String end) { + return spans.makeString(start, separator, end); + } + + @Override + public void appendString(Appendable appendable) { + spans.appendString(appendable); + } + + @Override + public void appendString(Appendable appendable, String separator) { + spans.appendString(appendable, separator); + } + + @Override + public void appendString(Appendable appendable, String start, String separator, String end) { + spans.appendString(appendable, start, separator, end); + } + + @Override + public > R countBy(Function function, R target) { + return spans.countBy(function, target); + } + + @Override + public > R countByWith( + Function2 function, P parameter, R target) { + return spans.countByWith(function, parameter, target); + } + + @Override + public > R groupBy(Function function, R target) { + return spans.groupBy(function, target); + } + + @Override + public > R groupByEach(Function> function, + R target) { + return spans.groupByEach(function, target); + } + + @Override + public String toString() { + return spans.toString(); + } + + @Override + @Deprecated + public >> R zip(Iterable that, R target) { + return spans.zip(that, target); + } + + @Override + @Deprecated + public >> R zipWithIndex(R target) { + return spans.zipWithIndex(target); + } + + @Override + public RichIterable> chunk(int size) { + return spans.chunk(size); + } + + /** + * @param + * @param + * @param arg0 + * @param arg1 + * @return + * @see org.eclipse.collections.api.RichIterable#groupByUniqueKey(org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.map.MutableMapIterable) + */ + @Override + public > R groupByUniqueKey(Function arg0, + R arg1) { + return spans.groupByUniqueKey(arg0, arg1); + } + + /** + * @param + * @param + * @param function + * @param target + * @return + * @see org.eclipse.collections.api.RichIterable#countByEach(org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.bag.MutableBagIterable) + */ + @Override + public > R countByEach(Function> function, + R target) { + return spans.countByEach(function, target); + } + + /** + * @param + * @param function + * @return + * @see org.eclipse.collections.api.collection.ImmutableCollection#countByEach(org.eclipse.collections.api.block.function.Function) + */ + @Override + public ImmutableBag countByEach(Function> function) { + return spans.countByEach(function); + } + + /** + * @return + * @see org.eclipse.collections.api.RichIterable#getAny() + */ + @Override + public Span getAny() { + return spans.getAny(); + } + + /** + * @param + * @param + * @param + * @param groupByFunction + * @param collectFunction + * @param target + * @return + * @see org.eclipse.collections.api.RichIterable#groupByAndCollect(org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.multimap.MutableMultimap) + */ + @Override + public > R groupByAndCollect( + Function groupByFunction, Function collectFunction, + R target) { + return spans.groupByAndCollect(groupByFunction, collectFunction, target); + } + + /** + * @param + * @param + * @param keyFunction + * @param valueFunction + * @return + * @see org.eclipse.collections.api.RichIterable#toBiMap(org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.block.function.Function) + */ + @Override + public MutableBiMap toBiMap(Function keyFunction, + Function valueFunction) { + return spans.toBiMap(keyFunction, valueFunction); + } + + /** + * @param + * @param + * @param + * @param keyFunction + * @param valueFunction + * @param target + * @return + * @see org.eclipse.collections.api.RichIterable#toMap(org.eclipse.collections.api.block.function.Function, + * org.eclipse.collections.api.block.function.Function, java.util.Map) + */ + @Override + public > R toMap(Function keyFunction, + Function valueFunction, R target) { + return spans.toMap(keyFunction, valueFunction, target); + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/Strings.java b/src/main/java/de/unistuttgart/ims/coref/annotator/Strings.java index c8e1fb7b..25e96546 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/Strings.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/Strings.java @@ -12,6 +12,8 @@ public class Strings { public static final String ACTION_ADD_FLAG_TOOLTIP = "action.add_flag.tooltip"; public static final String ACTION_ADD_MENTION_FLAG = "action.add_mention_flag"; public static final String ACTION_ADD_MENTION_FLAG_TOOLTIP = "action.add_mention_flag.tooltip"; + public static final String ACTION_ANALYZER = "action.analyzer"; + public static final String ACTION_ANALYZER_TOOLTIP = "action.analyzer.tooltip"; public static final String ACTION_CLEAR = "action.clear"; public static final String ACTION_CLEAR_TOOLTIP = "action.clear.tooltip"; public static final String ACTION_CLOSE = "action.close"; @@ -26,10 +28,10 @@ public class Strings { public static final String ACTION_COMPARE_TOOLTIP = "action.compare.tooltip"; public static final String ACTION_COPY = "action.copy"; public static final String ACTION_DELETE = "action.delete"; - public static final String ACTION_DELETE_IN_SELECTION = "action.delete_in_selection"; - public static final String ACTION_DELETE_IN_SELECTION_TOOLTIP = "action.delete_in_selection.tooltip"; public static final String ACTION_DELETE_FLAG = "action.delete_flag"; public static final String ACTION_DELETE_FLAG_TOOLTIP = "action.delete_flag.tooltip"; + public static final String ACTION_DELETE_IN_SELECTION = "action.delete_in_selection"; + public static final String ACTION_DELETE_IN_SELECTION_TOOLTIP = "action.delete_in_selection.tooltip"; public static final String ACTION_DELETE_TOOLTIP = "action.delete.tooltip"; public static final String ACTION_DUPLICATE_MENTIONS = "action.duplicate_mentions"; public static final String ACTION_EDIT_COMMENT = "action.edit.comment"; @@ -48,21 +50,23 @@ public class Strings { public static final String ACTION_FLAG_MENTION_NON_NOMINAL_TOOLTIP = "action.flag_mention_non_nominal.tooltip"; public static final String ACTION_GROUP = "action.group"; public static final String ACTION_GROUP_TOOLTIP = "action.group.tooltip"; + public static final String ACTION_GUIDELINES = "action.guidelines"; + public static final String ACTION_GUIDELINES_TOOLTIP = "action.guidelines.tooltip"; public static final String ACTION_MERGE = "action.merge"; - public static final String ACTION_MERGE_TOOLTIP = "action.merge.tooltip"; - public static final String ACTION_NEW = "action.new"; - public static final String ACTION_NEW_TOOLTIP = "action.new.tooltip"; public static final String ACTION_MERGE_ADJACENT_MENTIONS = "action.merge.adjacent_mentions"; public static final String ACTION_MERGE_ADJACENT_MENTIONS_TOOLTIP = "action.merge.adjacent_mentions.tooltip.ok"; - public static final String ACTION_MERGE_ADJACENT_MENTIONS_UNABLE_NOT_TWO_MENTIONS = "action.merge.adjacent_mentions.tooltip.not_two_mentions"; public static final String ACTION_MERGE_ADJACENT_MENTIONS_UNABLE_NOT_ADJACENT = "action.merge.adjacent_mentions.tooltip.not_adjacent"; + public static final String ACTION_MERGE_ADJACENT_MENTIONS_UNABLE_NOT_TWO_MENTIONS = "action.merge.adjacent_mentions.tooltip.not_two_mentions"; + public static final String ACTION_MERGE_TOOLTIP = "action.merge.tooltip"; + public static final String ACTION_NEW = "action.new"; + public static final String ACTION_NEW_TOOLTIP = "action.new.tooltip"; public static final String ACTION_OPEN = "action.open"; public static final String ACTION_REMOVE_FOREIGN_ANNOTATIONS = "action.remove.foreign_annotations"; public static final String ACTION_REMOVE_FOREIGN_ANNOTATIONS_TOOLTIP = "action.remove.foreign_annotations.tooltip"; public static final String ACTION_RENAME = "action.rename"; - public static final String ACTION_RENAME_TOOLTIP = "action.rename.tooltip"; public static final String ACTION_RENAME_ALL = "action.rename_all"; public static final String ACTION_RENAME_ALL_TOOLTIP = "action.rename_all.tooltip"; + public static final String ACTION_RENAME_TOOLTIP = "action.rename.tooltip"; public static final String ACTION_SAVE_AS = "action.save_as"; public static final String ACTION_SEARCH = "action.search"; public static final String ACTION_SEARCH_MENTION = "action.search.mention"; @@ -76,24 +80,28 @@ public class Strings { public static final String ACTION_SET_DOCUMENT_LANGUAGE_TOOLTIP = "action.set_document_language.tooltip"; public static final String ACTION_SET_SHORTCUT = "action.set_shortcut"; public static final String ACTION_SET_SHORTCUT_TOOLTIP = "action.set_shortcut.tooltip"; + public static final String ACTION_SHOW_A_SELECTED_MENTION_IN_TREE = "action.show_a_selected_mention_in_tree"; + public static final String ACTION_SHOW_A_SELECTED_MENTION_IN_TREE_TOOLTIP = "action.show_a_selected_mention_in_tree.tooltip"; public static final String ACTION_SHOW_COMMENTS = "action.show.comments"; + public static final String ACTION_SHOW_DOCUMENT_STATISTICS = "action.show_document_statistics"; + public static final String ACTION_SHOW_DOCUMENT_STATISTICS_TOOLTIP = "action.show_document_statistics.tooltip"; public static final String ACTION_SHOW_HISTORY = "action.show.history"; public static final String ACTION_SHOW_LOG = "action.show.log"; public static final String ACTION_SHOW_MENTION_IN_TREE = "action.show_mention_in_tree"; - public static final String ACTION_SHOW_A_SELECTED_MENTION_IN_TREE = "action.show_a_selected_mention_in_tree"; - public static final String ACTION_SHOW_A_SELECTED_MENTION_IN_TREE_TOOLTIP = "action.show_a_selected_mention_in_tree.tooltip"; public static final String ACTION_SORT_ALPHA = "action.sort_alpha"; public static final String ACTION_SORT_ALPHA_TOOLTIP = "action.sort_alpha.tooltip"; - public static final String ACTION_SORT_MENTIONS = "action.sort_mentions"; - public static final String ACTION_SORT_MENTIONS_TOOLTIP = "action.sort_mentions.tooltip"; public static final String ACTION_SORT_LASTMODIFIED = "action.sort_lastmodified"; public static final String ACTION_SORT_LASTMODIFIED_TOOLTIP = "action.sort_lastmodified.tooltip"; + public static final String ACTION_SORT_MENTIONS = "action.sort_mentions"; + public static final String ACTION_SORT_MENTIONS_TOOLTIP = "action.sort_mentions.tooltip"; + public static final String ACTION_SORT_POSITION = "action.sort_position"; + public static final String ACTION_SORT_POSITION_TOOLTIP = "action.sort_position.tooltip"; public static final String ACTION_SORT_REVERT = "action.sort_revert"; + public static final String ACTION_TOGGLE_ASK_BEFORE_FILE_OVERWRITE = "action.toggle.ask_before_file_overwrite"; public static final String ACTION_TOGGLE_COMPARE_BY_ENTITY_NAME = "action.toggle.compare_by_entity_name"; public static final String ACTION_TOGGLE_COMPARE_BY_ENTITY_NAME_TOOLTIP = "action.toggle.compare_by_entity_name.tooltip"; public static final String ACTION_TOGGLE_CREATE_DEFAULT_FLAGS = "action.toggle.create_default_flags"; public static final String ACTION_TOGGLE_CREATE_DEFAULT_FLAGS_TOOLTIP = "action.toggle.create_default_flags.tooltip"; - public static final String ACTION_TOGGLE_ASK_BEFORE_FILE_OVERWRITE = "action.toggle.ask_before_file_overwrite"; public static final String ACTION_TOGGLE_DELETE_EMPTY_ENTITIES = "action.toggle.delete_empty_entities"; public static final String ACTION_TOGGLE_ENTITY_VISIBILITY = "action.toggle.entity_visibility"; public static final String ACTION_TOGGLE_FULL_TOKENS = "action.toggle.full_tokens"; @@ -119,8 +127,33 @@ public class Strings { public static final String ACTION_UNDO = "action.undo"; public static final String ACTION_VIEW_DECREASE_FONT_SIZE = "action.view.decrease_font_size"; public static final String ACTION_VIEW_INCREASE_FONT_SIZE = "action.view.increase_font_size"; + public static final String ANALYZER_COLOR = "analyzer.color"; + public static final String ANALYZER_DATATABLE_COUNT = "analyzer.datatable.count"; + public static final String ANALYZER_DATATABLE_MENTIONS = "analyzer.datatable.mentions"; + public static final String ANALYZER_ENTITY = "analyzer.entity"; + public static final String ANALYZER_GROUPBY = "analyzer.groupby"; + public static final String ANALYZER_GROUPBY_ = "analyzer.groupby."; + public static final String ANALYZER_KWIC_CENTER = "analyzer.kwic.center"; + public static final String ANALYZER_KWIC_LEFT = "analyzer.kwic.left"; + public static final String ANALYZER_KWIC_RIGHT = "analyzer.kwic.right"; + public static final String ANALYZER_NEIGHBOUR_DIRECTION = "analyzer.neighbour.direction"; + public static final String ANALYZER_NEIGHBOUR_DIRECTION_ = "analyzer.neighbour.direction."; + public static final String ANALYZER_PLOT_PLOT_TYPE = "analyzer.plot.plot_type"; + public static final String ANALYZER_PLOT_PLOT_TYPE_BAR = "analyzer.plot.plot_type.bar"; + public static final String ANALYZER_PLOT_PLOT_TYPE_PIE = "analyzer.plot.plot_type.pie"; + public static final String ANALYZER_PLOT_REST_CATEGORY = "analyzer.plot.rest_category"; + public static final String ANALYZER_PLOT_REST_LIMIT = "analyzer.plot.rest_limit"; + public static final String ANALYZER_POSITION = "analyzer.position"; + public static final String ANALYZER_UNIT = "analyzer.neighbour.unit"; + public static final String ANALYZER_UNIT_ = "analyzer.neighbour.unit."; + public static final String ANALZYER_ACTIONS = "analyzer.actions"; + public static final String ANALZYER_ACTIONS_ = "analyzer.actions."; + public static final String ANALZYER_ENTITIES = "analyzer.entities"; public static final String COMPARE_CONTEXTMENU_INTERSECTION = "compare.contextmenu.intersection"; + public static final String COMPARE_MODE_DESCRIPTION_SPAN = "compare.mode_description.span"; + public static final String COMPARE_MODE_DESCRIPTION_SPAN_ENTITYNAME = "compare.mode_description.span_entityname"; public static final String COMPARE_NOT_COMPARABLE = "compare.not_comparable"; + public static final String COMPARE_SHOW_AGREEMENT_HELP = "compare.show_agreement_help"; public static final String DIALOG_ANNOTATOR_LABEL = "dialog.annotator_label"; public static final String DIALOG_ANNOTATOR_LABEL_TOOLTIP = "dialog.annotator_label.tooltip"; public static final String DIALOG_CANCEL = "dialog.cancel"; @@ -132,6 +165,7 @@ public class Strings { public static final String DIALOG_CHANGE_KEY_INVALID_STRING_TITLE = "dialog.change_key.invalid_string.title"; public static final String DIALOG_CHANGE_KEY_OK = "dialog.change_key.ok"; public static final String DIALOG_CHANGE_KEY_PROMPT = "dialog.change_key.prompt"; + public static final String DIALOG_EXPORT_AS_TITLE = "dialog.export_as.title"; public static final String DIALOG_EXPORT_OPTIONS_AUTO_OPEN = "dialog.export_options.auto_open"; public static final String DIALOG_EXPORT_OPTIONS_AUTO_OPEN_TOOLTIP = "dialog.export_options.auto_open.tooltip"; public static final String DIALOG_EXPORT_OPTIONS_CONTEXT_UNIT = "dialog.export_options.context_unit"; @@ -151,15 +185,22 @@ public class Strings { public static final String DIALOG_EXPORT_OPTIONS_TITLE_ = "dialog.export_options.title_"; public static final String DIALOG_EXPORT_OPTIONS_TRIM_WHITESPACE = "dialog.export_options.trim_whitespace"; public static final String DIALOG_EXPORT_OPTIONS_TRIM_WHITESPACE_TOOLTIP = "dialog.export_options.trim_whitespace.tooltip"; - public static final String DIALOG_EXPORT_AS_TITLE = "dialog.export_as.title"; + public static final String DIALOG_EXPORT_OPTIONS_WARNING_1 = "dialog.export_options.warning.1"; public static final String DIALOG_FILE_EXISTS_OVERWRITE = "dialog.file_exists.overwrite"; public static final String DIALOG_LANGUAGE_PROMPT = "dialog.language.prompt"; public static final String DIALOG_LANGUAGE_TITLE = "dialog.language.title"; - public static final String DIALOG_RENAME_ENTITY_PROMPT = "dialog.rename_entity.prompt"; + public static final String DIALOG_OPEN_WITH_TITLE = "dialog.open.with.title"; public static final String DIALOG_RENAME_ALL_SELECT_STRATEGY_PROMPT = "dialog.rename_all.prompt"; public static final String DIALOG_RENAME_ALL_SELECT_STRATEGY_TITLE = "dialog.rename_all.title"; + public static final String DIALOG_RENAME_ENTITY_PROMPT = "dialog.rename_entity.prompt"; public static final String DIALOG_SAVE_AS_TITLE = "dialog.save_as.title"; public static final String DIALOG_SELECT_FILE = "dialog.select_file"; + public static final String DIALOG_SPLASH_DEFAULT = "dialog.splash.default"; + public static final String DIALOG_SPLASH_IMPORT = "dialog.splash.import"; + public static final String DIALOG_SPLASH_FIRSTTIME = "dialog.splash.firsttime"; + public static final String DIALOG_SPLASH_FIRSTTIME_TEXT = "dialog.splash.firsttime.text"; + public static final String DIALOG_SPLASH_FIRSTTIME_BUTTON = "dialog.splash.firsttime.button"; + public static final String DIALOG_SPLASH_RECENT = "dialog.splash.recent"; public static final String DIALOG_UNSAVED_CHANGES_MESSAGE = "dialog.unsaved_changes.message"; public static final String DIALOG_UNSAVED_CHANGES_MESSAGE_CANCEL = "dialog.unsaved_changes.message.cancel"; public static final String DIALOG_UNSAVED_CHANGES_MESSAGE_DONT_SAVE = "dialog.unsaved_changes.message.dont_save"; @@ -196,16 +237,21 @@ public class Strings { public static final String MENU_FILE = "menu.file"; public static final String MENU_FILE_EXPORT_AS = "menu.file.export_as"; public static final String MENU_FILE_IMPORT_FROM = "menu.file.import_from"; + public static final String MENU_FILE_RECENT = "menu.file.recent"; public static final String MENU_FLAGS = "menu.flags"; public static final String MENU_HELP = "menu.help"; public static final String MENU_SETTINGS = "menu.settings"; + public static final String MENU_SETTINGS_CATEGORY_ANNOTATION_BEHAVIOUR = "menu.settings.category.annotation_behaviour"; + public static final String MENU_SETTINGS_CATEGORY_COMPARE_VIEW = "menu.settings.category.compare_view"; + public static final String MENU_SETTINGS_CATEGORY_MISC = "menu.settings.category.misc"; + public static final String MENU_SETTINGS_CATEGORY_USER_INTERFACE = "menu.settings.category.user_interface"; public static final String MENU_TOOLS = "menu.tools"; public static final String MENU_TOOLS_PROC = "menu.tools.proc"; public static final String MENU_VIEW = "menu.view"; public static final String MENU_VIEW_FONTFAMILY = "menu.view.fontfamily"; - public static final String MENU_VIEW_STYLE = "menu.view.style"; public static final String MENU_VIEW_LINE_NUMBERS = "menu.view.line_numbers"; public static final String MENU_VIEW_LINE_SPACING = "menu.view.line_spacing"; + public static final String MENU_VIEW_STYLE = "menu.view.style"; public static final String MESSAGE_CREATES_ENTITY = "message.creates_entity"; public static final String MESSAGE_CREATES_MENTION = "message.creates_mention"; public static final String MESSAGE_CREATES_MENTION_PART = "message.creates_mention_part"; @@ -215,7 +261,9 @@ public class Strings { public static final String MESSAGE_MENTION_CREATED = "message.mention_created"; public static final String MESSAGE_MENTION_PART_CREATED = "message.mention_part_created"; public static final String MESSAGE_SAVING = "message.saving"; - public static final String NAME_MS_EXCEL = "name.ms.excel"; + public static final String NAME_MS_EXCEL = "name.ms_excel"; + public static final String SEARCH_WINDOW_CASE_INSENSITIVE = "search.window.case_insensitive"; + public static final String SEARCH_WINDOW_CASE_INSENSITIVE_TOOLTIP = "search.window.case_insensitive.tooltip"; public static final String SEARCH_WINDOW_RESTRICT_TO_MENTIONS = "search.window.restrict_to_mentions"; public static final String SEARCH_WINDOW_TAB_STRUCTURE = "search.window.tab.structure"; public static final String SEARCH_WINDOW_TAB_TEXT = "search.window.tab.text"; @@ -242,11 +290,11 @@ public class Strings { public static final String STAT_KEY_TOTAL = "stat.key.total"; public static final String STAT_KEY_TOTAL_TOOLTIP = "stat.key.total.tooltip"; public static final String STATUS_NOW_AVAILABLE = "status.now.available"; + public static final String STATUS_PROFILE = "status.profile"; public static final String STATUS_SEARCH_RESULTS = "status.search.results"; public static final String STATUS_SEARCH_RESULTS_MORE_THAN = "status.search.more_than"; public static final String STATUS_SEARCH_SELECTED_ENTITY = "status.search.selected_entity"; public static final String STATUS_STYLE = "status.style"; - public static final String STATUS_PROFILE = "status.profile"; public static final String WINDOWTITLE_EDITED = "windowtitle.edited"; public static final String WINDOWTITLE_NEW_FILE = "windowtitle.new_file"; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/TreeSelectionUtil.java b/src/main/java/de/unistuttgart/ims/coref/annotator/TreeSelectionUtil.java index 5c18d711..fd90c293 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/TreeSelectionUtil.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/TreeSelectionUtil.java @@ -11,10 +11,9 @@ import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.factory.Lists; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class TreeSelectionUtil { TreeSelectionEvent currentEvent = null; @@ -72,16 +71,12 @@ public boolean isEntity() { return featureStructures.allSatisfy(f -> f instanceof Entity); } - public boolean isDetachedMentionPart() { - return featureStructures.allSatisfy(f -> f instanceof DetachedMentionPart); - } - public boolean isMention() { return featureStructures.allSatisfy(f -> f instanceof Mention); } public boolean isEntityGroup() { - return featureStructures.allSatisfy(f -> f instanceof EntityGroup); + return featureStructures.allSatisfy(f -> UimaUtil.isGroup(f)); } public boolean isLeaf() { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/TypeSystemVersion.java b/src/main/java/de/unistuttgart/ims/coref/annotator/TypeSystemVersion.java index c5b2059f..355f99cc 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/TypeSystemVersion.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/TypeSystemVersion.java @@ -1,9 +1,9 @@ package de.unistuttgart.ims.coref.annotator; public enum TypeSystemVersion { - LEGACY, v1; + LEGACY, v1, v2; public static TypeSystemVersion getCurrent() { - return TypeSystemVersion.v1; + return TypeSystemVersion.v2; } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/UpdateCheck.java b/src/main/java/de/unistuttgart/ims/coref/annotator/UpdateCheck.java index 5a3f001e..4c3377cf 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/UpdateCheck.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/UpdateCheck.java @@ -1,6 +1,7 @@ package de.unistuttgart.ims.coref.annotator; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -13,67 +14,40 @@ public class UpdateCheck { - private static final String HTML_URL = "html_url"; - private static final String TAG_NAME = "tag_name"; - transient JSONObject cache = null; - long lastCheck = Long.MIN_VALUE; - - public boolean checkForUpdate() throws IOException { - Version current = Version.get(); - - JSONObject o; - o = getRemote(); - String tagName = o.getString(TAG_NAME); - Version remote = Version.get(tagName.substring(1)); - return current.compareTo(remote) < 0; - } - - public Version getRemoteVersion() throws IOException { - JSONObject o = getRemote(); - String tagName = o.getString(TAG_NAME); - return Version.get(tagName.substring(1)); - } - - public URI getReleasePage() throws IOException { - JSONObject o = getRemote(); - try { - return new URI(o.getString(HTML_URL)); - } catch (JSONException | URISyntaxException e) { - e.printStackTrace(); + public static class Version implements Comparable { + private enum Tag { + ALPHA, BETA, RC, SNAPSHOT } - return null; - } - protected JSONObject getRemote() throws IOException { - long current = System.currentTimeMillis(); - if ((current - lastCheck) > 1000 || cache == null) { - URL url = new URL(Constants.URL_LATEST_RELEASE_API); - String s = IOUtils.toString(url.openStream(), "UTF-8"); - cache = new JSONObject(s); - lastCheck = current; - return cache; - } else - return cache; - } + static Pattern characters = Pattern.compile("[a-zA-Z]+");; - public static class Version implements Comparable { private static final String DEFAULT_VERSION = "0.0.1-SNAPSHOT"; - - private enum Tag { - ALPHA, BETA, SNAPSHOT, RC - }; - static Pattern numbers = Pattern.compile("\\d+"); - static Pattern characters = Pattern.compile("[a-zA-Z]+"); + static Version version = null; + public static Version get() { + if (version == null) { + // for demo purposes + // String s = "1.8.0"; + String s = Annotator.class.getPackage().getImplementationVersion(); + if (s == null) + s = DEFAULT_VERSION; + version = new Version(s); + } + return version; + } + public static Version get(String s) { + return new Version(s); + } int major = 0; int minor = 0; int patch = 0; - String tagString = null; - int tagLevel = 0; + Tag tag = null; - static Version version = null; + int tagLevel = 0; + + String tagString = null; private Version(String versionString) { String[] parts = versionString.split("[\\.-]"); @@ -92,22 +66,6 @@ private Version(String versionString) { } } - public static Version get(String s) { - return new Version(s); - } - - public static Version get() { - if (version == null) { - // for demo purposes - // String s = "1.8.0"; - String s = Annotator.class.getPackage().getImplementationVersion(); - if (s == null) - s = DEFAULT_VERSION; - version = new Version(s); - } - return version; - } - @Override public int compareTo(Version o) { int r = Integer.compare(this.major, o.major); @@ -136,13 +94,13 @@ public int compareTo(Version o) { } @Override - public int hashCode() { - return toString().hashCode(); + public boolean equals(Object o) { + return toString().equals(o.toString()); } @Override - public boolean equals(Object o) { - return toString().equals(o.toString()); + public int hashCode() { + return toString().hashCode(); } @Override @@ -151,4 +109,49 @@ public String toString() { } } + private static final String HTML_URL = "html_url"; + private static final String TAG_NAME = "tag_name"; + transient JSONObject cache = null; + + long lastCheck = Long.MIN_VALUE; + + public boolean checkForUpdate() throws IOException { + Version current = Version.get(); + + JSONObject o; + o = getRemote(); + String tagName = o.getString(TAG_NAME); + Version remote = Version.get(tagName.substring(1)); + return current.compareTo(remote) < 0; + } + + public URI getReleasePage() throws IOException { + JSONObject o = getRemote(); + try { + return new URI(o.getString(HTML_URL)); + } catch (JSONException | URISyntaxException e) { + e.printStackTrace(); + } + return null; + } + + protected JSONObject getRemote() throws IOException { + long current = System.currentTimeMillis(); + if ((current - lastCheck) > 1000 || cache == null) { + URL url = new URL(Constants.URL_LATEST_RELEASE_API); + try (InputStream is = url.openStream()) { + String s = IOUtils.toString(url.openStream(), "UTF-8"); + cache = new JSONObject(s); + lastCheck = current; + } + return cache; + } else + return cache; + } + + public Version getRemoteVersion() throws IOException { + JSONObject o = getRemote(); + String tagName = o.getString(TAG_NAME); + return Version.get(tagName.substring(1)); + } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/Util.java b/src/main/java/de/unistuttgart/ims/coref/annotator/Util.java index 5e1f417e..716587b5 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/Util.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/Util.java @@ -7,23 +7,6 @@ import javax.swing.tree.TreeModel; import javax.swing.tree.TreeNode; -import org.apache.uima.cas.CASException; -import org.apache.uima.cas.CASRuntimeException; -import org.apache.uima.cas.Feature; -import org.apache.uima.cas.FeatureStructure; -import org.apache.uima.fit.util.JCasUtil; -import org.apache.uima.jcas.JCas; -import org.apache.uima.jcas.cas.FSArray; -import org.apache.uima.jcas.cas.StringArray; -import org.apache.uima.jcas.cas.TOP; -import org.apache.uima.jcas.tcas.Annotation; -import org.eclipse.collections.api.list.MutableList; -import org.eclipse.collections.impl.factory.Lists; - -import de.unistuttgart.ims.coref.annotator.api.Meta; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; - public class Util { private static String[] languageNames = null; @@ -49,180 +32,6 @@ public static String toString(javax.swing.tree.TreeNode tn, int level) { } - public static boolean contains(StringArray array, String s) { - if (array == null) - return false; - for (int i = 0; i < array.size(); i++) - if (array.get(i).equals(s)) - return true; - return false; - } - - public static void addFlagKey(FeatureStructure fs, String flagKey) { - Feature feature = fs.getType().getFeatureByBaseName("Flags"); - try { - StringArray arr = addTo(fs.getCAS().getJCas(), (StringArray) fs.getFeatureValue(feature), flagKey); - fs.setFeatureValue(feature, arr); - } catch (CASRuntimeException | CASException e) { - e.printStackTrace(); - } - } - - public static void removeFlagKey(FeatureStructure fs, String flagKey) { - Feature feature = fs.getType().getFeatureByBaseName("Flags"); - try { - StringArray arr = removeFrom(fs.getCAS().getJCas(), (StringArray) fs.getFeatureValue(feature), flagKey); - fs.setFeatureValue(feature, arr); - } catch (CASRuntimeException | CASException e) { - e.printStackTrace(); - } - - } - - public static StringArray removeFrom(JCas jcas, StringArray arr, String fs) { - int i = 0, j = 0; - StringArray nArr = null; - int oldSize = arr == null ? 0 : arr.size(); - nArr = new StringArray(jcas, oldSize - 1); - for (; i < oldSize; i++, j++) { - if (!arr.get(i).equals(fs)) - nArr.set(j, arr.get(i)); - else - j--; - } - return nArr; - } - - public static FSArray removeFrom(JCas jcas, FSArray arr, FeatureStructure fs) { - int i = 0, j = 0; - FSArray nArr = null; - arr.removeFromIndexes(); - int oldSize = arr == null ? 0 : arr.size(); - nArr = new FSArray(jcas, oldSize - 1); - for (; i < oldSize; i++, j++) { - if (!arr.get(i).equals(fs)) - nArr.set(j, arr.get(i)); - else - j--; - } - nArr.addToIndexes(); - return nArr; - } - - public static StringArray addTo(JCas jcas, StringArray arr, String fs) { - int i = 0; - StringArray nArr; - int oldSize = arr == null ? 0 : arr.size(); - if (arr != null) { - nArr = new StringArray(jcas, oldSize + 1); - for (; i < oldSize; i++) { - nArr.set(i, arr.get(i)); - } - } else { - nArr = new StringArray(jcas, 1); - } - nArr.set(i, fs); - if (arr != null) - arr.removeFromIndexes(); - nArr.addToIndexes(); - return nArr; - - } - - public static FSArray addTo(JCas jcas, FSArray arr, FeatureStructure fs) { - int i = 0; - FSArray nArr; - if (arr != null) { - nArr = new FSArray(jcas, arr.size() + 1); - for (; i < arr.size(); i++) { - nArr.set(i, arr.get(i)); - } - } else { - nArr = new FSArray(jcas, 1); - } - nArr.set(i, fs); - arr.removeFromIndexes(); - nArr.addToIndexes(); - return nArr; - - } - - public static boolean isX(FeatureStructure fs, String flag) { - Feature feature = fs.getType().getFeatureByBaseName("Flags"); - return Util.contains((StringArray) fs.getFeatureValue(feature), flag); - } - - @Deprecated - public static boolean isGeneric(Entity e) { - return Util.contains(e.getFlags(), Constants.ENTITY_FLAG_GENERIC); - } - - @Deprecated - public static boolean isDifficult(Mention m) { - return Util.contains(m.getFlags(), Constants.MENTION_FLAG_DIFFICULT); - } - - @Deprecated - public static boolean isNonNominal(Mention m) { - return Util.contains(m.getFlags(), Constants.MENTION_FLAG_NON_NOMINAL); - } - - @Deprecated - public static boolean isAmbiguous(Mention m) { - return Util.contains(m.getFlags(), Constants.MENTION_FLAG_AMBIGUOUS); - } - - public static Meta getMeta(JCas jcas) { - if (!JCasUtil.exists(jcas, Meta.class)) { - Meta m = new Meta(jcas); - m.addToIndexes(); - return m; - } - try { - return JCasUtil.selectSingle(jcas, Meta.class); - } catch (IllegalArgumentException e) { - Annotator.logger.catching(e); - return null; - } - } - - public static T extend(T annotation) { - final char[] s = annotation.getCoveredText().toCharArray(); - char[] text = annotation.getCAS().getDocumentText().toCharArray(); - if (s.length == 0) - return annotation; - - int b = annotation.getBegin(), e = annotation.getEnd(); - - if (b > 0) { - char prev = text[b - 1]; - while (b > 0 && Character.isLetter(prev)) { - b--; - // if we have reached the beginning, we pretend the - // previous character to be a white space. - if (b == 0) - prev = ' '; - else - prev = text[b - 1]; - } - } - - if (e < text.length) { - char next = text[e]; - while (e < text.length && Character.isLetter(next)) { - e++; - if (e == text.length) - next = ' '; - else - next = text[e]; - } - } - - annotation.setBegin(b); - annotation.setEnd(e); - return annotation; - } - public static String[] getSupportedLanguageNames() { if (languageNames == null) { languageNames = new String[Constants.SUPPORTED_LANGUAGES.length]; @@ -247,51 +56,6 @@ public static String getLanguage(String languageName) { return null; } - public static int count(JCas jcas, Class cl) { - return JCasUtil.select(jcas, cl).size(); - } - - @SuppressWarnings("unchecked") - public static MutableList toList(FSArray arr) { - MutableList list = Lists.mutable.empty(); - arr.forEach(fs -> list.add((T) fs)); - return list; - } - - public static StringArray getFlags(FeatureStructure fs) throws CASException { - Feature feature = fs.getType().getFeatureByBaseName("Flags"); - if (feature == null) - return new StringArray(fs.getCAS().getJCas(), 0); - else { - StringArray sa = (StringArray) fs.getFeatureValue(feature); - if (sa == null) - return new StringArray(fs.getCAS().getJCas(), 0); - else - return sa; - } - } - - public static String[] getFlagsAsStringArray(FeatureStructure fs) { - Feature feature = fs.getType().getFeatureByBaseName("Flags"); - if (feature == null) - return new String[0]; - else { - StringArray sa = (StringArray) fs.getFeatureValue(feature); - if (sa == null) - return new String[0]; - else - return sa.toStringArray(); - } - } - - public static void setFlags(FeatureStructure fs, StringArray arr) throws CASException { - Feature feature = fs.getType().getFeatureByBaseName("Flags"); - if (feature == null) - return; - else - fs.setFeatureValue(feature, arr); - } - public static > T randomEnum(Class clazz) { int x = Constants.RANDOM.nextInt(clazz.getEnumConstants().length); return clazz.getEnumConstants()[x]; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/AddCurrentSpanToCurrentEntity.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/AddCurrentSpanToCurrentEntity.java index 52a49eaf..4ae0943d 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/AddCurrentSpanToCurrentEntity.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/AddCurrentSpanToCurrentEntity.java @@ -11,7 +11,6 @@ import de.unistuttgart.ims.coref.annotator.Constants; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToEntity; import de.unistuttgart.ims.coref.annotator.document.op.MoveMentionsToEntity; @@ -31,9 +30,9 @@ public void actionPerformed(ActionEvent evt) { if (((CATreeNode) tp.getLastPathComponent()).isEntity()) { CATreeNode etn = (CATreeNode) tp.getLastPathComponent(); if (Annotator.app.getPreferences().getBoolean(Constants.CFG_REPLACE_MENTION, false) - && getTarget().getSelectedAnnotations(Mention.class).size() == 1) { - getTarget().getDocumentModel().edit(new MoveMentionsToEntity(etn.getEntity(), - getTarget().getSelectedAnnotations(Mention.class))); + && getTarget().getSelectedMentions().size() == 1) { + getTarget().getDocumentModel() + .edit(new MoveMentionsToEntity(etn.getEntity(), getTarget().getSelectedMentions())); } else getTarget().getDocumentModel().edit(new AddMentionsToEntity(etn.getEntity(), new Span(b, e))); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/AddFlagAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/AddFlagAction.java index 9f3c455a..02f8d1bb 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/AddFlagAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/AddFlagAction.java @@ -10,8 +10,8 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.op.AddFlag; public class AddFlagAction extends TargetedOperationIkonAction { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/AnalyzeAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/AnalyzeAction.java new file mode 100644 index 00000000..09797746 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/AnalyzeAction.java @@ -0,0 +1,30 @@ +package de.unistuttgart.ims.coref.annotator.action; + +import java.awt.event.ActionEvent; + +import javax.swing.Action; + +import org.kordamp.ikonli.materialdesign.MaterialDesign; + +import de.unistuttgart.ims.coref.annotator.AbstractTextWindow; +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.analyzer.AnalyzerWindow; + +public class AnalyzeAction extends TargetedIkonAction { + + private static final long serialVersionUID = 1L; + + public AnalyzeAction(AbstractTextWindow dw) { + super(dw, MaterialDesign.MDI_CHART_LINE); + putValue(Action.NAME, Annotator.getString(Strings.ACTION_ANALYZER)); + putValue(Action.SHORT_DESCRIPTION, Annotator.getString(Strings.ACTION_ANALYZER_TOOLTIP)); + } + + @Override + public void actionPerformed(ActionEvent e) { + AnalyzerWindow aw = new AnalyzerWindow(); + aw.setDocumentModel(getTarget().getDocumentModel()); + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ChangeKeyForEntityAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ChangeKeyForEntityAction.java index 9a4d6be4..7a6f8f16 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ChangeKeyForEntityAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ChangeKeyForEntityAction.java @@ -17,7 +17,7 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; import de.unistuttgart.ims.coref.annotator.document.op.UpdateEntityKey; public class ChangeKeyForEntityAction extends TargetedOperationIkonAction { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteAction.java index ef42aa19..7669d0e4 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteAction.java @@ -1,6 +1,5 @@ package de.unistuttgart.ims.coref.annotator.action; -import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; @@ -13,7 +12,6 @@ import javax.swing.tree.TreePath; import org.apache.uima.cas.FeatureStructure; -import org.apache.uima.jcas.tcas.Annotation; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.api.set.MutableSet; @@ -26,15 +24,15 @@ import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; import de.unistuttgart.ims.coref.annotator.TreeSelectionUtil; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.coref.annotator.document.op.Operation; import de.unistuttgart.ims.coref.annotator.document.op.RemoveEntities; import de.unistuttgart.ims.coref.annotator.document.op.RemoveEntitiesFromEntityGroup; import de.unistuttgart.ims.coref.annotator.document.op.RemoveMention; -import de.unistuttgart.ims.coref.annotator.document.op.RemovePart; +import de.unistuttgart.ims.coref.annotator.document.op.RemoveMentionSurface; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class DeleteAction extends TargetedIkonAction implements CaretListener, TreeSelectionListener { @@ -54,8 +52,6 @@ public DeleteAction(DocumentWindow documentWindow) { public DeleteAction(DocumentWindow documentWindow, FeatureStructure featureStructure) { super(documentWindow, Strings.ACTION_DELETE, MaterialDesign.MDI_DELETE); putValue(Action.SHORT_DESCRIPTION, Annotator.getString(Strings.ACTION_DELETE_TOOLTIP)); - putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); this.featureStructure = featureStructure; } @@ -67,10 +63,10 @@ public void actionPerformed(ActionEvent e) { if (e.getSource() == getTarget().getTextPane()) { int low = getTarget().getTextPane().getSelectionStart(); int high = getTarget().getTextPane().getSelectionEnd(); - MutableSet annotations = Sets.mutable + MutableSet annotations = Sets.mutable .withAll(getTarget().getDocumentModel().getCoreferenceModel().getMentions(low)); MutableSet mentions = annotations.selectInstancesOf(Mention.class) - .select(a -> a.getBegin() == low && a.getEnd() == high); + .select(a -> UimaUtil.getBegin(a) == low && UimaUtil.getEnd(a) == high); MutableMap> mentionsByEntity = mentions.aggregateBy(m -> m.getEntity(), () -> Sets.mutable.empty(), (set, mention) -> { @@ -85,25 +81,22 @@ public void actionPerformed(ActionEvent e) { if (fs instanceof Entity) { FeatureStructure parentFs = node.getParent().getFeatureStructure(); - if (parentFs instanceof EntityGroup) { - operations.add(new RemoveEntitiesFromEntityGroup((EntityGroup) parentFs, node.getEntity())); + if (UimaUtil.isGroup(parentFs)) { + operations.add(new RemoveEntitiesFromEntityGroup((Entity) parentFs, node.getEntity())); } else if (node.isLeaf()) { operations.add(new RemoveEntities(getTarget().getSelectedEntities())); } } else if (fs instanceof Mention) { operations.add(new RemoveMention(selection.collect(tp -> (CATreeNode) tp.getLastPathComponent()) .collect(tn -> (Mention) tn.getFeatureStructure()))); - } else if (fs instanceof DetachedMentionPart) { - operations.add(new RemovePart(((DetachedMentionPart) fs).getMention(), (DetachedMentionPart) fs)); } } + } else if (featureStructure instanceof MentionSurface) { + operations.add(new RemoveMentionSurface((MentionSurface) featureStructure)); } else if (featureStructure instanceof Mention) { operations.add(new RemoveMention((Mention) featureStructure)); } else if (featureStructure instanceof Entity) { operations.add(new RemoveEntities((Entity) featureStructure)); - } else if (featureStructure instanceof DetachedMentionPart) { - DetachedMentionPart dmp = (DetachedMentionPart) featureStructure; - operations.add(new RemovePart(dmp.getMention(), dmp)); } if (!operations.isEmpty()) operations.forEach(op -> getTarget().getDocumentModel().edit(op)); @@ -121,8 +114,7 @@ public void caretUpdate(CaretEvent e) { public void valueChanged(TreeSelectionEvent e) { TreeSelectionUtil tsu = new TreeSelectionUtil(); tsu.collectData(e); - enabledByTree = tsu.isDetachedMentionPart() || tsu.isMention() || (tsu.isEntityGroup() && tsu.isLeaf()) - || (tsu.isEntity() && tsu.isLeaf()); + enabledByTree = tsu.isMention() || (tsu.isEntityGroup() && tsu.isLeaf()) || (tsu.isEntity() && tsu.isLeaf()); disabledByModel = tsu.getFeatureStructures().collect(fs -> getOperation(fs)) .collect(op -> getTarget().getDocumentModel().isBlocked(op)).contains(true); setStatus(); @@ -138,8 +130,6 @@ protected Class getOperation(FeatureStructure fs) { return RemoveMention.class; else if (fs instanceof Entity) return RemoveEntities.class; - else if (fs instanceof DetachedMentionPart) - return RemovePart.class; return null; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteAllMentionsInSelection.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteAllMentionsInSelection.java index 3c54bb54..522bf9d3 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteAllMentionsInSelection.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteAllMentionsInSelection.java @@ -6,7 +6,6 @@ import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; -import org.apache.uima.jcas.tcas.Annotation; import org.eclipse.collections.api.set.MutableSet; import org.eclipse.collections.impl.factory.Sets; import org.kordamp.ikonli.materialdesign.MaterialDesign; @@ -14,7 +13,7 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.op.RemoveMention; public class DeleteAllMentionsInSelection extends TargetedIkonAction implements CaretListener { @@ -32,10 +31,9 @@ public void actionPerformed(ActionEvent e) { int high = getTarget().getTextPane().getSelectionEnd(); if (low == high) return; - MutableSet annotations = Sets.mutable + MutableSet annotations = Sets.mutable .withAll(getTarget().getDocumentModel().getCoreferenceModel().getMentionsBetween(low, high)); - @SuppressWarnings("unchecked") - MutableSet mentions = (MutableSet) annotations.select(a -> a instanceof Mention); + MutableSet mentions = annotations.select(a -> a instanceof Mention); mentions.groupBy(m -> m.getEntity()) .forEachKeyMultiValues((entity, ms) -> getTarget().getDocumentModel().edit((new RemoveMention(ms)))); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteFlagAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteFlagAction.java index e740e21b..e1275870 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteFlagAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/DeleteFlagAction.java @@ -10,10 +10,9 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; import de.unistuttgart.ims.coref.annotator.Annotator; -import de.unistuttgart.ims.coref.annotator.Constants; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; import de.unistuttgart.ims.coref.annotator.document.op.DeleteFlag; public class DeleteFlagAction extends TargetedOperationIkonAction implements ListSelectionListener { @@ -51,19 +50,6 @@ public void setTable(JTable table) { @Override public void valueChanged(ListSelectionEvent e) { - if (!e.getValueIsAdjusting()) { - int row = table.getSelectedRow(); - try { - String key = (String) table.getModel().getValueAt(row, 1); - setEnabled(!(key.equals(Constants.ENTITY_FLAG_GENERIC) || key.equals(Constants.ENTITY_FLAG_HIDDEN) - || key.equals(Constants.MENTION_FLAG_AMBIGUOUS) || key.equals(Constants.MENTION_FLAG_DIFFICULT) - || key.equals(Constants.MENTION_FLAG_NON_NOMINAL))); - } catch (IndexOutOfBoundsException ex) { - setEnabled(false); - } - - } - } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/DuplicateMentions.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/DuplicateMentions.java index b36c597b..f4c0353b 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/DuplicateMentions.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/DuplicateMentions.java @@ -14,7 +14,7 @@ import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; import de.unistuttgart.ims.coref.annotator.TreeSelectionUtil; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class DuplicateMentions extends TargetedIkonAction implements TreeSelectionListener { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ExampleExport.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ExampleExport.java index 21b3cde6..51cf382e 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ExampleExport.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ExampleExport.java @@ -21,6 +21,7 @@ import de.unistuttgart.ims.uima.io.xml.GenericInlineWriter; import de.unistuttgart.ims.uima.io.xml.InlineTagFactory; +// TODO: Update for typesystem v2 public class ExampleExport extends DocumentWindowAction { private static final long serialVersionUID = 1L; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileCompareOpenAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileCompareOpenAction.java index dc64b257..cec65b78 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileCompareOpenAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileCompareOpenAction.java @@ -1,10 +1,8 @@ package de.unistuttgart.ims.coref.annotator.action; -import java.awt.Component; import java.awt.event.ActionEvent; import java.io.File; -import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.SwingUtilities; @@ -17,7 +15,6 @@ import de.unistuttgart.ims.coref.annotator.CompareMentionsWindow; import de.unistuttgart.ims.coref.annotator.CompareMentionsWindow.NotComparableException; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.comp.SelectTwoFiles; import de.unistuttgart.ims.coref.annotator.worker.JCasLoader; public class FileCompareOpenAction extends IkonAction { @@ -76,62 +73,4 @@ public void run() { }, ""); } - @Deprecated - class RunComparisonAction extends AbstractAction { - - private static final long serialVersionUID = 1L; - - public RunComparisonAction() { - putValue(Action.NAME, "Compare"); - } - - @Override - public void actionPerformed(ActionEvent e) { - SelectTwoFiles stf = (SelectTwoFiles) SwingUtilities.getWindowAncestor((Component) e.getSource()); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - CompareMentionsWindow cmw; - - try { - cmw = new CompareMentionsWindow(Annotator.app, stf.getFiles().size()); - cmw.setIndeterminateProgress(); - cmw.setVisible(true); - cmw.setFiles(stf.getFiles()); - - for (int i = 0; i < stf.getFiles().size(); i++) { - final int j = i; - - new JCasLoader(stf.getFiles().get(i), jcas -> { - try { - cmw.setJCas(jcas, stf.getNames().get(j), j); - } catch (NotComparableException e1) { - cmw.setVisible(false); - cmw.dispose(); - Annotator.app.warnDialog(e1.getLocalizedMessage(), "Loading Error"); - Annotator.logger.catching(e1); - } - }, ex -> { - cmw.setVisible(false); - cmw.dispose(); - Annotator.app.warnDialog(ex.getLocalizedMessage(), "Loading Error"); - }).execute(); - - } - cmw.setVisible(true); - cmw.pack(); - SwingUtilities.getWindowAncestor((Component) e.getSource()).setVisible(false); - } catch (UIMAException e1) { - Annotator.logger.catching(e1); - } - } - - }); - - } - - } - } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileMergeOpenAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileMergeOpenAction.java index aaa086ff..51b26ecf 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileMergeOpenAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileMergeOpenAction.java @@ -1,10 +1,8 @@ package de.unistuttgart.ims.coref.annotator.action; -import java.awt.Component; import java.awt.event.ActionEvent; import java.io.File; -import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.SwingUtilities; @@ -15,7 +13,6 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.comp.SelectTwoFiles; import de.unistuttgart.ims.coref.annotator.uima.MergeFilesPlugin; public class FileMergeOpenAction extends IkonAction { @@ -47,34 +44,4 @@ public void run() { }, ""); } - @Deprecated - class RunMergeAction extends AbstractAction { - - private static final long serialVersionUID = 1L; - - public RunMergeAction() { - putValue(Action.NAME, "Merge"); - } - - @Override - public void actionPerformed(ActionEvent e) { - SelectTwoFiles stf = (SelectTwoFiles) SwingUtilities.getWindowAncestor((Component) e.getSource()); - - MergeFilesPlugin pl = new MergeFilesPlugin(); - pl.setFiles(stf.getFiles().toImmutable()); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - DocumentWindow dw = Annotator.app.open(stf.getFiles().getFirst(), pl, ""); - dw.setFile(null); - } - - }); - - } - - } - } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileSaveAsAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileSaveAsAction.java index 94521945..819fcd8a 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileSaveAsAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileSaveAsAction.java @@ -9,12 +9,15 @@ import javax.swing.Action; import javax.swing.JFileChooser; import javax.swing.KeyStroke; +import javax.swing.filechooser.FileFilter; import org.apache.uima.jcas.JCas; import org.kordamp.ikonli.materialdesign.MaterialDesign; import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.DocumentWindow; +import de.unistuttgart.ims.coref.annotator.ExtensionFilters; +import de.unistuttgart.ims.coref.annotator.FileFilters; import de.unistuttgart.ims.coref.annotator.Strings; import de.unistuttgart.ims.coref.annotator.worker.SaveJCasWorker; import javafx.application.Platform; @@ -40,13 +43,13 @@ public void run() { javafx.stage.FileChooser fileChooser = new javafx.stage.FileChooser(); fileChooser.setTitle(Annotator.getString(Strings.DIALOG_SAVE_AS_TITLE)); fileChooser.setInitialDirectory(Annotator.app.getCurrentDirectory()); - fileChooser.getExtensionFilters() - .add(Annotator.app.getPluginManager().getDefaultIOPlugin().getExtensionFilter()); + fileChooser.getExtensionFilters().add(ExtensionFilters.ca2); + fileChooser.setInitialFileName(getTarget().getProposedFilename()); File f = fileChooser.showSaveDialog(null); if (f != null) { - if (!f.getName().endsWith(".xmi") && !f.getName().endsWith(".xmi.gz")) - f = new File(f.getAbsolutePath() + ".xmi.gz"); + if (!(f.getName().endsWith(".ca2")) && !(f.getName().endsWith(".ca2z"))) + f = new File(f.getAbsolutePath() + ".ca2z"); BiConsumer bicons; if (closeAfterSaving) { @@ -72,15 +75,32 @@ public void run() { else saveDialog = new JFileChooser(getTarget().getFile().getParentFile()); saveDialog.setDialogType(JFileChooser.SAVE_DIALOG); - saveDialog.setFileFilter(Annotator.app.getPluginManager().getDefaultIOPlugin().getFileFilter()); + saveDialog.setFileFilter(new FileFilter() { + + @Override + public boolean accept(File f) { + return FileFilters.ca2.accept(f); + } + + @Override + public String getDescription() { + return FileFilters.ca2.getDescription(); + } + + }); saveDialog.setDialogTitle(Annotator.getString(Strings.DIALOG_SAVE_AS_TITLE)); saveDialog.setCurrentDirectory(Annotator.app.getCurrentDirectory()); + if (getTarget().getProposedFilename() != null) { + File proposedFile = new File(Annotator.app.getCurrentDirectory(), + getTarget().getProposedFilename() + ".ca2z"); + saveDialog.setSelectedFile(proposedFile); + } int r = saveDialog.showSaveDialog(getTarget()); switch (r) { case JFileChooser.APPROVE_OPTION: File f = saveDialog.getSelectedFile(); - if (!f.getName().endsWith(".xmi") && !f.getName().endsWith(".xmi.gz")) - f = new File(f.getAbsolutePath() + ".xmi.gz"); + if (!(f.getName().endsWith(".ca2")) && !(f.getName().endsWith(".ca2z"))) + f = new File(f.getAbsolutePath() + ".ca2z"); SaveJCasWorker worker = new SaveJCasWorker(f, target.getDocumentModel().getJcas(), SaveJCasWorker.getConsumer(getTarget())); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileSelectAnalyzeAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileSelectAnalyzeAction.java new file mode 100644 index 00000000..d8f783ad --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/FileSelectAnalyzeAction.java @@ -0,0 +1,40 @@ +package de.unistuttgart.ims.coref.annotator.action; + +import java.awt.event.ActionEvent; + +import javax.swing.Action; + +import org.kordamp.ikonli.materialdesign.MaterialDesign; + +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.analyzer.AnalyzerWindow; +import de.unistuttgart.ims.coref.annotator.worker.DocumentModelLoader; +import de.unistuttgart.ims.coref.annotator.worker.JCasLoader; + +public class FileSelectAnalyzeAction extends IkonAction { + + private static final long serialVersionUID = 1L; + + public FileSelectAnalyzeAction() { + super(MaterialDesign.MDI_CHART_LINE); + putValue(Action.NAME, Annotator.getString(Strings.ACTION_ANALYZER)); + } + + @Override + public void actionPerformed(ActionEvent e) { + AnalyzerWindow aw = new AnalyzerWindow(); + Annotator.app.fileOpenDialog(null, Annotator.app.getPluginManager().getDefaultIOPlugin(), false, file -> { + JCasLoader loader = new JCasLoader(file[0], jcas -> { + DocumentModelLoader dml = new DocumentModelLoader(dm -> { + dm.setFile(file[0]); + aw.setDocumentModel(dm); + }, jcas); + dml.execute(); + }, ex -> { + }); + loader.execute(); + }, o -> Annotator.app.showOpening(), ""); + + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/IkonAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/IkonAction.java index a7a62e80..33c85128 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/IkonAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/IkonAction.java @@ -21,12 +21,14 @@ public abstract class IkonAction extends AbstractAction { MutableList ikon; Color enabledColor = Color.BLACK; Color disabledColor = Color.GRAY; + static int smallIkonSize = 12; + static int largeIkonSize = 16; public IkonAction(Ikon... icon) { this.ikon = Lists.mutable.of(icon); try { - putValue(Action.LARGE_ICON_KEY, FontIcon.of(ikon.get(0), enabledColor)); - putValue(Action.SMALL_ICON, FontIcon.of(ikon.get(0), enabledColor)); + putValue(Action.LARGE_ICON_KEY, getLargeIcon(ikon.get(0))); + putValue(Action.SMALL_ICON, getSmallIcon(ikon.get(0))); } catch (UnsupportedOperationException e) { Annotator.logger.catching(e); } @@ -37,8 +39,8 @@ public IkonAction(String stringKey, Ikon... icon) { putValue(Action.NAME, Annotator.getString(stringKey)); try { if (icon != null) { - putValue(Action.LARGE_ICON_KEY, getIcon()); - putValue(Action.SMALL_ICON, getIcon()); + putValue(Action.LARGE_ICON_KEY, getLargeIcon()); + putValue(Action.SMALL_ICON, getSmallIcon()); } } catch (UnsupportedOperationException e) { Annotator.logger.catching(e); @@ -53,8 +55,8 @@ public IkonAction(String stringKey, boolean isKey, Ikon... icon) { putValue(Action.NAME, Annotator.getStringWithDefault(stringKey, stringKey)); try { if (icon != null) { - putValue(Action.LARGE_ICON_KEY, getIcon()); - putValue(Action.SMALL_ICON, getIcon()); + putValue(Action.LARGE_ICON_KEY, getLargeIcon()); + putValue(Action.SMALL_ICON, getSmallIcon()); } } catch (UnsupportedOperationException e) { Annotator.logger.catching(e); @@ -65,8 +67,8 @@ public IkonAction(String stringKey, boolean isKey, Ikon... icon) { public void setEnabled(boolean b) { super.setEnabled(b); try { - putValue(Action.LARGE_ICON_KEY, getIcon()); - putValue(Action.SMALL_ICON, getIcon()); + putValue(Action.LARGE_ICON_KEY, getLargeIcon()); + putValue(Action.SMALL_ICON, getSmallIcon()); } catch (UnsupportedOperationException e) { Annotator.logger.catching(e); } @@ -78,16 +80,24 @@ public Ikon getIkon() { public void addIkon(Ikon ik) { ikon.add(ik); - putValue(Action.LARGE_ICON_KEY, getIcon()); - putValue(Action.SMALL_ICON, getIcon()); + putValue(Action.LARGE_ICON_KEY, getLargeIcon()); + putValue(Action.SMALL_ICON, getSmallIcon()); } - protected Icon getIcon(Ikon ik) { - return FontIcon.of(ik, (isEnabled() ? enabledColor : disabledColor)); + protected Icon getSmallIcon(Ikon ik) { + return FontIcon.of(ik, smallIkonSize, (isEnabled() ? enabledColor : disabledColor)); } - public Icon getIcon() { - return new CompoundIcon(ikon.collect(ik -> getIcon(ik)).toArray(new Icon[ikon.size()])); + protected Icon getLargeIcon(Ikon ik) { + return FontIcon.of(ik, largeIkonSize, (isEnabled() ? enabledColor : disabledColor)); + } + + public Icon getSmallIcon() { + return new CompoundIcon(ikon.collect(ik -> getSmallIcon(ik)).toArray(new Icon[ikon.size()])); + } + + public Icon getLargeIcon() { + return new CompoundIcon(ikon.collect(ik -> getLargeIcon(ik)).toArray(new Icon[ikon.size()])); } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/MergeAllAdjacentMentions.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/MergeAllAdjacentMentions.java index be98a806..83985ae3 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/MergeAllAdjacentMentions.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/MergeAllAdjacentMentions.java @@ -1,14 +1,16 @@ package de.unistuttgart.ims.coref.annotator.action; import java.awt.event.ActionEvent; +import java.util.Iterator; -import org.apache.uima.cas.FSIterator; import org.apache.uima.jcas.JCas; +import org.eclipse.collections.api.set.sorted.ImmutableSortedSet; +import org.eclipse.collections.impl.factory.SortedSets; import org.kordamp.ikonli.materialdesign.MaterialDesign; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class MergeAllAdjacentMentions extends TargetedIkonAction { @@ -21,7 +23,10 @@ public MergeAllAdjacentMentions(DocumentWindow dw) { @Override public void actionPerformed(ActionEvent e) { JCas jcas = getTarget().getJCas(); - FSIterator mentionIterator = jcas.getAnnotationIndex(Mention.class).iterator(); + + ImmutableSortedSet mentions = SortedSets.immutable.withAll(jcas.getIndexedFSs(Mention.class)); + + Iterator mentionIterator = mentions.iterator(); Mention current = null, previous = null; while (mentionIterator.hasNext()) { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ProcessAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ProcessAction.java index 37d30a25..682403df 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ProcessAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ProcessAction.java @@ -13,8 +13,8 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; import de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity; +import de.unistuttgart.ims.coref.annotator.AbstractWindow; import de.unistuttgart.ims.coref.annotator.Annotator; -import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Span; import de.unistuttgart.ims.coref.annotator.document.DocumentState; import de.unistuttgart.ims.coref.annotator.document.DocumentStateListener; @@ -22,13 +22,13 @@ import de.unistuttgart.ims.coref.annotator.document.op.Operation; import de.unistuttgart.ims.coref.annotator.plugins.ProcessingPlugin; -public class ProcessAction extends DocumentWindowAction implements DocumentStateListener { +public class ProcessAction extends TargetedIkonAction implements DocumentStateListener { private static final long serialVersionUID = 1L; ProcessingPlugin plugin; - public ProcessAction(DocumentWindow dw, ProcessingPlugin plugin) { + public ProcessAction(AbstractWindow dw, ProcessingPlugin plugin) { super(dw, plugin.getName(), false, MaterialDesign.MDI_AUTO_FIX); this.plugin = plugin; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/RemoveDuplicatesAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/RemoveDuplicatesAction.java index 5a255282..d1d82648 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/RemoveDuplicatesAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/RemoveDuplicatesAction.java @@ -12,7 +12,7 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.CATreeNode; import de.unistuttgart.ims.coref.annotator.DocumentWindow; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; import de.unistuttgart.ims.coref.annotator.document.op.RemoveDuplicateMentionsInEntities; public class RemoveDuplicatesAction extends DocumentWindowAction { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/RemoveMentionAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/RemoveMentionAction.java index 8a37d657..748169b3 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/RemoveMentionAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/RemoveMentionAction.java @@ -9,7 +9,7 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.op.RemoveMention; @Deprecated diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectNextMentionAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectNextMentionAction.java index a63f73d8..d383428d 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectNextMentionAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectNextMentionAction.java @@ -4,25 +4,30 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; +import de.unistuttgart.ims.coref.annotator.AbstractTextWindow; +import de.unistuttgart.ims.coref.annotator.CompareMentionsWindow; import de.unistuttgart.ims.coref.annotator.DocumentWindow; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; -public class SelectNextMentionAction extends TargetedIkonAction { +public class SelectNextMentionAction extends TargetedIkonAction { private static final long serialVersionUID = 1L; - public SelectNextMentionAction(DocumentWindow dw) { + public SelectNextMentionAction(AbstractTextWindow dw) { super(dw, MaterialDesign.MDI_ARROW_RIGHT); } @Override public void actionPerformed(ActionEvent e) { - int high = getTarget().getTextPane().getSelectionEnd(); - - Mention nextMention = getTarget().getDocumentModel().getCoreferenceModel().getNextMention(high); - + int high = getTarget().getTextPane().getSelectionStart() + 1; + + MentionSurface nextMention = null; + if (getTarget() instanceof DocumentWindow) { + nextMention = getTarget().getDocumentModel().getCoreferenceModel().getNextMentionSurface(high); + } else if (getTarget() instanceof CompareMentionsWindow) { + nextMention = ((CompareMentionsWindow) getTarget()).getNextMentionSurface(high); + } if (nextMention != null) getTarget().annotationSelected(nextMention); - } } \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectPreviousMentionAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectPreviousMentionAction.java index 621fa2d6..5db64c5e 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectPreviousMentionAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectPreviousMentionAction.java @@ -4,12 +4,14 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; +import de.unistuttgart.ims.coref.annotator.AbstractTextWindow; +import de.unistuttgart.ims.coref.annotator.CompareMentionsWindow; import de.unistuttgart.ims.coref.annotator.DocumentWindow; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; -public class SelectPreviousMentionAction extends TargetedIkonAction { +public class SelectPreviousMentionAction extends TargetedIkonAction { - public SelectPreviousMentionAction(DocumentWindow dw) { + public SelectPreviousMentionAction(AbstractTextWindow dw) { super(dw, MaterialDesign.MDI_ARROW_LEFT); } @@ -17,8 +19,13 @@ public SelectPreviousMentionAction(DocumentWindow dw) { @Override public void actionPerformed(ActionEvent e) { - int low = getTarget().getTextPane().getSelectionStart(); - Mention nextMention = getTarget().getDocumentModel().getCoreferenceModel().getPreviousMention(low); + int low = getTarget().getTextPane().getSelectionEnd() - 1; + MentionSurface nextMention = null; + if (getTarget() instanceof DocumentWindow) { + nextMention = getTarget().getDocumentModel().getCoreferenceModel().getPreviousMentionSurface(low); + } else if (getTarget() instanceof CompareMentionsWindow) { + nextMention = ((CompareMentionsWindow) getTarget()).getPreviousMentionSurface(low); + } if (nextMention != null) getTarget().annotationSelected(nextMention); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectedFileOpenAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectedFileOpenAction.java index 57e46b33..de25a12d 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectedFileOpenAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SelectedFileOpenAction.java @@ -15,9 +15,13 @@ public class SelectedFileOpenAction extends IkonAction { public SelectedFileOpenAction(Annotator mApplication, File file) { super(MaterialDesign.MDI_OPEN_IN_APP); - putValue(Action.NAME, file.getName()); - putValue(Action.SHORT_DESCRIPTION, file.getPath()); - this.file = file; + if (file != null) { + putValue(Action.NAME, file.getName()); + putValue(Action.SHORT_DESCRIPTION, file.getPath()); + this.file = file; + } else { + this.setEnabled(false); + } } @Override @@ -32,4 +36,15 @@ public void run() { }.run(); } + public File getFile() { + return file; + } + + public void setFile(File file) { + putValue(Action.NAME, file.getName()); + putValue(Action.SHORT_DESCRIPTION, file.getPath()); + this.file = file; + this.setEnabled(true); + } + } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SetLanguageAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SetLanguageAction.java index bcf210ff..17628761 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SetLanguageAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SetLanguageAction.java @@ -7,16 +7,16 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; import org.kordamp.ikonli.swing.FontIcon; +import de.unistuttgart.ims.coref.annotator.AbstractWindow; import de.unistuttgart.ims.coref.annotator.Annotator; -import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; import de.unistuttgart.ims.coref.annotator.Util; import de.unistuttgart.ims.coref.annotator.document.op.UpdateDocumentProperty; -public class SetLanguageAction extends DocumentWindowAction { +public class SetLanguageAction extends TargetedIkonAction { private static final long serialVersionUID = 1L; - public SetLanguageAction(DocumentWindow dw) { + public SetLanguageAction(AbstractWindow dw) { super(dw, Strings.ACTION_SET_DOCUMENT_LANGUAGE, MaterialDesign.MDI_SWITCH); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowDocumentStatistics.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowDocumentStatistics.java index a16af1b0..d7d100ae 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowDocumentStatistics.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowDocumentStatistics.java @@ -2,9 +2,13 @@ import java.awt.event.ActionEvent; +import javax.swing.Action; + import org.kordamp.ikonli.materialdesign.MaterialDesign; +import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.DocumentWindow; +import de.unistuttgart.ims.coref.annotator.Strings; import de.unistuttgart.ims.coref.annotator.stats.DocumentStatisticsWindow; public class ShowDocumentStatistics extends TargetedIkonAction { @@ -13,6 +17,7 @@ public class ShowDocumentStatistics extends TargetedIkonAction { public ShowDocumentStatistics(DocumentWindow dw) { super(dw, "action.show_statistics", MaterialDesign.MDI_TABLE); + putValue(Action.SHORT_DESCRIPTION, Annotator.getString(Strings.ACTION_SHOW_DOCUMENT_STATISTICS_TOOLTIP)); } @SuppressWarnings("unused") diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowGuidelinesAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowGuidelinesAction.java new file mode 100644 index 00000000..6db67fdc --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowGuidelinesAction.java @@ -0,0 +1,57 @@ +package de.unistuttgart.ims.coref.annotator.action; + +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.net.URISyntaxException; + +import javax.swing.Action; + +import org.kordamp.ikonli.materialdesign.MaterialDesign; + +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.profile.Profile; + +public class ShowGuidelinesAction extends IkonAction { + + private static final long serialVersionUID = 1L; + Profile profile; + + public ShowGuidelinesAction(Profile profile) { + super(MaterialDesign.MDI_BOOK_OPEN_PAGE_VARIANT); + StringBuilder b = new StringBuilder(); + String s = profile.getGuidelines().getTitle(); + if (s != null) + b.append(s); + else + b.append(Annotator.getString(Strings.ACTION_GUIDELINES)); + + String v = profile.getGuidelines().getVersion(); + if (v != null) { + b.append(' '); + b.append(v); + } + this.putValue(Action.SHORT_DESCRIPTION, Annotator.getString(Strings.ACTION_GUIDELINES_TOOLTIP)); + this.putValue(Action.NAME, b.toString()); + this.profile = profile; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (java.awt.Desktop.isDesktopSupported()) { + java.awt.Desktop desktop = java.awt.Desktop.getDesktop(); + + if (desktop.isSupported(java.awt.Desktop.Action.BROWSE)) { + java.net.URI uri; + try { + uri = new java.net.URI(profile.getGuidelines().getUrl()); + desktop.browse(uri); + + } catch (URISyntaxException | IOException e1) { + Annotator.logger.catching(e1); + } + } + } + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowMentionInTreeAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowMentionInTreeAction.java index 63b9babc..94981305 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowMentionInTreeAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ShowMentionInTreeAction.java @@ -6,7 +6,7 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.Strings; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SortTree.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SortTree.java index 2db0cbd1..333f02fd 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/SortTree.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/SortTree.java @@ -7,7 +7,7 @@ import javax.swing.Action; import org.kordamp.ikonli.Ikon; -import org.kordamp.ikonli.materialdesign.MaterialDesign; +import org.kordamp.ikonli.materialdesign2.MaterialDesignS; import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.Constants; @@ -38,26 +38,34 @@ public void actionPerformed(ActionEvent e) { } public static SortTree getSortByAlphabet(DocumentWindow win) { - SortTree st = new SortTree(win, MaterialDesign.MDI_SORT_ALPHABETICAL, EntitySortOrder.Alphabet, false); + SortTree st = new SortTree(win, MaterialDesignS.SORT_ALPHABETICAL_ASCENDING, EntitySortOrder.Alphabet, false); st.putValue(Action.NAME, Annotator.getString(Strings.ACTION_SORT_ALPHA)); st.putValue(Action.SHORT_DESCRIPTION, Annotator.getString(Strings.ACTION_SORT_ALPHA_TOOLTIP)); return st; } public static SortTree getSortByMention(DocumentWindow win) { - SortTree st = new SortTree(win, MaterialDesign.MDI_SORT_NUMERIC, EntitySortOrder.Mentions, true); + SortTree st = new SortTree(win, MaterialDesignS.SORT_ASCENDING, EntitySortOrder.Mentions, true); st.putValue(Action.NAME, Annotator.getString(Strings.ACTION_SORT_MENTIONS)); st.putValue(Action.SHORT_DESCRIPTION, Annotator.getString(Strings.ACTION_SORT_MENTIONS_TOOLTIP)); return st; } public static SortTree getSortByLastModified(DocumentWindow win) { - SortTree st = new SortTree(win, MaterialDesign.MDI_SORT_NUMERIC, EntitySortOrder.LastModified, true); + SortTree st = new SortTree(win, MaterialDesignS.SORT_CLOCK_ASCENDING_OUTLINE, EntitySortOrder.LastModified, + true); st.putValue(Action.NAME, Annotator.getString(Strings.ACTION_SORT_LASTMODIFIED)); st.putValue(Action.SHORT_DESCRIPTION, Annotator.getString(Strings.ACTION_SORT_LASTMODIFIED_TOOLTIP)); return st; } + public static SortTree getSortByPosition(DocumentWindow win) { + SortTree st = new SortTree(win, MaterialDesignS.SORT_NUMERIC_ASCENDING, EntitySortOrder.Position, true); + st.putValue(Action.NAME, Annotator.getString(Strings.ACTION_SORT_POSITION)); + st.putValue(Action.SHORT_DESCRIPTION, Annotator.getString(Strings.ACTION_SORT_POSITION_TOOLTIP)); + return st; + } + @Override public void entitySortEvent(EntitySortOrder newOrder, boolean descending) { putValue(Action.SELECTED_KEY, newOrder == order); @@ -65,9 +73,13 @@ public void entitySortEvent(EntitySortOrder newOrder, boolean descending) { @Override public void preferenceChange(PreferenceChangeEvent evt) { - if (getTarget().getDocumentModel().getTreeModel().getEntitySortOrder() == order - && evt.getKey() == Constants.CFG_KEEP_TREE_SORTED && evt.getNewValue() == Boolean.TRUE.toString()) - actionPerformed(null); + try { + if (getTarget().getDocumentModel().getTreeModel().getEntitySortOrder() == order + && evt.getKey() == Constants.CFG_KEEP_TREE_SORTED && evt.getNewValue() == Boolean.TRUE.toString()) + actionPerformed(null); + } catch (NullPointerException e) { + Annotator.logger.catching(e); + } } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ToggleFlagAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ToggleFlagAction.java index b77682be..fbbad4af 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/action/ToggleFlagAction.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/action/ToggleFlagAction.java @@ -16,11 +16,11 @@ import de.unistuttgart.ims.coref.annotator.Defaults; import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.TreeSelectionUtil; -import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.FlagModel; import de.unistuttgart.ims.coref.annotator.document.op.ToggleGenericFlag; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class ToggleFlagAction extends TargetedIkonAction implements TreeSelectionListener { @@ -44,9 +44,9 @@ public void actionPerformed(ActionEvent e) { .collect(tp -> ((CATreeNode) tp.getLastPathComponent()).getFeatureStructure()); if (Annotator.app.getPreferences().getBoolean(Constants.CFG_STICKY_FLAGS, Defaults.CFG_STICKY_FLAGS)) { targets.addAll(targets.selectInstancesOf(Mention.class).flatCollect(m -> getTarget().getDocumentModel() - .getCoreferenceModel().getMatchingMentions(m.getBegin(), m.getEnd()))); + .getCoreferenceModel().getMatchingMentions(UimaUtil.getBegin(m), UimaUtil.getEnd(m)))); } - getTarget().getDocumentModel().edit(new ToggleGenericFlag(flag.getKey(), targets)); + getTarget().getDocumentModel().edit(new ToggleGenericFlag(flag, targets)); } @Override @@ -56,8 +56,7 @@ public void valueChanged(TreeSelectionEvent e) { try { en = tsu.isClass(flagModel.getTargetClass(flag)); setEnabled(en); - putValue(Action.SELECTED_KEY, - en && tsu.getFeatureStructures().allSatisfy(fs -> Util.isX(fs, flag.getKey()))); + putValue(Action.SELECTED_KEY, en && tsu.getFeatureStructures().allSatisfy(fs -> UimaUtil.isX(fs, flag))); } catch (ClassNotFoundException ex) { Annotator.logger.catching(ex); setEnabled(false); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalysisAction.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalysisAction.java new file mode 100644 index 00000000..bae38061 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalysisAction.java @@ -0,0 +1,23 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; + +enum AnalysisAction { + MENTION, NEIGHBOUR, TEXTLOCATION, Flag, DUMMY; + + AnalyzerActionPanel getObject(DocumentModel documentModel, Iterable entity) { + switch (this) { + case TEXTLOCATION: + return new AnalyzerActionPanel_TextLocation(documentModel, entity); + case NEIGHBOUR: + return new AnalyzerActionPanel_Neighbour(documentModel, entity); + case MENTION: + return new AnalyzerActionPanel_Mention(documentModel, entity); + case Flag: + return new AnalyzerActionPanel_Flag(documentModel, entity); + default: + return new AnalyzerActionPanel_Dummy(documentModel, entity); + } + } +} \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel.java new file mode 100644 index 00000000..5ccfeac4 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel.java @@ -0,0 +1,74 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SpringLayout; + +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; + +public abstract class AnalyzerActionPanel extends JPanel { + + private static final long serialVersionUID = 1L; + + DocumentModel documentModel; + protected int gap = 5; + protected SpringLayout layout; + JPanel optionPanel; + int chartWidth = 700; + int chartHeight = 500; + Iterable entities = null; + Font headerFont = this.getFont().deriveFont(this.getFont().getSize() * 1.5f).deriveFont(Font.BOLD); + + public AnalyzerActionPanel(DocumentModel documentModel, Iterable entity) { + this.documentModel = documentModel; + this.entities = entity; + } + + protected void chartConstraints(Component c) { + layout.putConstraint(SpringLayout.WEST, c, gap, SpringLayout.WEST, this); + layout.putConstraint(SpringLayout.NORTH, c, gap, SpringLayout.SOUTH, optionPanel); + layout.putConstraint(SpringLayout.EAST, this, gap, SpringLayout.EAST, c); + } + + protected void init() { + setPreferredSize(new Dimension(700, 800)); + + layout = new SpringLayout(); + setLayout(layout); + JLabel headerLabel = new JLabel(Annotator.getString(Strings.ANALZYER_ACTIONS_ + getType().toString())); + headerLabel.setFont(headerFont); + headerLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 15, 0)); + add(headerLabel); + layout.putConstraint(SpringLayout.NORTH, headerLabel, gap, SpringLayout.NORTH, this); + layout.putConstraint(SpringLayout.WEST, headerLabel, gap, SpringLayout.WEST, this); + + optionPanel = getOptionPanel(); + add(optionPanel); + + layout.putConstraint(SpringLayout.NORTH, optionPanel, gap, SpringLayout.SOUTH, headerLabel); + layout.putConstraint(SpringLayout.EAST, this, gap, SpringLayout.EAST, optionPanel); + layout.putConstraint(SpringLayout.WEST, optionPanel, gap, SpringLayout.WEST, this); + } + + public abstract AnalysisAction getType(); + + public void setEntities(Iterable entities) { + this.entities = entities; + this.refresh(); + }; + + abstract void refresh(); + + JPanel getOptionPanel() { + return new JPanel(); + }; + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_CountChartTable.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_CountChartTable.java new file mode 100644 index 00000000..593915e9 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_CountChartTable.java @@ -0,0 +1,258 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.SpringLayout; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.table.DefaultTableModel; + +import org.eclipse.collections.api.map.MutableMap; +import org.eclipse.collections.api.map.MutableMapIterable; +import org.eclipse.collections.impl.factory.Maps; +import org.eclipse.collections.impl.tuple.Tuples; +import org.knowm.xchart.CategoryChart; +import org.knowm.xchart.CategoryChartBuilder; +import org.knowm.xchart.CategorySeries; +import org.knowm.xchart.CategorySeries.CategorySeriesRenderStyle; +import org.knowm.xchart.PieChart; +import org.knowm.xchart.PieChartBuilder; +import org.knowm.xchart.PieSeries; +import org.knowm.xchart.XChartPanel; +import org.knowm.xchart.internal.series.Series; +import org.knowm.xchart.style.Styler.LegendPosition; +import org.knowm.xchart.style.colors.XChartSeriesColors; +import org.kordamp.ikonli.materialdesign.MaterialDesign; +import org.kordamp.ikonli.swing.FontIcon; + +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.comp.SpringUtilities; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; + +public abstract class AnalyzerActionPanel_CountChartTable extends AnalyzerActionPanel_GenericChartTable { + + enum ChartType { + PIE, BAR + }; + + private static final long serialVersionUID = 1L; + + MutableMapIterable cts; + + double limit = 0.01; + + ChartType chartType = ChartType.BAR; + + public AnalyzerActionPanel_CountChartTable(DocumentModel documentModel, Iterable entity) { + super(documentModel, entity); + } + + abstract void calculateCounts(); + + int getTotalNumber() { + if (this.cts == null) + return 0; + return (int) cts.valuesView().sumOfInt(i -> i); + } + + @Override + public void refresh() { + chartPanelContainer.removeAll(); + + calculateCounts(); + + MutableMapIterable entriesBelowThreshold = cts + .select((s, i) -> (double) i / (double) getTotalNumber() < limit); + + MutableMapIterable filteredCounts = cts + .select((s, i) -> !entriesBelowThreshold.containsKey(s)); + + if ((int) entriesBelowThreshold.valuesView().sumOfInt(i -> i) > 0) + filteredCounts.put(Annotator.getString(Strings.ANALYZER_PLOT_REST_CATEGORY), + (int) entriesBelowThreshold.valuesView().sumOfInt(i -> i)); + + MutableMap seriesMap = Maps.mutable.empty(); + + Color[] colors = new XChartSeriesColors().getSeriesColors(); + + switch (chartType) { + case BAR: + CategoryChart categoryChart = new CategoryChartBuilder().width(chartWidth).height(chartHeight) + .title(getClass().getSimpleName()).build(); + + categoryChart.getStyler().setLegendPosition(LegendPosition.OutsideE); + categoryChart.getStyler().setChartBackgroundColor(getBackground()); + categoryChart.getStyler().setChartTitleVisible(false); + categoryChart.getStyler().setDefaultSeriesRenderStyle(CategorySeriesRenderStyle.Bar); + categoryChart.getStyler().setLegendVisible(false); + + // Series + int snum = 0; + for (String c : filteredCounts.keySet()) { + CategorySeries series = categoryChart.addSeries(c, new int[] { snum++ }, + new int[] { filteredCounts.get(c) }); + if (c.contentEquals(Annotator.getString(Strings.ANALYZER_PLOT_REST_CATEGORY))) { + series.setFillColor(Color.lightGray); + } else { + series.setFillColor(colors[snum % colors.length]); + } + + seriesMap.put(c, series); + } + XChartPanel categoryChartPanel; + categoryChartPanel = new XChartPanel(categoryChart); + categoryChartPanel.setPreferredSize(new Dimension(400, 400)); + chartPanelContainer.add(categoryChartPanel, BorderLayout.CENTER); + + break; + default: + // CHART + PieChart pieChart = new PieChartBuilder().width(chartWidth).height(chartHeight) + .title(getClass().getSimpleName()).build(); + + // Customize Chart + pieChart.getStyler().setLegendPosition(LegendPosition.OutsideE); + pieChart.getStyler().setChartBackgroundColor(getBackground()); + pieChart.getStyler().setChartTitleVisible(false); + pieChart.getStyler().setLegendVisible(false); + + // Series + snum = 0; + for (String s : filteredCounts.keySet()) { + PieSeries series = pieChart.addSeries(s, filteredCounts.get(s)); + if (s.contentEquals(Annotator.getString(Strings.ANALYZER_PLOT_REST_CATEGORY))) { + series.setFillColor(Color.lightGray); + } else { + series.setFillColor(colors[snum++ % colors.length]); + } + seriesMap.put(s, series); + + } + + XChartPanel chartPanel; + chartPanel = new XChartPanel(pieChart); + chartPanel.setPreferredSize(new Dimension(400, 400)); + chartPanelContainer.add(chartPanel, BorderLayout.CENTER); + } + + // TABLE + Object[][] dv = cts + .collect((s, + i) -> Tuples.pair(new Object[] { (entriesBelowThreshold.containsKey(s) ? Color.lightGray + : seriesMap.get(s).getFillColor()), s, i }, null)) + .keysView().toArray(new Object[cts.size()][]); + tableModel.setDataVector(dv, this.getColumnNames()); + + revalidate(); + } + + @Override + protected MyTableModel getTableModel() { + return new MyTableModel(); + } + + @Override + JPanel getOptionPanel() { + JPanel pan = new JPanel(); + pan.setLayout(new SpringLayout()); + + JLabel lab = new JLabel(Annotator.getString(Strings.ANALYZER_PLOT_REST_LIMIT)); + pan.add(lab); + + JSpinner spinner = new JSpinner(new SpinnerNumberModel(limit, 0, 1, 0.01)); + spinner.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + limit = (double) spinner.getValue(); + refresh(); + } + + }); + pan.add(spinner); + + pan.add(new JLabel(Annotator.getString(Strings.ANALYZER_PLOT_PLOT_TYPE))); + + JComboBox plotTypeBox = new JComboBox(ChartType.values()); + plotTypeBox.setSelectedItem(chartType); + plotTypeBox.setRenderer(new DefaultListCellRenderer() { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value != null) + switch ((ChartType) value) { + case BAR: + setIcon(FontIcon.of(MaterialDesign.MDI_CHART_BAR)); + setText(Annotator.getString(Strings.ANALYZER_PLOT_PLOT_TYPE_BAR)); + break; + default: + setIcon(FontIcon.of(MaterialDesign.MDI_CHART_PIE)); + setText(Annotator.getString(Strings.ANALYZER_PLOT_PLOT_TYPE_PIE)); + } + + return this; + } + + }); + plotTypeBox.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + chartType = (ChartType) plotTypeBox.getSelectedItem(); + refresh(); + } + + }); + pan.add(plotTypeBox); + + SpringUtilities.makeGrid(pan, 2, 2, // rows, cols + 0, 0, // initialX, initialY + 5, 5);// xPad, yPad + + return pan; + } + + public class MyTableModel extends DefaultTableModel { + + private static final long serialVersionUID = 1L; + + @Override + public Class getColumnClass(int c) { + switch (c) { + case 0: + return Color.class; + case 1: + return String.class; + default: + return Integer.class; + } + } + } + + @Override + protected String[] getColumnNames() { + return new String[] { Annotator.getString(Strings.ANALYZER_COLOR), + Annotator.getString(Strings.ANALYZER_DATATABLE_MENTIONS), + Annotator.getString(Strings.ANALYZER_DATATABLE_COUNT) }; + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Dummy.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Dummy.java new file mode 100644 index 00000000..a29b62d6 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Dummy.java @@ -0,0 +1,30 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; + +public class AnalyzerActionPanel_Dummy extends AnalyzerActionPanel { + + private static final long serialVersionUID = 1L; + + public AnalyzerActionPanel_Dummy(DocumentModel documentModel, Iterable entity) { + super(documentModel, entity); + + init(); + } + + @Override + public AnalysisAction getType() { + return AnalysisAction.DUMMY; + } + + @Override + public void setEntities(Iterable entities) { + this.entities = entities; + } + + @Override + void refresh() { + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Flag.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Flag.java new file mode 100644 index 00000000..3ac90e55 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Flag.java @@ -0,0 +1,111 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; + +import org.apache.uima.jcas.cas.TOP; +import org.apache.uima.jcas.tcas.Annotation; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.factory.Maps; + +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.comp.SpringUtilities; +import de.unistuttgart.ims.coref.annotator.comp.TranslatedListCellRenderer; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; + +public class AnalyzerActionPanel_Flag extends AnalyzerActionPanel_CountChartTable { + + private static final long serialVersionUID = 1L; + + int n = 1; + Class unit = Mention.class; + + public AnalyzerActionPanel_Flag(DocumentModel documentModel, Iterable entity) { + super(documentModel, entity); + + init(); + + refresh(); + } + + @Override + JPanel getOptionPanel() { + JPanel pan = super.getOptionPanel(); + + // unit + pan.add(new JLabel(Annotator.getString(Strings.ANALYZER_UNIT))); + + DefaultComboBoxModel> unitBoxModel = new DefaultComboBoxModel>(); + unitBoxModel.addElement(Mention.class); + unitBoxModel.addElement(Entity.class); + + JComboBox> unitBox = new JComboBox>(unitBoxModel); + unitBox.setSelectedItem(unit); + unitBox.addActionListener(new ActionListener() { + + @SuppressWarnings("unchecked") + @Override + public void actionPerformed(ActionEvent e) { + unit = (Class) unitBox.getSelectedItem(); + refresh(); + } + + }); + unitBox.setRenderer(new TranslatedListCellRenderer(Strings.ANALYZER_UNIT_) { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, + boolean isSelected, boolean cellHasFocus) { + return super.getListCellRendererComponent(list, ((Class) value).getSimpleName(), index, isSelected, + cellHasFocus); + + } + }); + pan.add(unitBox); + + SpringUtilities.makeGrid(pan, pan.getComponents().length / 2, 2, // rows, cols + 0, 0, // initialX, initialY + 5, 5);// xPad, yPad + return pan; + } + + @Override + public AnalysisAction getType() { + return AnalysisAction.Flag; + } + + @Override + void calculateCounts() { + cts = Maps.mutable.empty(); + if (unit == Entity.class) { + for (Flag f : documentModel.getFlagModel().getFlags() + .select(f -> f.getTargetClass().equalsIgnoreCase(Entity.class.getName()))) { + cts.put(f.getLabel(), Lists.mutable.withAll(entities).select(e -> UimaUtil.isX(e, f)).size()); + } + } else if (unit == Mention.class) { + MutableList mentions = Lists.mutable.withAll(entities) + .flatCollect(e -> documentModel.getCoreferenceModel().getMentions(e)); + for (Flag f : documentModel.getFlagModel().getFlags() + .select(f -> f.getTargetClass().equalsIgnoreCase(Mention.class.getName()))) { + cts.put(f.getLabel(), mentions.select(e -> UimaUtil.isX(e, f)).size()); + } + } + + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_GenericChartTable.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_GenericChartTable.java new file mode 100644 index 00000000..d1a8cece --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_GenericChartTable.java @@ -0,0 +1,56 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.awt.BorderLayout; +import java.awt.Color; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SpringLayout; +import javax.swing.table.DefaultTableModel; + +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.comp.ColorTableCellRenderer; +import de.unistuttgart.ims.coref.annotator.comp.EntityTableCellRenderer; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; + +public abstract class AnalyzerActionPanel_GenericChartTable extends AnalyzerActionPanel { + + private static final long serialVersionUID = 1L; + JTable jtable = new JTable(); + DefaultTableModel tableModel; + JScrollPane tableScroller = new JScrollPane(jtable); + protected JPanel chartPanelContainer = new JPanel(); + + public AnalyzerActionPanel_GenericChartTable(DocumentModel documentModel, Iterable entity) { + super(documentModel, entity); + // TODO Auto-generated constructor stub + } + + @Override + protected void init() { + super.init(); + + chartPanelContainer.setLayout(new BorderLayout()); + add(chartPanelContainer); + chartConstraints(chartPanelContainer); + + tableModel = getTableModel(); + jtable.setAutoCreateRowSorter(true); + jtable.setModel(tableModel); + jtable.setShowGrid(true); + jtable.setDefaultRenderer(Color.class, new ColorTableCellRenderer()); + jtable.setDefaultRenderer(Entity.class, new EntityTableCellRenderer()); + add(tableScroller); + + layout.putConstraint(SpringLayout.WEST, tableScroller, gap, SpringLayout.WEST, this); + layout.putConstraint(SpringLayout.EAST, this, gap, SpringLayout.EAST, tableScroller); + layout.putConstraint(SpringLayout.SOUTH, this, gap, SpringLayout.SOUTH, tableScroller); + layout.putConstraint(SpringLayout.NORTH, tableScroller, gap, SpringLayout.SOUTH, chartPanelContainer); + } + + protected abstract DefaultTableModel getTableModel(); + + protected abstract String[] getColumnNames(); + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Mention.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Mention.java new file mode 100644 index 00000000..cd4af747 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Mention.java @@ -0,0 +1,76 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.impl.factory.Lists; + +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.comp.SpringUtilities; +import de.unistuttgart.ims.coref.annotator.comp.TranslatedListCellRenderer; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; + +public class AnalyzerActionPanel_Mention extends AnalyzerActionPanel_CountChartTable { + + private static final long serialVersionUID = 1L; + + GroupBy groupBy = GroupBy.COVEREDTEXT; + + public AnalyzerActionPanel_Mention(DocumentModel documentModel, Iterable entities) { + super(documentModel, entities); + + init(); + + } + + @Override + public AnalysisAction getType() { + return AnalysisAction.MENTION; + } + + @Override + void calculateCounts() { + ImmutableList mentions = Lists.immutable.withAll(entities) + .flatCollect(e -> documentModel.getCoreferenceModel().getMentions(e)); + + cts = mentions.countBy(m -> groupBy.getFunction().apply(m)).toMapOfItemToCount(); + } + + @Override + JPanel getOptionPanel() { + JPanel pan = super.getOptionPanel(); + + // unit + pan.add(new JLabel(Annotator.getString(Strings.ANALYZER_GROUPBY))); + + DefaultComboBoxModel unitBoxModel = new DefaultComboBoxModel(GroupBy.values()); + + JComboBox unitBox = new JComboBox(unitBoxModel); + unitBox.setSelectedItem(groupBy); + unitBox.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + groupBy = (GroupBy) unitBox.getSelectedItem(); + refresh(); + } + + }); + unitBox.setRenderer(new TranslatedListCellRenderer(Strings.ANALYZER_GROUPBY_)); + pan.add(unitBox); + + SpringUtilities.makeGrid(pan, pan.getComponents().length / 2, 2, 0, 0, 5, 5); + + return pan; + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Neighbour.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Neighbour.java new file mode 100644 index 00000000..c81b6d1b --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_Neighbour.java @@ -0,0 +1,146 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; + +import org.apache.uima.cas.FeatureStructure; +import org.apache.uima.fit.util.JCasUtil; +import org.apache.uima.jcas.tcas.Annotation; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.impl.factory.Lists; + +import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence; +import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; +import de.unistuttgart.ims.coref.annotator.comp.SpringUtilities; +import de.unistuttgart.ims.coref.annotator.comp.TranslatedListCellRenderer; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; + +public class AnalyzerActionPanel_Neighbour extends AnalyzerActionPanel_CountChartTable { + + private static final long serialVersionUID = 1L; + + int n = 1; + Class neighbourType = MentionSurface.class; + DIRECTION direction = DIRECTION.RIGHT; + GroupBy toText = GroupBy.ENTITY; + + enum DIRECTION { + LEFT, RIGHT + }; + + public AnalyzerActionPanel_Neighbour(DocumentModel documentModel, Iterable entity) { + super(documentModel, entity); + + init(); + + refresh(); + } + + @Override + JPanel getOptionPanel() { + JPanel pan = super.getOptionPanel(); + + // direction + pan.add(new JLabel(Annotator.getString(Strings.ANALYZER_NEIGHBOUR_DIRECTION))); + JComboBox directionBox = new JComboBox(DIRECTION.values()); + directionBox.setEditable(false); + directionBox.setSelectedItem(direction); + directionBox.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + direction = (DIRECTION) directionBox.getSelectedItem(); + refresh(); + } + + }); + directionBox.setRenderer(new TranslatedListCellRenderer(Strings.ANALYZER_NEIGHBOUR_DIRECTION_)); + pan.add(directionBox); + + // unit + pan.add(new JLabel(Annotator.getString(Strings.ANALYZER_UNIT))); + + DefaultComboBoxModel> unitBoxModel = new DefaultComboBoxModel>(); + unitBoxModel.addElement(Mention.class); + if (JCasUtil.exists(documentModel.getJcas(), Token.class)) + unitBoxModel.addElement(Token.class); + if (JCasUtil.exists(documentModel.getJcas(), Sentence.class)) + unitBoxModel.addElement(Sentence.class); + + JComboBox> unitBox = new JComboBox>(unitBoxModel); + unitBox.setSelectedItem(neighbourType); + unitBox.addActionListener(new ActionListener() { + + @SuppressWarnings("unchecked") + @Override + public void actionPerformed(ActionEvent e) { + neighbourType = (Class) unitBox.getSelectedItem(); + refresh(); + } + + }); + unitBox.setRenderer(new TranslatedListCellRenderer(Strings.ANALYZER_UNIT_) { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, + boolean isSelected, boolean cellHasFocus) { + return super.getListCellRendererComponent(list, ((Class) value).getSimpleName(), index, isSelected, + cellHasFocus); + + } + }); + pan.add(unitBox); + + SpringUtilities.makeGrid(pan, pan.getComponents().length / 2, 2, // rows, cols + 0, 0, // initialX, initialY + 5, 5);// xPad, yPad + return pan; + } + + @Override + public AnalysisAction getType() { + return AnalysisAction.NEIGHBOUR; + } + + @Override + void calculateCounts() { + ImmutableList mentions = Lists.immutable.withAll(entities) + .flatCollect(e -> documentModel.getCoreferenceModel().getMentions(e)); + ImmutableList followers; + if (direction == DIRECTION.RIGHT) { + followers = mentions.flatCollect(m -> ((Iterable) UimaUtil.selectFollowing(m, n))); + } else { + followers = mentions.flatCollect(m -> ((Iterable) UimaUtil.selectPreceding(m, n))); + } + + if (neighbourType != Mention.class) + toText = GroupBy.COVEREDTEXT; + switch (toText) { + case ENTITY: + cts = followers.selectInstancesOf(Mention.class).countBy(m -> m.getEntity().getLabel()) + .toMapOfItemToCount(); + break; + case COVEREDTEXT: + default: + cts = followers.countBy(m -> UimaUtil.getCoveredText(m)).toMapOfItemToCount(); + + } + + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_TextLocation.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_TextLocation.java new file mode 100644 index 00000000..6ed508eb --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerActionPanel_TextLocation.java @@ -0,0 +1,244 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.DefaultListSelectionModel; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.DefaultTableModel; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.factory.Maps; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.map.MutableMap; +import org.eclipse.collections.api.set.sorted.ImmutableSortedSet; +import org.knowm.xchart.XYChart; +import org.knowm.xchart.XYChartBuilder; +import org.knowm.xchart.XYSeries; +import org.knowm.xchart.XYSeries.XYSeriesRenderStyle; +import org.knowm.xchart.style.Styler.LegendLayout; +import org.knowm.xchart.style.Styler.LegendPosition; +import org.knowm.xchart.style.markers.Rectangle; + +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.comp.EntityFromMentionTableCellRenderer; +import de.unistuttgart.ims.coref.annotator.comp.XChartPanel; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; + +public class AnalyzerActionPanel_TextLocation extends AnalyzerActionPanel_GenericChartTable { + public class EntityMouseListener extends MouseAdapter { + Entity entity; + XYSeries series; + double yLevel; + XYChart chart; + + public EntityMouseListener(XYChart chart, Entity entity, XYSeries series, double yLevel) { + super(); + this.chart = chart; + this.entity = entity; + this.series = series; + this.yLevel = yLevel; + } + + @Override + public void mouseClicked(MouseEvent e) { + + double x = chart.getChartXFromCoordinate(e.getX()); + double y = chart.getChartYFromCoordinate(e.getY()); + for (Mention m : documentModel.getCoreferenceModel().getMentions(entity)) { + int begin = UimaUtil.getBegin(m) - 20; + int end = UimaUtil.getEnd(m) + 20; + if (begin <= x && end >= x /* && Math.abs(yLevel - y) < 0.1 */) { + jtable.clearSelection(); + for (int r = 0; r < jtable.getRowCount(); r++) { + Mention rowMention = (Mention) jtable.getValueAt(r, 0); + if (rowMention == m) { + jtable.setRowSelectionInterval(r, r); + jtable.scrollRectToVisible(jtable.getCellRect(r, 0, false)); + } + } + } + } + + } + + } + + public class MyTableModel extends DefaultTableModel { + + private static final long serialVersionUID = 1L; + + @Override + public Class getColumnClass(int c) { + switch (c) { + case 0: + return Mention.class; + case 1: + return Integer.class; + default: + return String.class; + } + } + + } + + private static final long serialVersionUID = 1L; + ListSelectionModel tableSelectionModel = new DefaultListSelectionModel(); + XYSeries currentSelection = null; + final String currentSelectionName = "SELECTION"; + + public AnalyzerActionPanel_TextLocation(DocumentModel documentModel, Iterable entity) { + super(documentModel, entity); + + init(); + + } + + @Override + protected String[] getColumnNames() { + return new String[] { Annotator.getString(Strings.ANALYZER_ENTITY), + Annotator.getString(Strings.ANALYZER_POSITION), Annotator.getString(Strings.ANALYZER_KWIC_LEFT), + Annotator.getString(Strings.ANALYZER_KWIC_CENTER), Annotator.getString(Strings.ANALYZER_KWIC_RIGHT) }; + } + + @Override + protected MyTableModel getTableModel() { + return new MyTableModel(); + } + + @Override + public AnalysisAction getType() { + return AnalysisAction.TEXTLOCATION; + } + + @Override + protected void init() { + super.init(); + jtable.setDefaultRenderer(Mention.class, new EntityFromMentionTableCellRenderer()); + jtable.setSelectionModel(tableSelectionModel); + + tableSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + } + + @Override + public void refresh() { + chartPanelContainer.removeAll(); + + XYChart chart = new XYChartBuilder().width(chartWidth).height(chartHeight).build(); + + // Customize Chart + chart.getStyler().setDefaultSeriesRenderStyle(XYSeriesRenderStyle.Line); + chart.getStyler().setChartTitleVisible(false); + chart.getStyler().setLegendPosition(LegendPosition.OutsideS); + chart.getStyler().setLegendLayout(LegendLayout.Horizontal); + chart.getStyler().setToolTipsEnabled(true); + chart.getStyler().setChartBackgroundColor(getBackground()); + chart.getStyler().setToolTipsAlwaysVisible(false); + chart.getStyler().setYAxisTitleVisible(false); + chart.getStyler().setYAxisTicksVisible(false); + chart.getStyler().setLegendVisible(false); + chart.getStyler().setInfoPanelVisible(false); + chart.setInfoContent(Lists.immutable.of("bla", "blubb").castToList()); + + MutableList mentionLines = Lists.mutable.empty(); + MutableMap mentionIndex = Maps.mutable.empty(); + int width = 50; + + // Series + MutableList listeners = Lists.mutable.empty(); + int y = 0; + int textLength = documentModel.getJcas().getDocumentText().length(); + + for (Entity e : entities) { + Color entityColor = new Color(e.getColor()); + + ImmutableSortedSet mentions = documentModel.getCoreferenceModel().getMentions(e); + + double[] xData = new double[mentions.size()]; + double[] yData = new double[mentions.size()]; + List labels = new ArrayList(); + int i = 0; + for (Mention m : mentions) { + int begin = UimaUtil.getBegin(m), end = UimaUtil.getEnd(m); + xData[i] = begin; + yData[i] = y; + labels.add(UimaUtil.getCoveredText(m)); + + String left = documentModel.getJcas().getDocumentText().substring(Integer.max(begin - width, 0), begin); + String center = UimaUtil.getCoveredText(m); + String right = documentModel.getJcas().getDocumentText().substring(end, + Integer.min(end + width, textLength)); + mentionLines.add(new Object[] { m, begin, left, center, right }); + mentionIndex.put(m, i); + i++; + } + + if (xData.length == 0) + continue; + + XYSeries series = chart.addSeries(e.getLabel(), xData, yData); + series.setToolTips(labels.toArray(new String[labels.size()])); + series.setCustomToolTips(true); + series.setLineColor(entityColor); + series.setMarkerColor(entityColor); + // listeners.add(new EntityMouseListener(chart, e, series, y)); + tableSelectionModel.addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting()) + return; + // chart.resetFilter(); + highlightMention(null, chart, series); + int row = e.getFirstIndex(); + Mention m = (Mention) jtable.getValueAt(row, 0); + + // chart.filterXByIndex(seriesX - 10, seriesX + 10); + // TODO: highlight data point or region in plot + highlightMention(m, chart, series); + repaint(); + } + + }); + y++; + } + + tableModel.setDataVector(mentionLines.toArray(new Object[mentionLines.size()][]), this.getColumnNames()); + XChartPanel chartPanel = new XChartPanel(chart); + chartPanel.setPreferredSize(new Dimension(chartWidth, chartHeight)); + listeners.forEach(ml -> chartPanel.addMouseListener(ml)); + + chartPanelContainer.add(chartPanel, BorderLayout.CENTER); + + revalidate(); + + } + + protected void highlightMention(Mention mention, XYChart chart, XYSeries series) { + if (mention == null) { + if (currentSelection != null) + chart.removeSeries(currentSelectionName); + currentSelection = null; + return; + } + currentSelection = chart.addSeries(currentSelectionName, new double[] { UimaUtil.getBegin(mention) }, + new double[] { series.getYData()[0] }); + currentSelection.setMarker(new Rectangle()); + currentSelection.setShowInLegend(false); + currentSelection.setMarkerColor(Color.red); + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerWindow.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerWindow.java new file mode 100644 index 00000000..bee3f5a9 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/AnalyzerWindow.java @@ -0,0 +1,313 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.util.prefs.PreferenceChangeEvent; +import java.util.prefs.PreferenceChangeListener; + +import javax.swing.AbstractListModel; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.DefaultListCellRenderer; +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.kordamp.ikonli.materialdesign.MaterialDesign; +import org.kordamp.ikonli.swing.FontIcon; + +import de.unistuttgart.ims.coref.annotator.AbstractWindow; +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Constants; +import de.unistuttgart.ims.coref.annotator.HasDocumentModel; +import de.unistuttgart.ims.coref.annotator.Strings; +import de.unistuttgart.ims.coref.annotator.action.FileSelectAnalyzeAction; +import de.unistuttgart.ims.coref.annotator.action.FileSelectOpenAction; +import de.unistuttgart.ims.coref.annotator.action.ProcessAction; +import de.unistuttgart.ims.coref.annotator.action.SelectedFileOpenAction; +import de.unistuttgart.ims.coref.annotator.action.SetLanguageAction; +import de.unistuttgart.ims.coref.annotator.action.ShowLogWindowAction; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.document.CoreferenceModel.EntitySorter; +import de.unistuttgart.ims.coref.annotator.document.DocumentModel; +import de.unistuttgart.ims.coref.annotator.plugins.ProcessingPlugin; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; + +public class AnalyzerWindow extends AbstractWindow implements HasDocumentModel { + + public class ActionListCellRenderer extends DefaultListCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + super.getListCellRendererComponent(list, Annotator.getString(Strings.ANALZYER_ACTIONS_ + value.toString()), + index, isSelected, cellHasFocus); + return this; + } + } + + public class ActionListModel extends AbstractListModel { + + private static final long serialVersionUID = 1L; + + @Override + public AnalysisAction getElementAt(int index) { + return AnalysisAction.values()[index]; + + } + + @Override + public int getSize() { + return AnalysisAction.values().length - 1; + } + + } + + public class ActionListSelectionListener implements ListSelectionListener { + + @Override + public void valueChanged(ListSelectionEvent e) { + if (!e.getValueIsAdjusting()) { + actionPanel = actionList.getSelectedValue().getObject(documentModel, + entityList.getSelectedValuesList()); + innerSplitPane.add(actionPanel, JSplitPane.RIGHT); + updateActionPanel(); + } + } + + } + + public class EntityListModel extends AbstractListModel implements ListModel { + + private static final long serialVersionUID = 1L; + EntitySorter sorter = EntitySorter.CHILDREN; + + @Override + public Entity getElementAt(int index) { + return documentModel.getCoreferenceModel().getEntities(sorter).get(index); + } + + @Override + public int getSize() { + return documentModel.getCoreferenceModel().getEntities(sorter).size(); + } + + } + + public class EntityListSelectionListener implements ListSelectionListener { + + @Override + public void valueChanged(ListSelectionEvent e) { + if (!e.getValueIsAdjusting()) { + actionPanel.setEntities(entityList.getSelectedValuesList()); + updateActionPanel(); + } + } + } + + class MyTreeCellRenderer extends DefaultListCellRenderer implements PreferenceChangeListener { + + private static final long serialVersionUID = 1L; + boolean showText = Annotator.app.getPreferences().getBoolean(Constants.CFG_SHOW_TEXT_LABELS, true); + + protected void addFlag(JPanel panel, Flag flag, Color color) { + JLabel l = new JLabel(); + if (color != null) + l.setForeground(color); + if (showText) + l.setText(Annotator.getStringWithDefault(flag.getLabel(), flag.getLabel())); + l.setIcon(FontIcon.of(MaterialDesign.valueOf(flag.getIcon()), color)); + panel.add(Box.createRigidArea(new Dimension(5, 5))); + panel.add(l); + } + + public Icon getEntityIcon() { + return FontIcon.of(MaterialDesign.MDI_ACCOUNT); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + + // this is the panel representing the node + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); + panel.setOpaque(false); + + // this is the main label for the node + JLabel mainLabel = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, + cellHasFocus); + panel.add(mainLabel); + + return handleEntity(panel, mainLabel, (Entity) value); + } + + public Icon getMentionIcon() { + return FontIcon.of(MaterialDesign.MDI_COMMENT_ACCOUNT); + } + + protected JPanel handleEntity(JPanel panel, JLabel lab1, Entity entity) { + lab1.setText(entity.getLabel()); + + boolean isGrey = entity.getHidden(); + Color entityColor = new Color(entity.getColor()); + + if (isGrey) { + lab1.setForeground(Color.GRAY); + lab1.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT_OUTLINE, Color.GRAY)); + } else { + lab1.setForeground(Color.BLACK); + lab1.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT, entityColor)); + } + + if (UimaUtil.isGroup(entity)) { + panel.add(Box.createRigidArea(new Dimension(5, 5))); + panel.add(new JLabel(FontIcon.of(MaterialDesign.MDI_ACCOUNT_MULTIPLE))); + } + if (entity.getFlags() != null) + for (Flag flag : entity.getFlags()) { + addFlag(panel, flag, isGrey ? Color.GRAY : Color.BLACK); + } + return panel; + } + + @Override + public void preferenceChange(PreferenceChangeEvent evt) { + showText = Annotator.app.getPreferences().getBoolean(Constants.CFG_SHOW_TEXT_LABELS, true); + } + + } + + private static final long serialVersionUID = 1L; + + JList actionList; + AnalyzerActionPanel actionPanel; + DocumentModel documentModel; + + JList entityList; + + JSplitPane innerSplitPane; + + JSplitPane outerSplitPane; + + SelectedFileOpenAction openAnnotatorAction = new SelectedFileOpenAction(Annotator.app, null); + + public AnalyzerWindow() { + init(); + } + + @Override + public DocumentModel getDocumentModel() { + return documentModel; + } + + protected void init() { + + initializeWindow(); + + entityList = new JList(); + entityList.setCellRenderer(new MyTreeCellRenderer()); + entityList.addListSelectionListener(new EntityListSelectionListener()); + entityList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + entityList.setMaximumSize(new Dimension(200, 600)); + // entityList.setPreferredSize(new Dimension(200, 600)); + + actionList = new JList(); + actionList.setModel(new ActionListModel()); + actionList.addListSelectionListener(new ActionListSelectionListener()); + actionList.setCellRenderer(new ActionListCellRenderer()); + actionList.setMaximumSize(new Dimension(200, 600)); + + actionPanel = new AnalyzerActionPanel_Dummy(documentModel, null); + + JPanel entityListPanel = new JPanel(); + entityListPanel.setLayout(new BorderLayout(5, 5)); + entityListPanel.add(new JScrollPane(entityList), BorderLayout.CENTER); + entityListPanel.add(new JLabel(Annotator.getString(Strings.ANALZYER_ENTITIES)), BorderLayout.NORTH); + entityListPanel.setPreferredSize(new Dimension(200, 600)); + + JPanel actionListPanel = new JPanel(); + actionListPanel.setLayout(new BorderLayout(5, 5)); + actionListPanel.add(new JScrollPane(actionList), BorderLayout.CENTER); + actionListPanel.add(new JLabel(Annotator.getString(Strings.ANALZYER_ACTIONS)), BorderLayout.NORTH); + + innerSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, actionListPanel, actionPanel); + outerSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, entityListPanel, innerSplitPane); + innerSplitPane.setBorder(BorderFactory.createEmptyBorder()); + add(outerSplitPane, BorderLayout.CENTER); + + // Menus + JMenu menu = new JMenu(Annotator.getString(Strings.MENU_FILE)); + menu.add(new FileSelectAnalyzeAction()); + menu.add(new FileSelectOpenAction(Annotator.app)); + menu.add(openAnnotatorAction); + menu.add(new de.unistuttgart.ims.coref.annotator.action.CloseAction()); + menuBar.add(menu); + + JMenu procMenu = new JMenu(Annotator.getString(Strings.MENU_TOOLS_PROC)); + for (Class pp : Annotator.app.getPluginManager().getProcessingPlugins()) { + ProcessAction pa = new ProcessAction(this, Annotator.app.getPluginManager().getPlugin(pp)); + procMenu.add(pa); + } + + menu = new JMenu(Annotator.getString(Strings.MENU_TOOLS)); + menu.add(procMenu); + menu.add(new SetLanguageAction(this)); + menu.addSeparator(); + menu.add(new ShowLogWindowAction(Annotator.app)); + + menuBar.add(menu); + menuBar.add(initialiseMenuSettings()); + + setJMenuBar(menuBar); + + // toolbar + JToolBar controls = new JToolBar(); + controls.setFocusable(false); + controls.setRollover(true); + controls.add(openAnnotatorAction); + add(controls, BorderLayout.NORTH); + + add(getStatusBar(), BorderLayout.SOUTH); + + pack(); + + } + + protected void initContent() { + entityList.setModel(new EntityListModel()); + + if (documentModel.getFile() != null) + openAnnotatorAction.setFile(documentModel.getFile()); + + stopIndeterminateProgress(); + } + + public void setDocumentModel(DocumentModel documentModel) { + this.documentModel = documentModel; + + initContent(); + setVisible(true); + pack(); + + } + + protected void updateActionPanel() { + actionPanel.refresh(); + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/GroupBy.java b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/GroupBy.java new file mode 100644 index 00000000..76d4d0fb --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/analyzer/GroupBy.java @@ -0,0 +1,28 @@ +package de.unistuttgart.ims.coref.annotator.analyzer; + +import java.util.function.Function; + +import org.apache.uima.cas.FeatureStructure; +import org.apache.uima.jcas.tcas.Annotation; + +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; + +enum GroupBy { + COVEREDTEXT, ENTITY; + + public Function getFunction() { + switch (this) { + case ENTITY: + return a -> ((Mention) a).getEntity().getLabel(); + default: + return a -> { + if (a instanceof Mention) + return UimaUtil.getCoveredText((Mention) a); + if (a instanceof Annotation) + return ((Annotation) a).getCoveredText(); + return null; + }; + } + } +} \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/ColorIcon.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/ColorIcon.java index fe579784..5313af96 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/ColorIcon.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/ColorIcon.java @@ -90,4 +90,18 @@ public void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(color); g.fillRect(x, y, w, h); } + + /** + * @return the insets + */ + public Insets getInsets() { + return insets; + } + + /** + * @param insets the insets to set + */ + public void setInsets(Insets insets) { + this.insets = insets; + } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/ColorTableCellRenderer.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/ColorTableCellRenderer.java new file mode 100644 index 00000000..cf32ae30 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/ColorTableCellRenderer.java @@ -0,0 +1,28 @@ +package de.unistuttgart.ims.coref.annotator.comp; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Insets; + +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; + +public class ColorTableCellRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, + int row, int column) { + + ColorIcon color = new ColorIcon(20, 10, (Color) value); + color.setBorderColor((Color) value); + color.setInsets(new Insets(0, 0, 0, 0)); + + JLabel c = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + c.setText(null); + c.setIcon(color); + return c; + } +} \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityFromMentionTableCellRenderer.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityFromMentionTableCellRenderer.java new file mode 100644 index 00000000..984d8ae3 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityFromMentionTableCellRenderer.java @@ -0,0 +1,25 @@ +package de.unistuttgart.ims.coref.annotator.comp; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; + +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; + +public class EntityFromMentionTableCellRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, + int row, int column) { + Mention m = (Mention) value; + JLabel c = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + c.setText(m.getEntity().getLabel()); + c.setIcon(new ColorIcon(10, 10, new Color(m.getEntity().getColor()))); + return c; + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityLabel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityLabel.java index 670452f4..835c670a 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityLabel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityLabel.java @@ -9,9 +9,8 @@ import org.kordamp.ikonli.swing.FontIcon; import de.unistuttgart.ims.coref.annotator.Constants; -import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class EntityLabel extends JLabel { @@ -20,14 +19,14 @@ public class EntityLabel extends JLabel { public EntityLabel(Entity entity) { Color entityColor = new Color(entity.getColor()); - boolean isGrey = Util.isX(entity, Constants.ENTITY_FLAG_HIDDEN); + boolean isGrey = entity.getHidden(); if (isGrey) this.setForeground(Color.GRAY); else this.setForeground(Color.BLACK); this.setText(StringUtils.abbreviate(entity.getLabel(), Constants.UI_MAX_STRING_WIDTH_IN_STATUSBAR)); - if (entity instanceof EntityGroup) { + if (UimaUtil.isGroup(entity)) { this.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT_MULTIPLE, (isGrey ? Color.GRAY : entityColor))); } else { this.setIcon(FontIcon.of(MaterialDesign.MDI_ACCOUNT, (isGrey ? Color.GRAY : entityColor))); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityPanel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityPanel.java index e4ba848b..af57c027 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityPanel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityPanel.java @@ -17,8 +17,8 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.Constants; import de.unistuttgart.ims.coref.annotator.Defaults; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModelListener; import de.unistuttgart.ims.coref.annotator.document.DocumentModel; import de.unistuttgart.ims.coref.annotator.document.Event; @@ -53,10 +53,7 @@ protected void initialize() { add(mainLabel); if (entity.getFlags() != null && documentModel != null) - for (String flagKey : entity.getFlags()) { - if (flagKey == Constants.ENTITY_FLAG_HIDDEN) - continue; - Flag flag = documentModel.getFlagModel().getFlag(flagKey); + for (Flag flag : entity.getFlags()) { addFlag(this, flag, Color.BLACK); } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityTableCellRenderer.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityTableCellRenderer.java new file mode 100644 index 00000000..7bdb9a9d --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/EntityTableCellRenderer.java @@ -0,0 +1,25 @@ +package de.unistuttgart.ims.coref.annotator.comp; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; + +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; + +public class EntityTableCellRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, + int row, int column) { + Entity e = (Entity) value; + JLabel c = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + c.setText(e.getLabel()); + c.setIcon(new ColorIcon(10, 10, new Color(e.getColor()))); + return c; + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/FlagMenu.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/FlagMenu.java index e937528d..9ce4dc04 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/FlagMenu.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/FlagMenu.java @@ -10,7 +10,7 @@ import de.unistuttgart.ims.coref.annotator.DocumentWindow; import de.unistuttgart.ims.coref.annotator.action.ToggleFlagAction; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; import de.unistuttgart.ims.coref.annotator.document.FeatureStructureEvent; import de.unistuttgart.ims.coref.annotator.document.FlagModel; import de.unistuttgart.ims.coref.annotator.document.FlagModelListener; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/SegmentedScrollBar.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/SegmentedScrollBar.java index 69f75284..12f9873d 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/SegmentedScrollBar.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/SegmentedScrollBar.java @@ -23,7 +23,7 @@ import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.factory.Lists; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; import de.unistuttgart.ims.coref.annotator.document.SegmentModel; public class SegmentedScrollBar extends JScrollBar implements ListDataListener { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/SpringUtilities.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/SpringUtilities.java new file mode 100644 index 00000000..fc6727fe --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/SpringUtilities.java @@ -0,0 +1,162 @@ +package de.unistuttgart.ims.coref.annotator.comp; + +import java.awt.Component; +import java.awt.Container; + +import javax.swing.Spring; +import javax.swing.SpringLayout; + +public class SpringUtilities { + /** + * A debugging utility that prints to stdout the component's minimum, preferred, + * and maximum sizes. + */ + public static void printSizes(Component c) { + System.out.println("minimumSize = " + c.getMinimumSize()); + System.out.println("preferredSize = " + c.getPreferredSize()); + System.out.println("maximumSize = " + c.getMaximumSize()); + } + + /** + * Aligns the first rows * cols components of + * parent in a grid. Each component is as big as the maximum + * preferred width and height of the components. The parent is made just big + * enough to fit them all. + * + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeGrid(Container parent, int rows, int cols, int initialX, int initialY, int xPad, int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout) parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeGrid must use SpringLayout."); + return; + } + + Spring xPadSpring = Spring.constant(xPad); + Spring yPadSpring = Spring.constant(yPad); + Spring initialXSpring = Spring.constant(initialX); + Spring initialYSpring = Spring.constant(initialY); + int max = rows * cols; + + // Calculate Springs that are the max of the width/height so that all + // cells have the same size. + Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)).getWidth(); + Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)).getHeight(); + for (int i = 1; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + + maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth()); + maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight()); + } + + // Apply the new width/height Spring. This forces all the + // components to have the same size. + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + + cons.setWidth(maxWidthSpring); + cons.setHeight(maxHeightSpring); + } + + // Then adjust the x/y constraints of all the cells so that they + // are aligned in a grid. + SpringLayout.Constraints lastCons = null; + SpringLayout.Constraints lastRowCons = null; + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + if (i % cols == 0) { // start of new row + lastRowCons = lastCons; + cons.setX(initialXSpring); + } else { // x position depends on previous component + cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), xPadSpring)); + } + + if (i / cols == 0) { // first row + cons.setY(initialYSpring); + } else { // y position depends on previous row + cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), yPadSpring)); + } + lastCons = cons; + } + + // Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, + Spring.sum(Spring.constant(yPad), lastCons.getConstraint(SpringLayout.SOUTH))); + pCons.setConstraint(SpringLayout.EAST, + Spring.sum(Spring.constant(xPad), lastCons.getConstraint(SpringLayout.EAST))); + } + + /* Used by makeCompactGrid. */ + private static SpringLayout.Constraints getConstraintsForCell(int row, int col, Container parent, int cols) { + SpringLayout layout = (SpringLayout) parent.getLayout(); + Component c = parent.getComponent(row * cols + col); + return layout.getConstraints(c); + } + + /** + * Aligns the first rows * cols components of + * parent in a grid. Each component in a column is as wide as the + * maximum preferred width of the components in that column; height is similarly + * determined for each row. The parent is made just big enough to fit them all. + * + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeCompactGrid(Container parent, int rows, int cols, int initialX, int initialY, int xPad, + int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout) parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeCompactGrid must use SpringLayout."); + return; + } + + // Align all cells in each column and make them the same width. + Spring x = Spring.constant(initialX); + for (int c = 0; c < cols; c++) { + Spring width = Spring.constant(0); + for (int r = 0; r < rows; r++) { + width = Spring.max(width, getConstraintsForCell(r, c, parent, cols).getWidth()); + } + for (int r = 0; r < rows; r++) { + SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); + constraints.setX(x); + constraints.setWidth(width); + } + x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad))); + } + + // Align all cells in each row and make them the same height. + Spring y = Spring.constant(initialY); + for (int r = 0; r < rows; r++) { + Spring height = Spring.constant(0); + for (int c = 0; c < cols; c++) { + height = Spring.max(height, getConstraintsForCell(r, c, parent, cols).getHeight()); + } + for (int c = 0; c < cols; c++) { + SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); + constraints.setY(y); + constraints.setHeight(height); + } + y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad))); + } + + // Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, y); + pCons.setConstraint(SpringLayout.EAST, x); + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/TranslatedListCellRenderer.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/TranslatedListCellRenderer.java new file mode 100644 index 00000000..a8eff2dd --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/TranslatedListCellRenderer.java @@ -0,0 +1,30 @@ +package de.unistuttgart.ims.coref.annotator.comp; + +import java.awt.Component; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JLabel; +import javax.swing.JList; + +import de.unistuttgart.ims.coref.annotator.Annotator; + +public class TranslatedListCellRenderer extends DefaultListCellRenderer { + + private static final long serialVersionUID = 1L; + + String prefix = ""; + + public TranslatedListCellRenderer(String prefix) { + super(); + this.prefix = prefix; + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, + boolean isSelected, boolean cellHasFocus) { + JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + l.setText(Annotator.getString(prefix + value.toString())); + return l; + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/comp/XChartPanel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/XChartPanel.java new file mode 100644 index 00000000..7f726bf7 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/comp/XChartPanel.java @@ -0,0 +1,486 @@ +package de.unistuttgart.ims.coref.annotator.comp; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.print.PageFormat; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.io.File; +import java.io.IOException; + +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.UIManager; +import javax.swing.filechooser.FileFilter; + +import org.knowm.xchart.BitmapEncoder; +import org.knowm.xchart.BitmapEncoder.BitmapFormat; +import org.knowm.xchart.CSVExporter; +import org.knowm.xchart.VectorGraphicsEncoder; +import org.knowm.xchart.VectorGraphicsEncoder.VectorGraphicsFormat; +import org.knowm.xchart.XYChart; +import org.knowm.xchart.internal.chartpart.Chart; +import org.knowm.xchart.internal.chartpart.ToolTips; + +/** + * A Swing JPanel that contains a Chart + * + *

+ * Right-click + Save As... or ctrl+S pops up a Save As dialog box for saving + * the chart as PNG, JPEG, etc. file. + * + * @author timmolter + */ +public class XChartPanel extends JPanel { + + private static final long serialVersionUID = 1L; + private final T chart; + private final Dimension preferredSize; + private String saveAsString = "Save As..."; + private String exportAsString = "Export To..."; + private String printString = "Print..."; + + /** + * Constructor + * + * @param chart + */ + public XChartPanel(final T chart) { + + this.chart = chart; + preferredSize = new Dimension(chart.getWidth(), chart.getHeight()); + + // Right-click listener for saving chart + this.addMouseListener(new PopUpMenuClickListener()); + + // Mouse motion listener for data label popup + ToolTips toolTips = chart.getToolTips(); + if (toolTips != null) { + MouseMotionListener mml = toolTips.getMouseMotionListener(); + if (mml != null) { + this.addMouseMotionListener(mml); + } + } + + // Mouse motion listener for Cursor + this.addMouseMotionListener(chart.getCursor()); + } + + /** + * Set the "Save As..." String if you want to localize it. + * + * @param saveAsString + */ + public void setSaveAsString(String saveAsString) { + + this.saveAsString = saveAsString; + } + + /** + * Set the "Export As..." String if you want to localize it. + * + * @param exportAsString + */ + public void setExportAsString(String exportAsString) { + + this.exportAsString = exportAsString; + } + + /** + * Set the "Print..." String if you want to localize it. + * + * @param printString + */ + public void setPrintString(String printString) { + + this.printString = printString; + } + + @Override + protected void paintComponent(Graphics g) { + + super.paintComponent(g); + + Graphics2D g2d = (Graphics2D) g.create(); + chart.paint(g2d, getWidth(), getHeight()); + g2d.dispose(); + } + + public T getChart() { + + return this.chart; + } + + @Override + public Dimension getPreferredSize() { + + return preferredSize; + } + + private void showPrintDialog() { + PrinterJob printJob = PrinterJob.getPrinterJob(); + if (printJob.printDialog()) { + try { + // Page format + PageFormat pageFormat = printJob.defaultPage(); + Paper paper = pageFormat.getPaper(); + if (this.getWidth() > this.getHeight()) { + pageFormat.setOrientation(PageFormat.LANDSCAPE); + paper.setImageableArea(0, 0, pageFormat.getHeight(), pageFormat.getWidth()); + } else { + paper.setImageableArea(0, 0, pageFormat.getWidth(), pageFormat.getHeight()); + } + pageFormat.setPaper(paper); + pageFormat = printJob.validatePage(pageFormat); + + String jobName = "XChart " + chart.getTitle().trim(); + printJob.setJobName(jobName); + + printJob.setPrintable(new Printer(this), pageFormat); + printJob.print(); + } catch (PrinterException e) { + e.printStackTrace(); + } + } + } + + private void showSaveAsDialog() { + + UIManager.put("FileChooser.saveButtonText", "Save"); + UIManager.put("FileChooser.fileNameLabelText", "File Name:"); + JFileChooser fileChooser = new JFileChooser(); + FileFilter pngFileFilter = new SuffixSaveFilter("png"); // default + fileChooser.addChoosableFileFilter(pngFileFilter); + fileChooser.addChoosableFileFilter(new SuffixSaveFilter("jpg")); + fileChooser.addChoosableFileFilter(new SuffixSaveFilter("bmp")); + fileChooser.addChoosableFileFilter(new SuffixSaveFilter("gif")); + + // VectorGraphics2D is optional, so if it's on the classpath, allow saving + // charts as vector + // graphic + try { + Class.forName("de.erichseifert.vectorgraphics2d.VectorGraphics2D"); + // it exists on the classpath + fileChooser.addChoosableFileFilter(new SuffixSaveFilter("svg")); + fileChooser.addChoosableFileFilter(new SuffixSaveFilter("eps")); + fileChooser.addChoosableFileFilter(new SuffixSaveFilter("pdf")); + } catch (ClassNotFoundException e) { + // it does not exist on the classpath + } + + fileChooser.setAcceptAllFileFilterUsed(false); + + fileChooser.setFileFilter(pngFileFilter); + + if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { + + if (fileChooser.getSelectedFile() != null) { + File theFileToSave = fileChooser.getSelectedFile(); + try { + if (fileChooser.getFileFilter() == null) { + BitmapEncoder.saveBitmap(chart, theFileToSave.getCanonicalPath(), BitmapFormat.PNG); + } else if (fileChooser.getFileFilter().getDescription().equals("*.jpg,*.JPG")) { + BitmapEncoder.saveJPGWithQuality(chart, + BitmapEncoder.addFileExtension(theFileToSave.getCanonicalPath(), BitmapFormat.JPG), + 1.0f); + } else if (fileChooser.getFileFilter().getDescription().equals("*.png,*.PNG")) { + BitmapEncoder.saveBitmap(chart, theFileToSave.getCanonicalPath(), BitmapFormat.PNG); + } else if (fileChooser.getFileFilter().getDescription().equals("*.bmp,*.BMP")) { + BitmapEncoder.saveBitmap(chart, theFileToSave.getCanonicalPath(), BitmapFormat.BMP); + } else if (fileChooser.getFileFilter().getDescription().equals("*.gif,*.GIF")) { + BitmapEncoder.saveBitmap(chart, theFileToSave.getCanonicalPath(), BitmapFormat.GIF); + } else if (fileChooser.getFileFilter().getDescription().equals("*.svg,*.SVG")) { + VectorGraphicsEncoder.saveVectorGraphic(chart, theFileToSave.getCanonicalPath(), + VectorGraphicsFormat.SVG); + } else if (fileChooser.getFileFilter().getDescription().equals("*.eps,*.EPS")) { + VectorGraphicsEncoder.saveVectorGraphic(chart, theFileToSave.getCanonicalPath(), + VectorGraphicsFormat.EPS); + } else if (fileChooser.getFileFilter().getDescription().equals("*.pdf,*.PDF")) { + VectorGraphicsEncoder.saveVectorGraphic(chart, theFileToSave.getCanonicalPath(), + VectorGraphicsFormat.PDF); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + private void showExportAsDialog() { + + UIManager.put("FileChooser.saveButtonText", "Export"); + UIManager.put("FileChooser.fileNameLabelText", "Export To:"); + UIManager.put("FileChooser.saveDialogFileNameLabel.textAndMnemonic", "Export To:"); + // UIDefaults defaults = UIManager.getDefaults(); + // System.out.println(defaults.size()+ " properties"); + // for (Enumeration e = defaults.keys(); + // e.hasMoreElements();) { + // Object key = e.nextElement(); + // System.out.println(key + " = " + defaults.get(key)); + // } + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fileChooser.setFileFilter(new FileFilter() { + + @Override + public boolean accept(File f) { + + return f.isDirectory(); + } + + @Override + public String getDescription() { + + return "Any Directory"; + } + }); + fileChooser.setAcceptAllFileFilterUsed(false); + fileChooser.setDialogTitle("Export"); + + if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { + + File theFileToSave = fileChooser.getSelectedFile(); + try { + CSVExporter.writeCSVColumns((XYChart) chart, theFileToSave.getCanonicalPath() + File.separatorChar); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private class SaveAction extends AbstractAction { + + public SaveAction() { + + super("save"); + } + + @Override + public void actionPerformed(ActionEvent e) { + + showSaveAsDialog(); + } + } + + private class ExportAction extends AbstractAction { + + public ExportAction() { + + super("export"); + } + + @Override + public void actionPerformed(ActionEvent e) { + + showExportAsDialog(); + } + } + + private class PrintAction extends AbstractAction { + + public PrintAction() { + + super("print"); + } + + @Override + public void actionPerformed(ActionEvent e) { + + showPrintDialog(); + } + } + + /** + * File filter based on the suffix of a file. This file filter accepts all files + * that end with .suffix or the capitalized suffix. + * + * @author Benedikt Bünz + */ + private class SuffixSaveFilter extends FileFilter { + + private final String suffix; + + /** + * @param suffix This file filter accepts all files that end with .suffix or the + * capitalized suffix. + */ + public SuffixSaveFilter(String suffix) { + + this.suffix = suffix; + } + + @Override + public boolean accept(File f) { + + if (f.isDirectory()) { + return true; + } + + String s = f.getName(); + + return s.endsWith("." + suffix) || s.endsWith("." + suffix.toUpperCase()); + } + + @Override + public String getDescription() { + + return "*." + suffix + ",*." + suffix.toUpperCase(); + } + } + + private class PopUpMenuClickListener extends MouseAdapter { + + @Override + public void mousePressed(MouseEvent e) { + + if (e.isPopupTrigger()) { + doPop(e); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + + if (e.isPopupTrigger()) { + doPop(e); + } + } + + private void doPop(MouseEvent e) { + + XChartPanelPopupMenu menu = new XChartPanelPopupMenu(); + menu.show(e.getComponent(), e.getX(), e.getY()); + menu.getGraphics().dispose(); + } + } + + private class XChartPanelPopupMenu extends JPopupMenu { + + final JMenuItem saveAsMenuItem; + final JMenuItem printMenuItem; + JMenuItem exportAsMenuItem; + + public XChartPanelPopupMenu() { + + saveAsMenuItem = new JMenuItem(saveAsString); + saveAsMenuItem.addMouseListener(new MouseListener() { + + @Override + public void mouseReleased(MouseEvent e) { + + showSaveAsDialog(); + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseClicked(MouseEvent e) { + } + }); + add(saveAsMenuItem); + + printMenuItem = new JMenuItem(printString); + printMenuItem.addMouseListener(new MouseListener() { + + @Override + public void mouseReleased(MouseEvent e) { + + showPrintDialog(); + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseClicked(MouseEvent e) { + } + }); + add(printMenuItem); + + if (chart instanceof XYChart) { + exportAsMenuItem = new JMenuItem(exportAsString); + exportAsMenuItem.addMouseListener(new MouseListener() { + + @Override + public void mouseReleased(MouseEvent e) { + + showExportAsDialog(); + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseClicked(MouseEvent e) { + } + }); + add(exportAsMenuItem); + } + } + } + + public static class Printer implements Printable { + private Component component; + + Printer(Component c) { + component = c; + } + + @Override + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) { + if (pageIndex > 0) { + return NO_SUCH_PAGE; + } + + Graphics2D g2 = (Graphics2D) graphics; + g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); + double sx = pageFormat.getImageableWidth() / component.getWidth(); + double sy = pageFormat.getImageableHeight() / component.getHeight(); + g2.scale(sx, sy); + + component.printAll(g2); + + return PAGE_EXISTS; + } + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/CoreferenceModel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/CoreferenceModel.java index 7146b16a..0a489b9f 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/CoreferenceModel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/CoreferenceModel.java @@ -9,18 +9,22 @@ import org.apache.commons.collections4.multimap.HashSetValuedHashMap; import org.apache.commons.lang3.StringUtils; import org.apache.uima.cas.CASException; +import org.apache.uima.cas.CASRuntimeException; import org.apache.uima.cas.Feature; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.fit.factory.AnnotationFactory; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.EmptyFSList; import org.apache.uima.jcas.cas.FSArray; -import org.apache.uima.jcas.cas.StringArray; +import org.apache.uima.jcas.cas.FSList; +import org.apache.uima.jcas.cas.NonEmptyFSList; import org.apache.uima.jcas.tcas.Annotation; import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.api.multimap.list.MutableListMultimap; import org.eclipse.collections.api.multimap.set.MutableSetMultimap; +import org.eclipse.collections.api.multimap.sortedset.MutableSortedSetMultimap; import org.eclipse.collections.api.set.ImmutableSet; import org.eclipse.collections.api.set.MutableSet; import org.eclipse.collections.api.set.sorted.ImmutableSortedSet; @@ -36,40 +40,39 @@ import de.unistuttgart.ims.coref.annotator.Defaults; import de.unistuttgart.ims.coref.annotator.RangedHashSetValuedHashMap; import de.unistuttgart.ims.coref.annotator.Span; +import de.unistuttgart.ims.coref.annotator.Spans; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Comment; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Comment; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.coref.annotator.document.Event.Type; import de.unistuttgart.ims.coref.annotator.document.op.AddEntityToEntityGroup; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToEntity; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToNewEntity; -import de.unistuttgart.ims.coref.annotator.document.op.AttachPart; +import de.unistuttgart.ims.coref.annotator.document.op.AddSpanToMention; import de.unistuttgart.ims.coref.annotator.document.op.CoreferenceModelOperation; import de.unistuttgart.ims.coref.annotator.document.op.DuplicateMentions; import de.unistuttgart.ims.coref.annotator.document.op.GroupEntities; import de.unistuttgart.ims.coref.annotator.document.op.MergeEntities; import de.unistuttgart.ims.coref.annotator.document.op.MergeMentions; -import de.unistuttgart.ims.coref.annotator.document.op.MoveMentionPartToMention; import de.unistuttgart.ims.coref.annotator.document.op.MoveMentionsToEntity; import de.unistuttgart.ims.coref.annotator.document.op.Operation; import de.unistuttgart.ims.coref.annotator.document.op.RemoveDuplicateMentionsInEntities; import de.unistuttgart.ims.coref.annotator.document.op.RemoveEntities; import de.unistuttgart.ims.coref.annotator.document.op.RemoveEntitiesFromEntityGroup; import de.unistuttgart.ims.coref.annotator.document.op.RemoveMention; -import de.unistuttgart.ims.coref.annotator.document.op.RemovePart; +import de.unistuttgart.ims.coref.annotator.document.op.RemoveMentionSurface; import de.unistuttgart.ims.coref.annotator.document.op.RemoveSingletons; import de.unistuttgart.ims.coref.annotator.document.op.RenameAllEntities; import de.unistuttgart.ims.coref.annotator.document.op.ToggleGenericFlag; import de.unistuttgart.ims.coref.annotator.document.op.UpdateEntityColor; import de.unistuttgart.ims.coref.annotator.document.op.UpdateEntityKey; import de.unistuttgart.ims.coref.annotator.document.op.UpdateEntityName; -import de.unistuttgart.ims.coref.annotator.uima.AnnotationComparator; +import de.unistuttgart.ims.coref.annotator.uima.AnnotationUtil; +import de.unistuttgart.ims.coref.annotator.uima.MentionComparator; import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; -import de.unistuttgart.ims.uimautil.AnnotationUtil; /** * Class represents the document and the tree view on the document. All @@ -80,7 +83,7 @@ public class CoreferenceModel extends SubModel implements Model, PreferenceChangeListener { public static enum EntitySorter { - LABEL, CHILDREN, COLOR + LABEL, CHILDREN, COLOR, ADDRESS } /** @@ -100,9 +103,10 @@ public static enum EntitySorter { */ MutableList crModelListeners = Lists.mutable.empty(); - MutableSetMultimap entityMentionMap = Multimaps.mutable.set.empty(); + MutableSortedSetMultimap entityMentionMap = Multimaps.mutable.sortedSet + .of(new MentionComparator()); - MutableSetMultimap entityEntityGroupMap = Multimaps.mutable.set.empty(); + MutableSetMultimap entityEntityGroupMap = Multimaps.mutable.set.empty(); Map keyMap = Maps.mutable.empty(); @@ -143,55 +147,16 @@ private Mention addTo(Entity e, Span span) { return addTo(e, span.begin, span.end); } - /** - * does not fire events - * - * @param m - * @param begin - * @param end - * @return - */ - private DetachedMentionPart addTo(Mention m, int begin, int end) { - // document model - DetachedMentionPart d = createDetachedMentionPart(begin, end); - d.setMention(m); - m.setDiscontinuous(d); - - return d; - } - - private DetachedMentionPart addTo(Mention m, Span sp) { - return addTo(m, sp.begin, sp.end); - } - - protected DetachedMentionPart createDetachedMentionPart(int b, int e) { - DetachedMentionPart dmp = AnnotationFactory.createAnnotation(documentModel.getJcas(), b, e, - DetachedMentionPart.class); - if (getPreferences().getBoolean(Constants.CFG_TRIM_WHITESPACE, true)) - dmp = AnnotationUtil.trim(dmp); - registerAnnotation(dmp); - return dmp; - } - protected Entity createEntity(String l) { Entity e = new Entity(documentModel.getJcas()); e.setColor(colorMap.getNextColor().getRGB()); e.setLabel(l); - e.setFlags(new StringArray(documentModel.getJcas(), 0)); + e.setFlags(new EmptyFSList(documentModel.getJcas())); + e.setMembers(new FSArray(documentModel.getJcas(), 0)); e.addToIndexes(); return e; } - protected EntityGroup createEntityGroup(String l, int initialSize) { - EntityGroup e = new EntityGroup(documentModel.getJcas()); - e.setColor(colorMap.getNextColor().getRGB()); - e.setLabel(l); - e.setFlags(new StringArray(documentModel.getJcas(), 0)); - e.addToIndexes(); - e.setMembers(new FSArray(documentModel.getJcas(), initialSize)); - return e; - } - protected String createEntityGroupLabel(ImmutableList entityList) { String s = entityList.subList(0, Math.min(entityList.size(), 2)).select(e -> e.getLabel() != null) .collect( @@ -210,12 +175,13 @@ protected String createEntityGroupLabel(ImmutableList entityList) { * @return the created mention */ protected Mention createMention(int b, int e) { - Mention m = AnnotationFactory.createAnnotation(documentModel.getJcas(), b, e, Mention.class); + Mention m = UimaUtil.createMention(documentModel.getJcas(), b, e); if (getPreferences().getBoolean(Constants.CFG_TRIM_WHITESPACE, Defaults.CFG_TRIM_WHITESPACE)) - m = AnnotationUtil.trim(m); + AnnotationUtil.trim(m.getSurface(0)); if (getPreferences().getBoolean(Constants.CFG_FULL_TOKENS, Defaults.CFG_FULL_TOKENS)) - m = Util.extend(m); - registerAnnotation(m); + UimaUtil.extend(m.getSurface(0)); + for (MentionSurface ms : m.getSurface()) + registerAnnotation(ms); return m; } @@ -229,17 +195,12 @@ protected void edit(MergeEntities op) { protected void edit(MergeMentions op) { Mention firstMention = op.getMentions().getFirstOptional().get(); - int begin = op.getMentions().getFirstOptional().get().getBegin(); - int end = op.getMentions().getLastOptional().get().getEnd(); + int begin = UimaUtil.getBegin(op.getMentions().getFirstOptional().get()); + int end = UimaUtil.getEnd(op.getMentions().getLastOptional().get()); Mention newMention = addTo(firstMention.getEntity(), begin, end); op.getMentions().forEach(m -> { remove(m, false); - if (m.getDiscontinuous() != null) { - DetachedMentionPart dmp = m.getDiscontinuous(); - remove(dmp); - fireEvent(Event.get(this, Type.Remove, m, dmp)); - } }); fireEvent(Event.get(this, Event.Type.Remove, firstMention.getEntity(), op.getMentions())); fireEvent(Event.get(this, Type.Add, newMention.getEntity(), newMention)); @@ -279,14 +240,14 @@ protected synchronized void edit(CoreferenceModelOperation operation) { fireEvent(Event.get(this, Event.Type.Update, op.getObjects().flatCollect(e -> entityMentionMap.get(e)))); } else if (operation instanceof AddEntityToEntityGroup) { AddEntityToEntityGroup op = (AddEntityToEntityGroup) operation; - MutableList oldArr = Util.toList(op.getEntityGroup().getMembers()); + MutableList oldArr = UimaUtil.toList(op.getEntityGroup().getMembers()); MutableList newMembers = Lists.mutable.withAll(op.getEntities()); newMembers.removeAll(oldArr); op.setEntities(newMembers.toImmutable()); - FSArray arr = new FSArray(documentModel.getJcas(), + FSArray arr = new FSArray(documentModel.getJcas(), op.getEntityGroup().getMembers().size() + newMembers.size()); int i = 0; for (; i < op.getEntityGroup().getMembers().size(); i++) { @@ -309,7 +270,7 @@ protected synchronized void edit(CoreferenceModelOperation operation) { Mention fst = addTo(op.getEntity(), span); ms.add(fst); if (op.getEntity().getLabel() == "") { - op.getEntity().setLabel(fst.getCoveredText()); + op.getEntity().setLabel(UimaUtil.getCoveredText(fst)); } } fireEvent(Event.get(this, Event.Type.Add, null, op.getEntity())); @@ -327,10 +288,6 @@ protected synchronized void edit(CoreferenceModelOperation operation) { fireEvent(Event.get(this, Event.Type.Update, op.getEntity())); fireEvent(Event.get(this, Event.Type.Update, get(op.getEntity()))); } - } else if (operation instanceof AttachPart) { - AttachPart op = (AttachPart) operation; - op.setPart(addTo(op.getMention(), op.getSpan())); - fireEvent(Event.get(this, Event.Type.Add, op.getMention(), op.getPart())); } else if (operation instanceof MoveMentionsToEntity) { MoveMentionsToEntity op = (MoveMentionsToEntity) operation; op.getMentions().forEach(m -> moveTo(op.getTarget(), m)); @@ -350,15 +307,6 @@ protected synchronized void edit(CoreferenceModelOperation operation) { } } - } else if (operation instanceof MoveMentionPartToMention) { - MoveMentionPartToMention op = (MoveMentionPartToMention) operation; - op.getObjects().forEach(d -> { - d.setMention(op.getTarget()); - op.getTarget().setDiscontinuous(d); - op.getSource().setDiscontinuous(null); - }); - fireEvent(op.toEvent()); - fireEvent(Event.get(this, Event.Type.Move, op.getSource(), op.getTarget(), op.getObjects())); } else if (operation instanceof RemoveEntities) { boolean keepTreeSortedSetting = getPreferences().getBoolean(Constants.CFG_KEEP_TREE_SORTED, Defaults.CFG_KEEP_TREE_SORTED); @@ -378,20 +326,19 @@ protected synchronized void edit(CoreferenceModelOperation operation) { removeFrom(op.getEntityGroup(), e); updateEntityGroupLabel(op.getEntityGroup()); }); - } else if (operation instanceof RemovePart) { - RemovePart op = (RemovePart) operation; - remove(op.getPart()); - fireEvent(Event.get(this, Type.Remove, op.getMention(), op.getPart())); } else if (operation instanceof GroupEntities) { GroupEntities op = (GroupEntities) operation; Annotator.logger.trace("Forming entity group with {}.", op.getEntities()); - EntityGroup eg = createEntityGroup(createEntityGroupLabel(op.getEntities()), op.getEntities().size()); + Entity eg = createEntity(createEntityGroupLabel(op.getEntities())); + eg.setMembers(new FSArray(documentModel.getJcas(), op.getEntities().size())); for (int i = 0; i < op.getEntities().size(); i++) { eg.setMembers(i, op.getEntities().get(i)); entityEntityGroupMap.put(op.getEntities().get(i), eg); } fireEvent(Event.get(this, Event.Type.Add, null, eg)); op.setEntityGroup(eg); + } else if (operation instanceof RemoveMentionSurface) { + edit((RemoveMentionSurface) operation); } else if (operation instanceof RemoveMention) { edit((RemoveMention) operation); } else if (operation instanceof RemoveSingletons) { @@ -406,27 +353,42 @@ protected synchronized void edit(CoreferenceModelOperation operation) { edit((RenameAllEntities) operation); } else if (operation instanceof DuplicateMentions) { edit((DuplicateMentions) operation); + } else if (operation instanceof AddSpanToMention) { + edit((AddSpanToMention) operation); } else { throw new UnsupportedOperationException(); } } + protected void edit(AddSpanToMention op) { + MentionSurface ms = AnnotationFactory.createAnnotation(getJCas(), op.getSpan().begin, op.getSpan().end, + MentionSurface.class); + op.setMentionSurface(ms); + ms.setMention(op.getTarget()); + + UimaUtil.addMentionSurface(op.getTarget(), ms); + characterPosition2AnnotationMap.add(ms); + + fireEvent(Event.get(this, Event.Type.Add, op.getTarget(), ms)); + registerEdit(op); + } + protected void edit(DuplicateMentions op) { op.setNewMentions(op.getSourceMentions().collect(oldMention -> { - Mention newMention = addTo(oldMention.getEntity(), new Span(oldMention)); + Mention newMention = addTo(oldMention.getEntity(), new Span(oldMention.getSurface(0))); + for (int i = 1; i < oldMention.getSurface().size(); i++) { + MentionSurface oMS = oldMention.getSurface(i); + MentionSurface ms = AnnotationFactory.createAnnotation(getJCas(), oMS.getBegin(), oMS.getEnd(), + MentionSurface.class); + UimaUtil.addMentionSurface(newMention, ms); + characterPosition2AnnotationMap.add(ms); + } try { if (oldMention.getFlags() != null) newMention.setFlags(UimaUtil.clone(oldMention.getFlags())); } catch (CASException e) { Annotator.logger.catching(e); } - if (oldMention.getDiscontinuous() != null) { - DetachedMentionPart dmp = AnnotationFactory.createAnnotation(getJCas(), - oldMention.getDiscontinuous().getBegin(), oldMention.getDiscontinuous().getEnd(), - DetachedMentionPart.class); - dmp.setMention(newMention); - newMention.setDiscontinuous(dmp); - } return newMention; })); op.getNewMentions().forEach(m -> fireEvent(Event.get(this, Event.Type.Add, m.getEntity(), m))); @@ -437,38 +399,19 @@ protected void edit(RemoveDuplicateMentionsInEntities op) { MutableSet allRemoved = Sets.mutable.empty(); op.getEntities().forEach(e -> { - MutableListMultimap map = Multimaps.mutable.list.empty(); + MutableListMultimap spanMentionMap = Multimaps.mutable.list.empty(); MutableList toRemove = Lists.mutable.empty(); for (Mention m : entityMentionMap.get(e)) { - Span s = new Span(m); - if (map.containsKey(s)) { - for (Mention m2 : map.get(s)) { - if (m2.getDiscontinuous() == null && m.getDiscontinuous() == null) { - toRemove.add(m); - } else if (m2.getDiscontinuous() != null && m.getDiscontinuous() != null) { - Span s1 = new Span(m.getDiscontinuous()); - Span s2 = new Span(m2.getDiscontinuous()); - if (s1.equals(s2)) { - toRemove.add(m); - } else { - map.put(s, m); - } - } else { - map.put(s, m); - } - } + Spans s = new Spans(m); + if (spanMentionMap.containsKey(s)) { + toRemove.add(m); } else { - map.put(s, m); + spanMentionMap.put(s, m); } } toRemove.forEach(m -> { remove(m, false); - if (m.getDiscontinuous() != null) { - DetachedMentionPart dmp = m.getDiscontinuous(); - remove(dmp); - fireEvent(Event.get(this, Type.Remove, m, dmp)); - } }); fireEvent(Event.get(this, Event.Type.Remove, e, toRemove.toImmutable())); allRemoved.addAll(toRemove); @@ -480,11 +423,7 @@ protected void edit(RemoveDuplicateMentionsInEntities op) { protected void edit(RemoveMention op) { op.getFeatureStructures().forEach(m -> { remove(m, false); - if (m.getDiscontinuous() != null) { - DetachedMentionPart dmp = m.getDiscontinuous(); - remove(dmp); - fireEvent(Event.get(this, Type.Remove, m, dmp)); - } + // TODO: remove surfaces }); fireEvent(Event.get(this, Event.Type.Remove, op.getEntity(), op.getFeatureStructures())); @@ -506,11 +445,28 @@ protected void edit(RemoveMention op) { registerEdit(op); } + protected void edit(RemoveMentionSurface op) { + MutableList mentions = Lists.mutable.empty(); + MutableList spans = Lists.mutable.empty(); + op.getMentionSurface().forEach(ms -> { + Mention m = ms.getMention(); + UimaUtil.removeMentionSurface(m, ms); + fireEvent(Event.get(this, Type.Remove, m, ms)); + mentions.add(m); + spans.add(new Span(ms)); + ms.removeFromIndexes(); + characterPosition2AnnotationMap.remove(ms); + }); + op.setMention(mentions.toImmutable()); + op.setSpans(spans.toImmutable()); + registerEdit(op); + } + protected void edit(RemoveSingletons operation) { MutableSet entities = Sets.mutable.empty(); MutableSet mentions = Sets.mutable.empty(); for (Entity entity : Lists.immutable.withAll(JCasUtil.select(documentModel.getJcas(), Entity.class))) { - ImmutableSet ms = getMentions(entity); + ImmutableSortedSet ms = getMentions(entity); switch (ms.size()) { case 0: remove(entity); @@ -538,19 +494,19 @@ protected void edit(RenameAllEntities operation) { switch (operation.getStrategy()) { case LAST: - nameGiver = entityMentionMap.get(entity).maxBy(m -> m.getBegin()); + nameGiver = entityMentionMap.get(entity).maxBy(m -> UimaUtil.getBegin(m)); break; case LONGEST: - nameGiver = entityMentionMap.get(entity).maxBy(m -> m.getEnd() - m.getBegin()); + nameGiver = entityMentionMap.get(entity).maxBy(m -> UimaUtil.getEnd(m) - UimaUtil.getBegin(m)); break; case FIRST: default: - nameGiver = entityMentionMap.get(entity).minBy(m -> m.getBegin()); + nameGiver = entityMentionMap.get(entity).minBy(m -> UimaUtil.getBegin(m)); break; } operation.registerOldName(entity, getLabel(entity)); - String newName = nameGiver.getCoveredText(); + String newName = UimaUtil.getCoveredText(nameGiver); entity.setLabel(newName); } @@ -561,16 +517,22 @@ protected void edit(RenameAllEntities operation) { protected void edit(ToggleGenericFlag operation) { MutableSet featureStructures = Sets.mutable.empty(); operation.getObjects().forEach(fs -> { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); featureStructures.add(fs); - if (Util.isX(fs, operation.getFlag())) { - fs.setFeatureValue(feature, Util.removeFrom(documentModel.getJcas(), - (StringArray) fs.getFeatureValue(feature), operation.getFlag())); + @SuppressWarnings("unchecked") + FSList flags = (FSList) fs.getFeatureValue(feature); + + if (UimaUtil.isX(fs, operation.getFlag())) { + fs.setFeatureValue(feature, UimaUtil.removeFrom(flags, operation.getFlag())); } else { - fs.setFeatureValue(feature, Util.addTo(documentModel.getJcas(), - (StringArray) fs.getFeatureValue(feature), operation.getFlag())); + if (flags == null) { + fs.setFeatureValue(feature, new NonEmptyFSList(documentModel.getJcas(), operation.getFlag())); + } else { + fs.setFeatureValue(feature, flags.push(operation.getFlag())); + } } }); fireEvent(Event.get(this, Event.Type.Update, operation.getObjects())); @@ -584,7 +546,7 @@ protected void fireEvent(FeatureStructureEvent event) { crModelListeners.forEach(l -> l.entityEvent(event)); } - public ImmutableSet get(Entity entity) { + public ImmutableSortedSet get(Entity entity) { return entityMentionMap.get(entity).toImmutable(); } @@ -614,8 +576,9 @@ public int compare(Entity o1, Entity o2) { return Integer.compare(entityMentionMap.get(o2).size(), entityMentionMap.get(o1).size()); case COLOR: return Integer.compare(o1.getColor(), o2.getColor()); + case ADDRESS: default: - return o1.getLabel().compareTo(o2.getLabel()); + return Integer.compare(o1.getAddress(), o2.getAddress()); } } @@ -634,33 +597,55 @@ public String getLabel(Entity entity) { if (entity.getLabel() != null) return entity.getLabel(); - return get(entity).collect(m -> m.getCoveredText()).maxBy(s -> s.length()); + return get(entity).collect(m -> UimaUtil.getCoveredText(m)).maxBy(s -> s.length()); } public ImmutableSortedSet getMentions() { - return SortedSets.immutable.withAll(new AnnotationComparator(), JCasUtil.select(getJCas(), Mention.class)); + return SortedSets.immutable.withAll(new MentionComparator(), JCasUtil.select(getJCas(), Mention.class)); } - public ImmutableSet getMentions(Entity entity) { + public ImmutableSortedSet getMentions(Entity entity) { return entityMentionMap.get(entity).toImmutable(); } + @SuppressWarnings("resource") + public MentionSurface getNextMentionSurface(int position) { + try { + return getJCas().select(MentionSurface.class).following(position).get(); + } catch (Exception e) { + Annotator.logger.catching(e); + return null; + } + } + + @SuppressWarnings("resource") public Mention getNextMention(int position) { - for (int i = position; i < getDocumentModel().getJcas().getDocumentText().length(); i++) { - MutableSet mentions = characterPosition2AnnotationMap.get(i).selectInstancesOf(Mention.class); - if (!mentions.isEmpty()) - return mentions.iterator().next(); + try { + return getJCas().select(MentionSurface.class).following(position).get().getMention(); + } catch (Exception e) { + Annotator.logger.catching(e); + return null; + } + } + + @SuppressWarnings("resource") + public MentionSurface getPreviousMentionSurface(int position) { + try { + return getJCas().select(MentionSurface.class).preceding(position).backwards().get(); + } catch (Exception e) { + Annotator.logger.catching(e); + return null; } - return null; } + @SuppressWarnings("resource") public Mention getPreviousMention(int position) { - for (int i = position - 1; i >= 0; i--) { - MutableSet mentions = characterPosition2AnnotationMap.get(i).selectInstancesOf(Mention.class); - if (!mentions.isEmpty()) - return mentions.iterator().next(); + try { + return getJCas().select(MentionSurface.class).preceding(position).get().getMention(); + } catch (Exception e) { + Annotator.logger.catching(e); + return null; } - return null; } /** @@ -669,23 +654,30 @@ public Mention getPreviousMention(int position) { * @param position The character position * @return A collection of annotations */ - public MutableSet getMentions(int position) { + public MutableSet getMentionSurfaces(int position) { return this.characterPosition2AnnotationMap.get(position); } - public ImmutableSet getMentionsBetween(int start, int end) { - MutableSet mentions = Sets.mutable.empty(); + public MutableSet getMentions(int position) { + return this.characterPosition2AnnotationMap.get(position).selectInstancesOf(MentionSurface.class) + .collect(ms -> ms.getMention()); + } + + public ImmutableSet getMentionsBetween(int start, int end) { + MutableSet mentions = Sets.mutable.empty(); for (int i = start; i <= end; i++) { - mentions.addAll(characterPosition2AnnotationMap.get(i).select(a -> a instanceof Mention)); + mentions.addAll(characterPosition2AnnotationMap.get(i).selectInstancesOf(MentionSurface.class) + .collect(ms -> ms.getMention())); } return mentions.toImmutable(); } + // TODO: adapt to non-continuous mentions public ImmutableSet getMatchingMentions(int start, int end) { - MutableSet mentions = Sets.mutable.empty(); - mentions.addAll( + MutableSet mentionSurfaces = Sets.mutable.empty(); + mentionSurfaces.addAll( characterPosition2AnnotationMap.get(start).select(m -> m.getEnd() == end && m.getBegin() == start)); - return mentions.selectInstancesOf(Mention.class).toImmutable(); + return mentionSurfaces.selectInstancesOf(MentionSurface.class).collect(ms -> ms.getMention()).toImmutable(); } public Preferences getPreferences() { @@ -698,22 +690,20 @@ private boolean getSpecialHandlingForSingletons() { } public String getToolTipText(FeatureStructure featureStructure) { - if (featureStructure instanceof EntityGroup) { - StringBuilder b = new StringBuilder(); - EntityGroup entityGroup = (EntityGroup) featureStructure; - if (entityGroup.getMembers().size() > 0) { - if (entityGroup.getMembers(0) != null && entityGroup.getMembers(0).getLabel() != null) - b.append(entityGroup.getMembers(0).getLabel()); - for (int i = 1; i < entityGroup.getMembers().size(); i++) { + if (featureStructure instanceof Entity) { + Entity e = (Entity) featureStructure; + if (UimaUtil.isGroup(featureStructure)) { + StringBuilder b = new StringBuilder(); + if (e.getMembers(0) != null && e.getMembers(0).getLabel() != null) + b.append(e.getMembers(0).getLabel()); + for (int i = 1; i < e.getMembers().size(); i++) { b.append(", "); - b.append(entityGroup.getMembers(i).getLabel()); + b.append(e.getMembers(i).getLabel()); } return b.toString(); - } else { - return null; - } - } else if (featureStructure instanceof Entity) { - return ((Entity) featureStructure).getLabel(); + } else + return e.getLabel(); + } return null; } @@ -726,11 +716,13 @@ protected void initializeOnce() { } for (Mention mention : JCasUtil.select(documentModel.getJcas(), Mention.class)) { entityMentionMap.put(mention.getEntity(), mention); - mention.getEntity().addToIndexes(); - registerAnnotation(mention); - if (mention.getDiscontinuous() != null) { - registerAnnotation(mention.getDiscontinuous()); + try { + // TODO: Why do we do that? + // mention.getEntity().addToIndexes(); + } catch (CASRuntimeException e) { + Annotator.logger.catching(e); } + registerAnnotation(mention); } } @@ -748,10 +740,7 @@ public void initialPainting() { mention.getEntity().addToIndexes(); registerAnnotation(mention); fireEvent(Event.get(this, Event.Type.Add, mention.getEntity(), mention)); - if (mention.getDiscontinuous() != null) { - registerAnnotation(mention.getDiscontinuous()); - fireEvent(Event.get(this, Event.Type.Add, mention, mention.getDiscontinuous())); - } + } initialized = true; } @@ -800,20 +789,15 @@ public void registerAnnotation(Annotation a) { characterPosition2AnnotationMap.add(a); } + public void registerAnnotation(Mention a) { + for (MentionSurface ms : a.getSurface()) + registerAnnotation(ms); + } + private void registerEdit(Operation operation) { documentModel.fireDocumentChangedEvent(); } - /** - * does not fire evetns - * - * @param dmp - */ - private void remove(DetachedMentionPart dmp) { - dmp.removeFromIndexes(); - characterPosition2AnnotationMap.remove(dmp); - }; - /** * Removes entity and fires events * @@ -823,12 +807,13 @@ private void remove(Entity entity) { Annotator.logger.traceEntry(); fireEvent(Event.get(this, Event.Type.Remove, entity, entityMentionMap.get(entity).toList().toImmutable())); for (Mention m : entityMentionMap.get(entity)) { - characterPosition2AnnotationMap.remove(m); + for (MentionSurface ms : m.getSurface()) + characterPosition2AnnotationMap.remove(ms); m.removeFromIndexes(); // TODO: remove parts } - for (EntityGroup group : entityEntityGroupMap.get(entity)) { - group.setMembers(Util.removeFrom(documentModel.getJcas(), group.getMembers(), entity)); + for (Entity group : entityEntityGroupMap.get(entity)) { + group.setMembers(UimaUtil.removeFrom(documentModel.getJcas(), group.getMembers(), entity)); updateEntityGroupLabel(group); fireEvent(Event.get(this, Event.Type.Remove, group, entity)); } @@ -843,7 +828,8 @@ private void remove(Entity entity) { private void remove(Mention m, boolean autoRemove) { Entity entity = m.getEntity(); - characterPosition2AnnotationMap.remove(m); + for (MentionSurface ms : m.getSurface()) + characterPosition2AnnotationMap.remove(ms); entityMentionMap.remove(entity, m); m.removeFromIndexes(); if (autoRemove && entityMentionMap.get(entity).isEmpty() && getPreferences() @@ -863,9 +849,9 @@ public boolean removeCoreferenceModelListener(Object o) { * @param eg * @param entity */ - private void removeFrom(EntityGroup eg, Entity entity) { - FSArray oldArray = eg.getMembers(); - FSArray arr = new FSArray(documentModel.getJcas(), oldArray.size() - 1); + private void removeFrom(Entity eg, Entity entity) { + FSArray oldArray = eg.getMembers(); + FSArray arr = new FSArray(documentModel.getJcas(), oldArray.size() - 1); for (int i = 0, j = 0; i < oldArray.size() - 1 && j < arr.size() - 1; i++, j++) { @@ -879,6 +865,14 @@ private void removeFrom(EntityGroup eg, Entity entity) { fireEvent(Event.get(this, Event.Type.Remove, eg, entity)); } + protected void undo(AddSpanToMention op) { + MentionSurface ms = op.getMentionSurface(); + UimaUtil.removeMentionSurface(ms.getMention(), ms); + fireEvent(Event.get(this, Event.Type.Remove, ms.getMention(), ms)); + ms.removeFromIndexes(); + characterPosition2AnnotationMap.remove(ms); + } + protected void undo(CoreferenceModelOperation operation) { Annotator.logger.traceEntry(); if (operation instanceof UpdateEntityName) { @@ -924,18 +918,6 @@ protected void undo(CoreferenceModelOperation operation) { if (getSpecialHandlingForSingletons() && getSize(op.getEntity()) == 1) { fireEvent(Event.get(this, Event.Type.Update, get(op.getEntity()))); } - } else if (operation instanceof AttachPart) { - AttachPart op = (AttachPart) operation; - remove(op.getPart()); - fireEvent(Event.get(this, Event.Type.Remove, op.getMention(), op.getPart())); - } else if (operation instanceof MoveMentionPartToMention) { - MoveMentionPartToMention op = (MoveMentionPartToMention) operation; - op.getObjects().forEach(d -> { - op.getSource().setDiscontinuous(d); - d.setMention(op.getSource()); - op.getTarget().setDiscontinuous(null); - }); - fireEvent(op.toReversedEvent()); } else if (operation instanceof MoveMentionsToEntity) { MoveMentionsToEntity op = (MoveMentionsToEntity) operation; op.getMentions().forEach(m -> moveTo(op.getSource(), m)); @@ -956,11 +938,6 @@ protected void undo(CoreferenceModelOperation operation) { registerAnnotation(m); fireEvent(Event.get(this, Type.Add, m.getEntity(), m)); }); - } else if (operation instanceof RemovePart) { - RemovePart op = (RemovePart) operation; - op.getPart().setMention(op.getMention()); - op.getMention().setDiscontinuous(op.getPart()); - fireEvent(Event.get(this, Type.Add, op.getMention(), op.getPart())); } else if (operation instanceof RemoveMention) { undo((RemoveMention) operation); } else if (operation instanceof RemoveEntities) { @@ -968,8 +945,8 @@ protected void undo(CoreferenceModelOperation operation) { op.getFeatureStructures().forEach(e -> { e.addToIndexes(); if (op.entityEntityGroupMap.containsKey(e)) { - for (EntityGroup group : op.entityEntityGroupMap.get(e)) { - group.setMembers(Util.addTo(documentModel.getJcas(), group.getMembers(), e)); + for (Entity group : op.entityEntityGroupMap.get(e)) { + group.setMembers(UimaUtil.addTo(documentModel.getJcas(), group.getMembers(), e)); entityEntityGroupMap.put(e, group); updateEntityGroupLabel(group); } @@ -978,8 +955,9 @@ protected void undo(CoreferenceModelOperation operation) { fireEvent(Event.get(this, Event.Type.Add, null, op.getFeatureStructures())); } else if (operation instanceof RemoveEntitiesFromEntityGroup) { RemoveEntitiesFromEntityGroup op = (RemoveEntitiesFromEntityGroup) operation; - FSArray oldArr = op.getEntityGroup().getMembers(); - FSArray newArr = new FSArray(documentModel.getJcas(), oldArr.size() + op.getEntities().size()); + FSArray oldArr = op.getEntityGroup().getMembers(); + FSArray newArr = new FSArray(documentModel.getJcas(), + oldArr.size() + op.getEntities().size()); int i = 0; for (; i < oldArr.size(); i++) { newArr.set(i, oldArr.get(i)); @@ -1017,6 +995,10 @@ protected void undo(CoreferenceModelOperation operation) { undo((MergeMentions) operation); } else if (operation instanceof DuplicateMentions) { undo((DuplicateMentions) operation); + } else if (operation instanceof RemoveMentionSurface) { + undo((RemoveMentionSurface) operation); + } else if (operation instanceof AddSpanToMention) { + undo((AddSpanToMention) operation); } } @@ -1035,25 +1017,32 @@ private void undo(RemoveMention op) { m.addToIndexes(); m.setEntity(op.getEntity()); entityMentionMap.put(op.getEntity(), m); - characterPosition2AnnotationMap.add(m); - if (m.getDiscontinuous() != null) { - m.getDiscontinuous().addToIndexes(); - characterPosition2AnnotationMap.add(m.getDiscontinuous()); - } + for (MentionSurface ms : m.getSurface()) + characterPosition2AnnotationMap.add(ms); }); // fire event to draw them fireEvent(Event.get(this, Event.Type.Add, op.getEntity(), op.getFeatureStructures())); // re-create attached parts (if any) - op.getFeatureStructures().select(m -> m.getDiscontinuous() != null) - .forEach(m -> fireEvent(Event.get(this, Event.Type.Add, m, m.getDiscontinuous()))); + // TODO: re-create surfaces + } + private void undo(RemoveMentionSurface op) { + for (int i = 0; i < op.getSpans().size(); i++) { + Mention m = op.getMention(i); + Span s = op.getSpan(i); + MentionSurface ms = AnnotationFactory.createAnnotation(getJCas(), s.begin, s.end, MentionSurface.class); + ms.setMention(m); + UimaUtil.addMentionSurface(m, ms); + fireEvent(Event.get(this, Event.Type.Add, m, ms)); + } } private void undo(RemoveSingletons op) { op.getFeatureStructures().forEach(e -> e.addToIndexes()); op.getMentions().forEach(m -> { entityMentionMap.put(m.getEntity(), m); - characterPosition2AnnotationMap.add(m); + for (MentionSurface ms : m.getSurface()) + characterPosition2AnnotationMap.add(ms); m.addToIndexes(); m.getEntity().addToIndexes(); fireEvent(Event.get(this, Event.Type.Add, null, m.getEntity())); @@ -1095,7 +1084,7 @@ protected void undo(MergeMentions operation) { fireEvent(Event.get(this, Type.Remove, operation.getNewMention().getEntity(), operation.getNewMention())); } - private void updateEntityGroupLabel(EntityGroup entityGroup) { + private void updateEntityGroupLabel(Entity entityGroup) { entityGroup.setLabel(createEntityGroupLabel( Lists.immutable.ofAll(entityGroup.getMembers()).selectInstancesOf(Entity.class))); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/DocumentModel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/DocumentModel.java index cb4d701b..f1ef805e 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/DocumentModel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/DocumentModel.java @@ -1,5 +1,8 @@ package de.unistuttgart.ims.coref.annotator.document; +import java.io.File; +import java.awt.Color; +import java.lang.reflect.Field; import java.util.Deque; import java.util.LinkedList; import java.util.List; @@ -20,8 +23,8 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.Span; import de.unistuttgart.ims.coref.annotator.TypeSystemVersion; -import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Line; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Line; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModel.EntitySorter; import de.unistuttgart.ims.coref.annotator.document.op.AddFlag; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToNewEntity; @@ -29,6 +32,7 @@ import de.unistuttgart.ims.coref.annotator.document.op.DocumentModelOperation; import de.unistuttgart.ims.coref.annotator.document.op.FlagModelOperation; import de.unistuttgart.ims.coref.annotator.document.op.Operation; +import de.unistuttgart.ims.coref.annotator.document.op.ToggleGenericFlag; import de.unistuttgart.ims.coref.annotator.document.op.UpdateDocumentProperty; import de.unistuttgart.ims.coref.annotator.document.op.UpdateEntityColor; import de.unistuttgart.ims.coref.annotator.document.op.UpdateEntityKey; @@ -38,6 +42,7 @@ import de.unistuttgart.ims.coref.annotator.profile.FlagType; import de.unistuttgart.ims.coref.annotator.profile.PreferenceType; import de.unistuttgart.ims.coref.annotator.profile.Profile; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; /** * This class represents an opened document. Individual aspects are stored in @@ -72,6 +77,8 @@ public class DocumentModel implements Model { Profile profile; + File file = null; + transient int savedHistoryHash = history.hashCode(); public DocumentModel(JCas jcas, Preferences preferences) { @@ -83,16 +90,16 @@ public boolean addDocumentStateListener(DocumentStateListener e) { return documentStateListeners.add(e); } - public void edit(Operation operation) { + public T edit(T operation) { Annotator.logger.trace(operation); - edit(operation, true); + return edit(operation, true); } - private void edit(Operation operation, boolean addToHistory) { + private T edit(T operation, boolean addToHistory) { if (isBlocked(operation.getClass())) { Annotator.logger.info("Operation {} blocked.", operation.getClass().getCanonicalName()); - return; + return operation; } if (operation instanceof DocumentModelOperation) @@ -105,6 +112,7 @@ private void edit(Operation operation, boolean addToHistory) { if (addToHistory) history.push(operation); fireDocumentChangedEvent(); + return operation; } protected void edit(DocumentModelOperation operation) { @@ -192,7 +200,7 @@ public SegmentModel getSegmentModel() { @SuppressWarnings("unchecked") public Class getStylePlugin() throws ClassNotFoundException { - return (Class) Class.forName(Util.getMeta(jcas).getStylePlugin()); + return (Class) Class.forName(UimaUtil.getMeta(jcas).getStylePlugin()); } public EntityTreeModel getTreeModel() { @@ -229,7 +237,7 @@ public void loadProfile(Profile profile) { if (getFlagModel().getFlag(ft.getUuid()) != null) continue; try { - String targetClassName = "de.unistuttgart.ims.coref.annotator.api.v1." + ft.getTargetClass().value(); + String targetClassName = "de.unistuttgart.ims.coref.annotator.api.v2." + ft.getTargetClass().value(); Class tClass = Class.forName(targetClassName); @SuppressWarnings("unchecked") @@ -248,12 +256,31 @@ public void loadProfile(Profile profile) { AddMentionsToNewEntity op = new AddMentionsToNewEntity(); edit(op, false); edit(new UpdateEntityName(op.getEntity(), et.getLabel()), false); - if (et.getColor() != null) - edit(new UpdateEntityColor(op.getEntity(), et.getColor()), false); - else + if (et.getColor() != null) { + Color c = new Color(0); + if (et.getColor().matches("^\\d+$")) { + c = new Color(Integer.parseInt(et.getColor())); + } else { + Field field; + try { + field = Class.forName("java.awt.Color").getField(et.getColor()); + c = (Color) field.get(null); + } catch (NoSuchFieldException | SecurityException | ClassNotFoundException + | IllegalArgumentException | IllegalAccessException e1) { + e1.printStackTrace(); + } + } + edit(new UpdateEntityColor(op.getEntity(), c.getRGB()), false); + } else edit(new UpdateEntityColor(op.getEntity(), 0), false); if (et.getShortcut() != null) edit(new UpdateEntityKey(op.getEntity(), et.getShortcut().charAt(0)), false); + if (et.getFlags() != null && !et.getFlags().isBlank()) { + for (String uuid : et.getFlags().split("\\s+")) { + Flag flag = getFlagModel().getFlag(uuid); + edit(new ToggleGenericFlag(flag, Lists.immutable.of(op.getEntity()))); + } + } } for (PreferenceType pt : profile.getPreferences().getPreference()) { @@ -444,4 +471,12 @@ public Profile getProfile() { public void setProfile(Profile profile) { this.profile = profile; } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/EntityTreeModel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/EntityTreeModel.java index 3b912e30..0a93390b 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/EntityTreeModel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/EntityTreeModel.java @@ -11,23 +11,27 @@ import org.apache.uima.cas.FeatureStructure; import org.apache.uima.fit.util.JCasUtil; -import org.apache.uima.jcas.cas.StringArray; +import org.apache.uima.jcas.cas.FSList; import org.apache.uima.jcas.tcas.Annotation; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.factory.Lists; import org.eclipse.collections.impl.factory.Maps; +import org.eclipse.collections.impl.factory.SortedSets; import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.CATreeNode; import de.unistuttgart.ims.coref.annotator.Constants; import de.unistuttgart.ims.coref.annotator.Defaults; import de.unistuttgart.ims.coref.annotator.EntitySortOrder; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.coref.annotator.comp.SortingTreeModelListener; +import de.unistuttgart.ims.coref.annotator.document.CoreferenceModel.EntitySorter; import de.unistuttgart.ims.coref.annotator.document.op.UpdateEntityName; +import de.unistuttgart.ims.coref.annotator.uima.MentionComparator; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class EntityTreeModel extends DefaultTreeModel implements CoreferenceModelListener, Model, ModelAdapter { private static final long serialVersionUID = 1L; @@ -68,6 +72,8 @@ private CATreeNode createNode(FeatureStructure fs) { node = new CATreeNode(fs, ((Entity) fs).getLabel()); } else if (fs instanceof Annotation) { node = new CATreeNode(fs, ((Annotation) fs).getCoveredText()); + } else if (fs instanceof Mention) { + node = new CATreeNode(fs, UimaUtil.getCoveredText((Mention) fs)); } if (node != null) fsMap.put(fs, node); @@ -82,11 +88,13 @@ public void entityEvent(FeatureStructureEvent event) { case Add: CATreeNode arg0 = get(event.getArgument(0)); for (FeatureStructure fs : event.iterable(1)) { - if (fs instanceof Mention || fs instanceof Entity || fs instanceof DetachedMentionPart) { + if (fs instanceof MentionSurface) { + nodeChanged(arg0); + } else if (fs instanceof Mention || fs instanceof Entity) { CATreeNode tn = createNode(fs); insertNodeInto(tn, arg0, getInsertPosition(arg0, fs)); - if (fs instanceof EntityGroup) { - EntityGroup eg = (EntityGroup) fs; + if (fs instanceof Entity && UimaUtil.isGroup(fs)) { + Entity eg = (Entity) fs; for (int j = 0; j < eg.getMembers().size(); j++) try { insertNodeInto(new CATreeNode(eg.getMembers(j)), tn, 0); @@ -100,7 +108,7 @@ public void entityEvent(FeatureStructureEvent event) { optResort(); break; case Remove: - if (event.getArgument1() instanceof EntityGroup) { + if (UimaUtil.isGroup(event.getArgument1())) { CATreeNode gn = fsMap.get(event.getArgument1()); MutableList members = Lists.mutable.withAll(gn.getChildren()) .collect(n -> n.getFeatureStructure()); @@ -219,19 +227,17 @@ public CATreeNode getRoot() { } private void initialise() { - Lists.immutable.withAll(JCasUtil.select(coreferenceModel.getJCas(), Entity.class)).forEach(e -> { + for (Entity e : coreferenceModel.getEntities(EntitySorter.ADDRESS)) { entityEvent(Event.get(this, Event.Type.Add, null, e)); - }); - Annotator.logger.debug("Added all entities"); - - for (Mention m : JCasUtil.select(coreferenceModel.getJCas(), Mention.class)) { + } + MentionComparator mc = new MentionComparator(); + // this is needed for ascending sorting + mc.setDescending(true); + for (Mention m : SortedSets.immutable.withAll(mc, JCasUtil.select(coreferenceModel.getJCas(), Mention.class))) { entityEvent(Event.get(this, Event.Type.Add, m.getEntity(), m)); - if (m.getDiscontinuous() != null) - entityEvent(Event.get(this, Event.Type.Add, m, m.getDiscontinuous())); - // last modified should only represent user actions, so reset - get(m.getEntity()).resetLastModified(); } - Annotator.logger.debug("Added all mentions"); + + Annotator.logger.debug("Added all entities and mentions."); } protected boolean matches(Pattern pattern, CATreeNode e) { @@ -244,10 +250,10 @@ protected boolean matches(Pattern pattern, CATreeNode e) { if (m.find()) return true; } - StringArray flags = e.getEntity().getFlags(); + FSList flags = e.getEntity().getFlags(); if (flags != null) - for (int i = 0; i < e.getEntity().getFlags().size(); i++) { - m = pattern.matcher(e.getEntity().getFlags(i)); + for (int i = 0; i < e.getEntity().getFlags().getLength(); i++) { + m = pattern.matcher(flags.getNthElement(i).getLabel()); if (m.find()) return true; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/FlagModel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/FlagModel.java index f42fb63f..16dcbdbb 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/FlagModel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/FlagModel.java @@ -6,7 +6,7 @@ import org.apache.uima.cas.Feature; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.fit.util.JCasUtil; -import org.apache.uima.jcas.cas.StringArray; +import org.apache.uima.jcas.cas.FSList; import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.set.MutableSet; import org.eclipse.collections.impl.factory.Lists; @@ -15,20 +15,18 @@ import org.kordamp.ikonli.materialdesign.MaterialDesign; import de.unistuttgart.ims.coref.annotator.Annotator; -import de.unistuttgart.ims.coref.annotator.Constants; -import de.unistuttgart.ims.coref.annotator.Defaults; import de.unistuttgart.ims.coref.annotator.Strings; import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.Event.Type; import de.unistuttgart.ims.coref.annotator.document.op.AddFlag; import de.unistuttgart.ims.coref.annotator.document.op.DeleteFlag; import de.unistuttgart.ims.coref.annotator.document.op.FlagModelOperation; import de.unistuttgart.ims.coref.annotator.document.op.ToggleGenericFlag; import de.unistuttgart.ims.coref.annotator.document.op.UpdateFlag; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; /** *

Mapping of features to columns

@@ -64,35 +62,6 @@ public class FlagModel extends SubModel implements Model { public FlagModel(DocumentModel documentModel, Preferences preferences) { super(documentModel); - - if (preferences.getBoolean(Constants.CFG_CREATE_DEFAULT_FLAGS, Defaults.CFG_CREATE_DEFAULT_FLAGS) - && !JCasUtil.exists(documentModel.getJcas(), Flag.class)) { - initialiseDefaultFlags(); - } - } - - @Deprecated - protected void addFlag(String label, Class targetClass) { - addFlag(label, targetClass, null); - } - - @Deprecated - protected synchronized void addFlag(String label, Class targetClass, Ikon ikon) { - Flag f = new Flag(documentModel.getJcas()); - f.addToIndexes(); - f.setLabel(label); - String key = UUID.randomUUID().toString(); - while (keys.contains(key)) { - key = UUID.randomUUID().toString(); - } - f.setKey(key); - - if (ikon != null) - f.setIcon(ikon.toString()); - f.setTargetClass(targetClass.getName()); - f.addToIndexes(); - keys.add(key); - fireFlagEvent(Event.get(this, Type.Add, f)); } protected void edit(FlagModelOperation fmo) { @@ -122,7 +91,7 @@ protected void edit(AddFlag operation) { while (keys.contains(key)) { key = UUID.randomUUID().toString(); } - f.setKey(key); + f.setUuid(key); if (operation.getIcon() != null) f.setIcon(operation.getIcon().toString()); @@ -145,19 +114,12 @@ protected void edit(AddFlag operation) { protected void edit(DeleteFlag operation) { Flag flag = operation.getFlag(); - if (flag.getKey().equals(Constants.ENTITY_FLAG_GENERIC) || flag.getKey().equals(Constants.ENTITY_FLAG_HIDDEN) - || flag.getKey().equals(Constants.MENTION_FLAG_AMBIGUOUS) - || flag.getKey().equals(Constants.MENTION_FLAG_DIFFICULT) - || flag.getKey().equals(Constants.MENTION_FLAG_NON_NOMINAL)) - return; ImmutableList featureStructures = this.getFlaggedFeatureStructures(flag); operation.setFeatureStructures(featureStructures); - featureStructures.select(fs -> Util.isX(fs, flag.getKey())).forEach(fs -> { + featureStructures.select(fs -> UimaUtil.isX(fs, flag)).forEach(fs -> { Feature feature = fs.getType().getFeatureByBaseName("Flags"); - StringArray nArr = Util.removeFrom(documentModel.getJcas(), (StringArray) fs.getFeatureValue(feature), - flag.getKey()); - ((StringArray) fs.getFeatureValue(feature)).removeFromIndexes(); + FSList nArr = UimaUtil.removeFrom(UimaUtil.getFlags(fs), flag); fs.setFeatureValue(feature, nArr); }); @@ -182,12 +144,8 @@ protected void edit(UpdateFlag op) { flag.setTargetClass((String) op.getNewValue()); break; case KEY: - op.setOldValue(flag.getKey()); - getFlaggedFeatureStructures(flag).forEach(fs -> { - Util.removeFlagKey(fs, (String) op.getOldValue()); - Util.addFlagKey(fs, (String) op.getNewValue()); - }); - flag.setKey((String) op.getNewValue()); + op.setOldValue(flag.getUuid()); + flag.setUuid((String) op.getNewValue()); break; } Annotator.logger.traceEntry(); @@ -207,9 +165,6 @@ protected ImmutableList getFlaggedFeatureStructures(Flag flag) try { if (getTargetClass(flag) == Mention.class) { featureStructures = Lists.immutable.ofAll(JCasUtil.select(documentModel.getJcas(), Mention.class)); - } else if (getTargetClass(flag) == DetachedMentionPart.class) { - featureStructures = Lists.immutable - .ofAll(JCasUtil.select(documentModel.getJcas(), DetachedMentionPart.class)); } else if (getTargetClass(flag) == Entity.class) { featureStructures = Lists.immutable.ofAll(JCasUtil.select(documentModel.getJcas(), Entity.class)); } @@ -217,57 +172,7 @@ protected ImmutableList getFlaggedFeatureStructures(Flag flag) e.printStackTrace(); } - return featureStructures.select(fs -> Util.isX(fs, flag.getKey())); - } - - @Deprecated - protected void initialiseDefaultFlags() { - Flag flag; - - // ambiguous - flag = new Flag(documentModel.getJcas()); - flag.setKey(Constants.MENTION_FLAG_AMBIGUOUS); - flag.setLabel(Strings.MENTION_FLAG_AMBIGUOUS); - flag.setIcon("MDI_SHARE_VARIANT"); - flag.setTargetClass(Mention.class.getName()); - flag.addToIndexes(); - keys.add(Constants.MENTION_FLAG_AMBIGUOUS); - - // difficult - flag = new Flag(documentModel.getJcas()); - flag.setKey(Constants.MENTION_FLAG_DIFFICULT); - flag.setLabel(Strings.MENTION_FLAG_DIFFICULT); - flag.setIcon("MDI_ALERT_BOX"); - flag.setTargetClass(Mention.class.getName()); - flag.addToIndexes(); - keys.add(Constants.MENTION_FLAG_DIFFICULT); - - // non-nominal - flag = new Flag(documentModel.getJcas()); - flag.setKey(Constants.MENTION_FLAG_NON_NOMINAL); - flag.setLabel(Strings.MENTION_FLAG_NON_NOMINAL); - flag.setIcon("MDI_FLAG"); - flag.setTargetClass(Mention.class.getName()); - flag.addToIndexes(); - keys.add(Constants.MENTION_FLAG_NON_NOMINAL); - - // generic - flag = new Flag(documentModel.getJcas()); - flag.setKey(Constants.ENTITY_FLAG_GENERIC); - flag.setLabel(Strings.ACTION_FLAG_ENTITY_GENERIC); - flag.setIcon("MDI_CLOUD"); - flag.setTargetClass(Entity.class.getName()); - flag.addToIndexes(); - keys.add(Constants.ENTITY_FLAG_GENERIC); - - // hidden - flag = new Flag(documentModel.getJcas()); - flag.setKey(Constants.ENTITY_FLAG_HIDDEN); - flag.setLabel(Strings.ACTION_TOGGLE_ENTITY_VISIBILITY); - flag.setIcon("MDI_ACCOUNT_OUTLINE"); - flag.setTargetClass(Entity.class.getName()); - flag.addToIndexes(); - keys.add(Constants.ENTITY_FLAG_HIDDEN); + return featureStructures.select(fs -> UimaUtil.isX(fs, flag)); } public Class getTargetClass(Flag f) throws ClassNotFoundException { @@ -313,8 +218,7 @@ protected void undo(AddFlag fmo) { protected void undo(DeleteFlag fmo) { fmo.getFlag().addToIndexes(); - documentModel.getCoreferenceModel() - .edit(new ToggleGenericFlag(fmo.getFlag().getKey(), fmo.getFeatureStructures())); + documentModel.getCoreferenceModel().edit(new ToggleGenericFlag(fmo.getFlag(), fmo.getFeatureStructures())); fireFlagEvent(Event.get(this, Type.Add, fmo.getFlag())); documentModel.getCoreferenceModel().fireEvent(Event.get(this, Event.Type.Update, fmo.getFeatureStructures())); @@ -334,11 +238,7 @@ protected void undo(UpdateFlag op) { flag.setTargetClass((String) op.getOldValue()); break; case KEY: - getFlaggedFeatureStructures(flag).forEach(fs -> { - Util.removeFlagKey(fs, (String) op.getNewValue()); - Util.addFlagKey(fs, (String) op.getOldValue()); - }); - flag.setKey((String) op.getOldValue()); + flag.setUuid((String) op.getOldValue()); break; } updateFlag(flag); @@ -353,7 +253,7 @@ public void updateFlag(Flag flag) { public Flag getFlag(String key) { for (Flag f : getFlags()) - if (f.getKey().equals(key)) + if (f.getUuid().equals(key)) return f; return null; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/FlagTableModel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/FlagTableModel.java index a31c3cbb..f35fe0ac 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/FlagTableModel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/FlagTableModel.java @@ -11,7 +11,7 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.Strings; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; import de.unistuttgart.ims.coref.annotator.document.op.UpdateFlag; public class FlagTableModel implements TableModel, ModelAdapter, FlagModelListener { @@ -79,7 +79,7 @@ public Object getValueAt(int rowIndex, int columnIndex) { case 0: return MaterialDesign.valueOf(f.getIcon()); case 1: - return f.getKey(); + return f.getUuid(); case 2: return f.getLabel(); case 3: diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/SegmentModel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/SegmentModel.java index 9d12b2d9..3cda1788 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/SegmentModel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/SegmentModel.java @@ -20,7 +20,7 @@ import org.eclipse.collections.impl.factory.Lists; import de.unistuttgart.ims.coref.annotator.RangedHashSetValuedHashMap; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; import de.unistuttgart.ims.coref.annotator.uima.AnnotationLengthComparator; public class SegmentModel extends SubModel implements ListModel, TreeModel { @@ -44,6 +44,7 @@ protected void initializeOnce() { JCas jcas = getDocumentModel().getJcas(); rootSegment = AnnotationFactory.createAnnotation(jcas, 0, jcas.getDocumentText().length(), Segment.class); + rootSegment.setLabel("document"); tree = jcas.getAnnotationIndex(Segment.class).tree(rootSegment); for (Segment s : JCasUtil.select(jcas, Segment.class)) position2Segment.add(s); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddEntityToEntityGroup.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddEntityToEntityGroup.java index 1d398cb1..1b248b6b 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddEntityToEntityGroup.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddEntityToEntityGroup.java @@ -3,23 +3,22 @@ import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.impl.factory.Lists; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class AddEntityToEntityGroup implements CoreferenceModelOperation { - EntityGroup entityGroup; + Entity entityGroup; ImmutableList entities; - public AddEntityToEntityGroup(EntityGroup entityGroup, Iterable entities) { + public AddEntityToEntityGroup(Entity entityGroup, Iterable entities) { this.entityGroup = entityGroup; this.entities = Lists.immutable.withAll(entities); } - public EntityGroup getEntityGroup() { + public Entity getEntityGroup() { return entityGroup; } - public void setEntityGroup(EntityGroup entityGroup) { + public void setEntityGroup(Entity entityGroup) { this.entityGroup = entityGroup; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddFlag.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddFlag.java index 8faa5b18..cec3120e 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddFlag.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddFlag.java @@ -3,7 +3,7 @@ import org.apache.uima.cas.FeatureStructure; import org.kordamp.ikonli.Ikon; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; public class AddFlag implements FlagModelOperation, RedoableOperation { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddMentionsToEntity.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddMentionsToEntity.java index 71b004bf..3a077a0b 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddMentionsToEntity.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddMentionsToEntity.java @@ -4,8 +4,8 @@ import org.eclipse.collections.impl.factory.Lists; import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class AddMentionsToEntity implements CoreferenceModelOperation { Entity entity; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddMentionsToNewEntity.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddMentionsToNewEntity.java index 4da0c1c1..a299082e 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddMentionsToNewEntity.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddMentionsToNewEntity.java @@ -4,7 +4,7 @@ import org.eclipse.collections.impl.factory.Lists; import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class AddMentionsToNewEntity implements CoreferenceModelOperation { Entity entity; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddSpanToMention.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddSpanToMention.java new file mode 100644 index 00000000..68d77506 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AddSpanToMention.java @@ -0,0 +1,59 @@ +package de.unistuttgart.ims.coref.annotator.document.op; + +import de.unistuttgart.ims.coref.annotator.Span; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; + +public class AddSpanToMention implements CoreferenceModelOperation { + Mention target; + Span span; + MentionSurface mentionSurface; + + public AddSpanToMention(Mention target, Span span) { + super(); + this.target = target; + this.span = span; + } + + /** + * @return the target + */ + public Mention getTarget() { + return target; + } + + /** + * @param target the target to set + */ + public void setTarget(Mention target) { + this.target = target; + } + + /** + * @return the span + */ + public Span getSpan() { + return span; + } + + /** + * @param span the span to set + */ + public void setSpan(Span span) { + this.span = span; + } + + /** + * @return the mentionSurface + */ + public MentionSurface getMentionSurface() { + return mentionSurface; + } + + /** + * @param mentionSurface the mentionSurface to set + */ + public void setMentionSurface(MentionSurface mentionSurface) { + this.mentionSurface = mentionSurface; + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AttachPart.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AttachPart.java deleted file mode 100644 index abf6528a..00000000 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/AttachPart.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.unistuttgart.ims.coref.annotator.document.op; - -import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; - -public class AttachPart implements CoreferenceModelOperation { - Mention mention; - DetachedMentionPart part; - Span span; - - public AttachPart(Mention mention, Span span) { - this.mention = mention; - this.span = span; - } - - public Mention getMention() { - return mention; - } - - public DetachedMentionPart getPart() { - return part; - } - - public Span getSpan() { - return span; - } - - public void setMention(Mention mention) { - this.mention = mention; - } - - public void setPart(DetachedMentionPart part) { - this.part = part; - } - - public void setSpan(Span span) { - this.span = span; - } -} \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/DeleteFlag.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/DeleteFlag.java index 85af650f..564e1d70 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/DeleteFlag.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/DeleteFlag.java @@ -3,7 +3,7 @@ import org.apache.uima.cas.FeatureStructure; import org.eclipse.collections.api.list.ImmutableList; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; public class DeleteFlag implements FlagModelOperation { Flag flag; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/DuplicateMentions.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/DuplicateMentions.java index cc78e13c..ca5785ee 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/DuplicateMentions.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/DuplicateMentions.java @@ -3,7 +3,7 @@ import org.eclipse.collections.api.set.ImmutableSet; import org.eclipse.collections.impl.factory.Sets; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class DuplicateMentions implements CoreferenceModelOperation { ImmutableSet sourceMentions; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/GroupEntities.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/GroupEntities.java index bef6a7e6..a6f74d95 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/GroupEntities.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/GroupEntities.java @@ -3,12 +3,11 @@ import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.impl.factory.Lists; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class GroupEntities implements CoreferenceModelOperation { ImmutableList entities; - EntityGroup entityGroup; + Entity entityGroup; public GroupEntities(Entity... entities) { this.entities = Lists.immutable.of(entities); @@ -22,7 +21,7 @@ public ImmutableList getEntities() { return entities; } - public EntityGroup getEntityGroup() { + public Entity getEntityGroup() { return entityGroup; } @@ -30,7 +29,7 @@ public void setEntities(ImmutableList entities) { this.entities = entities; } - public void setEntityGroup(EntityGroup entityGroup) { + public void setEntityGroup(Entity entityGroup) { this.entityGroup = entityGroup; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MergeEntities.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MergeEntities.java index 1d8d18d8..5661a824 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MergeEntities.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MergeEntities.java @@ -4,8 +4,8 @@ import org.eclipse.collections.api.multimap.set.ImmutableSetMultimap; import org.eclipse.collections.impl.factory.Lists; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class MergeEntities implements CoreferenceModelOperation { ImmutableList entities; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MergeMentions.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MergeMentions.java index 09cfd8ff..bc0f363d 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MergeMentions.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MergeMentions.java @@ -8,8 +8,9 @@ import org.eclipse.collections.api.set.sorted.ImmutableSortedSet; import org.eclipse.collections.impl.factory.SortedSets; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.uima.AnnotationComparator; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.MentionComparator; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class MergeMentions implements CoreferenceModelOperation { public static final int STATE_OK = 0; @@ -22,11 +23,11 @@ public class MergeMentions implements CoreferenceModelOperation { Mention newMention; public MergeMentions(Mention... mentions) { - this.mentions = SortedSets.immutable.of(new AnnotationComparator(), mentions); + this.mentions = SortedSets.immutable.of(new MentionComparator(), mentions); } public MergeMentions(Collection mentions) { - this.mentions = SortedSets.immutable.withAll(new AnnotationComparator(), mentions); + this.mentions = SortedSets.immutable.withAll(new MentionComparator(), mentions); } public ImmutableSortedSet getMentions() { @@ -52,8 +53,8 @@ public static Function, Integer> isAppl if (!ms.allSatisfy(o -> o instanceof Mention)) return STATE_NOT_MENTIONS; - ImmutableSortedSet sms = ms.selectInstancesOf(Mention.class) - .toSortedSet(new AnnotationComparator()).toImmutable(); + ImmutableSortedSet sms = ms.selectInstancesOf(Mention.class).toSortedSet(new MentionComparator()) + .toImmutable(); Mention m1 = sms.getFirstOptional().get(); Mention m2 = sms.getLastOptional().get(); @@ -61,10 +62,10 @@ public static Function, Integer> isAppl if (m1.getEntity() != m2.getEntity()) return STATE_NOT_SAME_ENTITY; - if (m1.getEnd() == m2.getBegin()) + if (UimaUtil.getEnd(m1) == UimaUtil.getBegin(m2)) return STATE_OK; - String between = m1.getCAS().getDocumentText().substring(m1.getEnd(), m2.getBegin()); + String between = m1.getCAS().getDocumentText().substring(UimaUtil.getEnd(m1), UimaUtil.getBegin(m2)); if (!between.matches("^\\p{Space}*$")) return STATE_NOT_ADJACENT; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MoveMentionPartToMention.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MoveMentionPartToMention.java deleted file mode 100644 index 74a21672..00000000 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MoveMentionPartToMention.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.unistuttgart.ims.coref.annotator.document.op; - -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; - -public class MoveMentionPartToMention extends MoveOperation { - Mention from, to; - DetachedMentionPart part; - - public MoveMentionPartToMention(Mention target, DetachedMentionPart part) { - super(part.getMention(), target, part); - } - -} \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MoveMentionsToEntity.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MoveMentionsToEntity.java index 58b6c177..da99d147 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MoveMentionsToEntity.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/MoveMentionsToEntity.java @@ -2,8 +2,8 @@ import org.eclipse.collections.api.list.ImmutableList; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class MoveMentionsToEntity extends MoveOperation { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveDuplicateMentionsInEntities.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveDuplicateMentionsInEntities.java index 7c53da28..6f03aa4f 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveDuplicateMentionsInEntities.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveDuplicateMentionsInEntities.java @@ -4,8 +4,8 @@ import org.eclipse.collections.api.set.ImmutableSet; import org.eclipse.collections.impl.factory.Lists; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class RemoveDuplicateMentionsInEntities extends AbstractRemoveOperation implements CoreferenceModelOperation { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveEntities.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveEntities.java index c8c47b47..4adf0833 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveEntities.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveEntities.java @@ -4,11 +4,10 @@ import org.eclipse.collections.api.multimap.set.MutableSetMultimap; import org.eclipse.collections.impl.factory.Multimaps; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class RemoveEntities extends AbstractRemoveOperation implements CoreferenceModelOperation { - public MutableSetMultimap entityEntityGroupMap = Multimaps.mutable.set.empty(); + public MutableSetMultimap entityEntityGroupMap = Multimaps.mutable.set.empty(); public RemoveEntities(Entity... entities) { super(entities); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveEntitiesFromEntityGroup.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveEntitiesFromEntityGroup.java index 7500dc6b..4e5e5ebe 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveEntitiesFromEntityGroup.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveEntitiesFromEntityGroup.java @@ -3,19 +3,18 @@ import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.impl.factory.Lists; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class RemoveEntitiesFromEntityGroup implements CoreferenceModelOperation { ImmutableList entities; - EntityGroup entityGroup; + Entity entityGroup; - public RemoveEntitiesFromEntityGroup(EntityGroup entityGroup, Iterable entities) { + public RemoveEntitiesFromEntityGroup(Entity entityGroup, Iterable entities) { this.entities = Lists.immutable.withAll(entities); this.entityGroup = entityGroup; } - public RemoveEntitiesFromEntityGroup(EntityGroup entityGroup, Entity... entities) { + public RemoveEntitiesFromEntityGroup(Entity entityGroup, Entity... entities) { this.entities = Lists.immutable.of(entities); this.entityGroup = entityGroup; } @@ -28,11 +27,11 @@ public void setEntities(ImmutableList entities) { this.entities = entities; } - public EntityGroup getEntityGroup() { + public Entity getEntityGroup() { return entityGroup; } - public void setEntityGroup(EntityGroup entityGroup) { + public void setEntityGroup(Entity entityGroup) { this.entityGroup = entityGroup; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveMention.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveMention.java index 3a78a85f..1b40296a 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveMention.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveMention.java @@ -2,24 +2,24 @@ import org.eclipse.collections.api.list.ImmutableList; -import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.Spans; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class RemoveMention extends AbstractRemoveOperation implements CoreferenceModelOperation { Entity entity; - ImmutableList spans; + ImmutableList spans; boolean entityAutoDeleted = false; public RemoveMention(Mention... mention) { super(mention); - this.spans = getFeatureStructures().collect(m -> new Span(m)); + this.spans = getFeatureStructures().collect(m -> new Spans(m)); this.entity = getFeatureStructures().getFirst().getEntity(); } public RemoveMention(Iterable mention) { super(mention); - this.spans = getFeatureStructures().collect(m -> new Span(m)); + this.spans = getFeatureStructures().collect(m -> new Spans(m)); this.entity = getFeatureStructures().getFirst().getEntity(); } @@ -31,11 +31,12 @@ public Mention getMention() { return getFeatureStructures().getFirst(); } - public Span getSpan() { + @Deprecated + public Spans getSpan() { return spans.getFirst(); } - public ImmutableList getSpans() { + public ImmutableList getSpans() { return spans; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveMentionSurface.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveMentionSurface.java new file mode 100644 index 00000000..53860d01 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveMentionSurface.java @@ -0,0 +1,75 @@ +package de.unistuttgart.ims.coref.annotator.document.op; + +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.impl.factory.Lists; + +import de.unistuttgart.ims.coref.annotator.Span; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; + +public class RemoveMentionSurface implements CoreferenceModelOperation { + ImmutableList mention; + ImmutableList mentionSurface; + ImmutableList spans; + + public RemoveMentionSurface(ImmutableList mentionSurface) { + super(); + this.mentionSurface = mentionSurface; + } + + public RemoveMentionSurface(MentionSurface... mentionSurface) { + super(); + this.mentionSurface = Lists.immutable.of(mentionSurface); + } + + /** + * @return the mentionSurface + */ + public ImmutableList getMentionSurface() { + return mentionSurface; + } + + /** + * @param mentionSurface the mentionSurface to set + */ + public void setMentionSurface(ImmutableList mentionSurface) { + this.mentionSurface = mentionSurface; + } + + /** + * @return the spans + */ + public ImmutableList getSpans() { + return spans; + } + + public Span getSpan(int i) { + return spans.get(i); + } + + /** + * @param spans the spans to set + */ + public void setSpans(ImmutableList spans) { + this.spans = spans; + } + + /** + * @return the mention + */ + public ImmutableList getMention() { + return mention; + } + + public Mention getMention(int i) { + return mention.get(i); + } + + /** + * @param mention the mention to set + */ + public void setMention(ImmutableList mention) { + this.mention = mention; + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemovePart.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemovePart.java deleted file mode 100644 index e5434878..00000000 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemovePart.java +++ /dev/null @@ -1,42 +0,0 @@ -package de.unistuttgart.ims.coref.annotator.document.op; - -import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; - -public class RemovePart implements CoreferenceModelOperation { - Mention mention; - DetachedMentionPart part; - Span span; - - public RemovePart(Mention mention, DetachedMentionPart part) { - this.mention = mention; - this.part = part; - this.span = new Span(part); - } - - public Mention getMention() { - return mention; - } - - public DetachedMentionPart getPart() { - return part; - } - - public Span getSpan() { - return span; - } - - public void setMention(Mention mention) { - this.mention = mention; - } - - public void setPart(DetachedMentionPart part) { - this.part = part; - } - - public void setSpan(Span span) { - this.span = span; - } - -} \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveSingletons.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveSingletons.java index a7c1ac97..d2475e1c 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveSingletons.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RemoveSingletons.java @@ -2,8 +2,8 @@ import org.eclipse.collections.api.list.ImmutableList; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class RemoveSingletons extends AbstractRemoveOperation implements CoreferenceModelOperation { ImmutableList mentions; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RenameAllEntities.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RenameAllEntities.java index 48221bbe..a0f11f45 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RenameAllEntities.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/RenameAllEntities.java @@ -3,7 +3,7 @@ import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.impl.factory.Maps; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class RenameAllEntities implements CoreferenceModelOperation { public static enum Strategy { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/ToggleFlag.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/ToggleFlag.java index 173637e4..ac2808eb 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/ToggleFlag.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/ToggleFlag.java @@ -2,26 +2,28 @@ import org.apache.uima.cas.FeatureStructure; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; + public abstract class ToggleFlag extends UpdateOperation { - String flag; + Flag flag; @SafeVarargs - public ToggleFlag(String flag, T... objects) { + public ToggleFlag(Flag flag, T... objects) { super(objects); this.flag = flag; } - public ToggleFlag(String flag, Iterable objects) { + public ToggleFlag(Flag flag, Iterable objects) { super(objects); this.flag = flag; } - public String getFlag() { + public Flag getFlag() { return flag; } - public void setFlag(String flag) { + public void setFlag(Flag flag) { this.flag = flag; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/ToggleGenericFlag.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/ToggleGenericFlag.java index 3445ad2c..11b97a69 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/ToggleGenericFlag.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/ToggleGenericFlag.java @@ -2,9 +2,11 @@ import org.apache.uima.cas.FeatureStructure; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; + public class ToggleGenericFlag extends ToggleFlag implements CoreferenceModelOperation { - public ToggleGenericFlag(String flag, Iterable objects) { + public ToggleGenericFlag(Flag flag, Iterable objects) { super(flag, objects); } } \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityColor.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityColor.java index 2dcaaa28..6e3e2722 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityColor.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityColor.java @@ -1,6 +1,6 @@ package de.unistuttgart.ims.coref.annotator.document.op; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class UpdateEntityColor extends UpdateOperation implements CoreferenceModelOperation { int oldColor; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityKey.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityKey.java index 73cb49c6..e1eafd70 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityKey.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityKey.java @@ -1,6 +1,6 @@ package de.unistuttgart.ims.coref.annotator.document.op; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class UpdateEntityKey extends UpdateOperation implements CoreferenceModelOperation { Character oldKey = null; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityName.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityName.java index ceaeb496..23579335 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityName.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateEntityName.java @@ -1,6 +1,6 @@ package de.unistuttgart.ims.coref.annotator.document.op; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class UpdateEntityName extends UpdateOperation implements CoreferenceModelOperation { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateFlag.java b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateFlag.java index 01fd9898..aa55db1b 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateFlag.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/document/op/UpdateFlag.java @@ -1,6 +1,6 @@ package de.unistuttgart.ims.coref.annotator.document.op; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; public class UpdateFlag extends UpdateOperation implements FlagModelOperation { public enum FlagProperty { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/auto/stanford/StanfordCoref.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/auto/stanford/StanfordCoref.java index 463b6d29..5bdec487 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/auto/stanford/StanfordCoref.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/auto/stanford/StanfordCoref.java @@ -8,14 +8,14 @@ import org.apache.uima.fit.factory.AnalysisEngineFactory; import org.apache.uima.fit.factory.CollectionReaderFactory; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.text.TextReader; +import org.dkpro.core.stanfordnlp.StanfordCoreferenceResolver; +import org.dkpro.core.stanfordnlp.StanfordParser; +import org.dkpro.core.stanfordnlp.StanfordPosTagger; +import org.dkpro.core.stanfordnlp.StanfordSegmenter; -import de.tudarmstadt.ukp.dkpro.core.io.text.TextReader; -import de.tudarmstadt.ukp.dkpro.core.stanfordnlp.StanfordCoreferenceResolver; -import de.tudarmstadt.ukp.dkpro.core.stanfordnlp.StanfordParser; -import de.tudarmstadt.ukp.dkpro.core.stanfordnlp.StanfordPosTagger; -import de.tudarmstadt.ukp.dkpro.core.stanfordnlp.StanfordSegmenter; import de.unistuttgart.ims.coref.annotator.plugin.dkpro.ImportDKpro; -import de.unistuttgart.ims.uimautil.SetJCasLanguage; +import de.unistuttgart.ims.coref.annotator.uima.SetJCasLanguage; public class StanfordCoref extends de.unistuttgart.ims.coref.annotator.plugin.plaintext.Plugin { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/ConllExportPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/ConllExportPlugin.java index eb55e72f..9bf84625 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/ConllExportPlugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/ConllExportPlugin.java @@ -9,12 +9,12 @@ import org.apache.uima.fit.factory.AnalysisEngineFactory; import org.apache.uima.fit.factory.FlowControllerFactory; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.conll.Conll2012Writer; +import org.dkpro.core.tokit.BreakIteratorSegmenter; -import de.tudarmstadt.ukp.dkpro.core.io.conll.Conll2012Writer; -import de.tudarmstadt.ukp.dkpro.core.tokit.BreakIteratorSegmenter; import de.unistuttgart.ims.coref.annotator.plugins.AbstractExportPlugin; import de.unistuttgart.ims.coref.annotator.plugins.UimaExportPlugin; -import de.unistuttgart.ims.uimautil.SetDocumentId; +import de.unistuttgart.ims.coref.annotator.uima.SetDocumentId; import javafx.stage.FileChooser.ExtensionFilter; public class ConllExportPlugin extends AbstractExportPlugin implements UimaExportPlugin { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/Exporter.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/Exporter.java index 44db9c10..139869ab 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/Exporter.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/Exporter.java @@ -12,8 +12,9 @@ import org.apache.uima.jcas.JCas; import org.eclipse.collections.impl.factory.Maps; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class Exporter extends JCasAnnotator_ImplBase { @@ -34,7 +35,7 @@ public void process(JCas jcas) throws AnalysisEngineProcessException { } for (Mention m : JCasUtil.select(jcas, Mention.class)) { - AnnotationFS a = jcas.getCas().createAnnotation(linkType, m.getBegin(), m.getEnd()); + AnnotationFS a = jcas.getCas().createAnnotation(linkType, UimaUtil.getBegin(m), UimaUtil.getEnd(m)); jcas.addFsToIndexes(a); FeatureStructure prev = next.get(m.getEntity()); if (prev.getType() == chainType) { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/FlowController.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/FlowController.java index 506a0584..828c7fb2 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/FlowController.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/conll2012/FlowController.java @@ -13,7 +13,7 @@ import de.tudarmstadt.ukp.dkpro.core.api.coref.type.CoreferenceChain; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class FlowController extends JCasFlowController_ImplBase { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/csv/CSVWriter.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/csv/CSVWriter.java index 9da1dcb6..df7e0ba5 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/csv/CSVWriter.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/csv/CSVWriter.java @@ -6,7 +6,7 @@ import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.uima.UimaContext; import org.apache.uima.fit.descriptor.ConfigurationParameter; import org.apache.uima.fit.util.JCasUtil; @@ -18,17 +18,16 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.RangedHashSetValuedHashMap; -import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; -import de.unistuttgart.ims.coref.annotator.api.v1.Line; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Line; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; import de.unistuttgart.ims.coref.annotator.plugin.csv.CsvExportPlugin.ContextUnit; import de.unistuttgart.ims.coref.annotator.plugins.SingleFileWriter; -import de.unistuttgart.ims.coref.annotator.uima.AnnotationComparator; import de.unistuttgart.ims.coref.annotator.uima.AnnotationLengthComparator; +import de.unistuttgart.ims.coref.annotator.uima.MentionComparator; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class CSVWriter extends SingleFileWriter { @@ -82,8 +81,8 @@ public void configure() { @Override public void write(JCas jcas, Writer os) throws IOException { - ImmutableList allMentions = Lists.mutable.withAll(JCasUtil.select(jcas, Mention.class)) - .sortThis(new AnnotationComparator()).toImmutable(); + ImmutableList allMentions = Lists.mutable.withAll(jcas.getIndexedFSs(Mention.class)) + .sortThis(new MentionComparator()).toImmutable(); ImmutableList allFlags = Lists.immutable.withAll(JCasUtil.select(jcas, Flag.class)); ImmutableList mentionFlags = allFlags @@ -135,34 +134,32 @@ public void write(JCas jcas, Writer os) throws IOException { int entityNum = 0; for (Entity entity : entities) { for (Mention mention : allMentions.select(m -> m.getEntity() == entity)) { - String surface = mention.getCoveredText(); - if (mention.getDiscontinuous() != null) - surface += " " + mention.getDiscontinuous().getCoveredText(); + String surface = UimaUtil.getCoveredText(mention); if (optionReplaceNewlines) surface = surface.replaceAll(" ?[\n\r\f]+ ?", replacementForNewlines); - p.print(mention.getBegin()); - p.print(mention.getEnd()); + p.print(UimaUtil.getBegin(mention)); + p.print(UimaUtil.getEnd(mention)); if (optionIncludeLineNumbers) { if (segmentIndex.notEmpty()) { - Segment segment = Lists.mutable.ofAll(segmentIndex.get(mention.getBegin())) + Segment segment = Lists.mutable.ofAll(segmentIndex.get(UimaUtil.getBegin(mention))) .min(new AnnotationLengthComparator()); p.print(segment.getLabel()); - segment = Lists.mutable.ofAll(segmentIndex.get(mention.getEnd())) + segment = Lists.mutable.ofAll(segmentIndex.get(UimaUtil.getEnd(mention))) .min(new AnnotationLengthComparator()); p.print(segment.getLabel()); } try { - p.print(JCasUtil.selectPreceding(Line.class, mention, 1).get(0).getNumber()); + p.print(JCasUtil.selectPreceding(Line.class, mention.getSurface(0), 1).get(0).getNumber()); } catch (Exception e) { p.print(-1); } try { Annotation a = new Annotation(jcas); - a.setBegin(mention.getEnd()); - a.setEnd(mention.getEnd()); + a.setBegin(UimaUtil.getBegin(mention)); + a.setEnd(UimaUtil.getEnd(mention)); p.print(JCasUtil.selectPreceding(Line.class, a, 1).get(0).getNumber()); } catch (Exception e) { p.print(-1); @@ -194,12 +191,12 @@ public void write(JCas jcas, Writer os) throws IOException { } p.print(entityNum); p.print(entity.getLabel()); - p.print((entity instanceof EntityGroup)); + p.print(UimaUtil.isGroup(entity)); for (Flag flag : entityFlags) { - p.print(Util.isX(entity, flag.getKey())); + p.print(UimaUtil.isX(entity, flag)); } for (Flag flag : mentionFlags) { - p.print(Util.isX(mention, flag.getKey())); + p.print(UimaUtil.isX(mention, flag)); } p.println(); } @@ -213,33 +210,34 @@ protected String getContext(JCas jcas, Mention mention, boolean backward) { switch (optionContextUnit) { case LINE: if (backward) { - int leftEnd = Lists.immutable.withAll(JCasUtil.selectPreceding(Line.class, mention, optionContextWidth)) + int leftEnd = Lists.immutable + .withAll(JCasUtil.selectPreceding(Line.class, mention.getSurface(0), optionContextWidth)) .collect(l -> l.getBegin()).min(); if (optionTrimWhitespace) { - return text.substring(leftEnd, mention.getBegin()).trim(); + return text.substring(leftEnd, UimaUtil.getBegin(mention)).trim(); } else { - return text.substring(leftEnd, mention.getBegin()); + return text.substring(leftEnd, UimaUtil.getBegin(mention)); } } else { int rightEnd = Lists.immutable - .withAll(JCasUtil.selectFollowing(Line.class, mention, optionContextWidth)) + .withAll(JCasUtil.selectFollowing(Line.class, UimaUtil.getLast(mention), optionContextWidth)) .collect(l -> l.getEnd()).max(); if (optionTrimWhitespace) { - return text.substring(mention.getEnd(), rightEnd).trim(); + return text.substring(UimaUtil.getEnd(mention), rightEnd).trim(); } else { - return text.substring(mention.getEnd(), rightEnd); + return text.substring(UimaUtil.getEnd(mention), rightEnd); } } default: if (backward) if (optionTrimWhitespace) { - return StringUtils.right(text.substring(0, mention.getBegin()).trim(), optionContextWidth); + return StringUtils.right(text.substring(0, UimaUtil.getBegin(mention)).trim(), optionContextWidth); } else { return StringUtils.right(text, optionContextWidth); } else if (optionTrimWhitespace) { - return StringUtils.left(text.substring(mention.getEnd()).trim(), optionContextWidth); + return StringUtils.left(text.substring(UimaUtil.getEnd(mention)).trim(), optionContextWidth); } else { return StringUtils.left(text, optionContextWidth); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/csv/CsvExportPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/csv/CsvExportPlugin.java index bddf04ec..2985528c 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/csv/CsvExportPlugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/csv/CsvExportPlugin.java @@ -22,7 +22,7 @@ import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.ExtensionFilters; -import de.unistuttgart.ims.coref.annotator.api.v1.Line; +import de.unistuttgart.ims.coref.annotator.api.v2.Line; import de.unistuttgart.ims.coref.annotator.document.DocumentModel; import de.unistuttgart.ims.coref.annotator.plugins.AbstractExportPlugin; import de.unistuttgart.ims.coref.annotator.plugins.ConfigurableExportPlugin; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/dkpro/DKproPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/dkpro/DKproPlugin.java index 8df788b4..48507468 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/dkpro/DKproPlugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/dkpro/DKproPlugin.java @@ -10,8 +10,8 @@ import org.apache.uima.fit.factory.AnalysisEngineFactory; import org.apache.uima.fit.factory.CollectionReaderFactory; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.xmi.XmiReader; -import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiReader; import de.unistuttgart.ims.coref.annotator.ExtensionFilters; import de.unistuttgart.ims.coref.annotator.FileFilters; import de.unistuttgart.ims.coref.annotator.plugins.AbstractImportPlugin; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/dkpro/ImportDKpro.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/dkpro/ImportDKpro.java index 44ea1e7f..f3355c09 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/dkpro/ImportDKpro.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/dkpro/ImportDKpro.java @@ -2,15 +2,15 @@ import org.apache.uima.analysis_engine.AnalysisEngineProcessException; import org.apache.uima.fit.component.JCasAnnotator_ImplBase; -import org.apache.uima.fit.factory.AnnotationFactory; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; import de.tudarmstadt.ukp.dkpro.core.api.coref.type.CoreferenceChain; import de.tudarmstadt.ukp.dkpro.core.api.coref.type.CoreferenceLink; import de.unistuttgart.ims.coref.annotator.ColorProvider; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class ImportDKpro extends JCasAnnotator_ImplBase { @@ -25,7 +25,7 @@ public void process(JCas jcas) throws AnalysisEngineProcessException { int maxLength = 0; String maxLabel = null; while (link != null) { - Mention m = AnnotationFactory.createAnnotation(jcas, link.getBegin(), link.getEnd(), Mention.class); + Mention m = UimaUtil.createMention(jcas, link.getBegin(), link.getEnd()); m.setEntity(e); if (link.getCoveredText().length() > maxLength) { maxLabel = link.getCoveredText(); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/json/JSONWriter.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/json/JSONWriter.java index c407ea12..ef5ba5f7 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/json/JSONWriter.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/json/JSONWriter.java @@ -2,19 +2,21 @@ import java.io.IOException; import java.io.Writer; -import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.impl.factory.Lists; import org.json.JSONArray; import org.json.JSONObject; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.coref.annotator.plugins.SingleFileWriter; public class JSONWriter extends SingleFileWriter { @@ -25,14 +27,15 @@ public class JSONWriter extends SingleFileWriter { public void write(JCas jcas, Writer os) throws IOException { JSONArray array = new JSONArray(); - Map> indexed = JCasUtil.indexCovering(jcas, Token.class, Mention.class); + Map> indexed = JCasUtil.indexCovering(jcas, Token.class, MentionSurface.class); for (Token token : JCasUtil.select(jcas, Token.class)) { JSONObject o = new JSONObject(); o.put("s", token.getCoveredText()); if (indexed.containsKey(token)) { JSONArray entities = new JSONArray(); - for (Mention mention : indexed.get(token)) { + ImmutableList mss = Lists.immutable.ofAll(indexed.get(token)); + for (Mention mention : mss.collect(ms -> ms.getMention())) { entities.put(getEntityId(mention)); } o.put("e", entities); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/json/Plugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/json/Plugin.java index d3f709e4..8cb5f498 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/json/Plugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/json/Plugin.java @@ -9,8 +9,8 @@ import org.apache.uima.fit.factory.AnalysisEngineFactory; import org.apache.uima.fit.factory.FlowControllerFactory; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.tokit.BreakIteratorSegmenter; -import de.tudarmstadt.ukp.dkpro.core.tokit.BreakIteratorSegmenter; import de.unistuttgart.ims.coref.annotator.ExtensionFilters; import de.unistuttgart.ims.coref.annotator.plugins.AbstractExportPlugin; import de.unistuttgart.ims.coref.annotator.plugins.UimaExportPlugin; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/plaintext/Plugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/plaintext/Plugin.java index a28d72aa..b851e680 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/plaintext/Plugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/plaintext/Plugin.java @@ -9,8 +9,8 @@ import org.apache.uima.fit.factory.AnalysisEngineFactory; import org.apache.uima.fit.factory.CollectionReaderFactory; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.text.TextReader; -import de.tudarmstadt.ukp.dkpro.core.io.text.TextReader; import de.unistuttgart.ims.coref.annotator.ExtensionFilters; import de.unistuttgart.ims.coref.annotator.FileFilters; import de.unistuttgart.ims.coref.annotator.plugins.AbstractImportPlugin; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/proc/breakiterator/Tokenizer.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/proc/breakiterator/Tokenizer.java new file mode 100644 index 00000000..6e7c8070 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/proc/breakiterator/Tokenizer.java @@ -0,0 +1,42 @@ +package de.unistuttgart.ims.coref.annotator.plugin.proc.breakiterator; + +import org.apache.uima.analysis_engine.AnalysisEngineDescription; +import org.apache.uima.fit.factory.AggregateBuilder; +import org.apache.uima.fit.factory.AnalysisEngineFactory; +import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.tokit.BreakIteratorSegmenter; +import org.kordamp.ikonli.Ikon; + +import de.unistuttgart.ims.coref.annotator.Constants; +import de.unistuttgart.ims.coref.annotator.plugins.ProcessingPlugin; + +public class Tokenizer implements ProcessingPlugin { + + @Override + public String getDescription() { + return "A simple rule-based tokenizer"; + } + + @Override + public String getName() { + return "BreakIterator"; + } + + @Override + public Ikon getIkon() { + return null; + } + + @Override + public AnalysisEngineDescription getEngineDescription() throws ResourceInitializationException { + AggregateBuilder b = new AggregateBuilder(); + b.add(AnalysisEngineFactory.createEngineDescription(BreakIteratorSegmenter.class)); + return b.createAggregateDescription(); + } + + @Override + public String[] getSupportedLanguages() { + return Constants.SUPPORTED_LANGUAGES; + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/proc/stanford/NerPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/proc/stanford/NerPlugin.java index 9f0ab79f..e9a9b208 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/proc/stanford/NerPlugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/proc/stanford/NerPlugin.java @@ -4,10 +4,10 @@ import org.apache.uima.fit.factory.AggregateBuilder; import org.apache.uima.fit.factory.AnalysisEngineFactory; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.stanfordnlp.StanfordNamedEntityRecognizer; +import org.dkpro.core.tokit.BreakIteratorSegmenter; import org.kordamp.ikonli.Ikon; -import de.tudarmstadt.ukp.dkpro.core.stanfordnlp.StanfordNamedEntityRecognizer; -import de.tudarmstadt.ukp.dkpro.core.tokit.BreakIteratorSegmenter; import de.unistuttgart.ims.coref.annotator.plugins.ProcessingPlugin; public class NerPlugin implements ProcessingPlugin { diff --git a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/Constants.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/Constants.java similarity index 100% rename from quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/Constants.java rename to src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/Constants.java diff --git a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/QDStylePlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/QDStylePlugin.java similarity index 100% rename from quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/QDStylePlugin.java rename to src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/QDStylePlugin.java diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/MapCorefToXmlElements.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/MapCorefToXmlElements.java new file mode 100644 index 00000000..5ec3a3da --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/MapCorefToXmlElements.java @@ -0,0 +1,198 @@ +package de.unistuttgart.ims.coref.annotator.plugin.quadrama.tei; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.fit.component.JCasAnnotator_ImplBase; +import org.apache.uima.fit.factory.AnnotationFactory; +import org.apache.uima.fit.util.JCasUtil; +import org.apache.uima.jcas.JCas; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.map.MutableMap; +import org.eclipse.collections.api.set.MutableSet; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.factory.Maps; +import org.eclipse.collections.impl.factory.Sets; + +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; +import de.unistuttgart.ims.drama.api.Speaker; +import de.unistuttgart.ims.uima.io.xml.type.XMLElement; + +public class MapCorefToXmlElements extends JCasAnnotator_ImplBase { + + /** + * Pattern to extract xml ids from a string representation of the xml attributes + */ + Pattern xmlIdPattern = Pattern.compile("xml:id=\"([^\"]+)\""); + + /** + * This will be used to ensure that ids are unique within a document + */ + MutableSet ids = null; + + @Override + public void process(JCas jcas) throws AnalysisEngineProcessException { + ids = Sets.mutable.empty(); + ids.add("e"); + + // map from xml ids to elements + MutableMap idMap = Maps.mutable.empty(); + + // contains all covering XMLElement annotations for each mention + Map> coveringXMLElement = JCasUtil.indexCovering(jcas, MentionSurface.class, + XMLElement.class); + + // contains covering Speaker annotations for each mention + Map> coveringSpeaker = JCasUtil.indexCovering(jcas, MentionSurface.class, + Speaker.class); + + // the -element + XMLElement textElement = null; + XMLElement teiHeaderElement = null; + + MutableList spElements = Lists.mutable.empty(); + + for (XMLElement xmlElement : JCasUtil.select(jcas, XMLElement.class)) { + + // if the xmlElement has an xml:id attribute + Matcher m = xmlIdPattern.matcher(xmlElement.getAttributes()); + if (m.find()) { + String id = m.group(1); + + // store mapping of ids to elements + idMap.put(id, xmlElement); + } + + // identify -element + // we assume it's unique + if (xmlElement.getTag().equalsIgnoreCase("text")) + textElement = xmlElement; + + // identify -element + if (xmlElement.getTag().equalsIgnoreCase("teiHeader")) + teiHeaderElement = xmlElement; + + // scrub all who= attributes in -elements + if (xmlElement.getTag().equalsIgnoreCase("sp") && xmlElement.getAttributes().contains("who=")) { + xmlElement.setAttributes( + Pattern.compile("who=\"[^\"]*\"").matcher(xmlElement.getAttributes()).replaceFirst("")); + spElements.add(xmlElement); + } + + } + + // handle -elements separately + for (XMLElement spElement : spElements) { + + // we first collect all mentions that designate speaker tags + MutableSet speakerMentions = Sets.mutable.empty(); + for (Speaker speaker : JCasUtil.selectCovered(Speaker.class, spElement)) { + speakerMentions.addAll(Lists.mutable.withAll(JCasUtil.selectCovered(MentionSurface.class, speaker)) + .collect(ms -> ms.getMention())); + } + + // skip if doesn't contain a single element + if (speakerMentions.isEmpty()) + continue; + + // generate the new string for the who attribute + String newAttributeString = spElement.getAttributes(); + if (!(newAttributeString.isEmpty() || newAttributeString.endsWith(" "))) + newAttributeString += " "; + newAttributeString += "who=\"" + speakerMentions.collect(m -> "#" + toXmlId(m.getEntity())).makeString(" ") + + "\""; + + // add id to the xml element + spElement.setAttributes(newAttributeString); + } + + for (Mention m : JCasUtil.select(jcas, Mention.class)) { + + // we skip all mentions not in the text + if (!coveringXMLElement.get(m).contains(textElement)) + continue; + + // we skip mentions that are covered by speaker annotations + if (coveringSpeaker.containsKey(m)) + continue; + + // get entity + Entity e = m.getEntity(); + + // create xml id + String xid = toXmlId(e); + + // create new element annotation + boolean first = true; + String mentionId = UUID.randomUUID().toString(); + for (MentionSurface ms : m.getSurface()) { + XMLElement newElement = AnnotationFactory.createAnnotation(jcas, ms.getBegin(), ms.getEnd(), + XMLElement.class); + newElement.setTag("rs"); + + StringBuilder b = new StringBuilder(); + b.append(' ').append("ref=\"#").append(xid).append('"'); + if (first) { + if (m.getSurface().size() > 1) + b.append(" id=\"").append(mentionId).append('"'); + if (m.getFlags() != null && !m.getFlags().isEmpty()) + b.append(" ana=\"") + .append(StringUtils + .join(Lists.immutable.withAll(m.getFlags()).collect(f -> f.getUuid()), ",")) + .append('"'); + first = false; + } else { + b.append(' ').append("prev=\"").append(mentionId).append("\""); + } + newElement.setAttributes(b.toString()); + } + } + } + + /** + * This method takes an entity object and creates a valid XML id from the + * entity's label + * + * @param entity The entity + * @return A string containing a valid XML id + */ + String toXmlId(Entity entity) { + String id = null; + + if (entity.getXmlId() != null) { + id = entity.getXmlId(); + ids.add(id); + return id; + } else { + + String baseId; + if (entity.getLabel() != null) { + baseId = entity.getLabel().toLowerCase().replaceAll("[^a-z]", "_"); + } else { + baseId = "e"; + } + if (ids.contains(baseId)) { + int counter = (baseId == "e" ? 0 : 1); + do { + counter++; + id = baseId + String.valueOf(counter); + } while (ids.contains(id)); + ids.add(id); + entity.setXmlId(id); + return id; + } else { + ids.add(baseId); + entity.setXmlId(baseId); + return baseId; + } + } + } + +} diff --git a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/QuadramaTeiExportPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/QuadramaTeiExportPlugin.java similarity index 100% rename from quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/QuadramaTeiExportPlugin.java rename to src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/QuadramaTeiExportPlugin.java diff --git a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/QuadramaTeiImportPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/QuadramaTeiImportPlugin.java similarity index 100% rename from quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/QuadramaTeiImportPlugin.java rename to src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/QuadramaTeiImportPlugin.java diff --git a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiReader.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiReader.java similarity index 82% rename from quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiReader.java rename to src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiReader.java index 4ff2b255..9f8275ed 100644 --- a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiReader.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiReader.java @@ -8,22 +8,25 @@ import org.apache.uima.fit.descriptor.ConfigurationParameter; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.dkpro.core.api.io.ResourceCollectionReaderBase; +import org.dkpro.core.api.resources.CompressionUtils; import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.impl.factory.Maps; import org.eclipse.collections.impl.factory.Sets; import org.jsoup.nodes.Element; -import de.tudarmstadt.ukp.dkpro.core.api.io.ResourceCollectionReaderBase; import de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData; -import de.tudarmstadt.ukp.dkpro.core.api.resources.CompressionUtils; import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.ColorProvider; import de.unistuttgart.ims.coref.annotator.TypeSystemVersion; -import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIBody; +import de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIHeader; +import de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIText; import de.unistuttgart.ims.coref.annotator.plugin.quadrama.QDStylePlugin; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; import de.unistuttgart.ims.drama.api.Speaker; import de.unistuttgart.ims.uima.io.xml.GenericXmlReader; import de.unistuttgart.ims.uima.io.xml.type.XMLElement; @@ -76,7 +79,10 @@ public void getNext(CAS aCAS) { m.setEntity(cf); }); - gxr.addRule("speaker", Speaker.class); + gxr.addRule("text speaker", Speaker.class); + gxr.addRule("TEI > text", TEIText.class); + gxr.addRule("TEI > teiHeader", TEIHeader.class); + gxr.addRule("TEI > text > body", TEIBody.class); // entity references gxr.addRule("text rs[ref]", Mention.class, (m, e) -> { @@ -86,7 +92,7 @@ public void getNext(CAS aCAS) { entity = new Entity(jcas); entity.addToIndexes(); entity.setColor(colorProvider.getNextColor().getRGB()); - entity.setLabel(m.getCoveredText()); + entity.setLabel(UimaUtil.getCoveredText(m)); entity.setXmlId(id); entityMap.put(id, entity); } @@ -101,13 +107,14 @@ public void getNext(CAS aCAS) { entity = new Entity(jcas); entity.addToIndexes(); entity.setColor(colorProvider.getNextColor().getRGB()); - entity.setLabel(m.getCoveredText()); + entity.setLabel(UimaUtil.getCoveredText(m)); entity.setXmlId(id); entityMap.put(id, entity); } m.setEntity(entity); }); + // identify speaker tags gxr.addRule("text speaker", Mention.class, (m, e) -> { Element parent = e.parent(); if (parent.hasAttr("who")) { @@ -116,7 +123,7 @@ public void getNext(CAS aCAS) { if (entity == null) { entity = new Entity(jcas); entity.addToIndexes(); - entity.setLabel(m.getCoveredText()); + entity.setLabel(UimaUtil.getCoveredText(m)); entity.setColor(colorProvider.getNextColor().getRGB()); entityMap.put(id, entity); } @@ -154,8 +161,8 @@ public void getNext(CAS aCAS) { DocumentMetaData.create(jcas).setDocumentId(documentId); // set meta data - Util.getMeta(jcas).setStylePlugin(QDStylePlugin.class.getName()); - Util.getMeta(jcas).setTypeSystemVersion(TypeSystemVersion.getCurrent().toString()); + UimaUtil.getMeta(jcas).setStylePlugin(QDStylePlugin.class.getName()); + UimaUtil.getMeta(jcas).setTypeSystemVersion(TypeSystemVersion.getCurrent().toString()); // Remove und elements from XML structure (they'll be added later) for (XMLElement element : Sets.immutable.withAll(JCasUtil.select(jcas, XMLElement.class))) { diff --git a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiWriter.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiWriter.java similarity index 93% rename from quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiWriter.java rename to src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiWriter.java index c88cd1c5..5eb021c1 100644 --- a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiWriter.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TeiWriter.java @@ -9,8 +9,8 @@ import org.apache.uima.analysis_engine.AnalysisEngineProcessException; import org.apache.uima.fit.descriptor.ConfigurationParameter; import org.apache.uima.jcas.JCas; +import org.dkpro.core.api.io.JCasFileWriter_ImplBase; -import de.tudarmstadt.ukp.dkpro.core.api.io.JCasFileWriter_ImplBase; import de.unistuttgart.ims.uima.io.xml.GenericXmlWriter; public class TeiWriter extends JCasFileWriter_ImplBase { diff --git a/quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/description.txt b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/description.txt similarity index 100% rename from quadrama/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/description.txt rename to src/main/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/description.txt diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/rankings/MatchingRanker.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/rankings/MatchingRanker.java index bd406840..3620d43b 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/rankings/MatchingRanker.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/rankings/MatchingRanker.java @@ -13,10 +13,12 @@ import de.unistuttgart.ims.coref.annotator.Span; import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModel; import de.unistuttgart.ims.coref.annotator.plugins.EntityRankingPlugin; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class MatchingRanker implements EntityRankingPlugin { Pattern pattern; @@ -55,8 +57,9 @@ public int compare(Entity o1, Entity o2) { } protected boolean wasRecent(JCas jcas, Entity o1, int begin) { - for (Mention m : JCasUtil.selectPreceding(Mention.class, new Annotation(jcas, begin, begin), 20)) { - if (m.getEntity() == o1) + for (MentionSurface m : JCasUtil.selectPreceding(MentionSurface.class, new Annotation(jcas, begin, begin), + 20)) { + if (m.getMention().getEntity() == o1) return true; } return false; @@ -71,7 +74,7 @@ protected boolean matches(CoreferenceModel model, Entity e) { return true; } for (Mention child : model.get(e)) { - String mc = ((Annotation) child).getCoveredText(); + String mc = UimaUtil.getCoveredText(child); m = pattern.matcher(mc); if (m.find()) return true; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/rankings/PreceedingRanker.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/rankings/PreceedingRanker.java index 0e787f27..9ef3100a 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/rankings/PreceedingRanker.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/rankings/PreceedingRanker.java @@ -10,8 +10,8 @@ import org.kordamp.ikonli.Ikon; import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModel; import de.unistuttgart.ims.coref.annotator.plugins.EntityRankingPlugin; @@ -30,8 +30,8 @@ public String getName() { @Override public MutableSortedSet rank(Span span, CoreferenceModel cModel, JCas jcas) { return Sets.mutable - .ofAll(JCasUtil.selectPreceding(Mention.class, new Annotation(jcas, span.begin, span.end), 5)) - .collect(m -> m.getEntity()).toSortedSet(new Comparator() { + .ofAll(JCasUtil.selectPreceding(MentionSurface.class, new Annotation(jcas, span.begin, span.end), 5)) + .collect(m -> m.getMention().getEntity()).toSortedSet(new Comparator() { @Override public int compare(Entity o1, Entity o2) { return cModel.getLabel(o1).compareTo(cModel.getLabel(o2)); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/MapCorefToXmlElements.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/MapCorefToXmlElements.java index 430d5bbf..888c7bd8 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/MapCorefToXmlElements.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/MapCorefToXmlElements.java @@ -1,20 +1,24 @@ package de.unistuttgart.ims.coref.annotator.plugin.tei; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; import org.apache.uima.analysis_engine.AnalysisEngineProcessException; import org.apache.uima.fit.component.JCasAnnotator_ImplBase; import org.apache.uima.fit.factory.AnnotationFactory; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.api.set.MutableSet; import org.eclipse.collections.impl.factory.Maps; import org.eclipse.collections.impl.factory.Sets; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; import de.unistuttgart.ims.uima.io.xml.type.XMLElement; public class MapCorefToXmlElements extends JCasAnnotator_ImplBase { @@ -37,14 +41,33 @@ public void process(JCas jcas) throws AnalysisEngineProcessException { } } - // TODO: Handle who= elements for (Mention m : JCasUtil.select(jcas, Mention.class)) { Entity e = m.getEntity(); String xid = toXmlId(e); - XMLElement newElement = AnnotationFactory.createAnnotation(jcas, m.getBegin(), m.getEnd(), - XMLElement.class); - newElement.setTag("rs"); - newElement.setAttributes(" ref=\"#" + xid + "\""); + boolean first = true; + String mentionId = UUID.randomUUID().toString(); + for (MentionSurface ms : m.getSurface()) { + XMLElement newElement = AnnotationFactory.createAnnotation(jcas, ms.getBegin(), ms.getEnd(), + XMLElement.class); + newElement.setTag("rs"); + + StringBuilder b = new StringBuilder(); + b.append(' ').append("ref=\"#").append(xid).append('"'); + if (first) { + if (m.getSurface().size() > 1) + b.append(" id=\"").append(mentionId).append('"'); + if (m.getFlags() != null && !m.getFlags().isEmpty()) + b.append(" ana=\"") + .append(StringUtils + .join(Lists.immutable.withAll(m.getFlags()).collect(f -> f.getUuid()), ",")) + .append('"'); + first = false; + } else { + b.append(' ').append("prev=\"").append(mentionId).append("\""); + } + newElement.setAttributes(b.toString()); + } + } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TeiReader.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TeiReader.java index 235b2df4..7710dd83 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TeiReader.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TeiReader.java @@ -8,25 +8,30 @@ import org.apache.uima.fit.descriptor.ConfigurationParameter; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.FSArray; +import org.dkpro.core.api.io.ResourceCollectionReaderBase; +import org.dkpro.core.api.resources.CompressionUtils; import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.impl.factory.Maps; import org.eclipse.collections.impl.factory.Sets; -import de.tudarmstadt.ukp.dkpro.core.api.io.ResourceCollectionReaderBase; import de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData; -import de.tudarmstadt.ukp.dkpro.core.api.resources.CompressionUtils; import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.ColorProvider; import de.unistuttgart.ims.coref.annotator.Constants; import de.unistuttgart.ims.coref.annotator.TypeSystemVersion; -import de.unistuttgart.ims.coref.annotator.Util; import de.unistuttgart.ims.coref.annotator.api.format.Bold; import de.unistuttgart.ims.coref.annotator.api.format.Head; import de.unistuttgart.ims.coref.annotator.api.format.Italic; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Line; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Line; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIBody; +import de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIHeader; +import de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIText; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; import de.unistuttgart.ims.uima.io.xml.GenericXmlReader; import de.unistuttgart.ims.uima.io.xml.type.XMLElement; @@ -54,6 +59,7 @@ public void getNext(CAS aCAS) { } MutableMap entityMap = Maps.mutable.empty(); + MutableMap mentionMap = Maps.mutable.empty(); GenericXmlReader gxr = new GenericXmlReader(DocumentMetaData.class); gxr.setTextRootSelector(rootSelector.isEmpty() ? null : rootSelector); @@ -65,16 +71,40 @@ public void getNext(CAS aCAS) { if (jcas.getDocumentLanguage().equalsIgnoreCase(Constants.X_UNSPECIFIED)) gxr.addGlobalRule("langUsage[usage=100]", (d, e) -> jcas.setDocumentLanguage(e.attr("ident"))); - gxr.addRule("[ref]", Mention.class, (m, e) -> { - String id = e.attr("ref").substring(1); - Entity entity = entityMap.get(id); + gxr.addRule("[ref]", MentionSurface.class, (ms, e) -> { + // retrieve mention id + String mentionId = null; + if (e.hasAttr("prev")) + mentionId = e.attr("prev"); + else if (e.hasAttr("id")) + mentionId = e.attr("id"); + + // create or retrieve mention + Mention m = null; + if (mentionId != null) + m = mentionMap.get(mentionId); + if (m == null) { + m = new Mention(jcas); + m.addToIndexes(); + m.setSurface(new FSArray(jcas, 0)); + mentionMap.put(mentionId, m); + } + ms.setMention(m); + m.setSurface(UimaUtil.addTo(jcas, m.getSurface(), ms)); + + // retrieve entity id + String entityId = e.attr("ref").substring(1); + + // create or retrieve entity + Entity entity = entityMap.get(entityId); if (entity == null) { entity = new Entity(jcas); entity.addToIndexes(); entity.setColor(colorProvider.getNextColor().getRGB()); - entity.setLabel(m.getCoveredText()); - entity.setXmlId(id); - entityMap.put(id, entity); + // TODO: read old label from XML + entity.setLabel(UimaUtil.getCoveredText(m)); + entity.setXmlId(entityId); + entityMap.put(entityId, entity); } m.setEntity(entity); }); @@ -91,6 +121,10 @@ public void getNext(CAS aCAS) { gxr.addRule("l", Line.class, (line, element) -> line.setNumber(element.hasAttr("n") ? Integer.valueOf(element.attr("n")) : -1)); + gxr.addRule("TEI > text", TEIText.class); + gxr.addRule("TEI > teiHeader", TEIHeader.class); + gxr.addRule("TEI > text > body", TEIBody.class); + Resource res = nextFile(); // Read XMI file @@ -108,9 +142,9 @@ public void getNext(CAS aCAS) { if (jcas.getDocumentLanguage().equalsIgnoreCase(Constants.X_UNSPECIFIED)) jcas.setDocumentLanguage(getLanguage()); - Util.getMeta(jcas).setStylePlugin(TeiStylePlugin.class.getName()); - Util.getMeta(jcas).setTypeSystemVersion(TypeSystemVersion.getCurrent().toString()); - // TODO: Remove elements + UimaUtil.getMeta(jcas).setStylePlugin(TeiStylePlugin.class.getName()); + UimaUtil.getMeta(jcas).setTypeSystemVersion(TypeSystemVersion.getCurrent().toString()); + for (XMLElement element : Sets.immutable.withAll(JCasUtil.select(jcas, XMLElement.class))) { if (element.getTag().equalsIgnoreCase("rs")) element.removeFromIndexes(); diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TeiWriter.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TeiWriter.java index 0aba6507..c75dca11 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TeiWriter.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TeiWriter.java @@ -9,8 +9,8 @@ import org.apache.uima.analysis_engine.AnalysisEngineProcessException; import org.apache.uima.fit.descriptor.ConfigurationParameter; import org.apache.uima.jcas.JCas; +import org.dkpro.core.api.io.JCasFileWriter_ImplBase; -import de.tudarmstadt.ukp.dkpro.core.api.io.JCasFileWriter_ImplBase; import de.unistuttgart.ims.uima.io.xml.GenericXmlWriter; public class TeiWriter extends JCasFileWriter_ImplBase { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/legacy/LEGACY_To_V1_0.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/legacy/LEGACY_To_V1_0.java index cebbfbe7..86bd5920 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/legacy/LEGACY_To_V1_0.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/legacy/LEGACY_To_V1_0.java @@ -13,13 +13,13 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.TypeSystemVersion; -import de.unistuttgart.ims.coref.annotator.Util; import de.unistuttgart.ims.coref.annotator.api.Meta; import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; import de.unistuttgart.ims.coref.annotator.api.v1.Entity; import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; import de.unistuttgart.ims.coref.annotator.api.v1.Mention; import de.unistuttgart.ims.coref.annotator.uima.TypeSystemVersionConverter; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; @TypeCapability(inputs = { "de.unistuttgart.ims.coref.annotator.api.Entity", "de.unistuttgart.ims.coref.annotator.api.EntityGroup", "de.unistuttgart.ims.coref.annotator.api.Mention", @@ -53,7 +53,7 @@ public void process(JCas jcas) throws AnalysisEngineProcessException { fs.removeFromIndexes(); } - Meta meta = Util.getMeta(jcas); + Meta meta = UimaUtil.getMeta(jcas); meta.setTypeSystemVersion(TypeSystemVersion.v1.name()); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/legacy/Plugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/legacy/Plugin.java index 7e69fdcd..1d76ad6d 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/legacy/Plugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/legacy/Plugin.java @@ -10,8 +10,8 @@ import org.apache.uima.fit.factory.AnalysisEngineFactory; import org.apache.uima.fit.factory.CollectionReaderFactory; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.xmi.XmiReader; -import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiReader; import de.unistuttgart.ims.coref.annotator.ExtensionFilters; import de.unistuttgart.ims.coref.annotator.FileFilters; import de.unistuttgart.ims.coref.annotator.plugins.AbstractImportPlugin; diff --git a/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Plugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/v1/Plugin.java similarity index 73% rename from creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Plugin.java rename to src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/v1/Plugin.java index ef826aa4..859129f5 100644 --- a/creta/main/java/de/unistuttgart/ims/coref/annotator/plugin/creta/adorno/Plugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/v1/Plugin.java @@ -1,64 +1,61 @@ -package de.unistuttgart.ims.coref.annotator.plugin.creta.adorno; - -import java.io.File; - -import javax.swing.filechooser.FileFilter; - -import org.apache.uima.analysis_engine.AnalysisEngineDescription; -import org.apache.uima.collection.CollectionReaderDescription; -import org.apache.uima.fit.factory.AnalysisEngineFactory; -import org.apache.uima.fit.factory.CollectionReaderFactory; -import org.apache.uima.resource.ResourceInitializationException; - -import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiReader; -import de.unistuttgart.ims.coref.annotator.ExtensionFilters; -import de.unistuttgart.ims.coref.annotator.FileFilters; -import de.unistuttgart.ims.coref.annotator.plugins.AbstractImportPlugin; -import de.unistuttgart.ims.coref.annotator.plugins.StylePlugin; -import de.unistuttgart.ims.coref.annotator.plugins.UimaImportPlugin; -import javafx.stage.FileChooser.ExtensionFilter; - -public class Plugin extends AbstractImportPlugin implements UimaImportPlugin { - - @Override - public String getDescription() { - return "Importer for Adorno annotations done in CRETAnno"; - } - - @Override - public String getName() { - return "CRETA/Adorno"; - } - - @Override - public AnalysisEngineDescription getImporter() throws ResourceInitializationException { - return AnalysisEngineFactory.createEngineDescription(Importer.class); - } - - @Override - public Class getStylePlugin() { - return null; - } - - @Override - public CollectionReaderDescription getReader(File f) throws ResourceInitializationException { - return CollectionReaderFactory.createReaderDescription(XmiReader.class, XmiReader.PARAM_LENIENT, true, - XmiReader.PARAM_ADD_DOCUMENT_METADATA, false, XmiReader.PARAM_SOURCE_LOCATION, f.getAbsolutePath()); - } - - @Override - public FileFilter getFileFilter() { - return FileFilters.xmi; - } - - @Override - public ExtensionFilter getExtensionFilter() { - return ExtensionFilters.xmi; - } - - @Override - public String getSuffix() { - return ".xmi"; - } - -} +package de.unistuttgart.ims.coref.annotator.plugin.versions.v1; + +import java.io.File; + +import javax.swing.filechooser.FileFilter; + +import org.apache.uima.analysis_engine.AnalysisEngineDescription; +import org.apache.uima.collection.CollectionReaderDescription; +import org.apache.uima.fit.factory.AggregateBuilder; +import org.apache.uima.fit.factory.AnalysisEngineFactory; +import org.apache.uima.fit.factory.CollectionReaderFactory; +import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.xmi.XmiReader; + +import de.unistuttgart.ims.coref.annotator.ExtensionFilters; +import de.unistuttgart.ims.coref.annotator.FileFilters; +import de.unistuttgart.ims.coref.annotator.plugins.AbstractImportPlugin; +import de.unistuttgart.ims.coref.annotator.plugins.UimaImportPlugin; +import javafx.stage.FileChooser.ExtensionFilter; + +public class Plugin extends AbstractImportPlugin implements UimaImportPlugin { + + @Override + public String getDescription() { + return "Import v1 files and convert them to file format v2"; + } + + @Override + public String getName() { + return "Convert: v1 → v2"; + } + + @Override + public AnalysisEngineDescription getImporter() throws ResourceInitializationException { + AggregateBuilder b = new AggregateBuilder(); + b.add(AnalysisEngineFactory.createEngineDescription(V1_To_V2.class)); + return b.createAggregateDescription(); + } + + @Override + public FileFilter getFileFilter() { + return FileFilters.xmi_gz; + } + + @Override + public ExtensionFilter getExtensionFilter() { + return ExtensionFilters.xmi_gz; + } + + @Override + public String getSuffix() { + return ".xmi"; + } + + @Override + public CollectionReaderDescription getReader(File f) throws ResourceInitializationException { + return CollectionReaderFactory.createReaderDescription(XmiReader.class, XmiReader.PARAM_LENIENT, true, + XmiReader.PARAM_ADD_DOCUMENT_METADATA, false, XmiReader.PARAM_SOURCE_LOCATION, f.getAbsolutePath()); + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/v1/V1_To_V2.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/v1/V1_To_V2.java new file mode 100644 index 00000000..7f0a6885 --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/versions/v1/V1_To_V2.java @@ -0,0 +1,185 @@ +package de.unistuttgart.ims.coref.annotator.plugin.versions.v1; + +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.fit.descriptor.TypeCapability; +import org.apache.uima.fit.factory.AnnotationFactory; +import org.apache.uima.fit.util.JCasUtil; +import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.EmptyFSList; +import org.apache.uima.jcas.cas.FSArray; +import org.apache.uima.jcas.cas.TOP; +import org.eclipse.collections.api.map.MutableMap; +import org.eclipse.collections.api.set.MutableSet; +import org.eclipse.collections.impl.factory.Maps; +import org.eclipse.collections.impl.factory.Sets; + +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.TypeSystemVersion; +import de.unistuttgart.ims.coref.annotator.api.Meta; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Line; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; +import de.unistuttgart.ims.coref.annotator.uima.TypeSystemVersionConverter; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; + +@TypeCapability(inputs = { "de.unistuttgart.ims.coref.annotator.api.v1.Entity", + "de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup", "de.unistuttgart.ims.coref.annotator.api.v1.Mention", + "de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart" }, outputs = { + "de.unistuttgart.ims.coref.annotator.api.v2.Entity", + "de.unistuttgart.ims.coref.annotator.api.v2.EntityGroup", + "de.unistuttgart.ims.coref.annotator.api.v2.Mention", + "de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface", + "de.unistuttgart.ims.coref.annotator.api.v2.DetachedMentionPart" }) +public class V1_To_V2 extends TypeSystemVersionConverter { + MutableMap entityMap = Maps.mutable.empty(); + MutableMap mentionMap = Maps.mutable.empty(); + MutableMap flagMap = Maps.mutable.empty(); + MutableMap flagKeyMap = Maps.mutable.empty(); + MutableSet toRemove = Sets.mutable.empty(); + + @Override + public void process(JCas jcas) throws AnalysisEngineProcessException { + Annotator.logger.info("Converting type system from v1 to v2"); + + for (de.unistuttgart.ims.coref.annotator.api.v1.Flag oldFlag : JCasUtil.select(jcas, + de.unistuttgart.ims.coref.annotator.api.v1.Flag.class)) { + getFlag(jcas, oldFlag); + } + + // map entities and entity groups + for (de.unistuttgart.ims.coref.annotator.api.v1.Entity oldEntity : JCasUtil.select(jcas, + de.unistuttgart.ims.coref.annotator.api.v1.Entity.class)) { + getEntity(jcas, oldEntity); + } + + // map mentions and mention parts + for (de.unistuttgart.ims.coref.annotator.api.v1.Mention oldMention : JCasUtil.select(jcas, + de.unistuttgart.ims.coref.annotator.api.v1.Mention.class)) { + getMention(jcas, oldMention); + } + + for (de.unistuttgart.ims.coref.annotator.api.v1.Segment oldSegment : JCasUtil.select(jcas, + de.unistuttgart.ims.coref.annotator.api.v1.Segment.class)) { + getSegment(jcas, oldSegment); + } + + for (de.unistuttgart.ims.coref.annotator.api.v1.Line oldLine : JCasUtil.select(jcas, + de.unistuttgart.ims.coref.annotator.api.v1.Line.class)) { + getLine(jcas, oldLine); + } + + for (TOP fs : toRemove) { + fs.removeFromIndexes(); + } + + Meta meta = UimaUtil.getMeta(jcas); + meta.setTypeSystemVersion(TypeSystemVersion.v2.name()); + } + + Line getLine(JCas jcas, de.unistuttgart.ims.coref.annotator.api.v1.Line oldLine) { + Line line = AnnotationFactory.createAnnotation(jcas, oldLine.getBegin(), oldLine.getEnd(), Line.class); + line.setNumber(oldLine.getNumber()); + return line; + } + + Segment getSegment(JCas jcas, de.unistuttgart.ims.coref.annotator.api.v1.Segment oldSegment) { + Segment segment = AnnotationFactory.createAnnotation(jcas, oldSegment.getBegin(), oldSegment.getEnd(), + Segment.class); + segment.setLabel(oldSegment.getLabel()); + return segment; + + } + + Flag getFlag(JCas jcas, de.unistuttgart.ims.coref.annotator.api.v1.Flag oldFlag) { + Flag newFlag = new Flag(jcas); + newFlag.setIcon(oldFlag.getIcon()); + newFlag.setUuid(oldFlag.getKey()); + newFlag.setLabel(oldFlag.getLabel()); + newFlag.setTargetClass(oldFlag.getTargetClass().replace(".v1.", ".v2.")); + newFlag.addToIndexes(); + flagMap.put(oldFlag, newFlag); + flagKeyMap.put(oldFlag.getKey(), newFlag); + return newFlag; + } + + protected Mention getMention(JCas jcas, de.unistuttgart.ims.coref.annotator.api.v1.Mention oldMention) { + if (!mentionMap.containsKey(oldMention)) { + Mention mention = UimaUtil.createMention(jcas, oldMention.getBegin(), oldMention.getEnd()); + mention.addToIndexes(); + mention.setEntity(getEntity(jcas, oldMention.getEntity())); + + // this is a bit hacky, but for some reason a mention doesn't have an entity in + // an old file + // Disabled + if (false && mention.getEntity() == null) { + Entity newEntity = new Entity(jcas); + newEntity.addToIndexes(); + newEntity.setLabel(UimaUtil.getCoveredText(mention)); + mention.setEntity(newEntity); + } + mention.setFlags(new EmptyFSList(jcas)); + if (oldMention.getFlags() != null) + for (String flagKey : oldMention.getFlags()) { + mention.setFlags(mention.getFlags().push(flagKeyMap.get(flagKey))); + } + if (oldMention.getDiscontinuous() != null) { + MentionSurface ms = AnnotationFactory.createAnnotation(jcas, oldMention.getDiscontinuous().getBegin(), + oldMention.getDiscontinuous().getEnd(), MentionSurface.class); + ms.setMention(mention); + UimaUtil.addMentionSurface(mention, ms); + + de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart oldDmp = oldMention.getDiscontinuous(); + toRemove.add(oldDmp); + } + mentionMap.put(oldMention, mention); + toRemove.add(oldMention); + } + return mentionMap.get(oldMention); + } + + protected Entity getEntity(JCas jcas, de.unistuttgart.ims.coref.annotator.api.v1.Entity oldEntity) { + if (oldEntity == null) + return null; + if (!entityMap.containsKey(oldEntity)) { + Entity newEntity = new Entity(jcas); + if (oldEntity instanceof de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup) { + de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup oldEntityGroup = (de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup) oldEntity; + newEntity.setMembers(new FSArray(jcas, oldEntityGroup.getMembers().size())); + newEntity.getMembers().addToIndexes(); + for (int i = 0; i < newEntity.getMembers().size(); i++) { + newEntity.setMembers(i, getEntity(jcas, oldEntityGroup.getMembers(i))); + } + } + newEntity.addToIndexes(); + if (oldEntity.getLabel() != null) + newEntity.setLabel(oldEntity.getLabel()); + newEntity.setFlags(new EmptyFSList(jcas)); + if (oldEntity.getFlags() != null) + for (String flagKey : oldEntity.getFlags()) { + newEntity.setFlags(newEntity.getFlags().push(flagKeyMap.get(flagKey))); + } + newEntity.setColor(oldEntity.getColor()); + newEntity.setKey(oldEntity.getKey()); + newEntity.setXmlId(oldEntity.getXmlId()); + newEntity.setHidden(oldEntity.getHidden()); + + entityMap.put(oldEntity, newEntity); + toRemove.add(oldEntity); + } + return entityMap.get(oldEntity); + } + + @Override + public TypeSystemVersion getSource() { + return TypeSystemVersion.v1; + } + + @Override + public TypeSystemVersion getTarget() { + return TypeSystemVersion.v2; + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/xlsx/Plugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/xlsx/Plugin.java index a67e4ec7..698da0e5 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/xlsx/Plugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/xlsx/Plugin.java @@ -143,7 +143,9 @@ public Component getListCellRendererComponent(JList list, Object value, int i Defaults.CFG_OPTION_AUTO_OPEN, Strings.DIALOG_EXPORT_OPTIONS_AUTO_OPEN, Strings.DIALOG_EXPORT_OPTIONS_AUTO_OPEN_TOOLTIP)); - new PluginConfigurationDialog(parent, this, callback, options).setVisible(true); + PluginConfigurationDialog pcd = new PluginConfigurationDialog(parent, this, callback, options); + pcd.setDescription(Annotator.getString(Strings.DIALOG_EXPORT_OPTIONS_WARNING_1)); + pcd.setVisible(true); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/xlsx/XLSXWriter.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/xlsx/XLSXWriter.java index 9e4e8410..859f6330 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/xlsx/XLSXWriter.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugin/xlsx/XLSXWriter.java @@ -5,7 +5,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; @@ -25,17 +25,16 @@ import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.RangedHashSetValuedHashMap; -import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; -import de.unistuttgart.ims.coref.annotator.api.v1.Line; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Line; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; import de.unistuttgart.ims.coref.annotator.plugin.csv.CsvExportPlugin.ContextUnit; import de.unistuttgart.ims.coref.annotator.plugins.SingleFileStream; -import de.unistuttgart.ims.coref.annotator.uima.AnnotationComparator; import de.unistuttgart.ims.coref.annotator.uima.AnnotationLengthComparator; +import de.unistuttgart.ims.coref.annotator.uima.MentionComparator; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class XLSXWriter extends SingleFileStream { @@ -94,7 +93,7 @@ public void configure() { public void write(JCas jcas, OutputStream os) throws IOException { ImmutableList allMentions = Lists.mutable.withAll(JCasUtil.select(jcas, Mention.class)) - .sortThis(new AnnotationComparator()).toImmutable(); + .sortThis(new MentionComparator()).toImmutable(); ImmutableList allFlags = Lists.immutable.withAll(JCasUtil.select(jcas, Flag.class)); ImmutableList mentionFlags = allFlags @@ -141,38 +140,39 @@ public void write(JCas jcas, OutputStream os) throws IOException { for (Mention mention : allMentions.select(m -> m.getEntity() == entity)) { row = sheet.createRow(rowNum++); cellNum = 0; - String surface = mention.getCoveredText(); - if (mention.getDiscontinuous() != null) - surface += " " + mention.getDiscontinuous().getCoveredText(); + String surface = UimaUtil.getCoveredText(mention); if (optionReplaceNewlines) surface = surface.replaceAll(" ?[\n\r\f]+ ?", replacementForNewlines); - row.createCell(cellNum++).setCellValue(mention.getBegin()); - row.createCell(cellNum++).setCellValue(mention.getEnd()); + row.createCell(cellNum++).setCellValue(UimaUtil.getBegin(mention)); + row.createCell(cellNum++).setCellValue(UimaUtil.getEnd(mention)); if (optionIncludeLineNumbers) { if (segmentIndex.notEmpty()) { - Segment segment = Lists.mutable.ofAll(segmentIndex.get(mention.getBegin())) + Segment segment = Lists.mutable.ofAll(segmentIndex.get(UimaUtil.getBegin(mention))) .min(new AnnotationLengthComparator()); row.createCell(cellNum++).setCellValue(segment.getLabel()); - segment = Lists.mutable.ofAll(segmentIndex.get(mention.getEnd())) + segment = Lists.mutable.ofAll(segmentIndex.get(UimaUtil.getEnd(mention))) .min(new AnnotationLengthComparator()); row.createCell(cellNum++).setCellValue(segment.getLabel()); } + + int lineNumberBegin = -1, lineNumberEnd = -1; try { - row.createCell(cellNum++) - .setCellValue(JCasUtil.selectPreceding(Line.class, mention, 1).get(0).getNumber()); + lineNumberBegin = JCasUtil.selectPreceding(Line.class, mention.getSurface(0), 1).get(0) + .getNumber(); } catch (Exception e) { - row.createCell(cellNum++).setCellValue(-1); + // catch silently } + row.createCell(cellNum++).setCellValue(lineNumberBegin); try { Annotation a = new Annotation(jcas); - a.setBegin(mention.getEnd()); - a.setEnd(mention.getEnd()); + a.setBegin(UimaUtil.getEnd(mention)); + a.setEnd(UimaUtil.getEnd(mention)); - row.createCell(cellNum++) - .setCellValue(JCasUtil.selectPreceding(Line.class, a, 1).get(0).getNumber()); + lineNumberEnd = JCasUtil.selectFollowing(Line.class, a, 1).get(0).getNumber(); } catch (Exception e) { - row.createCell(cellNum++).setCellValue(-1); + // catch silently } + row.createCell(cellNum++).setCellValue(lineNumberEnd); } if (optionContextWidth > 0) { try { @@ -203,12 +203,12 @@ public void write(JCas jcas, OutputStream os) throws IOException { } row.createCell(cellNum++).setCellValue(entityNum); row.createCell(cellNum++).setCellValue(entity.getLabel()); - row.createCell(cellNum++).setCellValue((entity instanceof EntityGroup)); + row.createCell(cellNum++).setCellValue(UimaUtil.isGroup(entity)); for (Flag flag : entityFlags) { - row.createCell(cellNum++).setCellValue(Util.isX(entity, flag.getKey())); + row.createCell(cellNum++).setCellValue(UimaUtil.isX(entity, flag)); } for (Flag flag : mentionFlags) { - row.createCell(cellNum++).setCellValue(Util.isX(mention, flag.getKey())); + row.createCell(cellNum++).setCellValue(UimaUtil.isX(mention, flag)); } } entityNum++; @@ -273,32 +273,33 @@ protected String getContext(JCas jcas, Mention mention, boolean backward) { switch (optionContextUnit) { case LINE: if (backward) { - int leftEnd = Lists.immutable.withAll(JCasUtil.selectPreceding(Line.class, mention, optionContextWidth)) + int leftEnd = Lists.immutable + .withAll(JCasUtil.selectPreceding(Line.class, mention.getSurface(0), optionContextWidth)) .collect(l -> l.getBegin()).min(); if (optionTrimWhitespace) { - return text.substring(leftEnd, mention.getBegin()).trim(); + return text.substring(leftEnd, UimaUtil.getBegin(mention)).trim(); } else { - return text.substring(leftEnd, mention.getBegin()); + return text.substring(leftEnd, UimaUtil.getBegin(mention)); } } else { int rightEnd = Lists.immutable - .withAll(JCasUtil.selectFollowing(Line.class, mention, optionContextWidth)) + .withAll(JCasUtil.selectFollowing(Line.class, UimaUtil.getLast(mention), optionContextWidth)) .collect(l -> l.getEnd()).max(); if (optionTrimWhitespace) { - return text.substring(mention.getEnd(), rightEnd).trim(); + return text.substring(UimaUtil.getEnd(mention), rightEnd).trim(); } else { - return text.substring(mention.getEnd(), rightEnd); + return text.substring(UimaUtil.getEnd(mention), rightEnd); } } default: if (backward) if (optionTrimWhitespace) { - return StringUtils.right(text.substring(0, mention.getBegin()).trim(), optionContextWidth); + return StringUtils.right(text.substring(0, UimaUtil.getBegin(mention)).trim(), optionContextWidth); } else { return StringUtils.right(text, optionContextWidth); } else if (optionTrimWhitespace) { - return StringUtils.left(text.substring(mention.getEnd()).trim(), optionContextWidth); + return StringUtils.left(text.substring(UimaUtil.getEnd(mention)).trim(), optionContextWidth); } else { return StringUtils.left(text, optionContextWidth); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/CheckLoadability.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/CheckLoadability.java index 00f13000..10eb6ea8 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/CheckLoadability.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/CheckLoadability.java @@ -6,8 +6,8 @@ import org.apache.uima.jcas.JCas; import de.unistuttgart.ims.coref.annotator.TypeSystemVersion; -import de.unistuttgart.ims.coref.annotator.Util; import de.unistuttgart.ims.coref.annotator.api.Meta; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class CheckLoadability extends JCasAnnotator_ImplBase { @@ -15,7 +15,7 @@ public class CheckLoadability extends JCasAnnotator_ImplBase { public void process(JCas aJCas) throws AnalysisEngineProcessException { TypeSystemVersion is = TypeSystemVersion.LEGACY; if (JCasUtil.exists(aJCas, Meta.class)) { - Meta m = Util.getMeta(aJCas); + Meta m = UimaUtil.getMeta(aJCas); if (m.getTypeSystemVersion() != null) { is = TypeSystemVersion.valueOf(m.getTypeSystemVersion()); if (is == TypeSystemVersion.getCurrent()) diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/ConvertFlowController.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/ConvertFlowController.java index 3884b387..d8b3bcb7 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/ConvertFlowController.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/ConvertFlowController.java @@ -10,8 +10,8 @@ import org.apache.uima.jcas.JCas; import de.unistuttgart.ims.coref.annotator.TypeSystemVersion; -import de.unistuttgart.ims.coref.annotator.Util; import de.unistuttgart.ims.coref.annotator.api.Meta; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class ConvertFlowController extends JCasFlowController_ImplBase { @@ -20,7 +20,7 @@ public Flow computeFlow(JCas jcas) throws AnalysisEngineProcessException { return new JCasFlow_ImplBase() { @Override public Step next() throws AnalysisEngineProcessException { - Meta metaData = Util.getMeta(jcas); + Meta metaData = UimaUtil.getMeta(jcas); if (metaData.getTypeSystemVersion() == null) { return new SimpleStep(TypeSystemVersion.v1.name()); } else { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/DefaultExportPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/DefaultExportPlugin.java index 8f1776ba..8b90b377 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/DefaultExportPlugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/DefaultExportPlugin.java @@ -18,16 +18,17 @@ import org.apache.uima.fit.factory.JCasFactory; import org.apache.uima.jcas.JCas; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.xmi.XmiWriter; import org.kordamp.ikonli.Ikon; import org.kordamp.ikonli.materialdesign.MaterialDesign; import org.xml.sax.SAXException; -import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiWriter; import de.unistuttgart.ims.coref.annotator.ExtensionFilters; import de.unistuttgart.ims.coref.annotator.FileFilters; -import de.unistuttgart.ims.uimautil.SetDocumentId; +import de.unistuttgart.ims.coref.annotator.uima.SetDocumentId; import javafx.stage.FileChooser.ExtensionFilter; +@Deprecated public final class DefaultExportPlugin extends AbstractExportPlugin implements DirectFileIOPlugin, UimaExportPlugin { File lastFile; @@ -49,7 +50,7 @@ public AnalysisEngineDescription getExporter() throws ResourceInitializationExce @Override public FileFilter getFileFilter() { - return FileFilters.xmi_gz; + return FileFilters.ca2; } @Override @@ -61,11 +62,8 @@ public String[] getSupportedLanguages() { public JCas getJCas(File f) throws IOException, UIMAException { InputStream is = null; try { - if (f.getName().endsWith(".xmi")) { - is = new FileInputStream(f); - } else if (f.getName().endsWith(".xmi.gz")) { - is = new GZIPInputStream(new FileInputStream(f)); - } + + is = new GZIPInputStream(new FileInputStream(f)); JCas jcas = JCasFactory.createJCas(); XmiCasDeserializer.deserialize(is, jcas.getCas()); @@ -80,7 +78,7 @@ public JCas getJCas(File f) throws IOException, UIMAException { @Override public ExtensionFilter getExtensionFilter() { - return ExtensionFilters.xmi_gz; + return ExtensionFilters.ca2; } @Override @@ -95,7 +93,7 @@ public Consumer getPostExportAction() { @Override public String getSuffix() { - return ".xmi"; + return ".ca2z"; } @Override diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/DefaultImportPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/DefaultImportPlugin.java index 7fbd9d32..63eb9f37 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/DefaultImportPlugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/DefaultImportPlugin.java @@ -18,11 +18,11 @@ import org.apache.uima.fit.factory.JCasFactory; import org.apache.uima.jcas.JCas; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.xmi.XmiReader; import org.kordamp.ikonli.Ikon; import org.kordamp.ikonli.materialdesign.MaterialDesign; import org.xml.sax.SAXException; -import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiReader; import de.unistuttgart.ims.coref.annotator.ExtensionFilters; import de.unistuttgart.ims.coref.annotator.FileFilters; import javafx.stage.FileChooser.ExtensionFilter; @@ -62,7 +62,7 @@ public Class getStylePlugin() { @Override public FileFilter getFileFilter() { - return FileFilters.xmi_gz; + return FileFilters.ca2; } @Override @@ -74,10 +74,10 @@ public String[] getSupportedLanguages() { public JCas getJCas(File f) throws IOException, UIMAException { InputStream is = null; try { - if (f.getName().endsWith(".xmi")) { - is = new FileInputStream(f); - } else if (f.getName().endsWith(".xmi.gz")) { + if (f.getName().endsWith(getSuffix())) { is = new GZIPInputStream(new FileInputStream(f)); + } else if (f.getName().endsWith(".ca2")) { + is = new FileInputStream(f); } JCas jcas = JCasFactory.createJCas(); @@ -93,7 +93,7 @@ public JCas getJCas(File f) throws IOException, UIMAException { @Override public ExtensionFilter getExtensionFilter() { - return ExtensionFilters.xmi_gz; + return ExtensionFilters.ca2; } @Override @@ -103,7 +103,7 @@ public Ikon getIkon() { @Override public String getSuffix() { - return ".xmi"; + return ".ca2z"; } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/EntityRankingPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/EntityRankingPlugin.java index 0d08d6c3..65dee371 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/EntityRankingPlugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/EntityRankingPlugin.java @@ -4,7 +4,7 @@ import org.eclipse.collections.api.set.sorted.MutableSortedSet; import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModel; public interface EntityRankingPlugin extends Plugin { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/PluginConfigurationDialog.java b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/PluginConfigurationDialog.java index cad86d3a..ec4a1322 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/PluginConfigurationDialog.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/plugins/PluginConfigurationDialog.java @@ -1,7 +1,8 @@ package de.unistuttgart.ims.coref.annotator.plugins; import java.awt.BorderLayout; -import java.awt.GridLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import java.awt.Window; import java.awt.event.ActionEvent; import java.util.function.Consumer; @@ -11,6 +12,7 @@ import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; +import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; @@ -21,16 +23,26 @@ public class PluginConfigurationDialog extends JDialog { private static final long serialVersionUID = 1L; + JPanel optionPanel; + GridBagConstraints optionPanelConstraints; public PluginConfigurationDialog(Window parent, ConfigurableExportPlugin plugin, Consumer callback, Iterable options) { super(parent, Annotator.getString(Strings.DIALOG_EXPORT_OPTIONS_TITLE_, plugin.getName())); - JPanel optionPanel = new JPanel(new GridLayout(0, 2)); + optionPanel = new JPanel(new GridBagLayout()); + optionPanelConstraints = new GridBagConstraints(); + optionPanelConstraints.anchor = GridBagConstraints.WEST; + optionPanelConstraints.gridy = 0; for (PluginOption option : options) { - optionPanel.add(option.getLabel()); - optionPanel.add(option.getComponent()); + optionPanelConstraints.gridx = 0; + optionPanelConstraints.weightx = 2; + optionPanel.add(option.getLabel(), optionPanelConstraints); + optionPanelConstraints.gridx = 1; + optionPanelConstraints.weightx = 1; + optionPanel.add(option.getComponent(), optionPanelConstraints); + optionPanelConstraints.gridy++; } optionPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20)); @@ -82,4 +94,14 @@ public void actionPerformed(ActionEvent e) { SwingUtilities.getRootPane(okButton).setDefaultButton(okButton); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); } + + public void setDescription(String string) { + optionPanelConstraints.ipady = 10; + optionPanelConstraints.gridx = 0; + optionPanelConstraints.gridwidth = 2; + optionPanel.add(new JLabel(string), optionPanelConstraints); + + pack(); + validate(); + } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/stats/DocumentStatistics.java b/src/main/java/de/unistuttgart/ims/coref/annotator/stats/DocumentStatistics.java index c9a56ff2..efcd7c7f 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/stats/DocumentStatistics.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/stats/DocumentStatistics.java @@ -7,12 +7,12 @@ import org.eclipse.collections.impl.factory.Sets; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; -import de.unistuttgart.ims.coref.annotator.Util; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.CoreferenceModelListener; import de.unistuttgart.ims.coref.annotator.document.DocumentModel; import de.unistuttgart.ims.coref.annotator.document.FeatureStructureEvent; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class DocumentStatistics implements CoreferenceModelListener { public static enum Property { @@ -105,7 +105,7 @@ public DocumentModel getDocumentModel() { public void setDocumentModel(DocumentModel documentModel) { this.documentModel = documentModel; this.summaryStatistics = null; - this.numberOfTokens = Util.count(documentModel.getJcas(), Token.class); + this.numberOfTokens = UimaUtil.count(documentModel.getJcas(), Token.class); this.numberOfCharacters = documentModel.getJcas().getDocumentText().length(); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/stats/StatisticsPanel.java b/src/main/java/de/unistuttgart/ims/coref/annotator/stats/StatisticsPanel.java index a58a870b..aed0d790 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/stats/StatisticsPanel.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/stats/StatisticsPanel.java @@ -10,7 +10,7 @@ import javax.swing.JLabel; import javax.swing.JPanel; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import de.unistuttgart.ims.coref.annotator.Annotator; import de.unistuttgart.ims.coref.annotator.Util; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/tools/ExportMultipleFiles.java b/src/main/java/de/unistuttgart/ims/coref/annotator/tools/ExportMultipleFiles.java index 6d4d4ba1..c129cfa3 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/tools/ExportMultipleFiles.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/tools/ExportMultipleFiles.java @@ -67,6 +67,8 @@ public static void main(String[] args) for (File f : file.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { + if (pathname.isDirectory()) + return false; return pluginManager.getDefaultIOPlugin().getFileFilter().accept(pathname); } @@ -135,7 +137,14 @@ Class getPluginClass() { case tei: return de.unistuttgart.ims.coref.annotator.plugin.tei.TeiExportPlugin.class; case qdtei: - return de.unistuttgart.ims.coref.annotator.plugin.quadrama.tei.QuadramaTeiExportPlugin.class; + // This is a temporary workaround + try { + return (Class) Class + .forName("de.unistuttgart.ims.coref.annotator.plugin.quadrama.tei.QuadramaTeiExportPlugin"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return null; + } default: return null; } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/AnnotationUtil.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/AnnotationUtil.java new file mode 100644 index 00000000..4ef7d8be --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/AnnotationUtil.java @@ -0,0 +1,146 @@ +package de.unistuttgart.ims.coref.annotator.uima; + +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.uima.fit.util.JCasUtil; +import org.apache.uima.jcas.tcas.Annotation; + +public class AnnotationUtil { + static Pattern pattern = null; + + static char[] whitespace = new char[] { ' ', '\n', '\t', '\r', '\f' }; + + /** + * trims the annotated text. Similar to {@link String#trim()}, this method moves + * the begin and end indexes towards the middle as long as there is whitespace. + * + * The method throws a ArrayIndexOutOfBoundsException if the entire annotation + * consists of whitespace. + * + * @param annotation The annotation to trim + * @param ws An array of chars that are to be considered whitespace + * @param The annotation type + * @return The trimmed annotation (not a copy) + * @since 0.4.1 + */ + public static T trim(T annotation, char... ws) { + final char[] s = annotation.getCoveredText().toCharArray(); + if (s.length == 0) + return annotation; + + int b = 0; + while (ArrayUtils.contains(ws, s[b])) { + b++; + } + + int e = 0; + while (ArrayUtils.contains(ws, s[(s.length - 1) - e])) { + e++; + } + annotation.setBegin(annotation.getBegin() + b); + annotation.setEnd(annotation.getEnd() - e); + return annotation; + } + + /** + * + * + * This method first checks whether the string contains whitespace at all. See + * also {@link #trim(Annotation, char...) } + * + * @param annotation The annotation to trim + * @param the annotation type + * @return the trimmed annotation + * @since 0.4.1 + * + */ + public static T trim(T annotation) { + if (pattern == null) { + pattern = Pattern.compile("\\S"); + } + if (!pattern.matcher(annotation.getCoveredText()).find()) { + return annotation; + } + return trim(annotation, whitespace); + } + + /** + * trims an entire collection of annotations. Beware: directly trimming the + * result of {@link JCasUtil#select(org.apache.uima.jcas.JCas, Class)} throws a + * {@link ConcurrentModificationException}. + * + * @param annotations The annotations you want to trim + * @param the annotation type + * @since 0.4.1 + */ + public static void trim(Collection annotations) { + for (final T anno : annotations) { + trim(anno, ' ', '\n', '\t', '\r', '\f'); + } + } + + /** + * Moves the begin-index as long as a character contain in the array is at the + * beginning. + * + * @param annotation the annotation to be trimmed + * @param ws an array of chars to be trimmed + * @param the annotation type + * @return the trimmed annotation + * @since 0.4.1 + * @deprecated Use {@link #trimBegin(Annotation, char...)} instead. + */ + @Deprecated + public static T trimFront(T annotation, char... ws) { + return trimBegin(annotation, ws); + } + + /** + * Moves the begin-index as long as a character contain in the array is at the + * beginning. + * + * @param annotation the annotation to be trimmed + * @param ws an array of chars to be trimmed + * @param the annotation type + * @return the trimmed annotation + * @since 0.4.2 + */ + public static T trimBegin(T annotation, char... ws) { + char[] s = annotation.getCoveredText().toCharArray(); + if (s.length == 0) + return annotation; + + int b = 0; + while (ArrayUtils.contains(ws, s[b])) { + b++; + } + + annotation.setBegin(annotation.getBegin() + b); + return annotation; + } + + /** + * Moves the end-index as long a character that is contained in the array is at + * the end. + * + * @param annotation The annotation to be trimmed. + * @param ws An array of characters which are considered whitespace + * @return The trimmed annotation + * @since 0.4.2 + */ + public static T trimEnd(T annotation, char... ws) { + char[] s = annotation.getCoveredText().toCharArray(); + if (s.length == 0) + return annotation; + + int e = 0; + while (ArrayUtils.contains(ws, s[(s.length - 1) - e])) { + e++; + } + annotation.setEnd(annotation.getEnd() - e); + return annotation; + } +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/CoNLL2012Reader.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/CoNLL2012Reader.java index cb2beae3..c3ae1ca6 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/CoNLL2012Reader.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/CoNLL2012Reader.java @@ -12,16 +12,17 @@ import org.apache.uima.fit.factory.JCasBuilder; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.FSArray; +import org.dkpro.core.api.io.JCasResourceCollectionReader_ImplBase; +import org.dkpro.core.api.resources.CompressionUtils; import org.eclipse.collections.impl.factory.Maps; -import de.tudarmstadt.ukp.dkpro.core.api.io.JCasResourceCollectionReader_ImplBase; -import de.tudarmstadt.ukp.dkpro.core.api.resources.CompressionUtils; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; import de.unistuttgart.ims.coref.annotator.ColorProvider; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; -import de.unistuttgart.ims.uimautil.AnnotationUtil; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; public class CoNLL2012Reader extends JCasResourceCollectionReader_ImplBase { ColorProvider colorProvider = new ColorProvider(); @@ -65,7 +66,12 @@ public void getNext(JCas aJCas) throws IOException, CollectionException { Matcher m = pattern.matcher(cr); if (m.find() && cr.endsWith(")")) { int id = Integer.valueOf(m.group()); - Mention mention = b.add(beginMentionMap.get(id), Mention.class); + MentionSurface surface = b.add(beginMentionMap.get(id), MentionSurface.class); + Mention mention = new Mention(aJCas); + mention.addToIndexes(); + mention.setSurface(new FSArray(aJCas, 1)); + mention.setSurface(0, surface); + surface.setMention(mention); Entity e = getOrCreate(aJCas, entityMap, id); mention.setEntity(e); } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/EnsureMeta.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/EnsureMeta.java index 99fe274a..fe06a20c 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/EnsureMeta.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/EnsureMeta.java @@ -20,7 +20,7 @@ public class EnsureMeta extends JCasAnnotator_ImplBase { public static final String PARAM_TS_VERSION = "TS_VERSION"; - @ConfigurationParameter(name = PARAM_TS_VERSION, mandatory = false, defaultValue = "v1") + @ConfigurationParameter(name = PARAM_TS_VERSION, mandatory = false, defaultValue = "v2") String typeSystemVersion; @Override diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/Fix131.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/Fix131.java deleted file mode 100644 index 8881a629..00000000 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/Fix131.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.unistuttgart.ims.coref.annotator.uima; - -import java.util.Collection; - -import org.apache.uima.analysis_engine.AnalysisEngineProcessException; -import org.apache.uima.fit.component.JCasAnnotator_ImplBase; -import org.apache.uima.fit.util.JCasUtil; -import org.apache.uima.jcas.JCas; -import org.apache.uima.jcas.tcas.Annotation; -import org.eclipse.collections.api.set.MutableSet; -import org.eclipse.collections.impl.factory.Sets; - -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; - -/** - * Component to fix errors that result from conversion issues - * - * @author reiterns - * - */ -public class Fix131 extends JCasAnnotator_ImplBase { - - @Override - public void process(JCas jcas) throws AnalysisEngineProcessException { - MutableSet toRemove = Sets.mutable.empty(); - Collection parts = JCasUtil.select(jcas, DetachedMentionPart.class); - for (DetachedMentionPart part : parts) { - if (part.getMention() == null) { - for (Mention m : JCasUtil.select(jcas, Mention.class)) - if (m.getDiscontinuous() == part) - part.setMention(m); - if (part.getMention() == null) - toRemove.add(part); - } else if (part.getMention().getDiscontinuous() != part) { - part.getMention().setDiscontinuous(part); - } - } - } - -} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MentionComparator.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MentionComparator.java new file mode 100644 index 00000000..b71ce42f --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MentionComparator.java @@ -0,0 +1,45 @@ +package de.unistuttgart.ims.coref.annotator.uima; + +import java.util.Comparator; + +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; + +public class MentionComparator implements Comparator { + + boolean useEnd = false; + boolean descending = false; + + public MentionComparator() { + } + + public MentionComparator(boolean useEnd) { + this.useEnd = useEnd; + } + + @Override + public int compare(Mention o1, Mention o2) { + if (useEnd) + return (descending ? -1 : 1) * Integer.compare(UimaUtil.getEnd(o1), UimaUtil.getEnd(o2)); + else { + int returnValue = UimaUtil.compare(o1, o2); + return (descending ? -1 : 1) * returnValue; + } + } + + public boolean isUseEnd() { + return useEnd; + } + + public void setUseEnd(boolean useEnd) { + this.useEnd = useEnd; + } + + public boolean isDescending() { + return descending; + } + + public void setDescending(boolean descending) { + this.descending = descending; + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MergeAnnotations.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MergeAnnotations.java index 63fc02b3..a91b438c 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MergeAnnotations.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MergeAnnotations.java @@ -9,16 +9,16 @@ import org.apache.uima.fit.factory.AnnotationFactory; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.EmptyFSList; import org.apache.uima.jcas.cas.FSArray; -import org.apache.uima.jcas.cas.StringArray; import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.impl.factory.Maps; import org.xml.sax.SAXException; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; public class MergeAnnotations extends JCasAnnotator_ImplBase { @@ -40,54 +40,49 @@ public void process(JCas jcas) throws AnalysisEngineProcessException { // handle entities for (Entity oldEntity : JCasUtil.select(jcas2, Entity.class)) { Entity newEntity; - if (oldEntity instanceof EntityGroup) { - newEntity = new EntityGroup(jcas); - } else { - newEntity = new Entity(jcas); - } + + newEntity = new Entity(jcas); newEntity.setLabel(oldEntity.getLabel()); newEntity.setColor(oldEntity.getColor()); newEntity.addToIndexes(); entityMap.put(oldEntity, newEntity); + newEntity.setFlags(new EmptyFSList(jcas)); if (oldEntity.getFlags() != null) { - StringArray flags = new StringArray(jcas, oldEntity.getFlags().size()); - newEntity.setFlags(flags); - for (int i = 0; i < oldEntity.getFlags().size(); i++) { - newEntity.setFlags(i, oldEntity.getFlags(i)); - } + for (Flag flag : oldEntity.getFlags()) + newEntity.getFlags().push(flag); } - } - - // handle entity groups - for (EntityGroup oldEntity : JCasUtil.select(jcas2, EntityGroup.class)) { - EntityGroup newEntity = (EntityGroup) entityMap.get(oldEntity); - FSArray arr = new FSArray(jcas, oldEntity.getMembers().size()); - arr.addToIndexes(); - newEntity.setMembers(arr); - for (int i = 0; i < oldEntity.getMembers().size(); i++) { - newEntity.setMembers(i, entityMap.get(oldEntity.getMembers(i))); + if (UimaUtil.isGroup(oldEntity)) { + FSArray arr = new FSArray(jcas, oldEntity.getMembers().size()); + arr.addToIndexes(); + newEntity.setMembers(arr); + for (int i = 0; i < oldEntity.getMembers().size(); i++) { + newEntity.setMembers(i, entityMap.get(oldEntity.getMembers(i))); + } } + } // handle mentions for (Mention m : JCasUtil.select(jcas2, Mention.class)) { - Mention newMention = AnnotationFactory.createAnnotation(jcas, m.getBegin(), m.getEnd(), Mention.class); - newMention.setEntity(entityMap.get(m.getEntity())); - if (m.getDiscontinuous() != null) { - DetachedMentionPart dmp = AnnotationFactory.createAnnotation(jcas, m.getDiscontinuous().getBegin(), - m.getDiscontinuous().getEnd(), DetachedMentionPart.class); - newMention.setDiscontinuous(dmp); - dmp.setMention(newMention); + Mention newMention = new Mention(jcas); + newMention.setSurface(new FSArray(jcas, m.getSurface().size())); + int i = 0; + for (MentionSurface ms : m.getSurface()) { + MentionSurface newMS = AnnotationFactory.createAnnotation(jcas, ms.getBegin(), ms.getEnd(), + MentionSurface.class); + newMS.setMention(newMention); + newMention.setSurface(i++, newMS); } + newMention.setEntity(entityMap.get(m.getEntity())); + newMention.addToIndexes(); + newMention.setFlags(new EmptyFSList(jcas)); if (m.getFlags() != null) { - StringArray flags = new StringArray(jcas, m.getFlags().size()); - newMention.setFlags(flags); - for (int i = 0; i < m.getFlags().size(); i++) { - newMention.setFlags(i, m.getFlags(i)); - } + for (Flag flag : m.getFlags()) + newMention.getFlags().push(flag); + } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MergeFilesPlugin.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MergeFilesPlugin.java index 76a9ee4f..4846e518 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MergeFilesPlugin.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/MergeFilesPlugin.java @@ -10,9 +10,9 @@ import org.apache.uima.fit.factory.AnalysisEngineFactory; import org.apache.uima.fit.factory.CollectionReaderFactory; import org.apache.uima.resource.ResourceInitializationException; +import org.dkpro.core.io.xmi.XmiReader; import org.eclipse.collections.api.list.ImmutableList; -import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiReader; import de.unistuttgart.ims.coref.annotator.plugins.AbstractImportPlugin; import de.unistuttgart.ims.coref.annotator.plugins.StylePlugin; import de.unistuttgart.ims.coref.annotator.plugins.UimaImportPlugin; diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/SetDocumentId.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/SetDocumentId.java new file mode 100644 index 00000000..6969588d --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/SetDocumentId.java @@ -0,0 +1,32 @@ +package de.unistuttgart.ims.coref.annotator.uima; + +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.fit.component.JCasAnnotator_ImplBase; +import org.apache.uima.fit.descriptor.ConfigurationParameter; +import org.apache.uima.fit.util.JCasUtil; +import org.apache.uima.jcas.JCas; + +import de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData; + +public class SetDocumentId extends JCasAnnotator_ImplBase { + + public static final String PARAM_DOCUMENT_ID = "Document Id"; + public static final String PARAM_DOCUMENT_TITLE = "Document Title"; + + @ConfigurationParameter(name = PARAM_DOCUMENT_ID, mandatory = false) + String documentId = null; + + @ConfigurationParameter(name = PARAM_DOCUMENT_TITLE, mandatory = false) + String documentTitle = null; + + @Override + public void process(JCas jcas) throws AnalysisEngineProcessException { + if (!JCasUtil.exists(jcas, DocumentMetaData.class)) + DocumentMetaData.create(jcas); + if (documentId != null) + DocumentMetaData.get(jcas).setDocumentId(documentId); + if (documentTitle != null) + DocumentMetaData.get(jcas).setDocumentTitle(documentTitle); + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/SetJCasLanguage.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/SetJCasLanguage.java new file mode 100644 index 00000000..277ac3ad --- /dev/null +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/SetJCasLanguage.java @@ -0,0 +1,20 @@ +package de.unistuttgart.ims.coref.annotator.uima; + +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.fit.component.JCasAnnotator_ImplBase; +import org.apache.uima.fit.descriptor.ConfigurationParameter; +import org.apache.uima.jcas.JCas; + +public class SetJCasLanguage extends JCasAnnotator_ImplBase { + + public static final String PARAM_LANGUAGE = "Language"; + + @ConfigurationParameter(name = PARAM_LANGUAGE, mandatory = true) + String language = null; + + @Override + public void process(JCas jcas) throws AnalysisEngineProcessException { + jcas.setDocumentLanguage(language); + } + +} diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/UimaUtil.java b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/UimaUtil.java index 8743a255..3a8e8d78 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/uima/UimaUtil.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/uima/UimaUtil.java @@ -4,23 +4,352 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.Iterator; import java.util.function.Predicate; import java.util.zip.GZIPInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.uima.UIMAException; import org.apache.uima.cas.CASException; +import org.apache.uima.cas.CASRuntimeException; +import org.apache.uima.cas.Feature; +import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.impl.XmiCasDeserializer; import org.apache.uima.cas.text.AnnotationTreeNode; +import org.apache.uima.fit.factory.AnnotationFactory; import org.apache.uima.fit.factory.JCasFactory; +import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.EmptyFSList; +import org.apache.uima.jcas.cas.FSArray; +import org.apache.uima.jcas.cas.FSList; import org.apache.uima.jcas.cas.StringArray; +import org.apache.uima.jcas.cas.TOP; +import org.apache.uima.jcas.tcas.Annotation; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.factory.Lists; import org.xml.sax.SAXException; -import de.unistuttgart.ims.coref.annotator.api.v1.Segment; +import de.unistuttgart.ims.coref.annotator.Annotator; +import de.unistuttgart.ims.coref.annotator.Defaults; +import de.unistuttgart.ims.coref.annotator.api.Meta; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; +import de.unistuttgart.ims.coref.annotator.api.v2.Segment; public class UimaUtil { + + public static void addFlag(FeatureStructure fs, Flag flag) { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + FSList flagList = UimaUtil.getFlags(fs); + + fs.setFeatureValue(feature, flagList.push(flag)); + } + + @Deprecated + public static void addFlagKey(FeatureStructure fs, String flagKey) { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + try { + StringArray arr = addTo(fs.getCAS().getJCas(), (StringArray) fs.getFeatureValue(feature), flagKey); + fs.setFeatureValue(feature, arr); + } catch (CASRuntimeException | CASException e) { + e.printStackTrace(); + } + } + + public static void addMentionSurface(Mention mention, MentionSurface ms) { + FSArray oldArray = mention.getSurface(); + FSArray newArray = new FSArray(mention.getJCas(), oldArray.size() + 1); + + Iterator oldArrayIterator = oldArray.iterator(); + int i = 0; + boolean added = false; + while (oldArrayIterator.hasNext()) { + MentionSurface surf = oldArrayIterator.next(); + + if (!added && UimaUtil.compare(surf, ms) > 0) { + newArray.set(i++, ms); + added = true; + } + newArray.set(i++, surf); + } + if (!added) + newArray.set(i++, ms); + oldArray.removeFromIndexes(); + mention.setSurface(newArray); + } + + public static FSArray addTo(JCas jcas, FSArray arr, T fs) { + int i = 0; + FSArray nArr; + if (arr != null) { + nArr = new FSArray(jcas, arr.size() + 1); + for (; i < arr.size(); i++) { + nArr.set(i, arr.get(i)); + } + } else { + nArr = new FSArray(jcas, 1); + } + nArr.set(i, fs); + arr.removeFromIndexes(); + nArr.addToIndexes(); + return nArr; + + } + + public static StringArray addTo(JCas jcas, StringArray arr, String fs) { + int i = 0; + StringArray nArr; + int oldSize = arr == null ? 0 : arr.size(); + if (arr != null) { + nArr = new StringArray(jcas, oldSize + 1); + for (; i < oldSize; i++) { + nArr.set(i, arr.get(i)); + } + } else { + nArr = new StringArray(jcas, 1); + } + nArr.set(i, fs); + if (arr != null) + arr.removeFromIndexes(); + nArr.addToIndexes(); + return nArr; + + } + + public static FSList clone(FSList arr) throws CASException { + FSList newList = new EmptyFSList(arr.getJCas()); + for (int i = arr.getLength() - 1; i >= 0; i--) + newList.push(arr.getNthElement(i)); + return newList; + } + + @Deprecated + public static StringArray clone(StringArray arr) throws CASException { + StringArray newArray = new StringArray(arr.getCAS().getJCas(), arr.size()); + for (int i = 0; i < newArray.size(); i++) + newArray.set(i, arr.get(i)); + return newArray; + } + + public static int compare(Annotation m1, Annotation m2) { + int returnValue = Integer.compare(m1.getBegin(), m2.getBegin()); + if (returnValue == 0) + returnValue = Integer.compare(m2.getEnd(), m1.getEnd()); + if (returnValue == 0) + returnValue = Integer.compare(m1.hashCode(), m2.hashCode()); + return returnValue; + } + + public static int compare(Mention m1, Mention m2) { + int returnValue = Integer.compare(UimaUtil.getBegin(m1), UimaUtil.getBegin(m2)); + if (returnValue == 0) + returnValue = Integer.compare(UimaUtil.getEnd(m2), UimaUtil.getEnd(m1)); + if (returnValue == 0) + returnValue = Integer.compare(m1.hashCode(), m2.hashCode()); + return returnValue; + } + + @Deprecated + public static boolean contains(StringArray array, String s) { + if (array == null) + return false; + for (int i = 0; i < array.size(); i++) + if (array.get(i).equals(s)) + return true; + return false; + } + + public static boolean contains(FSList array, T s) { + if (array == null) + return false; + for (int i = 0; i < array.getLength(); i++) + if (array.getNthElement(i).equals(s)) + return true; + return false; + } + + public static int count(JCas jcas, Class cl) { + return JCasUtil.select(jcas, cl).size(); + } + + public static Mention createMention(JCas jcas, int begin, int end) { + MentionSurface ms = AnnotationFactory.createAnnotation(jcas, begin, end, MentionSurface.class); + Mention m = new Mention(jcas); + m.addToIndexes(); + m.setSurface(new FSArray(jcas, 1)); + m.setSurface(0, ms); + m.getSurface().addToIndexes(); + ms.setMention(m); + return m; + } + + public static T extend(T annotation) { + final char[] s = annotation.getCoveredText().toCharArray(); + char[] text = annotation.getCAS().getDocumentText().toCharArray(); + if (s.length == 0) + return annotation; + + int b = annotation.getBegin(), e = annotation.getEnd(); + + if (b > 0) { + char prev = text[b - 1]; + while (b > 0 && Character.isLetter(prev)) { + b--; + // if we have reached the beginning, we pretend the + // previous character to be a white space. + if (b == 0) + prev = ' '; + else + prev = text[b - 1]; + } + } + + if (e < text.length) { + char next = text[e]; + while (e < text.length && Character.isLetter(next)) { + e++; + if (e == text.length) + next = ' '; + else + next = text[e]; + } + } + + annotation.setBegin(b); + annotation.setEnd(e); + return annotation; + } + + public static int getBegin(Mention mention) { + return mention.getSurface(0).getBegin(); + } + + public static String getCoveredText(Mention mention) { + return StringUtils.join(JCasUtil.toText(mention.getSurface()), Defaults.CFG_MENTIONSURFACE_SEPARATOR); + } + + public static int getEnd(Mention mention) { + return mention.getSurface(mention.getSurface().size() - 1).getEnd(); + } + + public static MentionSurface getFirst(Mention m) { + return m.getSurface(0); + } + + public static FSList getFlags(FeatureStructure fs) { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + if (feature == null) + return new EmptyFSList(fs.getJCas()); + else { + @SuppressWarnings("unchecked") + FSList sa = (FSList) fs.getFeatureValue(feature); + if (sa == null) + return new EmptyFSList(fs.getJCas()); + else + return sa; + } + } + + @Deprecated + public static String[] getFlagsAsStringArray(FeatureStructure fs) { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + if (feature == null) + return new String[0]; + else { + StringArray sa = (StringArray) fs.getFeatureValue(feature); + if (sa == null) + return new String[0]; + else + return sa.toStringArray(); + } + } + + public static MentionSurface getLast(Mention m) { + return m.getSurface(m.getSurface().size() - 1); + } + + public static Meta getMeta(JCas jcas) { + if (!JCasUtil.exists(jcas, Meta.class)) { + Meta m = new Meta(jcas); + m.addToIndexes(); + return m; + } + try { + return JCasUtil.selectSingle(jcas, Meta.class); + } catch (IllegalArgumentException e) { + Annotator.logger.catching(e); + return null; + } + } + + public static Iterable selectFollowing(Mention m, int n) { + ImmutableList mss = Lists.immutable + .withAll(JCasUtil.selectFollowing(MentionSurface.class, UimaUtil.getLast(m), n)); + return mss.collect(ms -> ms.getMention()).toSet().toList(); + } + + public static Iterable selectPreceding(Mention m, int n) { + ImmutableList mss = Lists.immutable + .withAll(JCasUtil.selectPreceding(MentionSurface.class, UimaUtil.getFirst(m), n)); + return mss.collect(ms -> ms.getMention()).toSet().toList(); + } + + public static boolean isGroup(Object o) { + if (!(o instanceof Entity)) + return false; + Entity e = (Entity) o; + if (e.getMembers() == null) + return false; + return e.getMembers().size() > 0; + } + + @Deprecated + public static boolean isX(FeatureStructure fs, String flag) { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + return contains((StringArray) fs.getFeatureValue(feature), flag); + } + + @SuppressWarnings("unchecked") + public static boolean isX(FeatureStructure fs, Flag flag) { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + FeatureStructure flagsFS = fs.getFeatureValue(feature); + if (flagsFS instanceof FSList) + return contains((FSList) flagsFS, flag); + return false; + } + + public static String join(StringArray arr, String sep) { + if (arr.isEmpty()) + return ""; + StringBuilder b = new StringBuilder(); + b.append(arr.get(0)); + for (int i = 0; i < arr.size(); i++) { + b.append(sep); + b.append(arr.get(i)); + } + return b.toString(); + } + + public static int nextCharacter(JCas jcas, int pos, Predicate pred) { + char[] txt = jcas.getDocumentText().toCharArray(); + for (int i = pos; i < txt.length; i++) { + if (pred.test(txt[i])) + return i; + } + return -1; + } + + public static JCas readJCas(InputStream is) throws UIMAException, SAXException, IOException { + JCas jcas = JCasFactory.createJCas(); + XmiCasDeserializer.deserialize(is, jcas.getCas(), true); + return jcas; + } + public static JCas readJCas(String filename) throws UIMAException, FileNotFoundException, SAXException, IOException { if (filename.endsWith(".gz")) { @@ -38,19 +367,106 @@ public static JCas readJCas(String filename) } } - public static JCas readJCas(InputStream is) throws UIMAException, SAXException, IOException { - JCas jcas = JCasFactory.createJCas(); - XmiCasDeserializer.deserialize(is, jcas.getCas(), true); - return jcas; + public static void removeFlag(FeatureStructure fs, Flag flag) { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + FSList flagList = getFlags(fs); + flagList = removeFrom(flagList, flag); + fs.setFeatureValue(feature, flagList); } - public static int nextCharacter(JCas jcas, int pos, Predicate pred) { - char[] txt = jcas.getDocumentText().toCharArray(); - for (int i = pos; i < txt.length; i++) { - if (pred.test(txt[i])) - return i; + @Deprecated + public static void removeFlagKey(FeatureStructure fs, String flagKey) { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + try { + StringArray arr = removeFrom(fs.getCAS().getJCas(), (StringArray) fs.getFeatureValue(feature), flagKey); + fs.setFeatureValue(feature, arr); + } catch (CASRuntimeException | CASException e) { + e.printStackTrace(); } - return -1; + + } + + public static FSArray removeFrom(JCas jcas, FSArray arr, T fs) { + int i = 0, j = 0; + FSArray nArr = null; + arr.removeFromIndexes(); + int oldSize = arr == null ? 0 : arr.size(); + nArr = new FSArray(jcas, oldSize - 1); + for (; i < oldSize; i++, j++) { + if (!arr.get(i).equals(fs)) + nArr.set(j, arr.get(i)); + else + j--; + } + nArr.addToIndexes(); + return nArr; + } + + public static StringArray removeFrom(JCas jcas, StringArray arr, String fs) { + int i = 0, j = 0; + StringArray nArr = null; + int oldSize = arr == null ? 0 : arr.size(); + nArr = new StringArray(jcas, oldSize - 1); + for (; i < oldSize; i++, j++) { + if (!arr.get(i).equals(fs)) + nArr.set(j, arr.get(i)); + else + j--; + } + return nArr; + } + + public static FSList removeFrom(FSList list, FeatureStructure fs) { + FSList retList = new EmptyFSList(list.getJCas()); + Iterator iter = list.iterator(); + while (iter.hasNext()) { + T element = iter.next(); + if (element != fs) + retList = retList.push(element); + } + return retList; + } + + public static void removeMentionSurface(Mention mention, MentionSurface ms) { + FSArray oldArray = mention.getSurface(); + FSArray newArray = new FSArray(mention.getJCas(), oldArray.size() - 1); + + Iterator oldArrayIterator = oldArray.iterator(); + int i = 0; + while (oldArrayIterator.hasNext()) { + MentionSurface surf = oldArrayIterator.next(); + + if (surf == ms) + continue; + newArray.set(i++, surf); + } + oldArray.removeFromIndexes(); + mention.setSurface(newArray); + + } + + public static Mention selectMentionByIndex(JCas jcas, int index) { + Iterator iterator = jcas.getIndexedFSs(Mention.class).iterator(); + while (iterator.hasNext() && index >= 0) { + Mention m = iterator.next(); + if (index-- == 0) + return m; + } + return null; + } + + public static void setFlags(FeatureStructure fs, StringArray arr) throws CASException { + Feature feature = fs.getType().getFeatureByBaseName("Flags"); + if (feature == null) + return; + else + fs.setFeatureValue(feature, arr); + } + + public static MutableList toList(FSArray arr) { + MutableList list = Lists.mutable.empty(); + arr.forEach(fs -> list.add(fs)); + return list; } public static String toString(AnnotationTreeNode tn, String sep, int maxlength) { @@ -60,6 +476,8 @@ public static String toString(AnnotationTreeNode tn, String sep, int ma return null; StringBuilder b = new StringBuilder(); while (tn != null) { + if (tn.get().getLabel().equalsIgnoreCase("document")) + break; String s = tn.get().getLabel(); s = StringUtils.abbreviate(s, maxlength); if (s != null && !s.isBlank()) { @@ -70,11 +488,4 @@ public static String toString(AnnotationTreeNode tn, String sep, int ma } return b.toString(); } - - public static StringArray clone(StringArray arr) throws CASException { - StringArray newArray = new StringArray(arr.getCAS().getJCas(), arr.size()); - for (int i = 0; i < newArray.size(); i++) - newArray.set(i, arr.get(i)); - return newArray; - } } diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/worker/JCasLoader.java b/src/main/java/de/unistuttgart/ims/coref/annotator/worker/JCasLoader.java index 7aa62273..e539ca9e 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/worker/JCasLoader.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/worker/JCasLoader.java @@ -27,9 +27,7 @@ import de.unistuttgart.ims.coref.annotator.plugins.DirectFileIOPlugin; import de.unistuttgart.ims.coref.annotator.plugins.UimaImportPlugin; import de.unistuttgart.ims.coref.annotator.uima.EnsureMeta; -import de.unistuttgart.ims.coref.annotator.uima.Fix131; -import de.unistuttgart.ims.coref.annotator.uima.VerifyFlagObjects; -import de.unistuttgart.ims.uimautil.SetJCasLanguage; +import de.unistuttgart.ims.coref.annotator.uima.SetJCasLanguage; public class JCasLoader extends SwingWorker { @@ -108,8 +106,6 @@ private JCas readFile() throws IOException, UIMAException { b.add(AnalysisEngineFactory.createEngineDescription(SetJCasLanguage.class, SetJCasLanguage.PARAM_LANGUAGE, getLanguage())); b.add(flavor.getImporter()); - b.add(AnalysisEngineFactory.createEngineDescription(Fix131.class)); - b.add(AnalysisEngineFactory.createEngineDescription(VerifyFlagObjects.class)); SimplePipeline.runPipeline(jcas, b.createAggregateDescription()); return jcas; @@ -121,8 +117,6 @@ private JCas readFile() throws IOException, UIMAException { b.add(AnalysisEngineFactory.createEngineDescription(SetJCasLanguage.class, SetJCasLanguage.PARAM_LANGUAGE, getLanguage())); b.add(flavor.getImporter()); - b.add(AnalysisEngineFactory.createEngineDescription(Fix131.class)); - b.add(AnalysisEngineFactory.createEngineDescription(VerifyFlagObjects.class)); iter = SimplePipeline.iteratePipeline(crd, b.createAggregateDescription()).iterator(); if (iter.hasNext()) { diff --git a/src/main/java/de/unistuttgart/ims/coref/annotator/worker/SaveJCasWorker.java b/src/main/java/de/unistuttgart/ims/coref/annotator/worker/SaveJCasWorker.java index 4166693f..fc292bf3 100644 --- a/src/main/java/de/unistuttgart/ims/coref/annotator/worker/SaveJCasWorker.java +++ b/src/main/java/de/unistuttgart/ims/coref/annotator/worker/SaveJCasWorker.java @@ -31,11 +31,12 @@ protected Object doInBackground() throws Exception { Annotator.logger.info("Saving ... "); OutputStream os = null; try { - if (file.getName().endsWith(".xmi")) { - os = new FileOutputStream(file); - } else if (file.getName().endsWith(".gz")) { + if (file.getName().endsWith(".ca2z")) { os = new GZIPOutputStream(new FileOutputStream(file)); + } else if (file.getName().endsWith(".ca2")) { + os = new FileOutputStream(file); } + if (os != null) XmiCasSerializer.serialize(jcas.getCas(), null, os, true, null); } finally { @@ -55,7 +56,6 @@ protected void done() { public static BiConsumer getConsumer(DocumentWindow target) { return (file, jcas) -> { Annotator.app.addRecentFile(file); - Annotator.app.refreshRecents(); Annotator.app.setCurrentDirectory(file.getParentFile()); target.getDocumentModel().getHistory().clear(); target.setFile(file); diff --git a/src/main/resources/META-INF/org.apache.uima.fit/types.txt b/src/main/resources/META-INF/org.apache.uima.fit/types.txt index 64baeef6..94e8703e 100644 --- a/src/main/resources/META-INF/org.apache.uima.fit/types.txt +++ b/src/main/resources/META-INF/org.apache.uima.fit/types.txt @@ -1,6 +1,8 @@ classpath*:types.xml classpath*:types-meta.xml classpath*:types-v1.xml +classpath*:types-v2.xml classpath*:types-format.xml classpath*:creta-coref.xml +classpath*:types-quadrama.xml classpath*:sfb1391-types.xml \ No newline at end of file diff --git a/src/main/resources/docs/compare-view-sidebar.png b/src/main/resources/docs/compare-view-sidebar.png new file mode 100644 index 00000000..f39d77fc Binary files /dev/null and b/src/main/resources/docs/compare-view-sidebar.png differ diff --git a/src/main/resources/docs/compare.html b/src/main/resources/docs/compare.html index 36abd087..e67379ba 100644 --- a/src/main/resources/docs/compare.html +++ b/src/main/resources/docs/compare.html @@ -5,8 +5,7 @@

Compare annotations

The compare view allows the joined view of two (or more) annotated -documents. As of version 1.3, it only allows comparison of the spans of -the annotation mentions.

+documents.

The compare view shows the document in text view, and the annotated mentions underlined. Colors, however, do not signal @@ -16,8 +15,27 @@

Compare annotations

that are marked by all annotators are underlined in gray.

Statistics

-

The panel on the right shows some numbers about the agreement. Note -that this is only a rough estimate, and only shows observed agreement.

+
+ +
+

The panel on the right shows settings and numbers about the agreement +(see screenshot below). On the top, you find information about the +currently used mode. Below that, each annotators is presented individually. +On the bottom, you see some agreement statistics.

+ +

Information about annotators: For annotators, the view shows the number of +annotated mentions and entities, as well as the position. Position is the last +annotated mention (thus, it roughly corresponds to where in the document +the annotator is).

+ +

Modes: In version 2.0, two comparison modes are supported: By default, the +comparison only takes the span into account. I.e., two mentions are considered +equal, if they cover the same words, irrespective of the entity they refer to. +The alternative mode can be activated via the settings menu +("Compare by entity name"). If activated, two mentions are only considered +equal if they cover the same span and the names of the entities they refer to +are also equal.

+ diff --git a/src/main/resources/docs/flags.html b/src/main/resources/docs/flags.html index 6b55ac59..15afb045 100644 --- a/src/main/resources/docs/flags.html +++ b/src/main/resources/docs/flags.html @@ -6,7 +6,7 @@

Flags

Since version 1.8, it is possible to add custom flags that can -be attached to mentions, entities and detached mention parts. Flags are +be attached to mentions and entities. Flags are stored in the document.

Flag Editor

diff --git a/src/main/resources/docs/howto.html b/src/main/resources/docs/howto.html index c4a41123..da44f568 100644 --- a/src/main/resources/docs/howto.html +++ b/src/main/resources/docs/howto.html @@ -15,6 +15,7 @@

By drag and drop

underlined with the same color. The name of the entity will be the same as the text segment. Both name and color can be changed at any time.

+

By keyboard

CorefAnnotator can be used by keyboard. To annotate, mark a text segment @@ -39,5 +40,15 @@

Context-derived candidates

contains candidates. The candidates are based on the previous mentions as well as textual overlap with the mentions of any other entities.

+

Discontinuous mentions

+ +

Since version 2.0, a mention can be non-continuous. To add a second text +span to mention, simply select it in the text and drag it onto the existing +mention in the tree. The label of the mention will now consist of the different +spans, separated by a pipe symbol: |. There is no upper limit on the number of +discontinous elements in a mention. Please note that there is no further +relation between the different parts, except for their textual ordering.

+ + \ No newline at end of file diff --git a/src/main/resources/docs/index.html b/src/main/resources/docs/index.html index 76f1386e..9d0a0dba 100644 --- a/src/main/resources/docs/index.html +++ b/src/main/resources/docs/index.html @@ -5,11 +5,13 @@

Index

Overview

+

CorefAnnotator is an annotation tool for coreference, i.e., to mark whenever two or more words in a text refer to the same thing in the real world. We will refer to the words in a text as mentions and to the things in the real world as entities. Entities don't have to be touchable or concrete.

+

CorefAnnotator displays two views: The text on the left, and a tree on the right. Mentions in the text can be selected with a point device (e.g., mouse). To create a new entity in the tree on the right, either drag the @@ -17,10 +19,10 @@

Overview

Newly created entities then get a color assigned, and all their mentions in the text are underlined with the color. Selecting a mention in the tree also selects the mention in the text (and scrolls to an appropriate position if necessary). -Clicking on a mention in the text view shows a context menu with all mentions +A secondary click (i.e., right mouse button) in the text view shows a context menu with all mentions that cover a certain text span. From there, one can reveal the mention in the tree or -directly delete id.

+directly delete it.

In addition to a color, each entity has an assigned key code. This single letter shortcut can be used to quickly assign mentions to entities (without @@ -28,11 +30,11 @@

Overview

name of the entity that is displayed in the tree.

Annotation Concepts

-

Difficult cases

-

While annotating, one typically stumbles upon difficult cases that -need to be discussed with peers or supervisors. To support these discussions, -difficult mentions can be tagged with the exclamation mark symbol: -.

+

Difficult, ambiguous and generic cases

+

There are a lot of cases for which a mention or entity need to marked in a +particular way. This can be done with so-called flags. Flags can be created +with the flag editor, and then assigned to mentions and entities. +You find more on the flag editor on the help page about flags.

Groups

Sometimes, anaphoric expressions can appear in plural without a plural @@ -47,23 +49,12 @@

Groups

reveal their members (which are entities), as well as the mentions that are used to refer to the group.

-

Genericity

-

Genericity expresses whether an entity is a kind, instead of an instance. -The prototypical example is shown in (1) and (2):
-(1) The elephant met a rabbit. He asked him to be his friends.
-(2) When under water, the elephant uses its trunk as a snorkel.
-The underlined strings are exactly the same, but the first refers to a specific -instance or individual of a class, while the second refers to the class as a -whole.

- -

In CorefAnnotator, entities can be marked as generic via the context or top -menu. Generic entities are marked with the cloud symbol: -.

Import / Export

CorefAnnotator uses UIMA's XMI file format to store annotations and meta -data, with a custom type system. Only XMI files using this type system (i.e., -produced through Save as...) can be directly opened and saved. XMI files +data, with a custom type system. By default, CorefAnnotator uses the suffix '.ca2'. +Only files using this type system (i.e., produced through Save as...) can +be directly opened and saved. XMI files using other type systems can be imported and (sometimes) also exported. Non-XMI files are not supported at the moment &emdash; with the only exception that it is possible to import plain text files.

diff --git a/src/main/resources/docs/preferences.html b/src/main/resources/docs/preferences.html new file mode 100644 index 00000000..db975daf --- /dev/null +++ b/src/main/resources/docs/preferences.html @@ -0,0 +1,47 @@ + + +CorefAnnotator Help + + +

Preferences

+ +CorefAnnotator can be customized a bit, using preferences. They are stored in the home directory of the computer the program is running on. This page documents and explains the customization options. + +

Setting preferences

+

Most preferences can be set via the menu "Settings" in the menu bar. Some need to/can be set in a .ini file. Preferences are meant to be persistent.

+ +

Overview

+

Each preference is listed with their internal key (an all-caps string starting with CFG_), their their default value and a brief explanation.

+ +
    +
  • Behaviour
      +
    • CFG_CREATE_DEFAULT_FLAGS (default: false). In older versions of CorefAnnotator flags were built into the program and not changeable. For coreference annotation, a few flags were pre-defined. If this is set to true, they are created automatically when a new document is created.
    • +
    • CFG_DELETE_EMPTY_ENTITIES (default: false). If set to true, as soon as an entity is empty (i.e., doesn't have any mentions) it is removed.
    • +
    • CFG_FULL_TOKENS (default: true). If true, annotated a new mention will automatically expand the selection so that the full token is annotated. A token, in this case, is delimited by whatever matches on \\b in a regular expression. This works mostly, but not always, to user satisfaction. If it doesn't (or you need sub-token annotations), you can always disable this on the fly -- the next mention will not be expanded.
    • +
    • CFG_TRIM_WHITESPACE (default: true). Annotators do not always pay attention not to include a space character into their selection. If this setting is set to true, whitespace at the beginning or end of the selection is not included in the annotation.
    • +
    • CFG_ASK_BEFORE_FILE_OVERWRITE (default: true). It's usually a good idea to ask users whether they want to overwrite a file on disk. This setting controls if that happens.
    • +
    • CFG_STICKY_FLAGS (default: false). Flags attached to mentions are specific to each mention. If this setting is set to true, each flag operation (i.e., adding, deleting) is applied to all mentions with the same span (they do not have to belong to the same entity).
    • +
  • +
  • User interface
      +
    • CFG_SHOW_TEXT_LABELS (default: true). This setting controls whether flags in the tree view are shown as symbols only. If set to false, only the symbol is shown. By default, text and symbol are visible.
    • +
    • CFG_SHOW_TOC (default: true). If the document contains segments (chapters, texts, or acts/scenes), they can be displayed as a table of contents. The TOC is shown to the left of the text.
    • +
    • CFG_SHOW_LINE_NUMBER_IN_TREE (default: true). If the file has pre-defined line numbers, they can be displayed in the tree, along with each mention.
    • +
    • CFG_ENTITY_SORT_ORDER (default: by number of mentions). Controls how to sort entities in the tree view. Alternatives are by number of mentions or alphabetically by label.
    • +
    • CFG_ENTITY_SORT_DESCENDING (default: true). Sort direction.
    • +
    • CFG_KEEP_TREE_SORTED (default: true). Normally, each newly inserted entity will be placed at the correct position in the tree -- the tree is always sorted according to CFG_ENTITY_SORT_ORDER. This setting turns the auto-sorting off.
    • +
  • +
  • Compare view
      +
    • CFG_COMPARE_BY_ENTITY_NAME (default: true). This setting controls how the compare view works. If true, two mentions are considered equal if they have the same extent and refer to an entity with the same name. If false, they are considered equal if they only have the same extent.
    • +
    • CFG_IGNORE_SINGLETONS_WHEN_COMPARING (default: true). If true, singletons are not counted in the statistics view.
    • +
    • CFG_UNDERLINE_SINGLETONS_IN_GRAY (default: false). If true, singletons are underlined in gray.
    • +
  • +
  • Non-boolean settings. These can only be changed via a preferences file.
      +
    • CFG_AUTOSAVE_TIMER (default: 300000 ms = 5 min). The interval in which files are automatically saved.
    • +
    • CFG_SEARCH_RESULTS_CONTEXT (default: 50). The number of characters to display left and right of search results.
    • +
    • CFG_MENTIONSURFACE_SEPARATOR (default: |). The character to be used to separate the parts of discontinuous mentions.
    • +
    • CFG_ANNOTATOR_ID (default: Unknown annotator). The label to be used for an annotator that has not been named.
    • +
  • +
+ + + \ No newline at end of file diff --git a/src/main/resources/docs/profile.html b/src/main/resources/docs/profile.html new file mode 100644 index 00000000..bb14cd42 --- /dev/null +++ b/src/main/resources/docs/profile.html @@ -0,0 +1,147 @@ + + +CorefAnnotator Help + + +

Profiles

+ +

Usage scenario

+

The exact annotation possibilities for an annotator depend on the annotation +task. To support different kinds of annotation tasks, and to prevent annotation +mistakes, a profile for the task can be created to disable some functions and +enforce certain settings. Profiles are defined in an XML file called +profile.xml. If this file is present in the same directory as an +annotation file, it is loaded and activated.

+ +

Capabilities

+

Profiles can influence the following aspects of the annotation: Pre-defining +entities and flags, disabling some or all user operations, change default values +for all preferences, and provide information on the annotation guidelines.

+ +

Blocking of operations

+<forbidden>
+  <operation class="OPERATION" />
+</forbidden> +
+ +

The above snippet shows how to disallow an operation. Multiple operations can +be specified in this way (with multiple +<operation>-elements). The placeholder OPERATION +can be replaced by any class name in the package +de.unistuttgart.ims.coref.annotator.document.op +(follow this link).

+ +

Predefining entities and flags

+<entities>
+ <entity label="PER" color="0" shortcut="p" flags="" /> + <entity label="LOC" color="blue" shortcut="l" flags="" /> +</entities> +
+ +

Entities can be defined as shown above. The only mandatory field is +label, all others are optional. The label can be any +string, it is displayed directly in the UI (and, if not prevented, can be +changed by an annotator).
+The color should be specified as a single +integer value, as expected by class java.awt.Color. Alternatively, +any color name listed +here +under fields can be used.
+The shortcut should be a single letter or number. If it's longer, + only the first character will be used.
+The attribute flags can be used to assign flags to entities. To do +this, the attribute value should be space-separated list of UUIDs, as defined +in the flags section. +

+ + +<flags>
+ <flag label="deriv" uuid="deriv" icon="" targetClass="Mention" /> + <flag label="part" uuid="part" icon="" targetClass="Mention" /> +</entities> +
+ +

Flags can specified as shown above. Of the attributes, only icon +is optional, all others are mandatory.

+ +
    +
  • label: The text shown to annotators in menus and tree.
  • +
  • uuid: A unique identifier for the flag. Used internally. +Despite its name, it does not have be an UUID, any (unique) string will do.
  • +
  • icon: An icon to be used. The icon needs to be one of +these and should be given as an + upper case string of the form MDI_ICONNAME. The icon named 'flag', for + instance, is used by speciying MDI_FLAG. +
  • +
  • targetClass: Can be either Mention or +Entity and describes to which type these flags can be attached.
  • +
+ +

Guidelines

+<guidelines url="http://example.com/guidelines-1.0" title="My guidelines" version="1.0" /> + +

The above snippet demonstrates how to include a guideline link. The +attribute url is mandatory, title and +version are optional. The URL will be handed over to the system and + opened by a browser. Thus any URL that a browser can open can be supplied here + (most common are http and https links).

+ + +

Example file

+ +

The example below (tailored to do NER annotation) can be found as an XML file in the repository +under +src/test/resources/profile-ner.xml. + +

+<?xml version="1.0" encoding="UTF-8"?>
+<profile xmlns="https://nilsreiter.de/code/corefannotator-1.12.0/profile" name="NER">
+<forbidden>
+  <!-- flags -->
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.AddFlag" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.DeleteFlag" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.UpdateFlag" />
+
+  <!-- entities -->
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToNewEntity" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.RemoveEntities" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.UpdateEntityName" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.RemoveSingletons" />
+  
+  <!-- entity groups -->
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.AddEntityToEntityGroup" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.RemoveEntitiesFromEntityGroup" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.GroupEntities" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.MergeEntities" />
+
+  <!-- misc -->
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.RenameAllEntities" />
+  <operation class="de.unistuttgart.ims.coref.annotator.document.op.Clear" />
+</forbidden>
+<entities>
+  <entity label="PER" color="red" shortcut="p" flags="" />
+  <entity label="LOC" color="green" shortcut="l" flags="" />
+  <entity label="ORG" color="blue" shortcut="o" flags="" />
+  <entity label="OTH" color="yellow" shortcut="x" flags="" />
+</entities>
+<flags>
+  <flag label="deriv" uuid="deriv" icon="MDI_FLAG" targetClass="Mention" />
+  <flag label="part" uuid="part" icon="MDI_FLAG" targetClass="Mention" />
+  <flag label="virtual" uuid="virtual" icon="MDI_FLAG" targetClass="Mention" />
+</flags>
+<preferences>
+  <!-- Default setting is sort entities alphabetically -->
+  <preference key="CFG_ENTITY_SORT_ORDER" value="Alphabet" />
+  <!-- Default setting is sort entities alphabetically -->
+  <preference key="CFG_ENTITY_SORT_DESCENDING" value="false" />
+  <!-- The entity tree is kept in alphabetical order -->
+  <preference key="CFG_KEEP_TREE_SORTED" value="true" />
+  <!--  Flags for coreference should not be created -->
+  <preference key="CFG_CREATE_DEFAULT_FLAGS" value="false" />
+</preferences>
+<guidelines url="https://www.linguistik.hu-berlin.de/de/institut/professuren/korpuslinguistik/forschung/nosta-d/nosta-d-ner-1.5" />
+</profile>
+
+ + + \ No newline at end of file diff --git a/src/main/resources/docs/whatsnew.foot.html b/src/main/resources/docs/whatsnew.foot.html new file mode 100644 index 00000000..691287b6 --- /dev/null +++ b/src/main/resources/docs/whatsnew.foot.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/main/resources/docs/whatsnew.head.html b/src/main/resources/docs/whatsnew.head.html new file mode 100644 index 00000000..4e3570a8 --- /dev/null +++ b/src/main/resources/docs/whatsnew.head.html @@ -0,0 +1,9 @@ + + +CorefAnnotator Help + + +

What's New?

+ +

The changelog is also documented here.

+ diff --git a/src/main/resources/locales/strings.properties b/src/main/resources/locales/strings.properties index 5db568b5..c5e16b07 100644 --- a/src/main/resources/locales/strings.properties +++ b/src/main/resources/locales/strings.properties @@ -8,6 +8,8 @@ action.add_findings_to_new_entity = Create a new entity and add selected finding action.add_findings_to_new_entity.tooltip = Creates a new entity and adds all selected findings to it action.add_mention_flag = Add mention flag action.add_mention_flag.tooltip = Creates a new flag in the current document that can be applied to mentions +action.analyzer = Analyzer +action.analyzer.tooltip = Launches the Analyzer to explore an annotated document action.clear = Clear action.clear.tooltip = Clear findings action.close = Close @@ -44,6 +46,8 @@ action.flag_mention_non_nominal = Non-Nominal action.flag_mention_non_nominal.tooltip = Marks a mention as non-nominal, e.g. for clausal antecedents action.group = Group action.group.tooltip = Form a new entity group that contains the selected entities +action.guidelines = Open guidelines in browser +action.guidelines.tooltip = If guidelines are specified in profile, opens them in a web browser action.help = Help action.merge = Merge action.merge.adjacent_mentions = Merge mentions @@ -80,6 +84,8 @@ action.set_document_language = Set document language action.set_shortcut = Set shortcut action.set_shortcut.tooltip = Set new shortcut to add the selected word(s) as mention to an entity action.show.comments = Show comments +action.show_document_statistics = Show document statistics +action.show_document_statistics.tooltip = Shows simple document statistics action.show.history = Show history action.show.log = Show log action.show_a_selected_mention_in_tree = Show selected mention in tree @@ -92,6 +98,8 @@ action.sort_mentions = Sort by mentions action.sort_mentions.tooltip = Sort by mentions action.sort_lastmodified = Sort by last modified action.sort_lastmodified.tooltip = Sort by last modified +action.sort_position = Sort by position +action.sort_position.tooltip = Sort by position of the first mention of an entity action.sort_revert = Sort descending action.toggle.ask_before_file_overwrite = Ask before overwriting files action.toggle.compare_by_entity_name = Compare by entity name @@ -107,8 +115,8 @@ action.toggle.ignore_singletons = Ignore singletons action.toggle.ignore_singletons.tooltip = Ignores singletons when calculating agreement action.toggle.replace_mention = Overwrite existing mention annotations action.toggle.replace_mention.tooltip = Instead of adding a mention, existing mention annotations get replaced\\(i.e., the mention is moved into a new entity) -action.toggle.show_line_number_in_tree = Show line numbers in tree view -action.toggle.show_line_number_in_tree.tooltip = If enabled, mentions in the tree view are shown with the line number they appear in +action.toggle.show_line_number_in_tree = Show mention location in tree view +action.toggle.show_line_number_in_tree.tooltip = If enabled, mentions in the tree view are shown with the line and segment number(s) they appear in action.toggle.show_text_labels = Show text labels action.toggle.show_text_labels.tooltip = Display textual labels in the tree view action.toggle.show_toc = Show table of contents @@ -125,8 +133,42 @@ action.undo = Undo action.view.decrease_font_size = Decrease font size action.view.increase_font_size = Increase font size action.view.select_font_family = Select font family +analyzer.entities = Entities +analyzer.entity = Entity +analyzer.actions = Analyses +analyzer.actions.DUMMY = +analyzer.actions.Flag = Flags +analyzer.actions.MENTION = Mentions +analyzer.actions.NEIGHBOUR = Neighbours +analyzer.actions.TEXTLOCATION = Location +analyzer.color = Color +analyzer.datatable.mentions = Instance +analyzer.datatable.count = Number +analyzer.groupby = Group by +analyzer.groupby.COVEREDTEXT = Annotated surface +analyzer.groupby.ENTITY = Mentioned entity +analyzer.kwic.center = Annotation +analyzer.kwic.left = Left +analyzer.kwic.right = Right +analyzer.neighbour.direction = Direction +analyzer.neighbour.direction.RIGHT = Right +analyzer.neighbour.direction.LEFT = Left +analyzer.neighbour.unit = Unit +analyzer.neighbour.unit.Entity = Entity +analyzer.neighbour.unit.Mention = Mention +analyzer.neighbour.unit.Token = Token +analyzer.neighbour.unit.Sentence = Sentence +analyzer.plot.rest_category = Rest +analyzer.plot.rest_limit = Group below +analyzer.plot.plot_type = Plot type +analyzer.plot.plot_type.bar = Bar chart +analyzer.plot.plot_type.pie = Pie chart +analyzer.position = Position compare.contextmenu.intersection = Intersection +compare.mode_description.span = Mode: Only spans are compared +compare.mode_description.span_entityname = Mode: Spans and entitynames are compared compare.not_comparable = Selected files do not contain the same text +compare.show_agreement_help = How is this calculated? dialog.annotator_label = Annotator label dialog.annotator_label.tooltip = This label will be displayed in the compare window dialog.cancel = Cancel @@ -141,7 +183,7 @@ dialog.export_as.title = Export as dialog.export_options.context_unit = Measured by dialog.export_options.context_unit.LINE = Line dialog.export_options.context_unit.CHARACTER = Character -dialog.export_options.context_unit.Token = Token +dialog.export_options.context_unit.TOKEN = Token dialog.export_options.context_unit.tooltip = Sets the unit used for collecting the context dialog.export_options.context_width = Context width dialog.export_options.context_width.tooltip = Specifies the left and right context to be exported. If set to 0, the columns are suppressed @@ -158,11 +200,13 @@ dialog.export_options.title = Configure Export dialog.export_options.title_ = Configure Export to {0} dialog.export_options.trim_whitespace = Remove whitespace characters dialog.export_options.trim_whitespace.tooltip = If enabled, space characters at beginning and end of strings will be removed +dialog.export_options.warning.1 = Contexts are currently only displayed for first and last continuous mention elements dialog.file_exists.overwrite = File exists. Overwrite? dialog.language.title = Set document language dialog.language.prompt = Set document language dialog.less = Less dialog.more = More +dialog.open.with.title = Open file using {0} scheme dialog.rename_all.options.FIRST = First dialog.rename_all.options.LAST = Last dialog.rename_all.options.LONGEST = Longest @@ -172,6 +216,9 @@ dialog.rename_entity.prompt = Enter the new name dialog.save_as.title = Save file as ... dialog.select_file = Select file dialog.splash.default = Main +dialog.splash.firsttime = New Version +dialog.splash.firsttime.text =

You have opened version {0} for the first time.

+dialog.splash.firsttime.button = What's new? dialog.splash.import = Import from other formats dialog.splash.recent = Recently opened files dialog.unsaved_changes.message = You have unsaved changes in the document.
What do you want to do? @@ -206,7 +253,7 @@ menu.comments = Comments menu.document = Document menu.edit = Edit menu.edit.entities = Entities -menu.edit.entities.sort = Sort +menu.edit.entities.sort = Sort entities menu.edit.mentions = Mentions menu.entities = Annotated entities menu.entities.candidates = Annotate @@ -220,6 +267,10 @@ menu.flags = Flags menu.help = Help menu.help.help = Help menu.settings = Settings +menu.settings.category.annotation_behaviour = Annotation behaviour +menu.settings.category.compare_view = Compare view +menu.settings.category.misc = Miscellaneous +menu.settings.category.user_interface = User interface menu.tools = Tools menu.tools.proc = Automatic processing menu.view = View @@ -245,12 +296,15 @@ message.wrong_file_version.title = Loading Error message.wrong_file_version.text = This version of the program can only read files encoded in file format version {1}.
This file is saved as version {0}.
Please use the importer labeled {0} to update the file to the current version. message.wrong_file_version.ok = Acknowledge message.wrong_file_version.help = More information +name.ms_excel = Microsoft Excel plugin.tei.import_dialog.include_header = Include TEI header plugin.tei.import_dialog.language.tooltip = If a language is specified, the document will be marked with that language (can be changed later).
If left unspecified, the importer tries to extract an explicitly specified language from the document, by looking for an element langUsage[usage=100]. plugin.tei.import_dialog.ok = Import file plugin.tei.import_dialog.root_selector = Text root selector plugin.tei.import_dialog.root_selector.tooltip = The CSS-like expression entered here can be used to select a portion of the XML document to be extracted.
To ignore the TEI header, "TEI > text" can be used. plugin.tei.import_dialog.title = TEI Import options +search.window.case_insensitive = Case insensitive +search.window.case_insensitive.tooltip = Upper and lower case letters are considered equal search.window.restrict_to_mentions = Mentions only search.window.tab.structure = Annotations search.window.tab.text = Text diff --git a/src/main/resources/locales/strings_de.properties b/src/main/resources/locales/strings_de.properties index a9461b1b..1abcfe4f 100644 --- a/src/main/resources/locales/strings_de.properties +++ b/src/main/resources/locales/strings_de.properties @@ -8,6 +8,8 @@ action.add_findings_to_new_entity = Erzeuge eine neue Entit action.add_findings_to_new_entity.tooltip = Erzeugt eine neue Entität und füge alle ausgewählten Fundstellen hinzu action.add_mention_flag = Neuer Marker für Mentions action.add_mention_flag.tooltip = Fügt einen neuen Marker für Mentions in das aktuelle Dokuemnt hinzu +action.analyzer = Analyzer +action.analyzer.tooltip = Started das Analyzer-Fenster um ein annotiertes Dokument zu untersuchen action.clear = Alles löschen action.clear.tooltip = Fundstellen entfernen action.close = Schließen @@ -43,6 +45,8 @@ action.flag_mention_non_nominal = Nicht-Nominal action.flag_mention_non_nominal.tooltip = Markiert eine Mention als Nicht-Nominal, z.B. für verbale Antezedenten action.group = Gruppieren action.group.tooltip = Erzeuge eine neue Entitätengruppe mit den markierten Entitäten als Teilnehmern +action.guidelines = Öffne Richtlinien im Browser +action.guidelines.tooltip = Öffnet die im Profil angegebene URL im Web-Browser action.help = Hilfe action.merge = Vereinigen action.merge.adjacent_mentions = Mentions vereinigen @@ -78,14 +82,18 @@ action.set_document_language = Setze Dokumentsprache action.set_shortcut = Setze Tastenkürzel action.set_shortcut.tooltip = Einen neuen Shortcut für die Entität festlegen, um neue Mentions schnell hinzufŸgen zu kšnnen action.show.comments = Kommentare anzeigen +action.show_document_statistics = Dokumentstatistik +action.show_document_statistics.tooltip = Zeigt einige einfache Maße zum aktuellen Dokument action.show.history = Zeige Undo-Protokoll action.show.log = Logdatei anzeigen action.show_a_selected_mention_in_tree = Zeigt im Text markierte Mention im Baum action.show_a_selected_mention_in_tree.tooltip = Berührt der Cursor genau eine Mention, kann die Mention direkt im Baum angezeigt werden action.show_mention_in_tree = Im Baum anzeigen -action.sort_alpha = Alphabetisch sortieren -action.sort_mentions = Nach Anzahl der Mentions sortieren -action.sort_lastmodified = Nach zuletzt bearbeitet sortieren +action.sort_alpha = Nach Entitätenname alphabetisch +action.sort_mentions = Nach Anzahl der Mentions +action.sort_lastmodified = Nach zuletzt bearbeitet +action.sort_position = Nach Textposition +action.sort_position.tooltip = Sortiert Entitäten nach der Position der jeweils ersten Mention action.sort_revert = Absteigend sortieren action.toggle.ask_before_file_overwrite = Vor dem Überschreiben von Dateien nachfragen action.toggle.compare_by_entity_name = Vergleich über Entitätennamen @@ -97,10 +105,12 @@ action.toggle.full_tokens = Immer vollst action.toggle.full_tokens.tooltip = Erweitert Annotationen, so dass immer vollständige Tokens annotiert werden action.toggle.ignore_singletons = Singletons ignorieren action.toggle.ignore_singletons.tooltip = Ignoriert singletons für die Berechnung von Übereinstimmung +action.toggle.keep_tree_sorted = Baum sortiert halten +action.toggle.keep_tree_sorted.tooltip = Sorgt dafür, dass sich die Elemente im Baum immer in einer definierten Reihenfolge befinden action.toggle.replace_mention = Ersetzt existierende Mentions action.toggle.replace_mention.tooltip = Anstatt eine neue Mention zu erzeugen, existierende Mentions werden verschoben in eine neue Entität -action.toggle.show_line_number_in_tree = Zeilennummern im Baum anzeigen -action.toggle.show_line_number_in_tree.tooltip = Zeigt Mentions zusammen mit ihren Zeilennummern an +action.toggle.show_line_number_in_tree = Textort im Baum anzeigen +action.toggle.show_line_number_in_tree.tooltip = Zeigt Mentions zusammen mit ihren Zeilen- und Segmentnummern an action.toggle.show_text_labels = Text anzeigen action.toggle.show_text_labels.tooltip = Anzeige von Textbeschreibungen in der Baumansicht action.toggle.trim_whitespace = Leerzeichen entfernen @@ -114,6 +124,36 @@ action.toggle.underline_singletons_in_gray.tooltip = Singletons werden in hellgr action.undo = Rückgängig action.view.decrease_font_size = Schriftgröße verkleinern action.view.increase_font_size = Schriftgröße vergrößern +analyzer.color = Farbe +analyzer.entities = Entitäten +analyzer.actions = Analysen +analyzer.actions.DUMMY = +analyzer.actions.Flag = Marker +analyzer.actions.MENTION = Mentions +analyzer.actions.NEIGHBOUR = Nachbarn +analyzer.actions.TEXTLOCATION = Textort +analyzer.datatable.mentions = Instanz +analyzer.datatable.count = Anzahl +analyzer.groupby = Gruppieren nach +analyzer.groupby.COVEREDTEXT = Textoberfläche +analyzer.groupby.ENTITY = Erwähnter Entität +analyzer.kwic.center = Annotation +analyzer.kwic.left = Links +analyzer.kwic.right = Rechts +analyzer.neighbour.direction = Richtung +analyzer.neighbour.direction.RIGHT = Rechts +analyzer.neighbour.direction.LEFT = Links +analyzer.neighbour.unit = Einheit +analyzer.neighbour.unit.Entity = Entität +analyzer.neighbour.unit.Mention = Mention +analyzer.neighbour.unit.Token = Token +analyzer.neighbour.unit.Sentence = Satz +analyzer.plot.rest_category = Rest +analyzer.plot.rest_limit = Zusammenfassen unterhalb +analyzer.plot.plot_type = Diagrammtyp +analyzer.plot.plot_type.bar = Balkendiagramm +analyzer.plot.plot_type.pie = Kuchendiagramm +analyzer.position = Position compare.not_comparable = Ausgewählte Dateien enthalten nicht den gleichen Text compare.contextmenu.intersection = Schnittmenge dialog.annotator_label = Name @@ -130,7 +170,7 @@ dialog.export_options.auto_open.tooltip = dialog.export_options.context_unit = Gemessen in dialog.export_options.context_unit.LINE = Zeilen dialog.export_options.context_unit.CHARACTER = Zeichen -dialog.export_options.context_unit.Token = Wörtern +dialog.export_options.context_unit.TOKEN = Wörtern dialog.export_options.context_width = Kontextbreite dialog.export_options.ok = Export dialog.export_options.include_line_numbers = Zeilennummern ausgeben @@ -147,6 +187,7 @@ dialog.language.title = Setze Dokumentsprache dialog.language.prompt = Setze Dokumentsprache dialog.less = Weniger dialog.more = Mehr +dialog.open.with.title = Datei aus {0} importieren dialog.rename_all.options.FIRST = Erste dialog.rename_all.options.LAST = Letzte dialog.rename_all.options.LONGEST = Längste @@ -156,6 +197,9 @@ dialog.rename_entity.prompt = Neuen Namen eingeben dialog.save_as.title = Datei speichern unter ... dialog.select_file = Datei dialog.splash.default = Start +dialog.splash.firsttime = Neue Version +dialog.splash.firsttime.text =

Dies ist der erste Start von Version {0}.

+dialog.splash.firsttime.button = Was ist neu? dialog.splash.import = Import aus anderen Formaten dialog.splash.recent = Vorher geöffnete Dateien dialog.unsaved_changes.message = Im geöffneten Dokument gibt es ungespeicherte Änderungen.
Was soll passieren? @@ -187,7 +231,7 @@ menu.comments = Kommentare menu.document = Dokument menu.edit = Bearbeiten menu.edit.entities = Entitäten -menu.edit.entities.sort = Sortieren +menu.edit.entities.sort = Entitäten sortieren menu.edit.mentions = Mentions menu.entities = Entitäten menu.entities.candidates = Annotieren @@ -231,6 +275,8 @@ plugin.tei.import_dialog.ok = Datei importieren plugin.tei.import_dialog.root_selector = Text Selektor plugin.tei.import_dialog.root_selector.tooltip = Diese CSS-Eigenschaft kontrolliert, welche Teile des XML-Dokuments als Annotationsdokument eingelesen werden.
Um z.B. den TEI-Header zu überspringen, kann hier "TEI > text" eingegeben werden. plugin.tei.import_dialog.title = TEI Import Optionen +search.window.case_insensitive = Schreibung ignorieren +search.window.case_insensitive.tooltip = Groß- und kleingeschriebene Buchstaben werden als gleich betrachtet search.window.restrict_to_mentions = Nur Mentions search.window.tab.structure = Annotationen search.window.tab.text = Text diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 4c49e5e1..6fb40936 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -1,21 +1,30 @@ - ${user.home}/.CorefAnnotator.log - de.unistuttgart.ims.coref.annotator.Annotator + de.unistuttgart.ims.coref.annotator.Annotator + - + - - - + + + + + + + - - + + diff --git a/src/main/resources/types-quadrama.xml b/src/main/resources/types-quadrama.xml new file mode 100644 index 00000000..a7b42b4b --- /dev/null +++ b/src/main/resources/types-quadrama.xml @@ -0,0 +1,479 @@ + + + Drama + + 1.2 + Nils Reiter + + + + + + + de.unistuttgart.ims.drama.api.Speaker + + uima.tcas.Annotation + + + Id + + uima.cas.Integer + + + XmlId + + uima.cas.StringArray + + + Figure + @Deprecated + de.unistuttgart.ims.drama.api.Figure + + + CastFigure + + uima.cas.FSArray + de.unistuttgart.ims.drama.api.CastFigure + false + + + + + de.unistuttgart.ims.drama.api.Act + + de.unistuttgart.ims.drama.api.DramaSegment + + + de.unistuttgart.ims.drama.api.Scene + + de.unistuttgart.ims.drama.api.DramaSegment + + + de.unistuttgart.ims.drama.api.LevelSegment + + de.unistuttgart.ims.drama.api.DramaSegment + + + Level + + uima.cas.Integer + + + + + de.unistuttgart.ims.drama.api.Utterance + + uima.tcas.Annotation + + + CastFigure + + de.unistuttgart.ims.drama.api.DiscourseEntity + + + + + de.unistuttgart.ims.drama.api.StageDirection + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.Speech + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.Footnote + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.DramatisPersonae + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.FrontMatter + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.MainMatter + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.Drama + + de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData + + + DramaId + @Deprecated + uima.cas.String + + + Translation + Deprecated. Is this drama a translation? + uima.cas.Boolean + + + CastList + + uima.cas.FSArray + de.unistuttgart.ims.drama.api.CastFigure + false + + + DatePrinted + + uima.cas.Integer + + + DateWritten + + uima.cas.Integer + + + DatePremiere + + uima.cas.Integer + + + Date + + uima.cas.Integer + + + DateTranslation + + uima.cas.Integer + + + + + de.unistuttgart.ims.drama.api.SpeechVerse + + de.unistuttgart.ims.drama.api.Speech + + + de.unistuttgart.ims.drama.api.SpeechProse + + de.unistuttgart.ims.drama.api.Speech + + + de.unistuttgart.ims.drama.api.Figure + Represents one figure in the play. Each figure should + only have one Figure annotation (and multiple Speaker annotations) + uima.tcas.Annotation + + + Id + + uima.cas.Integer + + + XmlId + + uima.cas.String + + + Description + + de.unistuttgart.ims.drama.api.FigureDescription + + + Name + + de.unistuttgart.ims.drama.api.FigureName + + + Gender + + uima.cas.String + + + Reference + The reference string for a figure is the string in the + Dramatis Personae, up to and excluding the first punctuation sign. + uima.cas.String + + + + + de.unistuttgart.ims.drama.api.FigureType + This annotations represents the assignment of a figure + to a type. A figure can be assigned to multiple types, we add + multiple annotations then. + uima.tcas.Annotation + + + TypeClass + The class of figure type + uima.cas.String + + + TypeValue + The value of the figure type + uima.cas.String + + + + + de.unistuttgart.ims.drama.api.FigureMention + + de.unistuttgart.ims.drama.api.Mention + + + de.unistuttgart.ims.drama.api.SpeakerFigure + @Deprecated + +This type can be used to add figures on the fly, that are not declared in the dramatis personae. + de.unistuttgart.ims.drama.api.Figure + + + de.unistuttgart.ims.drama.api.FigureDescription + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.FigureName + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.DramaSegment + + uima.tcas.Annotation + + + Number + + uima.cas.Integer + + + Regular + Is this a regular segment? + uima.cas.Boolean + + + + + de.unistuttgart.ims.drama.api.Heading + + uima.tcas.Annotation + + + de.unistuttgart.ims.drama.api.SceneHeading + + de.unistuttgart.ims.drama.api.Heading + + + de.unistuttgart.ims.drama.api.ActHeading + + de.unistuttgart.ims.drama.api.Heading + + + de.unistuttgart.ims.drama.api.Field + @Deprecated + uima.tcas.Annotation + + + Name + + uima.cas.String + + + Amount + + uima.cas.Double + + + + + de.unistuttgart.ims.drama.api.Person + Represents a (real) person + de.unistuttgart.ims.drama.api.Metadatum + + + Name + The full name of the person + uima.cas.String + + + Pnd + The entry in the person norm database + uima.cas.String + + + + + de.unistuttgart.ims.drama.api.Author + A person who is author of the drama + de.unistuttgart.ims.drama.api.Person + + + de.unistuttgart.ims.drama.api.Translator + A person who is a translator of the drama + de.unistuttgart.ims.drama.api.Person + + + de.unistuttgart.ims.drama.api.Metadatum + super type for all kinds of meta data + uima.cas.TOP + + + Source + Describes the source of this meta datum + uima.cas.String + + + + + de.unistuttgart.ims.drama.api.Date + Describes a calendar date + de.unistuttgart.ims.drama.api.Metadatum + + + Year + The year of the date + uima.cas.Integer + + + + + de.unistuttgart.ims.drama.api.DateWritten + The date a drama was written + de.unistuttgart.ims.drama.api.Date + + + de.unistuttgart.ims.drama.api.DatePrint + The date a drama was written + de.unistuttgart.ims.drama.api.Date + + + de.unistuttgart.ims.drama.api.DatePremiere + The date a drama was written + de.unistuttgart.ims.drama.api.Date + + + de.unistuttgart.ims.drama.api.DateReference + The date a drama was written + de.unistuttgart.ims.drama.api.Date + + + de.unistuttgart.ims.drama.api.LevelSegmentHeading + + de.unistuttgart.ims.drama.api.Heading + + + de.unistuttgart.ims.drama.api.CastFigure + + de.unistuttgart.ims.drama.api.DiscourseEntity + + + XmlId + + uima.cas.StringArray + false + + + Names + + uima.cas.StringArray + + + Gender + + uima.cas.String + + + Age + + uima.cas.String + + + + + de.unistuttgart.ims.drama.api.DiscourseEntity + + uima.cas.TOP + + + DisplayName + + uima.cas.String + + + + + de.unistuttgart.ims.drama.api.Mention + + uima.tcas.Annotation + + + Entity + + uima.cas.FSArray + de.unistuttgart.ims.drama.api.DiscourseEntity + false + + + + + de.unistuttgart.quadrama.io.core.type.HTMLAnnotation + + de.unistuttgart.quadrama.io.core.type.XMLElement + + + de.unistuttgart.quadrama.io.core.type.XMLElement + + uima.tcas.Annotation + + + Tag + + uima.cas.String + + + Id + + uima.cas.String + + + Cls + + uima.cas.String + + + Selector + + uima.cas.String + + + Attributes + + uima.cas.String + + + + + de.unistuttgart.quadrama.io.core.type.XMLParsingDescription + + uima.cas.TOP + + + Encoding + + uima.cas.String + + + XmlDeclarations + + uima.cas.StringArray + false + + + + + diff --git a/src/main/resources/types-v1.xml b/src/main/resources/types-v1.xml index 2835397e..6d952059 100644 --- a/src/main/resources/types-v1.xml +++ b/src/main/resources/types-v1.xml @@ -142,6 +142,38 @@ + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIElement + Root type for TEI markup representation + uima.tcas.Annotation + + + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIHeader + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIElement + + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIText + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIElement + + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIBody + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIElement + + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIDiv + + de.unistuttgart.ims.coref.annotator.api.v1.tei.TEIElement + de.unistuttgart.ims.coref.annotator.api.v1.Comment diff --git a/src/main/resources/types-v2.xml b/src/main/resources/types-v2.xml new file mode 100644 index 00000000..7934512a --- /dev/null +++ b/src/main/resources/types-v2.xml @@ -0,0 +1,875 @@ + + + + + + Coref Annotator + + + + + + + + 2 + + + + Nils Reiter + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Flag + + + + A flag template + + + + uima.cas.TOP + + + + + + + + + + + + Label + + + + The UI label + + + + uima.cas.String + + + + + + + + + + + + TargetClass + + + + The class this flag can be applied to + + + + uima.cas.String + + + + + + + + + + + Icon + + + + + + + + uima.cas.String + + + + + + + + + Uuid + + + + uima.cas.String + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Segment + + + + + + + + uima.tcas.Annotation + + + + + + + + + + + Label + + + + + + + + uima.cas.String + + + + + + + + + + + + Flags + + + + + + + + uima.cas.StringArray + + + + false + + + + + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Mention + + + + A mention in the text. + + + + uima.cas.TOP + + + + + + + + + + + + Entity + + + + the entity that this mention belongs to. + + + + de.unistuttgart.ims.coref.annotator.api.v2.Entity + + + + + + + + + + + + Flags + + + + An array that stores flags + + + + uima.cas.FSList + + + + de.unistuttgart.ims.coref.annotator.api.v2.Flag + + + + false + + + + + + + + + + + + Surface + + + + + + + + uima.cas.FSArray + + + + de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface + + + + false + + + + + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface + + + + A part of the annotation of a mention + + + + uima.tcas.Annotation + + + + + + + + + + + + Mention + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Mention + + + + + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Entity + + + + An entity, that is not linked to a specific text segment. + + + + uima.cas.TOP + + + + + + + + + + + + Label + + + + A label of the entity, shown in the tree view. + + + + uima.cas.String + + + + + + + + + + + + Color + + + + The color used for underlining + + + + uima.cas.Integer + + + + + + + + + + + + Key + + + + The key for keyboard based annotation + + + + uima.cas.String + + + + + + + + + + + + Flags + + + + An array that stores flags + + + + uima.cas.FSList + + + + de.unistuttgart.ims.coref.annotator.api.v2.Flag + + + + false + + + + + + + + + + + + Hidden + + + + A boolean to indicate whether this entity has been hidden + + + + uima.cas.Boolean + + + + + + + + + + + + XmlId + + + + A field to store the xml id of the entity, if it has been loaded from TEI/XML + + + + uima.cas.String + + + + + + + + + + + + Members + + + + An array containin the members of the group + + + + uima.cas.FSArray + + + + de.unistuttgart.ims.coref.annotator.api.v2.Entity + + + + false + + + + + + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Comment + + + + + + + + uima.cas.TOP + + + + + + + + + + + + Author + + + + + + + + uima.cas.String + + + + + + + + + + + + Value + + + + + + + + uima.cas.String + + + + + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.MentionComment + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Comment + + + + + + + + + + + + Mention + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Mention + + + + + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.AnnotationComment + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Comment + + + + + + + + + + + + Annotation + + + + + + + + uima.tcas.Annotation + + + + + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.CommentAnchor + + + + + + + + uima.tcas.Annotation + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.Line + + + + + + + + uima.tcas.Annotation + + + + + + + + + + + + Number + + + + + + + + uima.cas.Integer + + + + + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIElement + + + + Root type for TEI markup representation + + + + uima.tcas.Annotation + + + + + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIHeader + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIElement + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIText + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIElement + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIBody + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIElement + + + + + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIDiv + + + + + + + + de.unistuttgart.ims.coref.annotator.api.v2.tei.TEIElement + + + + + + + + + + + + diff --git a/src/main/xsd/profile.xsd b/src/main/xsd/profile.xsd index 1484fa24..fbcf9bdf 100644 --- a/src/main/xsd/profile.xsd +++ b/src/main/xsd/profile.xsd @@ -43,6 +43,14 @@ + + + + + + + @@ -50,7 +58,7 @@ - + @@ -63,10 +71,10 @@ - - - - + + + + diff --git a/src/test/java/de/unistuttgart/ims/coref/annotator/TestUtil.java b/src/test/java/de/unistuttgart/ims/coref/annotator/TestUtil.java index 91331e0d..d4bb6da0 100644 --- a/src/test/java/de/unistuttgart/ims/coref/annotator/TestUtil.java +++ b/src/test/java/de/unistuttgart/ims/coref/annotator/TestUtil.java @@ -10,6 +10,8 @@ import org.apache.uima.jcas.tcas.Annotation; import org.junit.Test; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; + public class TestUtil { @Test public void testRemoveFromStringArray() throws UIMAException { @@ -18,7 +20,7 @@ public void testRemoveFromStringArray() throws UIMAException { arr = new StringArray(jcas, 2); arr.set(0, "Hello"); arr.set(1, "World"); - newArray = Util.removeFrom(jcas, arr, "Hello"); + newArray = UimaUtil.removeFrom(jcas, arr, "Hello"); assertEquals(1, newArray.size()); assertEquals("World", newArray.get(0)); @@ -28,43 +30,43 @@ public void testRemoveFromStringArray() throws UIMAException { public void testExtend() throws UIMAException { JCas jcas = JCasFactory.createText("The dog barks"); Annotation a = AnnotationFactory.createAnnotation(jcas, 5, 6, Annotation.class); - Util.extend(a); + UimaUtil.extend(a); assertEquals(4, a.getBegin()); a = AnnotationFactory.createAnnotation(jcas, 0, 3, Annotation.class); - Util.extend(a); + UimaUtil.extend(a); assertEquals(0, a.getBegin()); assertEquals(3, a.getEnd()); assertEquals("The", a.getCoveredText()); a = AnnotationFactory.createAnnotation(jcas, 0, 2, Annotation.class); - Util.extend(a); + UimaUtil.extend(a); assertEquals(0, a.getBegin()); assertEquals(3, a.getEnd()); a = AnnotationFactory.createAnnotation(jcas, 1, 2, Annotation.class); - Util.extend(a); + UimaUtil.extend(a); assertEquals(0, a.getBegin()); assertEquals(3, a.getEnd()); a = AnnotationFactory.createAnnotation(jcas, 10, 11, Annotation.class); - Util.extend(a); + UimaUtil.extend(a); assertEquals(8, a.getBegin()); assertEquals(13, a.getEnd()); assertEquals("barks", a.getCoveredText()); a = AnnotationFactory.createAnnotation(jcas, 8, 13, Annotation.class); - Util.extend(a); + UimaUtil.extend(a); assertEquals(8, a.getBegin()); assertEquals(13, a.getEnd()); a = AnnotationFactory.createAnnotation(jcas, 12, 13, Annotation.class); - Util.extend(a); + UimaUtil.extend(a); assertEquals(8, a.getBegin()); assertEquals(13, a.getEnd()); a = AnnotationFactory.createAnnotation(jcas, 8, 9, Annotation.class); - Util.extend(a); + UimaUtil.extend(a); assertEquals(8, a.getBegin()); assertEquals(13, a.getEnd()); diff --git a/src/test/java/de/unistuttgart/ims/coref/annotator/document/TestCoreferenceModel.java b/src/test/java/de/unistuttgart/ims/coref/annotator/document/TestCoreferenceModel.java index e91b11b7..55fd49c4 100644 --- a/src/test/java/de/unistuttgart/ims/coref/annotator/document/TestCoreferenceModel.java +++ b/src/test/java/de/unistuttgart/ims/coref/annotator/document/TestCoreferenceModel.java @@ -12,11 +12,11 @@ import org.apache.uima.fit.factory.JCasFactory; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; -import org.apache.uima.jcas.cas.StringArray; +import org.apache.uima.jcas.cas.EmptyFSList; import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.api.multimap.set.MutableSetMultimap; -import org.eclipse.collections.api.set.ImmutableSet; +import org.eclipse.collections.api.set.sorted.ImmutableSortedSet; import org.eclipse.collections.impl.factory.Lists; import org.eclipse.collections.impl.factory.Sets; import org.junit.Before; @@ -25,14 +25,12 @@ import de.unistuttgart.ims.coref.annotator.Constants; import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.DetachedMentionPart; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.EntityGroup; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.Event.Type; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToEntity; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToNewEntity; -import de.unistuttgart.ims.coref.annotator.document.op.AttachPart; import de.unistuttgart.ims.coref.annotator.document.op.GroupEntities; import de.unistuttgart.ims.coref.annotator.document.op.MergeEntities; import de.unistuttgart.ims.coref.annotator.document.op.MergeMentions; @@ -41,6 +39,7 @@ import de.unistuttgart.ims.coref.annotator.document.op.RemoveEntities; import de.unistuttgart.ims.coref.annotator.document.op.RemoveEntitiesFromEntityGroup; import de.unistuttgart.ims.coref.annotator.document.op.RemoveMention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; public class TestCoreferenceModel { @@ -76,7 +75,7 @@ public void testEditAddMentionsToNewEntity() { assertTrue(cmodel.getMentions(2).isEmpty()); assertTrue(cmodel.getMentions(3).isEmpty()); - Mention m = JCasUtil.selectByIndex(jcas, Mention.class, 0); + Mention m = jcas.getIndexedFSs(Mention.class).iterator().next(); assertNotNull(m.getEntity()); assertNotNull(m.getEntity().getLabel()); assertNotNull(m.getEntity().getColor()); @@ -103,7 +102,7 @@ public void testEditAddMentionsToExistingEntity() { Entity e = new Entity(jcas); e.setLabel("Test"); e.setColor(0); - e.setFlags(new StringArray(jcas, 0)); + e.setFlags(new EmptyFSList(jcas)); e.addToIndexes(); model.edit(new AddMentionsToEntity(e, new Span(1, 3))); @@ -115,7 +114,7 @@ public void testEditAddMentionsToExistingEntity() { assertFalse(cmodel.getMentions(2).isEmpty()); assertTrue(cmodel.getMentions(3).isEmpty()); - Mention m = JCasUtil.selectByIndex(jcas, Mention.class, 0); + Mention m = UimaUtil.selectMentionByIndex(jcas, 0); assertEquals(e, m.getEntity()); assertEquals(2, listener.events.size()); @@ -135,45 +134,6 @@ public void testEditAddMentionsToExistingEntity() { } - @Test - public void testEditAttachPart() { - Mention m = cmodel.createMention(1, 3); - - model.edit(new AttachPart(m, new Span(4, 5))); - - assertTrue(JCasUtil.exists(jcas, Mention.class)); - assertTrue(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(1, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(1, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - assertTrue(cmodel.getMentions(0).isEmpty()); - assertFalse(cmodel.getMentions(1).isEmpty()); - assertFalse(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertFalse(cmodel.getMentions(4).isEmpty()); - assertTrue(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - - assertEquals(Lists.immutable.of(Type.Init, Type.Add), listener.events.collect(ev -> ev.eventType)); - - model.undo(); - - assertTrue(JCasUtil.exists(jcas, Mention.class)); - assertFalse(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(1, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(0, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - - assertTrue(cmodel.getMentions(0).isEmpty()); - assertFalse(cmodel.getMentions(1).isEmpty()); - assertFalse(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertTrue(cmodel.getMentions(4).isEmpty()); - assertTrue(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - - assertEquals(Lists.immutable.of(Type.Init, Type.Add, Type.Remove), listener.events.collect(ev -> ev.eventType)); - - } - @Test public void testEditRemoveMention() { Mention m = cmodel.createMention(1, 3); @@ -205,57 +165,6 @@ public void testEditRemoveMention() { } - @Test - public void testEditRemoveMention2() { - Mention m = cmodel.createMention(1, 3); - DetachedMentionPart dmp = cmodel.createDetachedMentionPart(4, 6); - m.setDiscontinuous(dmp); - dmp.setMention(m); - - assertTrue(JCasUtil.exists(jcas, Mention.class)); - assertTrue(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(1, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(1, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - assertTrue(cmodel.getMentions(0).isEmpty()); - assertFalse(cmodel.getMentions(1).isEmpty()); - assertFalse(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertFalse(cmodel.getMentions(4).isEmpty()); - assertFalse(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - - model.edit(new RemoveMention(m)); - - assertEquals(Lists.immutable.of(Type.Init, Type.Remove, Type.Remove), - listener.events.collect(ev -> ev.eventType)); - - assertFalse(JCasUtil.exists(jcas, Mention.class)); - assertFalse(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(0, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(0, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - assertTrue(cmodel.getMentions(0).isEmpty()); - assertTrue(cmodel.getMentions(1).isEmpty()); - assertTrue(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertTrue(cmodel.getMentions(4).isEmpty()); - assertTrue(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - - model.undo(); - - assertTrue(JCasUtil.exists(jcas, Mention.class)); - assertTrue(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(1, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(1, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - assertTrue(cmodel.getMentions(0).isEmpty()); - assertFalse(cmodel.getMentions(1).isEmpty()); - assertFalse(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertFalse(cmodel.getMentions(4).isEmpty()); - assertFalse(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - } - @Test public void testEditMergeEntities() { model.edit(new AddMentionsToNewEntity(new Span(0, 1), new Span(2, 3))); @@ -303,7 +212,7 @@ public void testEditMoveEntities() { model.edit(new AddMentionsToNewEntity(new Span(4, 5), new Span(6, 7))); MutableList entities = Lists.mutable.withAll(JCasUtil.select(jcas, Entity.class)); - Mention m = ((Mention) cmodel.getMentions(0).iterator().next()); + Mention m = (cmodel.getMentions(0).iterator().next()); assertNotEquals(entities.get(1), m.getEntity()); assertTrue(JCasUtil.exists(jcas, Mention.class)); assertTrue(JCasUtil.exists(jcas, Entity.class)); @@ -345,17 +254,16 @@ public void testRemovEntityFromGroup() { assertTrue(JCasUtil.exists(jcas, Mention.class)); assertEquals(2, JCasUtil.select(jcas, Entity.class).size()); assertEquals(2, JCasUtil.select(jcas, Mention.class).size()); - assertFalse(JCasUtil.exists(jcas, EntityGroup.class)); - model.edit(new GroupEntities(e1, e2)); + GroupEntities ge = new GroupEntities(e1, e2); + model.edit(ge); assertTrue(JCasUtil.exists(jcas, Entity.class)); assertTrue(JCasUtil.exists(jcas, Mention.class)); assertEquals(3, JCasUtil.select(jcas, Entity.class).size()); assertEquals(2, JCasUtil.select(jcas, Mention.class).size()); - assertTrue(JCasUtil.exists(jcas, EntityGroup.class)); - EntityGroup eg = JCasUtil.select(jcas, EntityGroup.class).iterator().next(); + Entity eg = ge.getEntityGroup(); assertEquals(2, eg.getMembers().size()); model.edit(new RemoveEntitiesFromEntityGroup(eg, e1)); @@ -364,9 +272,7 @@ public void testRemovEntityFromGroup() { assertTrue(JCasUtil.exists(jcas, Mention.class)); assertEquals(3, JCasUtil.select(jcas, Entity.class).size()); assertEquals(2, JCasUtil.select(jcas, Mention.class).size()); - assertTrue(JCasUtil.exists(jcas, EntityGroup.class)); - eg = JCasUtil.select(jcas, EntityGroup.class).iterator().next(); assertEquals(1, eg.getMembers().size()); model.undo(); @@ -375,88 +281,19 @@ public void testRemovEntityFromGroup() { assertTrue(JCasUtil.exists(jcas, Mention.class)); assertEquals(3, JCasUtil.select(jcas, Entity.class).size()); assertEquals(2, JCasUtil.select(jcas, Mention.class).size()); - assertTrue(JCasUtil.exists(jcas, EntityGroup.class)); - eg = JCasUtil.select(jcas, EntityGroup.class).iterator().next(); assertEquals(2, eg.getMembers().size()); } - @Test - public void testSequence1() { - Entity e = cmodel.createEntity("test"); - Mention m = cmodel.createMention(1, 3); - m.setEntity(e); - - model.edit(new AttachPart(m, new Span(4, 5))); - - assertTrue(JCasUtil.exists(jcas, Mention.class)); - assertTrue(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(1, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(1, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - assertTrue(cmodel.getMentions(0).isEmpty()); - assertFalse(cmodel.getMentions(1).isEmpty()); - assertFalse(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertFalse(cmodel.getMentions(4).isEmpty()); - assertTrue(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - - model.edit(new RemoveMention(m)); - - assertFalse(JCasUtil.exists(jcas, Mention.class)); - assertFalse(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(0, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(0, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - assertTrue(cmodel.getMentions(0).isEmpty()); - assertTrue(cmodel.getMentions(1).isEmpty()); - assertTrue(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertTrue(cmodel.getMentions(4).isEmpty()); - assertTrue(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - - model.undo(); - - assertTrue(JCasUtil.exists(jcas, Mention.class)); - assertTrue(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(1, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(1, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - assertTrue(cmodel.getMentions(0).isEmpty()); - assertFalse(cmodel.getMentions(1).isEmpty()); - assertFalse(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertFalse(cmodel.getMentions(4).isEmpty()); - assertTrue(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - - model.undo(); - - assertTrue(JCasUtil.exists(jcas, Mention.class)); - assertFalse(JCasUtil.exists(jcas, DetachedMentionPart.class)); - assertEquals(1, JCasUtil.select(jcas, Mention.class).size()); - assertEquals(0, JCasUtil.select(jcas, DetachedMentionPart.class).size()); - assertTrue(cmodel.getMentions(0).isEmpty()); - assertFalse(cmodel.getMentions(1).isEmpty()); - assertFalse(cmodel.getMentions(2).isEmpty()); - assertTrue(cmodel.getMentions(3).isEmpty()); - assertTrue(cmodel.getMentions(4).isEmpty()); - assertTrue(cmodel.getMentions(5).isEmpty()); - assertTrue(cmodel.getMentions(6).isEmpty()); - - assertEquals(0, model.getHistory().size()); - } - @Test public void testRemoveDuplicates() { - model.edit(new AddMentionsToNewEntity(new Span(1, 3), new Span(1, 3), new Span(2, 4))); + Entity e = model.edit(new AddMentionsToNewEntity(new Span(1, 3), new Span(1, 3), new Span(2, 4))).getEntity(); assertTrue(JCasUtil.exists(jcas, Mention.class)); assertTrue(JCasUtil.exists(jcas, Entity.class)); assertEquals(3, JCasUtil.select(jcas, Mention.class).size()); assertEquals(1, JCasUtil.select(jcas, Entity.class).size()); - Entity e = JCasUtil.selectSingle(jcas, Entity.class); - model.edit(new RemoveDuplicateMentionsInEntities(e)); assertTrue(JCasUtil.exists(jcas, Mention.class)); @@ -474,18 +311,19 @@ public void testRemoveDuplicates() { @Test public void testRemoveEntityThatIsInGroup() { - model.edit(new AddMentionsToNewEntity(new Span(0, 1))); - model.edit(new AddMentionsToNewEntity(new Span(1, 2))); + Entity e1 = model.edit(new AddMentionsToNewEntity(new Span(0, 1))).getEntity(); + Entity e2 = model.edit(new AddMentionsToNewEntity(new Span(1, 2))).getEntity(); ImmutableList entities = Lists.immutable.withAll(JCasUtil.select(jcas, Entity.class)); ImmutableList mentions = Lists.immutable.withAll(JCasUtil.select(jcas, Mention.class)); - assertEquals(entities.getFirst(), mentions.getFirst().getEntity()); - assertEquals(entities.getLast(), mentions.getLast().getEntity()); + assertEquals(e2, mentions.getFirst().getEntity()); + assertEquals(e1, mentions.getLast().getEntity()); - model.edit(new GroupEntities(entities.get(0), entities.get(1))); + GroupEntities ge = new GroupEntities(entities.get(0), entities.get(1)); + model.edit(ge); - EntityGroup group = JCasUtil.select(jcas, EntityGroup.class).iterator().next(); + Entity group = ge.getEntityGroup(); assertEquals(2, group.getMembers().size()); assertEquals(entities.get(0), group.getMembers(0)); assertEquals(entities.get(1), group.getMembers(1)); @@ -513,8 +351,9 @@ public void testSequence2() { ImmutableList entities = Lists.immutable.withAll(JCasUtil.select(jcas, Entity.class)); ImmutableList mentions = Lists.immutable.withAll(JCasUtil.select(jcas, Mention.class)); - model.edit(new GroupEntities(entities.get(0), entities.get(1))); - EntityGroup group = JCasUtil.selectSingle(jcas, EntityGroup.class); + GroupEntities ge = new GroupEntities(entities.get(0), entities.get(1)); + model.edit(ge); + Entity group = ge.getEntityGroup(); model.edit(new MoveMentionsToEntity(group, mentions.get(2))); @@ -531,9 +370,9 @@ public void testMergeMentions() { Entity e = JCasUtil.selectSingle(jcas, Entity.class); model.edit(new AddMentionsToEntity(e, new Span(4, 6))); - Mention m1 = JCasUtil.selectByIndex(jcas, Mention.class, 0); - Mention m2 = JCasUtil.selectByIndex(jcas, Mention.class, 1); - ImmutableSet em = model.getCoreferenceModel().get(e); + Mention m1 = UimaUtil.selectMentionByIndex(jcas, 0); + Mention m2 = UimaUtil.selectMentionByIndex(jcas, 1); + ImmutableSortedSet em = model.getCoreferenceModel().get(e); assertEquals(2, em.size()); assertEquals(2, JCasUtil.select(jcas, Mention.class).size()); diff --git a/src/test/java/de/unistuttgart/ims/coref/annotator/document/TestFlagModel.java b/src/test/java/de/unistuttgart/ims/coref/annotator/document/TestFlagModel.java index facc82f7..21d94f83 100644 --- a/src/test/java/de/unistuttgart/ims/coref/annotator/document/TestFlagModel.java +++ b/src/test/java/de/unistuttgart/ims/coref/annotator/document/TestFlagModel.java @@ -10,16 +10,16 @@ import org.apache.uima.fit.factory.JCasFactory; import org.apache.uima.fit.util.JCasUtil; import org.apache.uima.jcas.JCas; -import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.api.factory.Lists; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import de.unistuttgart.ims.coref.annotator.Constants; import de.unistuttgart.ims.coref.annotator.Span; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Flag; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Flag; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; import de.unistuttgart.ims.coref.annotator.document.op.AddFlag; import de.unistuttgart.ims.coref.annotator.document.op.AddMentionsToNewEntity; import de.unistuttgart.ims.coref.annotator.document.op.ToggleGenericFlag; @@ -84,10 +84,11 @@ public void testAddFlag() throws ClassNotFoundException { @Test public void testDeleteFlag() { - model.edit(new AddFlag(Mention.class)); + Flag f = model.edit(new AddFlag(Mention.class)).getAddedFlag(); + f.setUuid("bla"); model.edit(new AddMentionsToNewEntity(new Span(0, 1))); Mention m = JCasUtil.select(jcas, Mention.class).iterator().next(); - model.edit(new ToggleGenericFlag("", Lists.fixedSize.of(m))); + model.edit(new ToggleGenericFlag(f, Lists.fixedSize.of(m))); } } diff --git a/quadrama/test/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TestRoundTrip.java b/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TestRoundTrip.java similarity index 100% rename from quadrama/test/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TestRoundTrip.java rename to src/test/java/de/unistuttgart/ims/coref/annotator/plugin/quadrama/tei/TestRoundTrip.java diff --git a/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TestMapCorefToXmlElements.java b/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TestMapCorefToXmlElements.java index 240a185a..1a956dc1 100644 --- a/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TestMapCorefToXmlElements.java +++ b/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TestMapCorefToXmlElements.java @@ -7,7 +7,6 @@ import org.apache.uima.UIMAException; import org.apache.uima.analysis_engine.AnalysisEngineProcessException; import org.apache.uima.fit.factory.AnalysisEngineFactory; -import org.apache.uima.fit.factory.AnnotationFactory; import org.apache.uima.fit.factory.JCasFactory; import org.apache.uima.fit.pipeline.SimplePipeline; import org.apache.uima.fit.util.JCasUtil; @@ -16,8 +15,9 @@ import org.junit.Before; import org.junit.Test; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.uima.UimaUtil; import de.unistuttgart.ims.uima.io.xml.type.XMLElement; public class TestMapCorefToXmlElements { @@ -29,15 +29,15 @@ public void setUp() throws UIMAException { jcas = JCasFactory.createText("the dog barks"); entity = new Entity(jcas); entity.addToIndexes(); - Mention m = AnnotationFactory.createAnnotation(jcas, 0, 1, Mention.class); + Mention m = UimaUtil.createMention(jcas, 0, 1); m.setEntity(entity); - m = AnnotationFactory.createAnnotation(jcas, 1, 2, Mention.class); + m = UimaUtil.createMention(jcas, 1, 2); m.setEntity(entity); entity2 = new Entity(jcas); entity2.addToIndexes(); - AnnotationFactory.createAnnotation(jcas, 2, 3, Mention.class).setEntity(entity2); - AnnotationFactory.createAnnotation(jcas, 3, 4, Mention.class).setEntity(entity2); + UimaUtil.createMention(jcas, 2, 3).setEntity(entity2); + UimaUtil.createMention(jcas, 3, 4).setEntity(entity2); } @@ -58,22 +58,22 @@ public void testGeneratedIdFromScratch() throws AnalysisEngineProcessException, assertEquals("rs", e.getTag()); assertEquals(0, e.getBegin()); assertEquals(1, e.getEnd()); - assertEquals(" ref=\"#e1\"", e.getAttributes()); + assertEquals(" ref=\"#e2\"", e.getAttributes()); e = JCasUtil.selectByIndex(jcas, XMLElement.class, 1); assertEquals("rs", e.getTag()); assertEquals(1, e.getBegin()); assertEquals(2, e.getEnd()); - assertEquals(" ref=\"#e1\"", e.getAttributes()); + assertEquals(" ref=\"#e2\"", e.getAttributes()); e = JCasUtil.selectByIndex(jcas, XMLElement.class, 2); assertEquals("rs", e.getTag()); - assertEquals(" ref=\"#e2\"", e.getAttributes()); + assertEquals(" ref=\"#e1\"", e.getAttributes()); e = JCasUtil.selectByIndex(jcas, XMLElement.class, 3); assertEquals("rs", e.getTag()); - assertEquals(" ref=\"#e2\"", e.getAttributes()); + assertEquals(" ref=\"#e1\"", e.getAttributes()); } @Test @@ -87,22 +87,22 @@ public void testGeneratedIdFromLabel() throws AnalysisEngineProcessException, Re assertEquals("rs", e.getTag()); assertEquals(0, e.getBegin()); assertEquals(1, e.getEnd()); - assertEquals(" ref=\"#dog\"", e.getAttributes()); + assertEquals(" ref=\"#dog2\"", e.getAttributes()); e = JCasUtil.selectByIndex(jcas, XMLElement.class, 1); assertEquals("rs", e.getTag()); assertEquals(1, e.getBegin()); assertEquals(2, e.getEnd()); - assertEquals(" ref=\"#dog\"", e.getAttributes()); + assertEquals(" ref=\"#dog2\"", e.getAttributes()); e = JCasUtil.selectByIndex(jcas, XMLElement.class, 2); assertEquals("rs", e.getTag()); - assertEquals(" ref=\"#dog2\"", e.getAttributes()); + assertEquals(" ref=\"#dog\"", e.getAttributes()); e = JCasUtil.selectByIndex(jcas, XMLElement.class, 3); assertEquals("rs", e.getTag()); - assertEquals(" ref=\"#dog2\"", e.getAttributes()); + assertEquals(" ref=\"#dog\"", e.getAttributes()); } diff --git a/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TestTeiReader.java b/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TestTeiReader.java index 3df1afad..d1281d34 100644 --- a/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TestTeiReader.java +++ b/src/test/java/de/unistuttgart/ims/coref/annotator/plugin/tei/TestTeiReader.java @@ -15,8 +15,8 @@ import org.apache.uima.jcas.JCas; import org.junit.Test; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; -import de.unistuttgart.ims.coref.annotator.api.v1.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; public class TestTeiReader { @Test diff --git a/src/test/java/de/unistuttgart/ims/coref/annotator/uima/TestCoNLL2012Reader.java b/src/test/java/de/unistuttgart/ims/coref/annotator/uima/TestCoNLL2012Reader.java index b61b65bb..59c3d77b 100644 --- a/src/test/java/de/unistuttgart/ims/coref/annotator/uima/TestCoNLL2012Reader.java +++ b/src/test/java/de/unistuttgart/ims/coref/annotator/uima/TestCoNLL2012Reader.java @@ -16,7 +16,7 @@ import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; -import de.unistuttgart.ims.coref.annotator.api.v1.Entity; +import de.unistuttgart.ims.coref.annotator.api.v2.Entity; public class TestCoNLL2012Reader { diff --git a/src/test/java/de/unistuttgart/ims/coref/annotator/uima/TestUimaUtil.java b/src/test/java/de/unistuttgart/ims/coref/annotator/uima/TestUimaUtil.java new file mode 100644 index 00000000..0f9e5cf8 --- /dev/null +++ b/src/test/java/de/unistuttgart/ims/coref/annotator/uima/TestUimaUtil.java @@ -0,0 +1,107 @@ +package de.unistuttgart.ims.coref.annotator.uima; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.apache.uima.cas.CASException; +import org.apache.uima.fit.factory.AnnotationFactory; +import org.apache.uima.fit.factory.JCasFactory; +import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.FSArray; +import org.apache.uima.resource.ResourceInitializationException; +import org.junit.Before; +import org.junit.Test; + +import de.unistuttgart.ims.coref.annotator.api.v2.Mention; +import de.unistuttgart.ims.coref.annotator.api.v2.MentionSurface; + +public class TestUimaUtil { + + JCas jcas; + + @Before + public void setUp() throws ResourceInitializationException, CASException { + jcas = JCasFactory.createText("abcdefghijklmnopqrstuvxyz"); + } + + @Test + public void testRemoveMentionSurface() { + MentionSurface[] ms = new MentionSurface[] { + AnnotationFactory.createAnnotation(jcas, 0, 2, MentionSurface.class), + AnnotationFactory.createAnnotation(jcas, 3, 5, MentionSurface.class), + AnnotationFactory.createAnnotation(jcas, 6, 8, MentionSurface.class) }; + + Mention m = new Mention(jcas); + m.addToIndexes(); + m.setSurface(new FSArray(jcas, 3)); + m.setSurface(0, ms[0]); + m.setSurface(1, ms[1]); + m.setSurface(2, ms[2]); + + assertEquals(3, m.getSurface().size()); + + UimaUtil.removeMentionSurface(m, ms[1]); + + assertEquals(2, m.getSurface().size()); + assertEquals(0, m.getSurface(0).getBegin()); + assertEquals(6, m.getSurface(1).getBegin()); + + UimaUtil.removeMentionSurface(m, ms[0]); + + assertEquals(1, m.getSurface().size()); + assertEquals(6, m.getSurface(0).getBegin()); + + } + + @Test + public void testAddRemoveMentionSurface() { + Mention m = new Mention(jcas); + m.addToIndexes(); + m.setSurface(new FSArray(jcas, 0)); + + MentionSurface[] ms = new MentionSurface[] { + AnnotationFactory.createAnnotation(jcas, 0, 2, MentionSurface.class), + AnnotationFactory.createAnnotation(jcas, 5, 6, MentionSurface.class), + AnnotationFactory.createAnnotation(jcas, 10, 12, MentionSurface.class) }; + + UimaUtil.addMentionSurface(m, ms[0]); + assertNotNull(m.getSurface()); + assertEquals(1, m.getSurface().size()); + UimaUtil.removeMentionSurface(m, ms[0]); + assertNotNull(m.getSurface()); + assertEquals(0, m.getSurface().size()); + } + + @Test + public void testAddMentionSurface() { + Mention m = new Mention(jcas); + m.addToIndexes(); + m.setSurface(new FSArray(jcas, 0)); + + MentionSurface[] ms = new MentionSurface[] { + AnnotationFactory.createAnnotation(jcas, 0, 2, MentionSurface.class), + AnnotationFactory.createAnnotation(jcas, 5, 6, MentionSurface.class), + AnnotationFactory.createAnnotation(jcas, 10, 12, MentionSurface.class) }; + + UimaUtil.addMentionSurface(m, ms[0]); + + assertNotNull(m.getSurface()); + assertEquals(1, m.getSurface().size()); + + UimaUtil.addMentionSurface(m, ms[2]); + + assertNotNull(m.getSurface()); + assertEquals(2, m.getSurface().size()); + assertEquals(0, m.getSurface(0).getBegin()); + assertEquals(10, m.getSurface(1).getBegin()); + + UimaUtil.addMentionSurface(m, ms[1]); + + assertNotNull(m.getSurface()); + assertEquals(3, m.getSurface().size()); + assertEquals(0, m.getSurface(0).getBegin()); + assertEquals(5, m.getSurface(1).getBegin()); + assertEquals(10, m.getSurface(2).getBegin()); + + } +} diff --git a/src/test/resources/log4j2-test.xml b/src/test/resources/log4j2-test.xml index 7f5074f8..dc7e599c 100644 --- a/src/test/resources/log4j2-test.xml +++ b/src/test/resources/log4j2-test.xml @@ -5,18 +5,27 @@ - + - - - + + + + + + + - - - - + + + + \ No newline at end of file diff --git a/src/test/resources/profile-ner.xml b/src/test/resources/profile-ner.xml new file mode 100644 index 00000000..e1e5bcab --- /dev/null +++ b/src/test/resources/profile-ner.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/tei/test2.xml b/src/test/resources/tei/test2.xml new file mode 100644 index 00000000..58127a5b --- /dev/null +++ b/src/test/resources/tei/test2.xml @@ -0,0 +1,12 @@ + + +Lorem ipsum dolor sit amet, +consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et +dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam +et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea +takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit +amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor +invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At +vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd +gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + \ No newline at end of file