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; 019 020import static org.fcrepo.kernel.api.utils.SubjectMappingUtil.mapSubject; 021import static java.util.stream.Stream.empty; 022import static org.fcrepo.kernel.api.RequiredRdfContext.MINIMAL; 023import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.isNonRdfSourceDescription; 024import static org.slf4j.LoggerFactory.getLogger; 025 026import javax.jcr.Node; 027import javax.jcr.PathNotFoundException; 028import javax.jcr.RepositoryException; 029 030import org.apache.jena.graph.Triple; 031import org.apache.jena.rdf.model.Resource; 032import org.fcrepo.kernel.api.RdfStream; 033import org.fcrepo.kernel.api.TripleCategory; 034import org.fcrepo.kernel.api.exception.PathNotFoundRuntimeException; 035import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 036import org.fcrepo.kernel.api.identifiers.IdentifierConverter; 037import org.fcrepo.kernel.api.models.FedoraResource; 038import org.fcrepo.kernel.api.models.NonRdfSourceDescription; 039import org.fcrepo.kernel.api.rdf.DefaultRdfStream; 040import org.fcrepo.kernel.modeshape.rdf.impl.InternalIdentifierTranslator; 041import org.slf4j.Logger; 042 043import java.util.Calendar; 044import java.util.Set; 045import java.util.stream.Stream; 046 047/** 048 * Abstraction for a Fedora datastream backed by a JCR node. 049 * 050 * @author ajs6f 051 * @since Feb 21, 2013 052 */ 053public class NonRdfSourceDescriptionImpl extends FedoraResourceImpl implements NonRdfSourceDescription { 054 055 private static final Logger LOGGER = getLogger(NonRdfSourceDescriptionImpl.class); 056 057 /** 058 * The JCR node for this datastream 059 * 060 * @param n an existing {@link Node} 061 */ 062 public NonRdfSourceDescriptionImpl(final Node n) { 063 super(n); 064 } 065 066 @Override 067 public FedoraResource getDescribedResource() { 068 return new FedoraBinaryImpl(getContentNode()); 069 } 070 071 private Node getContentNode() { 072 LOGGER.trace("Retrieved datastream content node."); 073 try { 074 if (isMemento()) { 075 final String mementoName = node.getName(); 076 return node.getParent().getParent().getParent().getNode(LDPCV_TIME_MAP).getNode(mementoName); 077 } 078 return node.getParent(); 079 } catch (final PathNotFoundException e) { 080 throw new PathNotFoundRuntimeException(e); 081 } catch (final RepositoryException e) { 082 throw new RepositoryRuntimeException(e); 083 } 084 } 085 086 @Override 087 public RdfStream getTriples(final IdentifierConverter<Resource, FedoraResource> idTranslator, 088 final Set<? extends TripleCategory> contexts) { 089 final FedoraResource described = getOriginalResource().getDescribedResource(); 090 091 final org.apache.jena.graph.Node describedNode = idTranslator.reverse().convert(described).asNode(); 092 final String resourceUri = idTranslator.reverse().convert(this).getURI(); 093 094 Stream<Triple> triples = contexts.stream() 095 .filter(contextMap::containsKey) 096 .map(x -> contextMap.get(x).apply(this).apply(idTranslator).apply(contexts.contains(MINIMAL))) 097 .reduce(empty(), Stream::concat) 098 .map(t -> mapSubject(t, resourceUri, describedNode)); 099 100 // if a memento, convert subjects to original resource and object references from referential integrity 101 // ignoring internal URL back the original external URL. 102 if (isMemento()) { 103 final IdentifierConverter<Resource, FedoraResource> internalIdTranslator = 104 new InternalIdentifierTranslator(getSession()); 105 triples = triples.map(convertMementoReferences(idTranslator, internalIdTranslator)); 106 } 107 108 return new DefaultRdfStream(idTranslator.reverse().convert(described).asNode(), triples); 109 } 110 111 /** 112 * Check if the node has a fedora:datastream mixin 113 * 114 * @param node node to check 115 * @return whether the node has a fedora:datastream mixin 116 */ 117 public static boolean hasMixin(final Node node) { 118 return isNonRdfSourceDescription.test(node); 119 } 120 121 /** 122 * Overrides the superclass to propagate updates to certain properties to the binary if explicitly set. 123 */ 124 @Override 125 public void touch(final boolean includeMembershipResource, final Calendar createdDate, final String createdUser, 126 final Calendar modifiedDate, final String modifyingUser) throws RepositoryException { 127 super.touch(includeMembershipResource, createdDate, createdUser, modifiedDate, modifyingUser); 128 if (createdDate != null || createdUser != null || modifiedDate != null || modifyingUser != null) { 129 ((FedoraBinaryImpl) getDescribedResource()).touch(false, createdDate, createdUser, 130 modifiedDate, modifyingUser); 131 } 132 } 133 134}