use of org.apache.uima.cas.FeatureStructure in project webanno by webanno.
the class ChainAdapter method deleteSpan.
private void deleteSpan(JCas aJCas, int aAddress) {
Type chainType = getAnnotationType(aJCas.getCas());
AnnotationFS linkToDelete = WebAnnoCasUtil.selectByAddr(aJCas, AnnotationFS.class, aAddress);
// case 1 "removing first link": we keep the existing chain head and just remove the
// first element
//
// case 2 "removing middle link": the new chain consists of the rest, the old chain head
// remains
//
// case 3 "removing the last link": the old chain head remains and the last element of the
// chain is removed.
// To know which case we have, we first need to find the chain containing the element to
// be deleted.
FeatureStructure oldChainFs = null;
AnnotationFS prevLinkFs = null;
chainLoop: for (FeatureStructure chainFs : selectFS(aJCas.getCas(), chainType)) {
AnnotationFS linkFs = getFirstLink(chainFs);
// Reset when entering new chain!
prevLinkFs = null;
// Now we seek the link within the current chain
while (linkFs != null) {
if (WebAnnoCasUtil.isSame(linkFs, linkToDelete)) {
oldChainFs = chainFs;
break chainLoop;
}
prevLinkFs = linkFs;
linkFs = getNextLink(linkFs);
}
}
// Did we find the chain?!
if (oldChainFs == null) {
throw new IllegalArgumentException("Chain link with address [" + aAddress + "] not found in any chain!");
}
AnnotationFS followingLinkToDelete = getNextLink(linkToDelete);
if (prevLinkFs == null) {
// case 1: first element removed
setFirstLink(oldChainFs, followingLinkToDelete);
aJCas.removeFsFromIndexes(linkToDelete);
// removed last element form chain?
if (followingLinkToDelete == null) {
aJCas.removeFsFromIndexes(oldChainFs);
}
} else if (followingLinkToDelete == null) {
// case 3: removing the last link (but not leaving the chain empty)
setNextLink(prevLinkFs, null);
aJCas.removeFsFromIndexes(linkToDelete);
} else if (prevLinkFs != null && followingLinkToDelete != null) {
// case 2: removing a middle link
// Set up new chain for rest
newChain(aJCas, followingLinkToDelete);
// Cut off from old chain
setNextLink(prevLinkFs, null);
// Delete middle link
aJCas.removeFsFromIndexes(linkToDelete);
} else {
throw new IllegalStateException("Unexpected situation while removing link. Please contact developers.");
}
}
use of org.apache.uima.cas.FeatureStructure in project webanno by webanno.
the class FeatureSupport method setFeatureValue.
/**
* Update this feature with a new value. This method should not be called directly but
* rather via {@link TypeAdapter#setFeatureValue}.
*
* @param aJcas
* the JCas.
* @param aFeature
* the feature.
* @param aAddress
* the annotation ID.
* @param aValue
* the value.
*/
default void setFeatureValue(JCas aJcas, AnnotationFeature aFeature, int aAddress, Object aValue) {
FeatureStructure fs = selectByAddr(aJcas, FeatureStructure.class, aAddress);
setFeature(fs, aFeature, aValue);
}
use of org.apache.uima.cas.FeatureStructure in project webanno by webanno.
the class MergeCas method reMergeCas.
/**
* Using {@code DiffResult}, determine the annotations to be deleted from the randomly generated
* MergeCase. The initial Merge CAs is stored under a name {@code CurationPanel#CURATION_USER}.
* <p>
* Any similar annotations stacked in a {@code CasDiff2.Position} will be assumed a difference
* <p>
* Any two annotation with different value will be assumed a difference
* <p>
* Any non stacked empty/null annotations are assumed agreement
* <p>
* Any non stacked annotations with similar values for each of the features are assumed
* agreement
* <p>
* Any two link mode / slotable annotations which agree on the base features are assumed
* agreement
*
* @param aDiff
* the {@code CasDiff2.DiffResult}
* @param aJCases
* a map of{@code JCas}s for each users and the random merge
* @return the actual merge {@code JCas}
*/
public static JCas reMergeCas(DiffResult aDiff, Map<String, JCas> aJCases) {
Set<FeatureStructure> slotFeaturesToReset = new HashSet<>();
Set<FeatureStructure> annotationsToDelete = new HashSet<>();
Set<String> users = aJCases.keySet();
for (Position position : aDiff.getPositions()) {
Map<String, List<FeatureStructure>> annosPerUser = new HashMap<>();
ConfigurationSet cfgs = aDiff.getConfigurtionSet(position);
if (cfgs.getConfigurations(WebAnnoConst.CURATION_USER).isEmpty()) {
// annotations
continue;
}
AnnotationFS mergeAnno = (AnnotationFS) cfgs.getConfigurations(WebAnnoConst.CURATION_USER).get(0).getFs(WebAnnoConst.CURATION_USER, aJCases);
// Get Annotations per user in this position
getAllAnnosOnPosition(aJCases, annosPerUser, users, mergeAnno);
for (FeatureStructure mergeFs : annosPerUser.get(WebAnnoConst.CURATION_USER)) {
// incomplete annotations
if (aJCases.size() != annosPerUser.size()) {
annotationsToDelete.add(mergeFs);
} else // agreed and not stacked
if (isAgree(mergeFs, annosPerUser)) {
Type t = mergeFs.getType();
Feature sourceFeat = t.getFeatureByBaseName(WebAnnoConst.FEAT_REL_SOURCE);
Feature targetFeat = t.getFeatureByBaseName(WebAnnoConst.FEAT_REL_TARGET);
// Is this a relation?
if (sourceFeat != null && targetFeat != null) {
AnnotationFS source = (AnnotationFS) mergeFs.getFeatureValue(sourceFeat);
AnnotationFS target = (AnnotationFS) mergeFs.getFeatureValue(targetFeat);
// all span anno on this source positions
Map<String, List<FeatureStructure>> sourceAnnosPerUser = new HashMap<>();
// all span anno on this target positions
Map<String, List<FeatureStructure>> targetAnnosPerUser = new HashMap<>();
getAllAnnosOnPosition(aJCases, sourceAnnosPerUser, users, source);
getAllAnnosOnPosition(aJCases, targetAnnosPerUser, users, target);
if (isAgree(source, sourceAnnosPerUser) && isAgree(target, targetAnnosPerUser)) {
slotFeaturesToReset.add(mergeFs);
} else {
annotationsToDelete.add(mergeFs);
}
} else {
slotFeaturesToReset.add(mergeFs);
}
} else // disagree or stacked annotations
{
annotationsToDelete.add(mergeFs);
}
// remove dangling rels
// setDanglingRelToDel(aJCases.get(CurationPanel.CURATION_USER),
// mergeFs, annotationsToDelete);
}
}
// remove annotations that do not agree or are a stacked ones
for (FeatureStructure fs : annotationsToDelete) {
if (!slotFeaturesToReset.contains(fs)) {
JCas mergeCas = aJCases.get(WebAnnoConst.CURATION_USER);
// Check if this difference is on POS, STEM and LEMMA (so remove from the token too)
Type type = fs.getType();
int fsBegin = ((AnnotationFS) fs).getBegin();
int fsEnd = ((AnnotationFS) fs).getEnd();
if (type.getName().equals(POS.class.getName())) {
Token t = JCasUtil.selectCovered(mergeCas, Token.class, fsBegin, fsEnd).get(0);
t.setPos(null);
}
if (type.getName().equals(Stem.class.getName())) {
Token t = JCasUtil.selectCovered(mergeCas, Token.class, fsBegin, fsEnd).get(0);
t.setStem(null);
}
if (type.getName().equals(Lemma.class.getName())) {
Token t = JCasUtil.selectCovered(mergeCas, Token.class, fsBegin, fsEnd).get(0);
t.setLemma(null);
}
if (type.getName().equals(MorphologicalFeatures.class.getName())) {
Token t = JCasUtil.selectCovered(mergeCas, Token.class, fsBegin, fsEnd).get(0);
t.setMorph(null);
}
mergeCas.removeFsFromIndexes(fs);
}
}
// if slot bearing annotation, clean
for (FeatureStructure baseFs : slotFeaturesToReset) {
for (Feature roleFeature : baseFs.getType().getFeatures()) {
if (isLinkMode(baseFs, roleFeature)) {
// FeatureStructure roleFs = baseFs.getFeatureValue(f);
ArrayFS roleFss = (ArrayFS) WebAnnoCasUtil.getFeatureFS(baseFs, roleFeature.getShortName());
if (roleFss == null) {
continue;
}
Map<String, ArrayFS> roleAnnosPerUser = new HashMap<>();
setAllRoleAnnosOnPosition(aJCases, roleAnnosPerUser, users, baseFs, roleFeature);
List<FeatureStructure> linkFSes = new LinkedList<>(Arrays.asList(roleFss.toArray()));
for (FeatureStructure roleFs : roleFss.toArray()) {
if (isRoleAgree(roleFs, roleAnnosPerUser)) {
for (Feature targetFeature : roleFs.getType().getFeatures()) {
if (isBasicFeature(targetFeature)) {
continue;
}
if (!targetFeature.getShortName().equals("target")) {
continue;
}
AnnotationFS targetFs = (AnnotationFS) roleFs.getFeatureValue(targetFeature);
if (targetFs == null) {
continue;
}
Map<String, List<FeatureStructure>> targetAnnosPerUser = new HashMap<>();
getAllAnnosOnPosition(aJCases, targetAnnosPerUser, users, targetFs);
// do not agree on targets
if (!isAgree(targetFs, targetAnnosPerUser)) {
linkFSes.remove(roleFs);
}
}
} else // do not agree on some role features
{
linkFSes.remove(roleFs);
}
}
ArrayFS array = baseFs.getCAS().createArrayFS(linkFSes.size());
array.copyFromArray(linkFSes.toArray(new FeatureStructure[linkFSes.size()]), 0, 0, linkFSes.size());
baseFs.setFeatureValue(roleFeature, array);
}
}
}
return aJCases.get(WebAnnoConst.CURATION_USER);
}
use of org.apache.uima.cas.FeatureStructure in project webanno by webanno.
the class MergeCas method isSameAnno.
/**
* Return true if these two annotations agree on every non slot features
*/
private static boolean isSameAnno(FeatureStructure aFirstFS, FeatureStructure aSeconFS) {
for (Feature f : getAllFeatures(aFirstFS)) {
// the annotations are already in the same position
if (isBasicFeature(f)) {
continue;
}
if (!isLinkMode(aFirstFS, f)) {
// check if attache type exists
try {
FeatureStructure attachFs1 = aFirstFS.getFeatureValue(f);
FeatureStructure attachFs2 = aSeconFS.getFeatureValue(f);
if (!isSameAnno(attachFs1, attachFs2)) {
return false;
}
} catch (Exception e) {
// no attach type -- continue
}
// assume null as equal
if (getFeatureValue(aFirstFS, f) == null && getFeatureValue(aSeconFS, f) == null) {
continue;
}
if (getFeatureValue(aFirstFS, f) == null && getFeatureValue(aSeconFS, f) != null) {
return false;
}
if (getFeatureValue(aFirstFS, f) != null && getFeatureValue(aSeconFS, f) == null) {
return false;
}
if (!getFeatureValue(aFirstFS, f).equals(getFeatureValue(aSeconFS, f))) {
return false;
}
}
}
return true;
}
use of org.apache.uima.cas.FeatureStructure in project webanno by webanno.
the class CopyAnnotationTest method copyLinkToEmptyTest.
@Test
public void copyLinkToEmptyTest() throws Exception {
JCas mergeCAs = JCasFactory.createJCas(DiffUtils.createMultiLinkWithRoleTestTypeSytem("f1"));
Type type = mergeCAs.getTypeSystem().getType(DiffUtils.HOST_TYPE);
Feature feature = type.getFeatureByBaseName("f1");
AnnotationFS mergeFs = DiffUtils.makeLinkHostMultiSPanFeatureFS(mergeCAs, 0, 0, feature, "A");
FeatureStructure copyFS = DiffUtils.makeLinkFS(mergeCAs, "slot1", 0, 0);
List<FeatureStructure> linkFs = new ArrayList<>();
linkFs.add(copyFS);
WebAnnoCasUtil.setLinkFeatureValue(mergeFs, type.getFeatureByBaseName("links"), linkFs);
JCas jcasA = JCasFactory.createJCas(DiffUtils.createMultiLinkWithRoleTestTypeSytem("f1"));
DiffUtils.makeLinkHostMultiSPanFeatureFS(jcasA, 0, 0, feature, "A", DiffUtils.makeLinkFS(jcasA, "slot1", 0, 0));
Map<String, List<JCas>> casByUser = new LinkedHashMap<>();
casByUser.put("user1", asList(mergeCAs));
casByUser.put("user2", asList(jcasA));
List<String> entryTypes = asList(DiffUtils.HOST_TYPE);
CasDiff2.SpanDiffAdapter adapter = new CasDiff2.SpanDiffAdapter(DiffUtils.HOST_TYPE);
adapter.addLinkFeature("links", "role", "target");
List<? extends CasDiff2.DiffAdapter> diffAdapters = asList(adapter);
CasDiff2.DiffResult diff = CasDiff2.doDiff(entryTypes, diffAdapters, CasDiff2.LinkCompareBehavior.LINK_TARGET_AS_LABEL, casByUser);
assertEquals(0, diff.getDifferingConfigurationSets().size());
assertEquals(0, diff.getIncompleteConfigurationSets().size());
}
Aggregations