001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 (the 006 * "License"); you may not use this file except in compliance with the 007 * License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.http.header; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021import java.util.*; 022import java.util.function.*; 023 024import org.apache.juneau.commons.http.*; 025 026 027/** 028 * Base for comma-separated tokens with optional q-values. 029 * 030 * @since 9.2.1 031 */ 032@SuppressWarnings({ 033 "java:S2160", // equals/hashCode are inherited from HttpHeaderBean (name and wire value); lazySupplier/lazyMode only control how the value is produced 034 "java:S9149", // Public Juneau DSL factory; hiding parent of()/create() is intentional. 035 "unchecked" // Supplier<?> is cast to Supplier<String>/Supplier<StringRanges> according to the lazyMode discriminator chosen by the factory methods 036}) 037public class HttpStringRangesHeader extends HttpHeaderBean { 038 039 public static final int LAZY_WIRE_STRING = 0; 040 public static final int LAZY_STRING_RANGES = 1; 041 042 private final StringRanges cachedForStringOrDirect; 043 private final Supplier<?> lazySupplier; 044 private final int lazyMode; 045 046 /** 047 * Creates an {@link HttpStringRangesHeader} by parsing the given wire-format value. 048 * 049 * @param name Header name. Must not be {@code null}. 050 * @param wireValue Wire value (e.g. {@code "gzip;q=0.5, identity"}). May be {@code null}. 051 * @return A new instance. Never {@code null}. 052 */ 053 public static HttpStringRangesHeader of(String name, String wireValue) { 054 return new HttpStringRangesHeader(name, wireValue); 055 } 056 057 /** 058 * Creates an {@link HttpStringRangesHeader} with the given typed value. 059 * 060 * @param name Header name. Must not be {@code null}. 061 * @param typedValue The string-ranges value. May be {@code null}. 062 * @return A new instance. Never {@code null}. 063 */ 064 public static HttpStringRangesHeader of(String name, StringRanges typedValue) { 065 return new HttpStringRangesHeader(name, typedValue); 066 } 067 068 protected HttpStringRangesHeader(String name, String value) { 069 super(name, value); 070 this.cachedForStringOrDirect = value == null ? null : StringRanges.of(value); 071 this.lazySupplier = null; 072 this.lazyMode = -1; 073 } 074 075 protected HttpStringRangesHeader(String name, StringRanges value) { 076 super(name, value == null ? null : value.toString()); 077 this.cachedForStringOrDirect = value; 078 this.lazySupplier = null; 079 this.lazyMode = -1; 080 } 081 082 protected HttpStringRangesHeader(String name, Supplier<?> supplier, int lazyMode) { 083 super(name, lazyMode == LAZY_WIRE_STRING 084 ? ((Supplier<String>) supplier)::get 085 : () -> { 086 var m = ((Supplier<StringRanges>) supplier).get(); 087 if (m == null) 088 return null; 089 return m.toString(); 090 }); 091 this.cachedForStringOrDirect = null; 092 this.lazySupplier = supplier; 093 this.lazyMode = lazyMode; 094 } 095 096 public Optional<StringRanges> asStringRanges() { 097 return o(toStringRanges()); 098 } 099 100 public StringRange getRange(int index) { 101 var x = toStringRanges(); 102 return x == null ? null : x.getRange(index); 103 } 104 105 public int match(List<String> names) { 106 var x = toStringRanges(); 107 return x == null ? -1 : x.match(names); 108 } 109 110 public StringRanges orElse(StringRanges other) { 111 var x = toStringRanges(); 112 return nn(x) ? x : other; 113 } 114 115 public StringRanges toStringRanges() { 116 if (lazyMode == LAZY_STRING_RANGES) 117 return ((Supplier<StringRanges>) lazySupplier).get(); 118 if (cachedForStringOrDirect != null) 119 return cachedForStringOrDirect; 120 var v = super.getValue(); 121 return v == null ? null : StringRanges.of(v); 122 } 123}