/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apereo.portal.events.aggr; import java.io.Serializable; import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.MappedSuperclass; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Transient; import org.apereo.portal.events.aggr.groups.AggregatedGroupMapping; import org.apereo.portal.events.aggr.stat.JpaStatisticalSummary; /** * Base for aggregate entities that track timed statistics * */ @Access(AccessType.FIELD) @MappedSuperclass public abstract class BaseTimedAggregationStatsImpl< K extends BaseAggregationKey, D extends BaseGroupedAggregationDiscriminator> extends BaseAggregationImpl<K, D> implements TimedAggregationStatistics, Serializable { private static final long serialVersionUID = 1L; @Column(name = "TIME_COUNT", nullable = false) private int count; @Column(name = "SUM_TIME", nullable = false) private double sum; @Column(name = "SUMSQ_TIME", nullable = false) private double sumsq; @Column(name = "MEAN_TIME", nullable = false) private double mean; @Column(name = "STD_DEVIATION_TIME", nullable = false) private double standardDeviation; @Column(name = "VARIANCE_TIME", nullable = false) private double variance; @Column(name = "POPULATION_VARIANCE_TIME", nullable = false) private double populationVariance; @Column(name = "MAX_TIME", nullable = false) private double max; @Column(name = "MIN_TIME", nullable = false) private double min; @Column(name = "GEOMETRIC_MEAN_TIME", nullable = false) private double geometricMean; @Column(name = "SUM_OF_LOGS_TIME", nullable = false) private double sumOfLogs; @Column(name = "SECOND_MOMENT_TIME", nullable = false) private double secondMoment; @Embedded private JpaStatisticalSummary statisticalSummary; @Column(name = "STATS_COMPLETE", nullable = false) private boolean complete = false; @Transient private boolean modified = false; protected BaseTimedAggregationStatsImpl() { super(); } protected BaseTimedAggregationStatsImpl( TimeDimension timeDimension, DateDimension dateDimension, AggregationInterval interval, AggregatedGroupMapping aggregatedGroup) { super(timeDimension, dateDimension, interval, aggregatedGroup); } @Override public final long getN() { updateStats(); return this.count; } public final double getSum() { updateStats(); return this.sum; } public final double getSumsq() { updateStats(); return this.sumsq; } public final double getMean() { updateStats(); return this.mean; } public final double getStandardDeviation() { updateStats(); return this.standardDeviation; } public final double getVariance() { updateStats(); return this.variance; } public final double getPopulationVariance() { updateStats(); return this.populationVariance; } public final double getMax() { updateStats(); return this.max; } public final double getMin() { updateStats(); return this.min; } public final double getGeometricMean() { updateStats(); return this.geometricMean; } public final double getSumOfLogs() { updateStats(); return this.sumOfLogs; } public final double getSecondMoment() { updateStats(); return this.secondMoment; } /** Check if the interval is complete, must be called by super classes if overridden */ @Override protected boolean isComplete() { return this.count > 0 && (this.complete || this.statisticalSummary == null); } /** Completes the stats interval, must be called by super classes if overridden */ @Override protected void completeInterval() { updateStats(); this.statisticalSummary = null; this.complete = true; } /** Add the value to the summary statistics */ public final void addValue(double v) { if (isComplete()) { this.getLogger() .warn( "{} is already closed, the new value of {} will be ignored on: {}", this.getClass().getSimpleName(), v, this); return; } //Lazily init the statistics object if (this.statisticalSummary == null) { this.statisticalSummary = new JpaStatisticalSummary(); } this.statisticalSummary.addValue(v); this.modified = true; } /** * Update the individual statistic fields if the {@link JpaStatisticalSummary} has been * modified, called automatically by the getter of each field */ @PrePersist @PreUpdate final void updateStats() { if (!this.modified || this.statisticalSummary == null) { return; } //Update statistic values this.count = (int) this.statisticalSummary.getN(); this.sum = this.statisticalSummary.getSum(); this.sumsq = this.statisticalSummary.getSumsq(); this.mean = this.statisticalSummary.getMean(); this.standardDeviation = this.statisticalSummary.getStandardDeviation(); this.variance = this.statisticalSummary.getVariance(); this.populationVariance = this.statisticalSummary.getPopulationVariance(); this.max = this.statisticalSummary.getMax(); this.min = this.statisticalSummary.getMin(); this.geometricMean = this.statisticalSummary.getGeometricMean(); this.sumOfLogs = this.statisticalSummary.getSumOfLogs(); this.secondMoment = this.statisticalSummary.getSecondMoment(); this.modified = false; } }