/* ================================================================== * JdbcGeneralNodeDatumDao.java - Aug 26, 2014 7:03:34 AM * * Copyright 2007-2014 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.dao.jdbc.general; import java.io.IOException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Date; import java.util.List; import net.solarnetwork.domain.GeneralDatumSamples; import net.solarnetwork.domain.GeneralNodeDatumSamples; import net.solarnetwork.node.dao.jdbc.AbstractJdbcDatumDao; import net.solarnetwork.node.domain.GeneralNodeDatum; import org.springframework.core.io.ClassPathResource; import org.springframework.dao.DuplicateKeyException; import org.springframework.jdbc.core.RowMapper; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.fasterxml.jackson.databind.ObjectMapper; /** * JDBC-based implementation of {@link net.solarnetwork.node.dao.DatumDao} for * {@link GeneralNodeDatum} domain objects. * * @author matt * @version 1.1 */ public class JdbcGeneralNodeDatumDao extends AbstractJdbcDatumDao<GeneralNodeDatum> { /** The default tables version. */ public static final int DEFAULT_TABLES_VERSION = 1; /** The table name for {@link PowerDatum} data. */ public static final String TABLE_GENERAL_NODE_DATUM = "sn_general_node_datum"; /** The default classpath Resource for the {@code initSqlResource}. */ public static final String DEFAULT_INIT_SQL = "derby-generalnodedatum-init.sql"; /** The default value for the {@code sqlGetTablesVersion} property. */ public static final String DEFAULT_SQL_GET_TABLES_VERSION = "SELECT svalue FROM solarnode.sn_settings WHERE skey = " + "'solarnode.sn_general_node_datum.version'"; private ObjectMapper objectMapper; /** * Default constructor. */ public JdbcGeneralNodeDatumDao() { super(); setSqlResourcePrefix("derby-generalnodedatum"); setTableName(TABLE_GENERAL_NODE_DATUM); setTablesVersion(DEFAULT_TABLES_VERSION); setSqlGetTablesVersion(DEFAULT_SQL_GET_TABLES_VERSION); setInitSqlResource(new ClassPathResource(DEFAULT_INIT_SQL, getClass())); } @Override public Class<? extends GeneralNodeDatum> getDatumType() { return GeneralNodeDatum.class; } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED, noRollbackFor = DuplicateKeyException.class) public void storeDatum(GeneralNodeDatum datum) { try { storeDomainObject(datum); } catch ( DuplicateKeyException e ) { List<GeneralNodeDatum> existing = findDatum(SQL_RESOURCE_FIND_FOR_PRIMARY_KEY, preparedStatementSetterForPrimaryKey(datum.getCreated(), datum.getSourceId()), rowMapper()); if ( existing.size() > 0 ) { // only update if the samples have changed GeneralDatumSamples existingSamples = existing.get(0).getSamples(); GeneralDatumSamples newSamples = datum.getSamples(); if ( !newSamples.equals(existingSamples) ) { updateDomainObject(datum, getSqlResource(SQL_RESOURCE_UPDATE_DATA)); } } } } @Override protected void setUpdateStatementValues(GeneralNodeDatum datum, PreparedStatement ps) throws SQLException { int col = 1; ps.setString(col++, jsonForSamples(datum)); ps.setTimestamp(col++, new Timestamp(datum.getCreated().getTime())); ps.setString(col++, datum.getSourceId()); } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED) public void setDatumUploaded(GeneralNodeDatum datum, Date date, String destination, String trackingId) { updateDatumUpload(datum, date == null ? System.currentTimeMillis() : date.getTime()); } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED) public int deleteUploadedDataOlderThan(int hours) { return deleteUploadedDataOlderThanHours(hours); } private RowMapper<GeneralNodeDatum> rowMapper() { return new RowMapper<GeneralNodeDatum>() { @Override public GeneralNodeDatum mapRow(ResultSet rs, int rowNum) throws SQLException { if ( log.isTraceEnabled() ) { log.trace("Handling result row " + rowNum); } GeneralNodeDatum datum = new GeneralNodeDatum(); int col = 0; datum.setCreated(rs.getTimestamp(++col)); datum.setSourceId(rs.getString(++col)); String jdata = rs.getString(++col); if ( jdata != null ) { GeneralNodeDatumSamples s; try { s = objectMapper.readValue(jdata, GeneralNodeDatumSamples.class); datum.setSamples(s); } catch ( IOException e ) { log.error("Error deserializing JSON into GeneralNodeDatumSamples: {}", e.getMessage()); } } return datum; } }; } @Override @Transactional(readOnly = true, propagation = Propagation.REQUIRED) public List<GeneralNodeDatum> getDatumNotUploaded(String destination) { return findDatumNotUploaded(rowMapper()); } private String jsonForSamples(GeneralNodeDatum datum) { String json; try { json = objectMapper.writeValueAsString(datum.getSamples()); } catch ( IOException e ) { log.error("Error serializing GeneralDatumSamples into JSON: {}", e.getMessage()); json = "{}"; } return json; } @Override protected void setStoreStatementValues(GeneralNodeDatum datum, PreparedStatement ps) throws SQLException { int col = 0; ps.setTimestamp(++col, new java.sql.Timestamp(datum.getCreated() == null ? System.currentTimeMillis() : datum .getCreated().getTime())); ps.setString(++col, datum.getSourceId() == null ? "" : datum.getSourceId()); String json = jsonForSamples(datum); ps.setString(++col, json); } public ObjectMapper getObjectMapper() { return objectMapper; } public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } }