accounting-lib/src/main/java/org/gcube/accounting/datamodel/AggregationStrategy.java

130 lines
3.9 KiB
Java

/**
*
*/
package org.gcube.accounting.datamodel;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
import org.gcube.accounting.exception.InvalidValueException;
import org.gcube.accounting.exception.NotAggregatableRecordsExceptions;
/**
* @author Luca Frosini (ISTI - CNR) http://www.lucafrosini.com/
*/
public abstract class AggregationStrategy<T extends AggregatedUsageRecord<T, B>, B extends SingleUsageRecord> {
protected T t;
protected Set<String> aggregationField;
protected void cleanExtraFields(){
Set<String> neededFields = ((BasicUsageRecord) t).requiredFields;
neededFields.addAll(((BasicUsageRecord) t).aggregatedFields);
Set<String> keysToRemove = new HashSet<String>();
Set<String> propertyKeys = ((BasicUsageRecord) t).resourceProperties.keySet();
for(String propertyName : propertyKeys){
if(!neededFields.contains(propertyName)){
keysToRemove.add(propertyName);
}
}
for(String keyToRemove : keysToRemove){
((BasicUsageRecord) t).resourceProperties.remove(keyToRemove);
}
}
public AggregationStrategy(T t){
this.t = t;
cleanExtraFields();
this.aggregationField = new HashSet<String>();
this.aggregationField.add(BasicUsageRecord.CONSUMER_ID);
this.aggregationField.add(BasicUsageRecord.USAGE_RECORD_TYPE);
this.aggregationField.add(BasicUsageRecord.SCOPE);
this.aggregationField.add(BasicUsageRecord.OPERATION_RESULT);
}
public T getAggregatedUsageRecord(){
return t;
}
protected String commonFieldHash(B record) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
String concatenation = "";
for(String field : aggregationField){
concatenation = concatenation + record.getResourceProperty(field).toString();
}
messageDigest.update(concatenation.getBytes());
return new String(messageDigest.digest());
}catch(NoSuchAlgorithmException e){
throw new UnsupportedOperationException(e);
}
}
protected boolean isAggregable(UsageRecord record) {
for(String field : aggregationField){
Comparable<? extends Serializable> recordValue = record.getResourceProperty(field);
Comparable<? extends Serializable> thisValue = ((BasicUsageRecord) t).getResourceProperty(field);
if(!recordValue.equals(thisValue)){
return false;
}
}
return true;
}
protected abstract T reallyAggregate(T t) throws NotAggregatableRecordsExceptions;
public synchronized T aggregate(T record) throws NotAggregatableRecordsExceptions {
try{
if(!isAggregable(record)){
throw new NotAggregatableRecordsExceptions("The Record provided as argument has different values for field wich must be common to be aggragatable");
}
Calendar convertedStartTime = ((BasicUsageRecord) record).getStartTimeAsCalendar();
Calendar actualStartTime = ((BasicUsageRecord) t).getStartTimeAsCalendar();
if(convertedStartTime.before(actualStartTime)){
((BasicUsageRecord) t).setStartTime(convertedStartTime);
}
Calendar convertedEndTime = ((BasicUsageRecord) record).getEndTimeAsCalendar();
Calendar actualEndTime = ((BasicUsageRecord) t).getEndTimeAsCalendar();
if(convertedEndTime.after(actualEndTime)){
((BasicUsageRecord) t).setEndTime(convertedEndTime);
}
Calendar newCreationTime = Calendar.getInstance();
t = reallyAggregate(record);
((BasicUsageRecord) t).setCreationTime(newCreationTime);
return t;
}catch(NotAggregatableRecordsExceptions e){
throw e;
}catch(Exception ex){
throw new NotAggregatableRecordsExceptions(ex.getCause());
}
}
public T aggregate(B record) throws NotAggregatableRecordsExceptions {
T convertedRecord;
try {
convertedRecord = t.getAggregatedUsageRecord(record);
return aggregate(convertedRecord);
} catch (InvalidValueException e) {
throw new NotAggregatableRecordsExceptions(e);
}
}
}