Skip to content

Commit

Permalink
When storing a URI property that points to a fcrepo4 resource, also s…
Browse files Browse the repository at this point in the history
…tore a WEAKREFERENCE node to the same, so we can e.g. query against it easily.
  • Loading branch information
cbeer committed Nov 14, 2013
1 parent 1e052a1 commit 993bb63
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 24 deletions.
Expand Up @@ -146,7 +146,7 @@ public void addedStatement(final Statement s) {
jcrRdfTools.createValue(subjectNode, s.getObject(),
NodePropertiesTools.getPropertyType(subjectNode,
propertyName));
NodePropertiesTools.appendOrReplaceNodeProperty(subjectNode,
NodePropertiesTools.appendOrReplaceNodeProperty(subjects, subjectNode,
propertyName,
v);
}
Expand Down Expand Up @@ -220,7 +220,7 @@ public void removedStatement(final Statement s) {
jcrRdfTools.createValue(subjectNode, s.getObject(),
NodePropertiesTools.getPropertyType(subjectNode,
propertyName));
NodePropertiesTools.removeNodeProperty(subjectNode,
NodePropertiesTools.removeNodeProperty(subjects, subjectNode,
propertyName,
v);
}
Expand Down
Expand Up @@ -28,9 +28,14 @@
import javax.jcr.Value;
import javax.jcr.nodetype.PropertyDefinition;

import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import org.fcrepo.kernel.exception.NoSuchPropertyDefinitionException;
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.slf4j.Logger;

import static javax.jcr.PropertyType.URI;

/**
* Tools for replacing, appending and deleting JCR node properties
* @author Chris Beer
Expand All @@ -39,6 +44,7 @@
public abstract class NodePropertiesTools {

private static final Logger logger = getLogger(NodePropertiesTools.class);
public static final String REFERENCE_PROPERTY_SUFFIX = "_ref";

/**
* Given a JCR node, property and value, either:
Expand All @@ -51,7 +57,8 @@ public abstract class NodePropertiesTools {
* @param newValue the JCR value to insert
* @throws RepositoryException
*/
public static void appendOrReplaceNodeProperty(final Node node,
public static void appendOrReplaceNodeProperty(final GraphSubjects subjects,
final Node node,
final String propertyName,
final Value newValue)
throws RepositoryException {
Expand All @@ -76,15 +83,18 @@ public static void appendOrReplaceNodeProperty(final Node node,
property.setValue(newValues
.toArray(new Value[newValues.size()]));
}

addReferencePlaceholders(subjects, node, property, newValue);
} else {
// or we'll just overwrite it
logger.debug("Overwriting {} property {} with new value {}",
PropertyType.nameFromValue(property.getType()),
propertyName, newValue);
property.setValue(newValue);
addReferencePlaceholders(subjects, node, property, newValue);
}
} else {
boolean isMultiple = false;
boolean isMultiple = true;
try {
isMultiple = isMultivaluedProperty(node, propertyName);

Expand All @@ -96,18 +106,55 @@ public static void appendOrReplaceNodeProperty(final Node node,
"initial value [{}]",
PropertyType.nameFromValue(newValue.getType()),
propertyName, newValue);
node.setProperty(propertyName, new Value[]{newValue}, newValue.getType());
final Property property = node.setProperty(propertyName, new Value[]{newValue}, newValue.getType());
addReferencePlaceholders(subjects, node, property, newValue);
} else {
logger.debug("Creating new single-valued {} property {} with " +
"initial value {}",
PropertyType.nameFromValue(newValue.getType()),
propertyName, newValue);
node.setProperty(propertyName, newValue, newValue.getType());
final Property property = node.setProperty(propertyName, newValue, newValue.getType());
addReferencePlaceholders(subjects, node, property, newValue);
}
}

}

private static void addReferencePlaceholders(final GraphSubjects subjects, final Node node, final Property property, final Value newValue) throws RepositoryException {
if (property.getType() == URI) {
final Resource resource = ResourceFactory.createResource(newValue.getString());

if (subjects.isFedoraGraphSubject(resource)) {
final Node refNode = subjects.getNodeFromGraphSubject(resource);
final String referencePropertyName = getReferencePropertyName(property);

if (!property.isMultiple() && node.hasProperty(referencePropertyName)) {
node.setProperty(referencePropertyName, (Value[])null);
}

final Value v = node.getSession().getValueFactory().createValue(refNode, true);
appendOrReplaceNodeProperty(subjects, node, referencePropertyName, v);
}
}
}

private static void removeReferencePlaceholders(final GraphSubjects subjects, final Node node, final Property property, final Value newValue) throws RepositoryException {
if (property.getType() == URI) {
final Resource resource = ResourceFactory.createResource(newValue.getString());

if (subjects.isFedoraGraphSubject(resource)) {
final String referencePropertyName = getReferencePropertyName(property);

if (!property.isMultiple() && node.hasProperty(referencePropertyName)) {
node.setProperty(referencePropertyName, (Value[])null);
} else {
final Node refNode = subjects.getNodeFromGraphSubject(resource);
final Value v = node.getSession().getValueFactory().createValue(refNode, true);
removeNodeProperty(subjects, node, referencePropertyName, v);
}
}
}
}
/**
* Given a JCR node, property and value, remove the value (if it exists)
* from the property, and remove the
Expand All @@ -119,7 +166,8 @@ public static void appendOrReplaceNodeProperty(final Node node,
* @param valueToRemove the JCR value to remove
* @throws RepositoryException
*/
public static void removeNodeProperty(final Node node,
public static void removeNodeProperty(final GraphSubjects subjects,
final Node node,
final String propertyName,
final Value valueToRemove)
throws RepositoryException {
Expand Down Expand Up @@ -154,17 +202,34 @@ public static void removeNodeProperty(final Node node,
.setValue(newValues
.toArray(new Value[newValues.size()]));
}
removeReferencePlaceholders(subjects, node, property, valueToRemove);
}

} else {
if (property.getValue().equals(valueToRemove)) {
logger.debug("Removing value {} property {}", propertyName);
property.setValue((Value)null);

if (property.getType() == URI && node.hasProperty(getReferencePropertyName(propertyName))) {
removeReferencePlaceholders(subjects, node, property, valueToRemove);
}
}
}
}
}

/**
* When we add certain URI properties, we also want to leave a reference node
* @param propertyName
* @return
*/
public static String getReferencePropertyName(final String propertyName) {
return propertyName + REFERENCE_PROPERTY_SUFFIX;
}

private static String getReferencePropertyName(final Property property) throws RepositoryException {
return getReferencePropertyName(property.getName());
}
/**
* Get the JCR property type ID for a given property name. If unsure, mark
* it as UNDEFINED.
Expand Down
Expand Up @@ -91,6 +91,6 @@ protected void operateOnProperty(final Statement t, final Node n) throws Reposit
getPropertyNameFromPredicate(n, t.getPredicate());
final Value v =
createValue(n, t.getObject(), getPropertyType(n, propertyName));
appendOrReplaceNodeProperty(n, propertyName, v);
appendOrReplaceNodeProperty(idTranslator(), n, propertyName, v);
}
}
Expand Up @@ -83,7 +83,7 @@ protected void operateOnProperty(final Statement t, final Node n)
final Value v =
jcrRdfTools().createValue(n, t.getObject(), getPropertyType(n,
propertyName));
removeNodeProperty(n, propertyName, v);
removeNodeProperty(idTranslator(), n, propertyName, v);
}
}
}
Expand Up @@ -125,7 +125,7 @@ public void testObjectGraph() throws Exception {
final Value value =
object.getNode().getProperty(object.getNode().getSession()
.getNamespacePrefix("info:myurn/") +
":info").getValue();
":info").getValues()[0];

assertEquals("This is some example data", value.getString());

Expand Down Expand Up @@ -160,4 +160,38 @@ public void testObjectGraph() throws Exception {
session.save();

}

@Test
public void testObjectGraphWithUriProperty() throws RepositoryException {
final Session session = repo.login();
final FedoraObject object =
objectService.createObject(session, "/graphObject");
final String graphSubject = RESTAPI_NAMESPACE + "/graphObject";
final Dataset graphStore = object.getPropertiesDataset(new DefaultGraphSubjects(session));

parseExecute("PREFIX some: <info:some#>\n" +
"INSERT { <" + graphSubject + "> some:urlProperty " +
"<" + graphSubject + "> } WHERE {}", graphStore);

final String prefix = session.getWorkspace().getNamespaceRegistry().getPrefix("info:some#");

assertNotNull(object.getNode().getProperty(prefix + ":urlProperty"));

assertEquals(object.getNode(), session.getNodeByIdentifier(object.getNode().getProperty(prefix + ":urlProperty_ref").getValues()[0].getString()));

parseExecute("PREFIX some: <info:some#>\n" +
"DELETE { <" + graphSubject + "> some:urlProperty " +
"<" + graphSubject + "> } WHERE {}", graphStore);

assertFalse(object.getNode().hasProperty(prefix + ":urlProperty_ref"));


parseExecute("PREFIX some: <info:some#>\n" +
"INSERT DATA { <" + graphSubject + "> some:urlProperty <" + graphSubject + ">;\n" +
" some:urlProperty <info:somewhere/else> . }", graphStore);

assertEquals(1, object.getNode().getProperty(prefix + ":urlProperty_ref").getValues().length);
assertEquals(object.getNode(), session.getNodeByIdentifier(object.getNode().getProperty(prefix + ":urlProperty_ref").getValues()[0].getString()));

}
}
Expand Up @@ -448,7 +448,7 @@ public void testUpdatingRdfTypedValues() throws RepositoryException {
assertEquals(LONG, object.getNode().getProperty("example:int-property")
.getType());
assertEquals(0L, object.getNode().getProperty("example:int-property")
.getValue().getLong());
.getValues()[0].getLong());
}

@Test
Expand All @@ -467,7 +467,7 @@ public void testUpdatingRdfType() throws RepositoryException {
assertEquals(PropertyType.URI, object.getNode().getProperty("rdf:type")
.getType());
assertEquals("http://some/uri", object.getNode()
.getProperty("rdf:type").getValue().getString());
.getProperty("rdf:type").getValues()[0].getString());
}

@Test
Expand Down

0 comments on commit 993bb63

Please sign in to comment.