/**
* Copyright (C) 2010 - 2016 52°North Initiative for Geospatial Open Source
* Software GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* If the program is linked with libraries which are licensed under one of
* the following licenses, the combination of the program with the linked
* library is not considered a "derivative work" of the program:
*
* • Apache License, version 2.0
* • Apache Software License, version 1.0
* • GNU Lesser General Public License, version 3
* • Mozilla Public License, versions 1.0, 1.1 and 2.0
* • Common Development and Distribution License (CDDL), version 1.0
*
* Therefore the distribution of the program linked with libraries licensed
* under the aforementioned licenses, is permitted by the copyright holders
* if the distribution is compliant with both the GNU General Public
* License version 2 and the aforementioned licenses.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*/
package org.n52.wps.server.r.syntax;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.n52.wps.io.data.IData;
import org.n52.wps.server.r.data.RDataTypeRegistry;
import org.n52.wps.server.r.data.RTypeDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Defines Syntax and Semantics for Annotations in R Skripts
*
* Syntax in (raw) BNF: <RAnnotation> ::= <StartKey> <AttributeSequence> <EndKey> <StartKey> <Attributequence>
* ::= <RAnnotationTypeInstance>.getStartKey() <RAnnotationTypeInstance>.getAttributeSequence() <EndKey> ::=
* RSeparator.ANNOTATION_END.getKey() <AttributeSequence> ::= {<RAttributeInstance>.getKey()
* ATRIBUTE_VALUE_SEPARATOR} <Attributevalue> {ATTRIBUTE_SEPARATOR <RAttributeSequence>}
*
* @author Matthias Hinz
*/
public class RAnnotation {
private RAnnotationType type;
private HashMap<RAttribute, Object> attributeHash = new HashMap<RAttribute, Object>();
private static Logger LOGGER = LoggerFactory.getLogger(RAnnotation.class);
/**
*
* @param type
* @param attributeHash
* @throws IOException
* if AttributHash is not valid for any cause
* @throws RAnnotationException
*/
public RAnnotation(RAnnotationType type, HashMap<RAttribute, Object> attributeHash) throws IOException,
RAnnotationException {
super();
this.type = type;
this.attributeHash.putAll(attributeHash);
this.type.validateDescription(this);
LOGGER.debug("NEW " + toString());
}
public RAnnotationType getType() {
return this.type;
}
/**
*
* @param attr
* @return Returns Attribute value as Java Object in case it is more complex
* @throws RAnnotationException
*/
public Object getObjectValue(RAttribute attr) throws RAnnotationException {
Object out = this.attributeHash.get(attr);
if (out == null && attr.getDefValue() != null)
out = attr.getDefValue();
else if (attr == RAttribute.ENCODING)
return getRDataType().getEncoding();
if (attr == RAttribute.SCHEMA)
return getRDataType().getSchema();
return out;
}
/**
*
* @param attr
* @return Returns an attribute value as string. Suits for most literal data types
* @throws RAnnotationException
*/
public String getStringValue(RAttribute attr) throws RAnnotationException {
Object value = getObjectValue(attr);
if (value == null)
return null;
return value.toString();
}
public static List<RAnnotation> filterAnnotations(Collection<RAnnotation> annotations,
RAnnotationType type,
RAttribute attribute,
String value) throws RAnnotationException {
LinkedList<RAnnotation> out = new LinkedList<RAnnotation>();
for (RAnnotation annotation : annotations) {
// type filter:
if (type == null || annotation.getType() == type) {
// attribute - value filter:
if (attribute == null || value == null || annotation.getStringValue(attribute).equalsIgnoreCase(value)) {
out.add(annotation);
}
}
}
return out;
}
public static List<RAnnotation> filterAnnotations(List<RAnnotation> annotations, RAttribute attribute, String value) throws RAnnotationException {
return filterAnnotations(annotations, null, attribute, value);
}
public static List<RAnnotation> filterAnnotations(List<RAnnotation> annotations, RAnnotationType type) throws RAnnotationException {
return filterAnnotations(annotations, type, null, null);
}
public static RAnnotation filterFirstMatchingAnnotation(List<RAnnotation> annotations,
RAttribute attribute,
String value) throws RAnnotationException {
Iterator<RAnnotation> iterator = filterAnnotations(annotations, null, attribute, value).iterator();
if (iterator.hasNext())
return iterator.next();
return null;
}
public static RAnnotation filterFirstMatchingAnnotation(List<RAnnotation> annotations, RAnnotationType type) throws RAnnotationException {
Iterator<RAnnotation> iterator = filterAnnotations(annotations, type, null, null).iterator();
if (iterator.hasNext())
return iterator.next();
return null;
}
/**
*
* @param rClass
* - value referring to RAttribute.TYPE
* @return null or supported IData class for rClass - string
* @throws RAnnotationException
*/
public static Class< ? extends IData> getDataClass(String rClass) throws RAnnotationException {
RTypeDefinition rType = RDataTypeRegistry.getInstance().getType(rClass);
return rType.getIDataClass();
}
public Class< ? extends IData> getDataClass() throws RAnnotationException {
String rClass = getStringValue(RAttribute.TYPE);
return getDataClass(rClass);
}
/**
* Checks if the type - argument of an annotation refers to complex data
*
* @return
* @throws RAnnotationException
*/
public static boolean isComplex(String rClass) throws RAnnotationException {
return RDataTypeRegistry.getInstance().getType(rClass).isComplex();
}
public RTypeDefinition getRDataType() throws RAnnotationException {
return RDataTypeRegistry.getInstance().getType(getStringValue(RAttribute.TYPE));
}
/**
* @return true, if the type attribute of an Annotation refers to a complex data type
* @throws RAnnotationException
*/
public boolean isComplex() throws RAnnotationException {
return isComplex(this.getStringValue(RAttribute.TYPE));
}
/**
*
* @return null or supported ProcessdescriptionType
* @throws RAnnotationException
*/
public String getProcessDescriptionType() throws RAnnotationException {
String type = getStringValue(RAttribute.TYPE);
RTypeDefinition rdt = RDataTypeRegistry.getInstance().getType(type);
if (rdt != null)
return rdt.getProcessKey();
return null;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("RAnnotation [type=");
builder.append(this.type);
builder.append(", attributeHash=");
builder.append(this.attributeHash);
builder.append("]");
return builder.toString();
}
public boolean containsKey(RAttribute key) {
return this.attributeHash.containsKey(key);
}
public void setAttribute(RAttribute key, Object value) {
this.attributeHash.put(key, value);
}
}