/*
* Licensed to DuraSpace under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* DuraSpace 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.fcrepo.http.commons.domain;
import org.glassfish.jersey.message.internal.HttpHeaderReader;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* Parse a single prefer tag, value and any optional parameters
*
* @author cabeer
*/
public class PreferTag implements Comparable<PreferTag> {
private final String tag;
private String value = "";
private Map<String, String> params = new HashMap<>();
/**
* Create an empty PreferTag
* @return the empty PreferTag
*/
public static PreferTag emptyTag() {
return new PreferTag((String)null);
}
/**
* Create a new PreferTag from an existing tag
* @param preferTag the preferTag
*/
public PreferTag(final PreferTag preferTag) {
tag = preferTag.getTag();
value = preferTag.getValue();
params = preferTag.getParams();
}
/**
* Parse the prefer tag and parameters out of the header
* @param reader the reader
*/
public PreferTag(final HttpHeaderReader reader) {
// Skip any white space
reader.hasNext();
if (reader.hasNext()) {
try {
tag = Optional.ofNullable(reader.nextToken())
.map(CharSequence::toString).orElse(null);
if (reader.hasNextSeparator('=', true)) {
reader.next();
value = Optional.ofNullable(reader.nextTokenOrQuotedString())
. map(CharSequence::toString)
.orElse(null);
}
if (reader.hasNext()) {
params = HttpHeaderReader.readParameters(reader);
if ( params == null ) {
params = new HashMap<>();
}
}
} catch (ParseException e) {
throw new IllegalArgumentException("Could not parse 'Prefer' header", e);
}
} else {
tag = "";
}
}
/**
* Create a blank prefer tag
* @param inputTag the input tag
*/
public PreferTag(final String inputTag) {
this(HttpHeaderReader.newInstance(inputTag));
}
/**
* Get the tag name
* @return tag name
*/
public String getTag() {
return tag;
}
/**
* Get the default value for the tag
* @return default value for the tag
*/
public String getValue() {
return value;
}
/**
* Get any additional parameters for the prefer tag
* @return additional parameters for the prefer tag
*/
public Map<String,String> getParams() {
return params;
}
/**
* Add appropriate response headers to indicate that the incoming preferences were acknowledged
* @param servletResponse the servlet response
*/
public void addResponseHeaders(final HttpServletResponse servletResponse) {
if (!value.equals("minimal")) {
servletResponse.addHeader("Preference-Applied", "return=representation");
} else {
servletResponse.addHeader("Preference-Applied", "return=minimal");
}
servletResponse.addHeader("Vary", "Prefer");
}
/**
* We consider tags with the same name to be equal, because <a
* href="http://tools.ietf.org/html/rfc7240#page-4">the definition of Prefer headers</a> does not permit that tags
* with the same name be consumed except by selecting for the first appearing tag.
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(final PreferTag otherTag) {
return getTag().compareTo(otherTag.getTag());
}
@Override
public boolean equals(final Object obj) {
if ((obj != null) && (obj instanceof PreferTag)) {
return getTag().equals(((PreferTag) obj).getTag());
}
return false;
}
@Override
public int hashCode() {
if (getTag() == null) {
return 0;
}
return getTag().hashCode();
}
}