130 lines
3.9 KiB
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);
|
|
}
|
|
|
|
}
|
|
|
|
}
|