001/**
002 * Copyright 2014 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.impl.rdf.impl;
017
018import com.google.common.base.Function;
019import com.google.common.base.Predicate;
020import com.google.common.collect.ImmutableList;
021import com.google.common.collect.Iterators;
022import com.hp.hpl.jena.rdf.model.Resource;
023import org.fcrepo.kernel.models.FedoraResource;
024import org.fcrepo.kernel.exception.RepositoryRuntimeException;
025import org.fcrepo.kernel.identifiers.IdentifierConverter;
026import org.fcrepo.kernel.impl.rdf.impl.mappings.PropertyValueIterator;
027import org.fcrepo.kernel.utils.iterators.PropertyIterator;
028import org.fcrepo.kernel.utils.iterators.RdfStream;
029
030import javax.jcr.Node;
031import javax.jcr.Property;
032import javax.jcr.PropertyType;
033import javax.jcr.RepositoryException;
034import javax.jcr.Value;
035import java.util.Iterator;
036
037import static javax.jcr.PropertyType.PATH;
038import static org.fcrepo.kernel.impl.identifiers.NodeResourceConverter.nodeConverter;
039import static org.fcrepo.kernel.impl.utils.FedoraTypesUtils.isBlankNode;
040
041/**
042 * Embed all blank nodes in the RDF stream
043 *
044 * @author cabeer
045 * @since 10/9/14
046 */
047public class BlankNodeRdfContext extends NodeRdfContext {
048
049    /**
050     * Default constructor.
051     *
052     * @param resource
053     * @param idTranslator
054     * @throws javax.jcr.RepositoryException
055     */
056    public BlankNodeRdfContext(final FedoraResource resource,
057                               final IdentifierConverter<Resource, FedoraResource> idTranslator)
058            throws RepositoryException {
059        super(resource, idTranslator);
060
061        concat(Iterators.concat(Iterators.transform(getBlankNodesIterator(), new Function<Node, RdfStream>() {
062            @Override
063            public RdfStream apply(final Node node) {
064                final FedoraResource resource = nodeConverter.convert(node);
065
066                return resource.getTriples(idTranslator, ImmutableList.of(TypeRdfContext.class,
067                        PropertiesRdfContext.class,
068                        BlankNodeRdfContext.class));
069            }
070        })));
071
072    }
073
074    private Iterator<Node> getBlankNodesIterator() throws RepositoryException {
075        final PropertyIterator properties = new PropertyIterator(resource().getNode().getProperties());
076
077        final Iterator<Property> references = Iterators.filter(properties, filterReferenceProperties);
078
079        final Iterator<Node> nodes = Iterators.transform(new PropertyValueIterator(references), getNodesForValue);
080
081        return Iterators.filter(nodes, isBlankNode);
082    }
083
084
085    private static final Predicate<Property> filterReferenceProperties = new Predicate<Property>() {
086        @Override
087        public boolean apply(final Property property) {
088            try {
089                final int type = property.getType();
090
091                return type == PropertyType.REFERENCE
092                        || type == PropertyType.WEAKREFERENCE
093                        || type == PropertyType.PATH;
094            } catch (final RepositoryException e) {
095                throw new RepositoryRuntimeException(e);
096            }
097        }
098    };
099
100    private final Function<Value, Node> getNodesForValue = new Function<Value, Node>() {
101        @Override
102        public Node apply(final Value v) {
103            try {
104                final Node refNode;
105
106                if (v.getType() == PATH) {
107                    refNode = resource().getNode().getSession().getNode(v.getString());
108                } else {
109                    refNode = resource().getNode().getSession().getNodeByIdentifier(v.getString());
110                }
111
112                return refNode;
113            } catch (final RepositoryException e) {
114                throw new RepositoryRuntimeException(e);
115            }
116        }
117    };
118
119}