/** * */ 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, B extends SingleUsageRecord> { protected T t; protected Set aggregationField; protected void cleanExtraFields(){ Set neededFields = ((BasicUsageRecord) t).requiredFields; neededFields.addAll(((BasicUsageRecord) t).aggregatedFields); Set keysToRemove = new HashSet(); Set 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(); 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 recordValue = record.getResourceProperty(field); Comparable 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); } } }