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 com.hp.hpl.jena.rdf.model.Resource;
019
020import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
021import org.fcrepo.kernel.api.models.FedoraResource;
022import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
023import org.fcrepo.kernel.modeshape.rdf.impl.mappings.PropertyValueIterator;
024import org.slf4j.Logger;
025
026import javax.jcr.AccessDeniedException;
027import javax.jcr.Node;
028import javax.jcr.Property;
029import javax.jcr.RepositoryException;
030import javax.jcr.Session;
031import javax.jcr.Value;
032
033import java.util.Objects;
034import java.util.stream.Stream;
035import java.util.function.Function;
036
037import static org.fcrepo.kernel.api.RequiredRdfContext.PROPERTIES;
038import static org.fcrepo.kernel.modeshape.identifiers.NodeResourceConverter.nodeConverter;
039import static org.fcrepo.kernel.modeshape.rdf.converters.ValueConverter.nodeForValue;
040import static org.fcrepo.kernel.modeshape.rdf.impl.ReferencesRdfContext.REFERENCE_TYPES;
041import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.isSkolemNode;
042import static org.fcrepo.kernel.modeshape.utils.UncheckedPredicate.uncheck;
043import static org.fcrepo.kernel.modeshape.utils.StreamUtils.iteratorToStream;
044import static org.slf4j.LoggerFactory.getLogger;
045
046/**
047 * Embed triples describing all skolem nodes in the RDF stream
048 *
049 * @author cabeer
050 * @author ajs6f
051 * @since 10/9/14
052 */
053public class SkolemNodeRdfContext extends NodeRdfContext {
054
055    private static final Logger LOGGER = getLogger(SkolemNodeRdfContext.class);
056
057    /**
058     * Default constructor.
059     *
060     * @param resource the resource
061     * @param idTranslator the idTranslator
062     * @throws RepositoryException if a repository exception occurred
063     */
064    public SkolemNodeRdfContext(final FedoraResource resource,
065                               final IdentifierConverter<Resource, FedoraResource> idTranslator)
066            throws RepositoryException {
067        super(resource, idTranslator);
068
069        concat(getBlankNodes(resource).flatMap(n -> nodeConverter.convert(n).getTriples(idTranslator,
070                    PROPERTIES)));
071    }
072
073    @SuppressWarnings("unchecked")
074    private static Stream<Node> getBlankNodes(final FedoraResource resource) throws RepositoryException {
075        final Function<Value, Node> valueToNode = sessionValueToNode.apply(resource.getNode().getSession());
076        final Stream<Property> refs = iteratorToStream(resource.getNode().getProperties())
077                .filter(uncheck((final Property p) -> REFERENCE_TYPES.contains(p.getType())));
078        return iteratorToStream(new PropertyValueIterator(refs.iterator()))
079                .map(valueToNode)
080                .filter(Objects::nonNull)
081                .filter(isSkolemNode);
082    }
083
084    private static final Function<Session, Function<Value, Node>> sessionValueToNode = session -> v -> {
085        try {
086            return nodeForValue(session, v);
087
088        } catch (final AccessDeniedException e) {
089            LOGGER.error("Link inaccessible by requesting user: {}, {}", v, session.getUserID());
090            return null;
091
092        } catch (final RepositoryException e) {
093            throw new RepositoryRuntimeException(e);
094        }
095    };
096}