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; 024 025import org.fcrepo.kernel.models.NonRdfSourceDescription; 026import org.fcrepo.kernel.models.FedoraResource; 027import org.fcrepo.kernel.exception.RepositoryRuntimeException; 028import org.fcrepo.kernel.identifiers.IdentifierConverter; 029import org.fcrepo.kernel.impl.rdf.converters.ValueConverter; 030import org.fcrepo.kernel.impl.rdf.impl.mappings.PropertyValueIterator; 031 032import org.slf4j.Logger; 033 034import javax.jcr.Node; 035import javax.jcr.Property; 036import javax.jcr.RepositoryException; 037import javax.jcr.Value; 038 039import java.util.Iterator; 040 041import static com.google.common.collect.Iterators.singletonIterator; 042import static com.hp.hpl.jena.graph.NodeFactory.createURI; 043import static com.hp.hpl.jena.graph.Triple.create; 044import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource; 045import static java.util.Collections.emptyIterator; 046import static org.fcrepo.kernel.FedoraJcrTypes.LDP_BASIC_CONTAINER; 047import static org.fcrepo.kernel.FedoraJcrTypes.LDP_DIRECT_CONTAINER; 048import static org.fcrepo.kernel.FedoraJcrTypes.LDP_HAS_MEMBER_RELATION; 049import static org.fcrepo.kernel.FedoraJcrTypes.LDP_INDIRECT_CONTAINER; 050import static org.fcrepo.kernel.FedoraJcrTypes.LDP_INSERTED_CONTENT_RELATION; 051import static org.fcrepo.kernel.FedoraJcrTypes.LDP_MEMBER_RESOURCE; 052import static org.fcrepo.kernel.RdfLexicon.LDP_MEMBER; 053import static org.fcrepo.kernel.RdfLexicon.MEMBER_SUBJECT; 054import static org.fcrepo.kernel.impl.identifiers.NodeResourceConverter.nodeConverter; 055import static org.fcrepo.kernel.impl.rdf.converters.PropertyConverter.getPropertyNameFromPredicate; 056import static org.fcrepo.kernel.impl.utils.FedoraTypesUtils.getReferencePropertyName; 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(ChildrenRdfContext.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 final Iterator<Property> memberReferences = resource.getNode().getReferences(LDP_MEMBER_RESOURCE); 079 final Iterator<Property> properties = Iterators.filter(memberReferences, isContainer ); 080 081 if (properties.hasNext()) { 082 LOGGER.trace("Found membership containers for {}", resource); 083 concat(membershipContext(properties)); 084 } 085 } 086 087 private static Predicate<Property> isContainer = new Predicate<Property>() { 088 089 @Override 090 public boolean apply(final Property property) { 091 try { 092 final Node container = property.getParent(); 093 return container.isNodeType(LDP_DIRECT_CONTAINER) || container.isNodeType(LDP_INDIRECT_CONTAINER); 094 } catch (final RepositoryException e) { 095 throw new RepositoryRuntimeException(e); 096 } 097 } 098 }; 099 100 private Iterator<Triple> membershipContext(final Iterator<Property> properties) { 101 return Iterators.concat(Iterators.transform(properties, nodes2triples())); 102 } 103 104 private Function<Property, Iterator<Triple>> nodes2triples() { 105 return new Function<Property,Iterator<Triple>>() { 106 107 @Override 108 public Iterator<Triple> apply(final Property property) { 109 try { 110 final FedoraResource resource = nodeConverter.convert(property.getParent()); 111 return memberRelations(resource); 112 } catch (final RepositoryException e) { 113 throw new RepositoryRuntimeException(e); 114 } 115 } 116 }; 117 } 118 119 /** 120 * Get the member relations assert on the subject by the given node 121 * @param container 122 * @return 123 * @throws RepositoryException 124 */ 125 private Iterator<Triple> memberRelations(final FedoraResource container) throws RepositoryException { 126 final com.hp.hpl.jena.graph.Node memberRelation; 127 128 if (container.hasProperty(LDP_HAS_MEMBER_RELATION)) { 129 final Property property = container.getProperty(LDP_HAS_MEMBER_RELATION); 130 memberRelation = createURI(property.getString()); 131 } else if (container.hasType(LDP_BASIC_CONTAINER)) { 132 memberRelation = LDP_MEMBER.asNode(); 133 } else { 134 return emptyIterator(); 135 } 136 137 final String insertedContainerProperty; 138 139 if (container.hasType(LDP_INDIRECT_CONTAINER)) { 140 if (container.hasProperty(LDP_INSERTED_CONTENT_RELATION)) { 141 insertedContainerProperty = container.getProperty(LDP_INSERTED_CONTENT_RELATION).getString(); 142 } else { 143 return emptyIterator(); 144 } 145 } else { 146 insertedContainerProperty = MEMBER_SUBJECT.getURI(); 147 } 148 149 final Iterator<FedoraResource> memberNodes = container.getChildren(); 150 151 return Iterators.concat(Iterators.transform(memberNodes, 152 new FedoraResourceTripleFunction(insertedContainerProperty, memberRelation))); 153 } 154 155 private class FedoraResourceTripleFunction implements Function<FedoraResource, Iterator<Triple>> { 156 157 private final String insertedContainerProperty; 158 159 private final com.hp.hpl.jena.graph.Node memberRelation; 160 161 public FedoraResourceTripleFunction(final String insertedContainerProperty, 162 final com.hp.hpl.jena.graph.Node memberRelation) { 163 this.insertedContainerProperty = insertedContainerProperty; 164 this.memberRelation = memberRelation; 165 } 166 167 @Override 168 public Iterator<Triple> apply(final FedoraResource child) { 169 170 try { 171 final com.hp.hpl.jena.graph.Node childSubject; 172 if (child instanceof NonRdfSourceDescription) { 173 childSubject = translator().reverse() 174 .convert(((NonRdfSourceDescription) child).getDescribedResource()) 175 .asNode(); 176 } else { 177 childSubject = translator().reverse().convert(child).asNode(); 178 } 179 180 if (insertedContainerProperty.equals(MEMBER_SUBJECT.getURI())) { 181 182 return singletonIterator(create(subject(), memberRelation, childSubject)); 183 } 184 String insertedContentProperty = getPropertyNameFromPredicate(resource().getNode(), 185 createResource(insertedContainerProperty), 186 null); 187 188 if (child.hasProperty(insertedContentProperty)) { 189 // do nothing, insertedContentProperty is good 190 191 } else if (child.hasProperty(getReferencePropertyName(insertedContentProperty))) { 192 // The insertedContentProperty is a pseudo reference property 193 insertedContentProperty = getReferencePropertyName(insertedContentProperty); 194 195 } else { 196 // No property found! 197 return emptyIterator(); 198 } 199 200 final PropertyValueIterator values 201 = new PropertyValueIterator(child.getProperty(insertedContentProperty)); 202 203 return Iterators.transform(values, new Function<Value, Triple>() { 204 @Override 205 public Triple apply(final Value input) { 206 final RDFNode membershipResource = new ValueConverter(session(), translator()) 207 .convert(input); 208 return create(subject(), memberRelation, membershipResource.asNode()); 209 } 210 }); 211 } catch (final RepositoryException e) { 212 throw new RepositoryRuntimeException(e); 213 } 214 } 215 216 } 217}