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 006 * (the "License"); you may not use this file except in compliance with 007 * the 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.part; 018 019import static java.time.format.DateTimeFormatter.*; 020import static java.time.temporal.ChronoUnit.*; 021import static org.apache.juneau.commons.utils.Shorts.*; 022 023import java.time.*; 024import java.util.*; 025import java.util.function.*; 026 027/** 028 * An {@link org.apache.juneau.http.HttpPart} whose value is an ISO-8601 date-time. 029 * 030 * <p> 031 * Mirrors the semantics of {@code BasicDatePart} from {@code juneau-rest-common-classic} without 032 * the Apache HttpCore dependency. Values are parsed/formatted via 033 * {@link java.time.format.DateTimeFormatter#ISO_DATE_TIME}. 034 * 035 * @since 10.0.0 036 */ 037@SuppressWarnings({ 038 "java:S2160" // Equality is fully determined by name + getValue() in HttpPartBean; the typed fields are derived from the wire value and add no state to compare 039}) 040public class HttpDatePart extends HttpPartBean { 041 042 /** 043 * Creates an {@link HttpDatePart} with the given name and date value. 044 * 045 * @param name The part name. Must not be <jk>null</jk>. 046 * @param value The date value. May be <jk>null</jk>. 047 * @return A new instance. Never <jk>null</jk>. 048 */ 049 public static HttpDatePart of(String name, ZonedDateTime value) { 050 return new HttpDatePart(name, value); 051 } 052 053 /** 054 * Creates an {@link HttpDatePart} by parsing the given ISO-8601 wire value. 055 * 056 * @param name The part name. Must not be <jk>null</jk>. 057 * @param value The wire value. May be <jk>null</jk> or empty. 058 * @return A new instance. Never <jk>null</jk>. 059 */ 060 public static HttpDatePart ofString(String name, String value) { 061 return new HttpDatePart(name, value); 062 } 063 064 /** 065 * Creates an {@link HttpDatePart} with a lazy date supplier. 066 * 067 * @param name The part name. Must not be <jk>null</jk>. 068 * @param supplier Supplier for the date value. Must not be <jk>null</jk>. 069 * @return A new instance. Never <jk>null</jk>. 070 */ 071 public static HttpDatePart ofLazy(String name, Supplier<ZonedDateTime> supplier) { 072 return new HttpDatePart(name, supplier); 073 } 074 075 private final ZonedDateTime typedValue; 076 private final Supplier<ZonedDateTime> typedSupplier; 077 078 /** 079 * Constructor accepting an ISO-8601 wire-format string value. 080 * 081 * @param name The part name. Must not be <jk>null</jk>. 082 * @param value The wire value. May be <jk>null</jk> or empty. 083 */ 084 public HttpDatePart(String name, String value) { 085 super(name, value); 086 this.typedValue = ie(value) ? null : ZonedDateTime.from(ISO_DATE_TIME.parse(value)).truncatedTo(SECONDS); 087 this.typedSupplier = null; 088 } 089 090 /** 091 * Constructor accepting a {@link ZonedDateTime} value. 092 * 093 * @param name The part name. Must not be <jk>null</jk>. 094 * @param value The date value. May be <jk>null</jk>. 095 */ 096 public HttpDatePart(String name, ZonedDateTime value) { 097 super(name, value == null ? null : ISO_DATE_TIME.format(value)); 098 this.typedValue = value; 099 this.typedSupplier = null; 100 } 101 102 /** 103 * Constructor accepting a lazy {@link ZonedDateTime} supplier. 104 * 105 * @param name The part name. Must not be <jk>null</jk>. 106 * @param supplier Supplier for the date value. Must not be <jk>null</jk>. 107 */ 108 public HttpDatePart(String name, Supplier<ZonedDateTime> supplier) { 109 super(name, () -> { 110 var v = supplier.get(); 111 return v == null ? null : ISO_DATE_TIME.format(v); 112 }); 113 this.typedValue = null; 114 this.typedSupplier = supplier; 115 } 116 117 /** 118 * Returns the value as an {@link Optional}{@code <ZonedDateTime>}. 119 * 120 * @return The date value, wrapped in an {@link Optional}. Never <jk>null</jk>. 121 */ 122 public Optional<ZonedDateTime> asZonedDateTime() { 123 return o(toZonedDateTime()); 124 } 125 126 /** 127 * Returns the value if present, otherwise returns {@code other}. 128 * 129 * @param other The default value. 130 * @return The value or {@code other}. 131 */ 132 public ZonedDateTime orElse(ZonedDateTime other) { 133 var x = toZonedDateTime(); 134 return nn(x) ? x : other; 135 } 136 137 /** 138 * Returns the value as a {@link ZonedDateTime}, or {@code null} if not set. 139 * 140 * @return The date value, possibly {@code null}. 141 */ 142 public ZonedDateTime toZonedDateTime() { 143 if (typedSupplier != null) 144 return typedSupplier.get(); 145 return typedValue; 146 } 147}