001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014 015package org.basepom.mojo.propertyhelper.definitions; 016 017import static com.google.common.base.Preconditions.checkNotNull; 018 019import org.basepom.mojo.propertyhelper.FieldContext; 020import org.basepom.mojo.propertyhelper.ValueCache; 021import org.basepom.mojo.propertyhelper.ValueProvider; 022import org.basepom.mojo.propertyhelper.fields.DateField; 023 024import java.io.IOException; 025import java.time.Instant; 026import java.time.ZoneId; 027import java.time.ZonedDateTime; 028import java.time.format.DateTimeFormatter; 029import java.time.format.DateTimeParseException; 030import java.util.Optional; 031import java.util.StringJoiner; 032import java.util.function.Function; 033 034import com.google.common.annotations.VisibleForTesting; 035 036public class DateDefinition extends FieldDefinition<ZonedDateTime> { 037 038 /** 039 * Timezone for this date. Field injected by Maven. 040 */ 041 String timezone = null; 042 043 /** 044 * Value for this date. Field injected by Maven. 045 */ 046 Long value = null; 047 048 public DateDefinition() { 049 } 050 051 @VisibleForTesting 052 DateDefinition(String id) { 053 super(id); 054 } 055 056 public ZoneId getTimezone() { 057 return Optional.ofNullable(timezone) 058 .map(ZoneId::of) 059 .orElse(ZoneId.systemDefault()); 060 } 061 062 public Optional<Long> getValue() { 063 return Optional.ofNullable(value); 064 } 065 066 @Override 067 public DateField createField(FieldContext context, ValueCache valueCache) throws IOException { 068 checkNotNull(context, "context is null"); 069 checkNotNull(valueCache, "valueCache is null"); 070 071 check(); 072 073 final ValueProvider dateValue = valueCache.getValueProvider(this); 074 return new DateField(this, dateValue, context); 075 } 076 077 @Override 078 public Function<ZonedDateTime, String> getPreFormat() { 079 DateTimeFormatter dateTimeFormatter = getFormatter().orElseGet(this::getFallbackFormatter); 080 return v -> v == null ? "" : dateTimeFormatter.format(v); 081 } 082 083 @Override 084 public Function<String, String> getPostFormat() { 085 return Function.identity(); 086 } 087 088 public Function<String, ZonedDateTime> getParser() { 089 return value -> getFormatter().map(f -> { 090 try { 091 return ZonedDateTime.parse(value, f); 092 } catch (DateTimeParseException e) { 093 return null; 094 } 095 }).orElseGet(() -> parseLong(value).map(getLongParser()) 096 .orElseGet(() -> ZonedDateTime.parse(value, getFallbackFormatter()))); 097 } 098 099 private Optional<Long> parseLong(String value) { 100 try { 101 return Optional.of(Long.parseLong(value)); 102 } catch (NumberFormatException e) { 103 return Optional.empty(); 104 } 105 } 106 107 public Function<Long, ZonedDateTime> getLongParser() { 108 return longValue -> ZonedDateTime.ofInstant(Instant.ofEpochMilli(longValue), getTimezone()); 109 } 110 111 public Optional<DateTimeFormatter> getFormatter() { 112 return Optional.ofNullable(format) 113 .map(DateTimeFormatter::ofPattern) 114 .map(formatter -> formatter.withZone(getTimezone())); 115 } 116 117 public DateTimeFormatter getFallbackFormatter() { 118 return DateTimeFormatter.ISO_DATE_TIME.withZone(getTimezone()); 119 } 120 121 @Override 122 public String toString() { 123 return new StringJoiner(", ", DateDefinition.class.getSimpleName() + "[", "]") 124 .add("timezone='" + timezone + "'") 125 .add("value=" + value) 126 .add(super.toString()) 127 .toString(); 128 } 129}