You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
accounting-analytics-persis.../src/main/java/org/gcube/accounting/analytics/persistence/postgresql/Query.java

267 lines
7.1 KiB
Java

package org.gcube.accounting.analytics.persistence.postgresql;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.gcube.accounting.analytics.Filter;
import org.gcube.accounting.analytics.TemporalConstraint;
import org.gcube.accounting.analytics.TemporalConstraint.AggregationMode;
import org.gcube.accounting.analytics.TemporalConstraint.CalendarEnum;
import org.gcube.accounting.datamodel.UsageRecord;
import org.gcube.accounting.datamodel.aggregation.AggregatedServiceUsageRecord;
import org.gcube.accounting.utility.postgresql.RecordToDBFields;
import org.gcube.accounting.utility.postgresql.RecordToDBMapping;
import org.gcube.documentstore.records.AggregatedRecord;
public class Query {
public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS Z";
public static final String DATE_OF_TIMESERIES_AS_FIELD = AggregatedRecord.START_TIME;
private Class<? extends AggregatedRecord<?, ?>> clz;
private final RecordToDBFields recordToDBMapper;
private List<String> requestedTableField;
private StringBuffer stringBuffer;
protected TemporalConstraint temporalConstraint;
protected List<Filter> filters;
protected Set<String> contexts;
public Query(Class<? extends AggregatedRecord<?, ?>> clz) throws Exception {
this.clz = clz;
this.recordToDBMapper = RecordToDBMapping.getRecordToDB(clz);
}
public List<String> getRequestedTableField() {
return requestedTableField;
}
public void setTemporalConstraint(TemporalConstraint temporalConstraint) {
this.temporalConstraint = temporalConstraint;
}
public void setFilters(List<Filter> filters) {
this.filters = filters;
}
public void setContexts(Set<String> contexts) {
this.contexts = contexts;
}
public void addContext(String context) {
if(contexts == null) {
contexts = new HashSet<>();
}
contexts.add(context);
}
public RecordToDBFields getRecordToDBMapper() {
return recordToDBMapper;
}
private void appendString(String string) {
stringBuffer.append("'");
stringBuffer.append(string);
stringBuffer.append("'");
}
protected String getTableField(String fieldName) {
return recordToDBMapper.getTableField(fieldName);
}
protected void appendTableField(String fieldName) {
stringBuffer.append(getTableField(fieldName));
}
public static String getFormattedDate(Calendar calendar) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN);
String date = simpleDateFormat.format(calendar.getTime());
return date;
}
protected void appendValue(Serializable serializable) {
if(serializable instanceof Number) {
stringBuffer.append(serializable.toString());
return;
}
if(serializable instanceof Calendar) {
Calendar calendar = (Calendar) serializable;
appendString(getFormattedDate(calendar));
return;
}
if(serializable instanceof Enum) {
Enum<?> e = (Enum<?>) serializable;
appendString(e.name());
return;
}
// String, URI etc
appendString(serializable.toString());
}
protected void addFilters() {
if(filters!=null && filters.size()>0) {
// The first filter if the time_bucket
stringBuffer.append(" AND ");
boolean first = true;
for(Filter filter : filters) {
if(first) {
first = false;
}else {
stringBuffer.append(" AND ");
}
appendTableField(filter.getKey());
stringBuffer.append("=");
appendValue(filter.getValue());
}
}
}
protected void addContextFilter() {
if(contexts!=null && contexts.size()>0) {
// The first filter if the time_bucket
stringBuffer.append(" AND (");
boolean first = true;
for(String context : contexts) {
if(first) {
first = false;
}else {
stringBuffer.append(" OR ");
}
appendTableField(UsageRecord.SCOPE);
stringBuffer.append("=");
appendValue(context);
}
stringBuffer.append(")");
}
}
protected void addEmittedFields() throws Exception {
Set<String> aggregatedField = clz.newInstance().getAggregatedFields();
for(String fieldName : aggregatedField) {
String dbField = getTableField(fieldName);
switch (fieldName) {
case AggregatedRecord.START_TIME:
case AggregatedRecord.END_TIME:
case AggregatedRecord.AGGREGATED:
continue;
case AggregatedRecord.OPERATION_COUNT:
stringBuffer.append(", SUM(");
stringBuffer.append(dbField);
stringBuffer.append(") AS ");
break;
// WEIGHTED AVERAGE
case AggregatedServiceUsageRecord.DURATION:
stringBuffer.append(", ROUND(SUM(");
stringBuffer.append(dbField);
stringBuffer.append("*");
appendTableField(AggregatedRecord.OPERATION_COUNT);
stringBuffer.append(")/SUM(");
appendTableField(AggregatedRecord.OPERATION_COUNT);
stringBuffer.append(")) AS ");
break;
case AggregatedServiceUsageRecord.MAX_INVOCATION_TIME:
stringBuffer.append(", MAX(");
stringBuffer.append(dbField);
stringBuffer.append(") AS ");
break;
case AggregatedServiceUsageRecord.MIN_INVOCATION_TIME:
stringBuffer.append(", MIN(");
stringBuffer.append(dbField);
stringBuffer.append(") AS ");
break;
default:
stringBuffer.append(", ");
break;
}
stringBuffer.append(dbField);
requestedTableField.add(dbField);
}
}
protected String getTimeBucketCalendarInterval(AggregationMode aggregationMode) {
CalendarEnum calendarEnum = CalendarEnum.values()[aggregationMode.ordinal()];
return calendarEnum.name().toLowerCase();
}
protected void addTimeBucket() {
stringBuffer.append("time_bucket('1 ");
String calendarInterval = getTimeBucketCalendarInterval(temporalConstraint.getAggregationMode());
stringBuffer.append(calendarInterval);
stringBuffer.append("',");
appendTableField(AggregatedRecord.START_TIME);
stringBuffer.append(") AS ");
stringBuffer.append(DATE_OF_TIMESERIES_AS_FIELD);
requestedTableField.add(DATE_OF_TIMESERIES_AS_FIELD);
}
private void newQuery() {
stringBuffer = new StringBuffer();
requestedTableField = new ArrayList<>();
stringBuffer.append("SELECT ");
}
protected void addTemporalConstraintToQuery() {
stringBuffer.append(" WHERE ");
String tableField = getTableField(AggregatedRecord.START_TIME);
stringBuffer.append(tableField);
stringBuffer.append(" > ");
appendValue(temporalConstraint.getAlignedStartTime());
stringBuffer.append(" AND ");
stringBuffer.append(tableField);
stringBuffer.append(" < ");
appendValue(temporalConstraint.getAlignedEndTime());
}
protected void addGropuBy() {
stringBuffer.append(" GROUP BY ");
stringBuffer.append(DATE_OF_TIMESERIES_AS_FIELD);
}
protected void addOrderBy() {
stringBuffer.append(" ORDER BY ");
stringBuffer.append(DATE_OF_TIMESERIES_AS_FIELD);
stringBuffer.append(" ASC");
}
public String getTimeSeriesQuery() throws Exception {
newQuery();
addTimeBucket();
addEmittedFields();
stringBuffer.append(" FROM ");
stringBuffer.append(recordToDBMapper.getTableName());
addTemporalConstraintToQuery();
addFilters();
addContextFilter();
addGropuBy();
addOrderBy();
return stringBuffer.toString();
}
}