Skip to content

Commit afdf49f

Browse files
authored
Merge pull request #27 from eisbilir/fix/list-projects
fix getting phases
2 parents 1411a8f + 4859705 commit afdf49f

File tree

1 file changed

+215
-6
lines changed

1 file changed

+215
-6
lines changed

phase-management-persistence/src/main/java/com/topcoder/management/phase/db/InformixPhasePersistence.java

Lines changed: 215 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,18 @@ public class InformixPhasePersistence implements PhasePersistence {
203203
+ "JOIN project_phase ON dependent_phase_id = project_phase_id "
204204
+ "WHERE project_id IN ";
205205

206+
/**
207+
* Selects phase data.
208+
*/
209+
private static final String SELECT_PHASE_FOR_PROJECT = "SELECT project_phase_id, project_id, fixed_start_time, "
210+
+ "scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, duration, "
211+
+ "project_phase.modify_date, "
212+
+ "phase_type_lu.phase_type_id, phase_type_lu.name phase_type_name, "
213+
+ "phase_status_lu.phase_status_id, phase_status_lu.name phase_status_name "
214+
+ "FROM project_phase JOIN phase_type_lu ON phase_type_lu.phase_type_id = project_phase.phase_type_id "
215+
+ "JOIN phase_status_lu ON phase_status_lu.phase_status_id = "
216+
+ "project_phase.phase_status_id WHERE project_id = ?";
217+
206218
/**
207219
* Selects phase data.
208220
*/
@@ -241,11 +253,6 @@ public class InformixPhasePersistence implements PhasePersistence {
241253
*/
242254
private static final String SELECT_PHASE_TYPES = "SELECT phase_type_id, name phase_type_name FROM phase_type_lu";
243255

244-
/**
245-
* Selects all projects - checks if all exists in database.
246-
*/
247-
private static final String SELECT_PROJECT_IDS = "SELECT project_id FROM project WHERE project_id IN ";
248-
249256
/**
250257
* <p>
251258
* Represents the audit creation type.
@@ -469,7 +476,14 @@ public InformixPhasePersistence(DBConnectionFactory connectionFactory, String co
469476
* @throws PhasePersistenceException if any database error happen.
470477
*/
471478
public Project getProjectPhases(long projectId) throws PhasePersistenceException {
472-
return getProjectPhases(new long[] {projectId})[0];
479+
Connection conn = createConnection(false);
480+
try {
481+
return getProjectPhasesImpl(conn, projectId);
482+
} catch (SQLException ex) {
483+
throw new PhasePersistenceException("Error occurs while retrieving the projects.", ex);
484+
} finally {
485+
close(conn);
486+
}
473487
}
474488

475489
/**
@@ -507,6 +521,65 @@ public Project[] getProjectPhases(long[] projectIds) throws PhasePersistenceExce
507521
}
508522
}
509523

524+
/**
525+
* This the current implementation of the {@link #getProjectPhases(long)} method. It will first check which
526+
* project for the given ids exists and which have no phases. The it selects all the phases for the project,
527+
* create them and return.
528+
*
529+
* @param conn the database connection to use.
530+
* @param projectIds the ids of the projects to retrieve.
531+
* @return the array of projects with one to one mapping between project and it id.
532+
*
533+
* @throws SQLException if any database error occurs.
534+
* @throws PhasePersistenceException if other error happen.
535+
*/
536+
private Project getProjectPhasesImpl(Connection conn, long projectId) throws SQLException,
537+
PhasePersistenceException {
538+
539+
PreparedStatement pstmt = null;
540+
ResultSet rs = null;
541+
542+
// create workdays to be used to create the project
543+
Workdays workdays = new DefaultWorkdaysFactory().createWorkdaysInstance();
544+
Project project = new Project(new Date(Long.MAX_VALUE), workdays);
545+
project.setId(projectId);
546+
try {
547+
Map phasesMap = new HashMap();
548+
// prepare the query to retrieve the phases .
549+
pstmt = conn.prepareStatement(SELECT_PHASE_FOR_PROJECT);
550+
pstmt.setLong(1, projectId);
551+
552+
rs = pstmt.executeQuery();
553+
554+
// for each phase in the response create the Phase object and add it to the internal list
555+
while (rs.next()) {
556+
Phase phase = populatePhase(rs, project);
557+
phasesMap.put(new Long(phase.getId()), phase);
558+
}
559+
560+
// fill the phases depedencies and criteria for them
561+
if (phasesMap.size() > 0) {
562+
fillDependencies(conn, phasesMap, new long[] {projectId});
563+
fillCriteria(conn, phasesMap, new long[] {projectId});
564+
}
565+
566+
// this comparator is used to get the lowest start date
567+
Comparator phasesComparator = new PhaseStartDateComparator();
568+
// set the correct date for project
569+
Phase[] phases = project.getAllPhases(phasesComparator);
570+
// if project has any phases - get the first one
571+
if (phases.length > 0) {
572+
project.setStartDate(phases[0].getScheduledStartDate());
573+
}
574+
575+
// create the result array
576+
return project;
577+
} finally {
578+
close(rs);
579+
close(pstmt);
580+
}
581+
}
582+
510583
/**
511584
* This the current implementation of the {@link #getProjectPhases(long[])} method. It will first check which
512585
* project for the given ids exists and which have no phases. The it selects all the phases for the projects,
@@ -625,6 +698,142 @@ private Project[] getProjectPhasesImpl(Connection conn, long[] projectIds) throw
625698
}
626699
}
627700

701+
/**
702+
* This method set the phase criteria into the phases from the given map.
703+
*
704+
* @param conn the database connection to be used.
705+
* @param phases the Phases to which criteria will ba add. Key should be Long phase id, value - Phase object.
706+
* @param projectIds all the project ids.
707+
*
708+
* @throws SQLException if any database error occurs.
709+
*/
710+
private void fillCriteria(Connection conn, Map phases, long[] projectIds) throws SQLException {
711+
PreparedStatement pstmt = null;
712+
ResultSet rs = null;
713+
714+
try {
715+
// create the statement
716+
pstmt = conn.prepareStatement(SELECT_PHASE_CRITERIA_FOR_PROJECTS + createQuestionMarks(projectIds.length));
717+
718+
// set the id to the statement
719+
for (int i = 0; i < projectIds.length; ++i) {
720+
pstmt.setLong(i + 1, projectIds[i]);
721+
}
722+
723+
// execute query
724+
rs = pstmt.executeQuery();
725+
726+
// create the phase criteria
727+
while (rs.next()) {
728+
// get the phase id
729+
Long id = new Long(rs.getLong("project_phase_id"));
730+
// get criteria name and parameter
731+
String name = rs.getString("name");
732+
String parameter = rs.getString("parameter");
733+
734+
// get the phase and add criteria
735+
Phase phase = (Phase) phases.get(id);
736+
phase.setAttribute(name, parameter);
737+
}
738+
} finally {
739+
close(rs);
740+
close(pstmt);
741+
}
742+
}
743+
744+
/**
745+
* This method selects all the depedencies for phases.
746+
*
747+
* @param conn the database connection.
748+
* @param phases the map of already retrieved phases.
749+
* @param projectIds all the project ids.
750+
*
751+
* @throws SQLException if database error occures.
752+
* @throws PhasePersistenceException if the phase depedencies cannot be filled.
753+
*/
754+
private void fillDependencies(Connection conn, Map phases, long[] projectIds) throws SQLException,
755+
PhasePersistenceException {
756+
// get the phase
757+
PreparedStatement pstmt = null;
758+
ResultSet rs = null;
759+
760+
try {
761+
// create the statement
762+
pstmt = conn.prepareStatement(SELECT_DEPENDENCY_FOR_PROJECTS + createQuestionMarks(projectIds.length));
763+
764+
// set the id to the statement
765+
for (int i = 0; i < projectIds.length; ++i) {
766+
pstmt.setLong(i + 1, projectIds[i]);
767+
}
768+
769+
// execte the query
770+
rs = pstmt.executeQuery();
771+
772+
while (rs.next()) {
773+
// get the depedency
774+
Long dependentId = new Long(rs.getLong("dependent_phase_id"));
775+
Long dependencyId = new Long(rs.getLong("dependency_phase_id"));
776+
// if the phase exists - create dependecy
777+
if (phases.containsKey(dependentId) && phases.containsKey(dependencyId)) {
778+
Phase phase = (Phase) phases.get(dependentId);
779+
Dependency dependency = createDependency(rs, phases, phase);
780+
phase.addDependency(dependency);
781+
} else {
782+
// because we have retrieved all the phases for project before, this should never happen
783+
throw new PhasePersistenceException("Missing dependecy: " + dependencyId
784+
+ " for phase: " + dependentId);
785+
}
786+
}
787+
788+
} finally {
789+
close(rs);
790+
close(pstmt);
791+
}
792+
}
793+
794+
/**
795+
* Create the Dependency instance from given result set.
796+
*
797+
* @param rs the source result set.
798+
* @param phases the retrieved phases.
799+
* @param dependantPhase the dependant phase.
800+
* @return the Dependency instance.
801+
*
802+
* @throws SQLException if database error occures.
803+
*/
804+
private static Dependency createDependency(ResultSet rs, Map phases, Phase dependantPhase) throws SQLException {
805+
Phase dependencyPhase = (Phase) phases.get(new Long(rs.getLong("dependency_phase_id")));
806+
long lagTime = rs.getLong("lag_time");
807+
808+
return new Dependency(dependencyPhase, dependantPhase, rs.getBoolean("dependency_start"), rs
809+
.getBoolean("dependent_start"), lagTime);
810+
}
811+
812+
/**
813+
* Creates the Phase instance from the given ResultSet.
814+
*
815+
* @param rs the source result set.
816+
* @param project the project for phase.
817+
* @return the Phase instance.
818+
* @throws SQLException if database error occurs.
819+
*/
820+
private static Phase populatePhase(ResultSet rs, Project project) throws SQLException {
821+
long duration = rs.getLong("duration");
822+
Phase phase = new Phase(project, duration);
823+
phase.setActualEndDate(rs.getTimestamp("actual_end_time"));
824+
phase.setActualStartDate(rs.getTimestamp("actual_start_time"));
825+
phase.setFixedStartDate(rs.getTimestamp("fixed_start_time"));
826+
phase.setId(rs.getLong("project_phase_id"));
827+
828+
phase.setPhaseStatus(populatePhaseStatus(rs));
829+
phase.setPhaseType(populatePhaseType(rs));
830+
phase.setScheduledEndDate(rs.getTimestamp("scheduled_end_time"));
831+
phase.setScheduledStartDate(rs.getTimestamp("scheduled_start_time"));
832+
phase.setModifyDate(rs.getTimestamp("modify_date"));
833+
834+
return phase;
835+
}
836+
628837
/**
629838
* <p>
630839
* Returns all the PhaseTypes from the datastore. The returned array might be empty if no types exists, but it

0 commit comments

Comments
 (0)