001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.kernel.modeshape.rdf.impl;
019
020import static com.hp.hpl.jena.graph.NodeFactory.createLiteral;
021import static com.hp.hpl.jena.graph.Triple.create;
022import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
023import static com.hp.hpl.jena.rdf.model.ResourceFactory.createTypedLiteral;
024import static org.fcrepo.kernel.api.FedoraTypes.FCR_VERSIONS;
025import static org.fcrepo.kernel.api.RdfLexicon.CREATED_DATE;
026import static org.fcrepo.kernel.api.RdfLexicon.HAS_VERSION;
027import static org.fcrepo.kernel.api.RdfLexicon.HAS_VERSION_LABEL;
028import static org.fcrepo.kernel.modeshape.utils.StreamUtils.iteratorToStream;
029import static org.fcrepo.kernel.modeshape.utils.UncheckedPredicate.uncheck;
030import static org.slf4j.LoggerFactory.getLogger;
031
032import java.util.Arrays;
033import java.util.stream.Stream;
034
035import javax.jcr.RepositoryException;
036import javax.jcr.version.Version;
037import javax.jcr.version.VersionHistory;
038import com.hp.hpl.jena.rdf.model.Resource;
039
040import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
041import org.fcrepo.kernel.api.models.FedoraResource;
042import org.fcrepo.kernel.api.rdf.DefaultRdfStream;
043import org.fcrepo.kernel.modeshape.utils.UncheckedFunction;
044
045import com.hp.hpl.jena.graph.Node;
046import com.hp.hpl.jena.graph.Triple;
047
048import org.slf4j.Logger;
049
050
051/**
052 * {@link org.fcrepo.kernel.api.RdfStream} that supplies {@link Triple}s concerning
053 * the versions of a selected {@link Node}.
054 *
055 * @author ajs6f
056 * @since Oct 15, 2013
057 */
058public class VersionsRdfContext extends DefaultRdfStream {
059
060    private final VersionHistory versionHistory;
061
062    private static final Logger LOGGER = getLogger(VersionsRdfContext.class);
063
064    /**
065     * Ordinary constructor.
066     *
067     * @param resource the resource
068     * @param idTranslator the id translator
069     * @throws RepositoryException if repository exception occurred
070     */
071    public VersionsRdfContext(final FedoraResource resource,
072                              final IdentifierConverter<Resource, FedoraResource> idTranslator)
073        throws RepositoryException {
074        super(idTranslator.reverse().convert(resource).asNode());
075        this.versionHistory = resource.getVersionHistory();
076        concat(versionTriples());
077    }
078
079    @SuppressWarnings("unchecked")
080    private Stream<Triple> versionTriples() throws RepositoryException {
081        return iteratorToStream(versionHistory.getAllVersions())
082            /* Discard jcr:rootVersion */
083            .filter(uncheck((final Version v) -> !v.getName().equals(versionHistory.getRootVersion().getName())))
084            /* Omit unlabelled versions */
085            .filter(uncheck((final Version v) -> {
086                final String[] labels = versionHistory.getVersionLabels(v);
087                if (labels.length == 0) {
088                    LOGGER.warn("An unlabeled version for {} was found!  Omitting from version listing!",
089                        topic().getURI());
090                } else if (labels.length > 1) {
091                    LOGGER.info("Multiple version labels found for {}!  Using first label, \"{}\".", topic().getURI());
092                }
093                return labels.length > 0;
094            }))
095            .flatMap(UncheckedFunction.uncheck((final Version v) -> {
096                final String[] labels = versionHistory.getVersionLabels(v);
097                final Node versionSubject
098                        = createProperty(topic() + "/" + FCR_VERSIONS + "/" + labels[0]).asNode();
099
100                return Stream.concat(
101                        Arrays.stream(labels).map(x -> create(versionSubject, HAS_VERSION_LABEL.asNode(),
102                                createLiteral(x))),
103
104                        Stream.of(create(topic(), HAS_VERSION.asNode(), versionSubject),
105                            create(versionSubject, CREATED_DATE.asNode(),
106                                createTypedLiteral(v.getCreated()).asNode())));
107            }));
108    }
109}