From bd52e3537ecbeb11024be02a7e74ef843c88e9fb Mon Sep 17 00:00:00 2001 From: MarkusKrug <markus.krug@uni-wuerzburg.de> Date: Mon, 3 Jul 2017 08:12:26 +0200 Subject: [PATCH] mapping should now also be configurable with the span matching. Currently there are 2 span matching modes -strict and ignore Whitespace --- .../view/widget/TreeHierarchyComposite.java | 1 + .../struct/ESpanMatching.java | 5 + .../util/AnnotationComparisonUtil.java | 130 ++++-- .../util/GoldMappingConfig.java | 14 + .../util/MappingConverter.java | 88 +++-- .../util/XmlMappingConfig.java | 153 ++++---- .../wizard/FeatureMappingPage.java | 222 +++++------ .../wizard/InitialTypeSelectionPage.java | 245 ++++++------ .../wizard/MappingWizard.java | 370 +++++++++--------- .../kall/coreferenceview/part/CorefView.java | 23 ++ 10 files changed, 690 insertions(+), 561 deletions(-) create mode 100644 de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/struct/ESpanMatching.java diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.athen.medie.owl.view/src/de/uniwue/mk/athen/medie/owl/view/widget/TreeHierarchyComposite.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.athen.medie.owl.view/src/de/uniwue/mk/athen/medie/owl/view/widget/TreeHierarchyComposite.java index 83ca71c6..34510704 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.athen.medie.owl.view/src/de/uniwue/mk/athen/medie/owl/view/widget/TreeHierarchyComposite.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.athen.medie.owl.view/src/de/uniwue/mk/athen/medie/owl/view/widget/TreeHierarchyComposite.java @@ -963,6 +963,7 @@ public class TreeHierarchyComposite extends Composite { OWLOntologyClassWrapper wrapper = (OWLOntologyClassWrapper) sel.getFirstElement(); // editClass(wrapper); + } } diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/struct/ESpanMatching.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/struct/ESpanMatching.java new file mode 100644 index 00000000..e53be457 --- /dev/null +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/struct/ESpanMatching.java @@ -0,0 +1,5 @@ +package de.uniwue.mk.kall.athen.goldstandardAnalyzer.struct; + +public enum ESpanMatching {STRICT,IGNORE_WHITESPACE; + +} diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/AnnotationComparisonUtil.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/AnnotationComparisonUtil.java index e96891e4..cb71217b 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/AnnotationComparisonUtil.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/AnnotationComparisonUtil.java @@ -13,13 +13,14 @@ import org.apache.uima.cas.Feature; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.Type; import org.apache.uima.cas.text.AnnotationFS; +import org.eclipse.swt.graphics.Point; import de.uniwue.mk.kall.athen.goldstandardAnalyzer.struct.BinaryTupelMapping; +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.struct.ESpanMatching; public class AnnotationComparisonUtil { - public static BinaryTupelMapping compareAnnotations(CAS cas, - GoldMappingConfig config) { + public static BinaryTupelMapping compareAnnotations(CAS cas, GoldMappingConfig config) { ArrayList<Pair<AnnotationFS, AnnotationFS>> list = new ArrayList<>(); List<AnnotationFS> goldList = new ArrayList<>(); @@ -28,7 +29,7 @@ public class AnnotationComparisonUtil { cas.getAnnotationIndex(config.getSystemType()).forEach(anno -> systemRemaining.add(anno)); /* - * Sorting is not necessary but should cause a speed-up in case of TPs. + * Sorting is not necessary but should cause a speed-up in case of TPs. */ Comparator<AnnotationFS> comparator = (anno1, anno2) -> { if (anno1.getBegin() != anno2.getBegin()) { @@ -46,7 +47,8 @@ public class AnnotationComparisonUtil { AnnotationFS foundAnno = null; for (AnnotationFS systemAnno : systemRemaining) { if (goldAnno.getBegin() < systemAnno.getBegin()) { - // lists sorted => systemAnnotations after this cannot be equal + // lists sorted => systemAnnotations after this cannot be + // equal break; } else if (areEqual(goldAnno, systemAnno, config)) { foundAnno = systemAnno; @@ -60,7 +62,8 @@ public class AnnotationComparisonUtil { }); /* - * Add remaining System Annotations (there is no equal Gold Annotation for these) + * Add remaining System Annotations (there is no equal Gold Annotation + * for these) */ systemRemaining.forEach(systemAnno -> { list.add(new Pair<AnnotationFS, AnnotationFS>(null, systemAnno)); @@ -71,18 +74,19 @@ public class AnnotationComparisonUtil { /** * Checks whether the two given Annotations have the same Features. <br/> - * If at least one of the Annotations is <code>null</code> the method will return false. + * If at least one of the Annotations is <code>null</code> the method will + * return false. + * * @param goldAnno * @param systemAnno * @return */ - public static boolean areEqual(AnnotationFS goldAnno, AnnotationFS systemAnno, - GoldMappingConfig config) { + public static boolean areEqual(AnnotationFS goldAnno, AnnotationFS systemAnno, GoldMappingConfig config) { if (goldAnno == null || systemAnno == null) { return false; } // check spans - if (!haveEqualSpans(goldAnno, systemAnno)) { + if (!haveEqualSpans(goldAnno, systemAnno, config.getSpanMatchingMode())) { return false; } // check whether the Types of the Annotations are mapped to each other @@ -94,20 +98,21 @@ public class AnnotationComparisonUtil { } /** - * Checks whether the Features of the two given Annotations are equal. Features that are - * Annotations themselves are compared using {@link #areEqual()}. + * Checks whether the Features of the two given Annotations are equal. + * Features that are Annotations themselves are compared using + * {@link #areEqual()}. + * * @param goldAnno * @param systemAnno * @return */ - public static boolean haveEqualFeatures(AnnotationFS goldAnno, AnnotationFS systemAnno, - GoldMappingConfig config) { + public static boolean haveEqualFeatures(AnnotationFS goldAnno, AnnotationFS systemAnno, GoldMappingConfig config) { List<Feature> goldFeatures = goldAnno.getType().getFeatures(); for (Feature goldFeat : goldFeatures) { /* - * Find the Feature that is mapped to goldFeat. - * If there is no Feature found then goldFeat has not been mapped and - * therefore does not need to be compared. + * Find the Feature that is mapped to goldFeat. If there is no + * Feature found then goldFeat has not been mapped and therefore + * does not need to be compared. */ Feature systemFeat = findMappedFeature(goldFeat, config); if (systemFeat == null) { @@ -117,8 +122,7 @@ public class AnnotationComparisonUtil { if (goldFeat.getRange().isPrimitive() || systemFeat.getRange().isPrimitive()) { String goldFvs = goldAnno.getFeatureValueAsString(goldFeat); String systemFvs = systemAnno.getFeatureValueAsString(systemFeat); - if ((goldFvs == null && systemFvs != null) || - (goldFvs != null && !goldFvs.equals(systemFvs))) { + if ((goldFvs == null && systemFvs != null) || (goldFvs != null && !goldFvs.equals(systemFvs))) { return false; } continue; @@ -141,7 +145,8 @@ public class AnnotationComparisonUtil { } } - // Compare both features depending on whether they are both Annotations + // Compare both features depending on whether they are both + // Annotations if (goldFS instanceof AnnotationFS && systemFS instanceof AnnotationFS) { if (!areEqual((AnnotationFS) goldFS, (AnnotationFS) systemFS, config)) { return false; @@ -154,7 +159,9 @@ public class AnnotationComparisonUtil { } /** - * Checks whether the GoldMappingConfig contains a mapping between the two given Types. + * Checks whether the GoldMappingConfig contains a mapping between the two + * given Types. + * * @param firstType * @param secondType * @param config @@ -165,12 +172,10 @@ public class AnnotationComparisonUtil { return true; } for (Pair<Type, Type> mapping : config.getTypeMapping()) { - if (firstType.equals(mapping.getFirstElement()) && - secondType.equals(mapping.getSecondElement())) { + if (firstType.equals(mapping.getFirstElement()) && secondType.equals(mapping.getSecondElement())) { return true; } - if (firstType.equals(mapping.getSecondElement()) && - secondType.equals(mapping.getFirstElement())) { + if (firstType.equals(mapping.getSecondElement()) && secondType.equals(mapping.getFirstElement())) { return true; } } @@ -178,19 +183,65 @@ public class AnnotationComparisonUtil { } /** - * Checks whether the given Annotations possess the same span (begin and end Features) + * Checks whether the given Annotations possess the same span (begin and end + * Features) + * * @param firstAnno * @param secondAnno + * @param eSpanMatching * @return */ - public static boolean haveEqualSpans(AnnotationFS firstAnno, AnnotationFS secondAnno) { - return firstAnno.getBegin() == secondAnno.getBegin() && - firstAnno.getEnd() == secondAnno.getEnd(); + public static boolean haveEqualSpans(AnnotationFS firstAnno, AnnotationFS secondAnno, ESpanMatching eSpanMatching) { + + //default + if(eSpanMatching==null){ + eSpanMatching =ESpanMatching.STRICT; + } + + if (eSpanMatching == ESpanMatching.STRICT) { + return firstAnno.getBegin() == secondAnno.getBegin() && firstAnno.getEnd() == secondAnno.getEnd(); + } else if (eSpanMatching == ESpanMatching.IGNORE_WHITESPACE) { + Point annoTrimmedFirst = trimAnno(firstAnno); + Point annoTrimmedsecond = trimAnno(secondAnno); + + return (annoTrimmedFirst.x == annoTrimmedsecond.x && annoTrimmedFirst.y == annoTrimmedsecond.y); + } + + return false; + } + + private static Point trimAnno(AnnotationFS firstAnno) { + + int beg = firstAnno.getBegin(); + + // trim beg + for (int i = 0; i < firstAnno.getCoveredText().length(); i++) { + + if (Character.isWhitespace(firstAnno.getCoveredText().charAt(i))) { + beg++; + } else { + break; + } + } + + // trim end + int end = firstAnno.getEnd(); + for (int i = firstAnno.getCoveredText().length() - 1; i >= 0; i--) { + + if (Character.isWhitespace(firstAnno.getCoveredText().charAt(i))) { + end--; + } else { + break; + } + } + return new Point(beg, end); } /** - * Finds the Feature that is mapped to the given Feature in hte given GoldMappingConfig. <br/> - * Returns <code>null</code> if there is no such Feature. + * Finds the Feature that is mapped to the given Feature in hte given + * GoldMappingConfig. <br/> + * Returns <code>null</code> if there is no such Feature. + * * @param feature * @param config * @return @@ -207,7 +258,7 @@ public class AnnotationComparisonUtil { return null; } - public static boolean haveEqualElements(CommonArrayFS goldArray, CommonArrayFS systemArray, + public static boolean haveEqualElements(CommonArrayFS goldArray, CommonArrayFS systemArray, GoldMappingConfig config) { if (goldArray instanceof ArrayFS || systemArray instanceof ArrayFS) { return haveEqualElements((ArrayFS) goldArray, (ArrayFS) systemArray, config); @@ -227,8 +278,7 @@ public class AnnotationComparisonUtil { return true; } - public static boolean haveEqualElements(ArrayFS goldArray, ArrayFS systemArray, - GoldMappingConfig config) { + public static boolean haveEqualElements(ArrayFS goldArray, ArrayFS systemArray, GoldMappingConfig config) { for (int i = 0; i < goldArray.size(); i++) { if (!arrayContains(systemArray, goldArray.get(i), config)) { return false; @@ -242,23 +292,19 @@ public class AnnotationComparisonUtil { return true; } - public static boolean arrayContains(ArrayFS array, FeatureStructure featureStructure, - GoldMappingConfig config) { + public static boolean arrayContains(ArrayFS array, FeatureStructure featureStructure, GoldMappingConfig config) { for (int i = 0; i < array.size(); i++) { FeatureStructure fs2 = array.get(i); /* - * Compare the two FeatureStructures - * 1. both are Annotations - * 2. both are arrays - * 3. all other cases + * Compare the two FeatureStructures 1. both are Annotations 2. both + * are arrays 3. all other cases */ if (featureStructure instanceof AnnotationFS && fs2 instanceof AnnotationFS) { if (areEqual((AnnotationFS) featureStructure, (AnnotationFS) fs2, config)) { return true; } - } else if (featureStructure instanceof CommonArrayFS && fs2 instanceof CommonArrayFS) { - if (haveEqualElements((CommonArrayFS) featureStructure, - (CommonArrayFS) fs2, config)) { + } else if (featureStructure instanceof CommonArrayFS && fs2 instanceof CommonArrayFS) { + if (haveEqualElements((CommonArrayFS) featureStructure, (CommonArrayFS) fs2, config)) { return true; } } else if (featureStructure != null && featureStructure.equals(fs2)) { diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/GoldMappingConfig.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/GoldMappingConfig.java index dd61d535..d36fb853 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/GoldMappingConfig.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/GoldMappingConfig.java @@ -6,6 +6,8 @@ import java.util.Collection; import org.apache.uima.cas.Feature; import org.apache.uima.cas.Type; +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.struct.ESpanMatching; + public class GoldMappingConfig { private Type goldType; private Type systemType; @@ -13,6 +15,7 @@ public class GoldMappingConfig { private Collection<Pair<Type, Type>> typeMapping; private Collection<Pair<Feature, Feature>> featureMapping; + private ESpanMatching spanMatchingMode; public GoldMappingConfig(){ typeMapping = new ArrayList<>(); @@ -59,6 +62,17 @@ public class GoldMappingConfig { public void setFeatureMapping(Collection<Pair<Feature, Feature>> featureMapping) { this.featureMapping = featureMapping; } + + + public ESpanMatching getSpanMatchingMode() { + return spanMatchingMode; + } + + public void setSpanMatchingMode(ESpanMatching spanMatchingMode) { + this.spanMatchingMode = spanMatchingMode; + } + + diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/MappingConverter.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/MappingConverter.java index 4fb9f102..fb1ee8ba 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/MappingConverter.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/MappingConverter.java @@ -1,42 +1,46 @@ -package de.uniwue.mk.kall.athen.goldstandardAnalyzer.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.uima.cas.Feature; -import org.apache.uima.cas.Type; -import org.apache.uima.cas.TypeSystem; - -public class MappingConverter { - - public static XmlMappingConfig convertToXml(GoldMappingConfig config) { - String goldType = config.getGoldType().getName(); - String systemType = config.getSystemType().getName(); - List<Pair<String, String>> typeMapping = config.getTypeMapping().stream().map(pair -> - new Pair<>(pair.getFirstElement().getName(), pair.getSecondElement().getName())). - collect(Collectors.toList()); - List<Pair<String, String>> featureMapping = config.getFeatureMapping().stream().map(pair -> - new Pair<>(pair.getFirstElement().getName(), pair.getSecondElement().getName())). - collect(Collectors.toList()); - return new XmlMappingConfig(goldType, systemType, new ArrayList<>(typeMapping), - new ArrayList<>(featureMapping)); - } - - public static GoldMappingConfig convert(XmlMappingConfig config, TypeSystem ts) { - Type goldType = ts.getType(config.getGoldType()); - Type systemType = ts.getType(config.getSystemType()); - List<Pair<Type, Type>> typeMapping = config.getTypeMapping().stream().map(pair -> { - Type firstType = ts.getType(pair.getFirstElement()); - Type secondType = ts.getType(pair.getSecondElement()); - return new Pair<>(firstType, secondType); - }).collect(Collectors.toList()); - List<Pair<Feature, Feature>> featureMapping = config.getFeatureMapping().stream().map(pair -> { - Feature firstFeature = ts.getFeatureByFullName(pair.getFirstElement()); - Feature secondFeature = ts.getFeatureByFullName(pair.getSecondElement()); - return new Pair<>(firstFeature, secondFeature); - }).collect(Collectors.toList()); - return new GoldMappingConfig(goldType, systemType, new ArrayList<>(typeMapping), - new ArrayList<>(featureMapping)); - } -} +package de.uniwue.mk.kall.athen.goldstandardAnalyzer.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.uima.cas.Feature; +import org.apache.uima.cas.Type; +import org.apache.uima.cas.TypeSystem; + +public class MappingConverter { + + public static XmlMappingConfig convertToXml(GoldMappingConfig config) { + String goldType = config.getGoldType().getName(); + String systemType = config.getSystemType().getName(); + List<Pair<String, String>> typeMapping = config.getTypeMapping().stream().map(pair -> + new Pair<>(pair.getFirstElement().getName(), pair.getSecondElement().getName())). + collect(Collectors.toList()); + List<Pair<String, String>> featureMapping = config.getFeatureMapping().stream().map(pair -> + new Pair<>(pair.getFirstElement().getName(), pair.getSecondElement().getName())). + collect(Collectors.toList()); + XmlMappingConfig xmlMappingConfig = new XmlMappingConfig(goldType, systemType, new ArrayList<>(typeMapping), + new ArrayList<>(featureMapping)); + xmlMappingConfig.setSpanMatchingMode(config.getSpanMatchingMode()); + return xmlMappingConfig; + } + + public static GoldMappingConfig convert(XmlMappingConfig config, TypeSystem ts) { + Type goldType = ts.getType(config.getGoldType()); + Type systemType = ts.getType(config.getSystemType()); + List<Pair<Type, Type>> typeMapping = config.getTypeMapping().stream().map(pair -> { + Type firstType = ts.getType(pair.getFirstElement()); + Type secondType = ts.getType(pair.getSecondElement()); + return new Pair<>(firstType, secondType); + }).collect(Collectors.toList()); + List<Pair<Feature, Feature>> featureMapping = config.getFeatureMapping().stream().map(pair -> { + Feature firstFeature = ts.getFeatureByFullName(pair.getFirstElement()); + Feature secondFeature = ts.getFeatureByFullName(pair.getSecondElement()); + return new Pair<>(firstFeature, secondFeature); + }).collect(Collectors.toList()); + GoldMappingConfig goldMappingConfig = new GoldMappingConfig(goldType, systemType, new ArrayList<>(typeMapping), + new ArrayList<>(featureMapping)); + goldMappingConfig.setSpanMatchingMode(config.getSpanMatchingMode()); + return goldMappingConfig; + } +} diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/XmlMappingConfig.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/XmlMappingConfig.java index ac31cac5..ecf780d2 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/XmlMappingConfig.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/util/XmlMappingConfig.java @@ -1,70 +1,83 @@ -package de.uniwue.mk.kall.athen.goldstandardAnalyzer.util; - -import java.util.ArrayList; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement -public class XmlMappingConfig { - private String goldType; - private String systemType; - - private ArrayList<Pair<String, String>> typeMapping; - - private ArrayList<Pair<String, String>> featureMappings; - - - public XmlMappingConfig() { - typeMapping = new ArrayList<>(); - featureMappings = new ArrayList<>(); - } - - public XmlMappingConfig(String goldType, String systemType, - ArrayList<Pair<String, String>> typeMapping, - ArrayList<Pair<String, String>> featureMapping) { - this.goldType = goldType; - this.systemType = systemType; - this.typeMapping = typeMapping; - this.featureMappings = featureMapping; - } - - public String getGoldType() { - return goldType; - } - - public void setGoldType(String goldType) { - if (this.goldType == null) { - this.goldType = goldType; - } - } - - public String getSystemType() { - return systemType; - } - - public void setSystemType(String systemType) { - if (this.systemType == null) { - this.systemType = systemType; - } - } - - public ArrayList<Pair<String, String>> getTypeMapping() { - return typeMapping; - } - - public void setTypeMapping(ArrayList<Pair<String, String>> typeMapping) { - if (this.typeMapping == null) { - this.typeMapping = typeMapping; - } - } - - public ArrayList<Pair<String, String>> getFeatureMapping() { - return featureMappings; - } - - public void setFeatureMapping(ArrayList<Pair<String, String>> featureMapping) { - if (this.featureMappings == null) { - this.featureMappings = featureMapping; - } - } -} +package de.uniwue.mk.kall.athen.goldstandardAnalyzer.util; + +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlRootElement; + +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.struct.ESpanMatching; + +@XmlRootElement +public class XmlMappingConfig { + private String goldType; + private String systemType; + + private ArrayList<Pair<String, String>> typeMapping; + + private ArrayList<Pair<String, String>> featureMappings; + + private ESpanMatching spanMatchingMode; + + + public XmlMappingConfig() { + typeMapping = new ArrayList<>(); + featureMappings = new ArrayList<>(); + } + + public XmlMappingConfig(String goldType, String systemType, + ArrayList<Pair<String, String>> typeMapping, + ArrayList<Pair<String, String>> featureMapping) { + this.goldType = goldType; + this.systemType = systemType; + this.typeMapping = typeMapping; + this.featureMappings = featureMapping; + } + + + public ESpanMatching getSpanMatchingMode() { + return spanMatchingMode; + } + + public void setSpanMatchingMode(ESpanMatching spanMatchingMode) { + this.spanMatchingMode = spanMatchingMode; + } + + public String getGoldType() { + return goldType; + } + + public void setGoldType(String goldType) { + if (this.goldType == null) { + this.goldType = goldType; + } + } + + public String getSystemType() { + return systemType; + } + + public void setSystemType(String systemType) { + if (this.systemType == null) { + this.systemType = systemType; + } + } + + public ArrayList<Pair<String, String>> getTypeMapping() { + return typeMapping; + } + + public void setTypeMapping(ArrayList<Pair<String, String>> typeMapping) { + if (this.typeMapping == null) { + this.typeMapping = typeMapping; + } + } + + public ArrayList<Pair<String, String>> getFeatureMapping() { + return featureMappings; + } + + public void setFeatureMapping(ArrayList<Pair<String, String>> featureMapping) { + if (this.featureMappings == null) { + this.featureMappings = featureMapping; + } + } +} diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/FeatureMappingPage.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/FeatureMappingPage.java index b0507509..9395aac8 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/FeatureMappingPage.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/FeatureMappingPage.java @@ -1,110 +1,112 @@ -package de.uniwue.mk.kall.athen.goldstandardAnalyzer.wizard; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.uima.cas.Feature; -import org.apache.uima.cas.Type; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; - -import de.uniwue.mk.kall.athen.goldstandardAnalyzer.util.Pair; -import de.uniwue.mk.kall.athen.goldstandardAnalyzer.widgets.MappingWidget; - -public class FeatureMappingPage extends WizardPage { - private Type firstType; - private Type secondType; - private Collection<Pair<Feature, Feature>> mapping; - private boolean primitivesOnly; - - private MappingWidget<Feature> widget; - private LabelProvider labelProvider; - - - protected FeatureMappingPage(Type firstType, Type secondType, boolean primitivesOnly, - Collection<Pair<Feature, Feature>> mapping) { - super("Feature Mapping"); - this.firstType = firstType; - this.secondType = secondType; - this.primitivesOnly = primitivesOnly; - this.mapping = mapping; - } - - - @Override - public void createControl(Composite parent) { - widget = new MappingWidget<>(parent, SWT.BORDER); - widget.addMappingChangedListener(ev -> checkPageCompletion()); - labelProvider = new LabelProvider() { - - @Override - public String getText(Object obj) { - if (obj instanceof Feature) { - return ((Feature) obj).getShortName(); - } - return ""; - } - - }; - - if (firstType == null || secondType == null) { - widget.setInput(new ArrayList<>(), new ArrayList<>(), labelProvider, mapping); - } else { - List<Feature> firstFeatures = firstType.getFeatures().stream(). - filter(feature -> !primitivesOnly || feature.getRange().isPrimitive()). - collect(Collectors.toList()); - List<Feature> secondFeatures = secondType.getFeatures().stream(). - filter(feature -> !primitivesOnly || feature.getRange().isPrimitive()). - collect(Collectors.toList()); - widget.setInput(firstFeatures, secondFeatures, labelProvider, mapping); - setMessage("Create mapping between the Features of " + firstType.getShortName() + - " and " + secondType.getShortName()); - } - - setControl(widget); - } - - public void update(Type firstType, Type secondType) { - this.firstType = firstType; - this.secondType = secondType; - if (firstType == null || secondType == null) { - widget.setInput(new ArrayList<>(), new ArrayList<>(), labelProvider, mapping); - } else { - List<Feature> firstFeatures = firstType.getFeatures().stream(). - filter(feature -> !primitivesOnly || feature.getRange().isPrimitive()). - filter(feature -> !isStandardFeature(feature)). - collect(Collectors.toList()); - List<Feature> secondFeatures = secondType.getFeatures().stream(). - filter(feature -> !primitivesOnly || feature.getRange().isPrimitive()). - filter(feature -> !isStandardFeature(feature)). - collect(Collectors.toList()); - widget.setInput(firstFeatures, secondFeatures, labelProvider, mapping); - setMessage("Create mapping between the Features of " + firstType.getShortName() + - " and " + secondType.getShortName()); - } - } - - public void checkPageCompletion() { - //TODO check whether non-primitive features are mapped to other non-primitive features - // set page as complete if no secondElement appears more than one time - boolean duplicateFree = mapping.stream().map(pair -> pair.getSecondElement()). - allMatch(new HashSet<>()::add); - if (!duplicateFree) { - setErrorMessage("Each Feature may only be mapped once!"); - } else { - setErrorMessage(null); - } - setPageComplete(duplicateFree); - } - - private boolean isStandardFeature(Feature feature) { - String name = feature.getShortName(); - return name.equals("sofa") || name.equals("begin") || name.equals("end"); - } - -} +package de.uniwue.mk.kall.athen.goldstandardAnalyzer.wizard; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.uima.cas.Feature; +import org.apache.uima.cas.Type; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.struct.ESpanMatching; +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.util.Pair; +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.widgets.MappingWidget; + +public class FeatureMappingPage extends WizardPage { + private Type firstType; + private Type secondType; + private Collection<Pair<Feature, Feature>> mapping; + private ESpanMatching spanMatching; + private boolean primitivesOnly; + + private MappingWidget<Feature> widget; + private LabelProvider labelProvider; + + + protected FeatureMappingPage(Type firstType, Type secondType, boolean primitivesOnly, + Collection<Pair<Feature, Feature>> mapping) { + super("Feature Mapping"); + this.firstType = firstType; + this.secondType = secondType; + this.primitivesOnly = primitivesOnly; + this.mapping = mapping; + } + + + @Override + public void createControl(Composite parent) { + widget = new MappingWidget<>(parent, SWT.BORDER); + widget.addMappingChangedListener(ev -> checkPageCompletion()); + labelProvider = new LabelProvider() { + + @Override + public String getText(Object obj) { + if (obj instanceof Feature) { + return ((Feature) obj).getShortName(); + } + return ""; + } + + }; + + if (firstType == null || secondType == null) { + widget.setInput(new ArrayList<>(), new ArrayList<>(), labelProvider, mapping); + } else { + List<Feature> firstFeatures = firstType.getFeatures().stream(). + filter(feature -> !primitivesOnly || feature.getRange().isPrimitive()). + collect(Collectors.toList()); + List<Feature> secondFeatures = secondType.getFeatures().stream(). + filter(feature -> !primitivesOnly || feature.getRange().isPrimitive()). + collect(Collectors.toList()); + widget.setInput(firstFeatures, secondFeatures, labelProvider, mapping); + setMessage("Create mapping between the Features of " + firstType.getShortName() + + " and " + secondType.getShortName()); + } + + setControl(widget); + } + + public void update(Type firstType, Type secondType) { + this.firstType = firstType; + this.secondType = secondType; + if (firstType == null || secondType == null) { + widget.setInput(new ArrayList<>(), new ArrayList<>(), labelProvider, mapping); + } else { + List<Feature> firstFeatures = firstType.getFeatures().stream(). + filter(feature -> !primitivesOnly || feature.getRange().isPrimitive()). + filter(feature -> !isStandardFeature(feature)). + collect(Collectors.toList()); + List<Feature> secondFeatures = secondType.getFeatures().stream(). + filter(feature -> !primitivesOnly || feature.getRange().isPrimitive()). + filter(feature -> !isStandardFeature(feature)). + collect(Collectors.toList()); + widget.setInput(firstFeatures, secondFeatures, labelProvider, mapping); + setMessage("Create mapping between the Features of " + firstType.getShortName() + + " and " + secondType.getShortName()); + } + } + + public void checkPageCompletion() { + //TODO check whether non-primitive features are mapped to other non-primitive features + // set page as complete if no secondElement appears more than one time + boolean duplicateFree = mapping.stream().map(pair -> pair.getSecondElement()). + allMatch(new HashSet<>()::add); + if (!duplicateFree) { + setErrorMessage("Each Feature may only be mapped once!"); + } else { + setErrorMessage(null); + } + setPageComplete(duplicateFree); + } + + private boolean isStandardFeature(Feature feature) { + String name = feature.getShortName(); + return name.equals("sofa") || name.equals("begin") || name.equals("end"); + } + +} diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/InitialTypeSelectionPage.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/InitialTypeSelectionPage.java index aa28c6a4..842b12ac 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/InitialTypeSelectionPage.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/InitialTypeSelectionPage.java @@ -1,114 +1,131 @@ -package de.uniwue.mk.kall.athen.goldstandardAnalyzer.wizard; - -import org.apache.uima.cas.Type; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; - -import de.uniwue.mk.kall.athen.part.editor.dialog.AnnotationStyleEditingDialog; -import de.uniwue.mk.kall.athen.widget.editor.AnnotationEditorWidget; - -public class InitialTypeSelectionPage extends WizardPage { - private AnnotationEditorWidget editor; - - private Type goldType; - private Type systemType; - - - public InitialTypeSelectionPage(AnnotationEditorWidget editor) { - super("Gold- and System-Type Selection"); - setMessage("Select the Types of the Annotations that should be compared"); - - this.editor = editor; - } - - @Override - public void createControl(Composite parent) { - Composite composite = new Composite(parent, SWT.NULL); - composite.setLayout(new GridLayout(3, false)); - setControl(composite); - - Label lbGoldDesc = new Label(composite, SWT.NULL); - lbGoldDesc.setText("Gold Annotation Type:"); - - Label lbGoldValue = new Label(composite, SWT.NULL); - lbGoldValue.setText(" - "); - lbGoldValue.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - Button btGold = new Button(composite, SWT.PUSH); - btGold.setText("Choose..."); - - Label lbSystemDesc = new Label(composite, SWT.NULL); - lbSystemDesc.setText("System Annotation Type:"); - - Label lbSystemValue = new Label(composite, SWT.NULL); - lbSystemValue.setText(" - "); - lbSystemValue.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - Button btSystem = new Button(composite, SWT.PUSH); - btSystem.setText("Choose..."); - - - btGold.addSelectionListener(new SelectionListener() { - - @Override - public void widgetSelected(SelectionEvent e) { - AnnotationStyleEditingDialog dialog = new AnnotationStyleEditingDialog(getShell(), - editor); - int open = dialog.open(); - if (open == Dialog.OK) { - Type type = dialog.getSelectedType(); - if (type != null) { - lbGoldValue.setText(type.getShortName()); - lbGoldValue.setToolTipText(type.getName()); - goldType = type; - } - setPageComplete(goldType != null && systemType != null); - } - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - } - }); - - btSystem.addSelectionListener(new SelectionListener() { - - @Override - public void widgetSelected(SelectionEvent e) { - AnnotationStyleEditingDialog dialog = new AnnotationStyleEditingDialog(getShell(), - editor); - int open = dialog.open(); - if (open == Dialog.OK) { - Type type = dialog.getSelectedType(); - if (type != null) { - lbSystemValue.setText(type.getShortName()); - lbSystemValue.setToolTipText(type.getName()); - systemType = type; - } - setPageComplete(goldType != null && systemType != null); - } - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - } - }); - } - - public Type getGoldType() { - return goldType; - } - - public Type getSystemType() { - return systemType; - } - -} +package de.uniwue.mk.kall.athen.goldstandardAnalyzer.wizard; + +import org.apache.uima.cas.Type; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.struct.ESpanMatching; +import de.uniwue.mk.kall.athen.part.editor.dialog.AnnotationStyleEditingDialog; +import de.uniwue.mk.kall.athen.widget.editor.AnnotationEditorWidget; + +public class InitialTypeSelectionPage extends WizardPage { + private AnnotationEditorWidget editor; + + private Type goldType; + private Type systemType; + private ESpanMatching spanMatchingMode = ESpanMatching.STRICT; + + public InitialTypeSelectionPage(AnnotationEditorWidget editor) { + super("Gold- and System-Type Selection"); + setMessage("Select the Types of the Annotations that should be compared"); + + this.editor = editor; + } + + @Override + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + composite.setLayout(new GridLayout(3, false)); + setControl(composite); + + Label lbGoldDesc = new Label(composite, SWT.NULL); + lbGoldDesc.setText("Gold Annotation Type:"); + + Label lbGoldValue = new Label(composite, SWT.NULL); + lbGoldValue.setText(" - "); + lbGoldValue.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + Button btGold = new Button(composite, SWT.PUSH); + btGold.setText("Choose..."); + + Label lbSystemDesc = new Label(composite, SWT.NULL); + lbSystemDesc.setText("System Annotation Type:"); + + Label lbSystemValue = new Label(composite, SWT.NULL); + lbSystemValue.setText(" - "); + lbSystemValue.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + Button btSystem = new Button(composite, SWT.PUSH); + btSystem.setText("Choose..."); + + btGold.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + AnnotationStyleEditingDialog dialog = new AnnotationStyleEditingDialog(getShell(), editor); + int open = dialog.open(); + if (open == Dialog.OK) { + Type type = dialog.getSelectedType(); + if (type != null) { + lbGoldValue.setText(type.getShortName()); + lbGoldValue.setToolTipText(type.getName()); + goldType = type; + } + setPageComplete(goldType != null && systemType != null); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + btSystem.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + AnnotationStyleEditingDialog dialog = new AnnotationStyleEditingDialog(getShell(), editor); + int open = dialog.open(); + if (open == Dialog.OK) { + Type type = dialog.getSelectedType(); + if (type != null) { + lbSystemValue.setText(type.getShortName()); + lbSystemValue.setToolTipText(type.getName()); + systemType = type; + } + setPageComplete(goldType != null && systemType != null); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + Label lbSpanMatchingMode = new Label(composite, SWT.NULL); + lbSpanMatchingMode.setText("Select Span Matching Mode:"); + lbSpanMatchingMode.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + ComboViewer comboViewer = new ComboViewer(composite); + comboViewer.setContentProvider(ArrayContentProvider.getInstance()); + comboViewer.setInput(ESpanMatching.values()); + comboViewer.setSelection(new StructuredSelection(ESpanMatching.STRICT)); + + comboViewer.addSelectionChangedListener((SelectionChangedEvent e) -> { + spanMatchingMode = (ESpanMatching) comboViewer.getStructuredSelection().getFirstElement(); + }); + } + + public Type getGoldType() { + return goldType; + } + + public Type getSystemType() { + return systemType; + } + public ESpanMatching getSpanMatchingMode(){ + return spanMatchingMode; + } + +} diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/MappingWizard.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/MappingWizard.java index 0570a0a3..4dd95615 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/MappingWizard.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.athen.goldstandardAnalyzer/src/de/uniwue/mk/kall/athen/goldstandardAnalyzer/wizard/MappingWizard.java @@ -1,183 +1,187 @@ -package de.uniwue.mk.kall.athen.goldstandardAnalyzer.wizard; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.uima.cas.Feature; -import org.apache.uima.cas.Type; -import org.apache.uima.cas.TypeSystem; -import org.eclipse.jface.wizard.IWizardPage; -import org.eclipse.jface.wizard.Wizard; - -import de.uniwue.mk.kall.athen.goldstandardAnalyzer.util.GoldMappingConfig; -import de.uniwue.mk.kall.athen.goldstandardAnalyzer.util.Pair; -import de.uniwue.mk.kall.athen.widget.editor.AnnotationEditorWidget; - -public class MappingWizard extends Wizard { - public static final String MESSAGE_TITLE_COMPLETE = "Mapping Complete"; - - - private Type goldType; - private Type systemType; - private TypeSystem typeSystem; - - private GoldMappingConfig config; - - private InitialTypeSelectionPage pageInitialTypeSelection; - private FeatureMappingPage pageInitialMapping; - private MessagePage pageMessageAdditionalTypes; - private TypeSelectionPage pageTypeSelection; - private TypeMappingPage pageTypeMapping; - private MessagePage pageMessageFeatureMapping; - - private Collection<Pair<Feature, Feature>> featureMapping; - private Collection<Pair<Type, Type>> typeMapping; - private Map<Pair<Type, Type>, FeatureMappingPage> subPages; - private Map<Pair<Type, Type>, Collection<Pair<Feature, Feature>>> subMappings; - private List<FeatureMappingPage> subPageOrder; - - - public MappingWizard(AnnotationEditorWidget editor) { - setWindowTitle("Mapping Wizard"); - - this.typeSystem = editor.getCas().getTypeSystem(); - - pageInitialTypeSelection = new InitialTypeSelectionPage(editor); - featureMapping = new HashSet<>(); - pageInitialMapping = new FeatureMappingPage(goldType, systemType, false, featureMapping); - pageMessageAdditionalTypes = new MessagePage(); - addPage(pageInitialTypeSelection); - addPage(pageInitialMapping); - addPage(pageMessageAdditionalTypes); - - typeMapping = new HashSet<>(); - Collection<Type> types = new HashSet<>(); - pageTypeSelection = new TypeSelectionPage(typeSystem, types); - pageTypeMapping = new TypeMappingPage(types, typeMapping); - pageMessageFeatureMapping = new MessagePage("", "Now that the Types have been selected and mapped " - + "their Features need to be mapped as well."); - addPage(pageTypeSelection); - addPage(pageTypeMapping); - addPage(pageMessageFeatureMapping); - - subPages = new HashMap<>(); - subMappings = new HashMap<>(); - subPageOrder = new ArrayList<>(); - } - - - @Override - public IWizardPage getNextPage(IWizardPage currentPage) { - if (currentPage == null) { - return pageInitialTypeSelection; - } - if (currentPage == pageInitialTypeSelection) { - goldType = pageInitialTypeSelection.getGoldType(); - systemType = pageInitialTypeSelection.getSystemType(); - pageInitialMapping.update(goldType, systemType); - return pageInitialMapping; - } - if (currentPage == pageInitialMapping) { - boolean primitivesOnly = featureMapping.stream(). - allMatch(pair -> pair.getFirstElement().getRange().isPrimitive()); - if (primitivesOnly) { - pageMessageAdditionalTypes.setMessage(MESSAGE_TITLE_COMPLETE); - pageMessageAdditionalTypes.setText("The mapping is complete."); - return pageMessageAdditionalTypes; - } else { - pageMessageAdditionalTypes.setMessage("Mapping Incomplete"); - pageMessageAdditionalTypes.setText("The mapping contains Features which are Annotations. \nThe " - + "Annotation Types that can appear as these Features need to be " - + "selected and mapped."); - return pageMessageAdditionalTypes; - } - } - if (currentPage == pageMessageAdditionalTypes) { - if (pageMessageAdditionalTypes.getMessage().equals(MESSAGE_TITLE_COMPLETE)) { - return null; - } else { - return pageTypeSelection; - } - } - if (currentPage == pageTypeSelection) { - pageTypeMapping.update(); - return pageTypeMapping; - } - if (currentPage == pageTypeMapping) { - manageSubPages(); - return pageMessageFeatureMapping; - } - if (currentPage == pageMessageFeatureMapping) { - return subPageOrder.size() > 0 ? subPageOrder.get(0) : null; - } - if (subPageOrder.contains(currentPage)) { - int index = subPageOrder.indexOf(currentPage); - if (index == subPageOrder.size() - 1) { - MessagePage page = new MessagePage(MESSAGE_TITLE_COMPLETE, - "All mappings have been completed."); - addPage(page); - return page; - } - return subPageOrder.get(index + 1); - } - return null; - } - - @Override - public boolean canFinish() { - IWizardPage currentPage = getContainer().getCurrentPage(); - if (currentPage instanceof MessagePage) { - return currentPage.getMessage().equals(MESSAGE_TITLE_COMPLETE); - } - return false; - } - - @Override - public boolean performFinish() { - subMappings.forEach((typePair, features) -> featureMapping.addAll(features)); - config = new GoldMappingConfig(goldType, systemType, - typeMapping, featureMapping); - - return true; - } - - private void manageSubPages() { - /* - * Remove obsolete pages (in case the user was on a sub page, went back to the - * original mapping page and now wants to access the sub pages again) - */ - Set<Pair<Type, Type>> obsoletePages = subPages.keySet().stream(). - filter(pair -> !typeMapping.contains(pair)).collect(Collectors.toSet()); - obsoletePages.forEach(pair -> { - FeatureMappingPage page = subPages.remove(pair); - subMappings.remove(pair); - subPageOrder.remove(page); - }); - /* - * Create new pages - */ - typeMapping.stream().filter(pair -> !subPages.containsKey(pair)).forEach( - pair -> createMappingPage(pair)); - } - - private void createMappingPage(Pair<Type, Type> pair) { - HashSet<Pair<Feature, Feature>> mapping = new HashSet<>(); - FeatureMappingPage page = new FeatureMappingPage(pair.getFirstElement(), - pair.getSecondElement(), true, mapping); - subPages.put(pair, page); - subMappings.put(pair, mapping); - subPageOrder.add(page); - addPage(page); - } - - public GoldMappingConfig getGoldMappingConfig() { - return config; - } - -} +package de.uniwue.mk.kall.athen.goldstandardAnalyzer.wizard; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.uima.cas.Feature; +import org.apache.uima.cas.Type; +import org.apache.uima.cas.TypeSystem; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; + +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.struct.ESpanMatching; +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.util.GoldMappingConfig; +import de.uniwue.mk.kall.athen.goldstandardAnalyzer.util.Pair; +import de.uniwue.mk.kall.athen.widget.editor.AnnotationEditorWidget; + +public class MappingWizard extends Wizard { + public static final String MESSAGE_TITLE_COMPLETE = "Mapping Complete"; + + + private Type goldType; + private Type systemType; + private TypeSystem typeSystem; + private ESpanMatching spanMatchingMode; + + private GoldMappingConfig config; + + private InitialTypeSelectionPage pageInitialTypeSelection; + private FeatureMappingPage pageInitialMapping; + private MessagePage pageMessageAdditionalTypes; + private TypeSelectionPage pageTypeSelection; + private TypeMappingPage pageTypeMapping; + private MessagePage pageMessageFeatureMapping; + + private Collection<Pair<Feature, Feature>> featureMapping; + private Collection<Pair<Type, Type>> typeMapping; + private Map<Pair<Type, Type>, FeatureMappingPage> subPages; + private Map<Pair<Type, Type>, Collection<Pair<Feature, Feature>>> subMappings; + private List<FeatureMappingPage> subPageOrder; + + + public MappingWizard(AnnotationEditorWidget editor) { + setWindowTitle("Mapping Wizard"); + + this.typeSystem = editor.getCas().getTypeSystem(); + + pageInitialTypeSelection = new InitialTypeSelectionPage(editor); + featureMapping = new HashSet<>(); + pageInitialMapping = new FeatureMappingPage(goldType, systemType, false, featureMapping); + pageMessageAdditionalTypes = new MessagePage(); + addPage(pageInitialTypeSelection); + addPage(pageInitialMapping); + addPage(pageMessageAdditionalTypes); + + typeMapping = new HashSet<>(); + Collection<Type> types = new HashSet<>(); + pageTypeSelection = new TypeSelectionPage(typeSystem, types); + pageTypeMapping = new TypeMappingPage(types, typeMapping); + pageMessageFeatureMapping = new MessagePage("", "Now that the Types have been selected and mapped " + + "their Features need to be mapped as well."); + addPage(pageTypeSelection); + addPage(pageTypeMapping); + addPage(pageMessageFeatureMapping); + + subPages = new HashMap<>(); + subMappings = new HashMap<>(); + subPageOrder = new ArrayList<>(); + } + + + @Override + public IWizardPage getNextPage(IWizardPage currentPage) { + if (currentPage == null) { + return pageInitialTypeSelection; + } + if (currentPage == pageInitialTypeSelection) { + goldType = pageInitialTypeSelection.getGoldType(); + systemType = pageInitialTypeSelection.getSystemType(); + spanMatchingMode = pageInitialTypeSelection.getSpanMatchingMode(); + pageInitialMapping.update(goldType, systemType); + return pageInitialMapping; + } + if (currentPage == pageInitialMapping) { + boolean primitivesOnly = featureMapping.stream(). + allMatch(pair -> pair.getFirstElement().getRange().isPrimitive()); + if (primitivesOnly) { + pageMessageAdditionalTypes.setMessage(MESSAGE_TITLE_COMPLETE); + pageMessageAdditionalTypes.setText("The mapping is complete."); + return pageMessageAdditionalTypes; + } else { + pageMessageAdditionalTypes.setMessage("Mapping Incomplete"); + pageMessageAdditionalTypes.setText("The mapping contains Features which are Annotations. \nThe " + + "Annotation Types that can appear as these Features need to be " + + "selected and mapped."); + return pageMessageAdditionalTypes; + } + } + if (currentPage == pageMessageAdditionalTypes) { + if (pageMessageAdditionalTypes.getMessage().equals(MESSAGE_TITLE_COMPLETE)) { + return null; + } else { + return pageTypeSelection; + } + } + if (currentPage == pageTypeSelection) { + pageTypeMapping.update(); + return pageTypeMapping; + } + if (currentPage == pageTypeMapping) { + manageSubPages(); + return pageMessageFeatureMapping; + } + if (currentPage == pageMessageFeatureMapping) { + return subPageOrder.size() > 0 ? subPageOrder.get(0) : null; + } + if (subPageOrder.contains(currentPage)) { + int index = subPageOrder.indexOf(currentPage); + if (index == subPageOrder.size() - 1) { + MessagePage page = new MessagePage(MESSAGE_TITLE_COMPLETE, + "All mappings have been completed."); + addPage(page); + return page; + } + return subPageOrder.get(index + 1); + } + return null; + } + + @Override + public boolean canFinish() { + IWizardPage currentPage = getContainer().getCurrentPage(); + if (currentPage instanceof MessagePage) { + return currentPage.getMessage().equals(MESSAGE_TITLE_COMPLETE); + } + return false; + } + + @Override + public boolean performFinish() { + subMappings.forEach((typePair, features) -> featureMapping.addAll(features)); + config = new GoldMappingConfig(goldType, systemType, + typeMapping, featureMapping); + config.setSpanMatchingMode(spanMatchingMode); + + return true; + } + + private void manageSubPages() { + /* + * Remove obsolete pages (in case the user was on a sub page, went back to the + * original mapping page and now wants to access the sub pages again) + */ + Set<Pair<Type, Type>> obsoletePages = subPages.keySet().stream(). + filter(pair -> !typeMapping.contains(pair)).collect(Collectors.toSet()); + obsoletePages.forEach(pair -> { + FeatureMappingPage page = subPages.remove(pair); + subMappings.remove(pair); + subPageOrder.remove(page); + }); + /* + * Create new pages + */ + typeMapping.stream().filter(pair -> !subPages.containsKey(pair)).forEach( + pair -> createMappingPage(pair)); + } + + private void createMappingPage(Pair<Type, Type> pair) { + HashSet<Pair<Feature, Feature>> mapping = new HashSet<>(); + FeatureMappingPage page = new FeatureMappingPage(pair.getFirstElement(), + pair.getSecondElement(), true, mapping); + subPages.put(pair, page); + subMappings.put(pair, mapping); + subPageOrder.add(page); + addPage(page); + } + + public GoldMappingConfig getGoldMappingConfig() { + return config; + } + +} diff --git a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.coreferenceview/src/de/uniwue/mk/kall/coreferenceview/part/CorefView.java b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.coreferenceview/src/de/uniwue/mk/kall/coreferenceview/part/CorefView.java index c6d7dc1b..223f843c 100644 --- a/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.coreferenceview/src/de/uniwue/mk/kall/coreferenceview/part/CorefView.java +++ b/de.uniwue.mk.athen/bundles/de.uniwue.mk.kall.coreferenceview/src/de/uniwue/mk/kall/coreferenceview/part/CorefView.java @@ -1183,6 +1183,29 @@ public class CorefView extends AEditorSubordinateViewPart { // create and add an empty relation Point selection = editor.getWidget().getSelection(); + + //snap to the nearest persons + int beg=-1; + int end = -1; + int amount=0; + for(AnnotationFS a : editor.getCas().getAnnotationIndex(typNE)){ + if(a.getBegin()>=selection.x && a.getEnd()<=selection.y){ + amount++; + if(beg==-1){ + beg = a.getBegin(); + } + if(end==-1){ + end = a.getEnd(); + } + beg = a.getBegin()<=beg?a.getBegin():beg; + end = a.getEnd()>=end?a.getEnd():end; + } + } + if(amount>=2){ + //SNAP! + selection.x = beg; + selection.y =end; + } AnnotationFS anno = editor.getCas().createAnnotation(relationType, selection.x, selection.y); editor.addAnnotation(anno); } -- GitLab