Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method PrepareGenerateOccurrences ( 
 | 
  output Date dateOfFirstRecurrence_o, 
 | 
  output Date endDate_o, 
 | 
  output Date startOverlap_o, 
 | 
  output Date endOverlap_o, 
 | 
  output Boolean preserveOccurrences_o 
 | 
) as Boolean 
 | 
{ 
 | 
  Description: 'Prepare the data that is required to generate the applicable occurrences of a recurring event.' 
 | 
  TextBody: 
 | 
  [* 
 | 
    this.CalcRecurrencePattern(); 
 | 
     
 | 
    pattern := this.RecurrencePattern(); 
 | 
    period  := this.GetRecurrencePeriod(); 
 | 
     
 | 
    ok := true; 
 | 
     
 | 
    if( not isnull( pattern ) and 
 | 
        not isnull( period ) ) 
 | 
    { 
 | 
      calendar := this.Calendar(); 
 | 
       
 | 
      // Make sure that the relevant attributes have been calculated. 
 | 
      period.CalcEndDate(); 
 | 
      this.Event().CalcEarliestStart(); 
 | 
      this.Event().CalcLatestEnd(); 
 | 
      this.Event().CalcCapacity(); 
 | 
      this.CalcNrOfOccurrences(); 
 | 
       
 | 
      // See if the generation of TimeIntervals was triggered by an update of the calendar window. 
 | 
      // This requires 'special treatment': TimeIntervals should only be added and/or removed at the 
 | 
      // start and/or end of the new window.  
 | 
      windowChanged := [Date]calendar.StartDate() <> calendar.PreviousStartDate() 
 | 
                    or [Date]calendar.EndDate()   <> calendar.PreviousEndDate(); 
 | 
     
 | 
      // Get the overlap between the old window and the new window. 
 | 
      // The TimeIntervals during that period should be preserved (i.e. not changed, left 'as is'). 
 | 
      startOverlap_o := maxvalue( [Date]calendar.StartDate(), calendar.PreviousStartDate() ); 
 | 
      endOverlap_o   := minvalue( [Date]calendar.EndDate(),   calendar.PreviousEndDate()   ); 
 | 
     
 | 
      // The same applies when only the RecurrencePeriod was changed; also in that case TimeIntervals 
 | 
      // should only be added and/or removed at the new start and/or end of the period, but TimeIntervals 
 | 
      // in the overlap of the old period and the new period should be preserved, i.e. should remain the same. 
 | 
      onlyPeriodChanged := not this.IsChanged() 
 | 
                       and not this.Event().IsChanged() 
 | 
                       and this.HasChangedRecurrencePeriod() 
 | 
                       and not isnull( period ); 
 | 
      if( onlyPeriodChanged ) 
 | 
      { 
 | 
        startOverlap_o := maxvalue( period.StartDate(), period.PreviousStartDate() ); 
 | 
        endOverlap_o   := minvalue( period.EndDate(),   period.PreviousEndDate()   ); 
 | 
      } 
 | 
     
 | 
      // See if all occurrences should be (re-)generated, or if during the overlap existing occurrences should be preserved. 
 | 
      preserveOccurrences_o := this.NrOfOccurrences() > 0 and  // Always generate all occurrences if there are non yet, for example after importing a new event. 
 | 
                               ( windowChanged or onlyPeriodChanged ); 
 | 
     
 | 
      /* Use the StartDate of the period, in order to get the correct basis for the RecurrenceInterval. 
 | 
       * The starting point matters if the RecurrenceInterval > 1. We cannot just use the current start of the calendar as starting point, 
 | 
       * because this can result in a wrong starting point for the recurrence. 
 | 
       * The calendar can now for example start on an odd day, while the start should be on an even day according the the StartDate of the period. 
 | 
       */ 
 | 
      dateOfFirstRecurrence_o := pattern.GetDateOfFirstRecurrence( period.StartDate(), this.Event().EarliestStart() ); 
 | 
          
 | 
      /* Stop at the EndDate, or at the latest end of the Event, or at the end of the Calendar. 
 | 
       * EndDate is always used as stop criterium, also when a specific number of occurrences must be generated. 
 | 
       * In that case the EndDate has already been calcutated as the date of the last occurrence. 
 | 
       * Stopping at the latest end of the Event prevents TimeIntervals to be generated until the end of the Calendar 
 | 
       * in case the initiating Event has a limited period but a participating Event is set to have no enddate. 
 | 
       */ 
 | 
      endDate_o := minvalue( period.EndDate(), 
 | 
                             this.Event().LatestEnd(), 
 | 
                             calendar.EndDate() ); 
 | 
                             /* 
 | 
                             ifexpr( calendar.End() <> calendar.End().StartOfDay(),  
 | 
                                     calendar.End().Date(), 
 | 
                                     calendar.End().Date() - 1 ) );  // If the calendar ends at midnight, the day before the EndDate of the Calendar is the last day that should be generated. 
 | 
                             */ 
 | 
    } 
 | 
    else 
 | 
    { 
 | 
      if( isnull( period ) ) 
 | 
      { 
 | 
        LibCal_Util::Info( "LibCal_Participation.GenerateTimeIntervals() : recurrring Event without RecurrencePeriod encountered; " + 
 | 
                           this.Calendar().CalendarID() + "." + this.Event().Subject() ); 
 | 
      } 
 | 
     
 | 
      if( isnull( pattern ) ) 
 | 
      { 
 | 
        LibCal_Util::Info( "LibCal_Participation.GenerateTimeIntervals() : recurring Event without RecurrencePattern encountered; " + 
 | 
                           this.Calendar().CalendarID() + "." + this.Event().Subject() ); 
 | 
      } 
 | 
       
 | 
      ok := false; 
 | 
    } 
 | 
     
 | 
    return ok; 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |