001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.kernel.impl.services;
017
018import org.fcrepo.kernel.exception.RepositoryRuntimeException;
019import org.fcrepo.kernel.exception.TombstoneException;
020import org.fcrepo.kernel.impl.TombstoneImpl;
021import org.modeshape.jcr.api.JcrTools;
022
023import javax.jcr.Node;
024import javax.jcr.RepositoryException;
025import javax.jcr.Session;
026
027import static org.fcrepo.kernel.FedoraJcrTypes.FEDORA_PAIRTREE;
028import static org.fcrepo.kernel.impl.utils.FedoraTypesUtils.getClosestExistingAncestor;
029import static org.modeshape.jcr.api.JcrConstants.NT_FOLDER;
030
031
032/**
033 * @author bbpennel
034 * @author ajs6f
035 * @since Feb 20, 2014
036 */
037public class AbstractService {
038    protected final static JcrTools jcrTools = new JcrTools();
039
040    protected Node findOrCreateNode(final Session session,
041                                    final String path,
042                                    final String finalNodeType) throws RepositoryException {
043
044        final Node preexistingNode = getClosestExistingAncestor(session, path);
045
046        if (TombstoneImpl.hasMixin(preexistingNode)) {
047            throw new TombstoneException(new TombstoneImpl(preexistingNode));
048        }
049
050        final Node node = jcrTools.findOrCreateNode(session, path, NT_FOLDER, finalNodeType);
051
052        if (node.isNew()) {
053            tagHierarchyWithPairtreeMixin(preexistingNode, node);
054        }
055
056        return node;
057    }
058
059    protected Node findNode(final Session session, final String path) {
060        try {
061            return session.getNode(path);
062        } catch (final RepositoryException e) {
063            throw new RepositoryRuntimeException(e);
064        }
065    }
066
067    /**
068     * Tag a hierarchy with {@link org.fcrepo.kernel.FedoraJcrTypes#FEDORA_PAIRTREE}
069     * @param baseNode Top most ancestor that should not be tagged
070     * @param createdNode Node whose parents should be tagged up to but not including {@code baseNode}
071     * @throws RepositoryException if repository exception occurred
072     */
073    public static void tagHierarchyWithPairtreeMixin(final Node baseNode, final Node createdNode)
074            throws RepositoryException {
075        Node parent = createdNode.getParent();
076
077        while (parent.isNew() && !parent.equals(baseNode)) {
078            parent.addMixin(FEDORA_PAIRTREE);
079            parent = parent.getParent();
080        }
081    }
082
083    /** test node existence at path
084     *
085     * @param session the session
086     * @param path the path
087     * @return whether T exists at the given path
088     */
089    public boolean exists(final Session session, final String path) {
090        try {
091            return session.nodeExists(path);
092        } catch (final RepositoryException e) {
093            throw new RepositoryRuntimeException(e);
094        }
095    }
096}