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