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}