package org.gcube.dataharvest.dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.dataharvest.datamodel.HarvestedData; import org.gcube.dataharvest.utils.DateUtils; import org.postgresql.util.PSQLException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Eric Perrone (ISTI - CNR) * @author Luca Frosini (ISTI - CNR) */ public class Dao { private Connection conn = null; private static Logger logger = LoggerFactory.getLogger(Dao.class); /** * Class constructor. This method must be called before any other class * method. * * @throws DaoException */ public void init() throws DaoException { try { Class.forName("org.postgresql.Driver"); } catch(ClassNotFoundException ex) { logger.error(ex.getLocalizedMessage()); throw new DaoException(ex.getLocalizedMessage(), ex.getCause()); } } /** * Connect a database * * @param url * @param user * @param password * @throws DaoException */ public void connect(String url, String user, String password) throws DaoException { try { conn = DriverManager.getConnection(url, user, password); logger.debug("Connected to: " + url); } catch(SQLException ex) { logger.error(ex.getLocalizedMessage()); throw new DaoException(ex.getLocalizedMessage(), ex.getCause()); } } /** * Release a database connection * * @throws DaoException */ public void disconnect() throws DaoException { try { if(conn != null) { conn.close(); conn = null; logger.debug("Disconnecting from database"); } } catch(SQLException ex) { logger.error(ex.getLocalizedMessage()); throw new DaoException(ex.getLocalizedMessage(), ex.getCause()); } } /** * Check the connection with the database. * * @return true|false */ public boolean isConnected() { return (!(conn == null)); } /** * Getter for the database connection * * @return Connection class */ public Connection getConnection() { return conn; } /** * Read on the database all active VRES * * @return */ public String[] getActiveVres() { String query = "select dname from context where dname is not null and dismissed is null"; logger.debug(query); Statement s = null; ResultSet rs = null; ArrayList list = new ArrayList<>(); try { s = conn.createStatement(); rs = s.executeQuery(query); while(rs.next()) { list.add(rs.getString("dname")); } return list.toArray(new String[list.size()]); } catch(Exception ex) { logger.error(ex.getLocalizedMessage()); return null; } finally { if(rs != null) { try { rs.close(); } catch(SQLException ex) { // do nothing } } if(s != null) { try { s.close(); } catch(SQLException ex) { // do nothing } } } } /** * This method insert/update data in the monthly_measure database table. * * @param data * @param from * @param to * @throws DaoException */ public void insertMonthlyMeasure(List data, Date from, Date to, boolean doUpdate) throws DaoException { // first of all: check if data of the same type are already in the // database. // In this case data will be updated. Calendar cFrom = DateUtils.dateToCalendar(from); Calendar cTo = DateUtils.dateToCalendar(to); int monthFrom = cFrom.get(Calendar.MONTH); int yearFrom = cFrom.get(Calendar.YEAR); int monthTo = cTo.get(Calendar.MONTH); int yearTo = cTo.get(Calendar.YEAR); if((monthFrom != monthTo) || (yearFrom != yearTo)) { String err = "Invalid time period. The time period MUST refer one month."; logger.error(err); throw new DaoException(err, null); } if(data == null || data.size() <= 0) { String err = "No data passed in input. Aborting operation."; logger.error(err); throw new DaoException(err, null); } monthFrom++; // because january = 0... try { for(HarvestedData harvestedData : data) { int contextId = getOrInsertContextId(harvestedData.getContext()); String query = "select id from monthly_measure where measure_type_id=" + harvestedData.getDataType() + " and context_id=" + contextId + " and month=" + monthFrom + " and year=" + yearFrom; logger.debug(query); Statement sel = conn.createStatement(); ResultSet rs = sel.executeQuery(query); if(rs.next()) { if(doUpdate) { // record found: update it Statement s = conn.createStatement(); int id = rs.getInt("id"); String update = "update monthly_measure set measure=" + harvestedData.getMeasure() + " where id=" + id; logger.debug(update); s.execute(update); s.close(); } else { logger.warn("Skipped " + harvestedData.getContext()); } } else { // record not found: insert new record Statement s = conn.createStatement(); String insert = "insert into monthly_measure (year, month, measure, measure_type_id, context_id, day) values ("; insert += yearFrom + "," + monthFrom + "," + harvestedData.getMeasure() + "," + harvestedData.getDataType() + ","; insert += "(select id from context where dname='" + harvestedData.getContext() + "'),"; insert += "'" + yearFrom + "-" + monthFrom + "-01'"; insert += ")"; logger.debug(insert); s.execute(insert); s.close(); } rs.close(); sel.close(); } } catch(PSQLException x) { // handled exception: try to iterate... logger.error(x.getLocalizedMessage()); } catch(Exception x) { // not handled exception: stop logger.error(x.getLocalizedMessage()); throw new DaoException(x.getClass().getName() + "::" + x.getLocalizedMessage(), x); } } public enum contextType { INFRASTRUCTURE, VO, VRE } public int getOrInsertContextId(String contextFullName) throws SQLException { String query = "select id from context where dname='" + contextFullName + "'"; logger.debug(query); Statement sel = conn.createStatement(); ResultSet rs = sel.executeQuery(query); if(rs.next()) { // context found int id = rs.getInt("id"); logger.debug("Context {} has id {}", contextFullName, id); return id; } else { // context not found: insert new record int parentId = 0; // The id of D4Science infrastructure as aggregator int lastIndexOfSlash = contextFullName.lastIndexOf("/"); if(lastIndexOfSlash!=0) { String parentContextFullName = contextFullName.substring(0, contextFullName.lastIndexOf("/")); parentId = getOrInsertContextId(parentContextFullName); } // It is a new context and we don't know which context type is. Using 0 for ROOT, 1 for VO, 2 for VRE int contextTypeId = contextType.INFRASTRUCTURE.ordinal(); ScopeBean scopeBean = new ScopeBean(contextFullName); switch(scopeBean.type()) { case INFRASTRUCTURE: contextTypeId = contextType.INFRASTRUCTURE.ordinal(); break; case VO: contextTypeId = contextType.VO.ordinal(); break; case VRE: contextTypeId = contextType.VRE.ordinal(); break; default: break; } Statement s = conn.createStatement(); String insert = "insert into context (name, context_id, context_type_id, dname) values ('"; insert += contextFullName + "'," + parentId + "," + contextTypeId + ", '" + contextFullName; insert += "')"; logger.debug(insert); s.execute(insert); s.close(); } rs.close(); sel.close(); return getOrInsertContextId(contextFullName); } public ArrayList getSubTree(Integer rootId) throws DaoException { String queryBase = "select id from context where context_id in (%%)"; ArrayList subTree = new ArrayList<>(); ArrayList temp = new ArrayList<>(); Statement s = null; ResultSet rs = null; temp.add(rootId); subTree.add(rootId); boolean again = true; for(int i = 0; (i < 10) && (again); i++) { try { String listId = ""; for(Integer id : temp) { listId += "," + id; } listId = listId.substring(1); String query = queryBase.replace("%%", listId); s = conn.createStatement(); rs = s.executeQuery(query); if(rs.next()) { temp = new ArrayList<>(); Integer dbId = rs.getInt("id"); subTree.add(dbId); temp.add(dbId); while(rs.next()) { dbId = rs.getInt("id"); subTree.add(dbId); temp.add(dbId); } } else { again = false; } rs.close(); s.close(); } catch(Exception x) { logger.error(x.getLocalizedMessage()); throw new DaoException(x.getClass().getName() + "::" + x.getLocalizedMessage(), x); } } return subTree; } public void createSocialReport(int contextId, int orderBy) throws DaoException { Statement rep = null; ResultSet rs = null; try { String report = "insert into report (context_id, name, orderby, chart_type, x_text, y_text) values "; report += "(" + contextId + ", \'VRE Social\', " + orderBy + ", \'column\', \'Period\', \'Social interaction\')"; logger.debug(report); rep = conn.createStatement(); rep.execute(report); String query = "select id from report where name=\'VRE Social\' order by id desc"; rs = rep.executeQuery(query); if(rs.next()) { int id = rs.getInt("id"); String reportItem = "insert into report_item (report_id, type_id_1, type_id_1_name) "; reportItem += "values (" + id + ", 8, \'mt\'), (" + id + ", 9, \'mt\'), (" + id + ", 10, \'mt\')"; rep.execute(reportItem); } else throw new DaoException("No report id.", null); } catch(SQLException ex) { logger.error(ex.getLocalizedMessage()); throw new DaoException(ex.getLocalizedMessage(), ex.getCause()); } finally { try { if(rs != null) { rs.close(); } if(rep != null) { rep.close(); } } catch(SQLException ex) { logger.error(ex.getLocalizedMessage()); } } } /** * Dummy tester * * @Deprecated * @param originator * @throws DaoException * */ public void dummyTest(String originator) throws DaoException { String insert = "insert into dummy (now, originator) values(current_timestamp, '" + originator + "')"; logger.debug(insert); Statement s = null; try { s = conn.createStatement(); s.execute(insert); } catch(SQLException ex) { logger.error(ex.getLocalizedMessage()); throw new DaoException(ex.getLocalizedMessage(), ex.getCause()); } finally { if(s != null) try { s.close(); } catch(SQLException ex) { logger.error(ex.getLocalizedMessage()); } } } }