/* * Licensed to DuraSpace under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * DuraSpace licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fcrepo.kernel.modeshape.rdf.impl; import static org.fcrepo.kernel.modeshape.identifiers.NodeResourceConverter.nodeConverter; import static org.fcrepo.kernel.modeshape.rdf.converters.ValueConverter.nodeForValue; import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode; import static org.fcrepo.kernel.modeshape.utils.StreamUtils.iteratorToStream; import static org.fcrepo.kernel.modeshape.utils.UncheckedFunction.uncheck; import static java.util.Arrays.asList; import static javax.jcr.PropertyType.PATH; import static javax.jcr.PropertyType.REFERENCE; import static javax.jcr.PropertyType.WEAKREFERENCE; import org.apache.jena.graph.Triple; import org.apache.jena.rdf.model.Resource; import org.fcrepo.kernel.api.identifiers.IdentifierConverter; import org.fcrepo.kernel.api.models.FedoraResource; import org.fcrepo.kernel.modeshape.rdf.impl.mappings.PropertyToTriple; import org.fcrepo.kernel.modeshape.rdf.impl.mappings.PropertyValueIterator; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.RepositoryException; import javax.jcr.Value; import java.util.List; import java.util.function.Predicate; import java.util.stream.Stream; /** * Accumulate inbound references to a given resource * * @author cabeer * @author escowles */ public class ReferencesRdfContext extends NodeRdfContext { private final PropertyToTriple property2triple; public static final List<Integer> REFERENCE_TYPES = asList(PATH, REFERENCE, WEAKREFERENCE); /** * Add the inbound references from other nodes to this resource to the stream * * @param resource the resource * @param idTranslator the id translator * @throws RepositoryException if repository exception occurred */ public ReferencesRdfContext(final FedoraResource resource, final IdentifierConverter<Resource, FedoraResource> idTranslator) throws RepositoryException { super(resource, idTranslator); property2triple = new PropertyToTriple(getJcrNode(resource).getSession(), idTranslator); concat(putReferencesIntoContext(getJcrNode(resource))); } private final Predicate<Triple> INBOUND = t -> { return t.getObject().getURI().equals(uriFor(resource()).getURI()); }; /* References from LDP indirect containers are generated dynamically by LdpContainerRdfContext, so they won't show up in getReferences()/getWeakReferences(). Instead, we should check referencers to see if they are members of an IndirectContainer and generate the appropriate inbound references. */ private Stream<Triple> putReferencesIntoContext(final Node node) throws RepositoryException { return Stream.concat( getAllReferences(node).flatMap(property2triple), getAllReferences(node).flatMap(uncheck((final Property x) -> { @SuppressWarnings("unchecked") final Stream<Value> values = iteratorToStream(new PropertyValueIterator(x.getParent() .getProperties())).filter((final Value y) -> REFERENCE_TYPES.contains(y.getType())); return values; })) .flatMap(uncheck((final Value x) -> { return new LdpContainerRdfContext(nodeConverter.convert(nodeForValue(node.getSession(), x)), translator()); })) .filter(INBOUND)); } @SuppressWarnings("unchecked") private static Stream<Property> getAllReferences(final Node node) throws RepositoryException { return Stream.concat(iteratorToStream(node.getReferences()), iteratorToStream(node.getWeakReferences())); } }