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.models.FedoraBinary;
019import org.fcrepo.kernel.exception.RepositoryRuntimeException;
020import org.fcrepo.kernel.exception.ResourceTypeException;
021import org.fcrepo.kernel.impl.FedoraBinaryImpl;
022import org.fcrepo.kernel.services.BinaryService;
023import org.slf4j.Logger;
024import org.springframework.stereotype.Component;
025
026import javax.jcr.Node;
027import javax.jcr.RepositoryException;
028import javax.jcr.Session;
029
030import static org.fcrepo.kernel.FedoraJcrTypes.FEDORA_BINARY;
031import static org.fcrepo.kernel.FedoraJcrTypes.FEDORA_NON_RDF_SOURCE_DESCRIPTION;
032import static org.fcrepo.kernel.FedoraJcrTypes.FEDORA_RESOURCE;
033import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
034import static org.modeshape.jcr.api.JcrConstants.NT_FILE;
035import static org.modeshape.jcr.api.JcrConstants.NT_RESOURCE;
036import static org.slf4j.LoggerFactory.getLogger;
037
038/**
039 * @author cabeer
040 * @author ajs6f
041 * @since 10/10/14
042 */
043@Component
044public class BinaryServiceImpl extends AbstractService implements BinaryService {
045
046    private static final Logger LOGGER = getLogger(BinaryServiceImpl.class);
047
048    /**
049     * Retrieve or create a Datastream instance by pid and dsid
050     *
051     * @param path jcr path to the datastream
052     * @return datastream
053     */
054    @Override
055    public FedoraBinary findOrCreate(final Session session, final String path) {
056        try {
057            final Node dsNode = findOrCreateNode(session, path, NT_FILE);
058
059            if (dsNode.isNew()) {
060                initializeNewDatastreamProperties(dsNode);
061            }
062
063            return cast(dsNode.getNode(JCR_CONTENT));
064        } catch (final RepositoryException e) {
065            throw new RepositoryRuntimeException(e);
066        }
067    }
068
069    /**
070     * Retrieve a Datastream instance by pid and dsid
071     *
072     * @param path jcr path to the datastream
073     * @return datastream
074     */
075    @Override
076    public FedoraBinary find(final Session session, final String path) {
077        try {
078            final Node dsNode = findNode(session, path);
079
080            return cast(dsNode.getNode(JCR_CONTENT));
081        } catch (final RepositoryException e) {
082            throw new RepositoryRuntimeException(e);
083        }
084    }
085
086    private static void initializeNewDatastreamProperties(final Node node) {
087        try {
088
089            if (node.canAddMixin(FEDORA_RESOURCE)) {
090                node.addMixin(FEDORA_RESOURCE);
091            }
092
093            if (node.canAddMixin(FEDORA_NON_RDF_SOURCE_DESCRIPTION)) {
094                node.addMixin(FEDORA_NON_RDF_SOURCE_DESCRIPTION);
095            }
096
097            final Node contentNode = jcrTools.findOrCreateChild(node, JCR_CONTENT, NT_RESOURCE);
098
099            if (contentNode.canAddMixin(FEDORA_BINARY)) {
100                contentNode.addMixin(FEDORA_BINARY);
101            }
102        } catch (final RepositoryException e) {
103            LOGGER.warn("Could not decorate {} with datastream properties: {}", node, e);
104        }
105
106    }
107    /**
108     * Retrieve a Datastream instance by pid and dsid
109     *
110     * @param node datastream node
111     * @return node as datastream
112     */
113    @Override
114    public FedoraBinary cast(final Node node) {
115        assertIsType(node);
116        return new FedoraBinaryImpl(node);
117    }
118
119    private static void assertIsType(final Node node) {
120        if (!FedoraBinaryImpl.hasMixin(node)) {
121            throw new ResourceTypeException(node + " can not be used as a binary");
122        }
123    }
124
125
126}