/** * */ package org.gcube.accounting.analytics.persistence; import java.util.ArrayList; import java.util.Calendar; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeSet; import org.gcube.accounting.analytics.Filter; import org.gcube.accounting.analytics.Info; import org.gcube.accounting.analytics.NumberedFilter; import org.gcube.accounting.analytics.TemporalConstraint; import org.gcube.accounting.datamodel.UsageRecord; import org.gcube.accounting.datamodel.aggregation.AggregatedStorageUsageRecord; import org.gcube.documentstore.records.AggregatedRecord; import org.gcube.documentstore.records.Record; import org.json.JSONException; import org.json.JSONObject; /** * @author Luca Frosini (ISTI - CNR) http://www.lucafrosini.com/ * */ public class AccountingPersistenceQuery { private static final AccountingPersistenceQuery accountingPersistenceQuery; public static final int DEFAULT_LIMIT_RESULT_NUMBER = 5; private AccountingPersistenceQuery() { } static { accountingPersistenceQuery = new AccountingPersistenceQuery(); } protected static synchronized AccountingPersistenceQuery getInstance() { return accountingPersistenceQuery; } public static SortedSet getQuerableKeys( @SuppressWarnings("rawtypes") AggregatedRecord instance) throws Exception { SortedSet properties = new TreeSet<>( instance.getRequiredFields()); properties.removeAll(instance.getAggregatedFields()); properties.removeAll(instance.getComputedFields()); properties.remove(Record.ID); properties.remove(Record.CREATION_TIME); properties.remove(Record.RECORD_TYPE); properties.remove(UsageRecord.SCOPE); return properties; } public static SortedSet getQuerableKeys( Class> aggregatedRecordClass) throws Exception { AggregatedRecord instance = aggregatedRecordClass.newInstance(); return getQuerableKeys(instance); } public SortedMap getTimeSeries( Class> aggregatedRecordClass, TemporalConstraint temporalConstraint, List filters, boolean pad) throws Exception { SortedMap ret = AccountingPersistenceBackendQueryFactory.getInstance() .getTimeSeries(aggregatedRecordClass, temporalConstraint, filters); if(pad){ ret = padMap(ret, temporalConstraint); } return ret; } public static String getDefaultOrderingProperties(Class> recordClass){ if(recordClass.isAssignableFrom(AggregatedStorageUsageRecord.class)){ return AggregatedStorageUsageRecord.DATA_VOLUME; } return AggregatedRecord.OPERATION_COUNT; } protected static JSONObject getPaddingJSONObject( Map unpaddedResults) throws JSONException { Info auxInfo = new ArrayList(unpaddedResults.values()).get(0); JSONObject auxJsonObject = auxInfo.getValue(); @SuppressWarnings("unchecked") Iterator keys = auxJsonObject.keys(); JSONObject jsonObject = new JSONObject(); while (keys.hasNext()) { String key = keys.next(); jsonObject.put(key, 0); } return jsonObject; } /** * Pad the data * * @param unpaddedData * the data to be pad * @param temporalConstraint * temporalConstraint the temporal interval and the granularity * of the data to pad * @return the data padded taking in account the TemporalConstraint * @throws Exception * if fails */ public static SortedMap padMap( SortedMap unpaddedData, TemporalConstraint temporalConstraint) throws Exception { JSONObject jsonObject = getPaddingJSONObject(unpaddedData); SortedSet sequence = temporalConstraint.getCalendarSequence(); for (Calendar progressTime : sequence) { Info info = unpaddedData.get(progressTime); if (info == null) { info = new Info(progressTime, jsonObject); unpaddedData.put(progressTime, info); } } return unpaddedData; } public static SortedMap> getTopValues( Class> aggregatedRecordClass, TemporalConstraint temporalConstraint, List filters, String orderingProperty, boolean pad, int limit) throws Exception { SortedMap> ret; if(orderingProperty==null){ orderingProperty = getDefaultOrderingProperties(aggregatedRecordClass); } ret = AccountingPersistenceBackendQueryFactory.getInstance() .getTopValues(aggregatedRecordClass, temporalConstraint, filters, orderingProperty); if(pad){ int count = ret.size() > limit ? limit : ret.size(); while(--count >= 0){ for(NumberedFilter nf : ret.keySet()){ padMap(ret.get(nf), temporalConstraint); } } } return ret; } public static SortedMap> getTopValues( Class> aggregatedRecordClass, TemporalConstraint temporalConstraint, List filters) throws Exception { return AccountingPersistenceBackendQueryFactory.getInstance() .getTopValues(aggregatedRecordClass, temporalConstraint, filters); } public static SortedSet getNextPossibleValues( Class> aggregatedRecordClass, TemporalConstraint temporalConstraint, List filters) throws Exception { return AccountingPersistenceBackendQueryFactory.getInstance() .getNextPossibleValues(aggregatedRecordClass, temporalConstraint, filters); } /** * Close the connection to persistence * * @throws Exception * if the close fails */ public void close() throws Exception { AccountingPersistenceBackendQueryFactory.getInstance().close(); } }