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.*;
020import static org.apache.juneau.commons.utils.StringUtils.*;
021
022import java.util.*;
023import java.util.function.*;
024
025/**
026 * Base for long headers.
027 *
028 * @since 9.2.1
029 */
030@SuppressWarnings({
031   "java:S2160", // equals() on HttpHeaderBean uses name + getValue(); typed state is reflected in getValue()
032   "java:S9149", // Public Juneau DSL factory; hiding parent of()/create() is intentional.
033   "unchecked" // Supplier<?> branches cast to typed suppliers after lazy-mode check
034})
035public class HttpLongHeader extends HttpHeaderBean {
036
037   public static final int LAZY_WIRE_STRING = 0;
038   public static final int LAZY_LONG = 1;
039
040   private final Long value;
041   private final Supplier<?> lazySupplier;
042   private final int lazyMode;
043
044   /**
045    * Creates an {@link HttpLongHeader} by parsing the given wire-format value.
046    *
047    * @param name Header name. Must not be {@code null}.
048    * @param wireValue Wire value. May be {@code null} or empty.
049    * @return A new instance. Never {@code null}.
050    */
051   public static HttpLongHeader of(String name, String wireValue) {
052      return new HttpLongHeader(name, wireValue);
053   }
054
055   /**
056    * Creates an {@link HttpLongHeader} with the given typed value.
057    *
058    * @param name Header name. Must not be {@code null}.
059    * @param typedValue The long value. May be {@code null}.
060    * @return A new instance. Never {@code null}.
061    */
062   public static HttpLongHeader of(String name, Long typedValue) {
063      return new HttpLongHeader(name, typedValue);
064   }
065
066   /**
067    * Constructor.
068    *
069    * @param name Header name. Must not be <jk>null</jk>.
070    * @param wireValue Wire value. Can be <jk>null</jk> or empty, in which case the parsed value is <jk>null</jk>.
071    */
072   protected HttpLongHeader(String name, String wireValue) {
073      super(name, wireValue);
074      this.value = toLong(wireValue);
075      this.lazySupplier = null;
076      this.lazyMode = -1;
077   }
078
079   /**
080    * Constructor.
081    *
082    * @param name Header name. Must not be <jk>null</jk>.
083    * @param typedValue The long value. Can be <jk>null</jk>, in which case the parsed value is <jk>null</jk>.
084    */
085   protected HttpLongHeader(String name, Long typedValue) {
086      super(name, s(typedValue));
087      this.value = typedValue;
088      this.lazySupplier = null;
089      this.lazyMode = -1;
090   }
091
092   /**
093    * Constructor with lazy value supplier.
094    *
095    * @param name Header name. Must not be <jk>null</jk>.
096    * @param supplier The lazy value supplier. Must not be <jk>null</jk>.
097    * @param lazyMode Either {@link #LAZY_WIRE_STRING} or {@link #LAZY_LONG}.
098    */
099   protected HttpLongHeader(String name, Supplier<?> supplier, int lazyMode) {
100      super(name, lazyMode == LAZY_WIRE_STRING
101         ? ((Supplier<String>) supplier)::get
102         : () -> s(((Supplier<Long>) supplier).get()));
103      this.value = null;
104      this.lazySupplier = supplier;
105      this.lazyMode = lazyMode;
106   }
107
108   public Optional<Long> asLong() {
109      return o(toLong());
110   }
111
112   /**
113    * Returns the wire-format value of this header.
114    *
115    * @return The wire value, or <jk>null</jk> if the value is unset.
116    */
117   @Override
118   public String getValue() {
119      return s(toLong());
120   }
121
122   /**
123    * Returns the parsed value of this header, or the specified default if unset.
124    *
125    * @param other The default value. Can be <jk>null</jk>.
126    * @return The parsed value, or <c>other</c> if the value is unset. Can be <jk>null</jk> if <c>other</c> is <jk>null</jk>.
127    */
128   public Long orElse(Long other) {
129      return asLong().orElse(other);
130   }
131
132   /**
133    * Returns the parsed value of this header.
134    *
135    * @return The parsed value, or <jk>null</jk> if the value is unset.
136    */
137   public Long toLong() {
138      if (lazyMode == LAZY_LONG)
139         return ((Supplier<Long>) lazySupplier).get();
140      if (value != null)
141         return value;
142      return toLong(super.getValue());
143   }
144
145   private static Long toLong(String value) {
146      if (value == null)
147         return null;
148      return parseLong(value, () -> iaex("Value '%s' could not be parsed as a long.", value));
149   }
150}