Skip to content

Commit

Permalink
Add getChildren() signature in FedoraResource...
Browse files Browse the repository at this point in the history
 - Implement it in FedoraResourceImpl.java
 - Expose the hierarchy levels through the IdentifierConverter and IdentifierTranslator on behalf of the getChildren() implementation.
 - Integrate the getChildren() method in FedoraResource to generate the hierarchy rdf triples for REST web UI.
 - Log the potential null children nodes and return as suggested.
 - Implement FedoraResource.getParent() for transparent hierarchy support.

Resolves: https://www.pivotaltracker.com/story/show/71941366
  • Loading branch information
lsitu authored and Andrew Woods committed Jul 2, 2014
1 parent a04bad4 commit ab5139c
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 10 deletions.
Expand Up @@ -19,6 +19,7 @@
import com.hp.hpl.jena.rdf.model.Resource;

import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.identifiers.HierarchyConverter;
import org.fcrepo.kernel.identifiers.InternalIdentifierConverter;
import org.fcrepo.kernel.identifiers.NamespaceConverter;
import org.fcrepo.kernel.services.functions.GetDefaultWorkspace;
Expand Down Expand Up @@ -130,6 +131,13 @@ public HttpIdentifierTranslator(final Session session,
this.defaultWorkspace = getDefaultWorkspace.apply(session.getRepository());
LOGGER.debug("Resolving graph subjects to a base URI of \"{}\"",
normalizedBasePath);
resetTranslationChain();
for (InternalIdentifierConverter converter : translationChain) {
if (converter instanceof HierarchyConverter) {
hierarchyLevels = converter.getLevels();
break;
}
}
}

/**
Expand Down Expand Up @@ -317,4 +325,13 @@ protected void resetTranslationChain() {

private static final List<InternalIdentifierConverter> minimalTranslationChain =
singletonList((InternalIdentifierConverter) new NamespaceConverter());

/**
* Hierarchy levels. Default 1 for converters other than the HierarchyConverter.
* @return
*/
@Override
public int getHierarchyLevels() {
return hierarchyLevels;
}
}
Expand Up @@ -232,6 +232,11 @@ protected static UriInfo getUriInfoImpl(final String path) {
return ui;
}

@Test
public void testGetHierarchyLevels() {
assertTrue(testObj.getHierarchyLevels() >= 0);
}

@Path("/rest/{path}")
protected class MockNodeController {

Expand Down
Expand Up @@ -17,7 +17,7 @@

import java.util.Collection;
import java.util.Date;

import java.util.Iterator;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.version.Version;
Expand Down Expand Up @@ -137,6 +137,25 @@ RdfStream getHierarchyTriples(final IdentifierTranslator graphSubjects,
final HierarchyRdfContextOptions serializationOptions)
throws RepositoryException;

/**
* Return a list children of this object
* @param graphSubjects
* @return
* @throws RepositoryException
*/
Iterator<Node> getChildren(final IdentifierTranslator graphSubjects)
throws RepositoryException;

/**
* Return the parent node of this object
* @param graphSubjects
* @return
* @throws RepositoryException
*/
Node getParent(final IdentifierTranslator graphSubjects)
throws RepositoryException;


/**
* Serialize the JCR versions information as an RDF dataset
* @param graphSubjects
Expand Down Expand Up @@ -165,7 +184,7 @@ RdfStream getVersionTriples(final IdentifierTranslator graphSubjects)

/**
* Get the JCR Base version for the node
*
*
* @return base version
* @throws RepositoryException
*/
Expand Down
Expand Up @@ -27,5 +27,13 @@
* @param <T> the type to and from which we are translating
*/
public abstract class IdentifierConverter<T> extends Converter<String, T> {
protected int hierarchyLevels = 0;

/**
* Get hierarchy levels for path conversion
* @return
**/
public int getLevels() {
return hierarchyLevels;
}
}
Expand Up @@ -57,4 +57,10 @@ public interface IdentifierTranslator {
* @return Resource
*/
Resource getContext();

/**
* Get the hierarchy levels for translation
* @return
*/
int getHierarchyLevels();
}
Expand Up @@ -18,6 +18,7 @@
import static java.util.Collections.singletonList;
import static org.fcrepo.kernel.identifiers.InternalIdentifierConverter.identityConverter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;
Expand All @@ -37,6 +38,11 @@ public void setUp() {
testTranslator = new ExternalIdentifierConverter();
}

@Test
public void testGetHierarchyLevels() {
assertTrue(testTranslator.getLevels() >= 0);
}

@Test
public void testRoundTrip() {
testTranslator.setTranslationChain(singletonList(identityConverter()));
Expand Down
102 changes: 102 additions & 0 deletions fcrepo-kernel/src/main/java/org/fcrepo/kernel/FedoraResourceImpl.java
Expand Up @@ -31,16 +31,23 @@
import static org.fcrepo.kernel.utils.FedoraTypesUtils.nodetype2name;
import static org.fcrepo.kernel.utils.FedoraTypesUtils.property2values;
import static org.fcrepo.kernel.utils.FedoraTypesUtils.value2string;
import static org.fcrepo.kernel.utils.FedoraTypesUtils.isInternalNode;
import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
import static org.modeshape.jcr.api.JcrConstants.NT_FOLDER;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.version.Version;
Expand Down Expand Up @@ -386,4 +393,99 @@ public String getEtagValue() throws RepositoryException {
}
return "";
}

@Override
public Iterator<Node> getChildren(final IdentifierTranslator graphSubjects) throws RepositoryException {
return getChildren(node, graphSubjects);
}

/**
* Retrieve children of a node
* @param node
* @param graphSubjects
* @return
* @throws RepositoryException
*/
public static Iterator<Node> getChildren(final Node node, final IdentifierTranslator graphSubjects)
throws RepositoryException {
final int hierarchyLevels = graphSubjects.getHierarchyLevels();
return findChildren(node, hierarchyLevels);
}

/**
* Find the child resources of a path.
* @param recurse If true, find all descenant resources, not just direct children.
* @throws RepositoryException
**/
private static Iterator<Node> findChildren(final Node node, final int hierarchyLevels) throws RepositoryException {
final Map<String, Node> childrenMap = new TreeMap<>();
final List<Node> children = new ArrayList<>();
findChildren( node, children, false );
for (int i = 0; i < hierarchyLevels && children.size() > 0; i++) {
final List<Node> childrenCopy = new ArrayList<>();
childrenCopy.addAll(children);
children.clear();
for (final Node child : childrenCopy) {
findChildren( child, children, false );
}
}

for (final Node child : children) {
childrenMap.put(child.getPath(), child);
}
return childrenMap.values().iterator();
}

/**
* Find children of a node.
* @param node Repository node to find children of
* @param children Set to add child paths to
* @param If true, find all descendant paths, not just direct child paths
**/
private static void findChildren(final Node node, final List<Node> children, final boolean recurse)
throws RepositoryException {
if (node.getNodes() == null) {
LOGGER.debug("Null children nodes returned from {}", node.getPath());
return;
}
for (final NodeIterator nodes = node.getNodes(); nodes.hasNext();) {
final Node child = nodes.nextNode();
if (!isInternalNode.apply(child) && !child.getName().equals(JCR_CONTENT)) {

children.add(child);

if (recurse) {
findChildren(child, children, recurse);
}
}
}
}

/**
* Get the parent of the current node
* @param graphSubjects
* @return
* @throws RepositoryException
*/
@Override
public Node getParent(final IdentifierTranslator graphSubjects) throws RepositoryException {
return findParent(node, graphSubjects);
}

/**
* Find the parent of the node
* @param node
* @param graphSubjects
* @return
* @throws RepositoryException
*/
public static Node findParent(final Node node, final IdentifierTranslator graphSubjects)
throws RepositoryException {
final int hierarchyLevels = graphSubjects.getHierarchyLevels();
Node parent = node.getParent();
for (int i = 0; i < hierarchyLevels; i++) {
parent = parent.getParent();
}
return parent;
}
}
Expand Up @@ -288,4 +288,12 @@ public String convertNamespace(final String namespace) {
return namespace;
}
}

/**
* Get hierarchy levels
*/
@Override
public int getLevels() {
return levels;
}
}
Expand Up @@ -85,4 +85,9 @@ public boolean isFedoraGraphSubject(final Resource subject) {
return subject.isURIResource() && subject.getURI().startsWith(RESOURCE_NAMESPACE);
}

@Override
public int getHierarchyLevels() {
return 0;
}

}
Expand Up @@ -15,7 +15,6 @@
*/
package org.fcrepo.kernel.rdf.impl;

import static com.google.common.base.Predicates.not;
import static com.google.common.base.Throwables.propagate;
import static com.hp.hpl.jena.graph.Triple.create;
import static com.hp.hpl.jena.vocabulary.RDF.type;
Expand All @@ -37,7 +36,7 @@
import org.fcrepo.kernel.rdf.HierarchyRdfContextOptions;
import org.fcrepo.kernel.rdf.IdentifierTranslator;
import org.fcrepo.kernel.rdf.JcrRdfTools;
import org.fcrepo.kernel.utils.iterators.NodeIterator;
import org.fcrepo.kernel.FedoraResourceImpl;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.slf4j.Logger;

Expand Down Expand Up @@ -106,7 +105,7 @@ private Triple[] containerContext() {
}

private Iterator<Triple> parentContext() throws RepositoryException {
final javax.jcr.Node parentNode = node().getParent();
final javax.jcr.Node parentNode = FedoraResourceImpl.findParent(node(), graphSubjects());//node().getParent();
final Node parentNodeSubject = graphSubjects().getSubject(parentNode.getPath()).asNode();

final RdfStream parentStream = new RdfStream();
Expand All @@ -117,9 +116,8 @@ private Iterator<Triple> parentContext() throws RepositoryException {
}

private Iterator<Triple> childrenContext() throws RepositoryException {

final Iterator<javax.jcr.Node> niceChildren =
Iterators.filter(new NodeIterator(node().getNodes()), not(nastyChildren));
final Iterator<javax.jcr.Node> niceChildren = FedoraResourceImpl.getChildren(node(), graphSubjects());
//Iterators.filter(new NodeIterator(node().getNodes()), not(nastyChildren));

final Iterator<javax.jcr.Node> salientChildren;

Expand Down

0 comments on commit ab5139c

Please sign in to comment.