Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion src/main/java/org/xmldb/api/base/Collection.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ public interface Collection extends Configurable, AutoCloseable, ServiceProvider
@Override
void close() throws XMLDBException;


/**
* Returns the time of creation of the collection.
*
Expand All @@ -232,4 +231,44 @@ public interface Collection extends Configurable, AutoCloseable, ServiceProvider
* @since 2.0
*/
Instant getCreationTime() throws XMLDBException;

/**
* Walks a file tree.
* <p>
* This method works as if invoking it were equivalent to evaluating the expression: <blockquote>
*
* <pre>
* walkCollectionTree(Integer.MAX_VALUE, visitor)
* </pre>
*
* </blockquote> In other words, it does not follow symbolic links, and visits all levels of the
* file tree.
*
* @param collectionVisitor the file visitor to invoke for each file
* @throws XMLDBException if an XML DB error is thrown by a visitor method
*
* @since 2.0
*/
default void walkCollectionTree(CollectionVisitor collectionVisitor) throws XMLDBException {
walkCollectionTree(Integer.MAX_VALUE, collectionVisitor);
}

/**
* Walks a file tree.
* <p>
* The {@code maxDepth} parameter is the maximum number of levels of directories to visit. A value
* of {@code 0} means that only the starting file is visited, unless denied by the security
* manager. A value of {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all levels
* should be visited. The {@code visitResource} method is invoked for all files, including
* directories, encountered at {@code maxDepth}, unless the basic file attributes cannot be read,
* in which case the {@code visitResourceFailed} method is invoked.
*
* @param maxDepth the maximum number of collection levels to visit
* @param collectionVisitor the file visitor to invoke for each file
* @throws IllegalArgumentException if the {@code maxDepth} parameter is negative
* @throws XMLDBException if an XML DB error is thrown by a visitor method
*
* @since 2.0
*/
void walkCollectionTree(int maxDepth, CollectionVisitor collectionVisitor) throws XMLDBException;
}
74 changes: 74 additions & 0 deletions src/main/java/org/xmldb/api/base/CollectionVisitResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* The XML:DB Initiative Software License, Version 1.0
*
* Copyright (c) 2000-2022 The XML:DB Initiative. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must include the
* following acknowledgment: "This product includes software developed by the XML:DB Initiative
* (http://www.xmldb.org/)." Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The name "XML:DB Initiative" must not be used to endorse or promote products derived from this
* software without prior written permission. For written permission, please contact info@xmldb.org.
*
* 5. Products derived from this software may not be called "XML:DB", nor may "XML:DB" appear in
* their name, without prior written permission of the XML:DB Initiative.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* =================================================================================================
* This software consists of voluntary contributions made by many individuals on behalf of the
* XML:DB Initiative. For more information on the XML:DB Initiative, please see
* <https://github.com/xmldb-org/>
*/
package org.xmldb.api.base;

import java.nio.file.FileVisitor;

/**
* The result type of a {@link CollectionVisitor}.
*
* @since 2.0
*
* @see Collection#walkCollectionTree
*/
public enum CollectionVisitResult {
/**
* Continue. When returned from a {@link CollectionVisitor#preVisitCollection preVisitCollection}
* method then the entries in the directory should also be visited.
*/
CONTINUE,
/**
* Terminate.
*/
TERMINATE,
/**
* Continue without visiting the entries in this directory. This result is only meaningful when
* returned from the {@link CollectionVisitor#preVisitCollection preVisitCollection} method;
* otherwise this result type is the same as returning {@link #CONTINUE}.
*/
SKIP_SUBTREE,
/**
* Continue without visiting the <em>siblings</em> of this file or directory. If returned from the
* {@link FileVisitor#preVisitDirectory preVisitDirectory} method then the entries in the
* directory are also skipped and the {@link FileVisitor#postVisitDirectory postVisitDirectory}
* method is not invoked.
*/
SKIP_SIBLINGS;
}
164 changes: 164 additions & 0 deletions src/main/java/org/xmldb/api/base/CollectionVisitor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* The XML:DB Initiative Software License, Version 1.0
*
* Copyright (c) 2000-2022 The XML:DB Initiative. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must include the
* following acknowledgment: "This product includes software developed by the XML:DB Initiative
* (http://www.xmldb.org/)." Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The name "XML:DB Initiative" must not be used to endorse or promote products derived from this
* software without prior written permission. For written permission, please contact info@xmldb.org.
*
* 5. Products derived from this software may not be called "XML:DB", nor may "XML:DB" appear in
* their name, without prior written permission of the XML:DB Initiative.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* =================================================================================================
* This software consists of voluntary contributions made by many individuals on behalf of the
* XML:DB Initiative. For more information on the XML:DB Initiative, please see
* <https://github.com/xmldb-org/>
*/
package org.xmldb.api.base;

/**
* A visitor of collections. An implementation of this interface is provided to the
* {@link Collection#walkCollectionTree} methods to visit each resource in a collection tree.
*
* <p>
* <b>Usage Examples:</b>
* <p>
* Suppose we want to delete a collection tree. In that case, each collection should be deleted
* after the resources in the collection are deleted.
*
* <pre>
* collection.walkCollectionTree(new SimpleCollectionVisitor() {
* &#64;Override
* public CollectionVisitResult visitResource(Resource resource) throws XMLDBException {
* resource.getParentCollection().removeResource(resource);
* return CollectionVisitResult.CONTINUE;
* }
*
* &#64;Override
* public CollectionVisitResult postVisitCollection(Collection collection, XMLDBException e)
* throws XMLDBException {
* if (e == null) {
* String collectionName = collection.getName()
* resource.getParentCollection().getService(CollectionManagementService.class).removeCollection(collectionName);
* return CollectionVisitResult.CONTINUE;
* } else {
* // collection iteration failed
* throw e;
* }
* }
* });
* </pre>
* <p>
* Furthermore, suppose we want to copy a collection tree to a target location. In that case,
* symbolic links should be followed and the target collection should be created before the
* resources in the collection are copied.
*
* <pre>
* sourceColelction.walkCollectionTree(Integer.MAX_VALUE, new SimpleFileVisitor&lt;Path&gt;() {
* &#64;Override
* public CollectionVisitResult preVisitCollection(Collection collection) throws XMLDBException {
* Path targetcollection = target.resolve(source.relativize(collection));
* try {
* Files.copy(collection, targetcollection);
* } catch (FileAlreadyExistsException e) {
* if (!Files.isDirectory(targetcollection))
* throw e;
* }
* return CONTINUE;
* }
*
* &#64;Override
* public CollectionVisitResult visitFile(Resource resource) throws XMLDBException {
* Files.copy(resource, target.resolve(source.relativize(resource)));
* return CONTINUE;
* }
* });
* </pre>
*
* @since 2.0
*/
public interface CollectionVisitor {
/**
* Invoked for a collection before resources in the collection are visited.
*
* <p>
* If this method returns {@link CollectionVisitResult#CONTINUE CONTINUE}, then resources in the
* collection are visited. If this method returns {@link CollectionVisitResult#SKIP_SUBTREE
* SKIP_SUBTREE} or {@link CollectionVisitResult#SKIP_SIBLINGS SKIP_SIBLINGS} then resources in
* the collection (and any descendants) will not be visited.
*
* @param collection a reference to the collection
*
* @return the visit result
*
* @throws XMLDBException if an XML DB error occurs
*/
Collection preVisitCollection(Collection collection) throws XMLDBException;

/**
* Invoked for a resource in a collection.
*
* @param resource a reference to the resource
*
* @return the visit result
*
* @throws XMLDBException if an XML DB error occurs
*/
Collection visitResource(Resource resource) throws XMLDBException;

/**
* Invoked for a resource that could not be visited. This method is invoked if the resource's
* attributes could not be read, the resource is a collection that could not be opened, and other
* reasons.
*
* @param resource a reference to the resource
* @param exc the XML DB exception that prevented the resource from being visited
*
* @return the visit result
*
* @throws XMLDBException if an XML DB error occurs
*/
Collection visitResourceFailed(Resource resource, XMLDBException exc) throws XMLDBException;

/**
* Invoked for a collection after resources in the collection, and all of their descendants, have
* been visited. This method is also invoked when iteration of the collection completes
* prematurely (by a {@link #visitResource visitFile} method returning
* {@link CollectionVisitResult#SKIP_SIBLINGS SKIP_SIBLINGS}, or an XML DB error when iterating
* over the collection).
*
* @param collection a reference to the collection
* @param exc {@code null} if the iteration of the collection completes without an error;
* otherwise the XML DB exception that caused the iteration of the collection to complete
* prematurely
*
* @return the visit result
*
* @throws XMLDBException if an XML DB error occurs
*/
Collection postVisitCollection(Collection collection, XMLDBException exc) throws XMLDBException;

}
7 changes: 7 additions & 0 deletions src/test/java/org/xmldb/api/TestCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.util.Optional;

import org.xmldb.api.base.Collection;
import org.xmldb.api.base.CollectionVisitor;
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.Service;
import org.xmldb.api.base.XMLDBException;
Expand Down Expand Up @@ -157,4 +158,10 @@ public void close() throws XMLDBException {
public Instant getCreationTime() throws XMLDBException {
return creation;
}

@Override
public void walkCollectionTree(int maxDepth, CollectionVisitor collectionVisitor)
throws XMLDBException {
throw new XMLDBException(NOT_IMPLEMENTED);
}
}
62 changes: 62 additions & 0 deletions src/test/java/org/xmldb/api/base/CollectionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* The XML:DB Initiative Software License, Version 1.0
*
* Copyright (c) 2000-2022 The XML:DB Initiative. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must include the
* following acknowledgment: "This product includes software developed by the XML:DB Initiative
* (http://www.xmldb.org/)." Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The name "XML:DB Initiative" must not be used to endorse or promote products derived from this
* software without prior written permission. For written permission, please contact info@xmldb.org.
*
* 5. Products derived from this software may not be called "XML:DB", nor may "XML:DB" appear in
* their name, without prior written permission of the XML:DB Initiative.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* =================================================================================================
* This software consists of voluntary contributions made by many individuals on behalf of the
* XML:DB Initiative. For more information on the XML:DB Initiative, please see
* <https://github.com/xmldb-org/>
*/
package org.xmldb.api.base;

import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.mockito.Mockito.verify;

import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoSettings;

@MockitoSettings
class CollectionTest {
@Spy
Collection collection;
@Mock
CollectionVisitor collectionVisitor;

@Test
void testWalkCollectionTree() throws XMLDBException {
assertThatNoException().isThrownBy(() -> collection.walkCollectionTree(collectionVisitor));
verify(collection).walkCollectionTree(Integer.MAX_VALUE, collectionVisitor);
}
}
Loading