org.apache.marmotta.platform.ldp.webservices.PreferHeader.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.marmotta.platform.ldp.webservices.PreferHeader.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.marmotta.platform.ldp.webservices;

import org.apache.commons.lang3.StringUtils;
import org.apache.marmotta.platform.core.exception.InvalidArgumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * HTML Prefer Header.
 *
 * @author Jakob Frank
 * @see <a href="http://www.ietf.org/rfc/rfc7240.txt">http://www.ietf.org/rfc/rfc7240.txt</a>
 */
public class PreferHeader {

    public static final String PREFERENCE_RESPOND_ASYNC = "respond-async";
    public static final String PREFERENCE_RETURN = "return";
    public static final String RETURN_REPRESENTATION = "representation";
    public static final String RETURN_MINIMAL = "minimal";
    public static final String PREFERENCE_WAIT = "wait";
    public static final String PREFERENCE_HANDLING = "handling";
    public static final String HANDLING_STRICT = "strict";
    public static final String HANDLING_LENIENT = "lenient";

    public static final String RETURN_PARAM_INCLUDE = "include";
    public static final String RETURN_PARAM_OMIT = "omit";

    public static Logger log = LoggerFactory.getLogger(PreferHeader.class);

    private String preference, preferenceValue;

    private Map<String, String> params;

    private PreferHeader(String preference) {
        this.preference = preference;
        this.params = new LinkedHashMap<>();
    }

    /**
     * Get the preference,
     * e.g. {@code foo} from {@code Prefer: foo="bar"}
     *
     * @return the preference of the prefer-header
     */
    public String getPreference() {
        return preference;
    }

    /**
     * Get the value of the preference,
     * e.g. {@code bar} from {@code Prefer: foo="bar"}.
     * @return the preference value of the prefer-header
     */
    public String getPreferenceValue() {
        return preferenceValue;
    }

    /**
     * Get the parameters of the prefer-header.
     * @return the prefer-parameters
     */
    public Map<String, String> getParams() {
        return Collections.unmodifiableMap(params);
    }

    /**
     * Get the parameter value of the prefer-header,
     * e,g, {@code val2} from {@code Prefer: foo="bar"; a1="val1"; a2="val2"} for {@code header.getParamValue("a2")}.
     * @param param the param to get the value of
     * @return the value of the requested parameter, or {@code null}
     */
    public String getParamValue(String param) {
        return params.get(param);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(preference);
        if (StringUtils.isNotBlank(preferenceValue)) {
            sb.append("=\"").append(preferenceValue).append("\"");
        }
        for (String param : params.keySet()) {
            sb.append("; ").append(param);
            final String value = params.get(param);
            if (StringUtils.isNotBlank(value)) {
                sb.append("=\"").append(value).append("\"");
            }
        }

        return sb.toString();
    }

    /**
     * Parse a PreferHeader.
     * @param headerValue the header value to parse
     * @return the parsed PreferHeader
     */
    public static PreferHeader valueOf(String headerValue) {
        if (StringUtils.isBlank(headerValue)) {
            log.error("Empty Prefer-Header - what should I do now?");
            throw new InvalidArgumentException();
        }

        String pref = null, val = null;
        final Map<String, String> params = new LinkedHashMap<>();
        final String[] parts = headerValue.split("\\s*;\\s");
        for (int i = 0; i < parts.length; i++) {
            final String part = parts[i];
            final String[] kv = part.split("\\s*=\\s*", 2);
            if (i == 0) {
                pref = StringUtils.trimToNull(kv[0]);
                if (kv.length > 1) {
                    val = StringUtils.trimToNull(StringUtils.removeStart(StringUtils.removeEnd(kv[1], "\""), "\""));
                }
            } else {
                String p, pval = null;
                p = StringUtils.trimToNull(kv[0]);
                if (kv.length > 1) {
                    pval = StringUtils
                            .trimToNull(StringUtils.removeStart(StringUtils.removeEnd(kv[1], "\""), "\""));
                }
                params.put(p, pval);
            }
        }

        final PreferHeader header = new PreferHeader(pref);
        header.preferenceValue = val;
        header.params = params;

        return header;
    }

    /**
     * Create and initialize a PreferBuilder for a {@code Prefer: respond-async} header.
     * @return initialized PreferBuilder
     */
    public static PreferBuilder preferRespondAsync() {
        return new PreferBuilder(PREFERENCE_RESPOND_ASYNC);
    }

    /**
     * Create and initialize a PreferBuilder for a {@code Prefer: return="representation"} header.
     * @return initialized PreferBuilder
     */
    public static PreferBuilder preferReturnRepresentation() {
        return new PreferBuilder(PREFERENCE_RETURN, RETURN_REPRESENTATION);
    }

    /**
     * Create and initialize a PreferBuilder for a {@code Prefer: return="minimal"} header.
     * @return initialized PreferBuilder
     */
    public static PreferBuilder preferReturnMinimal() {
        return new PreferBuilder(PREFERENCE_RETURN, RETURN_MINIMAL);
    }

    /**
     * Create and initialize a PreferBuilder for a {@code Prefer: wait="X"} header.
     * @param seconds seconds to wait, the <em>X</em> in the example.
     * @return initialized PreferBuilder
     */
    public static PreferBuilder preferWait(int seconds) {
        return new PreferBuilder(PREFERENCE_WAIT, String.valueOf(seconds));
    }

    /**
     * Create and initialize a PreferBuilder for a {@code Prefer: handling="strict"} header.
     * @return initialized PreferBuilder
     */
    public static PreferBuilder preferHandlingStrict() {
        return new PreferBuilder(PREFERENCE_HANDLING, HANDLING_STRICT);
    }

    /**
     * Create and initialize a PreferBuilder for a {@code Prefer: handling="lenient"} header.
     * @return initialized PreferBuilder
     */
    public static PreferBuilder preferHandlingLenient() {
        return new PreferBuilder(PREFERENCE_HANDLING, HANDLING_LENIENT);
    }

    /**
     * Create a PreferBuilder initialized with the provided PreferHeader.
     * @param prefer the PreferHeader used for initialisation
     * @return initialized PreferBuilder
     */
    public static PreferBuilder fromPrefer(PreferHeader prefer) {
        final PreferBuilder builder = new PreferBuilder(prefer.preference, prefer.preferenceValue);
        builder.params.putAll(prefer.params);
        return builder;
    }

    /**
     * Create a PreferBuilder for an arbitrary preference
     * @param preference the preference
     * @return initialized PreferBuilder
     */
    public static PreferBuilder prefer(String preference) {
        return prefer(preference, null);
    }

    /**
     * Create a PreferBuilder for an arbitrary preference
     * @param preference the preference
     * @param value the value of the preference
     * @return initialized PreferBuilder
     */
    private static PreferBuilder prefer(String preference, String value) {
        return new PreferBuilder(preference, value);
    }

    /**
     * Builder for PreferHeader
     */
    public static class PreferBuilder {

        private String preference;
        private String preferenceValue;
        private Map<String, String> params;

        private PreferBuilder(String preference) {
            this(preference, null);
        }

        private PreferBuilder(String preference, String preferenceValue) {
            this.preference = preference;
            this.preferenceValue = preferenceValue;
            this.params = new HashMap<>();
        }

        private PreferBuilder preference(String preference) {
            return preference(preference, null);
        }

        private PreferBuilder preference(String preference, String value) {
            this.preference = preference;
            this.preferenceValue = value;
            return this;
        }

        /**
         * Add a parameter (without value)
         * @param parameter the parameter to add
         * @return the PreferBuilder for chaining
         */
        public PreferBuilder parameter(String parameter) {
            this.params.put(parameter, null);
            return this;
        }

        /**
         * Add a parameter with the provided value. If the value is {@code null}, the parameter is removed.
         * @param parameter the parameter to add (or remove)
         * @param value the parameter value (or {@code null} to remove
         * @return the PreferBuilder for chaining
         */
        public PreferBuilder parameter(String parameter, String value) {
            if (value == null) {
                this.params.remove(parameter);
            } else {
                this.params.put(parameter, value);
            }
            return this;
        }

        /**
         * Add the provided parameters and their values. If the argument is {@code null}, all parameters will be removed.
         * @param params the parameters to add (or {@code null} to remove all parameters)
         * @return the PreferBuilder for chaining
         */
        public PreferBuilder parameters(Map<String, String> params) {
            if (params == null) {
                this.params.clear();
            } else {
                this.params.putAll(params);
            }
            return this;
        }

        /**
         * <strong>LDP specific:</strong> Add a "include" parameter for the given URIs.
         * @param ldpPreferUri the URIs to "include"
         * @return the PreferBuilder for chaining
         */
        public PreferBuilder include(String... ldpPreferUri) {
            return _ldp(RETURN_PARAM_INCLUDE, ldpPreferUri);
        }

        /**
         * <strong>LDP specific:</strong> Add a "omit" parameter for the given URIs.
         * @param ldpPreferUri the URIs to "omit"
         * @return the PreferBuilder for chaining
         */
        public PreferBuilder omit(String... ldpPreferUri) {
            return _ldp(RETURN_PARAM_OMIT, ldpPreferUri);
        }

        private PreferBuilder _ldp(String param, String... values) {
            if (values == null) {
                this.params.remove(param);
            } else {
                final StringBuilder sb = new StringBuilder();
                for (int i = 0; i < values.length; i++) {
                    if (i > 0) {
                        sb.append(" ");
                    }
                    sb.append(values[i]);
                }
                this.params.put(param, sb.toString());
            }
            return this;
        }

        /**
         * Create the PreferHeader. The builder can be reused.
         * @return the PreferHeader
         */
        public PreferHeader build() {
            final PreferHeader header = new PreferHeader(this.preference);
            header.preferenceValue = preferenceValue;
            header.params.putAll(params);
            return header;

        }

    }
}