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        try {
059            validatePath(jcrSession, path);
060            return jcrSession.nodeExists(path);
061        } catch (final IllegalArgumentException e) {
062            throw new InvalidResourceIdentifierException("Illegal path: " + path);
063        } catch (final RepositoryException e) {
064            throw new RepositoryRuntimeException(e);
065        }
066    }
067
068    /**
069     * Retrieve an existing Fedora resource at the given path
070     *
071     * @param session a JCR session
072     * @param path a JCR path
073     * @return Fedora resource at the given path
074     */
075    @Override
076    public FedoraResource find(final FedoraSession session, final String path) {
077        final Session jcrSession = getJcrSession(session);
078        try {
079            return new FedoraResourceImpl(jcrSession.getNode(path));
080        } catch (final RepositoryException e) {
081            throw new RepositoryRuntimeException(e);
082        }
083    }
084
085    /**
086     * Copy an existing object from the source path to the destination path
087     *
088     * @param session a JCR session
089     * @param source the source path
090     * @param destination the destination path
091     */
092    @Override
093    public void copyObject(final FedoraSession session, final String source, final String destination) {
094        final Session jcrSession = getJcrSession(session);
095        try {
096            jcrSession.getWorkspace().copy(source, destination);
097            touchLdpMembershipResource(getJcrNode(find(session, destination)));
098        } catch (final RepositoryException e) {
099            throw new RepositoryRuntimeException(e);
100        }
101    }
102
103    /**
104     * Move an existing object from the source path to the destination path
105     *
106     * @param session the session
107     * @param source the source path
108     * @param destination the destination path
109     */
110    @Override
111    public void moveObject(final FedoraSession session, final String source, final String destination) {
112        final Session jcrSession = getJcrSession(session);
113        try {
114            final FedoraResource srcResource = find(session, source);
115            final Node sourceNode = getJcrNode(srcResource);
116            final String name = sourceNode.getName();
117            final Node parent = sourceNode.getDepth() > 0 ? sourceNode.getParent() : null;
118
119            jcrSession.getWorkspace().move(source, destination);
120
121            if (parent != null) {
122                createTombstone(parent, name);
123            }
124
125            touchLdpMembershipResource(getJcrNode(find(session, source)));
126            touchLdpMembershipResource(getJcrNode(find(session, destination)));
127
128        } catch (final RepositoryException e) {
129            throw new RepositoryRuntimeException(e);
130        }
131    }
132
133    private static void createTombstone(final Node parent, final String path) throws RepositoryException {
134        final FedoraResourceImpl fedoraResource = new FedoraResourceImpl(parent);
135        final Node n  = fedoraResource.findOrCreateChild(parent, path, FEDORA_TOMBSTONE);
136        LOGGER.info("Created tombstone at {} ", n.getPath());
137    }
138
139    /**
140     * @param session the session
141     * @param path the path
142     */
143    @Override
144    public FedoraResource findOrCreate(final FedoraSession session, final String path) {
145        throw new RepositoryRuntimeException("unimplemented");
146    }
147}