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.api.utils.UncheckedFunction.uncheck; 019import static org.fcrepo.kernel.modeshape.identifiers.NodeResourceConverter.nodeConverter; 020import static org.fcrepo.kernel.modeshape.rdf.converters.ValueConverter.nodeForValue; 021import static java.util.Arrays.asList; 022import static javax.jcr.PropertyType.PATH; 023import static javax.jcr.PropertyType.REFERENCE; 024import static javax.jcr.PropertyType.WEAKREFERENCE; 025 026import com.google.common.collect.Iterators; 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.Iterator; 040import java.util.List; 041import java.util.function.Function; 042import java.util.function.Predicate; 043 044/** 045 * Accumulate inbound references to a given resource 046 * 047 * @author cabeer 048 * @author escowles 049 */ 050public class ReferencesRdfContext extends NodeRdfContext { 051 052 private final PropertyToTriple property2triple; 053 054 public static final List<Integer> REFERENCE_TYPES = asList(PATH, REFERENCE, WEAKREFERENCE); 055 056 /** 057 * Add the inbound references from other nodes to this resource to the stream 058 * 059 * @param resource the resource 060 * @param idTranslator the id translator 061 * @throws RepositoryException if repository exception occurred 062 */ 063 064 public ReferencesRdfContext(final FedoraResource resource, 065 final IdentifierConverter<Resource, FedoraResource> idTranslator) 066 throws RepositoryException { 067 super(resource, idTranslator); 068 property2triple = new PropertyToTriple(resource.getNode().getSession(), idTranslator); 069 putReferencesIntoContext(resource.getNode()); 070 } 071 072 private final Predicate<Triple> INBOUND = t -> { 073 return t.getObject().getURI().equals(uriFor(resource()).getURI()); 074 }; 075 076 @SuppressWarnings("unchecked") 077 private void putReferencesIntoContext(final Node node) throws RepositoryException { 078 Iterator<Property> references = node.getReferences(); 079 Iterator<Property> weakReferences = node.getWeakReferences(); 080 Iterator<Property> allReferences = Iterators.concat(references, weakReferences); 081 concat(flatMap(allReferences, property2triple)); 082 083 references = node.getReferences(); 084 weakReferences = node.getWeakReferences(); 085 allReferences = Iterators.concat(references, weakReferences); 086 concat(Iterators.filter(flatMap(flatMap( allReferences, potentialProxies), triplesForValue), INBOUND::test)); 087 } 088 089 /* References from LDP indirect containers are generated dynamically by LdpContainerRdfContext, so they won't 090 show up in getReferences()/getWeakReferences(). Instead, we should check referencers to see if they are 091 members of an IndirectContainer and generate the appropriate inbound references. */ 092 @SuppressWarnings("unchecked") 093 private final Function<Property, Iterator<Value>> potentialProxies = uncheck(p -> Iterators.filter( 094 new PropertyValueIterator(p.getParent().getProperties()), v -> REFERENCE_TYPES.contains(v.getType()))); 095 096 private final Function<Value, Iterator<Triple>> triplesForValue = uncheck(v -> 097 new LdpContainerRdfContext(nodeConverter.convert(nodeForValue(session(), v)), translator())); 098}