org.lappsgrid.serialization.lif.Container.groovy Maven / Gradle / Ivy
/*
* Copyright 2014 The Language Application Grid
*
* 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 org.lappsgrid.serialization.lif
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonPropertyOrder
import org.lappsgrid.serialization.LappsIOException
import org.lappsgrid.serialization.LifException
import org.lappsgrid.serialization.Utils
/**
* Container objects are the outer wrapper for all LIF objects.
*
* A Lappsgrid Container consists of:
*
* - the text content (with possibly the language).
* - some metadata
* - a list of {@link View}s
*
* The Container object also contains helper methods to find the {@link View}s
* containing a given annotation type:
*
* For example:
*
*
* String token = "http://vocab.lappsgrid.org/Token"
* Container container = new Container();
* container.setText("Goodbye cruel world, I am leaving you today.");
* container.setLanguage("en");
* View view = container.newView();
* view.addAnnotation("tok1", token, 0, 7);
* ...
* List views = container.findViewsThatContain(token);
* assertEquals(view, views.get(0));
*
*
*
* Since LIF objects are serialized to JSON-LD they also define a {@code context}. By
* default all LIF objects refer to the remote context document
* http://vocab.lappsgrid.org/context-1.0.0.jsonld.
* However, a local (in-line) context can be used with allows the context to be
* manipulated at runtime.
*
*
* Container container = new Container(ContextType.LOCAL);
* Map context = (Map) container.getContext();
* context.put("@vocab", "http://example.com/custom/vocabulary");
*
*
*
* @author Keith Suderman
*/
@JsonPropertyOrder(["context","metadata","text","views"])
public class Container {
public enum ContextType {
LOCAL, REMOTE
}
/** The text that is to be annotated. */
@JsonProperty('text')
Content content;
/** Any meta-data attached to this container. */
Map metadata
/** The list of annotations that have been created for the text. */
List views
@JsonProperty("@context")
Object context
public static final String REMOTE_CONTEXT = "http://vocab.lappsgrid.org/context-1.0.0.jsonld"
//TODO Keeping the local context up to date is a never ending process.
public static final Map LOCAL_CONTEXT = [
'@vocab':'http://vocab.lappsgrid.org/',
'meta':'http://vocab.lappsgrid.org/metadata/',
'lif':'http://vocab.lappsgrid.org/interchange/',
'types':'http://vocab.lappsgrid.org/types/',
'metadata': 'meta:metadata',
'contains': 'meta:contains',
'producer': 'meta:producer',
'url': ['@id':'meta:url', '@type':'@id'],
'type':['@id':'meta:type', '@type':'@id'],
'version':'meta:version',
'text':'lif:text',
'views': 'lif:views',
'annotations': 'lif:annotations',
'tokenization': 'types:tokenization/',
'tagset': 'types:posType/',
'ner': 'types:ner/',
'coref': "types:coref/",
'chunk': "types:chunk/",
'lookup': "types:lookup/",
'token': "http://vocab.lappsgrid.org/Token#",
"common": "http://vocab.lappsgrid.org/Annotation#",
"id":"common:id",
"start":"common:start",
"label":"common:label",
"end":"common:end",
"pos":"token:pos",
"lemma":"token:lemma",
"kind":"token:kind",
"length":"token:length",
"orth":"token:orth",
]
/** Default (empty) constructor uses the remote context. */
public Container() {
this(ContextType.REMOTE)
}
public Container(Container container) {
this.content = new Content(container.content)
this.metadata = Utils.deepCopy(container.metadata)
this.views = Utils.deepCopy(container.views)
if (container.context instanceof String) {
this.context = container.context
}
else {
this.context = Utils.deepCopy((Map)container.context)
}
}
protected Container(ContextType type) {
content = new Content()
// mapper = new ObjectMapper()
metadata = new HashMap();
views = new ArrayList()
if (type == ContextType.LOCAL) {
context = LOCAL_CONTEXT
}
else {
context = REMOTE_CONTEXT
}
}
public Container(Map map) {
initFromMap(map)
}
@JsonIgnore
void setLanguage(String lang) {
content.language = lang
}
@JsonIgnore
String getLanguage() {
return content.language
}
@JsonIgnore
void setText(String text) {
this.content.value = text
}
@JsonIgnore
String getText() {
return this.content.value
}
View newView(String id) throws LifException {
View view = findViewById(id);
if (view != null) {
throw new LifException("ID is already in use.")
}
view = new View()
view.id = id
views << view
return view
}
View newView() throws LifException {
return newView(generateId())
}
void addView(View view) {
if (view.id == null) {
view.id = generateId();
}
else if (findViewById(view.id) != null) {
throw new LifException("Duplicate ID for view.")
}
this.views << view
}
View getView(int index) {
if (index >= 0 && index < views.size()) {
return views[index]
}
return null
}
View findViewById(String id) {
views.find { it.id == id }
}
List findViewsThatContain(String type) {
views.findAll { it?.metadata?.contains && it.metadata.contains[type] }
}
List findViewsThatContainBy(String type, String producer) {
views.findAll { it?.metadata?.contains && it.metadata.contains[type]?.producer == producer }
}
void setMetadata(String name, Object value) {
if (this.metadata == null) {
this.metadata = [:]
}
this.metadata[name] = value
}
Object getMetadata(String name) {
if (this.metadata == null) {
return null
}
return this.metadata[name]
}
void define(String name, String iri) throws LappsIOException
{
if (!(this.context instanceof Map)) {
throw new LappsIOException("Can not define a context field when a remote context is used.")
}
if (this.context[name]) {
throw new LappsIOException("Context for ${name} already defined.")
}
this.context[name] = [
'@id': iri,
'@type': '@id'
]
}
protected String generateId() {
int index = views.size() + 1
int offset = -1
String id = "v${index}"
while (findViewById(id) != null) {
id = "v${index}-${++offset}";
}
return id;
}
private void initFromMap(Map map) {
if (map == null) {
return
}
if (map['@context']) {
this.context = Utils.deepCopy(map['@context'])
}
else {
this.context = Container.REMOTE_CONTEXT
}
this.content = new Content()//value:map.text.value, language:map.text.language)
this.text = map.text['@value']
this.language = map.text['@language']
this.metadata = Utils.deepCopy(map.metadata)
// this.views = Utils.deepCopy(map.views)
// this.metadata = [:]
// map.metadata.each { name, value ->
// this.metadata[name] = value
// }
this.views = []
map.views.each { v ->
// View view = new View(v)
this.views << new View(v)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy