001/* 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.kernel.modeshape.rdf.impl; 017 018import static org.fcrepo.kernel.modeshape.identifiers.NodeResourceConverter.nodeConverter; 019import static org.fcrepo.kernel.modeshape.rdf.converters.ValueConverter.nodeForValue; 020import static org.fcrepo.kernel.modeshape.utils.UncheckedFunction.uncheck; 021import static org.fcrepo.kernel.modeshape.utils.StreamUtils.iteratorToStream; 022import static java.util.Arrays.asList; 023import static javax.jcr.PropertyType.PATH; 024import static javax.jcr.PropertyType.REFERENCE; 025import static javax.jcr.PropertyType.WEAKREFERENCE; 026 027import com.hp.hpl.jena.graph.Triple; 028import com.hp.hpl.jena.rdf.model.Resource; 029import org.fcrepo.kernel.api.identifiers.IdentifierConverter; 030import org.fcrepo.kernel.api.models.FedoraResource; 031import org.fcrepo.kernel.modeshape.rdf.impl.mappings.PropertyToTriple; 032import org.fcrepo.kernel.modeshape.rdf.impl.mappings.PropertyValueIterator; 033 034import javax.jcr.Node; 035import javax.jcr.Property; 036import javax.jcr.RepositoryException; 037import javax.jcr.Value; 038 039import java.util.List; 040import java.util.function.Predicate; 041import java.util.stream.Stream; 042 043/** 044 * Accumulate inbound references to a given resource 045 * 046 * @author cabeer 047 * @author escowles 048 */ 049public class ReferencesRdfContext extends NodeRdfContext { 050 051 private final PropertyToTriple property2triple; 052 053 public static final List<Integer> REFERENCE_TYPES = asList(PATH, REFERENCE, WEAKREFERENCE); 054 055 /** 056 * Add the inbound references from other nodes to this resource to the stream 057 * 058 * @param resource the resource 059 * @param idTranslator the id translator 060 * @throws RepositoryException if repository exception occurred 061 */ 062 063 public ReferencesRdfContext(final FedoraResource resource, 064 final IdentifierConverter<Resource, FedoraResource> idTranslator) 065 throws RepositoryException { 066 super(resource, idTranslator); 067 property2triple = new PropertyToTriple(resource.getNode().getSession(), idTranslator); 068 concat(putReferencesIntoContext(resource.getNode())); 069 } 070 071 private final Predicate<Triple> INBOUND = t -> { 072 return t.getObject().getURI().equals(uriFor(resource()).getURI()); 073 }; 074 075 /* References from LDP indirect containers are generated dynamically by LdpContainerRdfContext, so they won't 076 show up in getReferences()/getWeakReferences(). Instead, we should check referencers to see if they are 077 members of an IndirectContainer and generate the appropriate inbound references. */ 078 private Stream<Triple> putReferencesIntoContext(final Node node) throws RepositoryException { 079 return Stream.concat( 080 getAllReferences(node).flatMap(property2triple), 081 getAllReferences(node).flatMap(uncheck((final Property x) -> { 082 return iteratorToStream(new PropertyValueIterator(x.getParent().getProperties())) 083 .filter((final Value y) -> REFERENCE_TYPES.contains(y.getType())); 084 })) 085 .flatMap(uncheck((final Value x) -> { 086 return new LdpContainerRdfContext(nodeConverter.convert(nodeForValue(node.getSession(), x)), 087 translator()); 088 })) 089 .filter(INBOUND)); 090 } 091 092 @SuppressWarnings("unchecked") 093 private static Stream<Property> getAllReferences(final Node node) throws RepositoryException { 094 return Stream.concat(iteratorToStream(node.getReferences()), iteratorToStream(node.getWeakReferences())); 095 } 096}