/* ================================================================== * JdbcAuthorizationDao.java - 8/06/2015 8:57:04 am * * Copyright 2007-2015 SolarNetwork.net Dev Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * ================================================================== */ package net.solarnetwork.node.ocpp.dao; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.xml.datatype.XMLGregorianCalendar; import net.solarnetwork.node.ocpp.Authorization; import net.solarnetwork.node.ocpp.AuthorizationDao; import ocpp.v15.cs.AuthorizationStatus; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * JDBC implementation of {@link AuthorizationDao}. * * @author matt * @version 1.0 */ public class JdbcAuthorizationDao extends AbstractOcppJdbcDao<Authorization> implements AuthorizationDao { /** The default tables version. */ public static final int TABLES_VERSION = 1; /** The table name for {@link Authorization} data. */ public static final String TABLE_NAME = "ocpp_auth"; /** The default classpath Resource for the {@code initSqlResource}. */ public static final String INIT_SQL = "derby-auth-init.sql"; /** The default value for the {@code sqlGetTablesVersion} property. */ public static final String SQL_GET_TABLES_VERSION = "SELECT svalue FROM solarnode.sn_settings WHERE skey = " + "'solarnode.ocpp_auth.version'"; public static final String SQL_INSERT = "insert"; public static final String SQL_UPDATE = "update"; public static final String SQL_GET_BY_PK = "get-pk"; public static final String SQL_DELETE_EXPIRED = "delete-expired"; public static final String SQL_FIND_STATUS_COUNTS = "statuscounts"; /** * Default constructor. */ public JdbcAuthorizationDao() { super(); setSqlResourcePrefix("derby-auth"); setTableName(TABLE_NAME); setTablesVersion(TABLES_VERSION); setSqlGetTablesVersion(SQL_GET_TABLES_VERSION); setInitSqlResource(new ClassPathResource(INIT_SQL, getClass())); } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED) public void storeAuthorization(final Authorization auth) { Authorization existing = getAuthorization(auth.getIdTag()); if ( existing != null ) { updateDomainObject(auth, getSqlResource(SQL_UPDATE)); } else { insertDomainObject(auth, getSqlResource(SQL_INSERT)); } } @Override @Transactional(readOnly = true, propagation = Propagation.SUPPORTS) public Authorization getAuthorization(String idTag) { List<Authorization> results = getJdbcTemplate().query(getSqlResource(SQL_GET_BY_PK), new AuthorizationRowMapper(), idTag); if ( results != null && results.size() > 0 ) { return results.get(0); } return null; } @Override protected void setStoreStatementValues(Authorization auth, PreparedStatement ps) throws SQLException { // Row order is: (created, idtag, parent_idtag, status, expires) ps.setTimestamp(1, new Timestamp(auth.getCreated() != null ? auth.getCreated().getTime() : System.currentTimeMillis()), utcCalendar); ps.setString(2, auth.getIdTag()); ps.setString(3, auth.getParentIdTag()); ps.setString(4, auth.getStatus().toString()); if ( auth.getExpiryDate() != null ) { // store ts in UTC time zone Calendar cal = calendarForXMLDate(auth.getExpiryDate()); Timestamp ts = new Timestamp(cal.getTimeInMillis()); ps.setTimestamp(5, ts, cal); } else { ps.setNull(5, Types.TIMESTAMP); } } @Override protected void setUpdateStatementValues(Authorization auth, PreparedStatement ps) throws SQLException { ps.setString(1, auth.getParentIdTag()); ps.setString(2, auth.getStatus().toString()); if ( auth.getExpiryDate() != null ) { // store ts in UTC time zone Calendar cal = calendarForXMLDate(auth.getExpiryDate()); Timestamp ts = new Timestamp(cal.getTimeInMillis()); ps.setTimestamp(3, ts, cal); } else { ps.setNull(3, Types.TIMESTAMP); } ps.setString(4, auth.getIdTag()); } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED) public int deleteExpiredAuthorizations(Date olderThanDate) { final Calendar cal = calendarForDate(olderThanDate != null ? olderThanDate : new Date()); final Timestamp ts = new Timestamp(cal.getTimeInMillis()); return getJdbcTemplate().update(getSqlResource(SQL_DELETE_EXPIRED), new PreparedStatementSetter() { @Override public void setValues(PreparedStatement ps) throws SQLException { ps.setTimestamp(1, ts, cal); } }); } @Override @Transactional(readOnly = true, propagation = Propagation.SUPPORTS) public Map<AuthorizationStatus, Integer> statusCounts() { final Map<AuthorizationStatus, Integer> result = new LinkedHashMap<AuthorizationStatus, Integer>( AuthorizationStatus.values().length); getJdbcTemplate().query(getSqlResource(SQL_FIND_STATUS_COUNTS), new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { AuthorizationStatus key = AuthorizationStatus.valueOf(rs.getString(1)); int count = rs.getInt(2); result.put(key, count); } }); return result; } private final class AuthorizationRowMapper implements RowMapper<Authorization> { private XMLGregorianCalendar xmlTimestamp(Timestamp ts) { if ( ts == null ) { return null; } GregorianCalendar cal = new GregorianCalendar(utcCalendar.getTimeZone()); cal.setTimeInMillis(ts.getTime()); return datatypeFactory.newXMLGregorianCalendar(cal); } @Override public Authorization mapRow(ResultSet rs, int rowNum) throws SQLException { Authorization auth = new Authorization(); // Row order is: created, idtag, parent_idtag, status, expires Timestamp ts = rs.getTimestamp(1, utcCalendar); if ( ts != null ) { auth.setCreated(new Date(ts.getTime())); } auth.setIdTag(rs.getString(2)); auth.setParentIdTag(rs.getString(3)); auth.setStatus(AuthorizationStatus.valueOf(rs.getString(4))); auth.setExpiryDate(xmlTimestamp(rs.getTimestamp(5, utcCalendar))); return auth; } } }