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.services; 019 020import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_CONTAINER; 021import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_RESOURCE; 022import static org.fcrepo.kernel.api.FedoraTypes.LDP_BASIC_CONTAINER; 023import static org.fcrepo.kernel.api.FedoraTypes.LDP_DIRECT_CONTAINER; 024import static org.fcrepo.kernel.api.FedoraTypes.LDP_HAS_MEMBER_RELATION; 025import static org.fcrepo.kernel.api.FedoraTypes.LDP_INDIRECT_CONTAINER; 026import static org.fcrepo.kernel.api.FedoraTypes.LDP_INSERTED_CONTENT_RELATION; 027import static org.fcrepo.kernel.api.FedoraTypes.LDP_MEMBER_RESOURCE; 028import static org.fcrepo.kernel.api.RdfLexicon.LDP_MEMBER; 029import static org.fcrepo.kernel.api.RdfLexicon.MEMBER_SUBJECT; 030import static org.fcrepo.kernel.modeshape.ContainerImpl.hasMixin; 031import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getContainingNode; 032import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.touch; 033import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.touchLdpMembershipResource; 034import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT; 035import static org.modeshape.jcr.api.JcrConstants.NT_FOLDER; 036import static org.slf4j.LoggerFactory.getLogger; 037 038import javax.jcr.Node; 039import javax.jcr.RepositoryException; 040 041import org.fcrepo.kernel.api.FedoraSession; 042import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 043import org.fcrepo.kernel.api.exception.ResourceTypeException; 044import org.fcrepo.kernel.api.models.Container; 045import org.fcrepo.kernel.api.services.ContainerService; 046import org.fcrepo.kernel.modeshape.ContainerImpl; 047 048import org.slf4j.Logger; 049import org.springframework.stereotype.Component; 050 051/** 052 * Service for creating and retrieving {@link org.fcrepo.kernel.api.models.Container} without using the JCR API. 053 * 054 * @author cbeer 055 * @author ajs6f 056 * @since Feb 11, 2013 057 */ 058@Component 059public class ContainerServiceImpl extends AbstractService implements ContainerService { 060 061 private static final Logger LOGGER = getLogger(ContainerServiceImpl.class); 062 063 @Override 064 public Container findOrCreate(final FedoraSession session, final String path, final String interactionModel) { 065 LOGGER.trace("Executing findOrCreateObject() with path: {}", path); 066 067 try { 068 final Node node = findOrCreateNode(session, path, NT_FOLDER); 069 070 if (node.isNew()) { 071 initializeNewObjectProperties(node); 072 073 getContainingNode(node).ifPresent(parent -> { 074 touch(parent); 075 touchLdpMembershipResource(node); 076 }); 077 078 if (LDP_INDIRECT_CONTAINER.equals(interactionModel)) { 079 node.addMixin(LDP_INDIRECT_CONTAINER); 080 node.setProperty(LDP_MEMBER_RESOURCE, node); 081 node.setProperty(LDP_HAS_MEMBER_RELATION, LDP_MEMBER.getURI()); 082 node.setProperty(LDP_INSERTED_CONTENT_RELATION, MEMBER_SUBJECT.getURI()); 083 } else if (LDP_DIRECT_CONTAINER.equals(interactionModel)) { 084 node.addMixin(LDP_DIRECT_CONTAINER); 085 node.setProperty(LDP_MEMBER_RESOURCE, node); 086 node.setProperty(LDP_HAS_MEMBER_RELATION, LDP_MEMBER.getURI()); 087 } else { 088 node.addMixin(LDP_BASIC_CONTAINER); 089 } 090 } 091 092 if (node.isNew()) { 093 touch(node); 094 } 095 096 return new ContainerImpl(node); 097 } catch (final RepositoryException e) { 098 throw new RepositoryRuntimeException(e); 099 } 100 } 101 102 /** 103 * @param path the path 104 * @param session the session 105 * @return A {@link org.fcrepo.kernel.api.models.Container} with the proffered PID 106 */ 107 @Override 108 public Container findOrCreate(final FedoraSession session, final String path) { 109 return findOrCreate(session, path, null); 110 } 111 112 /** 113 * Retrieve a {@link org.fcrepo.kernel.api.models.Container} instance by pid and dsid 114 * 115 * @param path the path 116 * @param session the session 117 * @return A {@link org.fcrepo.kernel.api.models.Container} with the proffered PID 118 */ 119 @Override 120 public Container find(final FedoraSession session, final String path) { 121 final Node node = findNode(session, path); 122 123 return cast(node); 124 } 125 126 private static void initializeNewObjectProperties(final Node node) { 127 try { 128 LOGGER.debug("Setting object properties on node {}...", node.getPath()); 129 130 if (node.canAddMixin(FEDORA_RESOURCE)) { 131 node.addMixin(FEDORA_RESOURCE); 132 } 133 134 if (node.canAddMixin(FEDORA_CONTAINER)) { 135 node.addMixin(FEDORA_CONTAINER); 136 } 137 138 } catch (final RepositoryException e) { 139 LOGGER.warn("Could not decorate {} with {} properties: {} ", 140 JCR_CONTENT, FEDORA_CONTAINER, e); 141 } 142 } 143 144 private Container cast(final Node node) { 145 assertIsType(node); 146 return new ContainerImpl(node); 147 } 148 149 private static void assertIsType(final Node node) { 150 if (!hasMixin(node)) { 151 throw new ResourceTypeException(node + " can not be used as a object"); 152 } 153 } 154 155}