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 */
032public class DefaultMonetarySummaryStatistics implements MonetarySummaryStatistics {
033
034    private final MonetaryAmount empty;
035
036    protected long count;
037
038    protected MonetaryAmount min;
039
040    protected MonetaryAmount max;
041
042    protected MonetaryAmount sum;
043
044    protected MonetaryAmount average;
045
046    /**
047     * Creates a new instance, targeting the given
048     * {@link javax.money.CurrencyUnit}.
049     *
050     * @param currencyUnit the target currency, not null.
051     */
052    protected DefaultMonetarySummaryStatistics(CurrencyUnit currencyUnit) {
053        empty = FastMoney.of(0, Objects.requireNonNull(currencyUnit));
054        setSameMonetary(empty);
055    }
056    
057    /**
058     * Creates a new instance, targeting the given
059     * {@link javax.money.CurrencyUnit}.
060     *
061     * @param currencyUnit the target currency, not null.
062     */
063    public static DefaultMonetarySummaryStatistics of(CurrencyUnit currencyUnit) {
064        return new DefaultMonetarySummaryStatistics(currencyUnit);
065    }
066
067    @Override
068    public void accept(MonetaryAmount amount) {
069
070        if (!empty.getCurrency().equals(
071                Objects.requireNonNull(amount).getCurrency())) {
072            return;
073        }
074        if (isEmpty()) {
075            setSameMonetary(amount);
076            count++;
077        } else {
078            doSummary(amount);
079        }
080    }
081
082    @Override
083    public CurrencyUnit getCurrencyUnit() {
084        return empty.getCurrency();
085    }
086
087    @Override
088    public MonetarySummaryStatistics combine(
089            MonetarySummaryStatistics summaryStatistics) {
090        Objects.requireNonNull(summaryStatistics);
091
092        if (!equals(summaryStatistics)) {
093            return this;
094        }
095        min = MonetaryFunctions.min(min, summaryStatistics.getMin());
096        max = MonetaryFunctions.max(max, summaryStatistics.getMax());
097        sum = sum.add(summaryStatistics.getSum());
098        count += summaryStatistics.getCount();
099        average = sum.divide(count);
100        return this;
101    }
102
103    private void doSummary(MonetaryAmount monetaryAmount) {
104        min = MonetaryFunctions.min(min, monetaryAmount);
105        max = MonetaryFunctions.max(max, monetaryAmount);
106        sum = sum.add(monetaryAmount);
107        average = sum.divide(++count);
108    }
109
110    private boolean isEmpty() {
111        return count == 0;
112    }
113
114    private void setSameMonetary(MonetaryAmount monetary) {
115        min = monetary;
116        max = monetary;
117        sum = monetary;
118        average = monetary;
119    }
120
121
122    @Override
123    public long getCount() {
124        return count;
125    }
126
127    @Override
128    public MonetaryAmount getMin() {
129        return min;
130    }
131
132
133    @Override
134    public MonetaryAmount getMax() {
135        return max;
136    }
137
138
139    @Override
140    public MonetaryAmount getSum() {
141        return sum;
142    }
143
144
145    @Override
146    public MonetaryAmount getAverage() {
147        return average;
148    }
149
150    @Override
151    public boolean equals(Object obj) {
152        if (DefaultMonetarySummaryStatistics.class.isInstance(obj)) {
153            DefaultMonetarySummaryStatistics other = DefaultMonetarySummaryStatistics.class
154                    .cast(obj);
155            return Objects.equals(empty.getCurrency(),
156                    other.empty.getCurrency());
157        }
158        return false;
159    }
160
161    @Override
162    public int hashCode() {
163        return empty.getCurrency().hashCode();
164    }
165
166    @Override
167    public String toString() {
168        StringBuilder sb = new StringBuilder();
169        sb.append("[currency: ").append(empty.getCurrency()).append(',');
170        sb.append("count:").append(count).append(',');
171        sb.append("min:").append(min).append(',');
172        sb.append("max:").append(max).append(',');
173        sb.append("sum:").append(sum).append(',');
174        sb.append("average:").append(average).append(']');
175        return sb.toString();
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}