package com.chiinc.smart.datamodel.schedules; import java.util.* ; import com.chiinc.smart.datamodel.Campaign ; import com.chiinc.smart.datamodel.cases.* ; import com.chiinc.smart.datamodel.contingencies.* ; import com.chiinc.smart.listeners.* ; import com.chiinc.utils.* ; import com.chiinc.smart.events.* ; import com.chiinc.smart.exceptions.* ; public class ContingencyBasedSchedule implements CaseBasedSchedule, ContingencyListener, CampaignListener { private Vector m_scheduleListeners = new Vector () ; private Vector m_selectionListeners = new Vector () ; private Vector m_masterContingencies = new Vector (); private Vector m_allContingencies = new Vector (); private Vector m_cases = new Vector () ; private Vector m_possibleCaseStartDates = new Vector () ; static private int m_nextAvailableContingencyID_s = 1; static private int m_nextAvailableCaseID_s = 1; private Case m_selectedCase = null ; private Campaign m_campaign ; public ContingencyBasedSchedule (Campaign campaign) { m_campaign = campaign ; } static public void SetNextAvailableContingencyID_s (int nextAvailableContingencyID) { m_nextAvailableContingencyID_s = nextAvailableContingencyID ; } //TO DO: look into ID proliferation for both cases and contingencies static public String GetNextAvailableContingencyID_s () { return String.valueOf (m_nextAvailableContingencyID_s) ; } static public String GetNewContingencyID_s () { return String.valueOf (m_nextAvailableContingencyID_s++) ; } static public void SetNextAvailableCaseID_s (int nextAvailableCaseID) { m_nextAvailableCaseID_s = nextAvailableCaseID ; } static public String GetNextAvailableCaseID_s () { return String.valueOf (m_nextAvailableCaseID_s) ; } static public String GetNewCaseID_s () { return String.valueOf (m_nextAvailableCaseID_s++) ; } /** * Used only to load from XML, does not resolve case overlap */ public void LoadSavedCases (Vector savedCases) { m_cases.addAll (savedCases) ; } /** * Used only to load from XML, does not resolve contingency overlap, does not recalculate cases */ public void LoadSavedMasterContingencies (Vector savedMasterContingencies) { m_masterContingencies.addAll (savedMasterContingencies) ; Iterator masterContingencyIterator = this.GetMasterContingencyIterator () ; while (masterContingencyIterator.hasNext ()) { MasterContingency masterContingency = (MasterContingency )masterContingencyIterator.next () ; Iterator branchIterator = masterContingency.GetBranchIterator () ; while (branchIterator.hasNext ()) { Contingency contingency = (Contingency )branchIterator.next () ; contingency.AddListener (this) ; m_allContingencies.add (contingency) ; } Iterator sequelIterator = masterContingency.GetSequelIterator () ; while (sequelIterator.hasNext ()) { Contingency contingency = (Contingency )sequelIterator.next () ; contingency.AddListener (this) ; m_allContingencies.add (contingency) ; } masterContingency.AddListener (this) ; m_allContingencies.add (masterContingency) ; } } private Contingency GetContingency (String id) { ListIterator contingencyIterator = this.GetAllContingencies ().listIterator () ; Contingency contingency = null ; while (contingencyIterator.hasNext ()) { Contingency candidateContingency = (Contingency )contingencyIterator.next () ; if (candidateContingency.GetID ().equals (id)) { contingency = candidateContingency ; break ; } } return contingency ; } private boolean HaveCaseForDateRange (DateRange dateRange) { boolean haveCaseForDateRange = false ; ListIterator caseIterator = m_cases.listIterator () ; while (caseIterator.hasNext ()) { CaseImpl storedCase = (CaseImpl )caseIterator.next () ; if (storedCase.GetDateRange().equals (dateRange)) { haveCaseForDateRange = true ; break ; } } return haveCaseForDateRange ; } private Contingency GetEarliestContingency () throws CaseSizeException, CaseIntersectionException { ListIterator contingencyIterator = this.GetMasterContingencyIterator () ; Contingency earliestContingency = null ; Date earliestStartDate = this.GetLatestEventDate () ; while (contingencyIterator.hasNext ()) { Contingency contingency = (Contingency )contingencyIterator.next () ; Date candidateEarliestStartDate = contingency.GetStartTime () ; if (candidateEarliestStartDate.before (earliestStartDate)) { earliestStartDate = candidateEarliestStartDate ; earliestContingency = contingency ; } } return earliestContingency ; } private Case GetEarliestCase () { ListIterator caseIterator = this.GetCaseIterator () ; Case earliestCase = null ; Date earliestStartDate = DateUtils.m_LATEST_DATE_s ; while (caseIterator.hasNext ()) { Case caseInstance = (Case )caseIterator.next () ; Date caseInstanceStartDate = caseInstance.GetStartDate () ; if (caseInstanceStartDate.before (earliestStartDate)) { earliestStartDate = caseInstanceStartDate ; earliestCase = caseInstance ; } } return earliestCase ; } private Case GetLatestCase () { ListIterator caseIterator = this.GetCaseIterator () ; Case latestCase = null ; Date latestEndDate = this.GetEarliestEventDate () ; while (caseIterator.hasNext ()) { Case caseInstance = (Case )caseIterator.next () ; Date caseInstanceEndDate = caseInstance.GetEndDate () ; if (caseInstanceEndDate.after (latestEndDate)) { latestEndDate = caseInstanceEndDate ; latestCase = caseInstance ; } } return latestCase ; } private Vector GetOrderedCasesIntersectedByDateRange (DateRange dateRange) {//to do: figure out why there is some case overlap when there shouldn't be (may be related to offset points) ListIterator caseIterator = m_cases.listIterator () ; Vector casesIntersectedByDateRange = new Vector () ; while (caseIterator.hasNext ()) { Case caseInstance = (Case )caseIterator.next () ; if (caseInstance.GetDateRange ().Intersects (dateRange)) {//this storedDateRange has some overlap with the dateRange casesIntersectedByDateRange.add (caseInstance) ; } } Collections.sort (casesIntersectedByDateRange) ; return casesIntersectedByDateRange ; } /** * This method is responsible for generating new cases and resolving case overlapping as new contingencies are added. * This method assumes that the contingency's drawing dateRange has been determined and that it is larger than the minimum case size. */ private void AddCaseForContingency (Contingency contingency) throws CaseSizeException, CaseIntersectionException { if (!contingency.IsInfoOnly ()) { DateRange contingencyDateRange = new DateRange (contingency.GetStartDateForDrawing (), contingency.GetEndDateForDrawing ()) ; if (!this.HaveCaseForDateRange (contingencyDateRange)) { Vector orderedIntersectingCases = this.GetOrderedCasesIntersectedByDateRange (contingencyDateRange) ; if (orderedIntersectingCases.isEmpty ()) {// just add the contingency case before the earliest case or after the latest Case caseInstance = this.AddNonIntersectingCase (contingencyDateRange) ; caseInstance.AddContingency (contingency) ; } else {//this daterange intersects at least some existing cases ListIterator caseIterator = orderedIntersectingCases.listIterator () ; boolean contingencyStartHandled = false ; boolean contingencyEndHandled = false ; Case firstContingencyDefinedCase = null ; Case secondContingencyDefinedCase = null ; Case previousCase = null ; while (caseIterator.hasNext ()) { boolean existingPlansValid = false ; boolean existingCaseContainsContingencyStart = false ; Case existingCase = (Case )caseIterator.next () ; if (existingCase.GetDateRange ().Contains (contingencyDateRange)) {//if the entire contingency is contained by this existing case (two cases must always be created, this block completely handles all case creation for this scenario) // create a firstContingencyDefinedCase which is a clone of the existing case firstContingencyDefinedCase = (Case )existingCase.clone () ; firstContingencyDefinedCase.SetStartDate (contingencyDateRange.GetStartDate ()) ; //set the start date to the startdate of the contingency firstContingencyDefinedCase.SetEndDate (contingencyDateRange.GetEndDate ()) ; //set the end date to the end date of the contingency firstContingencyDefinedCase.InvalidatePlans () ; //Invalidate the plans if (contingencyDateRange.GetEndDate ().after (existingCase.GetEndDate ())) {// create a new case for the secondContingencyDefinedCase which goes from the endTime of the contingency + 1 minute to the end time of the existing case secondContingencyDefinedCase = CaseFactory.GetCaseFactory ().CreateCase (new DateRange (new Date (contingencyDateRange.GetEndDate ().getTime () + DateUtils.m_NUMBER_MS_PER_MINUTE_s), existingCase.GetEndDate ())) ; } //set the end date of this case to the start date of the contingency -1 minute existingCase.SetEndDate (new Date (contingencyDateRange.GetStartDate ().getTime () - DateUtils.m_NUMBER_MS_PER_MINUTE_s)) ; existingPlansValid = true ; } else { if ((!contingencyStartHandled) && (previousCase == null) && (contingencyDateRange.GetStartDate ().before (existingCase.GetStartDate ()))) {//if start occurs before this case and start hasn't been handled yet if (existingCase.HasContingencies ()) {//if the existing case has contingencies //TO DO: possibly check to verify that new case is at least MinCaseSize away from it //create a new case which spans from contingency start time to this cases startTime - 1 minute firstContingencyDefinedCase = CaseFactory.GetCaseFactory ().CreateCase (new DateRange (contingencyDateRange.GetStartDate (), new Date (existingCase.GetStartDate ().getTime () - DateUtils.m_NUMBER_MS_PER_MINUTE_s))) ; firstContingencyDefinedCase.PotentiallyInvalidatePlans () ; //potentially invalidate this cases plans //firstContingencyDefinedCase is complete } else {//if it does not, modify the campaign dates accordingly m_campaign.SetListenersEnabled (false) ; m_campaign.SetStartDate (contingencyDateRange.GetStartDate ()) ; //and push start back to this contingency start existingCase.SetStartDate (contingencyDateRange.GetStartDate ()) ; m_campaign.SetListenersEnabled (true) ; } contingencyStartHandled = true ; } else if (existingCase.GetDateRange ().Contains (contingencyDateRange.GetStartDate ())) {//if start is contained in this case // create a cloned case going from the contingency startTime to the existing cases end time firstContingencyDefinedCase = (Case )existingCase.clone () ; //to do: check the size of the newly created case before creating it to eliminate case ID proliferation firstContingencyDefinedCase.SetStartDate (contingencyDateRange.GetStartDate ()) ; firstContingencyDefinedCase.InvalidatePlans () ; //invalidate the cloned cases plans and add it // set the existing case's end time to start time of contingency - 1 minute (if they're not too close to each other) existingCase.SetEndDate (new Date (contingencyDateRange.GetStartDate ().getTime () - DateUtils.m_NUMBER_MS_PER_MINUTE_s)) ; contingencyStartHandled = true ; existingCaseContainsContingencyStart = true ; existingPlansValid = true ; } if ((!contingencyEndHandled) && (!caseIterator.hasNext ()) && (contingencyDateRange.GetEndDate ().after (existingCase.GetEndDate ()))) {//if end occurs after this case and end hasn't been handled yet if (existingCase.HasContingencies ()) {//if the existing case has contingencies //create a new case which spans from this cases end time + 1 minute to the contingency end time secondContingencyDefinedCase = CaseFactory.GetCaseFactory ().CreateCase (new DateRange (new Date (existingCase.GetEndDate ().getTime () + DateUtils.m_NUMBER_MS_PER_MINUTE_s), contingencyDateRange.GetEndDate ())) ; secondContingencyDefinedCase.PotentiallyInvalidatePlans () ; //potentially invalidate this cases plans //TO DO: possibly check to verify that new case is at least MinCaseSize away from it } else {//if it does not, modify the campaign dates accordingly m_campaign.SetListenersEnabled (false) ; m_campaign.SetEndDate (contingencyDateRange.GetEndDate ()) ; if (existingCaseContainsContingencyStart) {//if this case also contains the start of the contingency, clean up the newly defined case firstContingencyDefinedCase.SetEndDate (contingencyDateRange.GetEndDate ()) ; } else {//push end back to this contingency end existingCase.SetEndDate (contingencyDateRange.GetEndDate ()) ; } m_campaign.SetListenersEnabled (true) ; } contingencyEndHandled = true ; } else if (existingCase.GetDateRange ().Contains (contingencyDateRange.GetEndDate ())) {//if end is contained in this case // create a cloned case going from this case's startTime to the contingencies endTime secondContingencyDefinedCase = (Case )existingCase.clone () ; secondContingencyDefinedCase.SetEndDate (contingencyDateRange.GetEndDate ()) ; secondContingencyDefinedCase.InvalidatePlans () ; //invalidate the cloned cases plans and add it // set this case's start time to end time of contingency + 1 minute (if they're not too close to each other) existingCase.SetStartDate (new Date (contingencyDateRange.GetEndDate ().getTime () + DateUtils.m_NUMBER_MS_PER_MINUTE_s)) ; contingencyEndHandled = true ; existingPlansValid = true ; } } if (previousCase != null) { if (DateUtils.DifferenceInMinute_s (previousCase.GetEndDate (), existingCase.GetStartDate ()) > 1) {//if there is a gap of more than a minute between this case and the previousCase, touch it up existingCase.SetStartDate (new Date (previousCase.GetEndDate ().getTime () + DateUtils.m_NUMBER_MS_PER_MINUTE_s)) ; } } if (contingencyDateRange.Contains (existingCase.GetDateRange ())) {//if the contingency spans this entire case, add the contingency to the case existingCase.AddContingency (contingency) ; } if (!existingPlansValid) {//If the existing plans are not valid, potentially invalidate them existingCase.PotentiallyInvalidatePlans () ; } previousCase = existingCase ; } if (firstContingencyDefinedCase != null) { if (contingencyDateRange.Contains (firstContingencyDefinedCase.GetDateRange ())) { firstContingencyDefinedCase.AddContingency (contingency) ; } this.AddCase (firstContingencyDefinedCase) ; } if (secondContingencyDefinedCase != null) { if (contingencyDateRange.Contains (secondContingencyDefinedCase.GetDateRange ())) { secondContingencyDefinedCase.AddContingency (contingency) ; } this.AddCase (secondContingencyDefinedCase) ; } } } else { //no need to recalculate cases since it overlaps an existing case exactly //just need to make sure the contingency is added to each case it intersects this.AddContingencyToIntersectingCases (contingency) ; } } } /** * this method adds cases that do not intersect existing cases (typically used for cases at the beginning or end of the campaigns date range) * @return the case to which this dateRange corresponds. */ private Case AddNonIntersectingCase (DateRange dateRange) throws CaseSizeException, CaseIntersectionException { Case caseInstanceToAdd = null ; if (!this.HaveCaseForDateRange (dateRange)) { Vector orderedIntersectingCases = this.GetOrderedCasesIntersectedByDateRange (dateRange) ; if (orderedIntersectingCases.isEmpty ()) { Case earliestCase = this.GetEarliestCase () ; Case latestCase = this.GetLatestCase () ; Case bridgingCaseInstanceToAdd = null ; DateRange bridgingDateRange = null ; if (earliestCase != null) { if (dateRange.GetEndDate ().before (earliestCase.GetStartDate ())) {//case occurs before the earliest start date bridgingDateRange = new DateRange (dateRange.GetEndDate (), earliestCase.GetStartDate ()) ; if (!CaseFactory.GetCaseFactory ().LargerThanAllowableCaseSize (bridgingDateRange)) { dateRange.SetEndDate (earliestCase.GetStartDate ()) ; } else { bridgingCaseInstanceToAdd = CaseFactory.GetCaseFactory ().CreateCase (bridgingDateRange) ; } if (!CaseFactory.GetCaseFactory ().LargerThanAllowableCaseSize (dateRange)) { earliestCase.SetStartDate (dateRange.GetStartDate ()) ; } m_campaign.SetListenersEnabled (false) ; m_campaign.SetStartDate (dateRange.GetStartDate ()) ; m_campaign.SetListenersEnabled (true) ; } else if (dateRange.GetStartDate ().after (latestCase.GetEndDate ())) {//case occurs after the latest end date bridgingDateRange = new DateRange (latestCase.GetEndDate (), dateRange.GetStartDate ()) ; if (!CaseFactory.GetCaseFactory ().LargerThanAllowableCaseSize (bridgingDateRange)) { dateRange.SetStartDate (latestCase.GetEndDate ()) ; } else { bridgingCaseInstanceToAdd = CaseFactory.GetCaseFactory ().CreateCase (bridgingDateRange) ; } if (!CaseFactory.GetCaseFactory ().LargerThanAllowableCaseSize (dateRange)) { latestCase.SetEndDate (dateRange.GetEndDate ()) ; } m_campaign.SetListenersEnabled (false) ; m_campaign.SetEndDate (dateRange.GetEndDate ()) ; m_campaign.SetListenersEnabled (true) ; } } if (CaseFactory.GetCaseFactory ().LargerThanAllowableCaseSize (dateRange)) { caseInstanceToAdd = CaseFactory.GetCaseFactory ().CreateCase (dateRange) ; } this.AddCase (caseInstanceToAdd) ; this.AddCase (bridgingCaseInstanceToAdd) ; } else { throw new CaseIntersectionException (this.getClass () + ".AddNonIntersectingCase(), ERROR: cases intersect") ; } } return caseInstanceToAdd ; } /** * adds the contingency to the list, updates case information and notifies listeners */ public void AddContingency (Contingency contingency) throws CaseSizeException, CaseIntersectionException { this.SetContingencyDrawDates (contingency) ; this.AddCaseForContingency (contingency) ; if ((contingency instanceof MasterContingency)) { m_masterContingencies.add (contingency) ; } m_allContingencies.add (contingency) ; contingency.AddListener (this) ; contingency.EnableListeners (true) ; this.Update () ; } private void AddCase (Case caseInstance, ListIterator caseIterator) {//this is necessary for concurrent modification of the list if (caseInstance != null) { DateRange dateRange = caseInstance.GetDateRange () ; if (!this.HaveCaseForDateRange (dateRange)) { if (dateRange.GetStartDate ().before (dateRange.GetEndDate ())) { if (!dateRange.GetStartDate ().equals (dateRange.GetEndDate ())) { System.out.println (this.getClass () + ".AddCase(), Adding case for DateRange: " + dateRange) ; caseIterator.add (caseInstance) ; } else { System.err.println (this.getClass () + ".AddCase(), ERROR: startDate equals endDate... Case not added") ; } } else { System.err.println (this.getClass () + ".AddCase(), ERROR: startDate occurs after endDate... Case not added") ; } } } } public void DeleteContingency (Contingency contingency) throws CaseSizeException, CaseIntersectionException { if (contingency instanceof BranchContingency) {//remove from Master BranchContingency branchContingency = (BranchContingency )contingency ; MasterContingency master = branchContingency.GetMasterContingency () ; master.DeleteBranch (branchContingency) ; } else if (contingency instanceof SequelContingency) {//remove from Master SequelContingency sequelContingency = (SequelContingency )contingency ; MasterContingency master = sequelContingency.GetMasterContingency () ; master.DeleteSequel (sequelContingency) ; } //remove contingency from all caseInstances Iterator caseIterator = this.GetOrderedCasesIntersectedByDateRange (new DateRange (contingency.GetStartTime (), contingency.GetEndTime ())).listIterator () ; while (caseIterator.hasNext ()) { Case caseInstance = (Case )caseIterator.next () ; caseInstance.RemoveContingency (contingency) ; } //remove contingency m_allContingencies.remove (contingency) ; this.Update () ; } private void RemoveCase (Case caseInstance) { m_cases.remove (caseInstance) ; this.Update () ; } public Vector GetMasterContingencies () { return m_masterContingencies ; } public ListIterator GetMasterContingencyIterator () { return m_masterContingencies.listIterator () ; } public Vector GetAllContingencies () { return m_allContingencies ; } private void AddCase (Case caseInstance) { this.AddCase (caseInstance, m_cases.listIterator ()) ; } //implements CaseBasedSchedule public ListIterator GetOrderedCaseIterator () { Collections.sort (m_cases) ; return m_cases.listIterator () ; } public ListIterator GetCaseIterator () { return m_cases.listIterator () ; } public int GetNumberCases () { return m_cases.size () ; } public void AddScheduleListener (CaseBasedScheduleListener caseBasedScheduleListener) { m_scheduleListeners.add (caseBasedScheduleListener) ; } public void NotifyScheduleListeners (ScheduleEvent scheduleEvent) { ListIterator listenerIterator = m_scheduleListeners.listIterator () ; while (listenerIterator.hasNext ()) { CaseBasedScheduleListener scheduleListener = (CaseBasedScheduleListener )listenerIterator.next () ; scheduleListener.ScheduleChanged (scheduleEvent) ; } } public void AddSelectionListener (CaseBasedScheduleSelectionListener caseBasedScheduleSelectionListener) { m_selectionListeners.add (caseBasedScheduleSelectionListener) ; } public void NotifySelectionListeners (CaseSelectionEvent caseSelectionEvent) { ListIterator listenerIterator = m_selectionListeners.listIterator () ; while (listenerIterator.hasNext ()) { CaseBasedScheduleSelectionListener selectionListener = (CaseBasedScheduleSelectionListener )listenerIterator.next () ; selectionListener.SelectionChanged (caseSelectionEvent) ; } } public Case GetSelectedCase () { return m_selectedCase ; } public void SetSelected (Case selectedCase) { if ((m_selectedCase == null) || (!m_selectedCase.equals (selectedCase))) { Case previouslySelectedCase = m_selectedCase ; m_selectedCase = selectedCase ; this.NotifySelectionListeners (new CaseSelectionEvent (this, previouslySelectedCase, m_selectedCase)) ; } } public Case GetCasePreceding (Case caseInstance) { Case previousCase = null ; if (m_cases.contains (caseInstance)) { ListIterator orderedCaseIterator = this.GetOrderedCaseIterator () ; while (orderedCaseIterator.hasNext ()) { Case candidateCase = (Case )orderedCaseIterator.next () ; if (candidateCase.equals (caseInstance)) { break ; } previousCase = candidateCase ; } } return previousCase ; } //end implements CaseBasedSchedule //implements ContingencyListener public void ContingencyChanged (ContingencyChangeEvent contingencyChangeEvent) throws CaseSizeException, CaseIntersectionException { Contingency contingency = contingencyChangeEvent.GetContingency () ; boolean shouldUpdate = false ; if (contingencyChangeEvent.GetEventType () == ContingencyChangeEvent.m_DATE_CHANGE_s) { this.SetContingencyDrawDates (contingency) ; this.AddCaseForContingency (contingency) ; shouldUpdate = true ; } else if (contingencyChangeEvent.GetEventType () == ContingencyChangeEvent.m_BRANCH_ADDED_s) { MasterContingency masterContingency = (MasterContingency )contingency ; Iterator branchIterator = masterContingency.GetBranchIterator () ; while (branchIterator.hasNext ()) { BranchContingency branchContingency = (BranchContingency )branchIterator.next () ; if (!m_allContingencies.contains (branchContingency)) { this.SetContingencyDrawDates (branchContingency) ; m_allContingencies.add (branchContingency) ; //no need to recalculate cases since it should have already been done for the master //just need to make sure the branch is added to each case it intersects this.AddContingencyToIntersectingCases (branchContingency) ; branchContingency.AddListener (this) ; } } shouldUpdate = true ; } else if (contingencyChangeEvent.GetEventType () == ContingencyChangeEvent.m_SEQUEL_ADDED_s) { MasterContingency masterContingency = (MasterContingency )contingency; Iterator sequelIterator = masterContingency.GetSequelIterator () ; while (sequelIterator.hasNext ()) { SequelContingency sequelContingency = (SequelContingency )sequelIterator.next () ; //to do: factor sequels into case calculation algorithm this.SetContingencyDrawDates (sequelContingency) ; this.AddCaseForContingency (sequelContingency) ; m_allContingencies.add (sequelContingency) ; sequelContingency.AddListener (this) ; } shouldUpdate = true ; } if (shouldUpdate) { this.Update () ; } } //end implements ContingencyListener //implements CampaignListener public void CampaignChanged (CampaignChangeEvent campaignChangeEvent) throws CaseSizeException, CaseIntersectionException { int eventType = campaignChangeEvent.GetEventType () ; if ((eventType == CampaignChangeEvent.m_DATE_CHANGE_s) || (eventType == CampaignChangeEvent.m_CASE_SIZE_CHANGE_s)) { this.RegenerateCasesFromContingencies () ; } else if (eventType == CampaignChangeEvent.m_LOADED_s) { this.Initialize () ; } } //end implements CampaignListener /** * Used to Initialize the case space. Typically invoked after a new campaign is created or an existing campaign has been loaded from XML */ private void Initialize () throws CaseSizeException, CaseIntersectionException { this.CreateInitialCampaignCase () ; this.PopulatePossibleCaseStartPoints (m_campaign.GetDateRange ()) ; this.InitializeContingencies () ; this.SetAllContingencyDrawDates () ; this.SetSelected (this.GetEarliestCase ()) ; this.Update () ; } /** * Used to Initialize the contingencies. Typically invoked after a new campaign is created or an existing campaign has been loaded from XML */ private void InitializeContingencies () throws CaseSizeException, CaseIntersectionException { Iterator contingencyIterator = this.GetAllContingencies ().listIterator () ; while (contingencyIterator.hasNext ()) { Contingency contingency = (Contingency )contingencyIterator.next () ; contingency.EnableListeners (false) ; contingency.Initialize () ; this.AddContingencyToIntersectingCases (contingency) ; contingency.EnableListeners (true) ; } } /** * Used to add a contingency to all cases which contain it. * Typically invoked after an existing campaign has been loaded from XML. * NOTE: this method does not trigger case recalculation, and should never be used when case recalculation is necessary. */ private void AddContingencyToIntersectingCases (Contingency contingency) { Iterator caseIterator = this.GetOrderedCasesIntersectedByDateRange (new DateRange (contingency.GetStartTime (), contingency.GetEndTime ())).listIterator () ; while (caseIterator.hasNext ()) { Case caseInstance = (Case )caseIterator.next () ; caseInstance.AddContingency (contingency) ; } } /** * Used to create the initial Case based on the Campaign start and end dates (i.e. when no other cases have been created) */ private void CreateInitialCampaignCase () throws CaseSizeException, CaseIntersectionException { if (m_cases.isEmpty ()) { DateRange initialDateRange = new DateRange (m_campaign.GetStartDate (), m_campaign.GetEndDate ()) ; this.AddNonIntersectingCase (initialDateRange) ; } } /** * Used to create the set of possible Case starting points for a campaign DateRange based on the minimum case size */ private void PopulatePossibleCaseStartPoints (DateRange campaignDateRange) { m_possibleCaseStartDates.removeAllElements () ; long minimumCaseSizeInMS = m_campaign.GetMinimumCaseSizeInMS () ; Date campaignEndDate = new Date (campaignDateRange.GetEndDate ().getTime () + m_campaign.GetMinimumCaseSizeInMS ()) ; Date lastCaseStartDate = campaignDateRange.GetStartDate () ; while (lastCaseStartDate.before (campaignEndDate)) { m_possibleCaseStartDates.add (lastCaseStartDate) ; lastCaseStartDate = new Date (lastCaseStartDate.getTime () + minimumCaseSizeInMS) ; } } /** * Used to set the dates used for contingency drawing based on the possible Case Start Dates */ private void SetAllContingencyDrawDates () throws CaseSizeException, CaseIntersectionException { Iterator contingencyIterator = this.GetAllContingencies ().listIterator () ; while (contingencyIterator.hasNext ()) { Contingency contingency = (Contingency )contingencyIterator.next () ; this.SetContingencyDrawDates (contingency) ; } } /** * Used to set the dates used for contingency drawing based on the possible Case Start Dates */ private void SetContingencyDrawDates (Contingency contingency) throws CaseSizeException, CaseIntersectionException { Date startDrawDate = this.GetClosestPossibleCaseBoundaryDate (contingency.GetStartTime ()) ; contingency.SetStartDateForDrawing (startDrawDate) ; Date endDrawDate = this.GetClosestPossibleCaseBoundaryDate (contingency.GetEndTime ()) ; contingency.SetEndDateForDrawing (endDrawDate) ; } /** * Used to get the closest possible Case Boundary date for a given Date */ private Date GetClosestPossibleCaseBoundaryDate (Date date) { if (date.before (this.GetEarliestEventDate ())) {//if date is before campaign StartDate //regenerate possible case start points from this date this.PopulatePossibleCaseStartPoints (new DateRange (date, this.GetLatestEventDate ())) ; //need to force a redraw of all cases this.RegenerateCasesFromContingencies () ; } else if (date.after (this.GetLatestEventDate ())) {//if date is after campaign EndDate //regenerate possible case start points to accomodate this date this.PopulatePossibleCaseStartPoints (new DateRange (this.GetEarliestEventDate (), date)) ; } return DateUtils.GetClosestDate_s (m_possibleCaseStartDates, date) ; } /** * Used to re-partition the case space from the existing contingencies. */ private void RegenerateCasesFromContingencies () { System.out.println (this.getClass () + ".RegenerateCasesFromContingencies(), WARNING - not yet implemented.") ; //TO DO: figure out how to match case content with redrawn cases /* m_cases.removeAllElements () ; this.CreateInitialCampaignCase () ; this.PopulatePossibleCaseStartPoints (m_campaign.GetDateRange ()) ; this.SetAllContingencyDrawDates () ; this.SetSelected (this.GetEarliestCase ()) ; this.Update () ; */ } private Date GetEarliestEventDate () { return m_campaign.GetStartDate () ; } private Date GetLatestEventDate () { return m_campaign.GetEndDate () ; } private void Update () { this.NotifyScheduleListeners (new ScheduleEvent (this, ScheduleEvent.m_UPDATE_s)) ; } }