Refactoring library

feature/21353
Luca Frosini 3 years ago
parent dc27ed4af4
commit 41fb6aa88c

@ -0,0 +1,8 @@
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# Changelog for Accounting Analytics Backend Connector for PostgreSQL
## [v1.0.0-SNAPSHOT]
- First Release

@ -1,3 +1,71 @@
# accounting-analytics-persistence-postgresql
# Accounting Analytics Backend Connector for PostgreSQL
Accounting Analytics Backend Connector for PostgreSQL
## Built With
* [OpenJDK](https://openjdk.java.net/) - The JDK used
* [Maven](https://maven.apache.org/) - Dependency Management
## Documentation
[Accounting Analytics Backend Connector for PostgreSQL](https://wiki.gcube-system.org/gcube/Accounting_Analytics)
## Change log
See [Releases](https://code-repo.d4science.org/gCubeSystem/accounting-analytics-persistence-postgresql/releases).
## Authors
* **Luca Frosini** ([ORCID](https://orcid.org/0000-0003-3183-2291)) - [ISTI-CNR Infrascience Group](http://nemis.isti.cnr.it/groups/infrascience)
## How to Cite this Software
Tell people how to cite this software.
* Cite an associated paper?
* Use a specific BibTeX entry for the software?
@Manual{,
title = {Accounting Analytics Backend Connector for PostgreSQL},
author = {{Frosini, Luca}},
organization = {ISTI - CNR},
address = {Pisa, Italy},
year = 2021,
url = {http://www.gcube-system.org/}
}
## License
This project is licensed under the EUPL V.1.2 License - see the [LICENSE.md](LICENSE.md) file for details.
## About the gCube Framework
This software is part of the [gCubeFramework](https://www.gcube-system.org/ "gCubeFramework"): an
open-source software toolkit used for building and operating Hybrid Data
Infrastructures enabling the dynamic deployment of Virtual Research Environments
by favouring the realisation of reuse oriented policies.
The projects leading to this software have received funding from a series of European Union programmes including:
- the Sixth Framework Programme for Research and Technological Development
- DILIGENT (grant no. 004260).
- the Seventh Framework Programme for research, technological development and demonstration
- D4Science (grant no. 212488);
- D4Science-II (grant no.239019);
- ENVRI (grant no. 283465);
- iMarine(grant no. 283644);
- EUBrazilOpenBio (grant no. 288754).
- the H2020 research and innovation programme
- SoBigData (grant no. 654024);
- PARTHENOS (grant no. 654119);
- EGIEngage (grant no. 654142);
- ENVRIplus (grant no. 654182);
- BlueBRIDGE (grant no. 675680);
- PerformFish (grant no. 727610);
- AGINFRAplus (grant no. 731001);
- DESIRA (grant no. 818194);
- ARIADNEplus (grant no. 823914);
- RISIS2 (grant no. 824091);
Accounting Analytics Backend Connector for PostgreSQL

@ -46,6 +46,11 @@
<artifactId>accounting-analytics</artifactId>
<version>[3.0.0-SNAPSHOT, 4.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.accounting</groupId>
<artifactId>accounting-postgresql-utilities</artifactId>
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
@ -56,7 +61,7 @@
<artifactId>postgresql</artifactId>
<version>42.2.19</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

@ -8,7 +8,6 @@ import java.sql.ResultSet;
import java.sql.Statement;
import java.time.OffsetDateTime;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -30,6 +29,9 @@ import org.gcube.accounting.analytics.persistence.AccountingPersistenceBackendQu
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;
@ -41,7 +43,7 @@ import org.slf4j.LoggerFactory;
*/
public class AccountingPersistenceQueryPostgreSQL implements AccountingPersistenceBackendQuery {
private static final Logger logger = LoggerFactory.getLogger(AccountingPersistenceQueryPostgreSQL.class);
protected static final Logger logger = LoggerFactory.getLogger(AccountingPersistenceQueryPostgreSQL.class);
public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS Z";
@ -50,40 +52,32 @@ public class AccountingPersistenceQueryPostgreSQL implements AccountingPersisten
protected AccountingPersistenceBackendQueryConfiguration configuration;
protected Map<Class<? extends AggregatedRecord<?, ?>>, UsageRecordDBInfo> usageRecordDB;
static {
// One Record per package is enough
RecordUtility.addRecordPackage(ServiceUsageRecord.class.getPackage());
RecordUtility.addRecordPackage(AggregatedServiceUsageRecord.class.getPackage());
Map<String, Class<? extends AggregatedRecord<?,?>>> aggregatedRecords = RecordUtility.getAggregatedRecordClassesFound();
for(String typeName : aggregatedRecords.keySet()) {
try {
Class<? extends AggregatedRecord<?,?>> clz = aggregatedRecords.get(typeName);
UsageRecordToDBMapping.getRecordToDB(clz);
} catch (Exception e) {
new RuntimeException(e);
}
}
}
protected Connection getConnection(Class<? extends AggregatedRecord<?, ?>> clz) throws Exception {
UsageRecordDBInfo usageRecordDBInfo = usageRecordDB.get(clz);
if(usageRecordDBInfo == null) {
usageRecordDBInfo = new UsageRecordDBInfo(clz, configuration);
usageRecordDB.put(clz, usageRecordDBInfo);
RecordToDBConnection recordDBInfo = RecordToDBMapping.getRecordDBInfo(clz);
if(recordDBInfo == null) {
RecordToDBMapping.addRecordToDB(clz, configuration);
}
return usageRecordDBInfo.getConnection();
return recordDBInfo.getConnection();
}
@Override
public void prepareConnection(AccountingPersistenceBackendQueryConfiguration configuration) throws Exception {
logger.trace("prepareConnection");
this.configuration = configuration;
// this.baseURL = configuration.getProperty(URL_PROPERTY_KEY);
this.usageRecordDB = new HashMap<>();
Map<String, Class<? extends AggregatedRecord<?,?>>> aggregatedRecords = RecordUtility.getAggregatedRecordClassesFound();
for(String typeName : aggregatedRecords.keySet()) {
try {
Class<? extends AggregatedRecord<?,?>> clz = aggregatedRecords.get(typeName);
RecordToDBMapping.getRecordToDB(clz);
} catch (Exception e) {
new RuntimeException(e);
}
}
}
public SortedMap<Calendar, Info> getTimeSeries(Class<? extends AggregatedRecord<?, ?>> clz,
@ -103,7 +97,7 @@ public class AccountingPersistenceQueryPostgreSQL implements AccountingPersisten
String sql = query.getTimeSeriesQuery();
List<String> requestedTableField = query.getRequestedTableField();
RecordToDBMapper recordToDBMapper = query.getRecordToDBMapper();
RecordToDBFields recordToDBMapper = query.getRecordToDBMapper();
ResultSet resultSet = statement.executeQuery(sql);
@ -114,7 +108,7 @@ public class AccountingPersistenceQueryPostgreSQL implements AccountingPersisten
JSONObject jsonObject = new JSONObject();
for(String tableField : requestedTableField) {
String usageRecordField = recordToDBMapper.getUsageRecordField(tableField);
String usageRecordField = recordToDBMapper.getRecordField(tableField);
Object object = resultSet.getObject(tableField);
jsonObject.put(usageRecordField, object);
}

@ -14,6 +14,8 @@ 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 {
@ -22,7 +24,7 @@ public class Query {
public static final String DATE_OF_TIMESERIES_AS_FIELD = AggregatedRecord.START_TIME;
private Class<? extends AggregatedRecord<?, ?>> clz;
private final RecordToDBMapper recordToDBMapper;
private final RecordToDBFields recordToDBMapper;
private List<String> requestedTableField;
private StringBuffer stringBuffer;
@ -33,7 +35,7 @@ public class Query {
public Query(Class<? extends AggregatedRecord<?, ?>> clz) throws Exception {
this.clz = clz;
this.recordToDBMapper = UsageRecordToDBMapping.getRecordToDB(clz);
this.recordToDBMapper = RecordToDBMapping.getRecordToDB(clz);
}
public List<String> getRequestedTableField() {
@ -60,7 +62,7 @@ public class Query {
}
public RecordToDBMapper getRecordToDBMapper() {
public RecordToDBFields getRecordToDBMapper() {
return recordToDBMapper;
}

@ -1,98 +0,0 @@
package org.gcube.accounting.analytics.persistence.postgresql;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.gcube.documentstore.records.AggregatedRecord;
import org.gcube.documentstore.records.Record;
public class RecordToDBMapper {
protected static String getRecordTypeByClass(Class<? extends AggregatedRecord<?, ?>> clz) {
try {
Record r = clz.newInstance();
return r.getRecordType();
}catch (Exception e) {
String type = clz.getSimpleName();
type = type.replace("Abstract", "");
type = type.replace("Aggregated", "");
return type;
}
}
protected static String getKey(String fieldName) {
StringBuffer stringBuffer = new StringBuffer();
int lenght = fieldName.length();
boolean lastLowerCase = true;
for (int i=0; i<lenght; i++) {
Character ch = fieldName.charAt(i); /*traversing String one by one*/
if (Character.isUpperCase(ch)) {
if(lastLowerCase) {
stringBuffer.append("_");
}
lastLowerCase = false;
}else {
lastLowerCase = true;
}
stringBuffer.append(Character.toLowerCase(ch));
}
return stringBuffer.toString();
}
protected final Class<? extends AggregatedRecord<?, ?>> clz;
protected final String typeName;
protected final String tableName;
protected final Map<String, String> tableFieldToUsageRecordField;
protected final Map<String, String> usageRecordFieldToTableField;
public RecordToDBMapper(Class<? extends AggregatedRecord<?, ?>> clz) throws Exception {
this.clz = clz;
this.typeName = getRecordTypeByClass(clz);
this.tableName = typeName.toLowerCase();
this.tableFieldToUsageRecordField = new HashMap<>();
this.usageRecordFieldToTableField = new HashMap<>();
mapFields();
}
public RecordToDBMapper(String typeName, Class<? extends AggregatedRecord<?, ?>> clz) throws Exception {
this.clz = clz;
this.typeName = typeName;
this.tableName = typeName.toLowerCase();
this.tableFieldToUsageRecordField = new HashMap<>();
this.usageRecordFieldToTableField = new HashMap<>();
mapFields();
}
protected void mapFields() throws Exception {
Set<String> requiredFields = clz.newInstance().getRequiredFields();
for(String usageRecordField : requiredFields) {
String dbField = getKey(usageRecordField);
tableFieldToUsageRecordField.put(dbField, usageRecordField);
usageRecordFieldToTableField.put(usageRecordField, dbField);
}
}
public String getTableField(String usageRecordField) {
return usageRecordFieldToTableField.get(usageRecordField);
}
public String getUsageRecordField(String tableField) {
String ret = tableFieldToUsageRecordField.get(tableField);
if(ret==null && usageRecordFieldToTableField.keySet().contains(tableField)) {
ret = tableField;
}
return ret;
}
public String getTypeName() {
return typeName;
}
public String getTableName() {
return tableName;
}
}

@ -1,51 +0,0 @@
package org.gcube.accounting.analytics.persistence.postgresql;
import java.sql.Connection;
import java.sql.DriverManager;
import org.gcube.accounting.analytics.persistence.AccountingPersistenceBackendQueryConfiguration;
import org.gcube.accounting.persistence.AccountingPersistenceConfiguration;
import org.gcube.documentstore.records.AggregatedRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UsageRecordDBInfo {
private static final Logger logger = LoggerFactory.getLogger(UsageRecordDBInfo.class);
public static final String URL_PROPERTY_KEY = AccountingPersistenceConfiguration.URL_PROPERTY_KEY;
public static final String DB_SUFFIX = "-db";
public static final String USERNAME_SUFFIX = "-username";
public static final String PASSWORD_SUFFIX = "-password";
private final String baseURL;
private final String dbName;
private final String url;
private final String username;
private final String password;
protected final Class<? extends AggregatedRecord<?, ?>> clz;
protected final String typeName;
public UsageRecordDBInfo(Class<? extends AggregatedRecord<?, ?>> clz, AccountingPersistenceBackendQueryConfiguration configuration) throws Exception {
this.clz = clz;
this.typeName = UsageRecordToDBMapping.getRecordToDB(clz).getTypeName();
this.baseURL = configuration.getProperty(URL_PROPERTY_KEY);
this.dbName = configuration.getProperty(typeName+DB_SUFFIX);
this.url = baseURL + "/" + dbName;
this.username = configuration.getProperty(typeName+USERNAME_SUFFIX);
this.password = configuration.getProperty(typeName+PASSWORD_SUFFIX);
}
protected Connection getConnection() throws Exception {
Class.forName("org.postgresql.Driver");
Connection connection = DriverManager.getConnection(url, username, password);
logger.trace("Database {} opened successfully", url);
connection.setAutoCommit(false);
return connection;
}
}

@ -1,25 +0,0 @@
package org.gcube.accounting.analytics.persistence.postgresql;
import java.util.HashMap;
import java.util.Map;
import org.gcube.documentstore.records.AggregatedRecord;
public class UsageRecordToDBMapping {
protected final static Map<Class<? extends AggregatedRecord<?, ?>>, RecordToDBMapper> classToRecordToDBMapper;
static {
classToRecordToDBMapper = new HashMap<>();
}
public static synchronized RecordToDBMapper getRecordToDB(Class<? extends AggregatedRecord<?, ?>> clz) throws Exception {
RecordToDBMapper recordToDBMapper = classToRecordToDBMapper.get(clz);
if(recordToDBMapper==null) {
recordToDBMapper = new RecordToDBMapper(clz);
classToRecordToDBMapper.put(clz, recordToDBMapper);
}
return recordToDBMapper;
}
}
Loading…
Cancel
Save