Skip to content

Commit

Permalink
Add FedoraResource.getTypes() method
Browse files Browse the repository at this point in the history
  • Loading branch information
acoburn authored and Andrew Woods committed Sep 1, 2015
1 parent 4629227 commit b03c4ea
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 64 deletions.
Expand Up @@ -18,6 +18,7 @@
import java.net.URI;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.jcr.AccessDeniedException;
import javax.jcr.Node;
Expand Down Expand Up @@ -108,11 +109,23 @@ public interface FedoraResource {
Date getLastModifiedDate();

/**
* Check if this object uses a given mixin
* Check if this object uses a given RDF type
*
* <p>Note: the type parameter should be in prefixed short form, so ldp:Container or ex:Image
* are both acceptable types. This method does not assume any jcr to fedora prefix mappings are
* managed by the implementation, so hasType("jcr:frozenNode") is a valid use of this method.</p>
*
* @param type the given type
* @return a collection of mixin names
* @return whether the object has the given type
*/
boolean hasType(final String type);

/**
* Get the RDF:type values for this resource
* @return a list of types for this resource
*/
List<URI> getTypes();

/**
* Update the provided properties with a SPARQL Update query. The updated
* properties may be serialized to the JCR store.
Expand Down
Expand Up @@ -23,12 +23,14 @@
import static com.google.common.collect.Lists.newArrayList;
import static com.hp.hpl.jena.update.UpdateAction.execute;
import static com.hp.hpl.jena.update.UpdateFactory.create;
import static java.util.Arrays.asList;
import static java.util.regex.Pattern.compile;
import static org.apache.commons.codec.digest.DigestUtils.shaHex;
import static org.fcrepo.kernel.api.services.functions.JcrPropertyFunctions.isFrozen;
import static org.fcrepo.kernel.api.services.functions.JcrPropertyFunctions.property2values;
import static org.fcrepo.kernel.api.utils.UncheckedFunction.uncheck;
import static org.fcrepo.kernel.modeshape.identifiers.NodeResourceConverter.nodeConverter;
import static org.fcrepo.kernel.modeshape.rdf.JcrRdfTools.getRDFNamespaceForJcrNamespace;
import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.isFrozenNode;
import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.isInternalNode;
import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
Expand All @@ -38,13 +40,15 @@
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.jcr.AccessDeniedException;
import javax.jcr.ItemNotFoundException;
Expand All @@ -55,6 +59,7 @@
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeType;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;

Expand Down Expand Up @@ -385,6 +390,42 @@ public boolean hasType(final String type) {
}
}

@Override
public List<URI> getTypes() {
try {
final List<NodeType> nodeTypes = new ArrayList<>();
final NodeType primaryNodeType = node.getPrimaryNodeType();
nodeTypes.add(primaryNodeType);
nodeTypes.addAll(asList(primaryNodeType.getSupertypes()));
final List<NodeType> mixinTypes = asList(node.getMixinNodeTypes());

nodeTypes.addAll(mixinTypes);
mixinTypes.stream()
.map(NodeType::getSupertypes)
.flatMap(Arrays::stream)
.forEach(nodeTypes::add);

return nodeTypes.stream()
.map(uncheck(x -> x.getName()))
.distinct()
.map(nodeTypeNameToURI::apply)
.peek(x -> LOGGER.debug("node has rdf:type {}", x))
.collect(Collectors.toList());

} catch (final PathNotFoundException e) {
throw new PathNotFoundRuntimeException(e);
} catch (final RepositoryException e) {
throw new RepositoryRuntimeException(e);
}
}

private Function<String, URI> nodeTypeNameToURI = uncheck(name -> {
final String prefix = name.split(":")[0];
final String typeName = name.split(":")[1];
final String namespace = getSession().getWorkspace().getNamespaceRegistry().getURI(prefix);
return URI.create(getRDFNamespaceForJcrNamespace(namespace) + typeName);
});

/* (non-Javadoc)
* @see org.fcrepo.kernel.api.models.FedoraResource#updateProperties
* (org.fcrepo.kernel.api.identifiers.IdentifierConverter, java.lang.String, RdfStream)
Expand Down
Expand Up @@ -15,7 +15,6 @@
*/
package org.fcrepo.kernel.modeshape.rdf.impl;

import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.rdf.model.Resource;

import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
Expand All @@ -24,22 +23,12 @@
import org.slf4j.Logger;

import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

import static com.hp.hpl.jena.graph.NodeFactory.createURI;
import static com.hp.hpl.jena.graph.Triple.create;
import static com.hp.hpl.jena.vocabulary.RDF.type;
import static org.fcrepo.kernel.modeshape.rdf.JcrRdfTools.getRDFNamespaceForJcrNamespace;

import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static org.fcrepo.kernel.api.RdfLexicon.MIX_NAMESPACE;
import static org.fcrepo.kernel.api.utils.UncheckedFunction.uncheck;
import static org.slf4j.LoggerFactory.getLogger;

/**
Expand All @@ -63,37 +52,14 @@ public TypeRdfContext(final FedoraResource resource,
super(resource, idTranslator);

//include rdf:type for primaryType, mixins, and their supertypes
concatRdfTypes();
concat(resource().getTypes().stream()
.map(uri -> create(subject(), type.asNode(), createURI(uri.toString())))
.iterator());
if (resource() instanceof NonRdfSource) {
// gather versionability info from the parent
if (resource().getNode().getParent().isNodeType("mix:versionable")) {
concat(create(subject(), type.asNode(), createURI(MIX_NAMESPACE + "versionable")));
}
}
}

private void concatRdfTypes() throws RepositoryException {
final List<NodeType> nodeTypes = new ArrayList<>();
final NodeType primaryNodeType = resource().getNode().getPrimaryNodeType();
nodeTypes.add(primaryNodeType);
nodeTypes.addAll(asList(primaryNodeType.getSupertypes()));
final NodeType[] mixinNodeTypesArr = resource().getNode().getMixinNodeTypes();
stream(mixinNodeTypesArr).forEach(nodeTypes::add);
stream(mixinNodeTypesArr).map(NodeType::getSupertypes).flatMap(Arrays::stream).forEach(nodeTypes::add);
concat(nodeTypes.stream().map(nodetype2triple).iterator());
}

private final Function<NodeType, Triple> nodetype2triple = uncheck(nodeType -> {
final String name = nodeType.getName();
final String prefix = name.split(":")[0];
final String typeName = name.split(":")[1];
final String namespace = getJcrUri(prefix);
final com.hp.hpl.jena.graph.Node rdfType = createURI(getRDFNamespaceForJcrNamespace(namespace) + typeName);
LOGGER.trace("Translating mixin: {} w/ namespace: {} into resource: {}", name, namespace, rdfType);
return create(subject(), type.asNode(), rdfType);
});

private String getJcrUri(final String prefix) throws RepositoryException {
return session().getWorkspace().getNamespaceRegistry().getURI(prefix);
}
}
Expand Up @@ -24,6 +24,8 @@
import static org.fcrepo.kernel.api.FedoraJcrTypes.FROZEN_NODE;
import static org.fcrepo.kernel.api.FedoraJcrTypes.JCR_CREATED;
import static org.fcrepo.kernel.api.FedoraJcrTypes.JCR_LASTMODIFIED;
import static org.fcrepo.kernel.api.RdfLexicon.JCR_NAMESPACE;
import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE;
import static org.fcrepo.kernel.api.utils.iterators.RdfStream.fromModel;
import static org.fcrepo.kernel.modeshape.testutilities.TestNodeIterator.nodeIterator;
import static org.junit.Assert.assertEquals;
Expand All @@ -45,7 +47,9 @@
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.jcr.NamespaceRegistry;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
Expand Down Expand Up @@ -98,6 +102,18 @@ public class FedoraResourceImplTest {
@Mock
private Node mockContainer;

@Mock
private NodeType mockPrimaryNodeType;

@Mock
private NodeType mockMixinNodeType;

@Mock
private NodeType mockPrimarySuperNodeType;

@Mock
private NodeType mockMixinSuperNodeType;

@Mock
private Session mockSession;

Expand Down Expand Up @@ -149,6 +165,48 @@ public void testGetCreatedDate() throws RepositoryException {
.getTime());
}

@Test
public void testGetTypes() throws RepositoryException {
final String mockNodeTypePrefix = "jcr";

final String mockPrimaryNodeTypeName = "somePrimaryType";
final String mockMixinNodeTypeName = "someMixinType";
final String mockPrimarySuperNodeTypeName = "somePrimarySuperType";
final String mockMixinSuperNodeTypeName = "someMixinSuperType";

final Workspace mockWorkspace = mock(Workspace.class);
final NamespaceRegistry mockNamespaceRegistry = mock(NamespaceRegistry.class);

when(mockSession.getWorkspace()).thenReturn(mockWorkspace);
when(mockWorkspace.getNamespaceRegistry()).thenReturn(mockNamespaceRegistry);
when(mockNamespaceRegistry.getURI("jcr")).thenReturn(JCR_NAMESPACE);
when(mockNode.getPrimaryNodeType()).thenReturn(mockPrimaryNodeType);
when(mockPrimaryNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockPrimaryNodeTypeName);

when(mockNode.getMixinNodeTypes()).thenReturn(
new NodeType[]{mockMixinNodeType});
when(mockMixinNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockMixinNodeTypeName);

when(mockPrimaryNodeType.getSupertypes()).thenReturn(
new NodeType[]{mockPrimarySuperNodeType});
when(mockPrimarySuperNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockPrimarySuperNodeTypeName);

when(mockMixinNodeType.getSupertypes()).thenReturn(
new NodeType[] {mockMixinSuperNodeType, mockMixinSuperNodeType});
when(mockMixinSuperNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockMixinSuperNodeTypeName);

final List<URI> types = testObj.getTypes();
assertTrue(types.contains(URI.create(REPOSITORY_NAMESPACE + mockPrimaryNodeTypeName)));
assertTrue(types.contains(URI.create(REPOSITORY_NAMESPACE + mockMixinNodeTypeName)));
assertTrue(types.contains(URI.create(REPOSITORY_NAMESPACE + mockPrimarySuperNodeTypeName)));
assertTrue(types.contains(URI.create(REPOSITORY_NAMESPACE + mockMixinSuperNodeTypeName)));
assertEquals(4, types.size());
}

@Test
public void testGetLastModifiedDateDefault() throws RepositoryException {
// test missing JCR_LASTMODIFIED
Expand Down
Expand Up @@ -34,10 +34,12 @@
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import static com.hp.hpl.jena.vocabulary.RDF.type;
import static org.fcrepo.kernel.api.RdfLexicon.JCR_NAMESPACE;
import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -98,33 +100,16 @@ public class TypeRdfContextTest {
@Before
public void setUp() throws RepositoryException {
initMocks(this);
when(mockResource.getNode()).thenReturn(mockNode);
when(mockNode.getPrimaryNodeType()).thenReturn(mockPrimaryNodeType);
when(mockPrimaryNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockPrimaryNodeTypeName);
final List<URI> types = new ArrayList<>();
types.add(URI.create(REPOSITORY_NAMESPACE + "somePrimaryType"));
types.add(URI.create(REPOSITORY_NAMESPACE + "someMixinType"));
types.add(URI.create(REPOSITORY_NAMESPACE + "somePrimarySuperType"));
types.add(URI.create(REPOSITORY_NAMESPACE + "someMixinSuperType"));

when(mockResource.getTypes()).thenReturn(types);
when(mockResource.getNode()).thenReturn(mockNode);
when(mockResource.getPath()).thenReturn("/" + mockNodeName);

when(mockNode.getMixinNodeTypes()).thenReturn(
new NodeType[]{mockMixinNodeType});
when(mockMixinNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockMixinNodeTypeName);

when(mockPrimaryNodeType.getSupertypes()).thenReturn(
new NodeType[]{mockPrimarySuperNodeType});
when(mockPrimarySuperNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockPrimarySuperNodeTypeName);

when(mockMixinNodeType.getSupertypes()).thenReturn(
new NodeType[] {mockMixinSuperNodeType});
when(mockMixinSuperNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockMixinSuperNodeTypeName);

when(mockNode.getSession()).thenReturn(mockSession);
when(mockSession.getRepository()).thenReturn(mockRepository);
when(mockSession.getWorkspace()).thenReturn(mockWorkspace);
when(mockWorkspace.getNamespaceRegistry()).thenReturn(mockNamespaceRegistry);
when(mockNamespaceRegistry.getURI("jcr")).thenReturn(JCR_NAMESPACE);
idTranslator = new DefaultIdentifierTranslator(mockSession);
}

Expand Down

0 comments on commit b03c4ea

Please sign in to comment.