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.fields;
016
017import org.basepom.mojo.propertyhelper.Field;
018import org.basepom.mojo.propertyhelper.FieldContext;
019import org.basepom.mojo.propertyhelper.ValueProvider;
020import org.basepom.mojo.propertyhelper.definitions.DateDefinition;
021
022import java.time.ZoneId;
023import java.time.ZonedDateTime;
024import java.time.temporal.ChronoUnit;
025import java.util.StringJoiner;
026
027import com.google.common.annotations.VisibleForTesting;
028
029
030public final class DateField extends Field<ZonedDateTime, DateDefinition> {
031
032    private final ValueProvider valueProvider;
033    private final ZoneId timezone;
034
035    @VisibleForTesting
036    public static DateField forTesting(DateDefinition dateDefinition, ValueProvider valueProvider) {
037        return new DateField(dateDefinition, valueProvider, FieldContext.forTesting());
038    }
039
040    public DateField(final DateDefinition dateDefinition, final ValueProvider valueProvider, FieldContext fieldContext) {
041        super(dateDefinition, fieldContext);
042
043        this.valueProvider = valueProvider;
044        this.timezone = dateDefinition.getTimezone();
045    }
046
047    @Override
048    public String getFieldName() {
049        return fieldDefinition.getId();
050    }
051
052    @Override
053    public String getValue() {
054        ZonedDateTime date = valueProvider.getValue()
055            .map(value -> fieldDefinition.getParser().apply(value))
056            .orElseGet(() -> fieldDefinition.getValue()
057                .map(fieldDefinition.getLongParser())
058                .orElseGet(this::now));
059
060        String result = formatResult(date);
061
062        if (fieldDefinition.getFormatter().isPresent()) {
063            // format was set, store time in the chosen format
064            valueProvider.setValue(result);
065        } else {
066            // not format was set. Store time as millis.
067            valueProvider.setValue(Long.toString(date.toInstant().toEpochMilli()));
068        }
069
070        return result;
071    }
072
073    @Override
074    public boolean isExposeAsProperty() {
075        return fieldDefinition.isExport();
076    }
077
078    private ZonedDateTime now() {
079        // code only saves in millisecond precision.
080        return ZonedDateTime.now(timezone).truncatedTo(ChronoUnit.MILLIS);
081    }
082
083    @Override
084    public String toString() {
085        return new StringJoiner(", ", DateField.class.getSimpleName() + "[", "]")
086            .add("valueProvider=" + valueProvider)
087            .toString();
088    }
089}