/*
* Copyright 2012
* Ubiquitous Knowledge Processing (UKP) Lab and FG Language Technology
* Technische Universität Darmstadt
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.tudarmstadt.ukp.clarin.webanno.brat.annotation;
import static de.tudarmstadt.ukp.clarin.webanno.api.annotation.util.TypeUtil.getAdapter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.uima.jcas.JCas;
import org.apache.wicket.model.IModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataRetrievalFailureException;
import de.tudarmstadt.ukp.clarin.webanno.api.AnnotationSchemaService;
import de.tudarmstadt.ukp.clarin.webanno.api.DocumentService;
import de.tudarmstadt.ukp.clarin.webanno.api.annotation.adapter.TypeAdapter;
import de.tudarmstadt.ukp.clarin.webanno.api.annotation.coloring.ColoringStrategy;
import de.tudarmstadt.ukp.clarin.webanno.api.annotation.model.AnnotatorStateImpl;
import de.tudarmstadt.ukp.clarin.webanno.brat.adapter.TypeRenderer;
import de.tudarmstadt.ukp.clarin.webanno.brat.message.GetDocumentResponse;
import de.tudarmstadt.ukp.clarin.webanno.brat.render.BratRenderer;
import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationDocument;
import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature;
import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer;
import de.tudarmstadt.ukp.clarin.webanno.model.Mode;
import de.tudarmstadt.ukp.clarin.webanno.support.JSONUtil;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
/**
* Displays a BRAT visualisation and fills it with data from an {@link AnnotationDocument}. We do
* not use a CAS as model object because the CAS is large and does not serialize well. It is easier
* to drive this component using a reference to the CAS (here an {@link AnnotationDocument}) and let
* the component fetch the associated CAS itself when necessary.
*/
public class BratAnnotationDocumentVisualizer
extends BratVisualizer
{
private final static Logger LOG = LoggerFactory.getLogger(BratAnnotationDocumentVisualizer.class);
private static final long serialVersionUID = -5898873898138122798L;
private boolean dirty = true;
private String docData = EMPTY_DOC;
private @SpringBean DocumentService repository;
private @SpringBean AnnotationSchemaService annotationService;
public BratAnnotationDocumentVisualizer(String id, IModel<AnnotationDocument> aModel)
{
super(id, aModel);
}
public void setModel(IModel<AnnotationDocument> aModel)
{
setDefaultModel(aModel);
}
public void setModelObject(AnnotationDocument aModel)
{
setDefaultModelObject(aModel);
}
@SuppressWarnings("unchecked")
public IModel<AnnotationDocument> getModel()
{
return (IModel<AnnotationDocument>) getDefaultModel();
}
public AnnotationDocument getModelObject()
{
return (AnnotationDocument) getDefaultModelObject();
}
@Override
protected void onModelChanged()
{
super.onModelChanged();
dirty = true;
}
@Override
protected String getDocumentData()
{
if (!dirty) {
return docData;
}
dirty = false;
// Clear the rendered document
docData = EMPTY_DOC;
// Check if a document is set
if (getModelObject() == null) {
return docData;
}
// Get CAS from the repository
JCas jCas = null;
try {
jCas = repository.readAnnotationCas(getModelObject());
}
catch (IOException | DataRetrievalFailureException e) {
LOG.error("Unable to read annotation document", e);
error("Unable to read annotation document: " + ExceptionUtils.getRootCauseMessage(e));
}
// Generate BRAT object model from CAS
GetDocumentResponse response = new GetDocumentResponse();
response.setText(jCas.getDocumentText());
AnnotatorStateImpl bratAnnotatorModel = new AnnotatorStateImpl(Mode.ANNOTATION);
BratRenderer.renderTokenAndSentence(jCas, response, bratAnnotatorModel);
Map<String[], Queue<String>> colorQueues = new HashMap<>();
for (AnnotationLayer layer : bratAnnotatorModel.getAnnotationLayers()) {
if (layer.getName().equals(Token.class.getName())) {
continue;
}
List<AnnotationFeature> features = annotationService.listAnnotationFeature(layer);
List<AnnotationFeature> invisibleFeatures = new ArrayList<AnnotationFeature>();
for (AnnotationFeature feature : features) {
if (!feature.isVisible()) {
invisibleFeatures.add(feature);
}
}
features.removeAll(invisibleFeatures);
ColoringStrategy coloringStrategy = ColoringStrategy.getBestStrategy(annotationService,
layer, bratAnnotatorModel.getPreferences(), colorQueues);
TypeAdapter typeAdapter = getAdapter(annotationService, layer);
TypeRenderer typeRenderer = BratRenderer.getRenderer(typeAdapter);
typeRenderer.render(jCas, features, response, bratAnnotatorModel, coloringStrategy);
}
// Serialize BRAT object model to JSON
try {
docData = JSONUtil.toInterpretableJsonString(response);
}
catch (IOException e) {
error(ExceptionUtils.getRootCauseMessage(e));
}
return docData;
}
}