-
Notifications
You must be signed in to change notification settings - Fork 130
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
Applied code changes to fresh clone. #596
Changes from 1 commit
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 |
---|---|---|
|
@@ -15,14 +15,18 @@ | |
*/ | ||
package org.fcrepo.http.api.responses; | ||
|
||
import static com.google.common.collect.ImmutableMap.builder; | ||
import static com.hp.hpl.jena.graph.Node.ANY; | ||
import static javax.ws.rs.core.MediaType.APPLICATION_XHTML_XML; | ||
import static javax.ws.rs.core.MediaType.APPLICATION_XHTML_XML_TYPE; | ||
import static javax.ws.rs.core.MediaType.TEXT_HTML; | ||
import static javax.ws.rs.core.MediaType.TEXT_HTML_TYPE; | ||
import static org.apache.commons.lang.StringUtils.isBlank; | ||
import static org.fcrepo.http.commons.responses.RdfSerializationUtils.getAllValuesForPredicate; | ||
import static org.fcrepo.http.commons.responses.RdfSerializationUtils.getFirstValueForPredicate; | ||
import static org.fcrepo.http.commons.responses.RdfSerializationUtils.mixinTypesPredicate; | ||
import static org.fcrepo.http.commons.responses.RdfSerializationUtils.primaryTypePredicate; | ||
import static com.google.common.collect.ImmutableList.copyOf; | ||
import static com.google.common.collect.ImmutableMap.builder; | ||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
import java.io.IOException; | ||
|
@@ -33,13 +37,17 @@ | |
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Type; | ||
import java.net.URL; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Properties; | ||
|
||
import javax.annotation.PostConstruct; | ||
import javax.jcr.RepositoryException; | ||
import javax.jcr.Session; | ||
import javax.jcr.nodetype.NodeType; | ||
import javax.jcr.nodetype.NodeTypeIterator; | ||
import javax.ws.rs.Produces; | ||
import javax.ws.rs.WebApplicationException; | ||
|
@@ -49,8 +57,10 @@ | |
import javax.ws.rs.ext.MessageBodyWriter; | ||
import javax.ws.rs.ext.Provider; | ||
|
||
import com.google.common.base.Predicate; | ||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.ImmutableMap; | ||
import com.google.common.collect.Iterables; | ||
import com.hp.hpl.jena.graph.Node; | ||
import com.hp.hpl.jena.rdf.model.Model; | ||
import org.apache.velocity.Template; | ||
|
@@ -109,6 +119,27 @@ public class StreamingBaseHtmlProvider implements MessageBodyWriter<RdfStream> { | |
private static final Logger LOGGER = | ||
getLogger(StreamingBaseHtmlProvider.class); | ||
|
||
protected final Predicate<NodeType> acceptWhenTemplateExists = new Predicate<NodeType>() { | ||
@Override | ||
public boolean apply(final NodeType nodeType) { | ||
final String nodeTypeName = nodeType.getName(); | ||
if (isBlank(nodeTypeName)) { | ||
return false; | ||
} | ||
return velocity.resourceExists(getTemplateLocation(nodeTypeName)); | ||
} | ||
}; | ||
|
||
protected final Predicate<String> acceptWhenTemplateMapContainsKey = new Predicate<String>() { | ||
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. Change from |
||
@Override | ||
public boolean apply(final String key) { | ||
if (isBlank(key)) { | ||
return false; | ||
} | ||
return templatesMap.containsKey(key); | ||
} | ||
}; | ||
|
||
@PostConstruct | ||
void init() throws IOException { | ||
|
||
|
@@ -127,29 +158,28 @@ void init() throws IOException { | |
final ImmutableMap.Builder<String, Template> templatesMapBuilder = builder(); | ||
final Session session = sessionFactory.getInternalSession(); | ||
try { | ||
// we search all of the possible node primary types | ||
// we search all of the possible node primary types and mixins | ||
for (final NodeTypeIterator primaryNodeTypes = | ||
session.getWorkspace().getNodeTypeManager() | ||
.getPrimaryNodeTypes(); primaryNodeTypes.hasNext();) { | ||
final NodeType primaryNodeType = | ||
primaryNodeTypes.nextNodeType(); | ||
final String primaryNodeTypeName = | ||
primaryNodeTypes.nextNodeType().getName(); | ||
// for each node primary type, we try to find a template | ||
final String templateLocation = | ||
templatesLocation + "/" + | ||
primaryNodeTypeName.replace(':', '-') + | ||
templateFilenameExtension; | ||
if (velocity.resourceExists(templateLocation)) { | ||
final Template template = | ||
velocity.getTemplate(templateLocation); | ||
template.setName(templateLocation); | ||
LOGGER.debug("Found template: {}", templateLocation); | ||
templatesMapBuilder.put(primaryNodeTypeName, template); | ||
LOGGER.debug("which we will use for nodes with primary type: {}", | ||
primaryNodeTypeName); | ||
primaryNodeType.getName(); | ||
|
||
// Create a list of the primary type and all its parents | ||
final List<NodeType> nodeTypesList = new ArrayList<NodeType>(); | ||
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. Change from: |
||
nodeTypesList.add(primaryNodeType); | ||
nodeTypesList.addAll(Arrays.asList(primaryNodeType.getSupertypes())); | ||
|
||
// Find a template that matches the primary type or one of its parents | ||
final NodeType templateMatch = Iterables.find(nodeTypesList, acceptWhenTemplateExists, null); | ||
if (templateMatch != null) { | ||
addTemplate(primaryNodeTypeName, templateMatch.getName(), templatesMapBuilder); | ||
} else { | ||
// No HTML representation available for that kind of node | ||
LOGGER.debug("Didn't find template for nodes with primary type: {} in location: {}", | ||
primaryNodeTypeName, templateLocation); | ||
LOGGER.debug("Didn't find template for nodes with primary type or its parents: {} in location: {}", | ||
primaryNodeTypeName, templatesLocation); | ||
} | ||
} | ||
|
||
|
@@ -158,9 +188,7 @@ void init() throws IOException { | |
|
||
for (final String key : otherTemplates) { | ||
final Template template = | ||
velocity.getTemplate(templatesLocation + "/" + | ||
key.replace(':', '-') + | ||
templateFilenameExtension); | ||
velocity.getTemplate(getTemplateLocation(key)); | ||
templatesMapBuilder.put(key, template); | ||
} | ||
|
||
|
@@ -235,6 +263,23 @@ private Template getTemplate(final Model rdf, final Node subject, | |
} | ||
} | ||
|
||
if (template == null) { | ||
LOGGER.trace("Attempting to discover the mixin types of the node for the resource in question..."); | ||
final Iterator<String> mixinTypes = | ||
getAllValuesForPredicate(rdf, subject, | ||
mixinTypesPredicate); | ||
|
||
LOGGER.debug("Found mixins: {}", mixinTypes); | ||
if (mixinTypes != null) { | ||
final ImmutableList<String> copy = copyOf(mixinTypes); | ||
final String mixin = Iterables.find(copy, acceptWhenTemplateMapContainsKey, null); | ||
if (mixin != null) { | ||
LOGGER.debug("Matched mixin type: {}", mixin); | ||
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. When I run the test with a debugger (or simply look for the debug statement here "Matched mixin type"), this block is not being executed... which is one of the main reasons for this PR. |
||
template = templatesMap.get(mixin); | ||
} | ||
} | ||
} | ||
|
||
if (template == null) { | ||
LOGGER.trace("Attempting to discover the primary type of the node for the resource in question..."); | ||
final String nodeType = | ||
|
@@ -271,4 +316,21 @@ public long getSize(final RdfStream t, final Class<?> type, | |
// we don't know in advance how large the result might be | ||
return -1; | ||
} | ||
|
||
private void addTemplate(final String primaryNodeTypeName, final String templateNodeTypeName, | ||
final ImmutableMap.Builder<String, Template> templatesMapBuilder) { | ||
final String templateLocation = getTemplateLocation(templateNodeTypeName); | ||
final Template template = | ||
velocity.getTemplate(templateLocation); | ||
template.setName(templateLocation); | ||
LOGGER.debug("Found template: {}", templateLocation); | ||
templatesMapBuilder.put(primaryNodeTypeName, template); | ||
LOGGER.debug("which we will use for nodes with primary type: {}", | ||
primaryNodeTypeName); | ||
} | ||
|
||
private String getTemplateLocation(final String nodeTypeName) { | ||
return templatesLocation + "/" + | ||
nodeTypeName.replace(':', '-') + templateFilenameExtension; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,6 +71,7 @@ public class StreamingBaseHtmlProviderTest { | |
private final StreamingBaseHtmlProvider testProvider = new StreamingBaseHtmlProvider(); | ||
|
||
private final RdfStream testData = new RdfStream(); | ||
private final RdfStream testData2 = new RdfStream(); | ||
|
||
@Mock | ||
private Session mockSession; | ||
|
@@ -93,13 +94,18 @@ public void setup() throws RepositoryException { | |
testData.session(mockSession); | ||
testData.topic(createURI("test:subject")); | ||
testData.concat( | ||
new Triple(createURI("test:subject"), | ||
new Triple(createURI("test:subject"), | ||
createURI("test:predicate"), | ||
createLiteral("test:object"))); | ||
testData.concat( | ||
new Triple(createURI("test:subject"), primaryTypePredicate, | ||
createLiteral("nt:file"))); | ||
|
||
testData2.session(mockSession); | ||
testData2.topic(createURI("test:subject2")); | ||
testData2.concat( | ||
new Triple(createURI("test:subject2"), primaryTypePredicate, | ||
createLiteral("childOf:ntFile"))); | ||
final UriInfo info = Mockito.mock(UriInfo.class); | ||
setField(testProvider, "uriInfo", info); | ||
} | ||
|
@@ -180,4 +186,31 @@ public Object answer(final InvocationOnMock invocation) { | |
assertTrue("Got no output from serialization!", results.length > 0); | ||
|
||
} | ||
|
||
@SuppressWarnings({"unchecked", "rawtypes"}) | ||
@Test | ||
public void testWriteToWithParentTemplate() throws WebApplicationException, | ||
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. Ideally, this test would exercise the block in StreamingBaseHtmlProvider.getTemplate():
However, the test as written results in 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. I changed the predicate of testData2 to mixinTypesPredicate (line 108 above) so the mixin is found here. |
||
IllegalArgumentException, IOException { | ||
final Template mockTemplate = mock(Template.class); | ||
final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); | ||
|
||
doAnswer(new Answer<Object>() { | ||
|
||
@Override | ||
public Object answer(final InvocationOnMock invocation) { | ||
outStream.write("abcdefighijk".getBytes(), 0, 10); | ||
return "I am pretending to merge a template for you."; | ||
} | ||
}).when(mockTemplate).merge(isA(Context.class), isA(Writer.class)); | ||
|
||
setField(testProvider, "templatesMap", | ||
of("childOf:ntFile", mockTemplate, | ||
"grandchildOf:ntFile", mockTemplate)); | ||
testProvider.writeTo(testData2, RdfStream.class, mock(Type.class), | ||
new Annotation[] {}, MediaType | ||
.valueOf("text/html"), | ||
(MultivaluedMap) new MultivaluedHashMap<>(), outStream); | ||
final byte[] results = outStream.toByteArray(); | ||
assertTrue("Got no output from serialization!", results.length > 0); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,19 +15,25 @@ | |
*/ | ||
package org.fcrepo.http.commons.responses; | ||
|
||
import static com.google.common.collect.ImmutableList.copyOf; | ||
import static com.google.common.collect.Iterables.transform; | ||
import static com.hp.hpl.jena.graph.NodeFactory.createURI; | ||
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty; | ||
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource; | ||
import static org.fcrepo.kernel.RdfLexicon.JCR_NAMESPACE; | ||
import static org.fcrepo.kernel.impl.rdf.JcrRdfTools.getRDFNamespaceForJcrNamespace; | ||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
import java.util.Iterator; | ||
|
||
import com.google.common.base.Function; | ||
import com.google.common.collect.ImmutableList; | ||
import com.hp.hpl.jena.graph.Node; | ||
import com.hp.hpl.jena.rdf.model.Model; | ||
import com.hp.hpl.jena.rdf.model.NodeIterator; | ||
import com.hp.hpl.jena.rdf.model.RDFNode; | ||
import org.slf4j.Logger; | ||
|
||
import com.hp.hpl.jena.graph.Node; | ||
|
||
/** | ||
* Utilities to help with serializing a graph to an HTTP resource | ||
* | ||
|
@@ -50,6 +56,18 @@ private RdfSerializationUtils() { | |
createURI(getRDFNamespaceForJcrNamespace(JCR_NAMESPACE) + | ||
"primaryType"); | ||
|
||
/** | ||
* The RDF predicate that will indicate the mixin types. | ||
*/ | ||
public static Node mixinTypesPredicate = | ||
createURI(getRDFNamespaceForJcrNamespace(JCR_NAMESPACE) + | ||
"mixinTypes"); | ||
|
||
public static final Function<RDFNode, String> stringConverter = new Function<RDFNode, String>() { | ||
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. This function should be |
||
public String apply(final RDFNode statement) { | ||
return statement.asLiteral().getLexicalForm(); | ||
} | ||
}; | ||
|
||
/** | ||
* Get the very first value for a predicate as a string, or null if the | ||
|
@@ -72,4 +90,23 @@ public static String getFirstValueForPredicate(final Model rdf, | |
return null; | ||
} | ||
|
||
/** | ||
* Get all the values for a predicate as a string array, or null if the | ||
* predicate is not used | ||
* | ||
* @param rdf | ||
* @param subject | ||
* @param predicate | ||
* @return first value for the given predicate or null if not found | ||
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. Documentation should read: |
||
*/ | ||
public static Iterator<String> getAllValuesForPredicate(final Model rdf, | ||
final Node subject, final Node predicate) { | ||
final NodeIterator statements = | ||
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. As a point of readability/clarity, this NodeIterator is actually an iterator of "objects" not "statements". |
||
rdf.listObjectsOfProperty(createResource(subject.getURI()), | ||
createProperty(predicate.getURI())); | ||
|
||
final ImmutableList<RDFNode> copy = copyOf(statements); | ||
return transform(copy, stringConverter).iterator(); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change from
protected
toprivate
.