/**
* 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 javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import org.apache.commons.lang.Validate;
import org.apereo.portal.events.aggr.dao.jpa.DateDimensionImpl;
import org.apereo.portal.events.aggr.dao.jpa.TimeDimensionImpl;
import org.apereo.portal.events.aggr.groups.AggregatedGroupMapping;
import org.apereo.portal.events.aggr.groups.AggregatedGroupMappingImpl;
import org.hibernate.annotations.NaturalId;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base implementations for aggregations that are grouped by date, time, interval and group
*
*/
@Access(AccessType.FIELD)
@MappedSuperclass
public abstract class BaseAggregationImpl<
K extends BaseAggregationKey, D extends BaseGroupedAggregationDiscriminator>
implements BaseAggregation<K, D> {
private static final long serialVersionUID = 1L;
@Transient private Logger logger = null;
@NaturalId
@ManyToOne(targetEntity = TimeDimensionImpl.class)
@JoinColumn(name = "TIME_DIMENSION_ID", nullable = false)
private final TimeDimension timeDimension;
@NaturalId
@ManyToOne(targetEntity = DateDimensionImpl.class)
@JoinColumn(name = "DATE_DIMENSION_ID", nullable = false)
private final DateDimension dateDimension;
@NaturalId
@Enumerated(EnumType.STRING)
@Column(name = "AGGR_INTERVAL", nullable = false)
private final AggregationInterval interval;
@NaturalId
@ManyToOne(targetEntity = AggregatedGroupMappingImpl.class)
@JoinColumn(name = "AGGR_GROUP_ID", nullable = false)
private final AggregatedGroupMapping aggregatedGroup;
@Column(name = "DURATION", nullable = false)
private int duration;
@Transient private Boolean complete = null;
@Transient private DateTime dateTime = null;
protected BaseAggregationImpl() {
this.timeDimension = null;
this.dateDimension = null;
this.interval = null;
this.aggregatedGroup = null;
}
protected BaseAggregationImpl(
TimeDimension timeDimension,
DateDimension dateDimension,
AggregationInterval interval,
AggregatedGroupMapping aggregatedGroup) {
Validate.notNull(timeDimension);
Validate.notNull(dateDimension);
Validate.notNull(interval);
Validate.notNull(aggregatedGroup);
this.timeDimension = timeDimension;
this.dateDimension = dateDimension;
this.interval = interval;
this.aggregatedGroup = aggregatedGroup;
}
public abstract long getId();
@Override
public DateTime getDateTime() {
DateTime dt = this.dateTime;
if (dt == null) {
dt = this.timeDimension.getTime().toDateTime(this.dateDimension.getDate());
this.dateTime = dt;
}
return dt;
}
@Override
public final TimeDimension getTimeDimension() {
return this.timeDimension;
}
@Override
public final DateDimension getDateDimension() {
return this.dateDimension;
}
@Override
public final AggregationInterval getInterval() {
return this.interval;
}
@Override
public final int getDuration() {
return this.duration;
}
@Override
public final AggregatedGroupMapping getAggregatedGroup() {
return this.aggregatedGroup;
}
/** Set the duration of the interval */
public final void setDuration(int duration) {
if (isComplete()) {
this.getLogger()
.warn(
"{} is already closed, the new duration of {} will be ignored on: {}",
this.getClass().getSimpleName(),
duration,
this);
return;
}
this.duration = duration;
}
/** Mark the interval as complete, set the final duration the interval spans */
public final void intervalComplete(int duration) {
this.duration = duration;
this.completeInterval();
this.complete = Boolean.TRUE;
}
/**
* Called to check if the interval is "complete". Defined as all data for the interval has been
* handled and the final aggregation step(s) have been done. Implies that {@link
* #completeInterval()} has been called at some point in the past
*/
protected abstract boolean isComplete();
/**
* Called to tell the the aggregation that the interval it exists for has been completed and any
* final calculations should be done
*/
protected abstract void completeInterval();
/**
* @return The {@link Logger} to use for this event, lazy init as Loggers are rarely used for
* events
*/
protected final Logger getLogger() {
Logger l = this.logger;
if (l == null) {
l = LoggerFactory.getLogger(this.getClass());
this.logger = l;
}
return l;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dateDimension == null) ? 0 : dateDimension.hashCode());
result = prime * result + ((aggregatedGroup == null) ? 0 : aggregatedGroup.hashCode());
result = prime * result + ((interval == null) ? 0 : interval.hashCode());
result = prime * result + ((timeDimension == null) ? 0 : timeDimension.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof BaseAggregationImpl)) return false;
BaseAggregation<?, ?> other = (BaseAggregation<?, ?>) obj;
if (dateDimension == null) {
if (other.getDateDimension() != null) return false;
} else if (!dateDimension.equals(other.getDateDimension())) return false;
if (aggregatedGroup == null) {
if (other.getAggregatedGroup() != null) return false;
} else if (!aggregatedGroup.equals(other.getAggregatedGroup())) return false;
if (interval != other.getInterval()) return false;
if (timeDimension == null) {
if (other.getTimeDimension() != null) return false;
} else if (!timeDimension.equals(other.getTimeDimension())) return false;
return true;
}
}