/** * * Copyright * 2009-2015 Jayway Products AB * 2016-2017 Föreningen Sambruk * * Licensed under AGPL, Version 3.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/agpl.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package se.streamsource.streamflow.web.application.statistics; import org.qi4j.api.injection.scope.Service; import org.qi4j.api.mixin.Mixins; import org.qi4j.api.service.Activatable; import org.qi4j.api.service.ServiceComposite; import org.qi4j.api.service.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import se.streamsource.infrastructure.database.Databases; import javax.sql.DataSource; import java.sql.PreparedStatement; import java.sql.SQLException; /** * Statistics store that saves data into a JDBC database */ @Mixins(JdbcStatisticsStore.Mixin.class) public interface JdbcStatisticsStore extends ServiceComposite, StatisticsStore, Activatable { class Mixin implements StatisticsStore, Activatable { @Service ServiceReference<DataSource> dataSource; private Logger log; public void activate() throws Exception { log = LoggerFactory.getLogger( JdbcStatisticsStore.class ); } public void passivate() throws Exception { } public void related( final RelatedStatisticsValue related ) throws StatisticsStoreException { Databases databases = getDatabases(); try { int rows = databases.update( "UPDATE descriptions SET description=?, type=? WHERE id=?", new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setString( 1, related.description().get() ); statement.setString( 2, related.relatedType().get().name() ); statement.setString( 3, related.identity().get() ); } } ); if (rows == 0) { // Do insert databases.update( "INSERT INTO descriptions (id,description,type) VALUES (?,?,?)", new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setString( 1, related.identity().get() ); statement.setString( 2, related.description().get() ); statement.setString( 3, related.relatedType().get().name() ); } } ); } } catch (SQLException e) { throw new StatisticsStoreException( "Could not update database", e ); } } public void caseStatistics( final CaseStatisticsValue caseStatistics ) throws StatisticsStoreException { Databases databases = getDatabases(); try { // Delete any old data databases.update( "DELETE FROM cases WHERE id=?", new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setString( 1, caseStatistics.identity().get() ); } } ); databases.update( "INSERT INTO cases VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { int idx = 1; statement.setString( idx++, caseStatistics.identity().get() ); statement.setString( idx++, caseStatistics.caseId().get() ); statement.setString( idx++, caseStatistics.description().get() ); statement.setString( idx++, caseStatistics.resolutionId().get() ); statement.setTimestamp( idx++, new java.sql.Timestamp( caseStatistics.createdOn().get().getTime() ) ); statement.setTimestamp( idx++, new java.sql.Timestamp( caseStatistics.closedOn().get().getTime() ) ); statement.setLong( idx++, caseStatistics.duration().get() ); statement.setString( idx++, caseStatistics.assigneeId().get() ); statement.setString( idx++, caseStatistics.caseTypeId().get() ); statement.setString( idx++, caseStatistics.caseTypeOwnerId().get() ); statement.setString( idx++, caseStatistics.projectId().get() ); statement.setString( idx++, caseStatistics.organizationalUnitId().get() ); statement.setString( idx++, caseStatistics.groupId().get() ); statement.setTimestamp( idx++, caseStatistics.dueOn().get() != null ? new java.sql.Timestamp( caseStatistics.dueOn().get().getTime() ) : null ); statement.setString( idx++, caseStatistics.priority().get() ); statement.setBoolean( idx, false ); } } ); databases.update( "DELETE FROM labels WHERE id=?", new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setString( 1, caseStatistics.identity().get() ); } } ); for (final String label : caseStatistics.labels().get()) { databases.update("INSERT INTO labels (id,label) VALUES (?,?)", new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setString( 1, caseStatistics.identity().get() ); statement.setString( 2, label ); } }); } databases.update( "DELETE FROM fields WHERE id=?", new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setString( 1, caseStatistics.identity().get() ); } } ); for (final FormFieldStatisticsValue field : caseStatistics.fields().get()) { databases.update("INSERT INTO fields (id,form,field,value,datatype) VALUES (?,?,?,?,?)", new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setString( 1, caseStatistics.identity().get() ); statement.setString( 2, field.formId().get() ); statement.setString( 3, field.fieldId().get() ); statement.setString( 4, field.value().get() ); statement.setString( 5, field.datatype().get() ); } }); } } catch (SQLException exception) { throw new StatisticsStoreException( "Could not update database", exception ); } } public void removedCase( final String id ) throws StatisticsStoreException { Databases databases = getDatabases(); try { Databases.StatementVisitor visitor = new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setBoolean( 1, true ); statement.setString( 2, id ); } }; databases.update( "UPDATE cases SET deleted=? WHERE id=?", visitor ); } catch (SQLException e) { throw new StatisticsStoreException("Could not remove case", e); } } public void structure(OrganizationalStructureValue structureValue) throws StatisticsStoreException { Databases database = getDatabases(); try { database.update("DELETE FROM organization"); for (final OrganizationalUnitValue organizationalUnitValue : structureValue.structure().get()) { database.update("INSERT INTO organization VALUES (?,?,?,?,?)", new Databases.StatementVisitor() { public void visit(PreparedStatement preparedStatement) throws SQLException { preparedStatement.setString(1, organizationalUnitValue.id().get()); preparedStatement.setString(2, organizationalUnitValue.name().get()); preparedStatement.setInt(3, organizationalUnitValue.left().get()); preparedStatement.setInt(4, organizationalUnitValue.right().get()); preparedStatement.setString(5, organizationalUnitValue.parent().get()); } }); } } catch (SQLException e) { log.error("Could not update organizational structure", e); throw new StatisticsStoreException("Could not update organizational structure", e); } } public void clearAll() throws StatisticsStoreException { Databases databases = getDatabases(); try { databases.update( "DELETE FROM descriptions" ); databases.update( "DELETE FROM labels" ); databases.update( "DELETE FROM fields" ); Databases.StatementVisitor visitor = new Databases.StatementVisitor() { public void visit( PreparedStatement statement ) throws SQLException { statement.setBoolean( 1, false ); } }; databases.update( "DELETE FROM cases where deleted=?", visitor ); } catch (SQLException e) { log.error( "Could not remove statistics", e ); throw new StatisticsStoreException("Could not remove case", e); } } public Databases getDatabases() throws StatisticsStoreException { try { return new Databases(dataSource.get()); } catch (Exception e) { throw new StatisticsStoreException("DataSource not available", e); } } } }