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