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);
}
}
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);
}
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));
}
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.");
}
}
}
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;
}
Aggregations