1.x branch (first created for gCube 2.12)
git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/branches/information-system/discovery-client/1.0@67186 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
commit
08dd818774
|
@ -0,0 +1,36 @@
|
||||||
|
<?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 excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||||
|
<attributes>
|
||||||
|
<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.6">
|
||||||
|
<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>discovery-client</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 @@
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
gCube System - License
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
The gCube/gCore software is licensed as Free Open Source software conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
|
||||||
|
The software and documentation is provided by its authors/distributors "as is" and no expressed or
|
||||||
|
implied warranty is given for its use, quality or fitness for a particular case.
|
|
@ -0,0 +1,2 @@
|
||||||
|
* Fabio Simeoni (fabio.simeoni@fao.org), FAO of the UN, Italy
|
||||||
|
* Lucio Lelii (lucio.lelii@isti.cnr.it), CNR, Italy
|
|
@ -0,0 +1,39 @@
|
||||||
|
The gCube System - ${name}
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
This work has been partially supported by the following European projects: DILIGENT (FP6-2003-IST-2), D4Science (FP7-INFRA-2007-1.2.2),
|
||||||
|
D4Science-II (FP7-INFRA-2008-1.2.2), iMarine (FP7-INFRASTRUCTURES-2011-2), and EUBrazilOpenBio (FP7-ICT-2011-EU-Brazil).
|
||||||
|
|
||||||
|
Authors
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fabio Simeoni (fabio.simeoni@fao.org), FAO of the UN, Italy
|
||||||
|
* Lucio Lelii (lucio.lelii@isti.cnr.it), CNR, Italy
|
||||||
|
|
||||||
|
Version and Release Date
|
||||||
|
------------------------
|
||||||
|
${version}
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
${description}
|
||||||
|
|
||||||
|
Download information
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Source code is available from SVN:
|
||||||
|
${scm.url}
|
||||||
|
|
||||||
|
Binaries can be downloaded from:
|
||||||
|
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
Documentation is available on-line from the Projects Documentation Wiki:
|
||||||
|
https://gcube.wiki.gcube-system.org/gcube/index.php
|
||||||
|
|
||||||
|
|
||||||
|
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="${build.finalName}" date="11/01/2013">
|
||||||
|
<Change>First Release</Change>
|
||||||
|
</Changeset>
|
||||||
|
</ReleaseNotes>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<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>INSTALL</include>
|
||||||
|
<include>MAINTAINERS</include>
|
||||||
|
<include>changelog.xml</include>
|
||||||
|
<include>profile.xml</include>
|
||||||
|
</includes>
|
||||||
|
<fileMode>755</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
<files>
|
||||||
|
<file>
|
||||||
|
<source>target/${build.finalName}.jar</source>
|
||||||
|
<outputDirectory>/${artifactId}</outputDirectory>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<source>${distroDirectory}/svnpath.txt</source>
|
||||||
|
<outputDirectory>/${artifactId}</outputDirectory>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</file>
|
||||||
|
</files>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<ID />
|
||||||
|
<Type>Service</Type>
|
||||||
|
<Profile>
|
||||||
|
<Description>${description}</Description>
|
||||||
|
<Class>InformationSystem</Class>
|
||||||
|
<Name>${artifactId}</Name>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Packages>
|
||||||
|
<Software>
|
||||||
|
<Name>${artifactId}</Name>
|
||||||
|
<Version>${version}</Version>
|
||||||
|
<MavenCoordinates>
|
||||||
|
<groupId>${groupId}</groupId>
|
||||||
|
<artifactId>${artifactId}</artifactId>
|
||||||
|
<version>${version}</version>
|
||||||
|
</MavenCoordinates>
|
||||||
|
<Files>
|
||||||
|
<File>${build.finalName}.jar</File>
|
||||||
|
</Files>
|
||||||
|
</Software>
|
||||||
|
</Packages>
|
||||||
|
</Profile>
|
||||||
|
</Resource>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
${scm.url}
|
|
@ -0,0 +1,103 @@
|
||||||
|
<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/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.gcube.tools</groupId>
|
||||||
|
<artifactId>maven-parent</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>org.gcube.resources.discovery</groupId>
|
||||||
|
<artifactId>discovery-client</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<name>Discovery Client</name>
|
||||||
|
<description>Base API for resource discovery clients</description>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>scm:svn:http://svn.d4science.research-infrastructures.eu/gcube/trunk/information-system/${project.artifactId}</connection>
|
||||||
|
<developerConnection>scm:svn:https://svn.d4science.research-infrastructures.eu/gcube/trunk/information-system/${project.artifactId}</developerConnection>
|
||||||
|
<url>http://svn.d4science.research-infrastructures.eu/gcube/trunk/information-system/${project.artifactId}</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<distroDirectory>distro</distroDirectory>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.data.access</groupId>
|
||||||
|
<artifactId>streams</artifactId>
|
||||||
|
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.6.4</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>1.6.4</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-profile</id>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-resources</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>target</outputDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>${distroDirectory}</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<includes>
|
||||||
|
<include>profile.xml</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>${distroDirectory}/descriptor.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>servicearchive</id>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.gcube.resources.discovery.client.api;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gcube.data.streams.Stream;
|
||||||
|
import org.gcube.resources.discovery.client.queries.api.Query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local interface for resource discovery.
|
||||||
|
* <p>
|
||||||
|
* Submits {@link Query}s for remote execution and returns a list of typed results.
|
||||||
|
*
|
||||||
|
* @author Fabio Simeoni
|
||||||
|
*
|
||||||
|
* @param <R> the type of query results
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface DiscoveryClient<R> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submits a {@link Query} for remote execution and returns a list of typed results.
|
||||||
|
*
|
||||||
|
* @param query the query
|
||||||
|
* @return the results
|
||||||
|
* @throws DiscoveryException if the query cannot be submitted
|
||||||
|
* @throws InvalidResultException if the results cannot be parsed. Implementations may adopt different degrees of
|
||||||
|
* tolerance to parsing errors before raising this exception.
|
||||||
|
*/
|
||||||
|
List<R> submit(Query query) throws DiscoveryException, InvalidResultException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submits a {@link Query} for remote execution and returns a {@link Stream} of typed results.
|
||||||
|
* <p>
|
||||||
|
* Parsing errors may and should be delivered as {@link InvalidResultException}s during stream iteration.
|
||||||
|
*
|
||||||
|
* @param query the query
|
||||||
|
* @return the results
|
||||||
|
* @throws DiscoveryException if the query cannot be submitted
|
||||||
|
*/
|
||||||
|
Stream<R> submitForStream(Query query) throws DiscoveryException;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.gcube.resources.discovery.client.api;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raised when services endpoints cannot be discovered.
|
||||||
|
*
|
||||||
|
* @author Fabio Simeoni
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DiscoveryException extends RuntimeException {
|
||||||
|
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with a message.
|
||||||
|
* @param msg the message
|
||||||
|
*/
|
||||||
|
public DiscoveryException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance from a cause.
|
||||||
|
* @param cause the cause
|
||||||
|
*/
|
||||||
|
public DiscoveryException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance from a message and a cause.
|
||||||
|
* @param msg the message
|
||||||
|
* @param cause the cause
|
||||||
|
*/
|
||||||
|
public DiscoveryException(String msg,Throwable cause) {
|
||||||
|
super(msg,cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package org.gcube.resources.discovery.client.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raised by {@link DiscoveryClient}s for result parsing errors.
|
||||||
|
*
|
||||||
|
* @author Fabio Simeoni
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class InvalidResultException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with a given message.
|
||||||
|
* @param msg the message
|
||||||
|
*/
|
||||||
|
public InvalidResultException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with a given cause.
|
||||||
|
* @param cause the cause
|
||||||
|
*/
|
||||||
|
public InvalidResultException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with a given message and a given cause.
|
||||||
|
* @param msg the message
|
||||||
|
* @param cause the cause
|
||||||
|
*/
|
||||||
|
public InvalidResultException(String msg, Throwable cause) {
|
||||||
|
super(msg,cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.gcube.resources.discovery.client.api;
|
||||||
|
|
||||||
|
import org.gcube.resources.discovery.client.queries.api.Query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms untyped results into typed results.
|
||||||
|
*
|
||||||
|
* @author Fabio Simeoni
|
||||||
|
*
|
||||||
|
* @param <R> the result type
|
||||||
|
*
|
||||||
|
* @see DiscoveryClient
|
||||||
|
* @see Query
|
||||||
|
*/
|
||||||
|
public interface ResultParser<R> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms an untyped result.
|
||||||
|
*
|
||||||
|
* @param result the untyped results
|
||||||
|
* @return the typed result
|
||||||
|
* @throws Exception if the result cannot be typed
|
||||||
|
*/
|
||||||
|
R parse(String result) throws Exception;
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
package org.gcube.resources.discovery.client.impl;
|
||||||
|
|
||||||
|
import static org.gcube.data.streams.dsl.Streams.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gcube.data.streams.Stream;
|
||||||
|
import org.gcube.data.streams.exceptions.StreamSkipSignal;
|
||||||
|
import org.gcube.data.streams.exceptions.StreamStopSignal;
|
||||||
|
import org.gcube.data.streams.generators.Generator;
|
||||||
|
import org.gcube.resources.discovery.client.api.DiscoveryClient;
|
||||||
|
import org.gcube.resources.discovery.client.api.DiscoveryException;
|
||||||
|
import org.gcube.resources.discovery.client.api.InvalidResultException;
|
||||||
|
import org.gcube.resources.discovery.client.api.ResultParser;
|
||||||
|
import org.gcube.resources.discovery.client.queries.api.Query;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link DiscoveryClient} that delegates the execution of queries to another {@link DiscoveryClient} that
|
||||||
|
* does not perform result parsing and the parsing itself to a dedicated {@link ResultParser}.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Fabio Simeoni
|
||||||
|
*
|
||||||
|
* @param <R> the type of query results
|
||||||
|
*/
|
||||||
|
public class DelegateClient<R> implements DiscoveryClient<R> {
|
||||||
|
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DelegateClient.class);
|
||||||
|
|
||||||
|
private final ResultParser<R> parser;
|
||||||
|
private final DiscoveryClient<String> inner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with a given {@link ResultParser} and a {@link DiscoveryClient} that produces untyped results
|
||||||
|
* @param parser the parser
|
||||||
|
* @param inner the client
|
||||||
|
*/
|
||||||
|
public DelegateClient(ResultParser<R> parser,DiscoveryClient<String> inner) {
|
||||||
|
this.parser=parser;
|
||||||
|
this.inner=inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* Result parsing errors are only logged as long as some results are successfully parsed. Otherwise, the
|
||||||
|
* client flags the parsing errors as likely due to the parser itself.
|
||||||
|
*/
|
||||||
|
public List<R> submit(Query query) throws DiscoveryException, InvalidResultException {
|
||||||
|
|
||||||
|
List<R> parsed = new ArrayList<R>();
|
||||||
|
|
||||||
|
List<String> unparsed = inner.submit(query);
|
||||||
|
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
for (String result : unparsed)
|
||||||
|
try {
|
||||||
|
parsed.add(parser.parse(result));
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
log.warn("discarded invalid result "+result,e);
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors>0 && parsed.size()==0)
|
||||||
|
throw new InvalidResultException("no success but "+errors+" errors parsing results");
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* Result parsing errors are only logged as long as they do results are successfully parsed. Otherwise, the
|
||||||
|
* client flags the parsing errors as likely due to the parser itself.
|
||||||
|
*/
|
||||||
|
public Stream<R> submitForStream(Query query) throws DiscoveryException {
|
||||||
|
|
||||||
|
Stream<String> unparsed = inner.submitForStream(query);
|
||||||
|
|
||||||
|
return pipe(unparsed).through(new ParsingGenerator());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//helper
|
||||||
|
private class ParsingGenerator implements Generator<String,R> {
|
||||||
|
|
||||||
|
public R yield(String result) throws StreamSkipSignal, StreamStopSignal {
|
||||||
|
try {
|
||||||
|
return parser.parse(result);
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
throw new InvalidResultException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.gcube.resources.discovery.client.impl;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBContext;
|
||||||
|
import javax.xml.bind.Unmarshaller;
|
||||||
|
|
||||||
|
import org.gcube.resources.discovery.client.api.ResultParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link ResultParser} that parses query results into JAXB annotated classes.
|
||||||
|
*
|
||||||
|
* @author Fabio Simeoni
|
||||||
|
*
|
||||||
|
* @param <R> the type of parsed results
|
||||||
|
*/
|
||||||
|
public class JAXBParser<R> implements ResultParser<R> {
|
||||||
|
|
||||||
|
private final Class<R> type;
|
||||||
|
private final Unmarshaller um;
|
||||||
|
|
||||||
|
//caches contexts per type
|
||||||
|
private static Map<Class<?>,JAXBContext> ctxts = new HashMap<Class<?>, JAXBContext>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with a JAXB-annotated class.
|
||||||
|
* @param type the class
|
||||||
|
*/
|
||||||
|
public JAXBParser(Class<R> type) {
|
||||||
|
|
||||||
|
this.type=type;
|
||||||
|
|
||||||
|
//lazily create unmarshaller for this type
|
||||||
|
try {
|
||||||
|
JAXBContext ctx = ctxts.get(type);
|
||||||
|
if (ctx==null) {
|
||||||
|
ctx = JAXBContext.newInstance(type);
|
||||||
|
ctxts.put(type,ctx);
|
||||||
|
}
|
||||||
|
this.um=ctx.createUnmarshaller();
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
throw new RuntimeException("error with parser",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public R parse(String result) throws Exception {
|
||||||
|
return type.cast(um.unmarshal(new StringReader(result)));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.gcube.resources.discovery.client.queries.api;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A query for resources.
|
||||||
|
* <p>
|
||||||
|
* The interface is intended for clients that consume queries and are not otherwise concerned with their construction.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface Query {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the textual expression of the query.
|
||||||
|
* @return the expression.
|
||||||
|
*/
|
||||||
|
public String expression();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package org.gcube.resources.discovery.client.queries.api;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Query} that can be customised with namespace declarations, conditions on results, and result expressions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface SimpleQuery extends Query {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a variable to the query.
|
||||||
|
*
|
||||||
|
* @param name the name of the variable
|
||||||
|
* @param range the range of the variable
|
||||||
|
* @return the query
|
||||||
|
*/
|
||||||
|
SimpleQuery addVariable(String name, String range);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a free-form condition on query results.
|
||||||
|
*
|
||||||
|
* @param condition the condition
|
||||||
|
* @return the query
|
||||||
|
*/
|
||||||
|
SimpleQuery addCondition(String condition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a namespace to the query.
|
||||||
|
* @param prefix the namespace prefix
|
||||||
|
* @param uri the namespace URI
|
||||||
|
* @return the query
|
||||||
|
*/
|
||||||
|
SimpleQuery addNamespace(String prefix, URI uri);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a result expression to the query.
|
||||||
|
* @param expression the result expression
|
||||||
|
* @return the query
|
||||||
|
*/
|
||||||
|
SimpleQuery setResult(String expression);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package org.gcube.resources.discovery.client.queries.impl;
|
||||||
|
|
||||||
|
import static org.gcube.resources.discovery.client.queries.impl.Utils.*;
|
||||||
|
|
||||||
|
import org.gcube.resources.discovery.client.queries.api.Query;
|
||||||
|
|
||||||
|
public class QueryBox implements Query {
|
||||||
|
|
||||||
|
private final String expression;
|
||||||
|
|
||||||
|
public QueryBox(String expression) {
|
||||||
|
notNull("expression",expression);
|
||||||
|
this.expression=expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String expression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString()+"="+expression();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((expression == null) ? 0 : expression.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
QueryBox other = (QueryBox) obj;
|
||||||
|
if (expression == null) {
|
||||||
|
if (other.expression != null)
|
||||||
|
return false;
|
||||||
|
} else if (!expression.equals(other.expression))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
package org.gcube.resources.discovery.client.queries.impl;
|
||||||
|
|
||||||
|
import static javax.xml.stream.XMLStreamConstants.*;
|
||||||
|
import static org.gcube.resources.discovery.client.queries.impl.Utils.*;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.stream.XMLInputFactory;
|
||||||
|
import javax.xml.stream.XMLStreamReader;
|
||||||
|
|
||||||
|
import org.gcube.resources.discovery.client.queries.api.Query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Query} that interpolates named parameters inside a template.
|
||||||
|
* <p>
|
||||||
|
* Templates are strings with empty XML elements, optionally with a {@link #DEFAULT} attribute, e.g.:
|
||||||
|
* <p>
|
||||||
|
* <code>all results that satisfy <cond1/> or <cond2 def='that'/> <extra/></code>
|
||||||
|
* <p>
|
||||||
|
* Whenever {@link #expression()} is invoked, the elements in the template are replaced according to the first rule that applies
|
||||||
|
* among the following:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>by the value of an equally named parameter, if one exists
|
||||||
|
* <li>by the value of the {@link #DEFAULT} attribute, if one exists
|
||||||
|
* <li>by the empty string
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* For example, given the previous template and the single parameter <code>cond1="this"</code>, {@link #expression()} returns:
|
||||||
|
* <p>
|
||||||
|
* <code>all results that satisfy this or that</code>
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class QueryTemplate extends QueryBox implements Query {
|
||||||
|
|
||||||
|
public static final String DEFAULT = "def";
|
||||||
|
|
||||||
|
|
||||||
|
private static final XMLInputFactory xmlif = XMLInputFactory.newInstance();
|
||||||
|
|
||||||
|
private static final String wrapper = "_template_";
|
||||||
|
|
||||||
|
|
||||||
|
private final Map<String, String> parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with a template.
|
||||||
|
*
|
||||||
|
* @param template the template
|
||||||
|
*/
|
||||||
|
public QueryTemplate(String template) {
|
||||||
|
super(template);
|
||||||
|
this.parameters = new HashMap<String, String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with a template and an initial set of parameters.
|
||||||
|
*
|
||||||
|
* @param template the template
|
||||||
|
*/
|
||||||
|
public QueryTemplate(String template, Map<String, String> parameters) {
|
||||||
|
super(template);
|
||||||
|
notNull("parameters", parameters);
|
||||||
|
this.parameters = new HashMap<String, String>(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String expression() {
|
||||||
|
return interpolate(super.expression(), parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a parameter to the query, overwriting any value that it may already have.
|
||||||
|
*
|
||||||
|
* @param name the parameter name
|
||||||
|
* @param value the parameter value
|
||||||
|
* @throws IllegalStateException if the parameter name or value are <code>null</code>
|
||||||
|
*/
|
||||||
|
public void addParameter(String name, String value) {
|
||||||
|
|
||||||
|
notNull("name",name);
|
||||||
|
notNull("value",value);
|
||||||
|
|
||||||
|
this.parameters.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a parameter to the query, extending any value that it may already have.
|
||||||
|
*
|
||||||
|
* @param name the parameter name
|
||||||
|
* @param value the value
|
||||||
|
* @throws IllegalStateException if the parameter name or value are <code>null</code>
|
||||||
|
*/
|
||||||
|
public void appendParameter(String name, String value) {
|
||||||
|
|
||||||
|
notNull("name",name);
|
||||||
|
notNull("value",value);
|
||||||
|
|
||||||
|
|
||||||
|
if (parameters.containsKey(name))
|
||||||
|
value=parameters.get(name)+value;
|
||||||
|
|
||||||
|
parameters.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current value of a parameter.
|
||||||
|
* @param name the parameter name
|
||||||
|
* @return the value
|
||||||
|
* @throws IllegalStateException if the parameter does not exist
|
||||||
|
* @throws IllegalStateException if the parameter name is <code>null</code>
|
||||||
|
*/
|
||||||
|
public String parameter(String name) throws IllegalStateException {
|
||||||
|
|
||||||
|
notNull("name",name);
|
||||||
|
|
||||||
|
if (hasParameter(name))
|
||||||
|
return parameters.get(name);
|
||||||
|
|
||||||
|
throw new IllegalStateException("unknown parameter "+name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if the query has a given parameter.
|
||||||
|
* @param name the parameter name
|
||||||
|
* @return <code>true</code> if the query has a given parameter, <code>false</code> otherwise
|
||||||
|
* @throws IllegalStateException if the parameter name is <code>null</code>
|
||||||
|
*/
|
||||||
|
public boolean hasParameter(String name) {
|
||||||
|
|
||||||
|
notNull("name",name);
|
||||||
|
|
||||||
|
return parameters.containsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper
|
||||||
|
private String interpolate(String expression, Map<String, String> parameters) {
|
||||||
|
// replace query parameters with their values.
|
||||||
|
try {
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
XMLStreamReader xmlr = xmlif.createXMLStreamReader(new StringReader("<"+wrapper+">"+expression+"</"+wrapper+">"));
|
||||||
|
|
||||||
|
loop: while (true) {
|
||||||
|
|
||||||
|
int tokenType = xmlr.next();
|
||||||
|
|
||||||
|
switch (tokenType) {
|
||||||
|
|
||||||
|
case START_ELEMENT: // replace parameters with values (provided or default)
|
||||||
|
|
||||||
|
String name = xmlr.getLocalName();
|
||||||
|
|
||||||
|
if (name.equals(wrapper))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (parameters.containsKey(name))
|
||||||
|
builder.append(parameters.get(name));
|
||||||
|
else {
|
||||||
|
// is there a default value?
|
||||||
|
String def = xmlr.getAttributeValue(null,DEFAULT);
|
||||||
|
if (def != null)
|
||||||
|
// add default as a parameter
|
||||||
|
builder.append(def);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHARACTERS: // copy text in output
|
||||||
|
builder.append(xmlr.getText());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case END_DOCUMENT:
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("cannot replace parameters " + parameters + " in query " + expression,e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.gcube.resources.discovery.client.queries.impl;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
|
||||||
|
public static void notNull(String name, Object value) throws IllegalArgumentException {
|
||||||
|
if (value==null)
|
||||||
|
throw new IllegalArgumentException("parameter "+ name+" is null");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package org.gcube.resources.discovery.client.queries.impl;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link SimpleQuery} over an XQuery template.
|
||||||
|
* <p>
|
||||||
|
* The template is defined as follows (cf. {@link #template}):
|
||||||
|
* <p>
|
||||||
|
* <code><ns/> for $resource in <range/><vars/> where <cond def="$result"/> return <result def="$result"/></code>
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* where:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li> {@link #range} stands for the path to the data ranged over by the <code>$result</code> variable. This parameter
|
||||||
|
* is typically bound at query-creation time (cf. {@link #XQuery(Map)}.
|
||||||
|
* <li> {@link #ns}, {@link #vars}, {@link #cond} and {@link #result} stand for, respectively, the declarations of namespace prefixes, the declarations of auxiliary variables,
|
||||||
|
* the conditions, and the result expression of the query. These parameters should be bound through the {@link SimpleQuery} API.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Fabio Simeoni
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class XQuery extends QueryTemplate implements SimpleQuery {
|
||||||
|
|
||||||
|
public static final String ns = "ns";
|
||||||
|
public static final String vars = "vars";
|
||||||
|
public static final String range = "range";
|
||||||
|
public static final String cond = "cond";
|
||||||
|
public static final String result = "result";
|
||||||
|
|
||||||
|
public static final String template = "<ns/> for $resource in <" + range + "/><vars/> where <" + cond + " " + DEFAULT
|
||||||
|
+ "='$resource'/> return <" + result + " " + DEFAULT + "='$resource'/>";
|
||||||
|
|
||||||
|
public XQuery(Map<String, String> parameters) {// add static parameters
|
||||||
|
|
||||||
|
super(template, parameters);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* In the condition, <code>$resource</code> ranges over resources.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public XQuery addCondition(String condition) {
|
||||||
|
|
||||||
|
String newcond = "("+condition+")";
|
||||||
|
|
||||||
|
if (hasParameter(cond))
|
||||||
|
appendParameter(cond," and "+newcond);
|
||||||
|
else
|
||||||
|
addParameter(cond,newcond);
|
||||||
|
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XQuery addNamespace(String prefix, URI uri) {
|
||||||
|
|
||||||
|
String declaration = "declare namespace " + prefix + " = '" + uri + "';";
|
||||||
|
|
||||||
|
appendParameter(ns,declaration);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XQuery addVariable(String variable, String range) {
|
||||||
|
|
||||||
|
String declaration = ", "+variable+" in "+range;
|
||||||
|
|
||||||
|
appendParameter(vars,declaration);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* In the expression, <code>$resource</code> ranges over resources.
|
||||||
|
*/
|
||||||
|
public XQuery setResult(String expression) {
|
||||||
|
addParameter(result, expression);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue