001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.http.header; 014 015import static org.apache.juneau.internal.StringUtils.*; 016 017import java.util.*; 018import java.util.function.*; 019 020import org.apache.juneau.http.*; 021 022/** 023 * Category of headers that consist of multiple parameterized string values. 024 * 025 * <p> 026 * <h5 class='figure'>Example</h5> 027 * <p class='bcode w800'> 028 * Accept: application/json;q=0.9,text/xml;q=0.1 029 * </p> 030 * 031 * <ul class='seealso'> 032 * <li class='extlink'>{@doc ExtRFC2616} 033 * </ul> 034*/ 035public class BasicMediaRangeArrayHeader extends BasicStringHeader { 036 037 private static final long serialVersionUID = 1L; 038 039 /** 040 * Convenience creator. 041 * 042 * @param name The header name. 043 * @param value 044 * The header value. 045 * <br>Can be any of the following: 046 * <ul> 047 * <li>{@link String} 048 * <li>Anything else - Converted to <c>String</c> then parsed. 049 * </ul> 050 * @return A new {@link BasicMediaRangeArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 051 */ 052 public static BasicMediaRangeArrayHeader of(String name, Object value) { 053 if (isEmpty(name) || value == null) 054 return null; 055 return new BasicMediaRangeArrayHeader(name, value); 056 } 057 058 /** 059 * Convenience creator using supplier. 060 * 061 * <p> 062 * Header value is re-evaluated on each call to {@link #getValue()}. 063 * 064 * @param name The header name. 065 * @param value 066 * The header value supplier. 067 * <br>Can be any of the following: 068 * <ul> 069 * <li>{@link String} 070 * <li>Anything else - Converted to <c>String</c> then parsed. 071 * </ul> 072 * @return A new {@link BasicMediaRangeArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 073 */ 074 public static BasicMediaRangeArrayHeader of(String name, Supplier<?> value) { 075 if (isEmpty(name) || value == null) 076 return null; 077 return new BasicMediaRangeArrayHeader(name, value); 078 } 079 080 private MediaRanges parsed; 081 082 /** 083 * Constructor 084 * 085 * @param name The header name. 086 * @param value 087 * <br>Can be any of the following: 088 * <ul> 089 * <li>{@link String} 090 * <li>Anything else - Converted to <c>String</c> then parsed. 091 * <li>A {@link Supplier} of anything on this list. 092 * </ul> 093 */ 094 public BasicMediaRangeArrayHeader(String name, Object value) { 095 super(name, value); 096 if (! isSupplier(value)) 097 parsed = parse(); 098 } 099 100 /** 101 * Returns this header as a {@link MediaRanges} object. 102 * 103 * @return This header as a {@link MediaRanges} object. 104 */ 105 public MediaRanges asMediaRanges() { 106 return parse(); 107 } 108 109 /** 110 * Given a list of media types, returns the best match for this <c>Accept</c> header. 111 * 112 * <p> 113 * Note that fuzzy matching is allowed on the media types where the <c>Accept</c> header may 114 * contain additional subtype parts. 115 * <br>For example, given identical q-values and an <c>Accept</c> value of <js>"text/json+activity"</js>, 116 * the media type <js>"text/json"</js> will match if <js>"text/json+activity"</js> or <js>"text/activity+json"</js> 117 * isn't found. 118 * <br>The purpose for this is to allow serializers to match when artifacts such as <c>id</c> properties are 119 * present in the header. 120 * 121 * <p> 122 * See {@doc https://www.w3.org/TR/activitypub/#retrieving-objects ActivityPub / Retrieving Objects} 123 * 124 * @param mediaTypes The media types to match against. 125 * @return The index into the array of the best match, or <c>-1</c> if no suitable matches could be found. 126 */ 127 public int match(List<? extends MediaType> mediaTypes) { 128 return asMediaRanges().match(mediaTypes); 129 } 130 131 /** 132 * Returns the {@link MediaRange} at the specified index. 133 * 134 * @param index The index position of the media range. 135 * @return The {@link MediaRange} at the specified index or <jk>null</jk> if the index is out of range. 136 */ 137 public MediaRange getRange(int index) { 138 return asMediaRanges().getRange(index); 139 } 140 141 /** 142 * Convenience method for searching through all of the subtypes of all the media ranges in this header for the 143 * presence of a subtype fragment. 144 * 145 * <p> 146 * For example, given the header <js>"text/json+activity"</js>, calling 147 * <code>hasSubtypePart(<js>"activity"</js>)</code> returns <jk>true</jk>. 148 * 149 * @param part The media type subtype fragment. 150 * @return <jk>true</jk> if subtype fragment exists. 151 */ 152 public boolean hasSubtypePart(String part) { 153 return asMediaRanges().hasSubtypePart(part); 154 } 155 156 /** 157 * Returns the media ranges that make up this object. 158 * 159 * @return The media ranges that make up this object. 160 */ 161 public List<MediaRange> getRanges() { 162 return asMediaRanges().getRanges(); 163 } 164 165 @Override /* Header */ 166 public String getValue() { 167 Object o = getRawValue(); 168 if (o == null) 169 return null; 170 return stringify(asMediaRanges()); 171 } 172 173 private MediaRanges parse() { 174 if (parsed != null) 175 return parsed; 176 Object o = getRawValue(); 177 if (o == null) 178 o = ""; 179 if (o instanceof MediaRanges) 180 return (MediaRanges)o; 181 return MediaRanges.of(o.toString()); 182 } 183}