001/*
002 *  Copyright 2018 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.core.model.type;
017
018import java.io.IOException;
019import java.time.LocalDate;
020import java.time.format.DateTimeParseException;
021import java.util.ArrayList;
022import java.util.List;
023import java.util.Optional;
024import java.util.stream.Stream;
025
026import org.apache.commons.lang3.StringUtils;
027import org.apache.commons.lang3.tuple.Triple;
028
029import org.ametys.core.util.DateUtils;
030import org.ametys.runtime.model.compare.DataChangeType;
031import org.ametys.runtime.model.compare.DataChangeTypeDetail;
032import org.ametys.runtime.model.exception.BadItemTypeException;
033import org.ametys.runtime.model.type.DataContext;
034
035/**
036 * Abstract class for date element types
037 */
038public abstract class AbstractDateElementType extends AbstractElementType<LocalDate>
039{
040    @Override
041    public LocalDate convertValue(Object value)
042    {
043        if (value instanceof String)
044        {
045            if (StringUtils.isEmpty((String) value))
046            {
047                return null;
048            }
049            
050            try
051            {
052                return DateUtils.parseLocalDate((String) value);
053            }
054            catch (DateTimeParseException e)
055            {
056                throw new BadItemTypeException("Unable to cast '" + value + "' to a date", e);
057            }
058        }
059            
060        return super.convertValue(value);
061    }
062
063    @Override
064    public String toString(LocalDate value)
065    {
066        if (value == null)
067        {
068            return null;
069        }
070        
071        return DateUtils.localDateToString(value);
072    }
073
074    public Object fromJSONForClient(Object json)
075    {
076        if (json == null)
077        {
078            return json;
079        }
080        else if (json instanceof String)
081        {
082            return convertValue(json);
083        }
084        else if (json instanceof List)
085        {
086            @SuppressWarnings("unchecked")
087            List<String> jsonList = (List<String>) json;
088            List<LocalDate> dateList = new ArrayList<>();
089            for (String singleJSON : jsonList)
090            {
091                dateList.add(castValue(singleJSON));
092            }
093            return dateList.toArray(new LocalDate[dateList.size()]);
094        }
095        else
096        {
097            throw new IllegalArgumentException("Try to convert the non Date JSON object '" + json + "' into a Date");
098        }
099    }
100    
101    @Override
102    protected Object _singleValueToJSON(LocalDate value, DataContext context)
103    {
104        return toString(value);
105    }
106    
107    @Override
108    protected Stream<Triple<DataChangeType, DataChangeTypeDetail, String>> _compareSingleValues(LocalDate value1, LocalDate value2) throws IOException
109    {
110        return Stream.of(ModelItemTypeHelper.compareSingleDates(value1, value2, StringUtils.EMPTY))
111                     .filter(Optional::isPresent)
112                     .map(Optional::get);
113    }
114    
115    public boolean isSimple()
116    {
117        return true;
118    }
119}