001/**
002 * Copyright (c) 2012, 2015, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * 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, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016package org.javamoney.moneta.convert;
017
018import java.time.LocalDate;
019import java.time.temporal.ChronoUnit;
020import java.util.ArrayList;
021import java.util.Comparator;
022import java.util.List;
023import java.util.Objects;
024import java.util.function.Predicate;
025import java.util.stream.Stream;
026
027import javax.money.CurrencyUnit;
028import javax.money.convert.ConversionQuery;
029import javax.money.convert.ConversionQueryBuilder;
030/**
031 * Class builder to find exchange rate from historical.
032 * @see {@link HistoricConversionQueryBuilder#of(CurrencyUnit)}
033 * @author Otavio Santana
034 * @deprecated
035 */
036@Deprecated
037public final class HistoricConversionQueryBuilder {
038
039        private final ConversionQueryBuilder conversionQueryBuilder;
040
041        private HistoricConversionQueryBuilder(ConversionQueryBuilder conversionQuery) {
042                this.conversionQueryBuilder = conversionQuery;
043        }
044
045        /**
046         *Create a {@link HistoricConversionQueryBuilder} from currency
047         * @param currencyUnit to be used in term currency.
048         * @return a HistoricConversionQuery from currency
049         * @throws NullPointerException when currency is null
050         */
051        public static HistoricConversionQueryBuilder of(CurrencyUnit currencyUnit) {
052                Objects.requireNonNull(currencyUnit, "Currency is required");
053                return new HistoricConversionQueryBuilder(ConversionQueryBuilder.of()
054                .setTermCurrency(currencyUnit));
055        }
056
057        /**
058         * Set a specify day on {@link HistoricConversionQueryBuilder}
059         * @param localDate
060         * @return this
061         * @throws NullPointerException when {@link LocalDate} is null
062         */
063        public HistoricConversionQueryWithDayBuilder withDay(LocalDate localDate) {
064                Objects.requireNonNull(localDate);
065                conversionQueryBuilder.set(LocalDate.class, localDate);
066
067                return new HistoricConversionQueryWithDayBuilder(conversionQueryBuilder);
068        }
069
070        /**
071         *Set days on {@link HistoricConversionQueryBuilder} to be used on ExchangeRateProvider,
072         *these parameters will sort to most recent to be more priority than other.
073         * @param localDates
074         * @return this
075         * @throws IllegalArgumentException when is empty or the parameter has an null value
076         */
077        @SafeVarargs
078        public final HistoricConversionQueryWithDayBuilder withDays(LocalDate... localDates) {
079                Objects.requireNonNull(localDates);
080                if(localDates.length == 0) {
081                        throw new IllegalArgumentException("LocalDates are required");
082                }
083
084                if(Stream.of(localDates).anyMatch(Predicate.isEqual(null))) {
085                        throw new IllegalArgumentException("LocalDates cannot be null");
086                }
087                Comparator<LocalDate> comparator = Comparator.naturalOrder();
088                LocalDate[] sortedDates =  Stream.of(localDates).sorted(comparator.reversed()).toArray(LocalDate[]::new);
089                conversionQueryBuilder.set(LocalDate[].class, sortedDates);
090
091                return new HistoricConversionQueryWithDayBuilder(conversionQueryBuilder);
092        }
093
094        /**
095         *Set days on {@link HistoricConversionQueryBuilder} to be used on ExchangeRateProvider,
096         *these parameters, different of  {@link HistoricConversionQueryBuilder#withDays(LocalDate...)}, consider the order already defined.
097         * @param localDates
098         * @return this
099         * @throws IllegalArgumentException when is empty or the parameter has an null value
100         */
101        @SafeVarargs
102        public final HistoricConversionQueryWithDayBuilder withDaysPriorityDefined(LocalDate... localDates) {
103                Objects.requireNonNull(localDates);
104                if(localDates.length == 0) {
105                        throw new IllegalArgumentException("LocalDates are required");
106                }
107
108                if(Stream.of(localDates).anyMatch(Predicate.isEqual(null))) {
109                        throw new IllegalArgumentException("LocalDates cannot be null");
110                }
111                conversionQueryBuilder.set(LocalDate[].class, localDates);
112
113                return new HistoricConversionQueryWithDayBuilder(conversionQueryBuilder);
114        }
115
116        /**
117         * Set the period of days on {@link HistoricConversionQueryBuilder}
118         *  to be used on ExchangeRateProvider,
119         * @param begin
120         * @param end
121         * @return this;
122         * <p>Example:</p>
123         * <pre>
124         * {@code
125         *LocalDate today = LocalDate.parse("2015-04-03");
126         *LocalDate yesterday = today.minusDays(1);
127         *LocalDate tomorrow = today.plusDays(1);
128         *ConversionQuery query = HistoricConversionQueryBuilder.of(real).onDaysBetween(yesterday, tomorrow).build();//the query with new LocalDate[] {tomorrow, today, yesterday}
129         * }
130         * </pre>
131         * @throws NullPointerException when either begin or end is null
132         * @throws IllegalArgumentException when the begin is bigger than end
133         */
134        public final HistoricConversionQueryWithDayBuilder withDaysBetween(LocalDate begin, LocalDate end) {
135                Objects.requireNonNull(begin);
136                Objects.requireNonNull(end);
137                if(end.isBefore(begin)) {
138                        throw new IllegalArgumentException("The end period should be bigger than the begin period.");
139                }
140
141                int days = (int) ChronoUnit.DAYS.between(begin, end);
142
143                List<LocalDate> dates = new ArrayList<>();
144                for(int index = days; index >= 0; index--) {
145                        dates.add(begin.plusDays(index));
146                }
147                conversionQueryBuilder.set(LocalDate[].class, dates.toArray(new LocalDate[dates.size()]));
148
149                return new HistoricConversionQueryWithDayBuilder(conversionQueryBuilder);
150        }
151
152        /**
153         * Create the {@link ConversionQuery} just with {@link CurrencyUnit}, to term currency, already defined.
154         * @return the conversion query
155         */
156        public ConversionQuery build() {
157                return conversionQueryBuilder.build();
158        }
159
160        @Override
161        public String toString() {
162            StringBuilder sb = new StringBuilder();
163            sb.append(HistoricConversionQueryBuilder.class.getName())
164            .append('{').append(" conversionQueryBuilder: ")
165            .append(conversionQueryBuilder).append('}');
166                return sb.toString();
167        }
168
169        public class HistoricConversionQueryWithDayBuilder {
170
171                private final ConversionQueryBuilder conversionQueryBuilder;
172
173                HistoricConversionQueryWithDayBuilder(
174                                ConversionQueryBuilder conversionQueryBuilder) {
175                        this.conversionQueryBuilder = conversionQueryBuilder;
176                }
177
178                /**
179                 * Create the {@link ConversionQuery} with {@link LocalDate} and {@link CurrencyUnit} to term currency already defined.
180                 * @return the conversion query
181                 */
182                public ConversionQuery build() {
183                        return conversionQueryBuilder.build();
184                }
185
186                @Override
187                public String toString() {
188                    StringBuilder sb = new StringBuilder();
189                    sb.append(HistoricConversionQueryWithDayBuilder.class.getName())
190                    .append('{').append(" conversionQueryBuilder: ")
191                    .append(conversionQueryBuilder).append('}');
192                        return sb.toString();
193                }
194
195        }
196
197}