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 com.hp.hpl.jena.graph.NodeFactory.createLiteral;
019import static com.hp.hpl.jena.graph.Triple.create;
020import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
021import static com.hp.hpl.jena.rdf.model.ResourceFactory.createTypedLiteral;
022import static org.fcrepo.kernel.api.FedoraTypes.FCR_VERSIONS;
023import static org.fcrepo.kernel.api.RdfLexicon.CREATED_DATE;
024import static org.fcrepo.kernel.api.RdfLexicon.HAS_VERSION;
025import static org.fcrepo.kernel.api.RdfLexicon.HAS_VERSION_LABEL;
026import static org.fcrepo.kernel.modeshape.utils.StreamUtils.iteratorToStream;
027import static org.fcrepo.kernel.modeshape.utils.UncheckedPredicate.uncheck;
028import static org.slf4j.LoggerFactory.getLogger;
029
030import java.util.Arrays;
031import java.util.stream.Stream;
032
033import javax.jcr.RepositoryException;
034import javax.jcr.version.Version;
035import javax.jcr.version.VersionHistory;
036import com.hp.hpl.jena.rdf.model.Resource;
037
038import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
039import org.fcrepo.kernel.api.models.FedoraResource;
040import org.fcrepo.kernel.api.rdf.DefaultRdfStream;
041import org.fcrepo.kernel.modeshape.utils.UncheckedFunction;
042
043import com.hp.hpl.jena.graph.Node;
044import com.hp.hpl.jena.graph.Triple;
045
046import org.slf4j.Logger;
047
048
049/**
050 * {@link org.fcrepo.kernel.api.RdfStream} that supplies {@link Triple}s concerning
051 * the versions of a selected {@link Node}.
052 *
053 * @author ajs6f
054 * @since Oct 15, 2013
055 */
056public class VersionsRdfContext extends DefaultRdfStream {
057
058    private final VersionHistory versionHistory;
059
060    private static final Logger LOGGER = getLogger(VersionsRdfContext.class);
061
062    /**
063     * Ordinary constructor.
064     *
065     * @param resource the resource
066     * @param idTranslator the id translator
067     * @throws RepositoryException if repository exception occurred
068     */
069    public VersionsRdfContext(final FedoraResource resource,
070                              final IdentifierConverter<Resource, FedoraResource> idTranslator)
071        throws RepositoryException {
072        super(idTranslator.reverse().convert(resource).asNode());
073        this.versionHistory = resource.getVersionHistory();
074        concat(versionTriples());
075    }
076
077    @SuppressWarnings("unchecked")
078    private Stream<Triple> versionTriples() throws RepositoryException {
079        return iteratorToStream(versionHistory.getAllVersions())
080            /* Discard jcr:rootVersion */
081            .filter(uncheck((final Version v) -> !v.getName().equals(versionHistory.getRootVersion().getName())))
082            /* Omit unlabelled versions */
083            .filter(uncheck((final Version v) -> {
084                final String[] labels = versionHistory.getVersionLabels(v);
085                if (labels.length == 0) {
086                    LOGGER.warn("An unlabeled version for {} was found!  Omitting from version listing!",
087                        topic().getURI());
088                } else if (labels.length > 1) {
089                    LOGGER.info("Multiple version labels found for {}!  Using first label, \"{}\".", topic().getURI());
090                }
091                return labels.length > 0;
092            }))
093            .flatMap(UncheckedFunction.uncheck((final Version v) -> {
094                final String[] labels = versionHistory.getVersionLabels(v);
095                final Node versionSubject
096                        = createProperty(topic() + "/" + FCR_VERSIONS + "/" + labels[0]).asNode();
097
098                return Stream.concat(
099                        Arrays.stream(labels).map(x -> create(versionSubject, HAS_VERSION_LABEL.asNode(),
100                                createLiteral(x))),
101
102                        Stream.of(create(topic(), HAS_VERSION.asNode(), versionSubject),
103                            create(versionSubject, CREATED_DATE.asNode(),
104                                createTypedLiteral(v.getCreated()).asNode())));
105            }));
106    }
107}