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.http.commons.domain;
017
018import org.glassfish.jersey.message.internal.HttpHeaderReader;
019
020import javax.servlet.http.HttpServletResponse;
021import java.text.ParseException;
022import java.util.HashMap;
023import java.util.Map;
024
025/**
026 * Parse a single prefer tag, value and any optional parameters
027 *
028 * @author cabeer
029 */
030public class PreferTag implements Comparable<PreferTag> {
031    private final String tag;
032    private String value = "";
033    private Map<String, String> params = new HashMap<>();
034
035    /**
036     * Create an empty PreferTag
037     * @return the empty PreferTag
038     */
039    public static PreferTag emptyTag() {
040        try {
041            return new PreferTag((String)null);
042        } catch (final ParseException e) {
043            throw new AssertionError(e);
044        }
045    }
046
047    /**
048     * Create a new PreferTag from an existing tag
049     * @param preferTag the preferTag
050     */
051    public PreferTag(final PreferTag preferTag) {
052        tag = preferTag.getTag();
053        value = preferTag.getValue();
054        params = preferTag.getParams();
055    }
056
057    /**
058     * Parse the prefer tag and parameters out of the header
059     * @param reader the reader
060     * @throws ParseException if parse exception occurred
061     */
062    public PreferTag(final HttpHeaderReader reader) throws ParseException {
063
064        // Skip any white space
065        reader.hasNext();
066
067        if (reader.hasNext()) {
068            tag = reader.nextToken();
069
070            if (reader.hasNextSeparator('=', true)) {
071                reader.next();
072
073                value = reader.nextTokenOrQuotedString();
074            }
075
076            if (reader.hasNext()) {
077                params = HttpHeaderReader.readParameters(reader);
078                if ( params == null ) {
079                    params = new HashMap<>();
080                }
081            }
082        } else {
083            tag = "";
084        }
085    }
086
087    /**
088     * Create a blank prefer tag
089     * @param inputTag the input tag
090     * @throws ParseException if parse exception occurred
091     */
092    public PreferTag(final String inputTag) throws ParseException {
093        this(HttpHeaderReader.newInstance(inputTag));
094    }
095
096    /**
097     * Get the tag name
098     * @return tag name
099     */
100    public String getTag() {
101        return tag;
102    }
103
104    /**
105     * Get the default value for the tag
106     * @return default value for the tag
107     */
108    public String getValue() {
109        return value;
110    }
111
112    /**
113     * Get any additional parameters for the prefer tag
114     * @return additional parameters for the prefer tag
115     */
116    public Map<String,String> getParams() {
117        return params;
118    }
119
120    /**
121     * Add appropriate response headers to indicate that the incoming preferences were acknowledged
122     * @param servletResponse the servlet response
123     */
124    public void addResponseHeaders(final HttpServletResponse servletResponse) {
125        if (!value.equals("minimal")) {
126            servletResponse.addHeader("Preference-Applied", "return=representation");
127        } else {
128            servletResponse.addHeader("Preference-Applied", "return=minimal");
129        }
130        servletResponse.addHeader("Vary", "Prefer");
131    }
132
133    /**
134     * We consider tags with the same name to be equal, because <a
135     * href="http://tools.ietf.org/html/rfc7240#page-4">the definition of Prefer headers</a> does not permit that tags
136     * with the same name be consumed except by selecting for the first appearing tag.
137     *
138     * @see java.lang.Comparable#compareTo(java.lang.Object)
139     */
140    @Override
141    public int compareTo(final PreferTag otherTag) {
142        return getTag().compareTo(otherTag.getTag());
143    }
144
145    @Override
146    public boolean equals(final Object obj) {
147        if ((obj != null) && (obj instanceof PreferTag)) {
148            return getTag().equals(((PreferTag) obj).getTag());
149        } else {
150            return false;
151        }
152    }
153
154    @Override
155    public int hashCode() {
156        if (getTag() == null) {
157            return 0;
158        }
159
160        return getTag().hashCode();
161    }
162}