/** * */ package org.gcube.accounting.analytics.persistence.postgresql; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.time.OffsetDateTime; import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; 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.analytics.UsageValue; import org.gcube.accounting.analytics.exception.DuplicatedKeyFilterException; import org.gcube.accounting.analytics.exception.KeyException; import org.gcube.accounting.analytics.exception.ValueException; import org.gcube.accounting.analytics.persistence.AccountingPersistenceBackendQuery; import org.gcube.accounting.analytics.persistence.AccountingPersistenceBackendQueryConfiguration; import org.gcube.accounting.datamodel.aggregation.AggregatedServiceUsageRecord; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.accounting.persistence.AccountingPersistenceConfiguration; import org.gcube.accounting.utility.postgresql.RecordToDBFields; import org.gcube.accounting.utility.postgresql.RecordToDBConnection; import org.gcube.accounting.utility.postgresql.RecordToDBMapping; import org.gcube.documentstore.records.AggregatedRecord; import org.gcube.documentstore.records.RecordUtility; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Luca Frosini (ISTI - CNR) */ public class AccountingPersistenceQueryPostgreSQL implements AccountingPersistenceBackendQuery { protected static final Logger logger = LoggerFactory.getLogger(AccountingPersistenceQueryPostgreSQL.class); public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS Z"; public static final String URL_PROPERTY_KEY = AccountingPersistenceConfiguration.URL_PROPERTY_KEY; // private String baseURL; protected AccountingPersistenceBackendQueryConfiguration configuration; static { // One Record per package is enough RecordUtility.addRecordPackage(ServiceUsageRecord.class.getPackage()); RecordUtility.addRecordPackage(AggregatedServiceUsageRecord.class.getPackage()); } protected Connection getConnection(Class> clz) throws Exception { RecordToDBConnection recordDBInfo = RecordToDBMapping.getRecordDBInfo(clz); if(recordDBInfo == null) { RecordToDBMapping.addRecordToDB(clz, configuration); } return recordDBInfo.getConnection(); } @Override public void prepareConnection(AccountingPersistenceBackendQueryConfiguration configuration) throws Exception { this.configuration = configuration; Map>> aggregatedRecords = RecordUtility.getAggregatedRecordClassesFound(); for(String typeName : aggregatedRecords.keySet()) { try { Class> clz = aggregatedRecords.get(typeName); RecordToDBMapping.getRecordToDB(clz); } catch (Exception e) { new RuntimeException(e); } } } public SortedMap getTimeSeries(Class> clz, TemporalConstraint temporalConstraint, List filters, Set contexts) throws Exception { Connection connection = getConnection(clz); try { Statement statement = connection.createStatement(); SortedMap result = new TreeMap<>(); Query query = new Query(clz); query.setTemporalConstraint(temporalConstraint); query.setFilters(filters); query.setContexts(contexts); String sql = query.getTimeSeriesQuery(); List requestedTableField = query.getRequestedTableField(); RecordToDBFields recordToDBMapper = query.getRecordToDBMapper(); ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()) { OffsetDateTime offsetDateTime = resultSet.getObject(Query.DATE_OF_TIMESERIES_AS_FIELD, OffsetDateTime.class); Calendar calendar = getCalendar(offsetDateTime); JSONObject jsonObject = new JSONObject(); for(String tableField : requestedTableField) { String usageRecordField = recordToDBMapper.getRecordField(tableField); Object object = resultSet.getObject(tableField); jsonObject.put(usageRecordField, object); } Info info = new Info(calendar, jsonObject); result.put(calendar, info); } return result; }finally { connection.close(); } } @Override public SortedMap getTimeSeries(Class> clz, TemporalConstraint temporalConstraint, List filters) throws DuplicatedKeyFilterException, KeyException, ValueException, Exception { String currentScope = AccountingPersistenceBackendQuery.getScopeToQuery(); Set contexts = new HashSet<>(); contexts.add(currentScope); return getTimeSeries(clz, temporalConstraint, filters, contexts); } protected Calendar getCalendar(OffsetDateTime offsetDateTime) { Calendar calendar = Calendar.getInstance(); long epochMillis = offsetDateTime.toInstant().toEpochMilli(); calendar.setTimeInMillis(epochMillis); return calendar; } @Override public SortedMap getNoContextTimeSeries(Class> clz, TemporalConstraint temporalConstraint, List filters) throws DuplicatedKeyFilterException, KeyException, ValueException, Exception { return getTimeSeries(clz, temporalConstraint, filters, null); } @Override public SortedMap> getTopValues( Class> clz, TemporalConstraint temporalConstraint, List filters, String topKey, String orderingProperty) throws DuplicatedKeyFilterException, KeyException, ValueException, Exception { // TODO Auto-generated method stub return null; } @Override public SortedSet getFilterValues(Class> clz, TemporalConstraint temporalConstraint, List filters, String key) throws Exception { // TODO Auto-generated method stub return null; } @Override public SortedSet getNextPossibleValues(Class> clz, TemporalConstraint temporalConstraint, List filters, String key, String orderingProperty) throws DuplicatedKeyFilterException, KeyException, ValueException, Exception { // TODO Auto-generated method stub return null; } @Override public SortedSet getNextPossibleValuesWithMap(Class> clz, TemporalConstraint temporalConstraint, List filters, String key, String orderingProperty) throws Exception { // TODO Auto-generated method stub return null; } @Override public void close() throws Exception { // OK } @Override public SortedSet getFilterValues(Class> clz, TemporalConstraint temporalConstraint, List filters, String key, Integer limit) throws Exception { // TODO Auto-generated method stub return null; } @Override public JSONObject getUsageValue(Class> clz, TemporalConstraint temporalConstraint, Filter applicant) throws Exception { // TODO Auto-generated method stub return null; } @Override public List getUsageValueQuotaTotal(List listUsage) throws Exception { // TODO Auto-generated method stub return null; } @Override public SortedMap> getContextTimeSeries( Class> clz, TemporalConstraint temporalConstraint, List filters, List contexts) throws Exception { // TODO Auto-generated method stub return null; } @Override public String getRecord(String recordId, String type) throws Exception { // TODO Auto-generated method stub return null; } @Override public SortedSet getSpaceProvidersIds() throws Exception { // TODO Auto-generated method stub return null; } @Override public SortedMap> getSpaceTimeSeries(Class> clz, TemporalConstraint temporalConstraint, List filters, List providersId) throws Exception { // TODO Auto-generated method stub return null; } @Override public boolean isConnectionActive() throws Exception { return true; } }