-
-
Notifications
You must be signed in to change notification settings - Fork 190
[Feature] Add xquery recursive collection creation with just one path expression #5062
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 3 commits
7ee7a8d
206772a
66a060e
f907b10
5135da7
78bf82e
e898899
31abe51
ff155b8
e7118ed
ac5f200
7cbd6dd
43f331f
cf1a8de
1915cfa
3ed9193
213d9bd
11b270b
138b435
fa16fd4
61faaae
72bc0ee
bd4d1d2
b963c00
4f71bdc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,64 +25,161 @@ | |
import org.apache.logging.log4j.Logger; | ||
|
||
import org.exist.dom.QName; | ||
import org.exist.xquery.Cardinality; | ||
import org.exist.xquery.FunctionSignature; | ||
import org.exist.xquery.XPathException; | ||
import org.exist.xquery.XQueryContext; | ||
import org.exist.xquery.value.FunctionReturnSequenceType; | ||
import org.exist.xquery.value.FunctionParameterSequenceType; | ||
import org.exist.xquery.value.Sequence; | ||
import org.exist.xquery.value.SequenceType; | ||
import org.exist.xquery.value.StringValue; | ||
import org.exist.xquery.value.Type; | ||
import org.exist.dom.persistent.NodeProxy; | ||
import org.exist.xmldb.LocalCollection; | ||
import org.exist.xmldb.XmldbURI; | ||
import org.exist.xquery.*; | ||
import org.exist.xquery.value.*; | ||
import org.xmldb.api.base.Collection; | ||
import org.xmldb.api.base.XMLDBException; | ||
import java.net.URISyntaxException; | ||
import java.util.Optional; | ||
|
||
/** | ||
* Implements eXist's xmldb:create-collection() function. | ||
* | ||
* @author wolf | ||
*/ | ||
public class XMLDBCreateCollection extends XMLDBAbstractCollectionManipulator { | ||
private static final Logger logger = LogManager.getLogger(XMLDBCreateCollection.class); | ||
public final static FunctionSignature signature = new FunctionSignature( | ||
private static final Logger logger = LogManager.getLogger(XMLDBCreateCollection.class); | ||
public final static FunctionSignature SIGNATURE_WITH_PARENT = new FunctionSignature( | ||
dizzzz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
new QName("create-collection", XMLDBModule.NAMESPACE_URI, | ||
XMLDBModule.PREFIX), | ||
"Create a new collection with name $new-collection as a child of " + | ||
"$target-collection-uri. " + XMLDBModule.COLLECTION_URI + | ||
"Returns the path to the new collection if successfully created, " + | ||
"otherwise the empty sequence.", | ||
"Create a new collection with name $new-collection as a child of " + | ||
"$target-collection-uri. " + XMLDBModule.COLLECTION_URI + | ||
"Returns the path to the new collection if successfully created, " + | ||
"otherwise the empty sequence.", | ||
new SequenceType[]{ | ||
new FunctionParameterSequenceType("target-collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The target collection URI"), | ||
new FunctionParameterSequenceType("new-collection", Type.STRING, Cardinality.EXACTLY_ONE, "The name of the new collection to create")}, | ||
new FunctionParameterSequenceType("target-collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The target collection URI"), | ||
new FunctionParameterSequenceType("new-collection", Type.STRING, Cardinality.EXACTLY_ONE, "The name of the new collection to create")}, | ||
new FunctionReturnSequenceType(Type.STRING, Cardinality.ZERO_OR_ONE, "the path to the new collection if successfully created, otherwise the empty sequence")); | ||
|
||
public XMLDBCreateCollection(XQueryContext context) { | ||
super(context, signature); | ||
} | ||
public final static FunctionSignature SIGNATURE_WITH_URI = new FunctionSignature( | ||
dizzzz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
new QName("create-collection", XMLDBModule.NAMESPACE_URI, | ||
XMLDBModule.PREFIX), | ||
"Create a new collection by specifying the full uri $new-collection-uri. " + XMLDBModule.COLLECTION_URI + | ||
"Returns the path to the new collection if successfully created, " + | ||
"otherwise the empty sequence.", | ||
new SequenceType[]{ | ||
new FunctionParameterSequenceType("new-collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The new collection URI")}, | ||
dizzzz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
new FunctionReturnSequenceType(Type.STRING, Cardinality.ZERO_OR_ONE, "the path to the new collection if successfully created, otherwise the empty sequence")); | ||
|
||
public XMLDBCreateCollection(XQueryContext context, FunctionSignature signature) { | ||
super(context, signature); | ||
} | ||
|
||
/* | ||
* (non-Javadoc) | ||
* | ||
* @see org.exist.xquery.Expression#eval(org.exist.dom.persistent.DocumentSet, | ||
* org.exist.xquery.value.Sequence, org.exist.xquery.value.Item) | ||
*/ | ||
public Sequence evalWithCollection(Collection collection, Sequence[] args, Sequence contextSequence) | ||
dizzzz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
throws XPathException { | ||
String collectionName = null; | ||
if(2 == args.length) { | ||
|
||
collectionName = args[1].getStringValue(); | ||
} else if(1 == args.length) { | ||
collectionName = args[0].getStringValue(); | ||
} | ||
|
||
/* | ||
* (non-Javadoc) | ||
* | ||
* @see org.exist.xquery.Expression#eval(org.exist.dom.persistent.DocumentSet, | ||
* org.exist.xquery.value.Sequence, org.exist.xquery.value.Item) | ||
*/ | ||
public Sequence evalWithCollection(Collection collection, Sequence[] args, Sequence contextSequence) | ||
throws XPathException { | ||
try { | ||
final Collection newCollection = createCollectionPath(collection, collectionName); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shoudl this go in to |
||
|
||
final String collectionName = args[1].getStringValue(); | ||
|
||
try { | ||
final Collection newCollection = createCollectionPath(collection, collectionName); | ||
if (newCollection == null) | ||
|
||
{return Sequence.EMPTY_SEQUENCE;} | ||
else | ||
{return new StringValue(this, newCollection.getName());} | ||
|
||
if (newCollection == null) | ||
{return Sequence.EMPTY_SEQUENCE;} | ||
else | ||
{return new StringValue(this, newCollection.getName());} | ||
} catch (final XMLDBException e) { | ||
logger.error("Unable to create new collection {}", collectionName, e); | ||
throw new XPathException(this, "failed to create new collection " + collectionName + ": " + e.getMessage(), e); | ||
} | ||
} | ||
|
||
/** | ||
adamretter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* Override of the eval method so we can create | ||
* a collection using just its path. | ||
* */ | ||
@Override | ||
public Sequence eval(final Sequence[] args, final Sequence contextSequence) | ||
throws XPathException { | ||
int paramNumber = 0; | ||
|
||
if (0 == args.length) { | ||
throw new XPathException(this, "Expected a collection as the argument " + (paramNumber + 1) + "."); | ||
} else if (2 == args.length) { | ||
return super.eval(args, contextSequence); | ||
} | ||
|
||
final boolean collectionNeedsClose = false; | ||
|
||
Collection collection = null; | ||
final Item item = args[paramNumber].itemAt(0); | ||
if (Type.subTypeOf(item.getType(), Type.NODE)) { | ||
final NodeValue node = (NodeValue) item; | ||
if (logger.isDebugEnabled()) { | ||
logger.debug("Found node"); | ||
|
||
} | ||
if (node.getImplementationType() == NodeValue.PERSISTENT_NODE) { | ||
final org.exist.collections.Collection internalCol = ((NodeProxy) node).getOwnerDocument().getCollection(); | ||
if (logger.isDebugEnabled()) { | ||
logger.debug("Found node"); | ||
|
||
} | ||
try { | ||
//TODO: use xmldbURI | ||
collection = getLocalCollection(this, context, internalCol.getURI().toString()); | ||
return new StringValue(this, collection.getName()); | ||
} catch (final XMLDBException e) { | ||
if (logger.isDebugEnabled()) { | ||
|
||
logger.debug("Couldn't find parent collection, creating a new one."); | ||
} | ||
} | ||
} else { | ||
return Sequence.EMPTY_SEQUENCE; | ||
} | ||
} | ||
|
||
final String collectionURI = args[paramNumber].getStringValue(); | ||
if (collection == null && collectionURI != null) { | ||
try { | ||
collection = getCollection(this, context, collectionURI, Optional.empty(), Optional.empty()); | ||
return new StringValue(this, collection.getName()); | ||
} catch (final XMLDBException xe) { | ||
if (logger.isDebugEnabled()) { | ||
|
||
logger.debug("Couldn't find parent collection, creating a new one."); | ||
} | ||
} | ||
} else { | ||
try { | ||
return new StringValue(this, collection.getName()); | ||
} catch (XMLDBException e) { | ||
|
||
throw new RuntimeException(e); | ||
dizzzz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
Sequence s = Sequence.EMPTY_SEQUENCE; | ||
try { | ||
collection = getRootCollection(context, collectionURI); | ||
s = evalWithCollection(collection, args, contextSequence); | ||
} finally { | ||
if (collectionNeedsClose && collection != null) { | ||
try { | ||
collection.close(); | ||
} catch (final Exception e) { | ||
|
||
throw new XPathException(this, "Unable to close collection", e); | ||
} | ||
} | ||
} | ||
return s; | ||
} | ||
|
||
} catch (final XMLDBException e) { | ||
logger.error("Unable to create new collection {}", collectionName, e); | ||
throw new XPathException(this, "failed to create new collection " + collectionName + ": " + e.getMessage(), e); | ||
public Collection getRootCollection(final XQueryContext context, final String collectionUri) throws XPathException { | ||
Collection rootCollection = null; | ||
try { | ||
rootCollection = new LocalCollection(context.getSubject(), context.getBroker().getBrokerPool(), XmldbURI.xmldbUriFor("/db", false)); | ||
|
||
} catch (final XMLDBException | URISyntaxException e) { | ||
throw new XPathException(this, "Failed to access the root collection", e); | ||
} | ||
return rootCollection; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
(: | ||
: eXist-db Open Source Native XML Database | ||
: Copyright (C) 2001 The eXist-db Authors | ||
: | ||
: [email protected] | ||
: http://www.exist-db.org | ||
: | ||
: This library is free software; you can redistribute it and/or | ||
: modify it under the terms of the GNU Lesser General Public | ||
: License as published by the Free Software Foundation; either | ||
: version 2.1 of the License, or (at your option) any later version. | ||
: | ||
: This library is distributed in the hope that it will be useful, | ||
: but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
: Lesser General Public License for more details. | ||
: | ||
: You should have received a copy of the GNU Lesser General Public | ||
: License along with this library; if not, write to the Free Software | ||
: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
:) | ||
xquery version "3.0"; | ||
|
||
module namespace t="http://exist-db.org/testsuite/collection-create"; | ||
|
||
import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql"; | ||
|
||
declare variable $t:parent-collection-name := "parent-collection"; | ||
declare variable $t:parent-collection := "/db/" || $t:parent-collection-name; | ||
declare variable $t:path-collection := "path/to/new-collection"; | ||
dizzzz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
declare | ||
%test:setUp | ||
function t:setup() { | ||
xmldb:create-collection("/db", $t:parent-collection-name) | ||
}; | ||
|
||
declare | ||
%test:tearDown | ||
function t:cleanup() { | ||
xmldb:remove($t:parent-collection) | ||
}; | ||
|
||
declare | ||
%test:assertEquals("/db/path/to/new-collection") | ||
function t:fnDocAvailableOnHiddenResource() { | ||
dizzzz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
let $collection := xmldb:create-collection($t:path-collection) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do I understand correctly that you are currently testing that:
creates the collection If so, that should not work! The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks good to me |
||
return ( | ||
dizzzz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
$collection | ||
) | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.