Lucio Lelii 7 years ago
commit b95572fe28

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>52n-wps-algorithm-d4s</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

@ -0,0 +1,5 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

@ -0,0 +1,5 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

@ -0,0 +1,38 @@
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.
This project includes:
52North WPS Algorithm API under Apache License, Version 2.0
52North WPS Commons under Apache License, Version 2.0
52North WPS Input/Output API under Apache License, Version 2.0
Commons Codec under The Apache Software License, Version 2.0
Commons IO under The Apache Software License, Version 2.0
Guava: Google Core Libraries for Java under The Apache Software License, Version 2.0
Hamcrest Core under New BSD License
Joda time under Apache 2
JUnit under Common Public License Version 1.0
OGC OWS schema (spec. v1.1.0) under The Apache Software License, Version 2.0
OGC WPS schema (spec. v1.0.0) under The Apache Software License, Version 2.0
SLF4J API Module under MIT License
SLF4J Simple Binding under MIT License
stax-utils under BSD
Stax2 API under The BSD License
W3C xlink schema (spec. v1.1.0) under The Apache Software License, Version 2.0
Woodstox under The Apache Software License, Version 2.0
WPS-Config under The Apache Software License, Version 2.0
Xalan Java under The Apache Software License, Version 2.0
Xalan Java Serializer under The Apache Software License, Version 2.0
XmlBeans under The Apache Software License, Version 2.0

@ -0,0 +1 @@
${gcube.license}

@ -0,0 +1,69 @@
The gCube System - ${name}
--------------------------------------------------
${description}
${gcube.description}
${gcube.funding}
Version
--------------------------------------------------
${version} (${buildDate})
Please see the file named "changelog.xml" in this directory for the release notes.
Authors
--------------------------------------------------
* Gianpaolo Coro (gianpaolo.coro-AT-isti.cnr.it),
Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" CNR, Pisa IT
Maintainers
-----------
* Gianpaolo Coro (gianpaolo.coro-AT-isti.cnr.it),
Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" CNR, Pisa IT
Download information
--------------------------------------------------
Source code is available from SVN:
${scm.url}
Binaries can be downloaded from the gCube website:
${gcube.website}
Installation
--------------------------------------------------
Installation documentation is available on-line in the gCube Wiki:
https://wiki.gcube-system.org/gcube/DataMiner_Installation
Documentation
--------------------------------------------------
Documentation is available on-line in the gCube Wiki:
https://wiki.gcube-system.org/gcube/DataMiner_Installation
Support
--------------------------------------------------
Bugs and support requests can be reported in the gCube issue tracking tool:
${gcube.issueTracking}
Licensing
--------------------------------------------------
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.

@ -0,0 +1,5 @@
<ReleaseNotes>
<Changeset component="${groupId}.${artifactId}.3-6-1" date="2017-07-05">
<Change>First Release</Change>
</Changeset>
</ReleaseNotes>

@ -0,0 +1,32 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>servicearchive</id>
<formats>
<format>tar.gz</format>
</formats>
<baseDirectory>/</baseDirectory>
<fileSets>
<fileSet>
<directory>${distroDirectory}</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>README</include>
<include>LICENSE</include>
<include>changelog.xml</include>
<include>profile.xml</include>
</includes>
<fileMode>755</fileMode>
<filtered>true</filtered>
</fileSet>
</fileSets>
<files>
<file>
<source>target/${build.finalName}.${project.packaging}</source>
<outputDirectory>/${artifactId}</outputDirectory>
</file>
</files>
</assembly>

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<Resource>
<ID></ID>
<Type>Service</Type>
<Profile>
<Description>${project.description}</Description>
<Class>DataAnalysis</Class>
<Name>${project.name}</Name>
<Version>1.0.0</Version>
<Packages>
<Software>
<Name>${project.name}</Name>
<Description>${project.description}</Description>
<Version>${version}</Version>
<MavenCoordinates>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</MavenCoordinates>
<Type>Service</Type>
<Files>
<File>${project.build.finalName}.${project.packaging}</File>
</Files>
</Software>
</Packages>
</Profile>
</Resource>

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>maven-parent</artifactId>
<groupId>org.gcube.tools</groupId>
<version>1.0.0</version>
<relativePath />
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.gcube.dataanalysis</groupId>
<artifactId>52n-wps-algorithm-gcube</artifactId>
<name>52North WPS Algorithm API modified for gcube</name>
<version>3.6.1-SNAPSHOT</version>
<description>API for implementation of algorithms to be exposed as web processes</description>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
</license>
</licenses>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>.</directory>
<includes>
<include>LICENSE</include>
<include>NOTICE</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<configuration>
<header>../misc/licenses/license_header_for_api_modules.txt</header>
</configuration>
</plugin>
<plugin>
<groupId>org.jasig.maven</groupId>
<artifactId>maven-notice-plugin</artifactId>
<configuration>
<noticeTemplate>../misc/licenses/NOTICE_for_api_modules.template</noticeTemplate>
<licenseMapping>
<param>../misc/licenses/license-mappings.xml</param>
</licenseMapping>
</configuration>
<executions>
<execution>
<id>check-licenses</id>
<phase />
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<dependency>
<groupId>org.n52.wps</groupId>
<artifactId>52n-wps-commons</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>org.n52.wps</groupId>
<artifactId>52n-wps-io</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<artifactId>52n-xml-wps-v100</artifactId>
<groupId>org.n52.sensorweb</groupId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.n52.wps</groupId>
<artifactId>52n-wps-config</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>n52-releases</id>
<name>52n Releases</name>
<url>http://52north.org/maven/repo/releases</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

@ -0,0 +1,50 @@
# Generated by org.codehaus.mojo.license.AddThirdPartyMojo
#-------------------------------------------------------------------------------
# Already used licenses in project :
# - Apache 2
# - Apache License
# - Apache-Style with the acknowledgment clause removed
# - BSD
# - BSD License
# - BSD License for HSQL
# - Common Development and Distribution License 1.0
# - Common Public License Version 1.0
# - EPSG database distribution license
# - Eclipse Public License 1.0
# - GNU GENERAL PUBLIC LICENSE Version 2, June 1991
# - HSQLDB License
# - Lesser General Public License (LGPL)
# - Lesser General Public License (LGPL), Version 2.1
# - MIT License
# - New BSD License
# - OGC copyright
# - Simplified BSD
# - Sun Binary Code License Agreement
# - The Apache Software License, Version 2.0
# - The BSD 2-Clause License
# - The BSD License
# - The GNU General Public License (GPL)
#-------------------------------------------------------------------------------
# Please fill the missing licenses for dependencies :
#
#
#Wed Jan 08 13:06:01 CET 2014
axis--axis-jaxrpc--1.4=The Apache Software License, Version 2.0
axis--axis-saaj--1.4=The Apache Software License, Version 2.0
axis--axis-wsdl4j--1.5.1=Common Public License Version 1.0
commons-discovery--commons-discovery--0.2=The Apache Software License, Version 2.0
edu.umn.gis--mapscript--6.0.3=
java3d--vecmath--1.3.2=The GNU General Public License (GPL)
javax.media--jai_codec--1.1.3=Sun Binary Code License Agreement
javax.media--jai_core--1.1.3=Sun Binary Code License Agreement
javax.media--jai_imageio--1.1=Sun Binary Code License Agreement
javax.servlet--servlet-api--2.5=Common Development and Distribution License 1.0
jdom--jdom--1.0=Apache-Style with the acknowledgment clause removed
jgridshift--jgridshift--1.0=Lesser General Public License (LGPL), Version 2.1
org.eclipse.emf--common--2.6.0=Eclipse Public License 1.0
org.eclipse.emf--ecore--2.6.1=Eclipse Public License 1.0
org.eclipse.xsd--xsd--2.6.0=Eclipse Public License 1.0
org.n52.wps--gmlpacket-2.0--0.4=GNU GENERAL PUBLIC LICENSE Version 2, June 1991
org.n52.wps--ogckml2.2--1.0.0=GNU GENERAL PUBLIC LICENSE Version 2, June 1991
picocontainer--picocontainer--1.2=The BSD 2-Clause License
xerces--xercesImpl--2.7.1=The Apache Software License, Version 2.0

@ -0,0 +1,37 @@
/**
* 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.algorithm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author tkunicki
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Algorithm {
String identifier() default "";
String title() default "";
String abstrakt() default ""; // 'abstract' is java reserved keyword
String version();
boolean storeSupported() default true;
boolean statusSupported() default true;
}

@ -0,0 +1,280 @@
/**
* 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.algorithm.annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.n52.wps.algorithm.annotation.AnnotationBinding.ExecuteMethodBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.InputBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.OutputBinding;
import org.n52.wps.algorithm.annotation.AnnotationParser.ComplexDataInputFieldAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.ComplexDataInputMethodAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.ComplexDataOutputFieldAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.ComplexDataOutputMethodAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.ExecuteAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.InputAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.LiteralDataInputFieldAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.LiteralDataInputMethodAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.LiteralDataOutputFieldAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.LiteralDataOutputMethodAnnotationParser;
import org.n52.wps.algorithm.annotation.AnnotationParser.OutputAnnotationParser;
import org.n52.wps.algorithm.descriptor.AlgorithmDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author tkunicki
*/
public class AnnotatedAlgorithmIntrospector {
private final static Logger LOGGER = LoggerFactory.getLogger(AnnotatedAlgorithmIntrospector.class);
private final static List<InputAnnotationParser<?,Field,?>> INPUT_FIELD_PARSERS;
private final static List<InputAnnotationParser<?,Method,?>> INPUT_METHOD_PARSERS;
private final static List<OutputAnnotationParser<?,Field,?>> OUTPUT_FIELD_PARSERS;
private final static List<OutputAnnotationParser<?,Method,?>> OUTPUT_METHOD_PARSERS;
private final static ExecuteAnnotationParser PROCESS_PARSER;
static {
List<InputAnnotationParser<?,Field,?>> inputFieldParsers =
new ArrayList<InputAnnotationParser<?,Field,?>>();
inputFieldParsers.add(new LiteralDataInputFieldAnnotationParser());
inputFieldParsers.add(new ComplexDataInputFieldAnnotationParser());
INPUT_FIELD_PARSERS = Collections.unmodifiableList(inputFieldParsers);
List<InputAnnotationParser<?,Method,?>> inputMethodParsers =
new ArrayList<InputAnnotationParser<?,Method,?>>();
inputMethodParsers.add(new LiteralDataInputMethodAnnotationParser());
inputMethodParsers.add(new ComplexDataInputMethodAnnotationParser());
INPUT_METHOD_PARSERS = Collections.unmodifiableList(inputMethodParsers);
List<OutputAnnotationParser<?,Field,?>> outputFieldParsers =
new ArrayList<OutputAnnotationParser<?,Field,?>>();
outputFieldParsers.add(new LiteralDataOutputFieldAnnotationParser());
outputFieldParsers.add(new ComplexDataOutputFieldAnnotationParser());
OUTPUT_FIELD_PARSERS = Collections.unmodifiableList(outputFieldParsers);
List<OutputAnnotationParser<?,Method,?>> outputMethodParsers =
new ArrayList<OutputAnnotationParser<?,Method,?>>();
outputMethodParsers.add(new LiteralDataOutputMethodAnnotationParser());
outputMethodParsers.add(new ComplexDataOutputMethodAnnotationParser());
OUTPUT_METHOD_PARSERS = Collections.unmodifiableList(outputMethodParsers);
PROCESS_PARSER = new ExecuteAnnotationParser();
}
private final static Map<Class<?>, AnnotatedAlgorithmIntrospector> INTROSPECTOR_MAP =
new HashMap<Class<?>, AnnotatedAlgorithmIntrospector>();
public static synchronized AnnotatedAlgorithmIntrospector getInstrospector(Class<?> algorithmClass) {
AnnotatedAlgorithmIntrospector introspector = INTROSPECTOR_MAP.get(algorithmClass);
if (introspector == null) {
introspector = new AnnotatedAlgorithmIntrospector(algorithmClass);
INTROSPECTOR_MAP.put(algorithmClass, introspector);
}
return introspector;
}
private Class<?> algorithmClass;
private AlgorithmDescriptor algorithmDescriptor;
private ExecuteMethodBinding executeMethodBinding;
private Map<String, AnnotationBinding.InputBinding<?, ?>> inputBindingMap;
private Map<String, AnnotationBinding.OutputBinding<?, ?>> outputBindingMap;
public AnnotatedAlgorithmIntrospector(Class<?> algorithmClass) {
this.algorithmClass = algorithmClass;
inputBindingMap = new LinkedHashMap<String, InputBinding<?, ?>>();
outputBindingMap = new LinkedHashMap<String, OutputBinding<?, ?>>();
parseClass();
inputBindingMap = Collections.unmodifiableMap(inputBindingMap);
outputBindingMap = Collections.unmodifiableMap(outputBindingMap);
}
//Modified by Gianpaolo Coro
private void parseClass() {
if (!algorithmClass.isAnnotationPresent(Algorithm.class)) {
throw new RuntimeException("Class isn't annotated with an Algorithm annotation");
}
boolean validContructor = false;
try {
Constructor defaultConstructor = algorithmClass.getConstructor(new Class[0]);
validContructor = (defaultConstructor.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC;
} catch (NoSuchMethodException ex) {
// inherit error message on fall through...
} catch (SecurityException ex) {
throw new RuntimeException("Current security policy limits use of reflection, error introspecting " + algorithmClass.getName());
}
if (!validContructor) {
throw new RuntimeException("Classes with Algorithm annotation require public no-arg constructor, error introspecting " + algorithmClass.getName());
}
AlgorithmDescriptor.Builder<?> algorithmBuilder = null;
Algorithm algorithm = algorithmClass.getAnnotation(Algorithm.class);
//MODIFICATIONS BY G CORO TO ACCOUNT FOR METHODS ORDER
List<Method> sortedMethods = new ArrayList<Method>();
List<Integer> methodsIdxs = new ArrayList<Integer>();
try{
for (Method m:algorithmClass.getDeclaredMethods()){
//System.out.println("Javaassist Analysing method "+m.getName());
ClassPool pool = ClassPool.getDefault();
ClassClassPath ccpath = new ClassClassPath(m.getDeclaringClass());
pool.insertClassPath(ccpath);
//System.out.println("Javaassist searching for canonical name "+m.getDeclaringClass().getCanonicalName());
CtClass cc = pool.get(m.getDeclaringClass().getCanonicalName());
//System.out.println("Javaassist cc "+cc.getName());
CtMethod javassistMethod = cc.getDeclaredMethod(m.getName());
//System.out.println("Javaassist method "+javassistMethod.getName());
int linenumber = javassistMethod.getMethodInfo().getLineNumber(0);
//System.out.println("Javaassist line number "+linenumber);
int i=0;
for (Integer methodsIdx :methodsIdxs){
if (methodsIdx>linenumber){
break;
}
i++;
}
sortedMethods.add(i,m);
methodsIdxs.add(i,linenumber);
}
}catch(Exception e){
LOGGER.warn("error getting method order",e);
}
Method[] sMethods = sortedMethods.toArray(new Method[sortedMethods.size()]);
algorithmBuilder = AlgorithmDescriptor.builder(
algorithm.identifier().length() > 0 ?
algorithm.identifier() :
algorithmClass.getCanonicalName());
algorithmBuilder.
title(algorithm.title()).
abstrakt(algorithm.abstrakt()).
version(algorithm.version()).
storeSupported(algorithm.storeSupported()).
statusSupported(algorithm.statusSupported());
parseElements(sMethods,
INPUT_METHOD_PARSERS,
OUTPUT_METHOD_PARSERS);
parseElements(algorithmClass.getDeclaredFields(),
INPUT_FIELD_PARSERS,
OUTPUT_FIELD_PARSERS);
for (Method method : sMethods) {
if (method.isAnnotationPresent(PROCESS_PARSER.getSupportedAnnotation())) {
ExecuteMethodBinding executeMethodBinding = PROCESS_PARSER.parse(method);
if (executeMethodBinding != null) {
if (this.executeMethodBinding != null) {
// we need to error out here because ordering of getDeclaredMethods() or
// getMethods() is not guarenteed to be consistent, if it were consistent
// maybe we could ignore this state, but having an algorithm behave
// differently betweeen runtimes would be bad...
throw new RuntimeException("Multiple execute method bindings encountered for class " + getClass().getCanonicalName());
}
this.executeMethodBinding = executeMethodBinding;
}
}
}
if(this.executeMethodBinding == null) {
throw new RuntimeException("No execute method binding for class " + this.algorithmClass.getCanonicalName());
}
for (InputBinding<?,?> inputBinding : inputBindingMap.values()) {
algorithmBuilder.addInputDescriptor(inputBinding.getDescriptor());
}
for (OutputBinding<?,?> outputBinding : outputBindingMap.values()) {
algorithmBuilder.addOutputDescriptor(outputBinding.getDescriptor());
}
algorithmDescriptor = algorithmBuilder.build();
}
public AlgorithmDescriptor getAlgorithmDescriptor() {
return algorithmDescriptor;
}
public ExecuteMethodBinding getExecuteMethodBinding() {
return executeMethodBinding;
}
public Map<String, AnnotationBinding.InputBinding<?, ?>> getInputBindingMap() {
return inputBindingMap;
}
public Map<String, AnnotationBinding.OutputBinding<?, ?>> getOutputBindingMap() {
return outputBindingMap;
}
public <M extends AccessibleObject & Member> void parseElements(
M members[],
List<InputAnnotationParser<?,M,?>> inputParser,
List<OutputAnnotationParser<?,M,?>> outputParser) {
for (M member : members) {
for (OutputAnnotationParser<?,M,?> parser : outputParser) {
if (member.isAnnotationPresent(parser.getSupportedAnnotation())) {
OutputBinding<?,?> binding = parser.parse(member);
if (binding != null) {
outputBindingMap.put(binding.getDescriptor().getIdentifier(), binding);
}
}
}
for (InputAnnotationParser<?,M,?> parser : inputParser) {
if (member.isAnnotationPresent(parser.getSupportedAnnotation())) {
InputBinding<?,?> binding = parser.parse(member);
if (binding != null) {
inputBindingMap.put(binding.getDescriptor().getIdentifier(), binding);
}
}
}
}
}
}

@ -0,0 +1,476 @@
/**
* 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.algorithm.annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.List;
import org.n52.wps.algorithm.descriptor.BoundDescriptor;
import org.n52.wps.algorithm.descriptor.InputDescriptor;
import org.n52.wps.algorithm.descriptor.OutputDescriptor;
import org.n52.wps.algorithm.util.ClassUtil;
import org.n52.wps.io.data.IData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author tkunicki
*/
public abstract class AnnotationBinding<M extends AccessibleObject & Member> {
private final static Logger LOGGER = LoggerFactory.getLogger(AnnotationBinding.class);
private M member;
public AnnotationBinding(M member) {
this.member = member;
}
public M getMember() {
return member;
}
protected boolean checkModifier() {
return (getMember().getModifiers() & Modifier.PUBLIC) != 0;
}
public abstract boolean validate();
public static class ExecuteMethodBinding extends AnnotationBinding<Method> {
public ExecuteMethodBinding(Method method) {
super(method);
}
@Override
public boolean validate() {
if (!checkModifier()) {
LOGGER.error("Method {} with Execute annotation can't be used, not public.", getMember());
return false;
}
// eh, do we really need to care about this?
if (!getMember().getReturnType().equals(void.class)) {
LOGGER.error("Method {} with Execute annotation can't be used, return type not void", getMember());
return false;
}
if (getMember().getParameterTypes().length != 0) {
LOGGER.error("Method {} with Execute annotation can't be used, method parameter count is > 0.", getMember());
return false;
}
return true;
}
public void execute(Object annotatedInstance) {
try {
getMember().invoke(annotatedInstance);
}catch (IllegalAccessException ex) {
throw new RuntimeException("Internal error executing process", ex);
} catch (IllegalArgumentException ex) {
throw new RuntimeException("Internal error executing process", ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause() == null ? ex : ex.getCause();
throw new RuntimeException(cause.getMessage(), cause);
}
}
}
public static abstract class DataBinding<M extends AccessibleObject & Member, D extends BoundDescriptor> extends AnnotationBinding<M> {
private D descriptor;
public DataBinding(M member) {
super(member);
}
public void setDescriptor(D descriptor) {
this.descriptor = descriptor;
}
public D getDescriptor() {
return descriptor;
}
public abstract Type getMemberType();
public Type getType() {
return getMemberType();
}
public Type getPayloadType() {
Type type = getType();
if (isTypeEnum()) {
return String.class;
}
if (type instanceof Class<?>) {
Class<?> inputClass = (Class<?>) type;
if (inputClass.isPrimitive()) {
return ClassUtil.wrap(inputClass);
}
}
return type;
}
public boolean isTypeEnum() {
Type inputType = getType();
return (inputType instanceof Class<?>) && ((Class<?>) inputType).isEnum();
}
}
public static abstract class InputBinding<M extends AccessibleObject & Member, D extends InputDescriptor> extends DataBinding<M,D> {
public InputBinding(M member) {
super(member);
}
@Override
public Type getType() {
Type memberType = getMemberType();
Type inputType = memberType;
if (memberType instanceof Class<?>) {
Class<?> memberClass = (Class<?>) memberType;
if (List.class.isAssignableFrom(memberClass)) {
// We treat List as List<? extends Object>
inputType = NOT_PARAMETERIZED_TYPE;
}
} else if (memberType instanceof ParameterizedType) {
ParameterizedType parameterizedMemberType = (ParameterizedType) memberType;
Class<?> rawClass = (Class<?>) parameterizedMemberType.getRawType();
if (List.class.isAssignableFrom(rawClass)) {
inputType = parameterizedMemberType.getActualTypeArguments()[0];
}
} else {
LOGGER.error("Unable to infer concrete type information for " + getMember());
}
return inputType;
}
public boolean isMemberTypeList() {
Type memberType = getMemberType();
if (memberType instanceof Class<?>) {
return List.class.isAssignableFrom((Class<?>) memberType);
} else if (memberType instanceof ParameterizedType) {
Class<?> rawClass = (Class<?>) ((ParameterizedType) memberType).getRawType();
return List.class.isAssignableFrom(rawClass);
} else {
LOGGER.error("Unable to infer concrete type information for " + getMember());
}
return false;
}
protected boolean checkType() {
Type inputPayloadType = getPayloadType();
Class<? extends IData> bindingClass = getDescriptor().getBinding();
try {
Class<?> bindingPayloadClass = bindingClass.getMethod("getPayload", (Class<?>[]) null).getReturnType();
if (inputPayloadType instanceof Class<?>) {
return ((Class<?>) inputPayloadType).isAssignableFrom(bindingPayloadClass);
} else if (inputPayloadType instanceof ParameterizedType) {
// i.e. List<FeatureCollection<SimpleFeatureType,SimpleFeature>>
return ((Class<?>) ((ParameterizedType) inputPayloadType).getRawType()).isAssignableFrom(bindingPayloadClass);
} else if (inputPayloadType instanceof WildcardType) {
// i.e. List<? extends String> or List<? super String>
WildcardType inputTypeWildcardType = (WildcardType) inputPayloadType;
Type[] lowerBounds = inputTypeWildcardType.getLowerBounds();
Type[] upperBounds = inputTypeWildcardType.getUpperBounds();
Class<?> lowerBoundClass = null;
Class<?> upperBoundClass = null;
if (lowerBounds != null && lowerBounds.length > 0) {
if (lowerBounds[0] instanceof Class<?>) {
lowerBoundClass = (Class<?>) lowerBounds[0];
} else if (lowerBounds[0] instanceof ParameterizedType) {
lowerBoundClass = (Class<?>) ((ParameterizedType) lowerBounds[0]).getRawType();
}
}
if (upperBounds != null && upperBounds.length > 0) {
if (upperBounds[0] instanceof Class<?>) {
upperBoundClass = (Class<?>) upperBounds[0];
} else if (upperBounds[0] instanceof ParameterizedType) {
upperBoundClass = (Class<?>) ((ParameterizedType) upperBounds[0]).getRawType();
}
}
return (upperBoundClass == null || upperBoundClass.isAssignableFrom(bindingPayloadClass)) && (lowerBounds == null || bindingPayloadClass.isAssignableFrom(lowerBoundClass));
} else {
LOGGER.error("Unable to infer assignability from type for " + getMember());
}
} catch (NoSuchMethodException e) {
return false;
}
return false;
}
public Object unbindInput(List<IData> boundValueList) {
Object value = null;
if (boundValueList != null && boundValueList.size() > 0) {
if (isMemberTypeList()) {
List valueList = new ArrayList(boundValueList.size());
for (IData bound : boundValueList) {
value = bound.getPayload();
if (isTypeEnum()) {
value = Enum.valueOf((Class<? extends Enum>)getType(), (String)value);
}
valueList.add(value);
}
value = valueList;
} else if (boundValueList.size() == 1) {
value = boundValueList.get(0).getPayload();
if (isTypeEnum()) {
value = Enum.valueOf((Class<? extends Enum>)getType(), (String)value);
}
}
}
return value;
}
public abstract void set(Object annotatedObject, List<IData> boundInputList);
}
public static abstract class OutputBinding<M extends AccessibleObject & Member, D extends OutputDescriptor> extends DataBinding<M,D> {
private Constructor<? extends IData> bindingConstructor;
public OutputBinding(M member) {
super(member);
}
protected boolean checkType( ) {
return getConstructor() != null;
}
public IData bindOutputValue(Object outputValue) {
try {
if (isTypeEnum()) {
outputValue = ((Enum<?>)outputValue).name();
}
return getConstructor().newInstance(outputValue);
} catch (InstantiationException ex) {
throw new RuntimeException("Internal error processing outputs", ex);
} catch (SecurityException ex) {
throw new RuntimeException("Internal error processing outputs", ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Internal error processing outputs", ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause() == null ? ex : ex.getCause();
throw new RuntimeException(cause.getMessage(), cause);
}
}
public abstract IData get(Object annotatedInstance);
private synchronized Constructor<? extends IData> getConstructor() {
if (bindingConstructor == null ){
try {
Class<? extends IData> bindingClass = getDescriptor().getBinding();
Class<?> outputPayloadClass = bindingClass.getMethod("getPayload", (Class<?>[]) null).getReturnType();
Type bindingPayloadType = getPayloadType();
if (bindingPayloadType instanceof Class<?>) {
Class<?> bindingPayloadClass = (Class<?>) bindingPayloadType;
if (bindingPayloadClass.isAssignableFrom(outputPayloadClass)) {
bindingConstructor = bindingClass.getConstructor(bindingPayloadClass);
}
}
} catch (NoSuchMethodException e) {
// error handling on fall-through
}
}
return bindingConstructor;
}
}
public static class InputFieldBinding<D extends InputDescriptor> extends InputBinding<Field, D> {
public InputFieldBinding(Field field) {
super(field);
}
@Override
public Type getMemberType() {
return getMember().getGenericType();
}
@Override
public boolean validate() {
if (!checkModifier()) {
LOGGER.error("Field {} with input annotation can't be used, not public.", getMember());
return false;
}
if (!(getDescriptor().getMaxOccurs().intValue() < 2 || isMemberTypeList())) {
LOGGER.error("Field {} with input annotation can't be used, maxOccurs > 1 and field is not of type List", getMember());
return false;
}
if (!checkType()) {
LOGGER.error("Field {} with input annotation can't be used, unable to safely assign field using binding payload type", getMember());
return false;
}
return true;
}
@Override
public void set(Object annotatedObject, List<IData> boundInputList) {
try {
getMember().set(annotatedObject, unbindInput(boundInputList));
} catch (IllegalArgumentException ex) {
throw new RuntimeException("Internal error processing inputs", ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Internal error processing inputs", ex);
}
}
}
public static class InputMethodBinding<D extends InputDescriptor> extends InputBinding<Method, D> {
public InputMethodBinding(Method method) {
super(method);
}
@Override
public Type getMemberType() {
Type[] genericParameterTypes = getMember().getGenericParameterTypes();
return (genericParameterTypes.length == 0) ? Void.class : genericParameterTypes[0];
}
@Override
public boolean validate() {
if (!checkModifier()) {
LOGGER.error("Field {} with input annotation can't be used, not public.", getMember());
return false;
}
if (!(getDescriptor().getMaxOccurs().intValue() < 2 || isMemberTypeList())) {
LOGGER.error("Field {} with input annotation can't be used, maxOccurs > 1 and field is not of type List", getMember());
return false;
}
if (!checkType()) {
LOGGER.error("Field {} with input annotation can't be used, unable to safely assign field using binding payload type", getMember());
return false;
}
return true;
}
@Override
public void set(Object annotatedObject, List<IData> boundInputList) {
try {
getMember().invoke(annotatedObject, unbindInput(boundInputList));
} catch (IllegalAccessException ex) {
throw new RuntimeException("Internal error processing inputs", ex);
} catch (IllegalArgumentException ex) {
throw new RuntimeException("Internal error processing inputs", ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause() == null ? ex : ex.getCause();
throw new RuntimeException(cause.getMessage(), cause);
}
}
}
public static class OutputFieldBinding<D extends OutputDescriptor> extends OutputBinding<Field, D> {
public OutputFieldBinding(Field field) {
super(field);
}
@Override
public Type getMemberType() {
return getMember().getGenericType();
}
@Override
public boolean validate() {
if (!checkModifier()) {
LOGGER.error("Field {} with output annotation can't be used, not public.", getMember());
return false;
}
if (!checkType()) {
LOGGER.error("Field {} with output annotation can't be used, unable to safely construct binding using field type", getMember());
return false;
}
return true;
}
@Override
public IData get(Object annotatedInstance) {
Object value;
try {
value = getMember().get(annotatedInstance);
} catch (IllegalArgumentException ex) {
throw new RuntimeException("Internal error processing inputs", ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Internal error processing inputs", ex);
}
return value == null ? null : bindOutputValue(value);
}
}
public static class OutputMethodBinding<D extends OutputDescriptor> extends OutputBinding<Method, D> {
public OutputMethodBinding(Method method) {
super(method);
}
@Override
public Type getMemberType() {
return getMember().getGenericReturnType();
}
@Override
public boolean validate() {
Method method = getMember();
if (method.getParameterTypes().length != 0) {
LOGGER.error("Method {} with output annotation can't be used, parameter count != 0", getMember());
return false;
}
if (!checkModifier()) {
LOGGER.error("Method {} with output annotation can't be used, not public", getMember());
return false;
}
if (!checkType()) {
LOGGER.error("Method {} with output annotation can't be used, unable to safely construct binding using method return type", getMember());
return false;
}
return true;
}
@Override
public IData get(Object annotatedInstance) {
Object value;
try {
value = getMember().invoke(annotatedInstance);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Internal error processing inputs", ex);
} catch (IllegalArgumentException ex) {
throw new RuntimeException("Internal error processing inputs", ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause() == null ? ex : ex.getCause();
throw new RuntimeException(cause.getMessage(), cause);
}
return value == null ? null : bindOutputValue(value);
}
}
// for example, a type reprecenting the <? extends Object> for types of List<? extends Object> or List
public final Type NOT_PARAMETERIZED_TYPE = new WildcardType() {
@Override public Type[] getUpperBounds() { return new Type[]{Object.class}; }
@Override public Type[] getLowerBounds() { return new Type[0]; }
};
}

@ -0,0 +1,324 @@
/**
* 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.algorithm.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.n52.wps.algorithm.annotation.AnnotationBinding.InputBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.InputFieldBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.InputMethodBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.OutputBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.OutputFieldBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.OutputMethodBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.ExecuteMethodBinding;
import org.n52.wps.algorithm.descriptor.BoundDescriptor;
import org.n52.wps.algorithm.descriptor.ComplexDataInputDescriptor;
import org.n52.wps.algorithm.descriptor.ComplexDataOutputDescriptor;
import org.n52.wps.algorithm.descriptor.InputDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataInputDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataOutputDescriptor;
import org.n52.wps.algorithm.descriptor.OutputDescriptor;
import org.n52.wps.algorithm.util.ClassUtil;
import org.n52.wps.io.BasicXMLTypeFactory;
import org.n52.wps.io.data.ILiteralData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author tkunicki
*/
public abstract class AnnotationParser<A extends Annotation, M extends AccessibleObject & Member, B extends AnnotationBinding<M>> {
public final static Logger LOGGER = LoggerFactory.getLogger(AnnotationParser.class);
public B parse(M member) {
A annotation = member.getAnnotation(getSupportedAnnotation());
return annotation == null ? null : parse(annotation, member);
}
public abstract B parse(A annotation, M member);
public abstract Class<? extends A> getSupportedAnnotation();
public static class ExecuteAnnotationParser extends AnnotationParser<Execute, Method, ExecuteMethodBinding> {
@Override
public ExecuteMethodBinding parse(Execute annotation, Method member) {
ExecuteMethodBinding annotationBinding = new ExecuteMethodBinding(member);
return annotationBinding.validate() ? annotationBinding : null;
}
@Override
public Class<? extends Execute> getSupportedAnnotation() {
return Execute.class;
}
}
public abstract static class DataAnnotationParser<A extends Annotation, M extends AccessibleObject & Member, B extends AnnotationBinding.DataBinding<M, ? extends BoundDescriptor>>
extends AnnotationParser<A,M,B> {
protected abstract B createBinding(M member);
}
public abstract static class InputAnnotationParser<A extends Annotation, M extends AccessibleObject & Member, B extends AnnotationBinding.InputBinding<M, ? extends InputDescriptor>>
extends DataAnnotationParser<A,M,B> {}
public abstract static class OutputAnnotationParser<A extends Annotation, M extends AccessibleObject & Member, B extends AnnotationBinding.OutputBinding<M, ? extends OutputDescriptor>>
extends DataAnnotationParser<A,M,B> {}
public abstract static class LiteralDataInputAnnotationParser<M extends AccessibleObject & Member, B extends AnnotationBinding.InputBinding<M, LiteralDataInputDescriptor>>
extends InputAnnotationParser<LiteralDataInput, M, B> {
@Override
public B parse(LiteralDataInput annotation, M member) {
B annotatedBinding = createBinding(member);
// auto generate binding if it's not explicitly declared
Type payloadType = annotatedBinding.getPayloadType();
Class<? extends ILiteralData> binding = annotation.binding();
if (binding == null || ILiteralData.class.equals(binding)) {
if (payloadType instanceof Class<?>) {
binding = BasicXMLTypeFactory.getBindingForPayloadType((Class<?>) payloadType);
if (binding == null) {
LOGGER.error("Unable to locate binding class for {}; binding not found.", payloadType);
}
} else {
if (annotatedBinding.isMemberTypeList()) {
LOGGER.error("Unable to determine binding class for {}; List must be parameterized with a type matching a known binding payload to use auto-binding.", payloadType);
} else {
LOGGER.error("Unable to determine binding class for {}; type must fully resolved to use auto-binding", payloadType);
}
}
}
String[] allowedValues = annotation.allowedValues();
String defaultValue = annotation.defaultValue();
int maxOccurs = annotation.maxOccurs();
// If InputType is enum
// 1) generate allowedValues if not explicitly declared
// 2) validate allowedValues if explicitly declared
// 3) validate defaultValue if declared
// 4) check for special ENUM_COUNT maxOccurs flag
Type inputType = annotatedBinding.getType();
if (annotatedBinding.isTypeEnum()) {
Class<? extends Enum> inputEnumClass = (Class<? extends Enum>) inputType;
// validate contents of allowed values maps to enum
if (allowedValues.length > 0) {
List<String> invalidValues = new ArrayList<String>();
for (String value : allowedValues) {
try {
Enum.valueOf(inputEnumClass, value);
} catch (IllegalArgumentException e) {
invalidValues.add(value);
LOGGER.warn("Invalid allowed value \"{}\" specified for for enumerated input type {}", value, inputType);
}
}
if (invalidValues.size() > 0) {
List<String> updatedValues = new ArrayList<String>(Arrays.asList(allowedValues));
updatedValues.removeAll(invalidValues);
allowedValues = updatedValues.toArray(new String[0]);
}
}
// if list is empty, populated with values from enum
if (allowedValues.length == 0) {
allowedValues = ClassUtil.convertEnumToStringArray(inputEnumClass);
}
if (defaultValue.length() > 0) {
try {
Enum.valueOf(inputEnumClass, defaultValue);
} catch (IllegalArgumentException e) {
LOGGER.warn("Invalid default value \"{}\" specified for for enumerated input type {}, ignoring.", defaultValue, inputType);
defaultValue = "";
}
}
if (maxOccurs == LiteralDataInput.ENUM_COUNT) {
maxOccurs = inputEnumClass.getEnumConstants().length;
}
} else {
if (maxOccurs == LiteralDataInput.ENUM_COUNT) {
maxOccurs = 1;
LOGGER.warn("Invalid maxOccurs \"ENUM_COUNT\" specified for for input type {}, setting maxOccurs to {}", inputType, maxOccurs);
}
}
if (binding != null) {
LiteralDataInputDescriptor descriptor =
LiteralDataInputDescriptor.builder(annotation.identifier(), binding).
title(annotation.title()).
abstrakt(annotation.abstrakt()).
minOccurs(annotation.minOccurs()).
maxOccurs(maxOccurs).
defaultValue(defaultValue).
allowedValues(allowedValues).
build();
annotatedBinding.setDescriptor(descriptor);
} else {
LOGGER.error("Unable to generate binding for input identifier \"{}\"", annotation.identifier());
}
return annotatedBinding.validate() ? annotatedBinding : null;
}
@Override
public Class<? extends LiteralDataInput> getSupportedAnnotation() {
return LiteralDataInput.class;
}
}
public abstract static class LiteralDataOutputAnnotationParser<M extends AccessibleObject & Member, B extends AnnotationBinding.OutputBinding<M, LiteralDataOutputDescriptor>>
extends OutputAnnotationParser<LiteralDataOutput, M, B> {
@Override
public B parse(LiteralDataOutput annotation, M member) {
B annotatedBinding = createBinding(member);
// auto generate binding if it's not explicitly declared
Type payloadType = annotatedBinding.getPayloadType();
Class<? extends ILiteralData> binding = annotation.binding();
if (binding == null || ILiteralData.class.equals(binding)) {
if (payloadType instanceof Class<?>) {
binding = BasicXMLTypeFactory.getBindingForPayloadType((Class<?>) payloadType);
if (binding == null) {
LOGGER.error("Unable to locate binding class for {}; binding not found.", payloadType);
}
} else {
LOGGER.error("Unable to determine binding class for {}; type must fully resolved to use auto-binding", payloadType);
}
}
if (binding != null) {
LiteralDataOutputDescriptor descriptor =
LiteralDataOutputDescriptor.builder(annotation.identifier(), binding).
title(annotation.title()).
abstrakt(annotation.abstrakt()).
build();
annotatedBinding.setDescriptor(descriptor);
} else {
LOGGER.error("Unable to generate binding for output identifier \"{}\"", annotation.identifier());
}
return annotatedBinding.validate() ? annotatedBinding : null;
}
@Override
public Class<? extends LiteralDataOutput> getSupportedAnnotation() {
return LiteralDataOutput.class;
}
}
public static class ComplexDataInputAnnotationParser<M extends AccessibleObject & Member, B extends AnnotationBinding.InputBinding<M, ComplexDataInputDescriptor>>
extends InputAnnotationParser<ComplexDataInput, M, B> {
@Override
public B parse(ComplexDataInput annotation, M member) {
B annotatedBinding = createBinding(member);
ComplexDataInputDescriptor descriptor =
ComplexDataInputDescriptor.builder(annotation.identifier(), annotation.binding()).
title(annotation.title()).
abstrakt(annotation.abstrakt()).
minOccurs(annotation.minOccurs()).
maxOccurs(annotation.maxOccurs()).
maximumMegaBytes(annotation.maximumMegaBytes()).
build();
annotatedBinding.setDescriptor(descriptor);
return annotatedBinding.validate() ? annotatedBinding : null;
}
@Override
public Class<? extends ComplexDataInput> getSupportedAnnotation() {
return ComplexDataInput.class;
}
@Override
protected B createBinding(M member) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
public abstract static class ComplexDataOutputAnnotationParser<M extends AccessibleObject & Member, B extends AnnotationBinding.OutputBinding<M, ComplexDataOutputDescriptor>>
extends OutputAnnotationParser<ComplexDataOutput, M, B> {
@Override
public B parse (ComplexDataOutput annotation, M member) {
B annotatedBinding = createBinding(member);
ComplexDataOutputDescriptor descriptor =
ComplexDataOutputDescriptor.builder(annotation.identifier(), annotation.binding()).
title(annotation.title()).
abstrakt(annotation.abstrakt()).
build();
annotatedBinding.setDescriptor(descriptor);
return annotatedBinding.validate() ? annotatedBinding : null;
}
@Override
public Class<? extends ComplexDataOutput> getSupportedAnnotation() {
return ComplexDataOutput.class;
}
}
public static class LiteralDataInputFieldAnnotationParser extends LiteralDataInputAnnotationParser<Field, AnnotationBinding.InputBinding<Field, LiteralDataInputDescriptor>> {
@Override
protected InputBinding<Field, LiteralDataInputDescriptor> createBinding(Field member) {
return new InputFieldBinding<LiteralDataInputDescriptor>(member);
}
}
public static class LiteralDataOutputFieldAnnotationParser extends LiteralDataOutputAnnotationParser<Field, AnnotationBinding.OutputBinding<Field, LiteralDataOutputDescriptor>> {
@Override
protected OutputBinding<Field, LiteralDataOutputDescriptor> createBinding(Field member) {
return new OutputFieldBinding<LiteralDataOutputDescriptor>(member);
}
}
public static class ComplexDataInputFieldAnnotationParser extends ComplexDataInputAnnotationParser<Field, AnnotationBinding.InputBinding<Field, ComplexDataInputDescriptor>> {
@Override
protected InputBinding<Field, ComplexDataInputDescriptor> createBinding(Field member) {
return new InputFieldBinding<ComplexDataInputDescriptor>(member);
}
}
public static class ComplexDataOutputFieldAnnotationParser extends ComplexDataOutputAnnotationParser<Field, AnnotationBinding.OutputBinding<Field, ComplexDataOutputDescriptor>> {
@Override
protected OutputBinding<Field, ComplexDataOutputDescriptor> createBinding(Field member) {
return new OutputFieldBinding<ComplexDataOutputDescriptor>(member);
}
}
public static class LiteralDataInputMethodAnnotationParser extends LiteralDataInputAnnotationParser<Method, AnnotationBinding.InputBinding<Method, LiteralDataInputDescriptor>> {
@Override
protected InputBinding<Method, LiteralDataInputDescriptor> createBinding(Method member) {
return new InputMethodBinding<LiteralDataInputDescriptor>(member);
}
}
public static class LiteralDataOutputMethodAnnotationParser extends LiteralDataOutputAnnotationParser<Method, AnnotationBinding.OutputBinding<Method, LiteralDataOutputDescriptor>> {
@Override
protected OutputBinding<Method, LiteralDataOutputDescriptor> createBinding(Method member) {
return new OutputMethodBinding<LiteralDataOutputDescriptor>(member);
}
}
public static class ComplexDataInputMethodAnnotationParser extends ComplexDataInputAnnotationParser<Method, AnnotationBinding.InputBinding<Method, ComplexDataInputDescriptor>> {
@Override
protected InputBinding<Method, ComplexDataInputDescriptor> createBinding(Method member) {
return new InputMethodBinding<ComplexDataInputDescriptor>(member);
}
}
public static class ComplexDataOutputMethodAnnotationParser extends ComplexDataOutputAnnotationParser<Method, AnnotationBinding.OutputBinding<Method, ComplexDataOutputDescriptor>> {
@Override
protected OutputBinding<Method, ComplexDataOutputDescriptor> createBinding(Method member) {
return new OutputMethodBinding<ComplexDataOutputDescriptor>(member);
}
}
}

@ -0,0 +1,39 @@
/**
* 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.algorithm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.n52.wps.io.data.IComplexData;
/**
*
* @author tkunicki
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface ComplexDataInput {
String identifier(); // identifier
String title() default "";
String abstrakt() default ""; // 'abstract' is java reserved keyword
int minOccurs() default 1;
int maxOccurs() default 1;
int maximumMegaBytes() default 0;
Class <? extends IComplexData> binding();
}

@ -0,0 +1,36 @@
/**
* 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.algorithm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.n52.wps.io.data.IComplexData;
/**
*
* @author tkunicki
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface ComplexDataOutput {
String identifier(); // identifier
String title() default "";
String abstrakt() default ""; // 'abstract' is java reserved keyword
Class <? extends IComplexData> binding();
}

@ -0,0 +1,32 @@
/**
* 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.algorithm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author tkunicki
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Execute {
}

@ -0,0 +1,44 @@
/**
* 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.algorithm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.n52.wps.io.data.ILiteralData;
/**
*
* @author tkunicki
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface LiteralDataInput {
String identifier(); // identifier
String title() default "";
String abstrakt() default ""; // 'abstract' is java reserved keyword
int minOccurs() default 1;
int maxOccurs() default 1;
String defaultValue() default "";
String[] allowedValues() default {};
Class <? extends ILiteralData> binding() default ILiteralData.class;
//// special maxOccurs flags
// set maxOccurs to enum constant count
public final static int ENUM_COUNT = -1;
}

@ -0,0 +1,36 @@
/**
* 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.algorithm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.n52.wps.io.data.ILiteralData;
/**
*
* @author tkunicki
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface LiteralDataOutput {
String identifier(); // identifier
String title() default "";
String abstrakt() default ""; // 'abstract' is java reserved keyword
Class <? extends ILiteralData> binding() default ILiteralData.class;
}

@ -0,0 +1,182 @@
/**
* 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.algorithm.descriptor;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author tkunicki
*/
public class AlgorithmDescriptor extends Descriptor {
private final String version;
private final boolean storeSupported;
private final boolean statusSupported;
private final Map<String, InputDescriptor> inputDescriptorMap;
private final Map<String, OutputDescriptor> outputDescriptorMap;
AlgorithmDescriptor(Builder<? extends Builder<?>> builder) {
super(builder);
this.version = builder.version;
this.storeSupported = builder.storeSupported;
this.statusSupported = builder.statusSupported;
Preconditions.checkState(
builder.outputDescriptors.size() > 0,
"Need at minimum 1 output for algorithm.");
// LinkedHaskMap to preserve order
Map<String, InputDescriptor> iMap = new LinkedHashMap<String, InputDescriptor>();
for (InputDescriptor iDescriptor : builder.inputDescriptors) {
iMap.put(iDescriptor.getIdentifier(), iDescriptor);
}
inputDescriptorMap = Collections.unmodifiableMap(iMap);
Map<String, OutputDescriptor> oMap = new LinkedHashMap<String, OutputDescriptor>();
for (OutputDescriptor oDescriptor : builder.outputDescriptors) {
oMap.put(oDescriptor.getIdentifier(), oDescriptor);
}
outputDescriptorMap = Collections.unmodifiableMap(oMap);
}
public String getVersion() {
return version;
}
public boolean getStoreSupported() {
return storeSupported;
}
public boolean getStatusSupported() {
return statusSupported;
}
public List<String> getInputIdentifiers() {
return Collections.unmodifiableList(new ArrayList<String>(inputDescriptorMap.keySet()));
}
public InputDescriptor getInputDescriptor(String identifier) {
return inputDescriptorMap.get(identifier);
}
public Collection<InputDescriptor> getInputDescriptors() {
return inputDescriptorMap.values();
}
public List<String> getOutputIdentifiers() {
return Collections.unmodifiableList(new ArrayList<String>(outputDescriptorMap.keySet()));
}
public OutputDescriptor getOutputDescriptor(String identifier) {
return outputDescriptorMap.get(identifier);
}
public Collection<OutputDescriptor> getOutputDescriptors() {
return outputDescriptorMap.values();
}
public static Builder<?> builder(String identifier) {
return new BuilderTyped(identifier);
}
public static Builder<?> builder(Class<?> clazz) {
Preconditions.checkNotNull(clazz, "clazz may not be null");
return new BuilderTyped(clazz.getCanonicalName());
}
private static class BuilderTyped extends Builder<BuilderTyped> {
public BuilderTyped(String identifier) {
super(identifier);
}
@Override
protected BuilderTyped self() {
return this;
}
}
public static abstract class Builder<B extends Builder<B>> extends Descriptor.Builder<B>{
private String version = "1.0.0";
private boolean storeSupported = true;
private boolean statusSupported = true;
private List<InputDescriptor> inputDescriptors;
private List<OutputDescriptor> outputDescriptors;
protected Builder(String identifier) {
super(identifier);
title(identifier);
inputDescriptors = new ArrayList<InputDescriptor>();
outputDescriptors = new ArrayList<OutputDescriptor>();
}
public B version(String version) {
this.version = version;
return self();
}
public B storeSupported(boolean storeSupported) {
this.storeSupported = storeSupported;
return self();
}
public B statusSupported(boolean statusSupported) {
this.statusSupported = statusSupported;
return self();
}
public B addInputDescriptor(InputDescriptor.Builder inputDescriptorBuilder) {
return addInputDescriptor(inputDescriptorBuilder.build());
}
public B addInputDescriptor(InputDescriptor inputDescriptor) {
this.inputDescriptors.add(inputDescriptor);
return self();
}
public B addInputDescriptors(List<? extends InputDescriptor> inputDescriptors) {
this.inputDescriptors.addAll(inputDescriptors);
return self();
}
public B addOutputDescriptor(OutputDescriptor.Builder outputDescriptorBuilder) {
return addOutputDescriptor(outputDescriptorBuilder.build());
}
public B addOutputDescriptor(OutputDescriptor outputDescriptor) {
this.outputDescriptors.add(outputDescriptor);
return self();
}
public B addOutputDescriptors(List<? extends OutputDescriptor> outputDescriptors) {
this.outputDescriptors.addAll(outputDescriptors);
return self();
}
public AlgorithmDescriptor build() {
return new AlgorithmDescriptor(this);
}
}
}

@ -0,0 +1,48 @@
/**
* 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.algorithm.descriptor;
import com.google.common.base.Preconditions;
/**
*
* @author tkunicki
*/
public abstract class BoundDescriptor<T extends Class<?>> extends Descriptor {
private final T binding;
BoundDescriptor(Builder<? extends Builder<?,T>, T> builder) {
super(builder);
this.binding = builder.binding;
}
public T getBinding() {
return binding;
}
public static abstract class Builder<B extends Builder<B,T>, T extends Class<?>> extends Descriptor.Builder<B> {
private final T binding;
protected Builder(String identifier, T binding) {
super(identifier);
Preconditions.checkArgument(binding != null, "binding may not be null");
this.binding = binding;
}
}
}

@ -0,0 +1,81 @@
/**
* 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.algorithm.descriptor;
import com.google.common.base.Preconditions;
import java.math.BigInteger;
import org.n52.wps.io.data.IComplexData;
/**
*
* @author tkunicki
*/
public class ComplexDataInputDescriptor<T extends Class<? extends IComplexData>> extends InputDescriptor<T> {
private final BigInteger maximumMegaBytes;
private ComplexDataInputDescriptor(Builder builder) {
super(builder);
this.maximumMegaBytes = builder.maximumMegaBytes;
}
public boolean hasMaximumMegaBytes() {
return maximumMegaBytes != null && maximumMegaBytes.longValue() > 0;
}
public BigInteger getMaximumMegaBytes() {
return maximumMegaBytes;
}
public static <T extends Class<? extends IComplexData>> Builder<?,T> builder(String identifier, T binding) {
return new BuilderTyped(identifier, binding);
}
private static class BuilderTyped<T extends Class<? extends IComplexData>> extends Builder<BuilderTyped<T>, T> {
public BuilderTyped(String identifier, T binding) {
super(identifier, binding);
}
@Override
protected BuilderTyped self() {
return this;
}
}
public static abstract class Builder<B extends Builder<B,T>, T extends Class<? extends IComplexData>> extends InputDescriptor.Builder<B,T> {
private BigInteger maximumMegaBytes;
private Builder(String identifier, T binding) {
super(identifier, binding);
}
public B maximumMegaBytes(int maximumMegaBytes) {
return maximumMegaBytes(BigInteger.valueOf(maximumMegaBytes));
}
public B maximumMegaBytes(BigInteger maximumMegaBytes) {
Preconditions.checkArgument(maximumMegaBytes.longValue() >= 0, "maximumMegabytes must be >= 0");
this.maximumMegaBytes = maximumMegaBytes;
return self();
}
@Override
public ComplexDataInputDescriptor<T> build() {
return new ComplexDataInputDescriptor<T>(this);
}
}
}

@ -0,0 +1,56 @@
/**
* 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.algorithm.descriptor;
import org.n52.wps.io.data.IComplexData;
/**
*
* @author tkunicki
*/
public class ComplexDataOutputDescriptor<T extends Class<? extends IComplexData>> extends OutputDescriptor<T> {
private ComplexDataOutputDescriptor(Builder builder) {
super(builder);
}
public static <T extends Class<? extends IComplexData>> Builder<?,T> builder(String identifier, T binding) {
return new BuilderTyped(identifier, binding);
}
private static class BuilderTyped<T extends Class<? extends IComplexData>> extends Builder<BuilderTyped<T>, T> {
public BuilderTyped(String identifier, T binding) {
super(identifier, binding);
}
@Override
protected BuilderTyped self() {
return this;
}
}
public static abstract class Builder<B extends Builder<B,T>, T extends Class<? extends IComplexData>> extends OutputDescriptor.Builder<B,T> {
private Builder(String identifier, T binding) {
super(identifier, binding);
}
public ComplexDataOutputDescriptor<T> build() {
return new ComplexDataOutputDescriptor<T>(this);
}
}
}

@ -0,0 +1,83 @@
/**
* 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.algorithm.descriptor;
import com.google.common.base.Preconditions;
/**
*
* @author tkunicki
*/
public abstract class Descriptor {
private final String identifier;
private final String title;
private final String abstrakt; // want 'abstract' but it's a java keyword
Descriptor(Builder<? extends Builder<?>> builder) {
this.identifier = builder.identifier;
this.title = builder.title;
this.abstrakt = builder.abstrakt;
}
public String getIdentifier() {
return identifier;
}
public boolean hasTitle() {
return title != null && title.length() > 0;
}
public String getTitle() {
return title;
}
public boolean hasAbstract() {
return abstrakt != null && abstrakt.length() > 0;
}
public String getAbstract() {
return abstrakt;
}
public static abstract class Builder<B extends Builder<B>> {
private final String identifier;
private String title;
private String abstrakt; // want 'abstract' but it's a java keyword
public Builder(String identifier) {
Preconditions.checkArgument(
!(identifier == null || identifier.isEmpty()),
"identifier may not be null or an empty String");
this.identifier = identifier;
}
public B title(String title) {
this.title = title;
return self();
}
// want 'abstract' but it's a java keyword
public B abstrakt(String abstrakt) {
this.abstrakt = abstrakt;
return self();
}
protected abstract B self();
}
}

@ -0,0 +1,82 @@
/**
* 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.algorithm.descriptor;
import com.google.common.base.Preconditions;
import java.math.BigInteger;
import org.n52.wps.io.data.IData;
/**
*
* @author tkunicki
*/
public abstract class InputDescriptor<T extends Class<? extends IData>> extends BoundDescriptor<T> {
private final BigInteger minOccurs;
private final BigInteger maxOccurs;
protected InputDescriptor(Builder<? extends Builder<?,T>, T> builder) {
super(builder);
this.minOccurs = builder.minOccurs;
this.maxOccurs = builder.maxOccurs;
Preconditions.checkState(maxOccurs.longValue() >= minOccurs.longValue(), "maxOccurs must be >= minOccurs");
}
public BigInteger getMinOccurs() {
return minOccurs;
}
public BigInteger getMaxOccurs() {
return maxOccurs;
}
public static abstract class Builder<B extends Builder<B,T>, T extends Class<? extends IData>> extends BoundDescriptor.Builder<B,T>{
private BigInteger minOccurs = BigInteger.ONE;
private BigInteger maxOccurs = BigInteger.ONE;
protected Builder(String identifier, T binding) {
super(identifier, binding);
}
public B minOccurs(int minOccurs) {
return minOccurs(BigInteger.valueOf(minOccurs));
}
public B minOccurs(BigInteger minOccurs) {
Preconditions.checkArgument(minOccurs.longValue() >= 0, "minOccurs must be >= 0");
this.minOccurs = minOccurs;
return self();
}
public B maxOccurs(int maxOccurs) {
return maxOccurs(BigInteger.valueOf(maxOccurs));
}
public B maxOccurs(BigInteger maxOccurs) {
Preconditions.checkArgument(maxOccurs.longValue() > 0, "maxOccurs must be > 0");
this.maxOccurs = maxOccurs;
return self();
}
public <E extends Enum<E>> B maxOccurs(Class<E> enumType) {
return maxOccurs(enumType.getEnumConstants().length);
}
public abstract InputDescriptor<T> build();
}
}

@ -0,0 +1,180 @@
/**
* 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.algorithm.descriptor;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.n52.wps.io.data.ILiteralData;
import org.n52.wps.io.data.binding.literal.LiteralAnyURIBinding;
import org.n52.wps.io.data.binding.literal.LiteralBase64BinaryBinding;
import org.n52.wps.io.data.binding.literal.LiteralBooleanBinding;
import org.n52.wps.io.data.binding.literal.LiteralByteBinding;
import org.n52.wps.io.data.binding.literal.LiteralDateTimeBinding;
import org.n52.wps.io.data.binding.literal.LiteralDoubleBinding;
import org.n52.wps.io.data.binding.literal.LiteralFloatBinding;
import org.n52.wps.io.data.binding.literal.LiteralIntBinding;
import org.n52.wps.io.data.binding.literal.LiteralLongBinding;
import org.n52.wps.io.data.binding.literal.LiteralShortBinding;
import org.n52.wps.io.data.binding.literal.LiteralStringBinding;
import org.n52.wps.io.BasicXMLTypeFactory;
/**
*
* @author tkunicki
*/
public class LiteralDataInputDescriptor<T extends Class<? extends ILiteralData>> extends InputDescriptor<T> {
private final String dataType;
private final String defaultValue;
private final List<String> allowedValues;
protected LiteralDataInputDescriptor(Builder builder) {
super(builder);
this.dataType = builder.dataType;
this.defaultValue = builder.defaultValue;
this.allowedValues = builder.allowedValues != null ?
Collections.unmodifiableList(builder.allowedValues) :
Collections.EMPTY_LIST;
// if allowedValues and defaultValue are set, make sure defaultValue is in set of allowedValues
Preconditions.checkState(
!hasAllowedValues() || !hasDefaultValue() || allowedValues.contains(defaultValue),
"defaultValue of %s not in set of allowedValues", defaultValue);
}
public String getDataType() {
return dataType;
}
public boolean hasDefaultValue() {
return defaultValue != null && defaultValue.length() > 0;
}
public String getDefaultValue() {
return defaultValue;
}
public boolean hasAllowedValues() {
return allowedValues != null && allowedValues.size() > 0;
}
public List<String> getAllowedValues() {
return allowedValues;
}
public static <T extends Class<? extends ILiteralData>> Builder<?,T> builder(String identifier, T binding) {
return new BuilderTyped(identifier, binding);
}
// utility functions, quite verbose...
public static Builder<?,Class<LiteralAnyURIBinding>> anyURIBuilder(String identifier) {
return builder(identifier, LiteralAnyURIBinding.class);
}
public static Builder<?,Class<LiteralBase64BinaryBinding>> base64BinaryBuilder(String identifier) {
return builder(identifier, LiteralBase64BinaryBinding.class);
}
public static Builder<?,Class<LiteralBooleanBinding>> booleanBuilder(String identifier) {
return builder(identifier, LiteralBooleanBinding.class);
}
public static Builder<?,Class<LiteralByteBinding>> byteBuilder(String identifier) {
return builder(identifier, LiteralByteBinding.class);
}
public static Builder<?,Class<LiteralDateTimeBinding>> dateTimeBuilder(String identifier) {
return builder(identifier, LiteralDateTimeBinding.class);
}
public static Builder<?,Class<LiteralDoubleBinding>> doubleBuilder(String identifier) {
return builder(identifier, LiteralDoubleBinding.class);
}
public static Builder<?,Class<LiteralFloatBinding>> floatBuilder(String identifier) {
return builder(identifier, LiteralFloatBinding.class);
}
public static Builder<?,Class<LiteralIntBinding>> intBuilder(String identifier) {
return builder(identifier, LiteralIntBinding.class);
}
public static Builder<?,Class<LiteralLongBinding>> longBuilder(String identifier) {
return builder(identifier, LiteralLongBinding.class);
}
public static Builder<?,Class<LiteralShortBinding>> shortBuilder(String identifier) {
return builder(identifier, LiteralShortBinding.class);
}
public static Builder<?,Class<LiteralStringBinding>> stringBuilder(String identifier) {
return builder(identifier, LiteralStringBinding.class);
}
private static class BuilderTyped<T extends Class<? extends ILiteralData>> extends Builder<BuilderTyped<T>, T> {
public BuilderTyped(String identifier, T binding) {
super(identifier, binding);
}
@Override
protected BuilderTyped self() {
return this;
}
}
public static abstract class Builder<B extends Builder<B,T>, T extends Class<? extends ILiteralData>> extends InputDescriptor.Builder<B,T> {
private final String dataType;
private String defaultValue;
private List<String> allowedValues;
protected Builder(String identifier, T binding) {
super(identifier, binding);
this.dataType = Preconditions.checkNotNull(
BasicXMLTypeFactory.getXMLDataTypeforBinding(binding),
"Unable to resolve XML DataType for binding class %s",
binding);
}
public B defaultValue(String defaultValue) {
this.defaultValue = defaultValue;
return self();
}
public B allowedValues(Class<? extends Enum> allowedValues) {
Enum[] constants = allowedValues.getEnumConstants();
List<String> names = new ArrayList<String>(constants.length);
for (Enum constant : constants) { names.add(constant.name()); }
return allowedValues(names);
}
public B allowedValues(String[] allowedValues) {
return allowedValues(Arrays.asList(allowedValues));
}
public B allowedValues(List<String> allowedValues) {
this.allowedValues = allowedValues;
return self();
}
@Override
public LiteralDataInputDescriptor<T> build() {
return new LiteralDataInputDescriptor<T>(this);
}
}
}

@ -0,0 +1,127 @@
/**
* 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.algorithm.descriptor;
import com.google.common.base.Preconditions;
import org.n52.wps.io.BasicXMLTypeFactory;
import org.n52.wps.io.data.ILiteralData;
import org.n52.wps.io.data.binding.literal.LiteralAnyURIBinding;
import org.n52.wps.io.data.binding.literal.LiteralBase64BinaryBinding;
import org.n52.wps.io.data.binding.literal.LiteralBooleanBinding;
import org.n52.wps.io.data.binding.literal.LiteralByteBinding;
import org.n52.wps.io.data.binding.literal.LiteralDateTimeBinding;
import org.n52.wps.io.data.binding.literal.LiteralDoubleBinding;
import org.n52.wps.io.data.binding.literal.LiteralFloatBinding;
import org.n52.wps.io.data.binding.literal.LiteralIntBinding;
import org.n52.wps.io.data.binding.literal.LiteralLongBinding;
import org.n52.wps.io.data.binding.literal.LiteralShortBinding;
import org.n52.wps.io.data.binding.literal.LiteralStringBinding;
/**
*
* @author tkunicki
*/
public class LiteralDataOutputDescriptor<T extends Class<? extends ILiteralData>> extends OutputDescriptor<T> {
private final String dataType;
protected LiteralDataOutputDescriptor(Builder builder) {
super(builder);
this.dataType = builder.dataType;
}
public String getDataType() {
return dataType;
}
public static <T extends Class<? extends ILiteralData>> Builder<?,T> builder(String identifier, T binding) {
return new BuilderTyped(identifier, binding);
}
// utility functions, quite verbose...
public static Builder<?,Class<LiteralAnyURIBinding>> anyURIBuilder(String identifier) {
return builder(identifier, LiteralAnyURIBinding.class);
}
public static Builder<?,Class<LiteralBase64BinaryBinding>> base64BinaryBuilder(String identifier) {
return builder(identifier, LiteralBase64BinaryBinding.class);
}
public static Builder<?,Class<LiteralBooleanBinding>> booleanBuilder(String identifier) {
return builder(identifier, LiteralBooleanBinding.class);
}
public static Builder<?,Class<LiteralByteBinding>> byteBuilder(String identifier) {
return builder(identifier, LiteralByteBinding.class);
}
public static Builder<?,Class<LiteralDateTimeBinding>> dateTimeBuilder(String identifier) {
return builder(identifier, LiteralDateTimeBinding.class);
}
public static Builder<?,Class<LiteralDoubleBinding>> doubleBuilder(String identifier) {
return builder(identifier, LiteralDoubleBinding.class);
}
public static Builder<?,Class<LiteralFloatBinding>> floatBuilder(String identifier) {
return builder(identifier, LiteralFloatBinding.class);
}
public static Builder<?,Class<LiteralIntBinding>> intBuilder(String identifier) {
return builder(identifier, LiteralIntBinding.class);
}
public static Builder<?,Class<LiteralLongBinding>> longBuilder(String identifier) {
return builder(identifier, LiteralLongBinding.class);
}
public static Builder<?,Class<LiteralShortBinding>> shortBuilder(String identifier) {
return builder(identifier, LiteralShortBinding.class);
}
public static Builder<?,Class<LiteralStringBinding>> stringBuilder(String identifier) {
return builder(identifier, LiteralStringBinding.class);
}
private static class BuilderTyped<T extends Class<? extends ILiteralData>> extends Builder<BuilderTyped<T>, T> {
public BuilderTyped(String identifier, T binding) {
super(identifier, binding);
}
@Override
protected BuilderTyped self() {
return this;
}
}
public static abstract class Builder<B extends Builder<B,T>, T extends Class<? extends ILiteralData>> extends OutputDescriptor.Builder<B,T> {
private final String dataType;
protected Builder(String identifier, T binding) {
super(identifier, binding);
this.dataType = Preconditions.checkNotNull(
BasicXMLTypeFactory.getXMLDataTypeforBinding(binding),
"Unable to resolve XML DataType for binding class %s",
binding);
}
@Override
public LiteralDataOutputDescriptor<T> build() {
return new LiteralDataOutputDescriptor<T>(this);
}
}
}

@ -0,0 +1,39 @@
/**
* 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.algorithm.descriptor;
import org.n52.wps.io.data.IData;
/**
*
* @author tkunicki
*/
public abstract class OutputDescriptor<T extends Class<? extends IData>> extends BoundDescriptor<T> {
OutputDescriptor(Builder<? extends Builder<?,T>, T> builder) {
super(builder);
}
public static abstract class Builder<B extends Builder<B,T>, T extends Class<? extends IData>> extends BoundDescriptor.Builder<B,T>{
protected Builder(String identifier, T binding) {
super(identifier, binding);
}
public abstract OutputDescriptor<T> build();
}
}

@ -0,0 +1,95 @@
/**
* 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.algorithm.util;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
*
* @author tkunicki
*/
public class ClassUtil {
private final static Map<Class<?>, Class<?>> TO_WRAPPER;
private final static Map<Class<?>, Class<?>> FROM_WRAPPER;
static {
BiMap<Class<?>, Class<?>> map = HashBiMap.create();
map.put(Float.TYPE, Float.class);
map.put(Double.TYPE, Double.class);
map.put(Byte.TYPE, Byte.class);
map.put(Short.TYPE, Short.class);
map.put(Integer.TYPE, Integer.class);
map.put(Long.TYPE, Long.class);
map.put(Character.TYPE, Character.class);
map.put(Boolean.TYPE, Boolean.class);
TO_WRAPPER = Collections.unmodifiableMap(map);
FROM_WRAPPER = Collections.unmodifiableMap(map.inverse());
}
public static <T extends Enum<T>> List<T> convertStringToEnumList(Class<T> enumType, List<String> stringList) {
List<T> enumList = new ArrayList<T>();
for (String string : stringList) {
enumList.add(Enum.valueOf(enumType, string));
}
return enumList;
}
public static <T extends Enum<T>> List<String> convertEnumToStringList(Class<T> enumType) {
ArrayList stringList = null;
T[] constants = enumType.getEnumConstants();
if (constants != null && constants.length > 0) {
stringList = new ArrayList(constants.length);
for (T constant : constants) {
stringList.add(constant.name());
}
}
return stringList;
}
public static <T extends Enum<T>> String[] convertEnumToStringArray(Class<T> enumType) {
List<String> stringList = convertEnumToStringList(enumType);
return stringList == null ? null :
stringList.toArray(new String[stringList.size()]);
}
public static boolean isWrapper(Class<?> clazz) {
return FROM_WRAPPER.containsKey(clazz);
}
public static Class<?> unwrap(Class<?> clazz) {
Class<?> unwrapped = FROM_WRAPPER.get(clazz);
if (unwrapped == null)
return clazz;
return unwrapped;
}
public static Class<?> wrap(Class<?> clazz) {
Class<?> wrapped = TO_WRAPPER.get(clazz);
if (wrapped == null)
return clazz;
return wrapped;
}
}

@ -0,0 +1,117 @@
/**
* 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.io.IOException;
import java.io.InputStream;
import net.opengis.wps.x100.ProcessDescriptionType;
import net.opengis.wps.x100.ProcessDescriptionsDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
/**
* This class has to be extended in order to be served through the WPS.
* The class file should also include a description file of the algorithm. This file has to be
* valid against the describeProcess.xsd. The file has to be placed in the folder of the class file and has
* to be named the same as the Algorithm.
*
* <p>If you want to apply a different initialization method, just override the initializeDescription() method.
*
* NOTE: This class is an adapter and it is recommended to extend this.
* @author foerster
*
*/
public abstract class AbstractAlgorithm implements IAlgorithm
{
private ProcessDescriptionType description; // private, force access through getter method for lazy loading.
private final String wkName;
private static Logger LOGGER = LoggerFactory.getLogger(AbstractAlgorithm.class);
/**
* default constructor, calls the initializeDescription() Method
*/
public AbstractAlgorithm() {
this.wkName = this.getClass().getName();
}
/**
* default constructor, calls the initializeDescription() Method
*/
public AbstractAlgorithm(String wellKnownName) {
this.wkName = wellKnownName;
}
/**
* This method should be overwritten, in case you want to have a way of initializing.
*
* In detail it looks for a xml descfile, which is located in the same directory as the implementing class and has the same
* name as the class, but with the extension XML.
* @return
*/
protected ProcessDescriptionType initializeDescription() {
String className = this.getClass().getName().replace(".", "/");
InputStream xmlDesc = this.getClass().getResourceAsStream("/" + className + ".xml");
try {
XmlOptions option = new XmlOptions();
option.setLoadTrimTextBuffer();
ProcessDescriptionsDocument doc = ProcessDescriptionsDocument.Factory.parse(xmlDesc, option);
if(doc.getProcessDescriptions().getProcessDescriptionArray().length == 0) {
LOGGER.warn("ProcessDescription does not contain correct any description");
return null;
}
// Checking that the process name (full class name or well-known name) matches the identifier.
if(!doc.getProcessDescriptions().getProcessDescriptionArray(0).getIdentifier().getStringValue().equals(this.getClass().getName()) &&
!doc.getProcessDescriptions().getProcessDescriptionArray(0).getIdentifier().getStringValue().equals(this.getWellKnownName())) {
doc.getProcessDescriptions().getProcessDescriptionArray(0).getIdentifier().setStringValue(this.getClass().getName());
LOGGER.warn("Identifier was not correct, was changed now temporary for server use to " + this.getClass().getName() + ". Please change it later in the description!");
}
return doc.getProcessDescriptions().getProcessDescriptionArray(0);
}
catch(IOException e) {
LOGGER.warn("Could not initialize algorithm, parsing error: " + this.getClass().getName(), e);
}
catch(XmlException e) {
LOGGER.warn("Could not initialize algorithm, parsing error: " + this.getClass().getName(), e);
}
return null;
}
@Override
public synchronized ProcessDescriptionType getDescription() {
if (description == null) {
description = initializeDescription();
}
return description;
}
@Override
public boolean processDescriptionIsValid() {
return getDescription().validate();
}
@Override
public String getWellKnownName() {
return this.wkName;
}
}

@ -0,0 +1,98 @@
/**
* 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.util.HashMap;
import java.util.List;
import java.util.Map;
import org.n52.wps.algorithm.annotation.AnnotatedAlgorithmIntrospector;
import static org.n52.wps.algorithm.annotation.AnnotatedAlgorithmIntrospector.getInstrospector;
import org.n52.wps.algorithm.annotation.AnnotationBinding;
import org.n52.wps.algorithm.descriptor.AlgorithmDescriptor;
import org.n52.wps.io.data.IData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author tkunicki
*/
public abstract class AbstractAnnotatedAlgorithm extends AbstractDescriptorAlgorithm {
private final static Logger LOGGER = LoggerFactory.getLogger(AbstractAnnotatedAlgorithm.class);
@Override
protected AlgorithmDescriptor createAlgorithmDescriptor() {
return getInstrospector(getAlgorithmClass()).getAlgorithmDescriptor();
}
@Override
public Map<String, IData> run(Map<String, List<IData>> inputMap) {
Object annotatedInstance = getAlgorithmInstance();
AnnotatedAlgorithmIntrospector introspector = getInstrospector(annotatedInstance.getClass());
for (Map.Entry<String, AnnotationBinding.InputBinding<?, ?>> iEntry : introspector.getInputBindingMap().entrySet()) {
iEntry.getValue().set(annotatedInstance, inputMap.get(iEntry.getKey()));
}
getInstrospector(annotatedInstance.getClass()).getExecuteMethodBinding().execute(annotatedInstance);
Map<String, IData> oMap = new HashMap<String, IData>();
for (Map.Entry<String, AnnotationBinding.OutputBinding<?, ?>> oEntry : introspector.getOutputBindingMap().entrySet()) {
oMap.put(oEntry.getKey(), oEntry.getValue().get(annotatedInstance));
}
return oMap;
}
public Object getAlgorithmInstance() {
return this;
}
public Class<?> getAlgorithmClass() {
return getClass();
}
public static class Proxy extends AbstractAnnotatedAlgorithm {
final private Class<?> proxiedClass;
final private Object proxiedInstance;
public Proxy(Class<?> proxiedClass) {
this.proxiedClass = proxiedClass;
try {
this.proxiedInstance = proxiedClass.newInstance();
} catch (InstantiationException ex) {
throw new RuntimeException("unable to instantiate proxied algorithm instance");
} catch (IllegalAccessException ex) {
throw new RuntimeException("unable to instantiate proxied algorithm instance");
}
}
@Override
public Class<?> getAlgorithmClass() {
return proxiedClass;
}
@Override
public Object getAlgorithmInstance() {
return proxiedInstance;
}
}
}

@ -0,0 +1,397 @@
/**
* 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.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import net.opengis.ows.x11.AllowedValuesDocument.AllowedValues;
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.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.SupportedComplexDataInputType;
import net.opengis.wps.x100.SupportedComplexDataType;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlValidationError;
import org.n52.wps.FormatDocument.Format;
import org.n52.wps.algorithm.descriptor.AlgorithmDescriptor;
import org.n52.wps.algorithm.descriptor.ComplexDataInputDescriptor;
import org.n52.wps.algorithm.descriptor.ComplexDataOutputDescriptor;
import org.n52.wps.algorithm.descriptor.InputDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataInputDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataOutputDescriptor;
import org.n52.wps.algorithm.descriptor.OutputDescriptor;
import org.n52.wps.io.GeneratorFactory;
import org.n52.wps.io.IGenerator;
import org.n52.wps.io.IOHandler;
import org.n52.wps.io.IParser;
import org.n52.wps.io.ParserFactory;
import org.n52.wps.io.data.IData;
import org.n52.wps.server.observerpattern.IObserver;
import org.n52.wps.server.observerpattern.ISubject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
public abstract class AbstractDescriptorAlgorithm implements IAlgorithm, ISubject {
private final static Logger LOGGER = LoggerFactory.getLogger(AbstractDescriptorAlgorithm.class);
private AlgorithmDescriptor descriptor;
private ProcessDescriptionType description;
public AbstractDescriptorAlgorithm() {
super();
}
@Override
public synchronized ProcessDescriptionType getDescription() {
if (description == null) {
description = createProcessDescription();
}
return description;
}
@Override
public String getWellKnownName() {
return getAlgorithmDescriptor().getIdentifier();
}
private ProcessDescriptionType createProcessDescription() {
AlgorithmDescriptor algorithmDescriptor = getAlgorithmDescriptor();
ProcessDescriptionsDocument document = ProcessDescriptionsDocument.Factory.newInstance();
ProcessDescriptions processDescriptions = document.addNewProcessDescriptions();
ProcessDescriptionType processDescription = processDescriptions.addNewProcessDescription();
if (algorithmDescriptor == null) {
throw new IllegalStateException("Instance must have an algorithm descriptor");
} else {
// 1. Identifier
processDescription.setStatusSupported(algorithmDescriptor.getStatusSupported());
processDescription.setStoreSupported(algorithmDescriptor.getStoreSupported());
processDescription.setProcessVersion(algorithmDescriptor.getVersion());
processDescription.addNewIdentifier().setStringValue(algorithmDescriptor.getIdentifier());
processDescription.addNewTitle().setStringValue( algorithmDescriptor.hasTitle() ?
algorithmDescriptor.getTitle() :
algorithmDescriptor.getIdentifier());
if (algorithmDescriptor.hasAbstract()) {
processDescription.addNewAbstract().setStringValue(algorithmDescriptor.getAbstract());
}
// 2. Inputs
Collection<InputDescriptor> inputDescriptors = algorithmDescriptor.getInputDescriptors();
DataInputs dataInputs = null;
if (inputDescriptors.size() > 0) {
dataInputs = processDescription.addNewDataInputs();
}
for (InputDescriptor inputDescriptor : inputDescriptors) {
InputDescriptionType dataInput = dataInputs.addNewInput();
dataInput.setMinOccurs(inputDescriptor.getMinOccurs());
dataInput.setMaxOccurs(inputDescriptor.getMaxOccurs());
dataInput.addNewIdentifier().setStringValue(inputDescriptor.getIdentifier());
dataInput.addNewTitle().setStringValue( inputDescriptor.hasTitle() ?
inputDescriptor.getTitle() :
inputDescriptor.getIdentifier());
if (inputDescriptor.hasAbstract()) {
dataInput.addNewAbstract().setStringValue(inputDescriptor.getAbstract());
}
if (inputDescriptor instanceof LiteralDataInputDescriptor) {
LiteralDataInputDescriptor<?> literalDescriptor = (LiteralDataInputDescriptor)inputDescriptor;
LiteralInputType literalData = dataInput.addNewLiteralData();
literalData.addNewDataType().setReference(literalDescriptor.getDataType());
if (literalDescriptor.hasDefaultValue()) {
literalData.setDefaultValue(literalDescriptor.getDefaultValue());
}
if (literalDescriptor.hasAllowedValues()) {
AllowedValues allowed = literalData.addNewAllowedValues();
for (String allowedValue : literalDescriptor.getAllowedValues()) {
allowed.addNewValue().setStringValue(allowedValue);
}
} else {
literalData.addNewAnyValue();
}
} else if (inputDescriptor instanceof ComplexDataInputDescriptor) {
SupportedComplexDataInputType complexDataType = dataInput.addNewComplexData();
ComplexDataInputDescriptor complexInputDescriptor =
(ComplexDataInputDescriptor)inputDescriptor;
if (complexInputDescriptor.hasMaximumMegaBytes()) {
complexDataType.setMaximumMegabytes(complexInputDescriptor.getMaximumMegaBytes());
}
describeComplexDataInputType(complexDataType, inputDescriptor.getBinding());
}
}
// 3. Outputs
ProcessOutputs dataOutputs = processDescription.addNewProcessOutputs();
Collection<OutputDescriptor> outputDescriptors = algorithmDescriptor.getOutputDescriptors();
if (outputDescriptors.size() < 1) {
LOGGER.error("No outputs found for algorithm {}", algorithmDescriptor.getIdentifier());
}
for (OutputDescriptor outputDescriptor : outputDescriptors) {
OutputDescriptionType dataOutput = dataOutputs.addNewOutput();
dataOutput.addNewIdentifier().setStringValue(outputDescriptor.getIdentifier());
dataOutput.addNewTitle().setStringValue( outputDescriptor.hasTitle() ?
outputDescriptor.getTitle() :
outputDescriptor.getIdentifier());
if (outputDescriptor.hasAbstract()) {
dataOutput.addNewAbstract().setStringValue(outputDescriptor.getAbstract());
}
if (outputDescriptor instanceof LiteralDataOutputDescriptor) {
LiteralDataOutputDescriptor<?> literalDescriptor = (LiteralDataOutputDescriptor)outputDescriptor;
dataOutput.addNewLiteralOutput().addNewDataType().
setReference(literalDescriptor.getDataType());
} else if (outputDescriptor instanceof ComplexDataOutputDescriptor) {
describeComplexDataOutputType(dataOutput.addNewComplexOutput(), outputDescriptor.getBinding());
}
}
}
return document.getProcessDescriptions().getProcessDescriptionArray(0);
}
private void describeComplexDataInputType(SupportedComplexDataType complexData, Class dataTypeClass) {
List<IParser> parsers = ParserFactory.getInstance().getAllParsers();
List<IParser> foundParsers = new ArrayList<IParser>();
for (IParser parser : parsers) {
// /*2.0*/ Class[] supportedClasses = parser.getSupportedInternalOutputDataType();
/*3.0*/ Class[] supportedClasses = parser.getSupportedDataBindings();
for (Class clazz : supportedClasses) {
if (dataTypeClass.isAssignableFrom(clazz)) {
foundParsers.add(parser);
}
}
}
describeComplexDataType(complexData, foundParsers);
}
private void describeComplexDataOutputType(SupportedComplexDataType complexData, Class dataTypeClass) {
List<IGenerator> generators = GeneratorFactory.getInstance().getAllGenerators();
List<IGenerator> foundGenerators = new ArrayList<IGenerator>();
for (IGenerator generator : generators) {
// /*2.0*/ Class[] supportedClasses = generator.getSupportedInternalInputDataType(); // appears to have been removed in 52n WPS 3.0
/*3.0*/ Class[] supportedClasses = generator.getSupportedDataBindings();
for (Class clazz : supportedClasses) {
if (clazz.isAssignableFrom(dataTypeClass)) {
foundGenerators.add(generator);
}
}
}
describeComplexDataType(complexData, foundGenerators);
}
private void describeComplexDataType(
SupportedComplexDataType complexData,
List<? extends IOHandler> handlers)
{
ComplexDataCombinationType defaultFormatType = complexData.addNewDefault();
ComplexDataCombinationsType supportedFormatType = complexData.addNewSupported();
boolean needDefault = true;
for (IOHandler handler : handlers) {
Format[] fullFormats = handler.getSupportedFullFormats();
if (fullFormats != null && fullFormats.length > 0) {
if (needDefault) {
needDefault = false;
describeComplexDataFormat(
defaultFormatType.addNewFormat(),
fullFormats[0]);
}
for (int formatIndex = 0, formatCount = fullFormats.length; formatIndex < formatCount; ++formatIndex) {
describeComplexDataFormat(
supportedFormatType.addNewFormat(),
fullFormats[formatIndex]);
}
} else {
String[] formats = handler.getSupportedFormats();
if (formats == null || formats.length == 0) {
LOGGER.warn("Skipping IOHandler {} in ProcessDescription generation for {}, no formats specified",
handler.getClass().getSimpleName(),
getWellKnownName());
} else {
// if formats, encodings or schemas arrays are 'null' or empty, create
// new array with single 'null' element. We do this so we can utilize
// a single set of nested loops to process all permutations. 'null'
// values will not be output...
String[] encodings = handler.getSupportedEncodings();
if (encodings == null || encodings.length == 0) {
encodings = new String[] { null };
}
String[] schemas = handler.getSupportedSchemas();
if (schemas == null || schemas.length == 0) {
schemas = new String[] { null };
}
for (String format : formats) {
for (String encoding : encodings) {
for (String schema : schemas) {
if (needDefault) {
needDefault = false;
describeComplexDataFormat(
defaultFormatType.addNewFormat(),
format, encoding, schema);
}
describeComplexDataFormat(
supportedFormatType.addNewFormat(),
format, encoding, schema);
}
}
}
}
}
}
}
private void describeComplexDataFormat(
ComplexDataDescriptionType description,
Format format)
{
describeComplexDataFormat(description,
format.getMimetype(),
format.getEncoding(),
format.getSchema());
}
private void describeComplexDataFormat(ComplexDataDescriptionType description,
String format,
String encoding,
String schema) {
if ( !Strings.isNullOrEmpty(format)) {
description.setMimeType(format);
}
if ( !Strings.isNullOrEmpty(encoding)) {
description.setEncoding(encoding);
}
if ( !Strings.isNullOrEmpty(schema)) {
description.setSchema(schema);
}
}
@Override
public boolean processDescriptionIsValid() {
XmlOptions xmlOptions = new XmlOptions();
List<XmlValidationError> xmlValidationErrorList = new ArrayList<XmlValidationError>();
xmlOptions.setErrorListener(xmlValidationErrorList);
boolean valid = getDescription().validate(xmlOptions);
if (!valid) {
LOGGER.error("Error validating process description for " + getClass().getCanonicalName());
for (XmlValidationError xmlValidationError : xmlValidationErrorList) {
LOGGER.error("\tMessage: {}", xmlValidationError.getMessage());
LOGGER.error("\tLocation of invalid XML: {}",
xmlValidationError.getCursorLocation().xmlText());
}
}
return valid;
}
protected final synchronized AlgorithmDescriptor getAlgorithmDescriptor() {
if (descriptor == null) {
descriptor = createAlgorithmDescriptor();
}
return descriptor;
}
protected abstract AlgorithmDescriptor createAlgorithmDescriptor();
@Override
public Class<? extends IData> getInputDataType(String identifier) {
AlgorithmDescriptor algorithmDescriptor = getAlgorithmDescriptor();
if (algorithmDescriptor != null) {
return getAlgorithmDescriptor().getInputDescriptor(identifier).getBinding();
} else {
throw new IllegalStateException("Instance must have an algorithm descriptor");
}
}
@Override
public Class<? extends IData> getOutputDataType(String identifier) {
AlgorithmDescriptor algorithmDescriptor = getAlgorithmDescriptor();
if (algorithmDescriptor != null) {
return getAlgorithmDescriptor().getOutputDescriptor(identifier).getBinding();
} else {
throw new IllegalStateException("Instance must have an algorithm descriptor");
}
}
private List observers = new ArrayList();
private Object state = null;
@Override
public Object getState() {
return state;
}
@Override
public void update(Object state) {
this.state = state;
notifyObservers();
}
@Override
public void addObserver(IObserver o) {
observers.add(o);
}
@Override
public void removeObserver(IObserver o) {
observers.remove(o);
}
public void notifyObservers() {
Iterator i = observers.iterator();
while (i.hasNext()) {
IObserver o = (IObserver) i.next();
o.update(this);
}
}
List<String> errorList = new ArrayList();
protected List<String> addError(String error) {
errorList.add(error);
return errorList;
}
@Override
public List<String> getErrors() {
return errorList;
}
}

@ -0,0 +1,139 @@
/**
* 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.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.opengis.wps.x100.ProcessDescriptionType;
import net.opengis.wps.x100.ProcessDescriptionsDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.n52.wps.server.observerpattern.IObserver;
import org.n52.wps.server.observerpattern.ISubject;
public abstract class AbstractObservableAlgorithm implements IAlgorithm, ISubject{
protected ProcessDescriptionType description;
protected final String wkName;
private static Logger LOGGER = LoggerFactory.getLogger(AbstractAlgorithm.class);
/**
* default constructor, calls the initializeDescription() Method
*/
public AbstractObservableAlgorithm() {
this.description = initializeDescription();
this.wkName = "";
}
public AbstractObservableAlgorithm(ProcessDescriptionType description) {
this.description = description;
this.wkName = "";
}
/**
* default constructor, calls the initializeDescription() Method
*/
public AbstractObservableAlgorithm(String wellKnownName) {
this.wkName = wellKnownName; // Has to be initialized before the description.
this.description = initializeDescription();
}
/**
* This method should be overwritten, in case you want to have a way of initializing.
*
* In detail it looks for a xml descfile, which is located in the same directory as the implementing class and has the same
* name as the class, but with the extension XML.
* @return
*/
protected ProcessDescriptionType initializeDescription() {
String className = this.getClass().getName().replace(".", "/");
InputStream xmlDesc = this.getClass().getResourceAsStream("/" + className + ".xml");
try {
XmlOptions option = new XmlOptions();
option.setLoadTrimTextBuffer();
ProcessDescriptionsDocument doc = ProcessDescriptionsDocument.Factory.parse(xmlDesc, option);
if(doc.getProcessDescriptions().getProcessDescriptionArray().length == 0) {
LOGGER.warn("ProcessDescription does not contain correct any description");
return null;
}
// Checking that the process name (full class name or well-known name) matches the identifier.
if(!doc.getProcessDescriptions().getProcessDescriptionArray(0).getIdentifier().getStringValue().equals(this.getClass().getName()) &&
!doc.getProcessDescriptions().getProcessDescriptionArray(0).getIdentifier().getStringValue().equals(this.getWellKnownName())) {
doc.getProcessDescriptions().getProcessDescriptionArray(0).getIdentifier().setStringValue(this.getClass().getName());
LOGGER.warn("Identifier was not correct, was changed now temporary for server use to " + this.getClass().getName() + ". Please change it later in the description!");
}
return doc.getProcessDescriptions().getProcessDescriptionArray(0);
}
catch(IOException e) {
LOGGER.warn("Could not initialize algorithm, parsing error: " + this.getClass().getName(), e);
}
catch(XmlException e) {
LOGGER.warn("Could not initialize algorithm, parsing error: " + this.getClass().getName(), e);
}
return null;
}
public ProcessDescriptionType getDescription() {
return description;
}
public boolean processDescriptionIsValid() {
return description.validate();
}
public String getWellKnownName() {
return this.wkName;
}
private List observers = new ArrayList();
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 i = observers.iterator();
while (i.hasNext()) {
IObserver o = (IObserver) i.next();
o.update(this);
}
}
}

@ -0,0 +1,420 @@
/**
* 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());
}
}
}
}
}

@ -0,0 +1,45 @@
/**
* 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.util.Map;
import org.n52.wps.io.data.IData;
import net.opengis.wps.x100.ExecuteDocument;
public abstract class AbstractTransactionalAlgorithm implements IAlgorithm{
protected String algorithmID;
public AbstractTransactionalAlgorithm(String algorithmID){
this.algorithmID = algorithmID;
}
public String getAlgorithmID() {
return algorithmID;
}
public abstract Map<String, IData> run(ExecuteDocument document);
}

@ -0,0 +1,30 @@
/**
* 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;
public class AlgorithmParameterException extends RuntimeException {
private static final long serialVersionUID = -514774594848925943L;
public AlgorithmParameterException() {
super();
}
public AlgorithmParameterException(String message) {
super(message);
}
}

@ -0,0 +1,56 @@
/**
* 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.util.List;
import java.util.Map;
import net.opengis.wps.x100.ProcessDescriptionType;
import org.n52.wps.io.data.IData;
import org.n52.wps.server.ExceptionReport;
/**
* @author Bastian Schaeffer, University of Muenster, Theodor Foerster, ITC
*
*/
public interface IAlgorithm {
Map<String, IData> run(Map<String, List<IData>> inputData) throws ExceptionReport;
List<String> getErrors();
ProcessDescriptionType getDescription();
/** Returns some well-known name for the process.
*
* @return Returns some well-known name for the process or algorithm
* if that exists, else returns an empty String, never null.
* @note The fully-qualified class name is gotten via getName();
*/
String getWellKnownName();
/**
* Checks if the processDescription complies to the process itself and fits any schema or other dependencies.
*/
boolean processDescriptionIsValid();
Class< ? > getInputDataType(String id);
Class< ? > getOutputDataType(String id);
}

@ -0,0 +1,42 @@
/**
* 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.util.Collection;
import net.opengis.wps.x100.ProcessDescriptionType;
/**
* @author Bastian Schaeffer, University of Muenster, Theodor Foerster, ITC
*
*/
public interface IAlgorithmRepository {
Collection<String> getAlgorithmNames();
IAlgorithm getAlgorithm(String processID);
ProcessDescriptionType getProcessDescription(String processID);
boolean containsAlgorithm(String processID);
/**
* use to free resources
*/
public void shutdown();
}

@ -0,0 +1,27 @@
/**
* 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;
/**
* @author Bastian Schaeffer, University of Muenster
*
*/
public interface ITransactionalAlgorithmRepository extends IAlgorithmRepository{
boolean addAlgorithm(Object className);
boolean removeAlgorithm(Object className);
}

@ -0,0 +1,24 @@
/**
* 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.io.File;
public interface IWorkspaceRepository {
File getWorkspace();
boolean createWorkspace();
}

@ -0,0 +1,160 @@
/**
* 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.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import net.opengis.wps.x100.ProcessDescriptionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.n52.wps.PropertyDocument.Property;
import org.n52.wps.algorithm.annotation.Algorithm;
import org.n52.wps.commons.WPSConfig;
/**
* A static repository to retrieve the available algorithms.
* @author foerster
*
*/
public class LocalAlgorithmRepository implements ITransactionalAlgorithmRepository{
private static Logger LOGGER = LoggerFactory.getLogger(LocalAlgorithmRepository.class);
private Map<String, String> algorithmMap;
private Map<String, ProcessDescriptionType> processDescriptionMap;
public LocalAlgorithmRepository() {
algorithmMap = new HashMap<String, String>();
processDescriptionMap = new HashMap<String, ProcessDescriptionType>();
// check if the repository is active
if(WPSConfig.getInstance().isRepositoryActive(this.getClass().getCanonicalName())){
Property[] propertyArray = WPSConfig.getInstance().getPropertiesForRepositoryClass(this.getClass().getCanonicalName());
for(Property property : propertyArray){
// check the name and active state
if(property.getName().equalsIgnoreCase("Algorithm") && property.getActive()){
addAlgorithm(property.getStringValue());
}
}
} else {
LOGGER.debug("Local Algorithm Repository is inactive.");
}
}
public boolean addAlgorithms(String[] algorithms) {
for(String algorithmClassName : algorithms) {
addAlgorithm(algorithmClassName);
}
LOGGER.info("Algorithms registered!");
return true;
}
public IAlgorithm getAlgorithm(String className) {
try {
return loadAlgorithm(algorithmMap.get(className));
} catch (Exception e) {
LOGGER.error("error getting algorithm",e);
return null;
}
}
public Collection<String> getAlgorithmNames() {
return new ArrayList<String>(algorithmMap.keySet());
}
public boolean containsAlgorithm(String className) {
return algorithmMap.containsKey(className);
}
private IAlgorithm loadAlgorithm(String algorithmClassName) throws Exception {
Class<?> algorithmClass = LocalAlgorithmRepository.class.getClassLoader().loadClass(algorithmClassName);
IAlgorithm algorithm = null;
if (IAlgorithm.class.isAssignableFrom(algorithmClass)) {
algorithm = IAlgorithm.class.cast(algorithmClass.newInstance());
} else if (algorithmClass.isAnnotationPresent(Algorithm.class)) {
// we have an annotated algorithm that doesn't implement IAlgorithm
// wrap it in a proxy class
algorithm = new AbstractAnnotatedAlgorithm.Proxy(algorithmClass);
}
else {
throw new Exception("Could not load algorithm " + algorithmClassName + " does not implement IAlgorithm or have a Algorithm annotation.");
}
if(!algorithm.processDescriptionIsValid()) {
LOGGER.warn("Algorithm description is not valid: " + algorithmClassName);
throw new Exception("Could not load algorithm " +algorithmClassName +". ProcessDescription Not Valid.");
}
return algorithm;
}
public boolean addAlgorithm(Object processID) {
if(!(processID instanceof String)){
return false;
}
String algorithmClassName = (String) processID;
algorithmMap.put(algorithmClassName, algorithmClassName);
LOGGER.info("Algorithm class registered: " + algorithmClassName);
return true;
}
public boolean removeAlgorithm(Object processID) {
if(!(processID instanceof String)){
return false;
}
String className = (String) processID;
if(algorithmMap.containsKey(className)){
algorithmMap.remove(className);
return true;
}
return false;
}
@Override
public ProcessDescriptionType getProcessDescription(String processID) {
if(!processDescriptionMap.containsKey(processID)){
processDescriptionMap.put(processID, getAlgorithm(processID).getDescription());
}
return processDescriptionMap.get(processID);
}
@Override
public void shutdown() {
// TODO Auto-generated method stub
}
}

@ -0,0 +1,90 @@
/**
* 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.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.opengis.wps.x100.ProcessDescriptionType;
public class ServiceLoaderAlgorithmRepository implements IAlgorithmRepository {
private static final Logger logger = LoggerFactory.getLogger(ServiceLoaderAlgorithmRepository.class);
private Map<String, Class<? extends IAlgorithm>> currentAlgorithms;
public ServiceLoaderAlgorithmRepository() {
this.currentAlgorithms = loadAlgorithms();
}
private Map<String, Class<? extends IAlgorithm>> loadAlgorithms() {
Map<String, Class<? extends IAlgorithm>> result = new HashMap<String, Class<? extends IAlgorithm>>();
ServiceLoader<IAlgorithm> loader = ServiceLoader.load(IAlgorithm.class);
for (IAlgorithm ia : loader) {
logger.debug("Adding algorithm with identifier {} and class {}",
ia.getWellKnownName(), ia.getClass().getCanonicalName());
result.put(ia.getWellKnownName(), ia.getClass());
}
return result;
}
@Override
public Collection<String> getAlgorithmNames() {
return this.currentAlgorithms.keySet();
}
@Override
public IAlgorithm getAlgorithm(String processID) {
Class<? extends IAlgorithm> clazz = this.currentAlgorithms.get(processID);
if (clazz != null) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
logger.warn(e.getMessage(), e);
} catch (IllegalAccessException e) {
logger.warn(e.getMessage(), e);
}
}
return null;
}
@Override
public ProcessDescriptionType getProcessDescription(String processID) {
IAlgorithm algo = getAlgorithm(processID);
if (algo != null) {
return algo.getDescription();
}
return null;
}
@Override
public boolean containsAlgorithm(String processID) {
return this.currentAlgorithms.containsKey(processID);
}
@Override
public void shutdown() {
}
}

@ -0,0 +1,158 @@
/**
* 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.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import net.opengis.wps.x100.ProcessDescriptionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.n52.wps.PropertyDocument.Property;
import org.n52.wps.commons.WPSConfig;
/**
* A static repository to retrieve the available algorithms.
*
* @author foerster, Bastian Schaeffer, University of Muenster
*
*/
public class UploadedAlgorithmRepository implements
ITransactionalAlgorithmRepository {
private static Logger LOGGER = LoggerFactory
.getLogger(LocalAlgorithmRepository.class);
private Map<String, String> algorithmMap;
private Map<String, ProcessDescriptionType> processDescriptionMap;
public UploadedAlgorithmRepository() {
algorithmMap = new HashMap<String, String>();
processDescriptionMap = new HashMap<String, ProcessDescriptionType>();
if (WPSConfig.getInstance().isRepositoryActive(
this.getClass().getCanonicalName())) {
Property[] propertyArray = WPSConfig.getInstance()
.getPropertiesForRepositoryClass(
this.getClass().getCanonicalName());
for (Property property : propertyArray) {
if (property.getName().equalsIgnoreCase("Algorithm")
&& property.getActive()) {
addAlgorithm(property.getStringValue());
}
}
} else {
LOGGER.debug("Local Algorithm Repository is inactive.");
}
}
public boolean addAlgorithms(String[] algorithms) {
for (String algorithmClassName : algorithms) {
addAlgorithm(algorithmClassName);
}
LOGGER.info("Algorithms registered!");
return true;
}
public IAlgorithm getAlgorithm(String className) {
try {
return loadAlgorithm(algorithmMap.get(className));
} catch (Exception e) {
LOGGER.error("error getting algorithm",e);
return null;
}
}
public Collection<IAlgorithm> getAlgorithms() {
Collection<IAlgorithm> resultList = new ArrayList<IAlgorithm>();
try {
for (String algorithmClasses : algorithmMap.values()) {
resultList
.add(loadAlgorithm(algorithmMap.get(algorithmClasses)));
}
} catch (Exception e) {
LOGGER.error("error getting algorithm",e);
}
return resultList;
}
public Collection<String> getAlgorithmNames() {
return new ArrayList<String>(algorithmMap.keySet());
}
public boolean containsAlgorithm(String className) {
return algorithmMap.containsKey(className);
}
private IAlgorithm loadAlgorithm(String algorithmClassName)
throws Exception {
IAlgorithm algorithm = (IAlgorithm) LocalAlgorithmRepository.class
.getClassLoader().loadClass(algorithmClassName).newInstance();
if (!algorithm.processDescriptionIsValid()) {
LOGGER.warn("Algorithm description is not valid: "
+ algorithmClassName);
throw new Exception("Could not load algorithm "
+ algorithmClassName + ". ProcessDescription Not Valid.");
}
return algorithm;
}
public boolean addAlgorithm(Object processID) {
if (!(processID instanceof String)) {
return false;
}
String algorithmClassName = (String) processID;
algorithmMap.put(algorithmClassName, algorithmClassName);
LOGGER.info("Algorithm class registered: " + algorithmClassName);
return true;
}
public boolean removeAlgorithm(Object processID) {
if (!(processID instanceof String)) {
return false;
}
String className = (String) processID;
if (algorithmMap.containsKey(className)) {
algorithmMap.remove(className);
return true;
}
return false;
}
@Override
public ProcessDescriptionType getProcessDescription(String processID) {
if (!processDescriptionMap.containsKey(processID)) {
processDescriptionMap.put(processID, getAlgorithm(processID)
.getDescription());
}
return processDescriptionMap.get(processID);
}
@Override
public void shutdown() {
// TODO Auto-generated method stub
}
}

@ -0,0 +1,47 @@
/**
* 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.test.mock;
import org.n52.wps.io.data.IComplexData;
/**
*
* @author tkunicki
*/
public class MockBinding implements IComplexData {
private final MockComplexObject payload;
public MockBinding(MockComplexObject payload) {
this.payload = payload;
}
@Override
public MockComplexObject getPayload() {
return payload;
}
@Override
public Class getSupportedClass() {
return MockComplexObject.class;
}
@Override
public void dispose() {
}
}

@ -0,0 +1,26 @@
/**
* 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.test.mock;
/**
*
* @author tkunicki
*/
public class MockComplexObject {
}

@ -0,0 +1,27 @@
/**
* 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.test.mock;
/**
*
* @author tkunicki
*/
public enum MockEnum {
VALUE1,
VALUE2,
VALUE3
}

@ -0,0 +1,114 @@
/**
* 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.test.mock;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.n52.wps.FormatDocument.Format;
import org.n52.wps.io.IGenerator;
import org.n52.wps.io.data.IData;
/**
*
* @author tkunicki
*/
public class MockGenerator implements IGenerator {
public final static List<String> schemaSet;
public final static List<String> formatSet;
public final static List<String> encodingSet;
static {
schemaSet = Collections.unmodifiableList(new ArrayList(MockUtil.getParserSupportedSchemas(MockParser.class)));
formatSet = Collections.unmodifiableList(new ArrayList(MockUtil.getParserSupportedFormats(MockParser.class)));
encodingSet = Collections.unmodifiableList(new ArrayList(MockUtil.getParserSupportedEncodings(MockParser.class)));
}
// @Override
// public OutputStream generate(IData coll) {
// throw new UnsupportedOperationException("Not supported yet.");
// }
//
// @Override
// public Class[] getSupportedInternalInputDataType() {
// return new Class[] { MockBinding.class };
// }
@Override
public boolean isSupportedSchema(String schema) {
return schemaSet.contains(schema);
}
@Override
public boolean isSupportedFormat(String format) {
return formatSet.contains(format);
}
@Override
public boolean isSupportedEncoding(String encoding) {
return encodingSet.contains(encoding);
}
@Override
public String[] getSupportedSchemas() {
return schemaSet.toArray(new String[0]);
}
@Override
public String[] getSupportedFormats() {
return formatSet.toArray(new String[0]);
}
@Override
public String[] getSupportedEncodings() {
return encodingSet.toArray(new String[0]);
}
@Override
public InputStream generateStream(IData data, String mimeType, String schema) throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public InputStream generateBase64Stream(IData data, String mimeType, String schema) throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean isSupportedDataBinding(Class<?> clazz) {
return Arrays.binarySearch(getSupportedDataBindings(), clazz) > -1;
}
@Override
public Format[] getSupportedFullFormats() {
Format f = Format.Factory.newInstance();
f.setSchema(schemaSet.get(0));
f.setEncoding(encodingSet.get(0));
f.setMimetype(formatSet.get(0));
return new Format[] {f};
}
@Override
public Class<?>[] getSupportedDataBindings() {
return new Class[] { MockBinding.class };
}
}

@ -0,0 +1,113 @@
/**
* 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.test.mock;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.n52.wps.FormatDocument.Format;
import org.n52.wps.io.IParser;
import org.n52.wps.io.data.IData;
/**
*
* @author tkunicki
*/
public class MockParser implements IParser {
public final static List<String> schemaSet;
public final static List<String> formatSet;
public final static List<String> encodingSet;
static {
schemaSet = Collections.unmodifiableList(new ArrayList(MockUtil.getParserSupportedSchemas(MockParser.class)));
formatSet = Collections.unmodifiableList(new ArrayList(MockUtil.getParserSupportedFormats(MockParser.class)));
encodingSet = Collections.unmodifiableList(new ArrayList(MockUtil.getParserSupportedEncodings(MockParser.class)));
}
// @Override
// public IData parse(InputStream input, String mimeType) {
// throw new UnsupportedOperationException("Not supported yet.");
// }
//
// @Override
// public Class[] getSupportedInternalOutputDataType() {
// return new Class[] { MockBinding.class };
// }
@Override
public boolean isSupportedSchema(String schema) {
return schemaSet.contains(schema);
}
@Override
public boolean isSupportedFormat(String format) {
return formatSet.contains(format);
}
@Override
public boolean isSupportedEncoding(String encoding) {
return encodingSet.contains(encoding);
}
@Override
public String[] getSupportedSchemas() {
return schemaSet.toArray(new String[0]);
}
@Override
public String[] getSupportedFormats() {
return formatSet.toArray(new String[0]);
}
@Override
public String[] getSupportedEncodings() {
return encodingSet.toArray(new String[0]);
}
@Override
public IData parse(InputStream input, String mimeType, String schema) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public IData parseBase64(InputStream input, String mimeType, String schema) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean isSupportedDataBinding(Class<?> clazz) {
return Arrays.binarySearch(getSupportedDataBindings(), clazz) > -1;
}
@Override
public Format[] getSupportedFullFormats() {
Format f = Format.Factory.newInstance();
f.setSchema(schemaSet.get(0));
f.setEncoding(encodingSet.get(0));
f.setMimetype(formatSet.get(0));
return new Format[] {f};
}
@Override
public Class<?>[] getSupportedDataBindings() {
return new Class[] { MockBinding.class };
}
}

@ -0,0 +1,124 @@
/**
* 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.test.mock;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.io.IOUtils;
import org.apache.xmlbeans.XmlException;
import org.n52.wps.PropertyDocument;
import org.n52.wps.PropertyDocument.Property;
import org.n52.wps.commons.WPSConfig;
import org.n52.wps.io.GeneratorFactory;
import org.n52.wps.io.IGenerator;
import org.n52.wps.io.IParser;
import org.n52.wps.io.ParserFactory;
/**
*
* @author tkunicki
*/
public class MockUtil {
public final static String SUPPORTED_SCHEMA = "supportedSchema";
public final static String SUPPORTED_FORMAT = "supportedFormat";
public final static String SUPPORTED_ENCODING = "supportedEncoding";
private static WPSConfig MOCK_CONFIG;
public synchronized static WPSConfig getMockConfig() throws XmlException, IOException {
if (MOCK_CONFIG == null) {
InputStream configInputStream = null;
try {
configInputStream = MockUtil.class.getResourceAsStream(
"/org/n52/test/mock/wps_config.xml");
WPSConfig.forceInitialization(configInputStream);
MOCK_CONFIG = WPSConfig.getInstance();
ParserFactory.initialize(MOCK_CONFIG.getActiveRegisteredParser());
GeneratorFactory.initialize(MOCK_CONFIG.getActiveRegisteredGenerator());
} finally {
IOUtils.closeQuietly(configInputStream);
}
}
return MOCK_CONFIG;
}
public static Collection<String> getParserSupportedSchemas(Class<? extends IParser> clazz) {
return getParserPropertyValues(clazz, SUPPORTED_SCHEMA);
}
public static Collection<String> getParserSupportedFormats(Class<? extends IParser> clazz) {
return getParserPropertyValues(clazz, SUPPORTED_FORMAT);
}
public static Collection<String> getParserSupportedEncodings(Class<? extends IParser> clazz) {
return getParserPropertyValues(clazz, SUPPORTED_ENCODING);
}
public static Collection<String> getGeneratorSupportedSchemas(Class<? extends IGenerator> clazz) {
return getGeneratorPropertyValues(clazz, SUPPORTED_SCHEMA);
}
public static Collection<String> getGeneratorSupportedFormats(Class<? extends IGenerator> clazz) {
return getGeneratorPropertyValues(clazz, SUPPORTED_FORMAT);
}
public static Collection<String> getGeneratorSupportedEncodings(Class<? extends IGenerator> clazz) {
return getGeneratorPropertyValues(clazz, SUPPORTED_ENCODING);
}
public static Collection<String> getParserPropertyValues(Class<? extends IParser> clazz, String propertyName) {
String clazzName = clazz.getName();
ArrayList<String> propertyList = new ArrayList<String>();
try {
WPSConfig mockConfig = MockUtil.getMockConfig();
PropertyDocument.Property properties[] =
mockConfig.getPropertiesForParserClass(clazzName);
for (Property property : properties) {
if (propertyName.equals(property.getName())) {
propertyList.add(property.getStringValue());
}
}
propertyList.trimToSize();
} catch (Exception e) {
System.err.println("ERROR parsing property " + propertyName + " for Parser class " + clazzName);
}
return propertyList;
}
public static Collection<String> getGeneratorPropertyValues(Class<? extends IGenerator> clazz, String propertyName) {
String clazzName = clazz.getName();
ArrayList<String> propertyList = new ArrayList<String>();
try {
WPSConfig mockConfig = MockUtil.getMockConfig();
PropertyDocument.Property properties[] =
mockConfig.getPropertiesForGeneratorClass(clazzName);
for (Property property : properties) {
if (propertyName.equals(property.getName())) {
propertyList.add(property.getStringValue());
}
}
} catch (Exception e) {
System.err.println("ERROR parsing property " + propertyName + " for Generator class " + clazzName);
}
propertyList.trimToSize();
return propertyList;
}
}

@ -0,0 +1,36 @@
/**
* 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.algorithm.annotation;
import org.hamcrest.CoreMatchers;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class AnnotatedAlgorithmIntrospectorTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
public AnnotatedAlgorithmIntrospector instance;
@Test
public void testClassWithNoExecuteAnnotation() {
thrown.expect(RuntimeException.class);
thrown.expectMessage(CoreMatchers.containsString("No execute method binding"));
instance = new AnnotatedAlgorithmIntrospector(ClassWithNoExecuteAnnotation.class);
}
}

@ -0,0 +1,592 @@
/**
* 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.algorithm.annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
import org.n52.test.mock.MockEnum;
import org.n52.wps.algorithm.annotation.AnnotationBinding.InputBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.InputFieldBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.InputMethodBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.OutputBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.OutputFieldBinding;
import org.n52.wps.algorithm.annotation.AnnotationBinding.OutputMethodBinding;
/**
*
* @author tkunicki
*/
public class AnnotatedMemberDescriptorTest extends TestCase {
// START - TEST DATA AS CLASS FIELDS AND METHODS
// represent almost all cases: literal or complex data, input or output. with expections noted below
public String stringField;
public List<String> stringListField;
public List<? extends String> stringExtendListField;
public List<? super String> stringSuperListField;
public List unboundListField; // effectively List<? extends Object>
// no polymorphism in test methods, will break use of methodMap
public void setString(String stringParameter) {
this.stringField = stringParameter;
}
public String getString() {
return stringField;
}
public void setStringList(List<String> stringListParameter) {
this.stringListField = stringListParameter;
}
public List<String> getStringList() {
return this.stringListField;
}
public void setStringExtendList(List<? extends String> stringExtendListParameter) {
this.stringExtendListField = stringExtendListParameter;
}
public List<? extends String> getStringExtendList() {
return this.stringExtendListField;
}
public void setStringSuperList(List<? super String> stringSuperListParameter) {
this.stringSuperListField = stringSuperListParameter;
}
public List<? super String> getStringSuperList() {
return this.stringSuperListField;
}
public void setUnboundList(List unboundListParameter) {
this.unboundListField = unboundListParameter;
}
public List getUnboundList() {
return this.unboundListField;
}
// special case: enumerations for *inputs* have data type of String *unless* List for outputs
public MockEnum enumField;
public List<MockEnum> enumListField;
/* NOT CURRENTLY SUPPORTED, need to be able to infer concrete type by reflection
public List<? extends MockEnum> enumExtendsListField;
public List<? super MockEnum> enumSuperListField;
*/
// no polymorphism in test methods, will break use of methodMap
public MockEnum getEnum() {
return enumField;
}
public void setEnum(MockEnum enumParameter) {
this.enumField = enumParameter;
}
public List<MockEnum> getEnumList() {
return enumListField;
}
public void setEnumList(List<MockEnum> enumListParameter) {
this.enumListField = enumListParameter;
}
/* NOT CURRENTLY SUPPORTED, need to be able to infer concrete type by reflection
public List<? extends MockEnum> getEnumExtendList() {
return enumExtendsListField;
}
public void setEnumExtendList(List<? extends MockEnum> enumExtendsListParameter) {
this.enumExtendsListField = enumExtendsListParameter;
}
public List<? super MockEnum> getEnumSuperList() {
return enumSuperListField;
}
public void setEnumSuperList(List<? super MockEnum> enumSuperListParameter) {
this.enumSuperListField = enumSuperListParameter;
}
*/
// END - TEST DATA AS CLASS FIELDS AND METHODS
Map<String, Method> methodMap;
public AnnotatedMemberDescriptorTest(String testName) {
super(testName);
methodMap = new HashMap<String, Method>();
for (Method method : AnnotationMemberDescriptorSample.class.getDeclaredMethods()) {
methodMap.put(method.getName(), method);
}
methodMap = Collections.unmodifiableMap(methodMap);
}
private Method getSampleMethod(String name) throws NoSuchMethodException {
Method method = methodMap.get(name);
if (method == null) {
throw new NoSuchMethodException(name);
}
return method;
}
private Field getSampleField(String name) throws NoSuchFieldException {
return AnnotationMemberDescriptorSample.class.getDeclaredField(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
public void testStringFieldAsInput() throws NoSuchFieldException {
Field field = getSampleField("stringField");
InputFieldBinding memberDescriptor = new InputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateInputMember(memberDescriptor);
}
public void testStringFieldAsOutput() throws NoSuchFieldException {
Field field = getSampleField("stringField");
OutputFieldBinding memberDescriptor = new OutputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateOutputMember(memberDescriptor);
}
public void testStringSetter() throws NoSuchMethodException {
Method method = getSampleMethod("setString");
InputMethodBinding memberDescriptor = new InputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericParameterTypes()[0], memberDescriptor.getMemberType());
validateInputMember(memberDescriptor);
}
public void testStringGetter() throws NoSuchMethodException {
Method method = getSampleMethod("getString");
OutputMethodBinding memberDescriptor = new OutputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericReturnType(), memberDescriptor.getMemberType());
validateOutputMember(memberDescriptor);
}
private void validateInputMember(InputBinding memberDescriptor) {
// data type matches member for inputs type *unless* member type is List
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getType());
// payload type matches data type, special handling reserved for enumerations
assertEquals(memberDescriptor.getType(), memberDescriptor.getPayloadType());
assertEquals(false, memberDescriptor.isMemberTypeList());
assertEquals(false, memberDescriptor.isTypeEnum());
}
private void validateOutputMember(OutputBinding memberDescriptor) {
// data type matches member type for outputs
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getType());
// data type matches payload type, special handling reserved for enumerations
assertEquals(memberDescriptor.getType(), memberDescriptor.getPayloadType());
assertEquals(false, memberDescriptor.isTypeEnum());
}
public void testStringListFieldAsInput() throws NoSuchFieldException {
Field field = getSampleField("stringListField");
InputFieldBinding memberDescriptor = new InputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateInputListMember(memberDescriptor);
}
public void testStringListFieldAsOutput() throws NoSuchFieldException {
Field field = getSampleField("stringListField");
OutputFieldBinding memberDescriptor = new OutputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateOutputListMember(memberDescriptor);
}
public void testStringListSetter() throws NoSuchMethodException {
Method method = getSampleMethod("setStringList");
InputMethodBinding memberDescriptor = new InputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericParameterTypes()[0], memberDescriptor.getMemberType());
validateInputListMember(memberDescriptor);
}
public void testStringListGetter() throws NoSuchMethodException {
Method method = getSampleMethod("getStringList");
OutputMethodBinding memberDescriptor = new OutputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericReturnType(), memberDescriptor.getMemberType());
validateOutputListMember(memberDescriptor);
}
private void validateInputListMember(InputBinding memberDescriptor) {
// we extract the parameterized type of the list for inputs. since member
// type is List<String> we expect String
assertEquals(String.class, memberDescriptor.getType());
// payload type matches data type, special handling reserved for enumerations
assertEquals(memberDescriptor.getType(), memberDescriptor.getPayloadType());
assertEquals(true, memberDescriptor.isMemberTypeList());
assertEquals(false, memberDescriptor.isTypeEnum());
}
private void validateOutputListMember(OutputBinding memberDescriptor) {
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getType());
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getPayloadType());
assertEquals(false, memberDescriptor.isTypeEnum());
}
public void testStringExtendListFieldAsInput() throws NoSuchFieldException {
Field field = getSampleField("stringExtendListField");
InputFieldBinding memberDescriptor = new InputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateExtendListInputMember(memberDescriptor);
}
public void testStringExtendListFieldAsOutput() throws NoSuchFieldException {
Field field = getSampleField("stringExtendListField");
OutputFieldBinding memberDescriptor = new OutputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateExtendListOutputMember(memberDescriptor);
}
public void testStringExtendListSetter() throws NoSuchMethodException {
Method method = getSampleMethod("setStringExtendList");
InputMethodBinding memberDescriptor = new InputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericParameterTypes()[0], memberDescriptor.getMemberType());
validateExtendListInputMember(memberDescriptor);
}
public void testStringExtendListGetter() throws NoSuchMethodException {
Method method = getSampleMethod("getStringExtendList");
OutputMethodBinding memberDescriptor = new OutputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericReturnType(), memberDescriptor.getMemberType());
validateExtendListOutputMember(memberDescriptor);
}
private void validateExtendListInputMember(InputBinding memberDescriptor) {
// we extract the parameterized type of the list for inputs. since member
// type is List<? extends String> we expect a WildcardType of <? extends String>
// we need this information later to make sure we can safely assign an
// instance to the list with type safety (fail early behavior)
Type type = memberDescriptor.getType();
assertTrue(type instanceof WildcardType);
WildcardType typeWildcard = (WildcardType)type;
assertEquals(0, typeWildcard.getLowerBounds().length);
assertEquals(1, typeWildcard.getUpperBounds().length);
assertEquals(String.class, typeWildcard.getUpperBounds()[0]);
// we extract the parameterized type of the list for inputs
assertEquals(memberDescriptor.getType(), memberDescriptor.getPayloadType());
assertEquals(true, memberDescriptor.isMemberTypeList());
assertEquals(false, memberDescriptor.isTypeEnum());
}
private void validateExtendListOutputMember(OutputBinding memberDescriptor) {
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getType());
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getPayloadType());
assertEquals(false, memberDescriptor.isTypeEnum());
}
public void testStringSuperListFieldAsInput() throws NoSuchFieldException {
Field field = getSampleField("stringSuperListField");
InputFieldBinding memberDescriptor = new InputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateSuperListInputMember(memberDescriptor);
}
public void testStringSuperListFieldAsOutput() throws NoSuchFieldException {
Field field = getSampleField("stringSuperListField");
OutputFieldBinding memberDescriptor = new OutputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateSuperListOutputMember(memberDescriptor);
}
public void testStringSuperListSetter() throws NoSuchMethodException {
Method method = getSampleMethod("setStringSuperList");
InputMethodBinding memberDescriptor = new InputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericParameterTypes()[0], memberDescriptor.getMemberType());
validateSuperListInputMember(memberDescriptor);
}
public void testStringSuperListGetter() throws NoSuchMethodException {
Method method = getSampleMethod("getStringSuperList");
OutputMethodBinding memberDescriptor = new OutputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericReturnType(), memberDescriptor.getMemberType());
validateSuperListOutputMember(memberDescriptor);
}
private void validateSuperListInputMember(InputBinding memberDescriptor) {
// we extract the parameterized type of the list for inputs. since member
// type is List<? super String> we expect a WildcardType of <? super String>
// we need this information later to make sure we can safely assign an
// instance to the list with type safety (fail early behavior)
Type type = memberDescriptor.getType();
assertTrue(type instanceof WildcardType);
WildcardType typeWildcard = (WildcardType)type;
assertEquals(1, typeWildcard.getLowerBounds().length);
assertEquals(String.class, typeWildcard.getLowerBounds()[0]);
assertEquals(1, typeWildcard.getUpperBounds().length);
assertEquals(Object.class, typeWildcard.getUpperBounds()[0]);
// we extract the parameterized type of the list for inputs
assertEquals(memberDescriptor.getType(), memberDescriptor.getPayloadType());
assertEquals(true, memberDescriptor.isMemberTypeList());
assertEquals(false, memberDescriptor.isTypeEnum());
}
private void validateSuperListOutputMember(OutputBinding memberDescriptor) {
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getType());
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getPayloadType());
assertEquals(false, memberDescriptor.isTypeEnum());
}
public void testUnboundListFieldAsInput() throws NoSuchFieldException {
Field field = getSampleField("unboundListField");
InputFieldBinding memberDescriptor = new InputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateUnboundListInputMember(memberDescriptor);
}
public void testUnboundListFieldAsOutput() throws NoSuchFieldException {
Field field = getSampleField("unboundListField");
OutputFieldBinding memberDescriptor = new OutputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateUnboundListOutputMember(memberDescriptor);
}
public void testUnboundListSetter() throws NoSuchMethodException {
Method method = getSampleMethod("setUnboundList");
InputMethodBinding memberDescriptor = new InputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericParameterTypes()[0], memberDescriptor.getMemberType());
validateUnboundListInputMember(memberDescriptor);
}
public void testUnboundListGetter() throws NoSuchMethodException {
Method method = getSampleMethod("getUnboundList");
OutputMethodBinding memberDescriptor = new OutputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericReturnType(), memberDescriptor.getMemberType());
validateUnboundListOutputMember(memberDescriptor);
}
private void validateUnboundListInputMember(InputBinding memberDescriptor) {
// // we extract the parameterized type of the list for inputs. since member
// // type is List<? super String> we expect a WildcardType of <? super String>
// // we need this information later to make sure we can safely assign an
// // instance to the list with type safety (fail early behavior)
// Type type = memberDescriptor.getType();
// assertTrue(type instanceof WildcardType);
// WildcardType typeWildcard = (WildcardType)type;
// assertEquals(0, typeWildcard.getLowerBounds().length);
// assertEquals(1, typeWildcard.getUpperBounds().length);
// assertEquals(Object.class, typeWildcard.getUpperBounds()[0]);
// // we extract the parameterized type of the list for inputs
// assertEquals(memberDescriptor.getType(), memberDescriptor.getPayloadType());
// assertEquals(true, memberDescriptor.isMemberTypeList());
// assertEquals(false, memberDescriptor.isTypeEnum());
// we extract the parameterized type of the list for inputs. since member
// type is List<? extends Object> we expect a WildcardType of <? extends Object>
// we need this information later to make sure we can safely assign an
// instance to the list with type safety (fail early behavior)
Type type = memberDescriptor.getType();
assertTrue(type instanceof WildcardType);
WildcardType typeWildcard = (WildcardType)type;
assertEquals(0, typeWildcard.getLowerBounds().length);
assertEquals(1, typeWildcard.getUpperBounds().length);
assertEquals(Object.class, typeWildcard.getUpperBounds()[0]);
// we extract the parameterized type of the list for inputs
assertEquals(memberDescriptor.getType(), memberDescriptor.getPayloadType());
assertEquals(true, memberDescriptor.isMemberTypeList());
assertEquals(false, memberDescriptor.isTypeEnum());
}
private void validateUnboundListOutputMember(OutputBinding memberDescriptor) {
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getType());
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getPayloadType());
assertEquals(false, memberDescriptor.isTypeEnum());
}
public void testEnumFieldAsInput() throws NoSuchFieldException {
Field field = getSampleField("enumField");
InputFieldBinding memberDescriptor = new InputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateEnumInputMember(memberDescriptor);
}
public void testEnumFieldAsOutput() throws NoSuchFieldException {
Field field = getSampleField("enumField");
OutputFieldBinding memberDescriptor = new OutputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateEnumOutputMember(memberDescriptor);
}
public void testEnumSetter() throws NoSuchMethodException {
Method method = getSampleMethod("setEnum");
InputMethodBinding memberDescriptor = new InputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericParameterTypes()[0], memberDescriptor.getMemberType());
validateEnumInputMember(memberDescriptor);
}
public void testEnumGetter() throws NoSuchMethodException {
Method method = getSampleMethod("getEnum");
OutputMethodBinding memberDescriptor = new OutputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericReturnType(), memberDescriptor.getMemberType());
validateEnumOutputMember(memberDescriptor);
}
private void validateEnumInputMember(InputBinding memberDescriptor) {
assertEquals(MockEnum.class, memberDescriptor.getType());
// for all instances of Class<? extends Enum> the payload type is Class<String>
// as these will be bound with LiteralStringBinding
assertEquals(String.class, memberDescriptor.getPayloadType());
assertEquals(false, memberDescriptor.isMemberTypeList());
assertEquals(true, memberDescriptor.isTypeEnum());
}
private void validateEnumOutputMember(OutputBinding memberDescriptor) {
assertEquals(MockEnum.class, memberDescriptor.getType());
// for all instances of Class<? extends Enum> the payload type is Class<String>
// as these will be bound with LiteralStringBinding
assertEquals(String.class, memberDescriptor.getPayloadType());
assertEquals(true, memberDescriptor.isTypeEnum());
}
public void testEnumListFieldAsInput() throws NoSuchFieldException {
Field field = getSampleField("enumListField");
InputFieldBinding memberDescriptor = new InputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateEnumListInputMember(memberDescriptor);
}
public void testEnumListFieldAsOutput() throws NoSuchFieldException {
Field field = getSampleField("enumListField");
OutputFieldBinding memberDescriptor = new OutputFieldBinding(field);
assertEquals(field, memberDescriptor.getMember());
assertEquals(field.getGenericType(), memberDescriptor.getMemberType());
validateEnumListOutputMember(memberDescriptor);
}
public void testEnumListSetter() throws NoSuchFieldException, NoSuchMethodException {
Method method = getSampleMethod("setEnumList");
InputMethodBinding memberDescriptor = new InputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericParameterTypes()[0], memberDescriptor.getMemberType());
validateEnumListInputMember(memberDescriptor);
}
public void testEnumListGetter() throws NoSuchFieldException, NoSuchMethodException {
Method method = getSampleMethod("getEnumList");
OutputMethodBinding memberDescriptor = new OutputMethodBinding(method);
assertEquals(method, memberDescriptor.getMember());
assertEquals(method.getGenericReturnType(), memberDescriptor.getMemberType());
validateEnumListOutputMember(memberDescriptor);
}
private void validateEnumListInputMember(InputBinding memberDescriptor) {
assertEquals(MockEnum.class, memberDescriptor.getType());
assertEquals(String.class, memberDescriptor.getPayloadType());
assertEquals(true, memberDescriptor.isMemberTypeList());
assertEquals(true, memberDescriptor.isTypeEnum());
}
private void validateEnumListOutputMember(OutputBinding memberDescriptor) {
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getType());
// no special handling for outputs of member type List, member type matches data type
assertEquals(memberDescriptor.getMemberType(), memberDescriptor.getPayloadType());
assertEquals(false, memberDescriptor.isTypeEnum());
}
}

@ -0,0 +1,106 @@
/**
* 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.algorithm.annotation;
import java.util.List;
import org.n52.test.mock.MockEnum;
/**
*
* @author tkunicki
*/
public class AnnotationMemberDescriptorSample {
// TEST IMPLEMENTATION NOTE: no polymorphism in sample methods, the reflection utilities
// used for generic method lookup used in the unit tests (polymorphism is ok in
// actual implementations as the annotations are what drive method lookups)
// Represents almost all cases for fields: literal or complex data, input or output. with expections noted below.
// We are using String instances, but any literal or complex payload type could be swapped out.
public String stringField;
public List<String> stringListField;
public List<? extends String> stringExtendListField;
public List<? super String> stringSuperListField;
public List unboundListField; // effectively List<? extends Object>
public void setString(String stringParameter) {
this.stringField = stringParameter;
}
public String getString() {
return stringField;
}
public void setStringList(List<String> stringListParameter) {
this.stringListField = stringListParameter;
}
public List<String> getStringList() {
return this.stringListField;
}
public void setStringExtendList(List<? extends String> stringExtendListParameter) {
this.stringExtendListField = stringExtendListParameter;
}
public List<? extends String> getStringExtendList() {
return this.stringExtendListField;
}
public void setStringSuperList(List<? super String> stringSuperListParameter) {
this.stringSuperListField = stringSuperListParameter;
}
public List<? super String> getStringSuperList() {
return this.stringSuperListField;
}
public void setUnboundList(List unboundListParameter) {
this.unboundListField = unboundListParameter;
}
public List getUnboundList() {
return this.unboundListField;
}
// Special case: enumerations for *inputs* have payload type of String so that
// Enumerations can be bound with LiteralStringBinding instances. Exception
// is List of enums for outputs.
public MockEnum enumField;
public List<MockEnum> enumListField;
/* NOT CURRENTLY SUPPORTED, need to be able to infer concrete type by reflection
public List<? extends MockEnum> enumExtendsListField;
public List<? super MockEnum> enumSuperListField;
*/
public MockEnum getEnum() {
return enumField;
}
public void setEnum(MockEnum enumParameter) {
this.enumField = enumParameter;
}
public List<MockEnum> getEnumList() {
return enumListField;
}
public void setEnumList(List<MockEnum> enumListParameter) {
this.enumListField = enumListParameter;
}
/* NOT CURRENTLY SUPPORTED, need to be able to infer concrete type by reflection
public List<? extends MockEnum> getEnumExtendList() {
return enumExtendsListField;
}
public void setEnumExtendList(List<? extends MockEnum> enumExtendsListParameter) {
this.enumExtendsListField = enumExtendsListParameter;
}
public List<? super MockEnum> getEnumSuperList() {
return enumSuperListField;
}
public void setEnumSuperList(List<? super MockEnum> enumSuperListParameter) {
this.enumSuperListField = enumSuperListParameter;
}
*/
}

@ -0,0 +1,33 @@
/**
* 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.algorithm.annotation;
@Algorithm(version = "1.0.0")
public class ClassWithNoExecuteAnnotation {
private String output;
// We forgot to mark this method as @Execute
public void execute() {
}
@LiteralDataOutput(identifier = "output")
public String getOutput() {
return output;
}
}

@ -0,0 +1,332 @@
/**
* 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.algorithm.descriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
import org.n52.test.mock.MockBinding;
/**
*
* @author tkunicki
*/
public class AlgorithmDescriptorTest extends TestCase {
private LiteralDataOutputDescriptor.Builder MOCK_OUPUT1_BUILDER;
private List<InputDescriptor.Builder<?,?>> MOCK_INPUT_BUILDERS;
private List<OutputDescriptor.Builder<?,?>> MOCK_OUTPUT_BUILDERS;
public AlgorithmDescriptorTest(String testName) {
super(testName);
}
@Override
protected void setUp() {
MOCK_INPUT_BUILDERS = new ArrayList<InputDescriptor.Builder<?,?>>();
MOCK_INPUT_BUILDERS.add(LiteralDataInputDescriptor.booleanBuilder("mock_input1"));
MOCK_INPUT_BUILDERS.add(LiteralDataInputDescriptor.booleanBuilder("mock_input2"));
MOCK_INPUT_BUILDERS.add(ComplexDataInputDescriptor.builder("mock_input3", MockBinding.class));
MOCK_INPUT_BUILDERS.add(ComplexDataInputDescriptor.builder("mock_input4", MockBinding.class));
MOCK_INPUT_BUILDERS = Collections.unmodifiableList(MOCK_INPUT_BUILDERS);
MOCK_OUPUT1_BUILDER = LiteralDataOutputDescriptor.booleanBuilder("mock_output1");
MOCK_OUTPUT_BUILDERS = new ArrayList<OutputDescriptor.Builder<?,?>>();
// MOCK_OUTPUT_BUILDERS.add(LiteralDataOutputDescriptor.booleanBuilder("mock_output1"));
MOCK_OUTPUT_BUILDERS.add(LiteralDataOutputDescriptor.booleanBuilder("mock_output2"));
MOCK_OUTPUT_BUILDERS.add(ComplexDataOutputDescriptor.builder("mock_output3", MockBinding.class));
MOCK_OUTPUT_BUILDERS.add(ComplexDataOutputDescriptor.builder("mock_output4", MockBinding.class));
MOCK_OUTPUT_BUILDERS = Collections.unmodifiableList(MOCK_OUTPUT_BUILDERS);
}
public void testStaticBuilder_String() {
AlgorithmDescriptor descriptor = null;
// Test fail-early, exception should be thrown if identifier is 'null';
boolean thrown = false;
try {
AlgorithmDescriptor.builder((String)null);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
// test that static builder with String parameter
descriptor = AlgorithmDescriptor.builder("mock_identifier").
addOutputDescriptor(MOCK_OUPUT1_BUILDER). // require one output
build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertTrue(descriptor.hasTitle());
assertEquals("mock_identifier", descriptor.getTitle());
}
public void testStaticBuilder_Class() {
AlgorithmDescriptor descriptor = null;
// Test fail-early, exception should be thrown if idnetifier is 'null';
boolean thrown = false;
try {
AlgorithmDescriptor.builder((Class)null);
fail("Expected NullPointerException");
} catch (NullPointerException e) {
thrown = true;
}
assertTrue(thrown);
// test that static builder with a valid class parameter
descriptor = AlgorithmDescriptor.builder(getClass()).
addOutputDescriptor(MOCK_OUPUT1_BUILDER). // require one output
build();
assertEquals(getClass().getCanonicalName(), descriptor.getIdentifier());
assertTrue(descriptor.hasTitle());
assertEquals(getClass().getCanonicalName(), descriptor.getTitle());
}
public void testVersion() {
AlgorithmDescriptor descriptor = null;
// test default is "1.0.0"
descriptor = createMinimumCompliantBuilder().build();
assertEquals("1.0.0", descriptor.getVersion());
// test we can change
descriptor = createMinimumCompliantBuilder().version("X.Y.Z").build();
assertEquals("X.Y.Z", descriptor.getVersion());
}
public void testStoreSupported() {
AlgorithmDescriptor descriptor = null;
// test default is true
descriptor = createMinimumCompliantBuilder().build();
assertTrue(descriptor.getStoreSupported());
// test we can set to true (explicitly)
descriptor = createMinimumCompliantBuilder().storeSupported(true).build();
assertTrue(descriptor.getStoreSupported());
// test we can set to false
descriptor = createMinimumCompliantBuilder().storeSupported(false).build();
assertFalse(descriptor.getStoreSupported());
}
public void testStatusSupported() {
AlgorithmDescriptor descriptor = null;
// test default is true
descriptor = createMinimumCompliantBuilder().build();
assertTrue(descriptor.getStatusSupported());
// test we can set to true (explicitly)
descriptor = createMinimumCompliantBuilder().statusSupported(true).build();
assertTrue(descriptor.getStatusSupported());
// test we can set to false
descriptor = createMinimumCompliantBuilder().statusSupported(false).build();
assertFalse(descriptor.getStatusSupported());
}
public void testInputDescriptorHandling() {
AlgorithmDescriptor descriptor = null;
// test default is true
descriptor = createMinimumCompliantBuilder().build();
assertNotNull(descriptor.getInputDescriptors());
assertEquals(0, descriptor.getInputDescriptors().size());
assertNotNull(descriptor.getInputIdentifiers());
assertEquals(0, descriptor.getInputIdentifiers().size());
// test addInputDescriptor(InputDescriptor.Builder<?,?>) interface.
AlgorithmDescriptor.Builder<?> builder = createMinimumCompliantBuilder();
for (InputDescriptor.Builder inputBuilder : MOCK_INPUT_BUILDERS) {
builder.addInputDescriptor(inputBuilder);
}
validateInputDescriptors(builder.build());
// test addInputDescriptor(InputDescriptor<?>) interface.
builder = createMinimumCompliantBuilder();
for (InputDescriptor.Builder inputBuilder : MOCK_INPUT_BUILDERS) {
builder.addInputDescriptor(inputBuilder.build());
}
validateInputDescriptors(builder.build());
// test addInputDescriptor(InputDescriptor<?>) interface.
builder = createMinimumCompliantBuilder();
List<InputDescriptor> inputDescriptorList = new ArrayList<InputDescriptor>(MOCK_INPUT_BUILDERS.size());
for (InputDescriptor.Builder inputBuilder : MOCK_INPUT_BUILDERS) {
inputDescriptorList.add(inputBuilder.build());
}
builder.addInputDescriptors(inputDescriptorList);
validateInputDescriptors(builder.build());
}
public void testOutputDescriptorHanding() {
AlgorithmDescriptor descriptor = null;
// Test fail-early, exception should be thrown if idnetifier is 'null';
boolean thrown = false;
try {
AlgorithmDescriptor.builder("mock_identifier").build();
fail("Expected IllegalArgumentException");
} catch (IllegalStateException e) {
thrown = true;
}
assertTrue(thrown);
// test assumption that createMinimumCompliantBuilder() returns us 1 output
descriptor = createMinimumCompliantBuilder().build();
assertNotNull(descriptor.getOutputDescriptors());
assertEquals(1, descriptor.getOutputDescriptors().size());
assertNotNull(descriptor.getOutputIdentifiers());
assertEquals(1, descriptor.getOutputIdentifiers().size());
// test addOutputDescriptor(OutputDescriptor.Builder<?,?>) interface.
AlgorithmDescriptor.Builder<?> builder = createMinimumCompliantBuilder();
for (OutputDescriptor.Builder outputBuilder : MOCK_OUTPUT_BUILDERS) {
builder.addOutputDescriptor(outputBuilder);
}
validateOutputDescriptors(builder.build());
// test addOutputDescriptor(OutputDescriptor<?>) interface.
builder = createMinimumCompliantBuilder();
for (OutputDescriptor.Builder outputBuilder : MOCK_OUTPUT_BUILDERS) {
builder.addOutputDescriptor(outputBuilder.build());
}
validateOutputDescriptors(builder.build());
// test addOutputDescriptor(OutputDescriptor<?>) interface.
builder = createMinimumCompliantBuilder();
List<OutputDescriptor> outputDescriptorList = new ArrayList<OutputDescriptor>(MOCK_OUTPUT_BUILDERS.size());
for (OutputDescriptor.Builder outputBuilder : MOCK_OUTPUT_BUILDERS) {
outputDescriptorList.add(outputBuilder.build());
}
builder.addOutputDescriptors(outputDescriptorList);
validateOutputDescriptors(builder.build());
}
private AlgorithmDescriptor.Builder<?> createMinimumCompliantBuilder() {
return AlgorithmDescriptor.builder("mock_identifier").
addOutputDescriptor(MOCK_OUPUT1_BUILDER);
}
private void validateInputDescriptors(AlgorithmDescriptor algorithmDescriptor) {
assertNotNull(algorithmDescriptor.getInputDescriptors());
// Test Collection<InputDescriptor> getInputDescriptors()
Collection<InputDescriptor> collection = algorithmDescriptor.getInputDescriptors();
// correct size?
assertEquals(4, collection.size());
// input order preserved?
Iterator<InputDescriptor> iterator = collection.iterator();
InputDescriptor inputDescriptor = iterator.next();
assertNotNull(inputDescriptor);
assertEquals("mock_input1", inputDescriptor.getIdentifier());
inputDescriptor = iterator.next();
assertNotNull(inputDescriptor);
assertEquals("mock_input2", inputDescriptor.getIdentifier());
inputDescriptor = iterator.next();
assertNotNull(inputDescriptor);
assertEquals("mock_input3", inputDescriptor.getIdentifier());
inputDescriptor = iterator.next();
assertNotNull(inputDescriptor);
assertEquals("mock_input4", inputDescriptor.getIdentifier());
assertFalse(iterator.hasNext());
// Test InputDescriptor getInputDescriptor(String)
// Can we access by indentifier?
assertNotNull(algorithmDescriptor.getInputDescriptor("mock_input1"));
assertNotNull(algorithmDescriptor.getInputDescriptor("mock_input2"));
assertNotNull(algorithmDescriptor.getInputDescriptor("mock_input3"));
assertNotNull(algorithmDescriptor.getInputDescriptor("mock_input4"));
// Are we getting the correct decriptors returned by identifier?
assertEquals(algorithmDescriptor.getInputDescriptor("mock_input1").getIdentifier(), "mock_input1");
assertEquals(algorithmDescriptor.getInputDescriptor("mock_input2").getIdentifier(), "mock_input2");
assertEquals(algorithmDescriptor.getInputDescriptor("mock_input3").getIdentifier(), "mock_input3");
assertEquals(algorithmDescriptor.getInputDescriptor("mock_input4").getIdentifier(), "mock_input4");
// Test List<String> getInputIdentifiers();
List<String> inputIdentifierList = algorithmDescriptor.getInputIdentifiers();
// Size ok?
assertEquals(4, inputIdentifierList.size());
// Order preserved?
assertEquals("mock_input1", inputIdentifierList.get(0));
assertEquals("mock_input2", inputIdentifierList.get(1));
assertEquals("mock_input3", inputIdentifierList.get(2));
assertEquals("mock_input4", inputIdentifierList.get(3));
}
private void validateOutputDescriptors(AlgorithmDescriptor algorithmDescriptor) {
assertNotNull(algorithmDescriptor.getOutputDescriptors());
// Test Collection<OutputDescriptor> getOutputDescriptors()
Collection<OutputDescriptor> collection = algorithmDescriptor.getOutputDescriptors();
// correct size?
assertEquals(4, collection.size());
// output order preserved?
Iterator<OutputDescriptor> iterator = collection.iterator();
OutputDescriptor outputDescriptor = iterator.next();
assertNotNull(outputDescriptor);
assertEquals("mock_output1", outputDescriptor.getIdentifier());
outputDescriptor = iterator.next();
assertNotNull(outputDescriptor);
assertEquals("mock_output2", outputDescriptor.getIdentifier());
outputDescriptor = iterator.next();
assertNotNull(outputDescriptor);
assertEquals("mock_output3", outputDescriptor.getIdentifier());
outputDescriptor = iterator.next();
assertNotNull(outputDescriptor);
assertEquals("mock_output4", outputDescriptor.getIdentifier());
assertFalse(iterator.hasNext());
// Test OutputDescriptor getOutputDescriptor(String)
// Can we access by indentifier?
assertNotNull(algorithmDescriptor.getOutputDescriptor("mock_output1"));
assertNotNull(algorithmDescriptor.getOutputDescriptor("mock_output2"));
assertNotNull(algorithmDescriptor.getOutputDescriptor("mock_output3"));
assertNotNull(algorithmDescriptor.getOutputDescriptor("mock_output4"));
// Are we getting the correct decriptors returned by identifier?
assertEquals(algorithmDescriptor.getOutputDescriptor("mock_output1").getIdentifier(), "mock_output1");
assertEquals(algorithmDescriptor.getOutputDescriptor("mock_output2").getIdentifier(), "mock_output2");
assertEquals(algorithmDescriptor.getOutputDescriptor("mock_output3").getIdentifier(), "mock_output3");
assertEquals(algorithmDescriptor.getOutputDescriptor("mock_output4").getIdentifier(), "mock_output4");
// Test List<String> getOutputIdentifiers();
List<String> outputIdentifierList = algorithmDescriptor.getOutputIdentifiers();
// Size ok?
assertEquals(4, outputIdentifierList.size());
// Order preserved?
assertEquals("mock_output1", outputIdentifierList.get(0));
assertEquals("mock_output2", outputIdentifierList.get(1));
assertEquals("mock_output3", outputIdentifierList.get(2));
assertEquals("mock_output4", outputIdentifierList.get(3));
}
}

@ -0,0 +1,71 @@
/**
* 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.algorithm.descriptor;
import junit.framework.TestCase;
/**
*
* @author tkunicki
*/
public class BoundDataDescriptorTest extends TestCase {
public BoundDataDescriptorTest(String testName) {
super(testName);
}
public void testBinding() {
BoundDescriptor descriptor = null;
// Test fail-early, exception should be thrown if binding is 'null';
boolean thrown = false;
try {
descriptor = (new BoundDescriptorImpl.Builder(null)).build();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
// make sure the class type we build with is the same as the one returned
// by the constucted object
descriptor = (new BoundDescriptorImpl.Builder(Double.class)).build();
assertEquals(Double.class, descriptor.getBinding());
descriptor = (new BoundDescriptorImpl.Builder(MockNumber.class)).build();
assertEquals(MockNumber.class, descriptor.getBinding());
}
public static class BoundDescriptorImpl extends BoundDescriptor<Class<? extends Number>> {
private BoundDescriptorImpl(Builder builder) { super(builder); }
public static class Builder extends BoundDescriptor.Builder<Builder, Class<? extends Number>> {
Builder(Class<? extends Number> binding) {
super("mock_identifier", binding);
}
@Override protected Builder self() { return this; }
public BoundDescriptorImpl build() { return new BoundDescriptorImpl(this); }
}
}
public static class MockNumber extends Number {
@Override public int intValue() { return Integer.MAX_VALUE; }
@Override public long longValue() { return Long.MAX_VALUE; }
@Override public float floatValue() { return Float.MAX_VALUE; }
@Override public double doubleValue() { return Double.MAX_VALUE; };
}
}

@ -0,0 +1,145 @@
/**
* 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.algorithm.descriptor;
import java.math.BigInteger;
import junit.framework.TestCase;
import org.n52.test.mock.MockBinding;
/**
*
* @author tkunicki
*/
public class ComplexDataInputDescriptorTest extends TestCase {
public ComplexDataInputDescriptorTest(String testName) {
super(testName);
}
public void testMaximumMegabytes() {
ComplexDataInputDescriptor descriptor = null;
descriptor = ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).build();
assertNull(descriptor.getMaximumMegaBytes());
assertFalse(descriptor.hasMaximumMegaBytes());
descriptor = ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(0).build();
assertNotNull(descriptor.getMaximumMegaBytes());
assertEquals(BigInteger.valueOf(0), descriptor.getMaximumMegaBytes());
assertFalse(descriptor.hasMaximumMegaBytes());
descriptor = ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(BigInteger.valueOf(0)).build();
assertNotNull(descriptor.getMaximumMegaBytes());
assertEquals(BigInteger.valueOf(0), descriptor.getMaximumMegaBytes());
assertFalse(descriptor.hasMaximumMegaBytes());
descriptor = ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(1).build();
assertNotNull(descriptor.getMaximumMegaBytes());
assertEquals(BigInteger.valueOf(1), descriptor.getMaximumMegaBytes());
descriptor = ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(BigInteger.valueOf(1)).build();
assertNotNull(descriptor.getMaximumMegaBytes());
assertEquals(BigInteger.valueOf(1), descriptor.getMaximumMegaBytes());
descriptor = ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(Integer.MAX_VALUE).build();
assertNotNull(descriptor.getMaximumMegaBytes());
assertEquals(BigInteger.valueOf(Integer.MAX_VALUE), descriptor.getMaximumMegaBytes());
descriptor = ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(BigInteger.valueOf(Integer.MAX_VALUE)).build();
assertNotNull(descriptor.getMaximumMegaBytes());
assertEquals(BigInteger.valueOf(Integer.MAX_VALUE), descriptor.getMaximumMegaBytes());
boolean thrown = false;
try {
ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(-1);
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(BigInteger.valueOf(-1));
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(Integer.MIN_VALUE);
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).
maximumMegaBytes(BigInteger.valueOf(Integer.MIN_VALUE));
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
}
public void testStaticBuilder() {
ComplexDataInputDescriptor descriptor =
ComplexDataInputDescriptor.builder("mock_identifier", MockBinding.class).build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(MockBinding.class, descriptor.getBinding());
boolean thrown = false;
try {
ComplexDataInputDescriptor.builder(null, MockBinding.class);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
ComplexDataInputDescriptor.builder("", MockBinding.class);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
ComplexDataInputDescriptor.builder("mock_identifier", null);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
}
}

@ -0,0 +1,67 @@
/**
* 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.algorithm.descriptor;
import junit.framework.TestCase;
import org.n52.test.mock.MockBinding;
/**
*
* @author tkunicki
*/
public class ComplexDataOutputDescriptorTest extends TestCase {
public ComplexDataOutputDescriptorTest(String testName) {
super(testName);
}
public void testBuilder() {
ComplexDataOutputDescriptor descriptor =
ComplexDataOutputDescriptor.builder("mock_identifier", MockBinding.class).build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(MockBinding.class, descriptor.getBinding());
boolean thrown = false;
try {
ComplexDataOutputDescriptor.builder(null, MockBinding.class);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
ComplexDataOutputDescriptor.builder("", MockBinding.class);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
ComplexDataOutputDescriptor.builder("mock_identifier", null);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
}
}

@ -0,0 +1,113 @@
/**
* 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.algorithm.descriptor;
import junit.framework.TestCase;
/**
*
* @author tkunicki
*/
public class DescriptorTest extends TestCase {
public DescriptorTest(String testName) {
super(testName);
}
public void testIdentifier() {
DescriptorImpl descriptor = null;
boolean thrown = false;
try {
new DescriptorImpl.Builder(null);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
new DescriptorImpl.Builder("");
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
// set case: set to 'an_identifier'
descriptor = (new DescriptorImpl.Builder("mock_identifier")).build();
assertEquals("mock_identifier", descriptor.getIdentifier());
}
public void testTitle() {
DescriptorImpl descriptor = null;
// default case: title is not initialized and therefore is null;
descriptor = (new DescriptorImpl.Builder("mock_identifier")).build();
assertNull(descriptor.getTitle());
assertFalse(descriptor.hasTitle());
// unset annotation case: 'title' default/unset value for annotations
// is empty string as 'null' is not a valid annotation value;
descriptor = (new DescriptorImpl.Builder("mock_identifier")).title("").build();
assertEquals("", descriptor.getTitle());
assertFalse(descriptor.hasTitle());
// set case: set to 'an_title'
descriptor = (new DescriptorImpl.Builder("mock_identifier")).title("mock_title").build();
assertEquals("mock_title", descriptor.getTitle());
assertTrue(descriptor.hasTitle());
}
public void testAbstract() {
DescriptorImpl descriptor = null;
// default case: abstrakt is not initialized and therefore is null;
descriptor = (new DescriptorImpl.Builder("mock_identifier")).build();
assertNull(descriptor.getAbstract());
assertFalse(descriptor.hasAbstract());
// unset annotation case: 'abstrakt' default/unset value for annotations
// is empty string as 'null' is not a valid annotation value;
descriptor = (new DescriptorImpl.Builder("mock_identifier")).abstrakt("").build();
assertEquals("", descriptor.getAbstract());
assertFalse(descriptor.hasAbstract());
// set case: set to 'an_abstrakt'
descriptor = (new DescriptorImpl.Builder("mock_identifier")).abstrakt("an_abstract").build();
assertEquals("an_abstract", descriptor.getAbstract());
assertTrue(descriptor.hasAbstract());
}
// Dummy implementation, Descriptor and Builder classes are abstract
// so we need to provide an concrete implementation to test.
public static class DescriptorImpl extends Descriptor {
private DescriptorImpl(Builder builder) { super(builder); }
public static class Builder extends Descriptor.Builder<Builder> {
Builder(String identifier) { super(identifier); }
@Override protected Builder self() { return this; }
public DescriptorImpl build() { return new DescriptorImpl(this); }
}
}
}

@ -0,0 +1,175 @@
/**
* 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.algorithm.descriptor;
import java.math.BigInteger;
import junit.framework.TestCase;
import org.n52.test.mock.MockEnum;
import org.n52.wps.io.data.IData;
/**
*
* @author tkunicki
*/
public class InputDataDescriptorTest extends TestCase {
public InputDataDescriptorTest(String testName) {
super(testName);
}
public void testMinOccurs() {
InputDescriptor inputDescriptor = null;
// test default minOccurs is 1
inputDescriptor = (new InputDescriptorImpl.Builder()).build();
assertEquals(BigInteger.valueOf(1), inputDescriptor.getMinOccurs());
// test default minOccurs is 1, that we set it again doesn't matter
inputDescriptor = (new InputDescriptorImpl.Builder()).minOccurs(1).build();
assertEquals(BigInteger.valueOf(1), inputDescriptor.getMinOccurs());
// the other API
inputDescriptor = (new InputDescriptorImpl.Builder()).minOccurs(BigInteger.valueOf(1)).build();
assertEquals(BigInteger.valueOf(1), inputDescriptor.getMinOccurs());
// test that 0 is OK
inputDescriptor = (new InputDescriptorImpl.Builder()).minOccurs(0).build();
assertEquals(BigInteger.valueOf(0), inputDescriptor.getMinOccurs());
// the other API
inputDescriptor = (new InputDescriptorImpl.Builder()).minOccurs(BigInteger.valueOf(0)).build();
assertEquals(BigInteger.valueOf(0), inputDescriptor.getMinOccurs());
// test fail early on < 0
boolean thrown = false;
try {
(new InputDescriptorImpl.Builder()).minOccurs(-1);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
// The other API
thrown = false;
try {
(new InputDescriptorImpl.Builder()).minOccurs(BigInteger.valueOf(-1));
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
// test that minOccurs can't be > maxOccurs
thrown = false;
try {
(new InputDescriptorImpl.Builder()).minOccurs(2).build();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
thrown = true;
}
assertTrue(thrown);
// The other API
thrown = false;
try {
(new InputDescriptorImpl.Builder()).minOccurs(BigInteger.valueOf(2)).build();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
thrown = true;
}
assertTrue(thrown);
}
public void testMaxOccurs() {
InputDescriptor inputDescriptor = null;
// test default maxOccurs is 1
inputDescriptor = (new InputDescriptorImpl.Builder()).build();
assertEquals(BigInteger.valueOf(1), inputDescriptor.getMaxOccurs());
// test default maxOccurs is 1, that we set it again doesn't matter
inputDescriptor = (new InputDescriptorImpl.Builder()).maxOccurs(1).build();
assertEquals(BigInteger.valueOf(1), inputDescriptor.getMaxOccurs());
// the other API
inputDescriptor = (new InputDescriptorImpl.Builder()).maxOccurs(BigInteger.valueOf(1)).build();
assertEquals(BigInteger.valueOf(1), inputDescriptor.getMaxOccurs());
// test that we can set maxOccurs value > 1
inputDescriptor = (new InputDescriptorImpl.Builder()).maxOccurs(2).build();
assertEquals(BigInteger.valueOf(2), inputDescriptor.getMaxOccurs());
// the other API
inputDescriptor = (new InputDescriptorImpl.Builder()).maxOccurs(BigInteger.valueOf(2)).build();
assertEquals(BigInteger.valueOf(2), inputDescriptor.getMaxOccurs());
// test that we set maxOccurs to number of enum constants
inputDescriptor = (new InputDescriptorImpl.Builder()).maxOccurs(MockEnum.class).build();
assertEquals(BigInteger.valueOf(MockEnum.values().length), inputDescriptor.getMaxOccurs());
// test fail-early for maxOccurs < 1;
boolean thrown = false;
try {
(new InputDescriptorImpl.Builder()).maxOccurs(0);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
// the other API
thrown = false;
try {
(new InputDescriptorImpl.Builder()).maxOccurs(BigInteger.valueOf(0));
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
// test maxOccurs can be < minOccurs even if both are non-default
thrown = false;
try {
(new InputDescriptorImpl.Builder()).
minOccurs(3).
maxOccurs(2).
build();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
thrown = true;
}
assertTrue(thrown);
// the other API
thrown = false;
try {
(new InputDescriptorImpl.Builder()).
minOccurs(BigInteger.valueOf(3)).
maxOccurs(BigInteger.valueOf(2)).
build();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
thrown = true;
}
assertTrue(thrown);
}
public static class InputDescriptorImpl extends InputDescriptor<Class<IData>> {
private InputDescriptorImpl(Builder builder) { super(builder); }
public static class Builder extends InputDescriptor.Builder<Builder, Class<IData>> {
Builder() {
super("mock_identifier", IData.class);
}
@Override protected Builder self() { return this; }
@Override public InputDescriptorImpl build() { return new InputDescriptorImpl(this); }
}
}
}

@ -0,0 +1,242 @@
/**
* 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.algorithm.descriptor;
import java.util.List;
import junit.framework.TestCase;
import org.n52.wps.algorithm.util.ClassUtil;
import org.n52.wps.io.BasicXMLTypeFactory;
import org.n52.wps.io.data.binding.literal.LiteralAnyURIBinding;
import org.n52.wps.io.data.binding.literal.LiteralBooleanBinding;
import org.n52.wps.io.data.binding.literal.LiteralByteBinding;
import org.n52.wps.io.data.binding.literal.LiteralDateTimeBinding;
import org.n52.wps.io.data.binding.literal.LiteralDoubleBinding;
import org.n52.wps.io.data.binding.literal.LiteralFloatBinding;
import org.n52.wps.io.data.binding.literal.LiteralIntBinding;
import org.n52.wps.io.data.binding.literal.LiteralLongBinding;
import org.n52.wps.io.data.binding.literal.LiteralShortBinding;
import org.n52.wps.io.data.binding.literal.LiteralStringBinding;
/**
*
* @author tkunicki
*/
public class LiteralDataInputDescriptorTest extends TestCase {
public final static String MOCK_UNALLOWED = "MOCK_UNALLOWED";
public enum MOCK_ALLOWED_VALUES {
MOCK_ALLOWED1,
MOCK_ALLOWED2,
MOCK_ALLOWED3,
}
public LiteralDataInputDescriptorTest(String testName) {
super(testName);
}
public void testDefaultValue() {
LiteralDataInputDescriptor descriptor = null;
// test default for defaultValue
descriptor = LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).build();
assertNull(descriptor.getDefaultValue());
assertFalse(descriptor.hasDefaultValue());
// test "" for defaultValue (unset annotation case)
descriptor = LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).
defaultValue("").
build();
assertEquals("", descriptor.getDefaultValue());
assertFalse(descriptor.hasDefaultValue());
// test with a valid defaultValue (unset annotation case)
descriptor = LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).
defaultValue("mock_default").
build();
assertEquals("mock_default", descriptor.getDefaultValue());
assertTrue(descriptor.hasDefaultValue());
}
public void testAllowedValues() {
LiteralDataInputDescriptor descriptor = null;
// test default for allowedValues
descriptor = LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).build();
assertNotNull(descriptor.getAllowedValues());
assertEquals(0, descriptor.getAllowedValues().size());
assertFalse(descriptor.hasAllowedValues());
// test allowedValues(String[])
descriptor = LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).
allowedValues(ClassUtil.convertEnumToStringArray(MOCK_ALLOWED_VALUES.class)).build();
validateAllowValues(descriptor);
// test allowedValues(List<String>)
descriptor = LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).
allowedValues(ClassUtil.convertEnumToStringList(MOCK_ALLOWED_VALUES.class)).build();
validateAllowValues(descriptor);
// test allowedValues(Class<? extends Enum>)
descriptor = LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).
allowedValues(MOCK_ALLOWED_VALUES.class).build();
validateAllowValues(descriptor);
// test allowedValues()
descriptor = LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).
defaultValue(MOCK_ALLOWED_VALUES.MOCK_ALLOWED1.name()).
allowedValues(MOCK_ALLOWED_VALUES.class).build();
validateAllowValues(descriptor);
boolean thrown = false;
try {
LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).
defaultValue(MOCK_UNALLOWED).
allowedValues(MOCK_ALLOWED_VALUES.class).
build();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
thrown = true;
}
assertTrue(thrown);
}
public void testBuilder() {
LiteralDataInputDescriptor descriptor =
LiteralDataInputDescriptor.builder("mock_identifier", LiteralStringBinding.class).build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralStringBinding.class, descriptor.getBinding());
boolean thrown = false;
try {
LiteralDataInputDescriptor.builder(null, LiteralStringBinding.class);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
LiteralDataInputDescriptor.builder("", LiteralStringBinding.class);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
LiteralDataInputDescriptor.builder("mock_identifier", null);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
}
public void testAnyURIBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.anyURIBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralAnyURIBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.ANYURI_URI, descriptor.getDataType());
}
public void testBase64BinaryBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.anyURIBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralAnyURIBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.ANYURI_URI, descriptor.getDataType());
}
public void testBooleanBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.booleanBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralBooleanBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.BOOLEAN_URI, descriptor.getDataType());
}
public void testByteBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.byteBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralByteBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.BYTE_URI, descriptor.getDataType());
}
public void testDateTimeBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.dateTimeBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralDateTimeBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.DATETIME_URI, descriptor.getDataType());
}
public void testDoubleBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.doubleBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralDoubleBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.DOUBLE_URI, descriptor.getDataType());
}
public void testFloatBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.floatBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralFloatBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.FLOAT_URI, descriptor.getDataType());
}
public void testIntBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.intBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralIntBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.INT_URI, descriptor.getDataType());
}
public void testLongBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.longBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralLongBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.LONG_URI, descriptor.getDataType());
}
public void testShortBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.shortBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralShortBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.SHORT_URI, descriptor.getDataType());
}
public void testStringBuilder() {
LiteralDataInputDescriptor descriptor = LiteralDataInputDescriptor.stringBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralStringBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.STRING_URI, descriptor.getDataType());
}
private void validateAllowValues(LiteralDataInputDescriptor descriptor) {
assertTrue(descriptor.hasAllowedValues());
List<String> allowedValueList = descriptor.getAllowedValues();
assertNotNull(allowedValueList);
assertEquals(MOCK_ALLOWED_VALUES.values().length, allowedValueList.size());
for (int index = 0; index < allowedValueList.size(); ++index) {
assertNotNull(allowedValueList.get(index));
assertEquals(MOCK_ALLOWED_VALUES.values()[index].name(), allowedValueList.get(index));
}
}
}

@ -0,0 +1,154 @@
/**
* 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.algorithm.descriptor;
import junit.framework.TestCase;
import org.n52.wps.io.BasicXMLTypeFactory;
import org.n52.wps.io.data.binding.literal.LiteralAnyURIBinding;
import org.n52.wps.io.data.binding.literal.LiteralBooleanBinding;
import org.n52.wps.io.data.binding.literal.LiteralByteBinding;
import org.n52.wps.io.data.binding.literal.LiteralDateTimeBinding;
import org.n52.wps.io.data.binding.literal.LiteralDoubleBinding;
import org.n52.wps.io.data.binding.literal.LiteralFloatBinding;
import org.n52.wps.io.data.binding.literal.LiteralIntBinding;
import org.n52.wps.io.data.binding.literal.LiteralLongBinding;
import org.n52.wps.io.data.binding.literal.LiteralShortBinding;
import org.n52.wps.io.data.binding.literal.LiteralStringBinding;
/**
*
* @author tkunicki
*/
public class LiteralDataOutputDescriptorTest extends TestCase {
public LiteralDataOutputDescriptorTest(String testName) {
super(testName);
}
public void testStaticBuilder() {
LiteralDataOutputDescriptor descriptor =
LiteralDataOutputDescriptor.builder("mock_identifier", LiteralStringBinding.class).build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralStringBinding.class, descriptor.getBinding());
boolean thrown = false;
try {
LiteralDataOutputDescriptor.builder(null, LiteralStringBinding.class);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
LiteralDataOutputDescriptor.builder("", LiteralStringBinding.class);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
LiteralDataOutputDescriptor.builder("mock_identifier", null);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
thrown = true;
}
assertTrue(thrown);
}
public void testAnyURIBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.anyURIBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralAnyURIBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.ANYURI_URI, descriptor.getDataType());
}
public void testBase64BinaryBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.anyURIBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralAnyURIBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.ANYURI_URI, descriptor.getDataType());
}
public void testBooleanBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.booleanBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralBooleanBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.BOOLEAN_URI, descriptor.getDataType());
}
public void testByteBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.byteBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralByteBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.BYTE_URI, descriptor.getDataType());
}
public void testDateTimeBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.dateTimeBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralDateTimeBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.DATETIME_URI, descriptor.getDataType());
}
public void testDoubleBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.doubleBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralDoubleBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.DOUBLE_URI, descriptor.getDataType());
}
public void testFloatBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.floatBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralFloatBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.FLOAT_URI, descriptor.getDataType());
}
public void testIntBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.intBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralIntBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.INT_URI, descriptor.getDataType());
}
public void testLongBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.longBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralLongBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.LONG_URI, descriptor.getDataType());
}
public void testShortBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.shortBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralShortBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.SHORT_URI, descriptor.getDataType());
}
public void testStringBuilder() {
LiteralDataOutputDescriptor descriptor = LiteralDataOutputDescriptor.stringBuilder("mock_identifier").build();
assertEquals("mock_identifier", descriptor.getIdentifier());
assertEquals(LiteralStringBinding.class, descriptor.getBinding());
assertEquals(BasicXMLTypeFactory.STRING_URI, descriptor.getDataType());
}
}

@ -0,0 +1,91 @@
/**
* 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.util.HashMap;
import org.n52.test.mock.MockUtil;
import junit.framework.TestCase;
import net.opengis.wps.x100.ProcessDescriptionType;
import org.apache.xmlbeans.XmlOptions;
/**
*
* @author tkunicki
*/
public class AbstractSelfDescribingAlgorithmTest extends TestCase {
public AbstractSelfDescribingAlgorithmTest(String testName) {
super(testName);
}
@Override
protected void setUp() throws Exception {
super.setUp();
MockUtil.getMockConfig();
}
public void testComplexSelfDescribingAlgorithmUsingDescriptor() {
IAlgorithm algorithm = new ComplexSelfDescribingAlgorithmUsingDescriptor();
printAlgorithmProcessDescription(algorithm);
}
public void testComplexAnnotatedAlgorithm() {
IAlgorithm algorithm = new ComplexAnnotatedAlgorithm();
printAlgorithmProcessDescription(algorithm);
}
public void testStringReverseSelfDescribingAlgorithm() {
IAlgorithm algorithm = new StringReverseSelfDescribingAlgorithm();
printAlgorithmProcessDescription(algorithm);
}
public void testStringReverseAnnotatedAlgorithm() {
IAlgorithm algorithm = new StringReverseAnnotatedAlgorithm();
printAlgorithmProcessDescription(algorithm);
}
public void testStringJoinSelfDescribingAlgorithm() {
IAlgorithm algorithm = new StringJoinSelfDescribingAlgorithm();
printAlgorithmProcessDescription(algorithm);
}
public void testStringJoinAnnotatedAlgorithm() {
IAlgorithm algorithm = new StringJoinAnnotatedAlgorithm();
printAlgorithmProcessDescription(algorithm);
}
private void printAlgorithmProcessDescription(IAlgorithm algorithm) {
System.out.println();
System.out.println(" ### DescribeProcess for " + algorithm.getClass().getName() + " ###");
System.out.println(getXMLAsStringFromDescription(algorithm.getDescription()));
System.out.println();
}
private String getXMLAsStringFromDescription(ProcessDescriptionType decription) {
XmlOptions options = new XmlOptions();
options.setSavePrettyPrint();
options.setSaveOuter();
HashMap ns = new HashMap();
ns.put("http://www.opengis.net/wps/1.0.0", "wps");
ns.put("http://www.opengis.net/ows/1.1", "ows");
options.setSaveNamespacesFirst().
setSaveSuggestedPrefixes(ns).
setSaveAggressiveNamespaces();
return decription.xmlText(options);
}
}

@ -0,0 +1,236 @@
/**
* 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.net.URI;
import java.util.Date;
import java.util.List;
import org.n52.test.mock.MockBinding;
import org.n52.test.mock.MockEnum;
import org.n52.test.mock.MockComplexObject;
import org.n52.wps.algorithm.annotation.Algorithm;
import org.n52.wps.algorithm.annotation.ComplexDataInput;
import org.n52.wps.algorithm.annotation.ComplexDataOutput;
import org.n52.wps.algorithm.annotation.LiteralDataInput;
import org.n52.wps.algorithm.annotation.LiteralDataOutput;
import org.n52.wps.algorithm.annotation.Execute;
import org.n52.wps.io.data.binding.literal.LiteralByteBinding;
import org.n52.wps.io.data.binding.literal.LiteralShortBinding;
/**
*
* @author tkunicki
*/
@Algorithm(
// identifier="SampleIdentifier" fully qualified class name is used when this is missing
version="0.0.1", // default is "1.0.0"
title="Sample Algorithm Title", // identifier is used if title is not set
abstrakt="Sample Algortihm Abstract", // default is null (not output)
storeSupported=false, // default is true
statusSupported=true) // default is true
public class ComplexAnnotatedAlgorithm extends AbstractAnnotatedAlgorithm {
// EXAMPLES FOR OUTPUTS
@LiteralDataInput(
// binding=LiteralDoubleBinding.class, not needed, can infer type from field type
identifier=Constants.LITERAL_DOUBLE,
title="Sample Input Title",
abstrakt="Sample Input Abstract",
minOccurs=0,
maxOccurs=2)
public List<Double> inputLiteralDouble;
// public List<? extends Double> inputLiteralDouble; OK, but needs explicit binding
// public List<? super Double> inputLiteralDouble; OK, but needs explicit binding
// public List<?> inputLiteralDouble; OK, but needs explicit binding
// public List<? extends Number> inputLiteralDouble; OK, but needs explicit binding
// public List<? super Number> inputLiteralDouble; FAIL, [dD]ouble not superclass of Number
// public [dDouble] inputLiteralDouble; FAIL, maxOccurs is 2, need List!
//
// not an exhaustive list, point is we can autobind literal types. For types
// where autobinding can't be inferred one can explicitly set binding but parser
// will check types to validate assignability between binding payload and field or
// method argument. Methods or fields must be public!
// primitive field
@LiteralDataInput(identifier=Constants.LITERAL_FLOAT)
public float inputLiteralFloat;
private Long inputLiteralLong;
// Primitive wrapper as method argument
@LiteralDataInput(identifier=Constants.LITERAL_LONG)
public void setInputLiteralLong(Long inputLiteralLong) {
this.inputLiteralLong = inputLiteralLong;
}
private int inputLiteralInt;
// Primitive as method argument
@LiteralDataInput(identifier=Constants.LITERAL_INT)
public void setInputLiteralLong(int inputLiteralInt) {
this.inputLiteralInt = inputLiteralInt;
}
private Number inputLiteralShort;
// Number as method argument type
@LiteralDataInput(
binding=LiteralShortBinding.class, // REQUIRED since literal type can't be inferred from method parameter type
identifier=Constants.LITERAL_SHORT)
public void setInputLiteralLong(Number inputLiteralShort) {
this.inputLiteralShort = inputLiteralShort;
}
// Object as field type
@LiteralDataInput(
binding=LiteralByteBinding.class, // REQUIRED since literal type can't be inferred from field type
identifier=Constants.LITERAL_BYTE)
public Object inputLiteralByte;
private boolean inputeLiteralBoolean;
// don't care what method name is, only check it's annotation...
@LiteralDataInput(identifier=Constants.LITERAL_BOOLEAN)
public void setWithSomeRandomName(boolean inputeLiteralBoolean) {
this.inputeLiteralBoolean = inputeLiteralBoolean;
}
private String inputLiteralString;
@LiteralDataInput(
identifier=Constants.LITERAL_STRING,
defaultValue="Some Default Value", // annotation parser will validate this is allowedValues if set
allowedValues= { "Some Default Value", "Not the default Value" } )
public void setInputLiteralString(String inputLiteralString) {
this.inputLiteralString = inputLiteralString;
}
private MockEnum inputLiteralEnum;
@LiteralDataInput(
// binding=LiteralStringBinding.class Not needed! Enums are auto-bound to strings!
identifier=Constants.LITERAL_ENUM,
// defaultValue=MockEnum.VALUE1, Argh, Can't do this!
// defaultValue=MockEnum.VALUE1.name(), Argh, Can't do this either!, only literals or constants! So we settle for String constants
defaultValue="VALUE1", // must be string but annotation parser will validate this is valid constant for MockEnum
// allowedValues= { ... } Already set to Enum constants for MockEnum!
maxOccurs=LiteralDataInput.ENUM_COUNT // special case, set maxOccurs to number of MockEnum constants
)
public void setInputEnumType(MockEnum inputLiteralEnum) {
this.inputLiteralEnum = inputLiteralEnum;
}
// then the rest of the inputs...
private Date inputLiteralDateTime;
private byte[] inputLiteralBase64Binary;
private URI inputLiteralAnyURI;
private MockComplexObject inputComplex;
@LiteralDataInput(identifier=Constants.LITERAL_DATETIME)
public void setInputLiteralDateTime(Date inputLiteralDateTime) {
this.inputLiteralDateTime = inputLiteralDateTime;
}
@LiteralDataInput(identifier=Constants.LITERAL_BASE64BINARY)
public void setInputLiteralDateTime(byte[] inputLiteralBase64Binary) {
this.inputLiteralBase64Binary = inputLiteralBase64Binary;
}
@LiteralDataInput(identifier=Constants.LITERAL_ANYURI)
public void setInputLiteralDateTime(URI inputLiteralAnyURI) {
this.inputLiteralAnyURI = inputLiteralAnyURI;
}
@ComplexDataInput(
identifier=Constants.COMPLEX,
binding=MockBinding.class, // Binding required for complex types!
maximumMegaBytes=16)
public void setInputComplex(MockComplexObject inputComplex) {
this.inputComplex = inputComplex;
}
// EXAMPLES FOR OUTPUTS
@LiteralDataOutput(
identifier=Constants.LITERAL_DOUBLE,
title="Sample Output Title", // identifier is used if title is not set
abstrakt="Sample Output Abstract") // defaults to null (not output)
public Double outputLiteralDouble;
@LiteralDataOutput(identifier=Constants.LITERAL_FLOAT)
public float outputLiteralFloat;
private Long outputLiteralLong;
@LiteralDataOutput(identifier=Constants.LITERAL_LONG)
public Long getOutputLiteralLong() { return outputLiteralLong; }
private int outputLiteralInt;
@LiteralDataOutput(identifier=Constants.LITERAL_INT)
public int getOutputLiteralInt() { return outputLiteralInt; }
@LiteralDataOutput(
binding=LiteralShortBinding.class, // REQUIRED, can't infer binding for type Number
identifier=Constants.LITERAL_SHORT)
public Number outputLiteralShort;
// and the rest...
private byte outputLiteralByte;
private boolean outputLiteralBoolean;
private String outputLiteralString;
private Date outputLiteralDateTime;
private byte[] outputLiteralBase64Binary;
private URI outputLiteralAnyURI;
private MockComplexObject outputComplex;
@LiteralDataOutput(identifier=Constants.LITERAL_BYTE)
public byte getOutputLiteralByte() { return outputLiteralByte; }
@LiteralDataOutput(identifier=Constants.LITERAL_BOOLEAN)
public boolean getOutputLiteralBoolean() { return outputLiteralBoolean; }
@LiteralDataOutput(identifier=Constants.LITERAL_STRING)
public String getOutputLiteralString() { return outputLiteralString; }
@LiteralDataOutput(identifier=Constants.LITERAL_DATETIME)
public Date getOutputLiteralDateTime() { return outputLiteralDateTime; }
@LiteralDataOutput(identifier=Constants.LITERAL_BASE64BINARY)
public byte[] getOutputLiteralBase64Binary() { return outputLiteralBase64Binary; }
@LiteralDataOutput(identifier=Constants.LITERAL_ANYURI)
public URI getOutputLiteralAnyURI() { return outputLiteralAnyURI; }
@ComplexDataOutput(
binding=MockBinding.class, // Binding required for complex types!
identifier=Constants.COMPLEX)
public MockComplexObject getComplex() { return outputComplex; }
@Execute
public void doStuff() {
// values already unbound by setting fields or calling methods
// just access your variables directly...
// output fields or methods will be called and bound after this method call returns
}
}

@ -0,0 +1,144 @@
/**
* 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 org.n52.test.mock.MockBinding;
import java.util.List;
import java.util.Map;
import org.n52.test.mock.MockEnum;
import org.n52.wps.io.data.IData;
import org.n52.wps.algorithm.descriptor.AlgorithmDescriptor;
import org.n52.wps.algorithm.descriptor.ComplexDataInputDescriptor;
import org.n52.wps.algorithm.descriptor.ComplexDataOutputDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataInputDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataOutputDescriptor;
/**
*
* @author tkunicki
*/
public class ComplexSelfDescribingAlgorithmUsingDescriptor extends AbstractDescriptorAlgorithm {
// NOTE: AbstractSelfDescribingAlgorithm.initializeDescription(), is called
// in the constructor of AbstractAlgorithm. This creates a situation where
// initializeDescription() and getAlgorithmDescriptor() can be called before
// the implementing classes have their constructors called...
// The descriptors do sanity checking and will throw Exceptions with illegal
// arguments or state (i.e. null identifier or maxOccurs < minOccurs). If
// you decide to instantiate the DESCRIPTOR using a static constructor be
// sure to wrap it in a try/catch with logging otherwise class load will fail,
// this is a difficult state to debug
private static AlgorithmDescriptor DESCRIPTOR;
protected synchronized static AlgorithmDescriptor getAlgorithmDescriptorStatic() {
if (DESCRIPTOR == null) {
DESCRIPTOR =
// Adding a lot of fields in order to provide example of AlgorithmDescriptor
// chaining with the different literal and complex types.
// most process descriptions would be much simpler...
// Show use of chaining enabled by use of Builder pattern...
AlgorithmDescriptor.builder(ComplexSelfDescribingAlgorithmUsingDescriptor.class).
version("0.0.1"). // default is "1.0.0"
title("Sample Algorithm Title"). // identifier is used if title is not set
abstrakt("Sample Algortihm Abstract"). // default is null (not output)
statusSupported(false). // default is true
storeSupported(false). // default is true
addInputDescriptor(
LiteralDataInputDescriptor.doubleBuilder(Constants.LITERAL_DOUBLE).
title("Sample Input Title"). // identifier is used if title is not set
abstrakt("Sample Input Abstract").// defaults to null (not output)
minOccurs(0). // defaults to 1
maxOccurs(2)). // defaults to 1
addInputDescriptor(
LiteralDataInputDescriptor.floatBuilder(Constants.LITERAL_FLOAT)).
addInputDescriptor(
LiteralDataInputDescriptor.longBuilder(Constants.LITERAL_LONG)).
addInputDescriptor(
LiteralDataInputDescriptor.intBuilder(Constants.LITERAL_INT)).
addInputDescriptor(
LiteralDataInputDescriptor.shortBuilder(Constants.LITERAL_SHORT)).
addInputDescriptor(
LiteralDataInputDescriptor.byteBuilder(Constants.LITERAL_BYTE)).
addInputDescriptor(
LiteralDataInputDescriptor.booleanBuilder(Constants.LITERAL_BOOLEAN)).
addInputDescriptor(
LiteralDataInputDescriptor.stringBuilder(Constants.LITERAL_STRING).
defaultValue("Some Default Value"). // can set a default value.
allowedValues(new String[] {"Some Default Value", "Not the default Value"})). // can set allowed values.
addInputDescriptor(
LiteralDataInputDescriptor.stringBuilder(Constants.LITERAL_ENUM).
defaultValue(MockEnum.VALUE1.name()).// you can pass in an enum to set allowed values
allowedValues(MockEnum.class). // you can pass in an enum to set allowed values
maxOccurs(MockEnum.class)). // you can pass in an enum to set maxOccurs
addInputDescriptor(
LiteralDataInputDescriptor.dateTimeBuilder(Constants.LITERAL_DATETIME)).
addInputDescriptor(
LiteralDataInputDescriptor.base64BinaryBuilder(Constants.LITERAL_BASE64BINARY)).
addInputDescriptor(
LiteralDataInputDescriptor.anyURIBuilder(Constants.LITERAL_ANYURI)).
addInputDescriptor(
ComplexDataInputDescriptor.builder(Constants.COMPLEX, MockBinding.class).
maximumMegaBytes(16)). // can set maximumMegaBytes for ComplexInput types
addOutputDescriptor(
LiteralDataOutputDescriptor.doubleBuilder(Constants.LITERAL_DOUBLE).
title("Sample Output Title"). // identifier is used if title is not set
abstrakt("Sample Output Abstract")). // defaults to null (not output)
addOutputDescriptor(
LiteralDataOutputDescriptor.floatBuilder(Constants.LITERAL_FLOAT)).
addOutputDescriptor(
LiteralDataOutputDescriptor.longBuilder(Constants.LITERAL_LONG)).
addOutputDescriptor(
LiteralDataOutputDescriptor.intBuilder(Constants.LITERAL_INT)).
addOutputDescriptor(
LiteralDataOutputDescriptor.shortBuilder(Constants.LITERAL_SHORT)).
addOutputDescriptor(
LiteralDataOutputDescriptor.byteBuilder(Constants.LITERAL_BYTE)).
addOutputDescriptor(
LiteralDataOutputDescriptor.booleanBuilder(Constants.LITERAL_BOOLEAN)).
addOutputDescriptor(
LiteralDataOutputDescriptor.stringBuilder(Constants.LITERAL_STRING)).
addOutputDescriptor(
LiteralDataOutputDescriptor.dateTimeBuilder(Constants.LITERAL_DATETIME)).
addOutputDescriptor(
LiteralDataOutputDescriptor.base64BinaryBuilder(Constants.LITERAL_BASE64BINARY)).
addOutputDescriptor(
LiteralDataOutputDescriptor.anyURIBuilder(Constants.LITERAL_ANYURI)).
addOutputDescriptor(
ComplexDataOutputDescriptor.builder(Constants.COMPLEX, MockBinding.class)).
build();
}
return DESCRIPTOR;
}
// Ideally this would be an abstract method in AbstractSelfDescribingAlgorithm,
// this would break backwards compatibility with the Old API as it would
// force migration to the new AlgorithmDescriptor based API.
@Override
public AlgorithmDescriptor createAlgorithmDescriptor() {
// read note in static constructor...
return getAlgorithmDescriptorStatic();
}
@Override
public Map<String, IData> run(Map<String, List<IData>> inputData) {
// unbind and do stuff...
return null;
}
}

@ -0,0 +1,41 @@
/**
* 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;
/**
*
* @author tkunicki
*/
public class Constants {
public final static String LITERAL_DOUBLE = "LITERAL_DOUBLE";
public final static String LITERAL_FLOAT = "LITERAL_FLOAT";
public final static String LITERAL_LONG = "LITERAL_LONG";
public final static String LITERAL_INT = "LITERAL_INT";
public final static String LITERAL_SHORT = "LITERAL_SHORT";
public final static String LITERAL_BYTE = "LITERAL_BYTE";
public final static String LITERAL_BOOLEAN = "LITERAL_BOOLEAN";
public final static String LITERAL_STRING = "LITERAL_STRING";
public final static String LITERAL_DATETIME = "LITERAL_DATETIME";
public final static String LITERAL_BASE64BINARY = "LITERAL_BASE64BINARY";
public final static String LITERAL_ANYURI = "LITERAL_ANYURI";
public final static String LITERAL_ENUM = "LITERAL_ENUM";
public final static String COMPLEX = "COMPLEX";
}

@ -0,0 +1,111 @@
/**
* 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 net.opengis.wps.x100.ProcessDescriptionType;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.n52.wps.algorithm.annotation.Algorithm;
import org.n52.wps.algorithm.annotation.Execute;
import org.n52.wps.algorithm.annotation.LiteralDataInput;
import org.n52.wps.algorithm.annotation.LiteralDataOutput;
import static org.hamcrest.CoreMatchers.*;
public class ServiceLoaderAlgorithmTest {
private ServiceLoaderAlgorithmRepository repo;
@Before
public void init() {
this.repo = new ServiceLoaderAlgorithmRepository();
Assert.assertNotNull(this.repo);
}
@Test
public void shouldFindAlgorithms() {
String identified = "dummy-test-identifier";
Assert.assertThat(repo.containsAlgorithm(identified), is(true));
Assert.assertThat(repo.getAlgorithm(identified),
is(notNullValue()));
Assert.assertThat(repo.getAlgorithm(DummyAnnotatedAlgorithm.class
.getCanonicalName()), is(notNullValue()));
}
@Test
public void shouldNotFindAlgorithm() {
String identified = "not-in-there";
Assert.assertThat(repo.containsAlgorithm(identified), is(not(true)));
Assert.assertThat(repo.getAlgorithm(identified), is(nullValue()));
}
@Test
public void shouldFindTwoRegisteredAlgorithms() {
Assert.assertThat(this.repo.getAlgorithmNames().size(), is(2));
}
@Test
public void shouldResolveProcessDescription() {
ProcessDescriptionType description = repo.getProcessDescription(DummyAnnotatedAlgorithm.class.getCanonicalName());
Assert.assertThat(description, is(notNullValue()));
Assert.assertThat(description, is(instanceOf(ProcessDescriptionType.class)));
}
@Algorithm(version = "0.1")
public static class DummyAnnotatedAlgorithm extends
AbstractAnnotatedAlgorithm {
private String output;
@LiteralDataInput(identifier = "input")
public String input;
@LiteralDataOutput(identifier = "output")
public String getOutput() {
return this.output;
}
@Execute
public void myRunMethodFollowingNoSyntaxNoArgumentsAllowed() {
this.output = "works like a charm.";
}
}
@Algorithm(version = "0.1", identifier = "dummy-test-identifier")
public static class DummyIdentifiedAnnotatedAlgorithm extends
DummyAnnotatedAlgorithm {
private String output;
@LiteralDataInput(identifier = "input")
public String input;
@LiteralDataOutput(identifier = "output")
public String getOutput() {
return this.output;
}
@Execute
public void myRunMethodFollowingNoSyntaxNoArgumentsAllowed() {
this.output = "works like a charm.";
}
}
}

@ -0,0 +1,93 @@
/**
* 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 com.google.common.base.Joiner;
import java.util.List;
import org.n52.wps.algorithm.annotation.Algorithm;
import org.n52.wps.algorithm.annotation.LiteralDataInput;
import org.n52.wps.algorithm.annotation.LiteralDataOutput;
import org.n52.wps.algorithm.annotation.Execute;
/**
*
* @author tkunicki
*/
@Algorithm(
version="0.0.1",
title="String Join Algorithm (Annotated)",
abstrakt="This is an example algorithm implementation described using annotations that joins strings using the specified delimiter.",
statusSupported=false,
storeSupported=false)
public class StringJoinAnnotatedAlgorithm extends AbstractAnnotatedAlgorithm {
public enum Delimiter {
SPACE(' '),
TAB('\t'),
PIPE('|'),
COMMA(','),
SEMI_COLON(';'),
COLON(':');
public final char value;
Delimiter(char value) {
this.value = value;
}
}
private List<String> inputStrings;
private Delimiter inputDelimiter;
private String outputString;
@LiteralDataInput(
identifier="INPUT_STRINGS",
title="Input Strings",
abstrakt="The strings you want joined.",
minOccurs=2,
maxOccurs=32)
public void setInputString(List<String> inputStrings) {
this.inputStrings = inputStrings;
}
@LiteralDataInput(
identifier="INPUT_DELIMITER",
title="Delimiter",
abstrakt="The value to use when joining strings")
public void setInputDelimiter(Delimiter inputDelimiter) {
this.inputDelimiter = inputDelimiter;
}
@LiteralDataOutput(
identifier="OUTPUT_STRING",
title="Output String",
abstrakt="The strings joined with the delimiter")
public String getOutputString() {
return outputString;
}
@LiteralDataInput(identifier="yourMom")
public String yourMom;
@Execute
public void reverse() {
// don't need to do any parameter bounds checking that is specified
// as part of the DescribeProcess, it's already done before this
// method is called...
outputString = Joiner.on(inputDelimiter.value).join(inputStrings);
}
}

@ -0,0 +1,143 @@
/**
* 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 com.google.common.base.Joiner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.n52.wps.io.data.IData;
import org.n52.wps.algorithm.descriptor.AlgorithmDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataInputDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataOutputDescriptor;
import org.n52.wps.io.data.binding.literal.LiteralStringBinding;
/**
*
* @author tkunicki
*/
public class StringJoinSelfDescribingAlgorithm extends AbstractDescriptorAlgorithm {
public final static String INPUT_STRINGS = "INPUT_STRINGS";
public final static String INPUT_DELIMITER = "INPUT_DELIMITER";
public final static String OUTPUT_STRING = "OUTPUT_STRING";
public enum Delimiter {
SPACE(' '),
TAB('\t'),
PIPE('|'),
COMMA(','),
SEMI_COLON(';'),
COLON(':');
public final char value;
Delimiter(char value) {
this.value = value;
}
}
private static AlgorithmDescriptor DESCRIPTOR;
protected synchronized static AlgorithmDescriptor getAlgorithmDescriptorStatic() {
if (DESCRIPTOR == null) {
DESCRIPTOR =
// passing in a class to the AlgorithmDescriptor.builder will set
// set the identity to the the fully qualified class name. If this
// is not desired use the String constructor.
AlgorithmDescriptor.builder(StringJoinSelfDescribingAlgorithm.class).
version("0.0.1"). // default is "1.0.0"
title("String Join Algorithm (Self Describing)"). // identifier is used if title is not set
abstrakt("This is an example algorithm implementation described using a chained builder that joins strings using the specified delimiter."). // default is null (not output)
statusSupported(false). // default is true
storeSupported(false). // default is true
addInputDescriptor(
LiteralDataInputDescriptor.stringBuilder(INPUT_STRINGS).
title("Input Strings"). // identifier is used if title is not set
abstrakt("The strings you want joined.").// defaults to null (not output)
minOccurs(2). // defaults to 1
maxOccurs(32)).
addInputDescriptor(
LiteralDataInputDescriptor.stringBuilder(INPUT_DELIMITER).
title("Delimiter"). // identifier is used if title is not set
abstrakt("The value to use when joining strings"). // defaults to null (not output)
allowedValues(Delimiter.class)).
addOutputDescriptor(
LiteralDataOutputDescriptor.stringBuilder(OUTPUT_STRING).
title("Output String"). // identifier is used if title is not set
abstrakt("The strings joined with the delimiter")). // defaults to null (not output).
build();
}
return DESCRIPTOR;
}
@Override
public AlgorithmDescriptor createAlgorithmDescriptor() {
return getAlgorithmDescriptorStatic();
}
@Override
public Map<String, IData> run(Map<String, List<IData>> inputMap) {
// unwrap input strings and error check
List<IData> inputBoundStringList = inputMap.get(INPUT_STRINGS);
if (inputBoundStringList == null || inputBoundStringList.size() < 2) {
addError("Invalid parameter count for" + INPUT_STRINGS);
return null;
}
List<String> inputStringList = new ArrayList<String>();
for (IData boundString : inputBoundStringList) {
if (boundString == null || !(boundString instanceof LiteralStringBinding)) {
addError("unexpected binding ecountered unbinding " + INPUT_STRINGS + " parameter list");
return null;
}
String inputString = ((LiteralStringBinding)boundString).getPayload();
if (inputString == null || inputString.length() == 0) {
addError("invalid value encounterd in " + INPUT_STRINGS + " parameter list");
}
inputStringList.add(inputString);
}
// unwrap input delimiter and error check
List<IData> inputBoundDelimiterList = inputMap.get(INPUT_DELIMITER);
if (inputBoundDelimiterList == null || inputBoundDelimiterList.size() != 1) {
addError("Invalid parameter count for" + INPUT_DELIMITER);
return null;
}
IData inputBoundDelimiterData = inputBoundDelimiterList.get(0);
if (inputBoundDelimiterData == null || !(inputBoundDelimiterData instanceof LiteralStringBinding)) {
addError("Something wierd happened with the request parser!");
return null;
}
String inputDelimiterString = ((LiteralStringBinding)inputBoundDelimiterData).getPayload();
Delimiter inputDelimiter = null;
try {
inputDelimiter = Delimiter.valueOf(inputDelimiterString);
} catch (IllegalArgumentException e) {
addError("invalid value encounterd for " + INPUT_DELIMITER + " parameter");
return null;
}
// do work
String outputString = Joiner.on(inputDelimiter.value).join(inputStringList);
// wrap output
Map<String, IData> outputMap = new HashMap<String, IData>();
outputMap.put(OUTPUT_STRING, new LiteralStringBinding(outputString));
return outputMap;
}
}

@ -0,0 +1,61 @@
/**
* 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 org.n52.wps.algorithm.annotation.Algorithm;
import org.n52.wps.algorithm.annotation.LiteralDataInput;
import org.n52.wps.algorithm.annotation.LiteralDataOutput;
import org.n52.wps.algorithm.annotation.Execute;
/**
*
* @author tkunicki
*/
@Algorithm(
version="0.0.1",
title="String Reverse Algorithm (Annotated)",
abstrakt="This is an example algorithm implementation described using annotations that reverses a string.",
statusSupported=false,
storeSupported=false)
public class StringReverseAnnotatedAlgorithm extends AbstractAnnotatedAlgorithm {
private String inputString;
private String outputString;
@LiteralDataInput(
identifier="INPUT_STRING",
title="Input String",
abstrakt="The input string you want reversed.")
public void setInputString(String inputString) {
this.inputString = inputString;
}
@LiteralDataOutput(
identifier="OUTPUT_STRING",
title="Output String",
abstrakt="The reverse of the input string.")
public String getOutputString() {
return outputString;
}
@Execute
public void reverse() {
outputString = (new StringBuffer(inputString)).reverse().toString();
}
}

@ -0,0 +1,95 @@
/**
* 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.util.HashMap;
import java.util.List;
import java.util.Map;
import org.n52.wps.io.data.IData;
import org.n52.wps.algorithm.descriptor.AlgorithmDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataInputDescriptor;
import org.n52.wps.algorithm.descriptor.LiteralDataOutputDescriptor;
import org.n52.wps.io.data.binding.literal.LiteralStringBinding;
/**
*
* @author tkunicki
*/
public class StringReverseSelfDescribingAlgorithm extends AbstractDescriptorAlgorithm {
public final static String INPUT_STRING = "INPUT_STRING";
public final static String OUTPUT_STRING = "OUTPUT_STRING";
private static AlgorithmDescriptor DESCRIPTOR;
protected synchronized static AlgorithmDescriptor getAlgorithmDescriptorStatic() {
if (DESCRIPTOR == null) {
DESCRIPTOR =
// passing in a class to the AlgorithmDescriptor.builder will set
// set the identity to the the fully qualified class name. If this
// is not desired use the String constructor.
AlgorithmDescriptor.builder(StringReverseSelfDescribingAlgorithm.class).
version("0.0.1"). // default is "1.0.0"
title("String Reverse Algorithm (Self Describing)"). // identifier is used if title is not set
abstrakt("This is an example algorithm implementation described using a chained builder that reverses a string."). // default is null (not output)
statusSupported(false). // default is true
storeSupported(false). // default is true
addInputDescriptor(
LiteralDataInputDescriptor.stringBuilder(INPUT_STRING).
title("Input String"). // identifier is used if title is not set
abstrakt("The input string you want reversed.").// defaults to null (not output)
minOccurs(1). // defaults to 1
maxOccurs(1)). // defaults to 1
addOutputDescriptor(
LiteralDataOutputDescriptor.stringBuilder(OUTPUT_STRING).
title("Output String"). // identifier is used if title is not set
abstrakt("The reverse of the input string.")). // defaults to null (not output).
build();
}
return DESCRIPTOR;
}
@Override
public AlgorithmDescriptor createAlgorithmDescriptor() {
return getAlgorithmDescriptorStatic();
}
@Override
public Map<String, IData> run(Map<String, List<IData>> inputMap) {
// unwrap input(s)
List<IData> inputDataList = inputMap.get(INPUT_STRING);
if (inputDataList == null || inputDataList.isEmpty()) {
addError("Missing input string!");
return null;
}
IData inputData = inputDataList.get(0);
if (inputData == null || !(inputData instanceof LiteralStringBinding)) {
addError("Something wierd happened with the request parser!");
return null;
}
String inputString = ((LiteralStringBinding)inputData).getPayload();
// do work
String outputString = (new StringBuffer(inputString)).reverse().toString();
// wrap output
Map<String, IData> outputMap = new HashMap<String, IData>();
outputMap.put(OUTPUT_STRING, new LiteralStringBinding(outputString));
return outputMap;
}
}

@ -0,0 +1,2 @@
org.n52.wps.server.ServiceLoaderAlgorithmTest$DummyAnnotatedAlgorithm
org.n52.wps.server.ServiceLoaderAlgorithmTest$DummyIdentifiedAnnotatedAlgorithm

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<WPSConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://n52.org/wps schema_v1.xsd" xmlns="http://n52.org/wps">
<Datahandlers>
<ParserList>
<Parser name="MockParser" className="org.n52.test.mock.MockParser" active="true">
<Property name="supportedSchema" active="true">http://a.mock.schema/apple</Property>
<Property name="supportedSchema" active="true">http://a.mock.schema/orange</Property>
<Property name="supportedFormat" active="true">test/mock</Property>
<Property name="supportedEncoding" active="true">UTF-8</Property>
</Parser>
</ParserList>
<GeneratorList>
<Generator name="MockGenerator" className="org.n52.test.mock.MockGenerator" active="true">
<Property name="supportedSchema" active="true">http://a.mock.schema/apple</Property>
<Property name="supportedSchema" active="true">http://a.mock.schema/orange</Property>
<Property name="supportedFormat" active="true">test/mock</Property>
<Property name="supportedEncoding" active="true">UTF-8</Property>
</Generator>
</GeneratorList>
</Datahandlers>
<AlgorithmRepositoryList>
<Repository name="LocalAlgorithmRepository" className="org.n52.wps.server.LocalAlgorithmRepository" active="true">
<Property name="Algorithm" active="true">org.n52.wps.server.SelfDescribingAlgorithmUsingDeprecatedAPI</Property>
<Property name="Algorithm" active="true">org.n52.wps.server.SelfDescribingAlgorithmUsingDescriptor</Property>
</Repository>
<Repository name="ServiceLoaderAlgorithmRepository" className="org.n52.wps.server.ServiceLoaderAlgorithmRepository" active="true">
</Repository>
</AlgorithmRepositoryList>
<!-- @hostname@, @hostport@ and @webappPath@ are filtered and replaced by values derived from
HttpServelRequest instance of getRequestURL() in response using a Filter -->
<Server hostname="@hostname@" hostport="@hostport@" webappPath="@webappPath@" includeDataInputsInResponse="true" computationTimeoutMilliSeconds="5" cacheCapabilites="false">
<Database/>
</Server>
</WPSConfiguration>
Loading…
Cancel
Save