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 org.apache.jena.graph.Triple;
021import org.apache.jena.rdf.model.Resource;
022
023import org.fcrepo.kernel.api.models.FedoraResource;
024import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
025import org.fcrepo.kernel.modeshape.rdf.converters.ValueConverter;
026import org.fcrepo.kernel.modeshape.rdf.impl.mappings.PropertyValueIterator;
027import org.fcrepo.kernel.modeshape.utils.UncheckedFunction;
028import org.fcrepo.kernel.modeshape.utils.UncheckedPredicate;
029
030import org.slf4j.Logger;
031
032import java.util.stream.Stream;
033
034import javax.jcr.Node;
035import javax.jcr.Property;
036import javax.jcr.RepositoryException;
037
038import static java.util.stream.Stream.empty;
039import static java.util.stream.Stream.of;
040import static org.apache.jena.graph.NodeFactory.createURI;
041import static org.apache.jena.graph.Triple.create;
042import static org.apache.jena.rdf.model.ResourceFactory.createResource;
043import static org.fcrepo.kernel.api.FedoraTypes.LDP_BASIC_CONTAINER;
044import static org.fcrepo.kernel.api.FedoraTypes.LDP_DIRECT_CONTAINER;
045import static org.fcrepo.kernel.api.FedoraTypes.LDP_HAS_MEMBER_RELATION;
046import static org.fcrepo.kernel.api.FedoraTypes.LDP_INDIRECT_CONTAINER;
047import static org.fcrepo.kernel.api.FedoraTypes.LDP_INSERTED_CONTENT_RELATION;
048import static org.fcrepo.kernel.api.FedoraTypes.LDP_MEMBER_RESOURCE;
049import static org.fcrepo.kernel.api.RdfLexicon.LDP_MEMBER;
050import static org.fcrepo.kernel.api.RdfLexicon.MEMBER_SUBJECT;
051import static org.fcrepo.kernel.modeshape.identifiers.NodeResourceConverter.nodeConverter;
052import static org.fcrepo.kernel.modeshape.rdf.converters.PropertyConverter.getPropertyNameFromPredicate;
053import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode;
054import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getReferencePropertyName;
055import static org.fcrepo.kernel.modeshape.utils.StreamUtils.iteratorToStream;
056import static org.fcrepo.kernel.modeshape.utils.UncheckedFunction.uncheck;
057import static org.slf4j.LoggerFactory.getLogger;
058
059/**
060 * @author cabeer
061 * @author ajs6f
062 * @since 9/25/14
063 */
064public class LdpContainerRdfContext extends NodeRdfContext {
065    private static final Logger LOGGER = getLogger(LdpContainerRdfContext.class);
066
067    /**
068     * Default constructor.
069     *
070     * @param resource the resource
071     * @param idTranslator the id translator
072     * @throws javax.jcr.RepositoryException if repository exception occurred
073     */
074    public LdpContainerRdfContext(final FedoraResource resource,
075                                  final IdentifierConverter<Resource, FedoraResource> idTranslator)
076            throws RepositoryException {
077        super(resource, idTranslator);
078
079        concat(getMembershipContext(resource)
080                .flatMap(uncheck(p -> memberRelations(nodeConverter.convert(p.getParent())))));
081    }
082
083    @SuppressWarnings("unchecked")
084    private static Stream<Property> getMembershipContext(final FedoraResource resource) throws RepositoryException {
085        return iteratorToStream(getJcrNode(resource).getReferences(LDP_MEMBER_RESOURCE))
086                    .filter(UncheckedPredicate.uncheck((final Property p) -> {
087                        final Node container = p.getParent();
088                        return container.isNodeType(LDP_DIRECT_CONTAINER)
089                            || container.isNodeType(LDP_INDIRECT_CONTAINER);
090                    }));
091    }
092
093    /**
094     * Get the member relations assert on the subject by the given node
095     * @param container
096     * @return
097     * @throws RepositoryException
098     */
099    private Stream<Triple> memberRelations(final FedoraResource container) throws RepositoryException {
100        final org.apache.jena.graph.Node memberRelation;
101
102        if (container.hasProperty(LDP_HAS_MEMBER_RELATION)) {
103            final Property property = getJcrNode(container).getProperty(LDP_HAS_MEMBER_RELATION);
104            memberRelation = createURI(property.getString());
105        } else if (container.hasType(LDP_BASIC_CONTAINER)) {
106            memberRelation = LDP_MEMBER.asNode();
107        } else {
108            return empty();
109        }
110
111        final String insertedContainerProperty;
112
113        if (container.hasType(LDP_INDIRECT_CONTAINER)) {
114            if (container.hasProperty(LDP_INSERTED_CONTENT_RELATION)) {
115                insertedContainerProperty = getJcrNode(container).getProperty(LDP_INSERTED_CONTENT_RELATION)
116                    .getString();
117            } else {
118                return empty();
119            }
120        } else {
121            insertedContainerProperty = MEMBER_SUBJECT.getURI();
122        }
123
124        return container.getChildren().flatMap(
125            UncheckedFunction.<FedoraResource, Stream<Triple>>uncheck(child -> {
126                final org.apache.jena.graph.Node childSubject = uriFor(child.getDescribedResource());
127
128                if (insertedContainerProperty.equals(MEMBER_SUBJECT.getURI())) {
129                    return of(create(subject(), memberRelation, childSubject));
130                }
131                String insertedContentProperty = getPropertyNameFromPredicate(getJcrNode(resource()),
132                        createResource(insertedContainerProperty), null);
133
134                if (child.hasProperty(insertedContentProperty)) {
135                    // do nothing, insertedContentProperty is good
136
137                } else if (child.hasProperty(getReferencePropertyName(insertedContentProperty))) {
138                    // The insertedContentProperty is a pseudo reference property
139                    insertedContentProperty = getReferencePropertyName(insertedContentProperty);
140
141                } else {
142                    // No property found!
143                    return empty();
144                }
145
146                return iteratorToStream(new PropertyValueIterator(
147                        getJcrNode(child).getProperty(insertedContentProperty)))
148                    .map(uncheck(v -> create(subject(), memberRelation,
149                        new ValueConverter(getJcrNode(container).getSession(), translator()).convert(v).asNode())));
150            }));
151    }
152}