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 com.hp.hpl.jena.graph.Node;
019import com.hp.hpl.jena.graph.Triple;
020import com.hp.hpl.jena.rdf.model.Resource;
021import org.fcrepo.kernel.api.models.FedoraResource;
022import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
023import org.fcrepo.kernel.modeshape.rdf.converters.ValueConverter;
024import org.fcrepo.kernel.modeshape.rdf.impl.mappings.PropertyValueIterator;
025
026import javax.jcr.Property;
027import javax.jcr.RepositoryException;
028
029import java.util.stream.Stream;
030
031import static java.util.stream.Stream.empty;
032import static java.util.stream.Stream.of;
033import static com.hp.hpl.jena.graph.NodeFactory.createURI;
034import static com.hp.hpl.jena.graph.Triple.create;
035import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
036import static org.fcrepo.kernel.api.FedoraTypes.LDP_DIRECT_CONTAINER;
037import static org.fcrepo.kernel.api.FedoraTypes.LDP_INDIRECT_CONTAINER;
038import static org.fcrepo.kernel.api.FedoraTypes.LDP_INSERTED_CONTENT_RELATION;
039import static org.fcrepo.kernel.api.FedoraTypes.LDP_IS_MEMBER_OF_RELATION;
040import static org.fcrepo.kernel.api.FedoraTypes.LDP_MEMBER_RESOURCE;
041import static org.fcrepo.kernel.api.RdfLexicon.MEMBER_SUBJECT;
042import static org.fcrepo.kernel.modeshape.rdf.converters.PropertyConverter.getPropertyNameFromPredicate;
043import static org.fcrepo.kernel.modeshape.rdf.impl.ReferencesRdfContext.REFERENCE_TYPES;
044import static org.fcrepo.kernel.modeshape.utils.StreamUtils.iteratorToStream;
045
046/**
047 * @author cabeer
048 * @author ajs6f
049 * @since 10/7/14
050 */
051public class LdpIsMemberOfRdfContext extends NodeRdfContext {
052    private final ValueConverter valueConverter;
053
054    /**
055     * Default constructor.
056     *
057     * @param resource the resource
058     * @param idTranslator the id translator
059     * @throws javax.jcr.RepositoryException if repository exception
060     */
061    public LdpIsMemberOfRdfContext(final FedoraResource resource,
062                                   final IdentifierConverter<Resource, FedoraResource> idTranslator)
063            throws RepositoryException {
064        super(resource, idTranslator);
065
066        valueConverter = new ValueConverter(resource.getNode().getSession(), translator());
067        final FedoraResource container = resource.getContainer();
068
069        if (container != null
070                && (container.hasType(LDP_DIRECT_CONTAINER) || container.hasType(LDP_INDIRECT_CONTAINER))
071                && container.hasProperty(LDP_IS_MEMBER_OF_RELATION)) {
072            concat(concatIsMemberOfRelation(container));
073        }
074    }
075
076    private Stream<Triple> concatIsMemberOfRelation(final FedoraResource container) throws RepositoryException {
077        final Property property = container.getNode().getProperty(LDP_IS_MEMBER_OF_RELATION);
078
079        final Resource memberRelation = createResource(property.getString());
080        final Node membershipResource = getMemberResource(container);
081
082        if (membershipResource == null) {
083            return empty();
084        }
085
086        final String insertedContainerProperty;
087
088        if (container.hasType(LDP_INDIRECT_CONTAINER)) {
089            if (container.hasProperty(LDP_INSERTED_CONTENT_RELATION)) {
090                insertedContainerProperty = container.getNode().getProperty(LDP_INSERTED_CONTENT_RELATION).getString();
091            } else {
092                return empty();
093            }
094        } else {
095            insertedContainerProperty = MEMBER_SUBJECT.getURI();
096        }
097
098        if (insertedContainerProperty.equals(MEMBER_SUBJECT.getURI())) {
099            return of(create(subject(), memberRelation.asNode(), membershipResource));
100        } else if (container.hasType(LDP_INDIRECT_CONTAINER)) {
101            final String insertedContentProperty = getPropertyNameFromPredicate(resource().getNode(), createResource
102                    (insertedContainerProperty), null);
103
104            if (resource().hasProperty(insertedContentProperty)) {
105                return iteratorToStream(new PropertyValueIterator(
106                            resource().getNode().getProperty(insertedContentProperty)))
107                        .map(valueConverter::convert)
108                        .filter(n -> n.isURIResource())
109                        .filter(n -> translator().inDomain(n.asResource()))
110                        .map(s -> create(s.asNode(), memberRelation.asNode(), membershipResource));
111            }
112        }
113        return empty();
114    }
115
116    /**
117     * Get the membership resource relation asserted by the container
118     * @param parent
119     * @return
120     * @throws RepositoryException
121     */
122    private Node getMemberResource(final FedoraResource parent) throws RepositoryException {
123        final Node membershipResource;
124
125        if (parent.hasProperty(LDP_MEMBER_RESOURCE)) {
126            final Property memberResource = parent.getNode().getProperty(LDP_MEMBER_RESOURCE);
127
128            if (REFERENCE_TYPES.contains(memberResource.getType())) {
129                membershipResource = nodeConverter().convert(memberResource.getNode()).asNode();
130            } else {
131                membershipResource = createURI(memberResource.getString());
132            }
133        } else {
134            membershipResource = uriFor(parent);
135        }
136
137        return membershipResource;
138    }
139}