Search in sources :

Example 1 with RelationAdapter

use of de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter in project webanno by webanno.

the class RelationRenderer method render.

@Override
public void render(final CAS aCas, List<AnnotationFeature> aFeatures, VDocument aResponse, int aWindowBegin, int aWindowEnd) {
    RelationAdapter typeAdapter = getTypeAdapter();
    Type type;
    Type spanType;
    try {
        type = getType(aCas, typeAdapter.getAnnotationTypeName());
        spanType = getType(aCas, typeAdapter.getAttachTypeName());
    } catch (IllegalArgumentException e) {
        // CAS does not contain any instances of them
        return;
    }
    List<AnnotationFeature> visibleFeatures = aFeatures.stream().filter(f -> f.isVisible() && f.isEnabled()).collect(Collectors.toList());
    Feature dependentFeature = type.getFeatureByBaseName(typeAdapter.getTargetFeatureName());
    Feature governorFeature = type.getFeatureByBaseName(typeAdapter.getSourceFeatureName());
    Feature arcSpanFeature = spanType.getFeatureByBaseName(typeAdapter.getAttachFeatureName());
    FeatureStructure dependentFs;
    FeatureStructure governorFs;
    Map<Integer, Set<Integer>> relationLinks = getRelationLinks(aCas, aWindowBegin, aWindowEnd, type, dependentFeature, governorFeature, arcSpanFeature);
    // if this is a governor for more than one dependent, avoid duplicate yield
    List<Integer> yieldDeps = new ArrayList<>();
    // Index mapping annotations to the corresponding rendered arcs
    Map<AnnotationFS, VArc> annoToArcIdx = new HashMap<>();
    for (AnnotationFS fs : selectCovered(aCas, type, aWindowBegin, aWindowEnd)) {
        if (typeAdapter.getAttachFeatureName() != null) {
            dependentFs = fs.getFeatureValue(dependentFeature).getFeatureValue(arcSpanFeature);
            governorFs = fs.getFeatureValue(governorFeature).getFeatureValue(arcSpanFeature);
        } else {
            dependentFs = fs.getFeatureValue(dependentFeature);
            governorFs = fs.getFeatureValue(governorFeature);
        }
        String bratTypeName = typeAdapter.getEncodedTypeName();
        Map<String, String> features = renderLabelFeatureValues(typeAdapter, fs, visibleFeatures);
        if (dependentFs == null || governorFs == null) {
            StringBuilder message = new StringBuilder();
            message.append("Relation [" + typeAdapter.getLayer().getName() + "] with id [" + getAddr(fs) + "] has loose ends - cannot render.");
            if (typeAdapter.getAttachFeatureName() != null) {
                message.append("\nRelation [" + typeAdapter.getLayer().getName() + "] attached to feature [" + typeAdapter.getAttachFeatureName() + "].");
            }
            message.append("\nDependent: " + dependentFs);
            message.append("\nGovernor: " + governorFs);
            RequestCycle requestCycle = RequestCycle.get();
            IPageRequestHandler handler = PageRequestHandlerTracker.getLastHandler(requestCycle);
            Page page = (Page) handler.getPage();
            page.warn(message.toString());
            continue;
        }
        VArc arc = new VArc(typeAdapter.getLayer(), fs, bratTypeName, governorFs, dependentFs, features);
        arc.addLazyDetails(getLazyDetails(typeAdapter, fs, aFeatures));
        annoToArcIdx.put(fs, arc);
        aResponse.add(arc);
        // Render errors if required features are missing
        renderRequiredFeatureErrors(visibleFeatures, fs, aResponse);
        if (relationLinks.keySet().contains(getAddr(governorFs)) && !yieldDeps.contains(getAddr(governorFs))) {
            yieldDeps.add(getAddr(governorFs));
            // sort the annotations (begin, end)
            List<Integer> sortedDepFs = new ArrayList<>(relationLinks.get(getAddr(governorFs)));
            sortedDepFs.sort(comparingInt(arg0 -> selectAnnotationByAddr(aCas, arg0).getBegin()));
            String cm = getYieldMessage(aCas, sortedDepFs);
            aResponse.add(new VComment(governorFs, VCommentType.YIELD, cm));
        }
    }
    for (RelationLayerBehavior behavior : behaviors) {
        behavior.onRender(typeAdapter, aResponse, annoToArcIdx);
    }
}
Also used : AnnotationFS(org.apache.uima.cas.text.AnnotationFS) Page(org.apache.wicket.Page) VCommentType(de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VCommentType) LoggerFactory(org.slf4j.LoggerFactory) RelationLayerBehavior(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationLayerBehavior) CAS(org.apache.uima.cas.CAS) Feature(org.apache.uima.cas.Feature) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Type(org.apache.uima.cas.Type) RequestCycle(org.apache.wicket.request.cycle.RequestCycle) Map(java.util.Map) PageRequestHandlerTracker(org.apache.wicket.request.cycle.PageRequestHandlerTracker) WebAnnoCasUtil.selectAnnotationByAddr(de.tudarmstadt.ukp.clarin.webanno.api.annotation.util.WebAnnoCasUtil.selectAnnotationByAddr) FeatureStructure(org.apache.uima.cas.FeatureStructure) LayerSupportRegistry(de.tudarmstadt.ukp.clarin.webanno.api.annotation.layer.LayerSupportRegistry) WebAnnoCasUtil.getAddr(de.tudarmstadt.ukp.clarin.webanno.api.annotation.util.WebAnnoCasUtil.getAddr) Comparator.comparingInt(java.util.Comparator.comparingInt) Logger(org.slf4j.Logger) Collections.emptyList(java.util.Collections.emptyList) VArc(de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VArc) VComment(de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VComment) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) Collectors(java.util.stream.Collectors) RelationAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter) CasUtil.selectCovered(org.apache.uima.fit.util.CasUtil.selectCovered) List(java.util.List) ConcurrentSkipListSet(java.util.concurrent.ConcurrentSkipListSet) AnnotationFeature(de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature) IPageRequestHandler(org.apache.wicket.core.request.handler.IPageRequestHandler) CasUtil.getType(org.apache.uima.fit.util.CasUtil.getType) AnnotationAwareOrderComparator(org.springframework.core.annotation.AnnotationAwareOrderComparator) VDocument(de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VDocument) FeatureSupportRegistry(de.tudarmstadt.ukp.clarin.webanno.api.annotation.feature.FeatureSupportRegistry) Set(java.util.Set) ConcurrentSkipListSet(java.util.concurrent.ConcurrentSkipListSet) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) RequestCycle(org.apache.wicket.request.cycle.RequestCycle) ArrayList(java.util.ArrayList) Page(org.apache.wicket.Page) Feature(org.apache.uima.cas.Feature) AnnotationFeature(de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature) FeatureStructure(org.apache.uima.cas.FeatureStructure) AnnotationFS(org.apache.uima.cas.text.AnnotationFS) AnnotationFeature(de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature) RelationAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter) RelationLayerBehavior(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationLayerBehavior) IPageRequestHandler(org.apache.wicket.core.request.handler.IPageRequestHandler) VComment(de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VComment) VCommentType(de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VCommentType) Type(org.apache.uima.cas.Type) CasUtil.getType(org.apache.uima.fit.util.CasUtil.getType) VArc(de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VArc)

Example 2 with RelationAdapter

use of de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter in project webanno by webanno.

the class AnnotationDetailEditorPanel method actionReverse.

@Override
public void actionReverse(AjaxRequestTarget aTarget) throws IOException, AnnotationException {
    aTarget.addChildren(getPage(), IFeedback.class);
    CAS cas = getEditorCas();
    AnnotatorState state = getModelObject();
    AnnotationFS idFs = selectAnnotationByAddr(cas, state.getSelection().getAnnotation().getId());
    cas.removeFsFromIndexes(idFs);
    AnnotationFS originFs = selectAnnotationByAddr(cas, state.getSelection().getOrigin());
    AnnotationFS targetFs = selectAnnotationByAddr(cas, state.getSelection().getTarget());
    List<FeatureState> featureStates = getModelObject().getFeatureStates();
    TypeAdapter adapter = annotationService.getAdapter(state.getSelectedAnnotationLayer());
    if (adapter instanceof RelationAdapter) {
        // If no features, still create arc #256
        AnnotationFS arc = ((RelationAdapter) adapter).add(state.getDocument(), state.getUser().getUsername(), targetFs, originFs, cas);
        state.getSelection().setAnnotation(new VID(getAddr(arc)));
        for (FeatureState featureState : featureStates) {
            adapter.setFeatureValue(state.getDocument(), state.getUser().getUsername(), cas, getAddr(arc), featureState.feature, featureState.value);
        }
    } else {
        error("chains cannot be reversed");
        return;
    }
    // persist changes
    editorPage.writeEditorCas(cas);
    int sentenceNumber = getSentenceNumber(cas, originFs.getBegin());
    state.setFocusUnitIndex(sentenceNumber);
    state.getDocument().setSentenceAccessed(sentenceNumber);
    autoScroll(cas);
    state.rememberFeatures();
    // in case the user re-reverse it
    state.getSelection().reverseArc();
    onChange(aTarget);
}
Also used : VID(de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.VID) AnnotationFS(org.apache.uima.cas.text.AnnotationFS) RelationAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter) CAS(org.apache.uima.cas.CAS) AnnotatorState(de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.AnnotatorState) TypeAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.TypeAdapter) FeatureState(de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.FeatureState)

Example 3 with RelationAdapter

use of de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter in project webanno by webanno.

the class AnnotationDetailEditorPanel method deleteAnnotation.

private void deleteAnnotation(CAS aCas, AnnotatorState state, AnnotationFS fs, AnnotationLayer layer, TypeAdapter adapter) {
    RequestCycle.get().find(AjaxRequestTarget.class).ifPresent(_target -> _target.addChildren(getPage(), IFeedback.class));
    // point to it directly or indirectly via the attachFeature.
    if (adapter instanceof SpanAdapter) {
        for (AttachedAnnotation rel : annotationService.getAttachedRels(layer, fs)) {
            RelationAdapter relationAdapter = (RelationAdapter) annotationService.findAdapter(state.getProject(), rel.getRelation());
            relationAdapter.delete(state.getDocument(), state.getUser().getUsername(), aCas, new VID(rel.getRelation()));
            info(generateMessage(relationAdapter.getLayer(), null, true));
        }
    }
    // to be deleted: the link feature must be the type of the FS or it must be generic.
    if (adapter instanceof SpanAdapter) {
        for (AnnotationFeature linkFeature : annotationService.listAttachedLinkFeatures(layer)) {
            Type linkHostType = CasUtil.getType(aCas, linkFeature.getLayer().getName());
            for (FeatureStructure linkHostFS : CasUtil.selectFS(aCas, linkHostType)) {
                List<LinkWithRoleModel> links = adapter.getFeatureValue(linkFeature, linkHostFS);
                Iterator<LinkWithRoleModel> i = links.iterator();
                boolean modified = false;
                while (i.hasNext()) {
                    LinkWithRoleModel link = i.next();
                    if (link.targetAddr == getAddr(fs)) {
                        i.remove();
                        info("Cleared slot [" + link.role + "] in feature [" + linkFeature.getUiName() + "] on [" + linkFeature.getLayer().getUiName() + "]");
                        LOG.debug("Cleared slot [" + link.role + "] in feature [" + linkFeature.getName() + "] on annotation [" + getAddr(linkHostFS) + "]");
                        modified = true;
                    }
                }
                if (modified) {
                    setFeature(linkHostFS, linkFeature, links);
                    // If the currently armed slot is part of this link, then we disarm the slot
                    // to avoid the armed slot no longer pointing at the index which the user
                    // had selected it to point at.
                    FeatureState armedFeature = state.getArmedFeature();
                    if (armedFeature != null && WebAnnoCasUtil.getAddr(linkHostFS) == armedFeature.vid.getId() && armedFeature.feature.equals(linkFeature)) {
                        state.clearArmedSlot();
                    }
                }
            }
        }
    }
    // relation.
    if (adapter instanceof RelationAdapter) {
    // Do nothing ;)
    }
    // Actually delete annotation
    adapter.delete(state.getDocument(), state.getUser().getUsername(), aCas, state.getSelection().getAnnotation());
    info(generateMessage(state.getSelectedAnnotationLayer(), null, true));
}
Also used : RelationAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter) LinkWithRoleModel(de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.LinkWithRoleModel) FeatureState(de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.FeatureState) AjaxRequestTarget(org.apache.wicket.ajax.AjaxRequestTarget) VID(de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.VID) FeatureStructure(org.apache.uima.cas.FeatureStructure) Type(org.apache.uima.cas.Type) SpanAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.SpanAdapter) IFeedback(org.apache.wicket.feedback.IFeedback) AttachedAnnotation(de.tudarmstadt.ukp.clarin.webanno.api.AttachedAnnotation) AnnotationFeature(de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature)

Example 4 with RelationAdapter

use of de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter in project webanno by webanno.

the class AnnotationDetailEditorPanel method createNewAnnotation.

private void createNewAnnotation(AjaxRequestTarget aTarget, TypeAdapter aAdapter, CAS aCas) throws AnnotationException, IOException {
    AnnotatorState state = getModelObject();
    if (state.getSelection().isArc()) {
        if (aAdapter instanceof SpanAdapter) {
            error("Layer [" + aAdapter.getLayer().getUiName() + "] does not support arc annotation.");
            aTarget.addChildren(getPage(), IFeedback.class);
        } else if (aAdapter instanceof RelationAdapter) {
            createNewRelationAnnotation((RelationAdapter) aAdapter, aCas);
        } else if (aAdapter instanceof ChainAdapter) {
            createNewChainLinkAnnotation((ChainAdapter) aAdapter, aCas);
        } else {
            throw new IllegalStateException("I don't know how to use [" + aAdapter.getClass().getSimpleName() + "] in this situation.");
        }
    } else {
        if (aAdapter instanceof SpanAdapter) {
            createNewSpanAnnotation(aTarget, (SpanAdapter) aAdapter, aCas);
        } else if (aAdapter instanceof ChainAdapter) {
            createNewChainElement(aTarget, (ChainAdapter) aAdapter, aCas);
        } else {
            throw new IllegalStateException("I don't know how to use [" + aAdapter.getClass().getSimpleName() + "] in this situation.");
        }
    }
}
Also used : RelationAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter) AnnotatorState(de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.AnnotatorState) SpanAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.SpanAdapter) ChainAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.ChainAdapter)

Example 5 with RelationAdapter

use of de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter in project webanno by webanno.

the class DanglingRelationsCheck method check.

@Override
public boolean check(Project aProject, CAS aCas, List<LogMessage> aMessages) {
    boolean ok = true;
    for (AnnotationFS fs : aCas.getAnnotationIndex()) {
        Type t = fs.getType();
        Feature sourceFeat = t.getFeatureByBaseName(FEAT_REL_SOURCE);
        Feature targetFeat = t.getFeatureByBaseName(FEAT_REL_TARGET);
        // Is this a relation?
        if (!(sourceFeat != null && targetFeat != null)) {
            continue;
        }
        RelationAdapter relationAdapter = (RelationAdapter) annotationService.findAdapter(aProject, fs);
        Feature relationSourceAttachFeature = null;
        Feature relationTargetAttachFeature = null;
        if (relationAdapter.getAttachFeatureName() != null) {
            relationSourceAttachFeature = sourceFeat.getRange().getFeatureByBaseName(relationAdapter.getAttachFeatureName());
            relationTargetAttachFeature = targetFeat.getRange().getFeatureByBaseName(relationAdapter.getAttachFeatureName());
        }
        FeatureStructure source = fs.getFeatureValue(sourceFeat);
        FeatureStructure target = fs.getFeatureValue(targetFeat);
        // Here we get the annotations that the relation is pointing to in the UI
        if (source != null && relationSourceAttachFeature != null) {
            source = (AnnotationFS) source.getFeatureValue(relationSourceAttachFeature);
        }
        if (target != null && relationTargetAttachFeature != null) {
            target = (AnnotationFS) target.getFeatureValue(relationTargetAttachFeature);
        }
        // Does it have null endpoints?
        if (source == null || target == null) {
            StringBuilder message = new StringBuilder();
            message.append("Relation [" + relationAdapter.getLayer().getName() + "] with id [" + getAddr(fs) + "] has loose ends - cannot identify attached annotations.");
            if (relationAdapter.getAttachFeatureName() != null) {
                message.append("\nRelation [" + relationAdapter.getLayer().getName() + "] attached to feature [" + relationAdapter.getAttachFeatureName() + "].");
            }
            message.append("\nSource: " + source);
            message.append("\nTarget: " + target);
            aMessages.add(new LogMessage(this, INFO, "%s", message));
            ok = false;
        }
    }
    return ok;
}
Also used : FeatureStructure(org.apache.uima.cas.FeatureStructure) AnnotationFS(org.apache.uima.cas.text.AnnotationFS) RelationAdapter(de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter) Type(org.apache.uima.cas.Type) LogMessage(de.tudarmstadt.ukp.clarin.webanno.support.logging.LogMessage) Feature(org.apache.uima.cas.Feature)

Aggregations

RelationAdapter (de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationAdapter)14 AnnotationFS (org.apache.uima.cas.text.AnnotationFS)11 AnnotationFeature (de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature)7 Type (org.apache.uima.cas.Type)7 ArrayList (java.util.ArrayList)6 Feature (org.apache.uima.cas.Feature)6 CAS (org.apache.uima.cas.CAS)5 FeatureStructure (org.apache.uima.cas.FeatureStructure)5 VID (de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.VID)4 SpanAdapter (de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.SpanAdapter)3 VComment (de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VComment)3 VDocument (de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.model.VDocument)3 AnnotationLayer (de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer)3 SourceDocument (de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument)3 Set (java.util.Set)3 CasUtil.getType (org.apache.uima.fit.util.CasUtil.getType)3 AttachedAnnotation (de.tudarmstadt.ukp.clarin.webanno.api.AttachedAnnotation)2 RelationCrossSentenceBehavior (de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationCrossSentenceBehavior)2 RelationLayerBehavior (de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.RelationLayerBehavior)2 FeatureSupportRegistry (de.tudarmstadt.ukp.clarin.webanno.api.annotation.feature.FeatureSupportRegistry)2