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.rdf.impl; 019 020import static com.google.common.collect.Lists.newArrayList; 021import static org.apache.jena.rdf.model.ResourceFactory.createResource; 022 023import com.google.common.base.Converter; 024import com.google.common.collect.Lists; 025 026import org.fcrepo.kernel.api.models.FedoraResource; 027import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 028import org.fcrepo.kernel.api.identifiers.IdentifierConverter; 029 030import org.apache.jena.rdf.model.Resource; 031 032import org.fcrepo.kernel.modeshape.identifiers.HashConverter; 033import org.fcrepo.kernel.modeshape.identifiers.NamespaceConverter; 034import org.fcrepo.kernel.modeshape.identifiers.NodeResourceConverter; 035 036import javax.jcr.RepositoryException; 037import javax.jcr.Session; 038 039import java.util.List; 040 041/** 042 * A very simple {@link IdentifierConverter} which translates JCR paths into Fedora subjects with 043 * a configurable resource namespace (e.g., a baseURL). When a REST API context is available for 044 * constructing URIs, org.fcrepo.http.commons.api.rdf.HttpResourceConverter should be used instead. 045 * 046 * @author barmintor 047 * @author ajs6f 048 * @author escowles 049 * @since 2015-04-24 050 */ 051public class PrefixingIdentifierTranslator extends IdentifierConverter<Resource, FedoraResource> { 052 053 054 private static final NodeResourceConverter nodeResourceConverter = new NodeResourceConverter(); 055 056 private final String resourceNamespace; 057 private final Session session; 058 059 /** 060 * Construct the graph with the provided resource namespace, which will translate JCR paths into 061 * URIs prefixed with that namespace. Should only be used when a REST API context is not available 062 * for constructing URIs. 063 * @param session Session to lookup nodes 064 * @param resourceNamespace Resource namespace (i.e., base URL) 065 **/ 066 public PrefixingIdentifierTranslator(final Session session, final String resourceNamespace) { 067 this.session = session; 068 this.resourceNamespace = resourceNamespace; 069 setTranslationChain(); 070 } 071 072 073 private Converter<String, String> forward = identity(); 074 private Converter<String, String> reverse = identity(); 075 076 /* 077 * TODO: much of what happens with chains of translators inside these converters should be factored 078 * out into some abstract class, or post Java 8, default implementation. 079 */ 080 private void setTranslationChain() { 081 082 for (final Converter<String, String> t : minimalTranslationChain) { 083 forward = forward.andThen(t); 084 } 085 for (final Converter<String, String> t : Lists.reverse(minimalTranslationChain)) { 086 reverse = reverse.andThen(t.reverse()); 087 } 088 } 089 090 private static final List<Converter<String, String>> minimalTranslationChain = 091 newArrayList(new NamespaceConverter(), new HashConverter() ); 092 093 @Override 094 protected FedoraResource doForward(final Resource subject) { 095 try { 096 if (!inDomain(subject)) { 097 throw new RepositoryRuntimeException("Subject " + subject + " is not in this repository"); 098 } 099 100 return nodeResourceConverter.convert(session.getNode(asString(subject))); 101 } catch (final RepositoryException e) { 102 throw new RepositoryRuntimeException(e); 103 } 104 } 105 106 @Override 107 protected Resource doBackward(final FedoraResource resource) { 108 final String absPath = resource.getPath(); 109 110 return toDomain(absPath); 111 } 112 113 @Override 114 public boolean inDomain(final Resource subject) { 115 return subject.isURIResource() && subject.getURI().startsWith(resourceNamespace); 116 } 117 118 @Override 119 public Resource toDomain(final String absPath) { 120 final String relativePath; 121 122 if (absPath.startsWith("/")) { 123 relativePath = absPath.substring(1); 124 } else { 125 relativePath = absPath; 126 } 127 return createResource(resourceNamespace + reverse.convert(relativePath)); 128 } 129 130 @Override 131 public String asString(final Resource subject) { 132 if (!inDomain(subject)) { 133 return null; 134 } 135 136 final String path = subject.getURI().substring(resourceNamespace.length() - 1); 137 138 final String absPath = forward.convert(path); 139 140 if (absPath.isEmpty()) { 141 return "/"; 142 } 143 return absPath; 144 } 145 146}