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

505 lines
13 KiB
Java

/**
*
*/
package org.gcube.accounting.datamodel;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import org.gcube.accounting.datamodel.annotations.NotEmpty;
import org.gcube.accounting.datamodel.annotations.NotEmptyIfNotNull;
import org.gcube.accounting.datamodel.annotations.ValidLong;
import org.gcube.accounting.datamodel.annotations.ValidOperationResult;
import org.gcube.accounting.datamodel.annotations.ValidityChecker;
import org.gcube.accounting.datamodel.validators.FieldValidator;
import org.gcube.accounting.exception.InvalidValueException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR) http://www.lucafrosini.com/
*
*/
public abstract class RawUsageRecord implements UsageRecord, Serializable {
private static Logger logger = LoggerFactory.getLogger(RawUsageRecord.class);
@NotEmpty
public static final String ID = "id";
@NotEmpty
public static final String CREATOR_ID = "creatorId";
@NotEmpty
public static final String CONSUMER_ID = "consumerId";
@ValidLong
public static final String CREATION_TIME = "creationTime";
@ValidLong
protected static final String START_TIME = "startTime";
@ValidLong
protected static final String END_TIME = "endTime";
@NotEmpty
public static final String RESOURCE_TYPE = "resourceType";
@NotEmpty
public static final String RESOURCE_SCOPE = "resourceScope";
@NotEmpty
public static final String RESOURCE_OWNER = "resourceOwner";
@NotEmptyIfNotNull
protected static final String AGGREGATED_ID = "aggregatedId";
@NotEmptyIfNotNull
protected static final String AGGREGATED_USAGE_RECORD_ID = "aggregatedUsageRecordId";
@ValidOperationResult
public static final String OPERATION_RESULT = "operationResult";
/**
* Generated Serial Version UID
*/
private static final long serialVersionUID = -2060728578456796388L;
/**
* resource-specific properties
*/
protected Map<String, Serializable> resourceSpecificProperties;
protected final Map<String, List<FieldValidator<? extends Annotation>>> validation;
protected void initializeValidation() {
logger.debug("Initializing Field Validators");
List<Field> fields = Arrays.asList(this.getClass().getDeclaredFields());
for(Field field : fields){
String keyString;
try {
keyString = (String) field.get(null);
} catch (Exception e) {
continue;
}
List<FieldValidator<? extends Annotation>> fieldValidators = new ArrayList<FieldValidator<? extends Annotation>>();
validation.put(keyString, fieldValidators);
for (Annotation annotation : field.getAnnotations()){
if (annotation.annotationType().isAnnotationPresent(ValidityChecker.class)){
Class<? extends FieldValidator<?>> managedClass = ((ValidityChecker)annotation.annotationType().getAnnotation(ValidityChecker.class)).managed();
FieldValidator<?> validator;
try {
validator = managedClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
continue;
}
fieldValidators.add(validator);
}
}
}
}
protected RawUsageRecord(){
this.resourceSpecificProperties = new HashMap<String, Serializable>();
this.validation = new HashMap<String, List<FieldValidator<? extends Annotation>>>();
initializeValidation();
this.resourceSpecificProperties.put(ID, UUID.randomUUID().toString());
this.resourceSpecificProperties.put(RESOURCE_TYPE, this.getClass().getSimpleName());
Calendar calendar = Calendar.getInstance();
this.resourceSpecificProperties.put(CREATION_TIME, calendar.getTimeInMillis());
}
protected RawUsageRecord(Map<String, Serializable> properties) throws InvalidValueException {
this.validation = new HashMap<String, List<FieldValidator<? extends Annotation>>>();
initializeValidation();
setResourceSpecificProperties(properties);
}
/**
* {@inheritDoc}
*/
@Override
public String getId() {
return (String) this.resourceSpecificProperties.get(ID);
}
/**
* {@inheritDoc}
*/
@Override
public void setId(String id) throws InvalidValueException {
setResourceSpecificProperty(ID, id);
}
/**
* {@inheritDoc}
*/
@Override
public String getCreatorId() {
return (String) this.resourceSpecificProperties.get(CREATOR_ID);
}
/**
* {@inheritDoc}
*/
@Override
public void setCreatorId(String creatorId) throws InvalidValueException {
setResourceSpecificProperty(CREATOR_ID, creatorId);
}
/**
* {@inheritDoc}
*/
@Override
public String getConsumerId() {
return (String) this.resourceSpecificProperties.get(CONSUMER_ID);
}
/**
* {@inheritDoc}
*/
@Override
public void setConsumerId(String consumerId) throws InvalidValueException {
setResourceSpecificProperty(CONSUMER_ID, consumerId);
}
protected Calendar timestampStringToCalendar(long millis){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(millis);
return calendar;
}
/**
* {@inheritDoc}
*/
@Override
public Calendar getCreationTime() {
long millis = (Long) this.resourceSpecificProperties.get(CREATION_TIME);
return timestampStringToCalendar(millis);
}
/**
* {@inheritDoc}
*/
@Override
public void setCreationTime(Calendar creationTime) throws InvalidValueException {
setResourceSpecificProperty(CREATION_TIME, creationTime.getTimeInMillis());
}
@Override
@Deprecated
public Date getCreateTime() {
long millis = (Long) this.resourceSpecificProperties.get(CREATION_TIME);
return timestampStringToCalendar(millis).getTime();
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public void setCreateTime(Date createTime) throws InvalidValueException {
Calendar calendar = Calendar.getInstance();
calendar.setTime(createTime);
setCreationTime(calendar);
}
/**
* {@inheritDoc}
*/
@Override
public Calendar getStartTime() {
long millis = (Long) this.resourceSpecificProperties.get(START_TIME);
return timestampStringToCalendar(millis);
}
/**
* Set the left end of the time interval covered by this {#UsageRecord}
* @param startTime Start Time
* @throws InvalidValueException
*/
protected void setStartTime(Calendar startTime) throws InvalidValueException {
setResourceSpecificProperty(START_TIME, startTime.getTimeInMillis());
}
/* *
* {@inheritDoc}
* /
@Override
@Deprecated
public void setStartTime(Date startTime) throws InvalidValueException {
Calendar calendar = Calendar.getInstance();
calendar.setTime(startTime);
setStartTime(calendar);
}
*/
/**
* {@inheritDoc}
*/
@Override
public Calendar getEndTime() {
long millis = (Long) this.resourceSpecificProperties.get(END_TIME);
return timestampStringToCalendar(millis);
}
/**
* Set the right end of the time interval covered by this {#UsageRecord}
* @param endTime End Time
* @throws InvalidValueException
*/
protected void setEndTime(Calendar endTime) throws InvalidValueException {
setResourceSpecificProperty(END_TIME, endTime.getTimeInMillis());
}
/* *
* {@inheritDoc}
* /
@Override
@Deprecated
public void setEndTime(Date endTime) throws InvalidValueException {
Calendar calendar = Calendar.getInstance();
calendar.setTime(endTime);
setEndTime(calendar);
}
*/
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public String getUsageRecordType() {
//return (String) this.resourceSpecificProperties.get(RESOURCE_TYPE);
return this.getClass().getSimpleName();
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public String getResourceType(){
return getUsageRecordType();
}
/**
* {@inheritDoc}
*/
@Deprecated
public void setResourceType(String resourceType){}
/**
* {@inheritDoc}
*/
@Override
public String getResourceScope() {
return (String) this.resourceSpecificProperties.get(RESOURCE_SCOPE);
}
/**
* {@inheritDoc}
*/
@Override
public void setResourceScope(String scope) throws InvalidValueException {
setResourceSpecificProperty(RESOURCE_SCOPE, scope);
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public String getResourceOwner() {
return (String) this.resourceSpecificProperties.get(RESOURCE_OWNER);
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public void setResourceOwner(String owner) throws InvalidValueException {
setResourceSpecificProperty(RESOURCE_OWNER, owner);
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public String getAggregatedId() {
return (String) this.resourceSpecificProperties.get(AGGREGATED_ID);
}
/**
* {@inheritDoc}
*/
@Override@
Deprecated
public void setAggregatedId(String aggregatedId) throws InvalidValueException {
setResourceSpecificProperty(AGGREGATED_ID, aggregatedId);
}
public String getAggregatedUsageRecordId() {
return (String) this.resourceSpecificProperties.get(AGGREGATED_USAGE_RECORD_ID);
}
public void setAggregatedUsageRecordId(String aggregatedId) throws InvalidValueException {
setResourceSpecificProperty(AGGREGATED_USAGE_RECORD_ID, aggregatedId);
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, Serializable> getResourceSpecificProperties() {
return this.resourceSpecificProperties;
}
/**
* {@inheritDoc}
*/
@Override
public void setResourceSpecificProperties(Map<String, Serializable> properties) throws InvalidValueException {
validate(properties);
this.resourceSpecificProperties = new HashMap<String, Serializable>(properties);
}
/**
* {@inheritDoc}
*/
@Override
public Serializable getResourceSpecificProperty(String key) {
return this.resourceSpecificProperties.get(key);
}
/**
* {@inheritDoc}
*/
@Override
public void setResourceSpecificProperty(String key, Serializable value) throws InvalidValueException {
validateField(key, value);
this.resourceSpecificProperties.put(key, value);
}
protected void validateField(String key, Serializable serializable) throws InvalidValueException {
List<FieldValidator<? extends Annotation>> fieldValidators = validation.get(key);
if(fieldValidators!=null){
for(FieldValidator<? extends Annotation> fieldValidator : fieldValidators){
if(!fieldValidator.isValid(serializable)){
throw new InvalidValueException(fieldValidator.getErrorSuffix());
}
}
}
}
protected void validate(Map<String, Serializable> properties) throws InvalidValueException{
// TODO Change the behavior. Get the list of validators and check the
// field in properties Map
for(String key : properties.keySet()){
Serializable serializable = properties.get(key);
validateField(key, serializable);
}
}
/**
* {@inheritDoc}
*/
@Override
public void validate() throws InvalidValueException{
validate(this.resourceSpecificProperties);
}
@Override
public String toString(){
return resourceSpecificProperties.toString();
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public String getFullyQualifiedConsumerId() {
return getConsumerId();
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public void setFullyQualifiedConsumerId(String fqcid) { }
/**
* {@inheritDoc}
*/
@Override
public OperationResult getOperationResult(){
return OperationResult.valueOf((String) this.resourceSpecificProperties.get(OPERATION_RESULT));
}
/**
* {@inheritDoc}
* @throws InvalidValueException
*/
@Override
public void setOperationResult(OperationResult operationResult) throws InvalidValueException {
setResourceSpecificProperty(OPERATION_RESULT, operationResult);
}
/**
* Compare this UsageRecord instance with the one provided as argument
* @param usageRecord the Usage Record to compare
* @return 0 is and only if the UsageRecord provided as parameter
* contains all and ONLY the parameters contained in this instance.
* If the number of parameters differs, the methods return the difference
* between the number of parameter in this instance and the ones in the
* UsageRecord provided as parameter.
* If the size is the same but the UsageRecord provided as parameter does
* not contains all parameters in this instance, -1 is returned.
*/
@Override
public int compareTo(UsageRecord usageRecord) {
Set<Entry<String, Serializable>> thisSet = this.resourceSpecificProperties.entrySet();
Set<Entry<String, Serializable>> usageRecordSet = usageRecord.getResourceSpecificProperties().entrySet();
if(thisSet.size() != usageRecordSet.size()){
return thisSet.size() - usageRecordSet.size();
}
if(usageRecordSet.containsAll(thisSet)){
return 0;
}
return 1;
}
public static List<UsageRecord> aggregate(List<UsageRecord> records){
// TODO implements
throw new UnsupportedOperationException();
}
/**
* This method use the resourceType value contained in the Map to instance
* the right UsageRecord class and return it. If the type implementation
* does not exist or the validation of one or more field validation fails
* an exception is thrown
* @param usageRecordMap
* @return the instance of the UsageRecord class.
* @throws Exception if fails
*/
public static UsageRecord getUsageRecord(Map<String, Serializable> usageRecordMap) throws Exception {
// TODO Auto-generated method stub
return null;
}
}