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_TOMBSTONE;
021import static org.fcrepo.kernel.modeshape.FedoraSessionImpl.getJcrSession;
022import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode;
023import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.touchLdpMembershipResource;
024import static org.fcrepo.kernel.modeshape.utils.NamespaceTools.validatePath;
025import static org.slf4j.LoggerFactory.getLogger;
026
027import javax.jcr.Node;
028import javax.jcr.RepositoryException;
029import javax.jcr.Session;
030
031import org.fcrepo.kernel.api.FedoraSession;
032import org.fcrepo.kernel.api.exception.InvalidResourceIdentifierException;
033import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
034import org.fcrepo.kernel.api.models.FedoraResource;
035import org.fcrepo.kernel.api.services.NodeService;
036import org.fcrepo.kernel.modeshape.FedoraResourceImpl;
037import org.slf4j.Logger;
038import org.springframework.stereotype.Component;
039
040/**
041 * Service for managing access to Fedora 'nodes' (either datastreams or objects, we don't care.)
042 *
043 * @author Chris Beer
044 * @author ajs6f
045 * @since May 9, 2013
046 */
047@Component
048public class NodeServiceImpl extends AbstractService implements NodeService {
049
050    private static final Logger LOGGER = getLogger(NodeServiceImpl.class);
051
052    /* (non-Javadoc)
053     * @see org.fcrepo.kernel.api.services.Service#exists(javax.jcr.Session, java.lang.String)
054     */
055    @Override
056    public boolean exists(final FedoraSession session, final String path) {
057        final Session jcrSession = getJcrSession(session);
058        final String encodedPath = encodePath(path, session);
059        try {
060            validatePath(jcrSession, encodedPath);
061            return jcrSession.nodeExists(encodedPath);
062        } catch (final IllegalArgumentException e) {
063            throw new InvalidResourceIdentifierException("Illegal path: " + path);
064        } catch (final RepositoryException e) {
065            throw new RepositoryRuntimeException(e);
066        }
067    }
068
069    /**
070     * Retrieve an existing Fedora resource at the given path
071     *
072     * @param session a JCR session
073     * @param path a JCR path
074     * @return Fedora resource at the given path
075     */
076    @Override
077    public FedoraResource find(final FedoraSession session, final String path) {
078        final Session jcrSession = getJcrSession(session);
079        try {
080            return new FedoraResourceImpl(jcrSession.getNode(encodePath(path, session)));
081        } catch (final RepositoryException e) {
082            throw new RepositoryRuntimeException(e);
083        }
084    }
085
086    /**
087     * Copy an existing object from the source path to the destination path
088     *
089     * @param session a JCR session
090     * @param source the source path
091     * @param destination the destination path
092     */
093    @Override
094    public void copyObject(final FedoraSession session, final String source, final String destination) {
095        final Session jcrSession = getJcrSession(session);
096        try {
097            jcrSession.getWorkspace().copy(encodePath(source, session), encodePath(destination, session));
098            touchLdpMembershipResource(getJcrNode(find(session, encodePath(destination, session))));
099        } catch (final RepositoryException e) {
100            throw new RepositoryRuntimeException(e);
101        }
102    }
103
104    /**
105     * Move an existing object from the source path to the destination path
106     *
107     * @param session the session
108     * @param source the source path
109     * @param destination the destination path
110     */
111    @Override
112    public void moveObject(final FedoraSession session, final String source, final String destination) {
113        final Session jcrSession = getJcrSession(session);
114        try {
115            final FedoraResource srcResource = find(session, encodePath(source, session));
116            final Node sourceNode = getJcrNode(srcResource);
117            final String name = sourceNode.getName();
118            final Node parent = sourceNode.getDepth() > 0 ? sourceNode.getParent() : null;
119
120            jcrSession.getWorkspace().move(source, encodePath(destination, session));
121
122            if (parent != null) {
123                createTombstone(parent, encodePath(name, session));
124            }
125
126            touchLdpMembershipResource(getJcrNode(find(session, encodePath(source, session))));
127            touchLdpMembershipResource(getJcrNode(find(session, encodePath(destination, session))));
128
129        } catch (final RepositoryException e) {
130            throw new RepositoryRuntimeException(e);
131        }
132    }
133
134    private static void createTombstone(final Node parent, final String path) throws RepositoryException {
135        final FedoraResourceImpl fedoraResource = new FedoraResourceImpl(parent);
136        final Node n = fedoraResource.findOrCreateChild(parent, path, FEDORA_TOMBSTONE);
137        LOGGER.info("Created tombstone at {} ", n.getPath());
138    }
139
140    /**
141     * @param session the session
142     * @param path the path
143     */
144    @Override
145    public FedoraResource findOrCreate(final FedoraSession session, final String path) {
146        throw new RepositoryRuntimeException("unimplemented");
147    }
148}