001/*
002 * Copyright (c) 2012, 2015, 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.function;
017
018import java.util.Objects;
019
020import javax.money.CurrencyUnit;
021import javax.money.MonetaryAmount;
022
023import org.javamoney.moneta.FastMoney;
024
025/**
026 * the default implementations of {@link MonetarySummaryStatistics} This
027 * implementations cannot do exchange rate
028 *
029 * @author otaviojava
030 * @author Anatole Tresch
031 * @author Werner Keil
032 */
033public class DefaultMonetarySummaryStatistics implements MonetarySummaryStatistics {
034
035    private final MonetaryAmount empty;
036
037    protected long count;
038
039    protected MonetaryAmount min;
040
041    protected MonetaryAmount max;
042
043    protected MonetaryAmount sum;
044
045    protected MonetaryAmount average;
046
047    /**
048     * Creates a new instance, targeting the given
049     * {@link javax.money.CurrencyUnit}.
050     *
051     * @param currencyUnit the target currency, not null.
052     */
053    protected DefaultMonetarySummaryStatistics(CurrencyUnit currencyUnit) {
054        empty = FastMoney.of(0, Objects.requireNonNull(currencyUnit));
055        setSameMonetary(empty);
056    }
057    
058    /**
059     * Creates a new instance, targeting the given
060     * {@link javax.money.CurrencyUnit}.
061     *
062     * @param currencyUnit the target currency, not null.
063     */
064    public static DefaultMonetarySummaryStatistics of(CurrencyUnit currencyUnit) {
065        return new DefaultMonetarySummaryStatistics(currencyUnit);
066    }
067
068    @Override
069    public void accept(MonetaryAmount amount) {
070
071        if (!empty.getCurrency().equals(
072                Objects.requireNonNull(amount).getCurrency())) {
073            return;
074        }
075        if (isEmpty()) {
076            setSameMonetary(amount);
077            count++;
078        } else {
079            doSummary(amount);
080        }
081    }
082
083    @Override
084    public CurrencyUnit getCurrencyUnit() {
085        return empty.getCurrency();
086    }
087
088    @Override
089    public MonetarySummaryStatistics combine(
090            MonetarySummaryStatistics summaryStatistics) {
091        Objects.requireNonNull(summaryStatistics);
092
093        if (!equals(summaryStatistics)) {
094            return this;
095        }
096        min = MonetaryFunctions.min(min, summaryStatistics.getMin());
097        max = MonetaryFunctions.max(max, summaryStatistics.getMax());
098        sum = sum.add(summaryStatistics.getSum());
099        count += summaryStatistics.getCount();
100        average = sum.divide(count);
101        return this;
102    }
103
104    private void doSummary(MonetaryAmount monetaryAmount) {
105        min = MonetaryFunctions.min(min, monetaryAmount);
106        max = MonetaryFunctions.max(max, monetaryAmount);
107        sum = sum.add(monetaryAmount);
108        average = sum.divide(++count);
109    }
110
111    private boolean isEmpty() {
112        return count == 0;
113    }
114
115    private void setSameMonetary(MonetaryAmount monetary) {
116        min = monetary;
117        max = monetary;
118        sum = monetary;
119        average = monetary;
120    }
121
122
123    @Override
124    public long getCount() {
125        return count;
126    }
127
128    @Override
129    public MonetaryAmount getMin() {
130        return min;
131    }
132
133
134    @Override
135    public MonetaryAmount getMax() {
136        return max;
137    }
138
139
140    @Override
141    public MonetaryAmount getSum() {
142        return sum;
143    }
144
145
146    @Override
147    public MonetaryAmount getAverage() {
148        return average;
149    }
150
151    @Override
152    public boolean equals(Object obj) {
153        if (DefaultMonetarySummaryStatistics.class.isInstance(obj)) {
154            DefaultMonetarySummaryStatistics other = DefaultMonetarySummaryStatistics.class
155                    .cast(obj);
156            return Objects.equals(empty.getCurrency(),
157                    other.empty.getCurrency());
158        }
159        return false;
160    }
161
162    @Override
163    public int hashCode() {
164        return empty.getCurrency().hashCode();
165    }
166
167    @Override
168    public String toString() {
169        String sb = "[currency: " + empty.getCurrency() + ',' +
170                "count:" + count + ',' +
171                "min:" + min + ',' +
172                "max:" + max + ',' +
173                "sum:" + sum + ',' +
174                "average:" + average + ']';
175        return sb;
176    }
177
178    @Override
179    public boolean isExchangeable() {
180        return false;
181    }
182
183    @Override
184    public MonetarySummaryStatistics to(CurrencyUnit unit) {
185        throw new UnsupportedOperationException(
186                "the default implementation of MonetarySummaryStatistics cannot do exchange rate");
187    }
188}