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