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
rest-collector
fabio.simeoni 11 years ago
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,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 &lt;cond1/> or &lt;cond2 def='that'/> &lt;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>&lt;ns/> for $resource in &lt;range/>&lt;vars/> where &ltcond def="$result"/> return &lt;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…
Cancel
Save