52n-wps-algorithm-gcube/src/main/java/org/n52/wps/server/AbstractSelfDescribingAlgor...

421 lines
14 KiB
Java
Raw Normal View History

/**
* Copyright (C) 2007 - 2016 52°North Initiative for Geospatial Open Source
* Software GmbH
*
* 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.n52.wps.server;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.opengis.ows.x11.DomainMetadataType;
import net.opengis.wps.x100.CRSsType;
import net.opengis.wps.x100.ComplexDataCombinationType;
import net.opengis.wps.x100.ComplexDataCombinationsType;
import net.opengis.wps.x100.ComplexDataDescriptionType;
import net.opengis.wps.x100.InputDescriptionType;
import net.opengis.wps.x100.LiteralInputType;
import net.opengis.wps.x100.LiteralOutputType;
import net.opengis.wps.x100.OutputDescriptionType;
import net.opengis.wps.x100.ProcessDescriptionType;
import net.opengis.wps.x100.ProcessDescriptionType.DataInputs;
import net.opengis.wps.x100.ProcessDescriptionType.ProcessOutputs;
import net.opengis.wps.x100.ProcessDescriptionsDocument;
import net.opengis.wps.x100.ProcessDescriptionsDocument.ProcessDescriptions;
import net.opengis.wps.x100.SupportedCRSsType;
import net.opengis.wps.x100.SupportedCRSsType.Default;
import net.opengis.wps.x100.SupportedComplexDataInputType;
import net.opengis.wps.x100.SupportedComplexDataType;
import org.n52.wps.FormatDocument.Format;
import org.n52.wps.io.GeneratorFactory;
import org.n52.wps.io.IGenerator;
import org.n52.wps.io.IParser;
import org.n52.wps.io.ParserFactory;
import org.n52.wps.io.data.IBBOXData;
import org.n52.wps.io.data.IComplexData;
import org.n52.wps.io.data.ILiteralData;
import org.n52.wps.server.observerpattern.IObserver;
import org.n52.wps.server.observerpattern.ISubject;
public abstract class AbstractSelfDescribingAlgorithm extends AbstractAlgorithm implements ISubject{
@Override
protected ProcessDescriptionType initializeDescription() {
ProcessDescriptionsDocument document = ProcessDescriptionsDocument.Factory.newInstance();
ProcessDescriptions processDescriptions = document.addNewProcessDescriptions();
ProcessDescriptionType processDescription = processDescriptions.addNewProcessDescription();
processDescription.setStatusSupported(true);
processDescription.setStoreSupported(true);
processDescription.setProcessVersion("1.0.0");
//1. Identifier
processDescription.addNewIdentifier().setStringValue(this.getClass().getName());
processDescription.addNewTitle().setStringValue(this.getClass().getCanonicalName());
//2. Inputs
List<String> identifiers = this.getInputIdentifiers();
DataInputs dataInputs = null;
if(identifiers.size()>0){
dataInputs = processDescription.addNewDataInputs();
}
for(String identifier : identifiers){
InputDescriptionType dataInput = dataInputs.addNewInput();
dataInput.setMinOccurs(getMinOccurs(identifier));
dataInput.setMaxOccurs(getMaxOccurs(identifier));
dataInput.addNewIdentifier().setStringValue(identifier);
dataInput.addNewTitle().setStringValue(identifier);
Class<?> inputDataTypeClass = this.getInputDataType(identifier);
Class<?>[] interfaces = inputDataTypeClass.getInterfaces();
//we have to add this because of the new AbstractLiteralDataBinding class
if(interfaces.length == 0){
interfaces = inputDataTypeClass.getSuperclass().getInterfaces();
}
for(Class<?> implementedInterface : interfaces){
if(implementedInterface.equals(ILiteralData.class)){
LiteralInputType literalData = dataInput.addNewLiteralData();
String inputClassType = "";
Constructor<?>[] constructors = inputDataTypeClass.getConstructors();
for(Constructor<?> constructor : constructors){
Class<?>[] parameters = constructor.getParameterTypes();
if(parameters.length==1){
inputClassType = parameters[0].getSimpleName();
}
}
if(inputClassType.length()>0){
DomainMetadataType datatype = literalData.addNewDataType();
datatype.setReference("xs:"+inputClassType.toLowerCase());
literalData.addNewAnyValue();
}
}else if(implementedInterface.equals(IBBOXData.class)){
SupportedCRSsType bboxData = dataInput.addNewBoundingBoxData();
String[] supportedCRSAray = getSupportedCRSForBBOXInput(identifier);
for(int i = 0; i<supportedCRSAray.length; i++){
if(i==0){
Default defaultCRS = bboxData.addNewDefault();
defaultCRS.setCRS(supportedCRSAray[0]);
if(supportedCRSAray.length==1){
CRSsType supportedCRS = bboxData.addNewSupported();
supportedCRS.addCRS(supportedCRSAray[0]);
}
}else{
if(i==1){
CRSsType supportedCRS = bboxData.addNewSupported();
supportedCRS.addCRS(supportedCRSAray[1]);
}else{
bboxData.getSupported().addCRS(supportedCRSAray[i]);
}
}
}
}else if(implementedInterface.equals(IComplexData.class)){
SupportedComplexDataInputType complexData = dataInput.addNewComplexData();
List<IParser> parsers = ParserFactory.getInstance().getAllParsers();
List<IParser> foundParsers = new ArrayList<IParser>();
for(IParser parser : parsers) {
Class<?>[] supportedClasses = parser.getSupportedDataBindings();
for(Class<?> clazz : supportedClasses){
if(clazz.equals(inputDataTypeClass)){
foundParsers.add(parser);
}
}
}
addInputFormats(complexData, foundParsers);
}
}
}
//3. Outputs
ProcessOutputs dataOutputs = processDescription.addNewProcessOutputs();
List<String> outputIdentifiers = this.getOutputIdentifiers();
for(String identifier : outputIdentifiers){
OutputDescriptionType dataOutput = dataOutputs.addNewOutput();
dataOutput.addNewIdentifier().setStringValue(identifier);
dataOutput.addNewTitle().setStringValue(identifier);
dataOutput.addNewAbstract().setStringValue(identifier);
Class<?> outputDataTypeClass = this.getOutputDataType(identifier);
Class<?>[] interfaces = outputDataTypeClass.getInterfaces();
//we have to add this because of the new AbstractLiteralDataBinding class
if(interfaces.length == 0){
interfaces = outputDataTypeClass.getSuperclass().getInterfaces();
}
for(Class<?> implementedInterface : interfaces){
if(implementedInterface.equals(ILiteralData.class)){
LiteralOutputType literalData = dataOutput.addNewLiteralOutput();
String outputClassType = "";
Constructor<?>[] constructors = outputDataTypeClass.getConstructors();
for(Constructor<?> constructor : constructors){
Class<?>[] parameters = constructor.getParameterTypes();
if(parameters.length==1){
outputClassType = parameters[0].getSimpleName();
}
}
if(outputClassType.length()>0){
literalData.addNewDataType().setReference("xs:"+outputClassType.toLowerCase());
}
}else if(implementedInterface.equals(IBBOXData.class)){
SupportedCRSsType bboxData = dataOutput.addNewBoundingBoxOutput();
String[] supportedCRSAray = getSupportedCRSForBBOXOutput(identifier);
for(int i = 0; i<supportedCRSAray.length; i++){
if(i==0){
Default defaultCRS = bboxData.addNewDefault();
defaultCRS.setCRS(supportedCRSAray[0]);
if(supportedCRSAray.length==1){
CRSsType supportedCRS = bboxData.addNewSupported();
supportedCRS.addCRS(supportedCRSAray[0]);
}
}else{
if(i==1){
CRSsType supportedCRS = bboxData.addNewSupported();
supportedCRS.addCRS(supportedCRSAray[1]);
}else{
bboxData.getSupported().addCRS(supportedCRSAray[i]);
}
}
}
}else if(implementedInterface.equals(IComplexData.class)){
SupportedComplexDataType complexData = dataOutput.addNewComplexOutput();
List<IGenerator> generators = GeneratorFactory.getInstance().getAllGenerators();
List<IGenerator> foundGenerators = new ArrayList<IGenerator>();
for(IGenerator generator : generators) {
Class<?>[] supportedClasses = generator.getSupportedDataBindings();
for(Class<?> clazz : supportedClasses){
if(clazz.equals(outputDataTypeClass)){
foundGenerators.add(generator);
}
}
}
addOutputFormats(complexData, foundGenerators);
}
}
}
return document.getProcessDescriptions().getProcessDescriptionArray(0);
}
/**
* Override this class for BBOX input data to set supported mime types. The first one in the resulting array will be the default one.
* @param identifier ID of the input BBOXType
* @return
*/
public String[] getSupportedCRSForBBOXInput(String identifier){
return new String[0];
}
/**
* Override this class for BBOX output data to set supported mime types. The first one in the resulting array will be the default one.
* @param identifier ID of the input BBOXType
* @return
*/
public String[] getSupportedCRSForBBOXOutput(String identifier){
return new String[0];
}
public BigInteger getMinOccurs(String identifier){
return new BigInteger("1");
}
public BigInteger getMaxOccurs(String identifier){
return new BigInteger("1");
}
public abstract List<String> getInputIdentifiers();
public abstract List<String> getOutputIdentifiers();
private List<IObserver> observers = new ArrayList<IObserver>();
private Object state = null;
public Object getState() {
return state;
}
public void update(Object state) {
this.state = state;
notifyObservers();
}
public void addObserver(IObserver o) {
observers.add(o);
}
public void removeObserver(IObserver o) {
observers.remove(o);
}
public void notifyObservers() {
Iterator<IObserver> i = observers.iterator();
while (i.hasNext()) {
IObserver o = (IObserver) i.next();
o.update(this);
}
}
@Override
public List<String> getErrors() {
List<String> errors = new ArrayList<String>();
return errors;
}
private void addInputFormats(SupportedComplexDataInputType complexData,
List<IParser> foundParsers) {
ComplexDataCombinationsType supportedInputFormat = complexData
.addNewSupported();
for (int i = 0; i < foundParsers.size(); i++) {
IParser parser = foundParsers.get(i);
Format[] supportedFullFormats = parser.getSupportedFullFormats();
if (complexData.getDefault() == null) {
ComplexDataCombinationType defaultInputFormat = complexData
.addNewDefault();
/*
* default format will be the first config format
*/
Format format = supportedFullFormats[0];
ComplexDataDescriptionType defaultFormat = defaultInputFormat
.addNewFormat();
defaultFormat.setMimeType(format.getMimetype());
String encoding = format.getEncoding();
if (encoding != null && !encoding.equals("")) {
defaultFormat.setEncoding(encoding);
}
String schema = format.getSchema();
if (schema != null && !schema.equals("")) {
defaultFormat.setSchema(schema);
}
}
for (int j = 0; j < supportedFullFormats.length; j++) {
/*
* create supportedFormat for each mimetype, encoding, schema
* composition mimetypes can have several encodings and schemas
*/
Format format1 = supportedFullFormats[j];
/*
* add one format for this mimetype
*/
ComplexDataDescriptionType supportedFormat = supportedInputFormat
.addNewFormat();
supportedFormat.setMimeType(format1.getMimetype());
if (format1.getEncoding() != null) {
supportedFormat.setEncoding(format1.getEncoding());
}
if (format1.getSchema() != null) {
supportedFormat.setSchema(format1.getSchema());
}
}
}
}
private void addOutputFormats(SupportedComplexDataType complexData,
List<IGenerator> foundGenerators) {
ComplexDataCombinationsType supportedOutputFormat = complexData
.addNewSupported();
for (int i = 0; i < foundGenerators.size(); i++) {
IGenerator generator = foundGenerators.get(i);
Format[] supportedFullFormats = generator.getSupportedFullFormats();
if (complexData.getDefault() == null) {
ComplexDataCombinationType defaultInputFormat = complexData
.addNewDefault();
/*
* default format will be the first config format
*/
Format format = supportedFullFormats[0];
ComplexDataDescriptionType defaultFormat = defaultInputFormat
.addNewFormat();
defaultFormat.setMimeType(format.getMimetype());
String encoding = format.getEncoding();
if (encoding != null && !encoding.equals("")) {
defaultFormat.setEncoding(encoding);
}
String schema = format.getSchema();
if (schema != null && !schema.equals("")) {
defaultFormat.setSchema(schema);
}
}
for (int j = 0; j < supportedFullFormats.length; j++) {
/*
* create supportedFormat for each mimetype, encoding, schema
* composition mimetypes can have several encodings and schemas
*/
Format format1 = supportedFullFormats[j];
/*
* add one format for this mimetype
*/
ComplexDataDescriptionType supportedFormat = supportedOutputFormat
.addNewFormat();
supportedFormat.setMimeType(format1.getMimetype());
if (format1.getEncoding() != null) {
supportedFormat.setEncoding(format1.getEncoding());
}
if (format1.getSchema() != null) {
supportedFormat.setSchema(format1.getSchema());
}
}
}
}
}