/*
* Copyright 2015
* Ubiquitous Knowledge Processing (UKP) Lab
* 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.dkpro.core.io.brat.internal.model;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.fasterxml.jackson.core.JsonGenerator;
public class BratConfiguration
{
private Map<String, BratEventAnnotationDecl> events = new LinkedHashMap<>();
private Map<String, BratTextAnnotationDecl> entities = new LinkedHashMap<>();
private Map<String, BratRelationAnnotationDecl> relations = new LinkedHashMap<>();
private Map<String, BratAttributeDecl> attributes = new LinkedHashMap<>();
private Map<String, BratLabelDecl> labels = new LinkedHashMap<>();
private Map<String, BratDrawingDecl> drawings = new LinkedHashMap<>();
public void addEventDecl(BratEventAnnotationDecl aDecl)
{
events.put(aDecl.getType(), aDecl);
}
public BratEventAnnotationDecl getEventDecl(String aType)
{
return events.get(aType);
}
public void addEntityDecl(String aSuperType, String aType)
{
entities.put(aType, new BratTextAnnotationDecl(aSuperType, aType));
}
public BratAttributeDecl addAttributeDecl(String aOwner, Collection<String> aSubTypes,
String aAttribute, String aValue)
{
String key = aOwner + ":" + aAttribute;
List<String> targets = new ArrayList<String>();
targets.add(aOwner);
targets.addAll(aSubTypes);
BratAttributeDecl attr = attributes.get(key);
if (attr == null) {
attr = new BratAttributeDecl(aAttribute, targets.toArray(new String[targets.size()]));
attributes.put(key, attr);
}
attr.addValue(aValue);
return attr;
}
public void addRelationDecl(String aSuperType, String aType, String aArg1Label,
String aArg2Label)
{
String key = aType;
BratRelationAnnotationDecl attr = relations.get(key);
if (attr == null) {
attr = new BratRelationAnnotationDecl(aSuperType, aType, aArg1Label, aArg2Label);
relations.put(key, attr);
}
}
private void write(Writer aWriter, int aDepth, BratAnnotationDecl aDecl,
Map<String, ? extends BratAnnotationDecl> aAll, Collection<BratAnnotationDecl> aRendered)
throws IOException
{
// Avoid rendering the same declaration multiple times
if (aRendered.contains(aDecl)) {
return;
}
// Do we have a declaration of the supertype? If yes, we have to wait until the supertype
// has been rendered (and will be rendered as part of the supertypes rendering cycle).
if (aDepth == 0 && aAll.containsKey(aDecl.getSuperType())) {
return;
}
// Render the current declaration
for (int i = 0; i < aDepth; i++) {
aWriter.append('\t');
}
aWriter.append(aDecl.toString());
aWriter.append('\n');
aRendered.add(aDecl);
// Render subtypes
for (BratAnnotationDecl decl : aDecl.getSubTypes()) {
write(aWriter, aDepth + 1, decl, aAll, aRendered);
}
}
private void fillSubtypes(Map<String, ? extends BratAnnotationDecl> aDecls)
{
for (BratAnnotationDecl decl : aDecls.values()) {
BratAnnotationDecl superDecl = aDecls.get(decl.getSuperType());
if (superDecl != null) {
superDecl.addSubType(decl);
}
}
}
public void addLabelDecl(String aType, String... aLabels)
{
labels.put(aType, new BratLabelDecl(aType, aLabels));
}
public void addDrawingDecl(BratAttributeDecl aAttribute)
{
drawings.put(aAttribute.getName(), new BratAttributeDrawingDecl(aAttribute));
}
public BratDrawingDecl getDrawingDecl(String aType)
{
return drawings.get(aType);
}
public void addDrawingDecl(BratDrawingDecl aDecl)
{
drawings.put(aDecl.getType(), aDecl);
}
public boolean hasDrawingDecl(String aType)
{
return drawings.containsKey(aType);
}
private void writeLabelAndStyle(JsonGenerator aJG, BratAnnotationDecl aDecl)
throws IOException
{
BratLabelDecl label = labels.get(aDecl.getType());
if (label != null) {
label.write(aJG);
}
BratDrawingDecl draw = drawings.get(aDecl.getType());
if (draw != null) {
draw.write(aJG);
}
}
public void write(JsonGenerator aJG)
throws IOException
{
aJG.writeStartObject();
aJG.writeFieldName("entity_types");
aJG.writeStartArray();
for (BratTextAnnotationDecl decl : entities.values()) {
aJG.writeStartObject();
aJG.writeStringField("type", decl.getType());
writeLabelAndStyle(aJG, decl);
aJG.writeEndObject();
}
aJG.writeEndArray();
aJG.writeFieldName("entity_attribute_types");
aJG.writeStartArray();
for (BratAttributeDecl decl : attributes.values()) {
aJG.writeStartObject();
aJG.writeStringField("type", decl.getName());
aJG.writeFieldName("values");
aJG.writeStartArray();
aJG.writeStartObject();
for (String value : decl.getValues()) {
aJG.writeFieldName(value);
aJG.writeStartObject();
aJG.writeStringField("glyph", value);
aJG.writeEndObject();
}
aJG.writeEndObject();
aJG.writeEndArray();
aJG.writeEndObject();
}
aJG.writeEndArray();
aJG.writeFieldName("relation_types");
aJG.writeStartArray();
for (BratRelationAnnotationDecl decl : relations.values()) {
aJG.writeStartObject();
aJG.writeStringField("type", decl.getType());
aJG.writeFieldName("args");
aJG.writeStartArray();
// Arg 1
aJG.writeStartObject();
aJG.writeStringField("role", decl.getArg1Label());
aJG.writeFieldName("targets");
aJG.writeStartArray();
aJG.writeString(decl.getArg1Range());
aJG.writeEndArray();
aJG.writeEndObject();
// Arg 2
aJG.writeStartObject();
aJG.writeStringField("role", decl.getArg2Label());
aJG.writeFieldName("targets");
aJG.writeStartArray();
aJG.writeString(decl.getArg2Range());
aJG.writeEndArray();
aJG.writeEndObject();
aJG.writeEndArray();
writeLabelAndStyle(aJG, decl);
aJG.writeEndObject();
}
aJG.writeEndArray();
aJG.writeFieldName("event_types");
aJG.writeStartArray();
for (BratEventAnnotationDecl decl : events.values()) {
aJG.writeStartObject();
aJG.writeStringField("type", decl.getType());
aJG.writeFieldName("arcs");
aJG.writeStartArray();
for (BratEventArgumentDecl arg : decl.getSlots()) {
aJG.writeStartObject();
aJG.writeStringField("type", arg.getName());
aJG.writeEndObject();
}
aJG.writeEndArray();
writeLabelAndStyle(aJG, decl);
aJG.writeEndObject();
}
aJG.writeEndArray();
aJG.writeEndObject();
}
public void writeVisualConfiguration(Writer aWriter)
throws IOException
{
aWriter.append("[labels]\n");
for (BratLabelDecl e : labels.values()) {
aWriter.append(e.toString());
aWriter.append('\n');
}
aWriter.append('\n');
aWriter.append("[drawing]\n");
for (BratDrawingDecl e : drawings.values()) {
aWriter.append(e.toString());
aWriter.append('\n');
}
}
public void writeAnnotationConfiguration(Writer aWriter)
throws IOException
{
Set<BratAnnotationDecl> rendered = new HashSet<>();
fillSubtypes(entities);
fillSubtypes(relations);
fillSubtypes(events);
aWriter.append("[entities]\n");
for (BratTextAnnotationDecl e : entities.values()) {
write(aWriter, 0, e, entities, rendered);
}
aWriter.append('\n');
aWriter.append("[relations]\n");
for (BratRelationAnnotationDecl e : relations.values()) {
write(aWriter, 0, e, entities, rendered);
}
aWriter.append("<OVERLAP>\tArg1:<ENTITY>, Arg2:<ENTITY>, <OVL-TYPE>:<ANY>");
aWriter.append('\n');
aWriter.append('\n');
aWriter.write("[events]\n");
for (BratEventAnnotationDecl e : events.values()) {
write(aWriter, 0, e, events, rendered);
}
aWriter.append('\n');
aWriter.append("[attributes]\n");
for (BratAttributeDecl e : attributes.values()) {
aWriter.append(e.toString());
aWriter.append('\n');
}
}
}