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.camel.processor;
019
020import static com.hp.hpl.jena.util.URIref.encode;
021import java.io.IOException;
022
023import org.apache.camel.Message;
024import org.apache.commons.lang3.StringUtils;
025import org.fcrepo.camel.FcrepoHeaders;
026import org.fcrepo.camel.JmsHeaders;
027
028/**
029 * Utility functions for fcrepo processor classes
030 * @author Aaron Coburn
031 * @since November 14, 2014
032 */
033
034public final class ProcessorUtils {
035
036    /**
037     * This is a utility class; the constructor is off-limits.
038     */
039    private ProcessorUtils() {
040    }
041
042    private static String trimTrailingSlash(final String path) {
043        String trimmed = path;
044        while (trimmed.endsWith("/")) {
045            trimmed = trimmed.substring(0, trimmed.length() - 1);
046        }
047        return trimmed;
048    }
049
050    /**
051     * Extract a language string suitable for Jena from a MimeType value
052     * @param contentType a MIMEType string
053     * @return a Jena-compatible language string
054     */
055    public static String langFromMimeType(final String contentType) {
056        if (contentType.equals("application/n-triples")) {
057            return "N-TRIPLE";
058        } else if (contentType.equals("text/turtle")) {
059            return "TURTLE";
060        } else if (contentType.equals("application/rdf+xml")) {
061            return "RDF/XML";
062        } else if (contentType.equals("text/rdf+n3") || contentType.equals("text/n3")) {
063            return "N3";
064        } else {
065            return null;
066        }
067    }
068
069    /**
070     * Extract the subject URI from the incoming message headers.
071     * @param in the incoming Message
072     * @return the subject URI
073     * @throws IOException when no baseURL header is present
074     */
075    public static String getSubjectUri(final Message in) throws IOException {
076        final StringBuilder base = new StringBuilder("");
077
078        if (in.getHeader(FcrepoHeaders.FCREPO_BASE_URL) != null) {
079            base.append(trimTrailingSlash(in.getHeader(FcrepoHeaders.FCREPO_BASE_URL, String.class)));
080        } else if (in.getHeader(JmsHeaders.BASE_URL) != null) {
081            base.append(trimTrailingSlash(in.getHeader(JmsHeaders.BASE_URL, String.class)));
082        } else {
083            throw new IOException("No baseURL header available!");
084        }
085
086        if (in.getHeader(FcrepoHeaders.FCREPO_IDENTIFIER) != null) {
087           base.append(in.getHeader(FcrepoHeaders.FCREPO_IDENTIFIER, String.class));
088        } else if (in.getHeader(JmsHeaders.IDENTIFIER) != null) {
089           base.append(in.getHeader(JmsHeaders.IDENTIFIER, String.class));
090        }
091        return base.toString();
092    }
093
094    /**
095     * Create a DELETE WHERE { ... } statement from the provided subject
096     *
097     * @param subject the subject of the triples to delete.
098     * @param namedGraph an optional named graph
099     * @return the delete statement
100     */
101    public static String deleteWhere(final String subject, final String namedGraph) {
102        final StringBuilder stmt = new StringBuilder("DELETE WHERE { ");
103
104        if (!StringUtils.isBlank(namedGraph)) {
105            stmt.append("GRAPH ");
106            stmt.append("<" + encode(namedGraph) + ">");
107            stmt.append(" { ");
108        }
109
110        stmt.append("<" + encode(subject) + ">");
111        stmt.append(" ?p ?o ");
112
113        if (!StringUtils.isBlank(namedGraph)) {
114            stmt.append("} ");
115        }
116
117        stmt.append("}");
118        return stmt.toString();
119    }
120
121    /**
122     *  Create an INSERT DATA { ... } update query with the provided ntriples
123     *
124     *  @param serializedGraph the triples to insert
125     *  @param namedGraph an optional named graph
126     *  @return the insert statement
127     */
128    public static String insertData(final String serializedGraph, final String namedGraph) {
129        final StringBuilder query = new StringBuilder("INSERT DATA { ");
130
131        if (!StringUtils.isBlank(namedGraph)) {
132            query.append("GRAPH <");
133            query.append(encode(namedGraph));
134            query.append("> { ");
135        }
136
137        query.append(serializedGraph);
138
139        if (!StringUtils.isBlank(namedGraph)) {
140            query.append("} ");
141        }
142
143        query.append("}");
144        return query.toString();
145    }
146}
147