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.Iterators;
021import com.hp.hpl.jena.graph.Triple;
022import com.hp.hpl.jena.rdf.model.RDFNode;
023import com.hp.hpl.jena.rdf.model.Resource;
024import org.fcrepo.kernel.models.FedoraResource;
025import org.fcrepo.kernel.RdfLexicon;
026import org.fcrepo.kernel.identifiers.IdentifierConverter;
027import org.fcrepo.kernel.impl.rdf.converters.ValueConverter;
028import org.fcrepo.kernel.impl.rdf.impl.mappings.PropertyValueIterator;
029
030import javax.jcr.Property;
031import javax.jcr.RepositoryException;
032
033import java.util.Iterator;
034
035import static com.hp.hpl.jena.graph.Triple.create;
036import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
037import static javax.jcr.PropertyType.PATH;
038import static javax.jcr.PropertyType.REFERENCE;
039import static javax.jcr.PropertyType.WEAKREFERENCE;
040import static org.fcrepo.kernel.FedoraJcrTypes.LDP_DIRECT_CONTAINER;
041import static org.fcrepo.kernel.FedoraJcrTypes.LDP_INDIRECT_CONTAINER;
042import static org.fcrepo.kernel.FedoraJcrTypes.LDP_INSERTED_CONTENT_RELATION;
043import static org.fcrepo.kernel.FedoraJcrTypes.LDP_IS_MEMBER_OF_RELATION;
044import static org.fcrepo.kernel.FedoraJcrTypes.LDP_MEMBER_RESOURCE;
045import static org.fcrepo.kernel.impl.rdf.converters.PropertyConverter.getPropertyNameFromPredicate;
046
047/**
048 * @author cabeer
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(session(), 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            concatIsMemberOfRelation(container);
073        }
074    }
075
076    private void concatIsMemberOfRelation(final FedoraResource container) throws RepositoryException {
077        final Property property = container.getProperty(LDP_IS_MEMBER_OF_RELATION);
078
079        final Resource memberRelation = createResource(property.getString());
080        final Resource membershipResource = getMemberResource(container);
081
082        if (membershipResource == null) {
083            return;
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.getProperty(LDP_INSERTED_CONTENT_RELATION).getString();
091            } else {
092                return;
093            }
094        } else {
095            insertedContainerProperty = RdfLexicon.MEMBER_SUBJECT.getURI();
096        }
097
098        if (insertedContainerProperty.equals(RdfLexicon.MEMBER_SUBJECT.getURI())) {
099            concat(create(subject(), memberRelation.asNode(), membershipResource.asNode()));
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;
106            }
107
108            final PropertyValueIterator values
109                    = new PropertyValueIterator(resource().getProperty(insertedContentProperty));
110
111            final Iterator<RDFNode> insertedContentRelations = Iterators.filter(
112                    Iterators.transform(values, valueConverter),
113                    new Predicate<RDFNode>() {
114                        @Override
115                        public boolean apply(final RDFNode input) {
116                            return input.isURIResource() && translator().inDomain(input.asResource());
117                        }
118                    });
119
120            concat(Iterators.transform(insertedContentRelations, new Function<RDFNode, Triple>() {
121                @Override
122                public Triple apply(final RDFNode input) {
123                    return create(input.asNode(), memberRelation.asNode(), membershipResource.asNode());
124                }
125            }));
126
127        }
128    }
129
130    /**
131     * Get the membership resource relation asserted by the container
132     * @param parent
133     * @return
134     * @throws RepositoryException
135     */
136    private Resource getMemberResource(final FedoraResource parent) throws RepositoryException {
137        final Resource membershipResource;
138
139        if (parent.hasProperty(LDP_MEMBER_RESOURCE)) {
140            final Property memberResource = parent.getProperty(LDP_MEMBER_RESOURCE);
141
142            final int type = memberResource.getType();
143            if ( type == REFERENCE || type == WEAKREFERENCE || type == PATH) {
144                membershipResource = nodeConverter().convert(memberResource.getNode());
145            } else {
146                membershipResource = createResource(memberResource.getString());
147            }
148        } else {
149            membershipResource = translator().reverse().convert(parent);
150        }
151
152        return membershipResource;
153    }
154}