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.impl.models;
019
020import static org.slf4j.LoggerFactory.getLogger;
021
022import javax.inject.Inject;
023
024import org.fcrepo.kernel.api.ContainmentIndex;
025import org.fcrepo.kernel.api.Transaction;
026import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
027import org.fcrepo.kernel.api.identifiers.FedoraId;
028import org.fcrepo.kernel.api.models.ResourceHeaders;
029import org.fcrepo.kernel.api.models.ResourceHelper;
030import org.fcrepo.persistence.api.PersistentStorageSession;
031import org.fcrepo.persistence.api.PersistentStorageSessionManager;
032import org.fcrepo.persistence.api.exceptions.PersistentItemNotFoundException;
033import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
034import org.fcrepo.persistence.common.ResourceHeadersImpl;
035
036import org.slf4j.Logger;
037import org.springframework.beans.factory.annotation.Autowired;
038import org.springframework.beans.factory.annotation.Qualifier;
039import org.springframework.stereotype.Component;
040
041/**
042 * Utility class for helper methods.
043 * @author whikloj
044 * @since 6.0.0
045 */
046@Component
047public class ResourceHelperImpl implements ResourceHelper {
048
049    private static final Logger LOGGER = getLogger(ResourceHeadersImpl.class);
050
051    @Inject
052    private PersistentStorageSessionManager persistentStorageSessionManager;
053
054    @Autowired
055    @Qualifier("containmentIndex")
056    private ContainmentIndex containmentIndex;
057
058    @Override
059    public boolean isGhostNode(final Transaction transaction, final FedoraId resourceId) {
060        if (!doesResourceExist(transaction, resourceId, true)) {
061            return containmentIndex.hasResourcesStartingWith(transaction, resourceId);
062        }
063        return false;
064    }
065
066    @Override
067    public boolean doesResourceExist(final Transaction transaction, final FedoraId fedoraId,
068                                     final boolean includeDeleted) {
069        if (fedoraId.isRepositoryRoot()) {
070            // Root always exists.
071            return true;
072        }
073        if (!(fedoraId.isMemento() || fedoraId.isAcl())) {
074            // containment index doesn't handle versions and only tells us if the resource (not acl) is there,
075            // so don't bother checking for them.
076            return containmentIndex.resourceExists(transaction, fedoraId, includeDeleted);
077        } else {
078
079            final PersistentStorageSession psSession = getSession(transaction);
080
081            try {
082                // Resource ID for metadata or ACL contains their individual endopoints (ie. fcr:metadata, fcr:acl)
083                final ResourceHeaders headers = psSession.getHeaders(fedoraId, fedoraId.getMementoInstant());
084                return !headers.isDeleted();
085            } catch (final PersistentItemNotFoundException e) {
086                // Object doesn't exist.
087                return false;
088            } catch (final PersistentStorageException e) {
089                // Other error, pass along.
090                throw new RepositoryRuntimeException(e.getMessage(), e);
091            }
092        }
093    }
094
095    /**
096     * Get a session for this interaction.
097     *
098     * @param transaction The supplied transaction.
099     * @return a storage session.
100     */
101    private PersistentStorageSession getSession(final Transaction transaction) {
102        final PersistentStorageSession session;
103        if (transaction.isReadOnly() || !transaction.isOpen()) {
104            session = persistentStorageSessionManager.getReadOnlySession();
105        } else {
106            session = persistentStorageSessionManager.getSession(transaction);
107        }
108        return session;
109    }
110}