public static FeatureStructure[] resolve(RelationAdapter aAdapter, AnnotationFS aRelation) { Type type = aRelation.getType(); Feature targetFeature = type.getFeatureByBaseName(aAdapter.getTargetFeatureName()); Feature sourceFeature = type.getFeatureByBaseName(aAdapter.getSourceFeatureName()); FeatureStructure targetFs; FeatureStructure sourceFs; if (aAdapter.getAttachFeatureName() != null) { Type spanType = getType(aRelation.getCAS(), aAdapter.getAttachTypeName()); Feature arcSpanFeature = spanType.getFeatureByBaseName(aAdapter.getAttachFeatureName()); targetFs = aRelation.getFeatureValue(targetFeature).getFeatureValue(arcSpanFeature); sourceFs = aRelation.getFeatureValue(sourceFeature).getFeatureValue(arcSpanFeature); } else { targetFs = aRelation.getFeatureValue(targetFeature); sourceFs = aRelation.getFeatureValue(sourceFeature); } return new FeatureStructure[] { sourceFs, targetFs }; } }
@Override public RelationAdapter createAdapter(AnnotationLayer aLayer) { RelationAdapter adapter = new RelationAdapter(featureSupportRegistry, eventPublisher, aLayer, FEAT_REL_TARGET, FEAT_REL_SOURCE, schemaService.listAnnotationFeature(aLayer), layerBehaviorsRegistry.getLayerBehaviors(this, RelationLayerBehavior.class)); return adapter; }
String aDepCoveredText, String aGovCoveredText, Object aValue) Feature dependentFeature = aAdapter.getAnnotationType(aJCas.getCas()) .getFeatureByBaseName(aAdapter.getTargetFeatureName()); Feature governorFeature = aAdapter.getAnnotationType(aJCas.getCas()) .getFeatureByBaseName(aAdapter.getSourceFeatureName()); Type type = CasUtil.getType(aJCas.getCas(), aAdapter.getAnnotationTypeName()); Type spanType = getType(aJCas.getCas(), aAdapter.getAttachTypeName()); Feature arcSpanFeature = spanType.getFeatureByBaseName(aAdapter.getAttachFeatureName()); if (aAdapter.getAttachFeatureName() != null) { dependentFs = (AnnotationFS) fs.getFeatureValue(dependentFeature) .getFeatureValue(arcSpanFeature); if (ObjectUtils.equals(aAdapter.getFeatureValue(aFeature, fs), aValue)) { aAdapter.delete(aDocument, aUsername, aJCas, new VID(getAddr(fs)));
@Override public List<Pair<LogMessage, AnnotationFS>> onValidate(TypeAdapter aAdapter, JCas aJCas) { if (aAdapter.getLayer().isCrossSentence()) { emptyList(); } RelationAdapter adapter = (RelationAdapter) aAdapter; CAS cas = aJCas.getCas(); Type type = getType(cas, adapter.getAnnotationTypeName()); Feature targetFeature = type.getFeatureByBaseName(adapter.getTargetFeatureName()); Feature sourceFeature = type.getFeatureByBaseName(adapter.getSourceFeatureName()); List<Pair<LogMessage, AnnotationFS>> messages = new ArrayList<>(); for (AnnotationFS fs : select(cas, type)) { AnnotationFS targetFs = (AnnotationFS) fs.getFeatureValue(targetFeature); AnnotationFS sourceFs = (AnnotationFS) fs.getFeatureValue(sourceFeature); if (!isBeginInSameSentence(aJCas, targetFs.getBegin(), sourceFs.getBegin())) { messages.add(Pair.of( LogMessage.error(this, "Crossing sentence bounardies is not permitted."), fs)); } } return messages; } }
Type relationType = CasUtil.getType(cas, relationLayer.getName()); Feature sourceFeature = relationType.getFeatureByBaseName(relationAdapter .getSourceFeatureName()); Feature targetFeature = relationType.getFeatureByBaseName(relationAdapter .getTargetFeatureName()); if (relationAdapter.getAttachFeatureName() != null) { relationSourceAttachFeature = sourceFeature.getRange().getFeatureByBaseName( relationAdapter.getAttachFeatureName()); relationTargetAttachFeature = targetFeature.getRange().getFeatureByBaseName( relationAdapter.getAttachFeatureName());
RelationAdapter adapter = (RelationAdapter) aAdapter; Type type = getType(cas, aAdapter.getAnnotationTypeName()); Feature targetFeature = type.getFeatureByBaseName(adapter.getTargetFeatureName()); Feature sourceFeature = type.getFeatureByBaseName(adapter.getSourceFeatureName());
throws AnnotationException if (aAdapter.getLayer().isAllowStacking()) { return aRequest; final AnnotationLayer layer = aAdapter.getLayer(); final JCas jcas = aRequest.getJcas(); final Type type = getType(jcas.getCas(), aAdapter.getLayer().getName()); final Feature dependentFeature = type.getFeatureByBaseName(aAdapter.getTargetFeatureName()); final Feature governorFeature = type.getFeatureByBaseName(aAdapter.getSourceFeatureName());
@Test public void thatRelationAttachmentBehaviorOnCreateWorks() throws Exception { TokenBuilder<Token, Sentence> builder = new TokenBuilder<>(Token.class, Sentence.class); builder.buildTokens(jcas, "This is a test ."); for (Token t : select(jcas, Token.class)) { POS pos = new POS(jcas, t.getBegin(), t.getEnd()); t.setPos(pos); pos.addToIndexes(); } RelationAdapter sut = new RelationAdapter(featureSupportRegistry, null, depLayer, FEAT_REL_TARGET, FEAT_REL_SOURCE, asList(dependencyLayerGovernor, dependencyLayerDependent), behaviors); List<POS> posAnnotations = new ArrayList<>(select(jcas, POS.class)); List<Token> tokens = new ArrayList<>(select(jcas, Token.class)); POS source = posAnnotations.get(0); POS target = posAnnotations.get(1); AnnotationFS dep = sut.add(document, username, source, target, jcas, 0, jcas.getDocumentText().length()); assertThat(FSUtil.getFeature(dep, FEAT_REL_SOURCE, Token.class)).isEqualTo(tokens.get(0)); assertThat(FSUtil.getFeature(dep, FEAT_REL_TARGET, Token.class)).isEqualTo(tokens.get(1)); }
RelationAdapter sut = new RelationAdapter(featureSupportRegistry, null, depLayer, FEAT_REL_TARGET, FEAT_REL_SOURCE, asList(dependencyLayerGovernor, dependencyLayerDependent), behaviors); sut.add(document, username, source, target, jcas, 0, jcas.getDocumentText().length()); sut.add(document, username, source, target, jcas, 0, jcas.getDocumentText().length()); assertThat(sut.validate(jcas)) .extracting(Pair::getLeft) .usingElementComparatorIgnoringFields("source", "message")
if (typeAdapter.getAttachFeatureName() != null) { dependentFs = fs.getFeatureValue(dependentFeature).getFeatureValue(arcSpanFeature); governorFs = fs.getFeatureValue(governorFeature).getFeatureValue(arcSpanFeature); log.warn("Relation [" + typeAdapter.getLayer().getName() + "] with id [" + getAddr(fs) + "] has loose ends - cannot render."); continue;
if (dCoveredText.equals(fs.getCoveredText())) { if (g != null && isSamAnno(attachSpanType, fs, aDepFS)) { AnnotationFS arc = adapter.add(aState.getDocument(), aState.getUser().getUsername(), g, fs, jCas, aStart, aEnd); adapter.setFeatureValue(aState.getDocument(), aState.getUser().getUsername(), jCas, getAddr(arc), aFeature, aValue); g = null; AnnotationFS arc = adapter.add(aState.getDocument(), aState.getUser().getUsername(), fs, d, jCas, aStart, aEnd); adapter.setFeatureValue(aState.getDocument(), aState.getUser().getUsername(), jCas, getAddr(arc), aFeature, aValue); g = null;
@Override public List<Pair<LogMessage, AnnotationFS>> validate(JCas aJCas) { List<Pair<LogMessage, AnnotationFS>> messages = new ArrayList<>(); for (RelationLayerBehavior behavior : behaviors) { long startTime = currentTimeMillis(); messages.addAll(behavior.onValidate(this, aJCas)); log.trace("Validation for [{}] on [{}] took {}ms", behavior.getClass().getSimpleName(), getLayer().getUiName(), currentTimeMillis() - startTime); } return messages; } }
private void createNewRelationAnnotation(RelationAdapter aAdapter, JCas aJCas) throws AnnotationException { LOG.trace("createNewRelationAnnotation()"); AnnotatorState state = getModelObject(); Selection selection = state.getSelection(); AnnotationFS originFs = selectByAddr(aJCas, selection.getOrigin()); AnnotationFS targetFs = selectByAddr(aJCas, selection.getTarget()); // Creating a relation AnnotationFS arc = aAdapter.add(state.getDocument(), state.getUser().getUsername(), originFs, targetFs, aJCas, state.getWindowBeginOffset(), state.getWindowEndOffset()); selection.selectArc(new VID(arc), originFs, targetFs); }
Type type = getType(cas, adapter.getAnnotationTypeName()); Feature targetFeature = type.getFeatureByBaseName(adapter.getTargetFeatureName()); Feature sourceFeature = type.getFeatureByBaseName(adapter.getSourceFeatureName());
RelationAdapter typeAdpt = (RelationAdapter) annotationService.getAdapter(layer); adpt = new ArcDiffAdapter(layer.getName(), typeAdpt.getSourceFeatureName(), typeAdpt.getTargetFeatureName(), labelFeatures); break;
throws AnnotationException if (aAdapter.getLayer().isAllowStacking()) { return aRequest; final AnnotationLayer layer = aAdapter.getLayer(); final JCas jcas = aRequest.getJcas(); final Type type = getType(jcas.getCas(), aAdapter.getLayer().getName()); final Feature dependentFeature = type.getFeatureByBaseName(aAdapter.getTargetFeatureName()); final Feature governorFeature = type.getFeatureByBaseName(aAdapter.getSourceFeatureName());
@Test public void thatRelationStackingBehaviorOnCreateDoesNotThrowException() throws Exception { TokenBuilder<Token, Sentence> builder = new TokenBuilder<>(Token.class, Sentence.class); builder.buildTokens(jcas, "This is a test .\nThis is sentence two ."); for (Token t : select(jcas, Token.class)) { POS pos = new POS(jcas, t.getBegin(), t.getEnd()); t.setPos(pos); pos.addToIndexes(); } RelationAdapter sut = new RelationAdapter(featureSupportRegistry, null, depLayer, FEAT_REL_TARGET, FEAT_REL_SOURCE, asList(dependencyLayerGovernor, dependencyLayerDependent), behaviors); List<POS> posAnnotations = new ArrayList<>(select(jcas, POS.class)); List<Token> tokens = new ArrayList<>(select(jcas, Token.class)); POS source = posAnnotations.get(0); POS target = posAnnotations.get(1); depLayer.setAllowStacking(true); AnnotationFS dep1 = sut.add(document, username, source, target, jcas, 0, jcas.getDocumentText().length()); AnnotationFS dep2 = sut.add(document, username, source, target, jcas, 0, jcas.getDocumentText().length()); assertThat(FSUtil.getFeature(dep1, FEAT_REL_SOURCE, Token.class)).isEqualTo(tokens.get(0)); assertThat(FSUtil.getFeature(dep1, FEAT_REL_TARGET, Token.class)).isEqualTo(tokens.get(1)); assertThat(FSUtil.getFeature(dep2, FEAT_REL_SOURCE, Token.class)).isEqualTo(tokens.get(0)); assertThat(FSUtil.getFeature(dep2, FEAT_REL_TARGET, Token.class)).isEqualTo(tokens.get(1)); }
@Test public void thatRelationCrossSentenceBehaviorOnValidateGeneratesErrors() throws Exception { TokenBuilder<Token, Sentence> builder = new TokenBuilder<>(Token.class, Sentence.class); builder.buildTokens(jcas, "This is a test .\nThis is sentence two ."); for (Token t : select(jcas, Token.class)) { POS pos = new POS(jcas, t.getBegin(), t.getEnd()); t.setPos(pos); pos.addToIndexes(); } RelationAdapter sut = new RelationAdapter(featureSupportRegistry, null, depLayer, FEAT_REL_TARGET, FEAT_REL_SOURCE, asList(dependencyLayerGovernor, dependencyLayerDependent), behaviors); List<POS> posAnnotations = new ArrayList<>(select(jcas, POS.class)); POS source = posAnnotations.get(0); POS target = posAnnotations.get(posAnnotations.size() - 1); depLayer.setCrossSentence(true); sut.add(document, username, source, target, jcas, 0, jcas.getDocumentText().length()); depLayer.setCrossSentence(false); assertThat(sut.validate(jcas)) .extracting(Pair::getLeft) .usingElementComparatorIgnoringFields("source", "message") .containsExactly(LogMessage.error(null, "")); }
if (typeAdapter.getAttachFeatureName() != null) { dependentFs = fs.getFeatureValue(dependentFeature).getFeatureValue(arcSpanFeature); governorFs = fs.getFeatureValue(governorFeature).getFeatureValue(arcSpanFeature); log.warn("Relation [" + typeAdapter.getLayer().getName() + "] with id [" + getAddr(fs) + "] has loose ends - cannot render."); continue;
if (dCoveredText.equals(fs.getCoveredText())) { if (g != null && isSamAnno(attachSpanType, fs, aDepFS)) { AnnotationFS arc = adapter.add(aState.getDocument(), aState.getUser().getUsername(), g, fs, jCas, aStart, aEnd); adapter.setFeatureValue(aState.getDocument(), aState.getUser().getUsername(), jCas, getAddr(arc), aFeature, aValue); g = null; AnnotationFS arc = adapter.add(aState.getDocument(), aState.getUser().getUsername(), fs, d, jCas, aStart, aEnd); adapter.setFeatureValue(aState.getDocument(), aState.getUser().getUsername(), jCas, getAddr(arc), aFeature, aValue); g = null;