421 lines
14 KiB
Java
421 lines
14 KiB
Java
/**
|
||
* 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());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|