Skip to content

Commit

Permalink
Merge pull request #2081 from inception-project/bugfix/2077-Unable-to…
Browse files Browse the repository at this point in the history
…-merge-via-curation-siderbar-if-username-contains-DOT-0_18_x

#2077 - Unable to merge via curation siderbar if username contains "."
  • Loading branch information
reckart committed Mar 12, 2021
2 parents bfd2a02 + 16979a9 commit 83f87f9
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.uima.cas.CAS;
import org.apache.uima.cas.Feature;
Expand Down Expand Up @@ -97,64 +95,74 @@ public void handleAction(AnnotationActionHandler aPanel, AnnotatorState aState,
if (!aParamId.getExtensionId().equals(EXTENSION_ID)) {
return;
}
VID extendedVID = parse(aParamId);

if (!aAction.equals(ACTION_SELECT_ARC) && !aAction.equals(ACTION_SELECT_SPAN)) {
return;
}

// Annotation has been selected for gold
saveAnnotation(aAction, aPanel, aState, aTarget, aCas, extendedVID);
CurationVID extendedVID = CurationVID.parse(aParamId.getExtensionPayload());
if (extendedVID != null) {
saveAnnotation(aAction, aPanel, aState, aTarget, aCas, extendedVID);
}
}

/**
* Save annotation identified by aVID from user CAS to given curator's CAS
*/
private void saveAnnotation(String aAction, AnnotationActionHandler aPanel,
AnnotatorState aState, AjaxRequestTarget aTarget, CAS aTargetCas, VID aVID)
AnnotatorState aState, AjaxRequestTarget aTarget, CAS aTargetCas,
CurationVID aCurationVid)
throws IOException, AnnotationException
{
AnnotationLayer layer = annotationService.getLayer(aVID.getLayerId());

// get user CAS and annotation (to be merged into curator's)
SourceDocument doc = aState.getDocument();
String srcUser = ((CurationVID) aVID).getUsername();
String srcUser = aCurationVid.getUsername();

if (!documentService.existsAnnotationDocument(doc, srcUser)) {
log.error(String.format("Source CAS of %s for curation not found", srcUser));
return;
}

VID vid = VID.parse(aCurationVid.getExtensionPayload());

AnnotationLayer layer = annotationService.getLayer(vid.getLayerId());

CAS srcCas = documentService.readAnnotationCas(doc, srcUser);
AnnotationFS sourceAnnotation = selectAnnotationByAddr(srcCas, aVID.getId());
AnnotationFS sourceAnnotation = selectAnnotationByAddr(srcCas, vid.getId());

// merge into curator's CAS depending on annotation type (span or arc)
CasMerge casMerge = new CasMerge(annotationService);
CasMergeOperationResult mergeResult;
if (ACTION_SELECT_SPAN.equals(aAction.toString())) {
mergeResult = casMerge.mergeSpanAnnotation(doc, srcUser, layer, aTargetCas,
sourceAnnotation, layer.isAllowStacking());
// open created/updates FS in annotation detail editorpanel
aState.getSelection().selectSpan(new VID(mergeResult.getResultFSAddress()), aTargetCas,
sourceAnnotation.getBegin(), sourceAnnotation.getEnd());

// open created/updates FS in annotation detail editorpanel
AnnotationFS mergedAnno = selectAnnotationByAddr(aTargetCas,
mergeResult.getResultFSAddress());
aState.getSelection().selectSpan(mergedAnno);
}
else if (ACTION_SELECT_ARC.equals(aAction.toString())) {
// this is a slot arc
if (aVID.isSlotSet()) {
if (vid.isSlotSet()) {
TypeAdapter adapter = annotationService.getAdapter(layer);
AnnotationFeature feature = adapter.listFeatures().stream().sequential()
.skip(aVID.getAttribute()).findFirst().get();
.skip(vid.getAttribute()).findFirst().get();

mergeResult = casMerge.mergeSlotFeature(doc, srcUser, layer, aTargetCas,
sourceAnnotation, feature.getName(), aVID.getSlot());
sourceAnnotation, feature.getName(), vid.getSlot());

// open created/updates FS in annotation detail editorpanel
aState.getSelection().selectSpan(new VID(mergeResult.getResultFSAddress()),
aTargetCas, sourceAnnotation.getBegin(), sourceAnnotation.getEnd());
AnnotationFS mergedAnno = selectAnnotationByAddr(aTargetCas,
mergeResult.getResultFSAddress());
aState.getSelection().selectSpan(mergedAnno);
}
// normal relation annotation arc is clicked
else {
mergeResult = casMerge.mergeRelationAnnotation(doc, srcUser, layer, aTargetCas,
sourceAnnotation, layer.isAllowStacking());

// open created/updates FS in annotation detail editorpanel
AnnotationFS mergedAnno = selectAnnotationByAddr(aTargetCas,
mergeResult.getResultFSAddress());
Expand All @@ -163,38 +171,14 @@ else if (ACTION_SELECT_ARC.equals(aAction.toString())) {
Feature targetFeat = depType.getFeatureByBaseName(WebAnnoConst.FEAT_REL_TARGET);
AnnotationFS originFS = (AnnotationFS) mergedAnno.getFeatureValue(originFeat);
AnnotationFS targetFS = (AnnotationFS) mergedAnno.getFeatureValue(targetFeat);
aState.getSelection().selectArc(new VID(mergeResult.getResultFSAddress()), originFS,
targetFS);
aState.getSelection().selectArc(new VID(mergedAnno), originFS, targetFS);
}
}

aPanel.actionSelect(aTarget);
aPanel.actionCreateOrUpdate(aTarget, aTargetCas); // should also update timestamps
}

/**
* Parse extension payload of given VID into CurationVID
*/
protected VID parse(VID aParamId)
{
// format of extension payload is <USER>:<VID> with standard VID format
// <ID>-<SUB>.<ATTR>.<SLOT>@<LAYER>
Matcher matcher = Pattern.compile("(?:(?<USER>\\w+)\\:)" + "(?<VID>.+)")
.matcher(aParamId.getExtensionPayload());
if (!matcher.matches()) {
return aParamId;
}

if (matcher.group("VID") == null || matcher.group("USER") == null) {
return aParamId;
}

String vidStr = matcher.group("VID");
String username = matcher.group("USER");
return new CurationVID(aParamId.getExtensionId(), username, VID.parse(vidStr),
aParamId.getExtensionPayload());
}

@Override
public void render(CAS aCas, AnnotatorState aState, VDocument aVdoc, int aWindowBeginOffset,
int aWindowEndOffset)
Expand Down Expand Up @@ -246,7 +230,7 @@ public void render(CAS aCas, AnnotatorState aState, VDocument aVdoc, int aWindow
for (VSpan vspan : tmpDoc.spans()) {
VID aDepVID = vspan.getVid();
VID prevVID = VID.copyVID(aDepVID);
VID newVID = new CurationVID(EXTENSION_ID, username,
VID newVID = new CurationVID(username,
new VID(vspan.getLayer().getId(), aDepVID.getId(), aDepVID.getSubId(),
aDepVID.getAttribute(), aDepVID.getSlot()));
vspan.setVid(newVID);
Expand All @@ -263,9 +247,8 @@ public void render(CAS aCas, AnnotatorState aState, VDocument aVdoc, int aWindow
for (VArc varc : tmpDoc.arcs()) {
// update varc vid
VID vid = varc.getVid();
VID extendedVID = new CurationVID(EXTENSION_ID, username,
new VID(varc.getLayer().getId(), vid.getId(), vid.getSubId(),
vid.getAttribute(), vid.getSlot()));
VID extendedVID = new CurationVID(username, new VID(varc.getLayer().getId(),
vid.getId(), vid.getSubId(), vid.getAttribute(), vid.getSlot()));
// set target and src with new vids for arc
VSpan targetSpan = newIdSpan.get(varc.getTarget());
VSpan srcSpan = newIdSpan.get(varc.getSource());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@
*/
package de.tudarmstadt.ukp.inception.curation;

import static de.tudarmstadt.ukp.inception.curation.CurationEditorExtension.EXTENSION_ID;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.VID;

public class CurationVID
Expand All @@ -30,17 +39,9 @@ public class CurationVID

private final String username;

public CurationVID(String aExtId, String aUsername, VID aVID)
public CurationVID(String aUsername, VID aVID)
{
super(aExtId, aVID.getLayerId(), aVID.getId(), aVID.getSubId(), aVID.getAttribute(),
aVID.getSlot(), aUsername + ":" + aVID.toString());
username = aUsername;
}

public CurationVID(String aExtId, String aUsername, VID aVID, String aExtensionPayload)
{
super(aExtId, aVID.getLayerId(), aVID.getId(), aVID.getSubId(), aVID.getAttribute(),
aVID.getSlot(), aExtensionPayload);
super(aVID.getId(), EXTENSION_ID, aUsername + "!" + aVID.toString());
username = aUsername;
}

Expand All @@ -50,15 +51,51 @@ public String getUsername()
}

@Override
public int hashCode()
public String getExtensionPayload()
{
return StringUtils.substringAfter(super.getExtensionPayload(), "!");
}

/**
* Parse extension payload of given VID into CurationVID
*/
public static CurationVID parse(String aParamId)
{
return super.hashCode() * 31 + username.hashCode();
// format of extension payload is <USER>!<VID> with standard VID format
// <ID>-<SUB>.<ATTR>.<SLOT>@<LAYER>
Matcher matcher = Pattern.compile("(?:(?<USER>[^!]+)\\!)(?<VID>.+)").matcher(aParamId);
if (!matcher.matches()) {
return null;
}

if (matcher.group("VID") == null || matcher.group("USER") == null) {
return null;
}

String vidStr = matcher.group("VID");
String username = matcher.group("USER");
return new CurationVID(username, VID.parse(vidStr));
}

@Override
public boolean equals(Object aObj)
public boolean equals(final Object other)
{
return super.equals(aObj) && ((CurationVID) aObj).getUsername().equals(username);
if (!(other instanceof CurationVID)) {
return false;
}

CurationVID castOther = (CurationVID) other;
return new EqualsBuilder() //
.append(username, castOther.username) //
.append(getId(), castOther.getId()) //
.append(getExtensionPayload(), castOther.getExtensionPayload()) //
.isEquals();
}

@Override
public int hashCode()
{
return new HashCodeBuilder().append(username).append(getId()).append(getExtensionPayload())
.toHashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,50 +21,47 @@
*/
package de.tudarmstadt.ukp.inception.curation;

import static org.junit.Assert.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Before;
import org.junit.Test;

import de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.VID;

public class CurationVIDTest
{
private CurationEditorExtension extension;

@Before
public void setup()
{
extension = new CurationEditorExtension();
}

@Test
public void testParse()
{
assertParseVid(VID.parse("ext:10-kevin:10"), "ext", -1, 10, -1, -1, -1, "kevin",
"kevin:10");
assertParseVid(VID.parse("ext:10-kevin:10.1"), "ext", -1, 10, -1, 1, -1, "kevin",
"kevin:10.1");
assertParseVid(VID.parse("ext:10-kevin:10.1.2"), "ext", -1, 10, -1, 1, 2, "kevin",
"kevin:10.1.2");
assertParseVid(VID.parse("ext:10-kevin:10-1.2.3"), "ext", -1, 10, 1, 2, 3, "kevin",
"kevin:10-1.2.3");
assertParseVid(VID.parse("ext:10-kevin:10-1.2.3@1"), "ext", 1, 10, 1, 2, 3, "kevin",
"kevin:10-1.2.3@1");
assertParseVid(VID.parse("curationEditorExtension:10-kevin!10"), //
"curationEditorExtension", "kevin", "10", -1, 10, -1, -1, -1);

assertParseVid(VID.parse("curationEditorExtension:10-kevin!10.1"), //
"curationEditorExtension", "kevin", "10.1", -1, 10, -1, 1, -1);

assertParseVid(VID.parse("curationEditorExtension:10-kevin!10.1.2"), //
"curationEditorExtension", "kevin", "10.1.2", -1, 10, -1, 1, 2);

assertParseVid(VID.parse("curationEditorExtension:10-kevin!10-1.2.3"), //
"curationEditorExtension", "kevin", "10-1.2.3", -1, 10, 1, 2, 3);

assertParseVid(VID.parse("curationEditorExtension:10-kevin!10-1.2.3@1"), //
"curationEditorExtension", "kevin", "10-1.2.3@1", 1, 10, 1, 2, 3);
}

private void assertParseVid(VID aVID, String aExtensionId, int aLayerId, int aAnnotationID,
int aSubAnnotationId, int aAttribute, int aSlot, String aUsername,
String aExtensionPayload)
private void assertParseVid(VID aVID, String aExtensionId, String aUsername, String aPayload,
int aLayerId, int aAnnotationID, int aSubAnnotationId, int aAttribute, int aSlot)
{
VID a = extension.parse(aVID);
assertEquals(aExtensionId, a.getExtensionId());
assertEquals(aExtensionPayload, a.getExtensionPayload());
assertEquals(aUsername, ((CurationVID) a).getUsername());
assertEquals(aLayerId, a.getLayerId());
assertEquals(aAnnotationID, a.getId());
assertEquals(aSubAnnotationId, a.getSubId());
assertEquals(aAttribute, a.getAttribute());
assertEquals(aSlot, a.getSlot());
CurationVID a = CurationVID.parse(aVID.getExtensionPayload());
VID b = VID.parse(a.getExtensionPayload());

assertThat(a.getExtensionId()).isEqualTo(aExtensionId);
assertThat(a.getExtensionPayload()).isEqualTo(aPayload);
assertThat(a.getUsername()).isEqualTo(aUsername);

assertThat(b.getLayerId()).isEqualTo(aLayerId);
assertThat(b.getId()).isEqualTo(aAnnotationID);
assertThat(b.getSubId()).isEqualTo(aSubAnnotationId);
assertThat(b.getAttribute()).isEqualTo(aAttribute);
assertThat(b.getSlot()).isEqualTo(aSlot);
}
}

0 comments on commit 83f87f9

Please sign in to comment.