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_RESOURCE;
021import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_TIME_MAP;
022import static org.fcrepo.kernel.api.FedoraTypes.MEMENTO_ORIGINAL;
023import static org.fcrepo.kernel.api.RdfLexicon.LDPCV_TIME_MAP;
024import static org.modeshape.jcr.api.JcrConstants.NT_FOLDER;
025import static org.slf4j.LoggerFactory.getLogger;
026
027import javax.jcr.Node;
028import javax.jcr.RepositoryException;
029import org.fcrepo.kernel.api.FedoraSession;
030import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
031import org.fcrepo.kernel.api.exception.ResourceTypeException;
032import org.fcrepo.kernel.api.models.FedoraTimeMap;
033import org.fcrepo.kernel.api.services.TimeMapService;
034import org.fcrepo.kernel.modeshape.FedoraTimeMapImpl;
035import org.slf4j.Logger;
036import org.springframework.stereotype.Component;
037
038
039/**
040 * Service for creating and retrieving {@link org.fcrepo.kernel.api.models.FedoraTimeMap} without using the JCR API.
041 *
042 * @author bbpennel
043 */
044@Component
045public class TimeMapServiceImpl extends AbstractService implements TimeMapService {
046
047    private static final Logger LOGGER = getLogger(TimeMapServiceImpl.class);
048
049    @Override
050    public FedoraTimeMap find(final FedoraSession session, final String path) {
051        final String ldpcvPath = getLdpcvPath(path);
052
053        return cast(findNode(session, ldpcvPath));
054    }
055
056    @Override
057    public FedoraTimeMap findOrCreate(final FedoraSession session, final String path) {
058        try {
059            // Add fedora:timemap to path if not present
060            final String ldpcvPath = getLdpcvPath(path);
061
062            final Node node = findOrCreateNode(session, ldpcvPath, NT_FOLDER);
063
064            if (node.isNew()) {
065                LOGGER.debug("Created TimeMap LDPCv {}", node.getPath());
066
067                // add mixin type fedora:Resource
068                if (node.canAddMixin(FEDORA_RESOURCE)) {
069                    node.addMixin(FEDORA_RESOURCE);
070                }
071
072                // add mixin type fedora:TimeMap
073                if (node.canAddMixin(FEDORA_TIME_MAP)) {
074                    node.addMixin(FEDORA_TIME_MAP);
075                }
076
077                // Set reference from timegate/map to original resource
078                node.setProperty(MEMENTO_ORIGINAL, node.getParent());
079            }
080
081            return new FedoraTimeMapImpl(node);
082        } catch (final RepositoryException e) {
083            throw new RepositoryRuntimeException(e);
084        }
085    }
086
087    @Override
088    public boolean exists(final FedoraSession session, final String path) {
089        final String ldpcvPath = getLdpcvPath(path);
090        return super.exists(session, ldpcvPath);
091    }
092
093    private static final String getLdpcvPath(final String path) {
094        if (path.endsWith("/" + LDPCV_TIME_MAP)) {
095            return path;
096        } else {
097            return path.replaceFirst("/*$", "") + "/" + LDPCV_TIME_MAP;
098        }
099    }
100
101    private FedoraTimeMap cast(final Node node) {
102        assertIsType(node);
103        return new FedoraTimeMapImpl(node);
104    }
105
106    private static void assertIsType(final Node node) {
107        if (!FedoraTimeMapImpl.hasMixin(node)) {
108            throw new ResourceTypeException(node + " can not be used as a timemap");
109        }
110    }
111}