CasMerge { public CasMergeOperationResult mergeSpanAnnotation(SourceDocument aDocument, String aUsername, AnnotationLayer aAnnotationLayer, CAS aTargetCas, AnnotationFS aSourceFs, boolean aAllowStacking) throws AnnotationException { if (existsSameAt(aTargetCas, aSourceFs)) { throw new AlreadyMergedException( "The annotation already exists in the target document."); } SpanAdapter adapter = (SpanAdapter) adapterCache.get(aAnnotationLayer); if (silenceEvents) { adapter.silenceEvents(); } List<AnnotationFS> existingAnnos = selectAt(aTargetCas, aSourceFs.getType(), aSourceFs.getBegin(), aSourceFs.getEnd()); if (existingAnnos.isEmpty() || aAllowStacking) { AnnotationFS mergedSpan = adapter.add(aDocument, aUsername, aTargetCas, aSourceFs.getBegin(), aSourceFs.getEnd()); int mergedSpanAddr = -1; try { copyFeatures(aDocument, aUsername, adapter, mergedSpan, aSourceFs); mergedSpanAddr = getAddr(mergedSpan); } catch (AnnotationException e) { adapter.delete(aDocument, aUsername, aTargetCas, new VID(mergedSpan)); throw e; } return new CasMergeOperationResult(CasMergeOperationResult.ResultState.CREATED, mergedSpanAddr); } else { AnnotationFS annoToUpdate = existingAnnos.get(0); copyFeatures(aDocument, aUsername, adapter, annoToUpdate, aSourceFs); int mergedSpanAddr = getAddr(annoToUpdate); return new CasMergeOperationResult(CasMergeOperationResult.ResultState.UPDATED, mergedSpanAddr); } } CasMerge(AnnotationSchemaService aSchemaService);  CasMerge(AnnotationSchemaService aSchemaService,
            ApplicationEventPublisher aEventPublisher); void setSilenceEvents(boolean aSilenceEvents); boolean isSilenceEvents(); void setMergeIncompleteAnnotations(boolean aMergeIncompleteAnnotations); boolean isMergeIncompleteAnnotations(); void reMergeCas(DiffResult aDiff, SourceDocument aTargetDocument, String aTargetUsername,
            CAS aTargetCas, Map<String, CAS> aCases); CasMergeOperationResult mergeSpanAnnotation(SourceDocument aDocument, String aUsername,
            AnnotationLayer aAnnotationLayer, CAS aTargetCas, AnnotationFS aSourceFs,
            boolean aAllowStacking); CasMergeOperationResult mergeRelationAnnotation(SourceDocument aDocument,
            String aUsername, AnnotationLayer aAnnotationLayer, CAS aTargetCas,
            AnnotationFS aSourceFs, boolean aAllowStacking); CasMergeOperationResult mergeSlotFeature(SourceDocument aDocument, String aUsername,
            AnnotationLayer aAnnotationLayer, CAS aTargetCas,
            AnnotationFS aSourceFs, String aSourceFeature, int aSourceSlotIndex);  }
@Test public void simpleCopyToEmptyTest() throws Exception { AnnotatorState state = new AnnotatorStateImpl(CURATION); state.setUser(new User()); CAS jcas = createJCas().getCas(); AnnotationFS clickedFs = createNEAnno(jcas, "NN", 0, 0); CAS curatorCas = createJCas().getCas(); createTokenAnno(curatorCas, 0, 0); sut.mergeSpanAnnotation(null, null, neLayer, curatorCas, clickedFs, false); assertThat(selectCovered(curatorCas, getType(curatorCas, NamedEntity.class), 0, 0)) .hasSize(1); }
@Test public void simpleCopyToSameExistingAnnoTest() throws Exception { CAS jcas = createJCas().getCas(); Type type = jcas.getTypeSystem().getType(POS.class.getTypeName()); AnnotationFS clickedFs = createPOSAnno(jcas, "NN", 0, 0); CAS mergeCas = createJCas().getCas(); AnnotationFS existingFs = mergeCas.createAnnotation(type, 0, 0); Feature posValue = type.getFeatureByBaseName("PosValue"); existingFs.setStringValue(posValue, "NN"); mergeCas.addFsToIndexes(existingFs); Assertions.assertThatExceptionOfType(AnnotationException.class) .isThrownBy(() -> sut.mergeSpanAnnotation(null, null, posLayer, mergeCas, clickedFs, false)) .withMessageContaining("annotation already exists"); }
@Test public void simpleCopyToDiffExistingAnnoWithNoStackingTest() throws Exception { CAS jcas = createJCas().getCas(); Type type = jcas.getTypeSystem().getType(POS.class.getTypeName()); AnnotationFS clickedFs = createPOSAnno(jcas, "NN", 0, 0); CAS mergeCAs = createJCas().getCas(); AnnotationFS existingFs = mergeCAs.createAnnotation(type, 0, 0); Feature posValue = type.getFeatureByBaseName("PosValue"); existingFs.setStringValue(posValue, "NE"); mergeCAs.addFsToIndexes(existingFs); sut.mergeSpanAnnotation(null, null, posLayer, mergeCAs, clickedFs, false); assertEquals(1, CasUtil.selectCovered(mergeCAs, type, 0, 0).size()); }
@Test public void simpleCopyToDiffExistingAnnoWithStackingTest() throws Exception { neLayer.setOverlapMode(OverlapMode.ANY_OVERLAP); CAS jcas = createJCas().getCas(); Type type = jcas.getTypeSystem().getType(NamedEntity.class.getTypeName()); AnnotationFS clickedFs = createNEAnno(jcas, "NN", 0, 0); CAS mergeCAs = createJCas().getCas(); createTokenAnno(mergeCAs, 0, 0); AnnotationFS existingFs = mergeCAs.createAnnotation(type, 0, 0); Feature posValue = type.getFeatureByBaseName("value"); existingFs.setStringValue(posValue, "NE"); mergeCAs.addFsToIndexes(existingFs); sut.mergeSpanAnnotation(null, null, neLayer, mergeCAs, clickedFs, true); assertEquals(2, selectCovered(mergeCAs, type, 0, 0).size()); }
@Test public void copySpanWithSlotNoStackingTest() throws Exception { slotLayer.setOverlapMode(OverlapMode.NO_OVERLAP); JCas jcasA = createJCas(CurationTestUtils.createMultiLinkWithRoleTestTypeSystem("f1")); Type type = jcasA.getTypeSystem().getType(CurationTestUtils.HOST_TYPE); Feature feature = type.getFeatureByBaseName("f1"); AnnotationFS clickedFs = CurationTestUtils.makeLinkHostMultiSPanFeatureFS(jcasA, 0, 0, feature, "A", CurationTestUtils.makeLinkFS(jcasA, "slot1", 0, 0)); JCas mergeCAs = JCasFactory .createJCas(CurationTestUtils.createMultiLinkWithRoleTestTypeSystem("f1")); CurationTestUtils.makeLinkHostMultiSPanFeatureFS(mergeCAs, 0, 0, feature, "C", CurationTestUtils.makeLinkFS(mergeCAs, "slot1", 0, 0)); sut.mergeSpanAnnotation(null, null, slotLayer, mergeCAs.getCas(), clickedFs, false); assertEquals(1, selectCovered(mergeCAs.getCas(), type, 0, 0).size()); }
@Test public void copySpanWithSlotWithStackingTest() throws Exception { AnnotatorState state = new AnnotatorStateImpl(CURATION); state.setUser(new User()); slotLayer.setAnchoringMode(TOKENS); slotLayer.setOverlapMode(OverlapMode.ANY_OVERLAP); JCas jcasA = createJCas(CurationTestUtils.createMultiLinkWithRoleTestTypeSystem("f1")); Type type = jcasA.getTypeSystem().getType(CurationTestUtils.HOST_TYPE); Feature feature = type.getFeatureByBaseName("f1"); AnnotationFS clickedFs = CurationTestUtils.makeLinkHostMultiSPanFeatureFS(jcasA, 0, 0, feature, "A", CurationTestUtils.makeLinkFS(jcasA, "slot1", 0, 0)); JCas mergeCAs = JCasFactory .createJCas(CurationTestUtils.createMultiLinkWithRoleTestTypeSystem("f1")); CurationTestUtils.makeLinkHostMultiSPanFeatureFS(mergeCAs, 0, 0, feature, "C", CurationTestUtils.makeLinkFS(mergeCAs, "slot1", 0, 0)); sut.mergeSpanAnnotation(null, null, slotLayer, mergeCAs.getCas(), clickedFs, true); assertEquals(2, selectCovered(mergeCAs.getCas(), type, 0, 0).size()); }