Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method GenerateOccurrences ( 
 | 
  Date dateOfFirstRecurrence_i, 
 | 
  Date endDate_i, 
 | 
  Date startOverlap_i, 
 | 
  Date endOverlap_i, 
 | 
  Boolean preserveOccurrences_i 
 | 
) 
 | 
{ 
 | 
  Description: 'Generate TimeIntervals for the occurrences of an Event, given the RecurrencePattern of the Event and the RecurrencePeriod of the Participation.' 
 | 
  TextBody: 
 | 
  [* 
 | 
    calendar := this.Calendar(); 
 | 
    pattern  := this.RecurrencePattern(); 
 | 
    timezone := this.Calendar().GetTimeZone(); 
 | 
     
 | 
    // For debugging 
 | 
    //showInfo := this.Event().Subject() = "TEST"; 
 | 
    //showInfo := true; 
 | 
    //mask     := "dd D-M-Y H:m"; 
 | 
    //convOps  := ConversionOptions::ISO(); 
 | 
     
 | 
    // Get the date of the first occurrence to be generated. 
 | 
    dateOfRecurrence := dateOfFirstRecurrence_i; 
 | 
    date             := pattern.GetDateOfNextOccurrence( dateOfRecurrence, dateOfRecurrence ); 
 | 
     
 | 
    // Remember the first existing occurrence for a check later on. 
 | 
    firstOccurrence := minselect( this, ExplicitTimeInterval, eti, true, eti.Start() ); 
 | 
     
 | 
    //if( showInfo ){ info( ">>> Generate from", date, "to", endDate_i, "| preserve =", preserveOccurrences_i ) }; 
 | 
    //if( showInfo ){ info( ">>> startOverlap =", startOverlap_i.Format( mask ), "endOverlap =", endOverlap_i.Format( mask ) ) }; 
 | 
    //if( showInfo ){ info( ">>> startOfWindowMovedForward =", calendar.StartDate() > calendar.PreviousStartDate() ); } 
 | 
    //if( showInfo ){ info( ">>> startOfWindowMovedBackward =", calendar.StartDate() < calendar.PreviousStartDate() ); } 
 | 
     
 | 
    // Generate the TimeIntervals. 
 | 
    while( date <= endDate_i ) 
 | 
    { 
 | 
      // Calculate start and end, taking timezone and DSL into account. 
 | 
      start := LibCal_Util::CalculateStartTime( timezone, date, this.Event().StartTimeOfDay() ); 
 | 
      end   := LibCal_Util::CalculateEndTime(   timezone, date, this.Event().StartTimeOfDay(), this.Event().Duration() ); 
 | 
       
 | 
      //if( showInfo ){ info( ">>>", start.Format( mask, convOps ), "-", end.Format( mask, convOps ), "preserve =", preserveOccurrences_i ); } 
 | 
     
 | 
      // If end is at midnight, one day should be subtracted in order to not take the next day into account. 
 | 
      startDate := start.Date( timezone ); 
 | 
      endDate   := end.Date( timezone ) - ifexpr( end = end.StartOfDay( timezone ), 1, 0 ); 
 | 
       
 | 
      // Ignore TimeIntervals outside of the CalendarWindow. 
 | 
      isInCalendarWindow := end   > calendar.Start() and 
 | 
                            start < calendar.End();   
 | 
      if( isInCalendarWindow ) 
 | 
      { 
 | 
        // See if the TimeInterval already exists. 
 | 
        // NOTE: if the times of an occurrence were changed it is not found here anymore, 
 | 
        //       as a result of which it will be removed...! 
 | 
        // ToDo: see how this can be solved. 
 | 
        timeInterval := select( this, ExplicitTimeInterval, eti, true, 
 | 
                                eti.Start() = start and 
 | 
                                eti.End()   = end ); 
 | 
     
 | 
        // When occurrences must be preserved, TimeIntervals that were already part of the existing window should be ignored; 
 | 
        // they must be used 'as-is' and not be re-generated. This concerns the TimeIntervals that are part of the overlap between the old and the new window. 
 | 
        // Note that a TimeInterval is considered to be part of the overlap when its *StartDate* is part of the overlapping period. 
 | 
        isPartOfOverlap := startDate >= startOverlap_i and 
 | 
                           startDate <= endOverlap_i; 
 | 
                            
 | 
        //if( showInfo ){ info( ">>> isPartOfOverlap =", isPartOfOverlap ); } 
 | 
     
 | 
        if( not preserveOccurrences_i or 
 | 
            ( calendar.Window() > 0 and 
 | 
              not isPartOfOverlap ) ) 
 | 
        { 
 | 
          //if( showInfo ){ info( "startDate < startOverlap_i : ", startDate.Format( mask ), "<", startOverlap_i.Format( mask ), "-->", startDate < startOverlap_i ); } 
 | 
          //if( showInfo ){ info( "endDate   > endOverlap_i   : ", endDate.  Format( mask ), ">", endOverlap_i.  Format( mask ), "-->", endDate   > endOverlap_i   ); } 
 | 
           
 | 
          // Reuse the TimeInterval if it already exists, otherwise create a new one. 
 | 
          if( not isnull( timeInterval ) ) 
 | 
          { 
 | 
            timeInterval.IsSoftDeleted( false ); 
 | 
          } 
 | 
          else 
 | 
          { 
 | 
            if( this.DoGenerateOccurrence( start, end, firstOccurrence ) ) 
 | 
            { 
 | 
              leadingETI := this.CreateTimeInterval( start, end, this.Event().Capacity() ); 
 | 
               
 | 
              if( not isnull( leadingETI ) ) 
 | 
              { 
 | 
                // Also generate a new occurrence for the Subscripions. 
 | 
                // Take the CalendarWindow of the subscribing Calendar and, if applicable,  
 | 
                // the specific RecurrencePeriod of the Subscription into account. 
 | 
                traverse( this, Subscription, subscription, 
 | 
                          startDate <= subscription.Calendar().EndDate()   and 
 | 
                          endDate   >= subscription.Calendar().StartDate() and 
 | 
                          ( isnull( subscription.RecurrencePeriod() ) or 
 | 
                            ( startDate <= subscription.RecurrencePeriod().EndDate() and 
 | 
                              endDate   >= subscription.RecurrencePeriod().StartDate() ) ) ) 
 | 
                { 
 | 
                  subscribingETI := subscription.CreateTimeInterval( start, end, this.Event().Capacity() ); 
 | 
                   
 | 
                  if( not isnull( subscribingETI ) ) 
 | 
                  { 
 | 
                    // Register the occurrence (i.e. the ExplicitTimeInterval) as SubscribingETI of the LeadingETI. 
 | 
                    subscribingETI.LeadingETI( relset, leadingETI ); 
 | 
                  } 
 | 
                } 
 | 
              } 
 | 
            } 
 | 
          } 
 | 
        } 
 | 
      } 
 | 
     
 | 
      // Get the date of the next occurrence. 
 | 
      // When there are no more occurrences within the current recurrence, dateOfRecurrence is updated to the next recurrence. 
 | 
      date := pattern.GetDateOfNextOccurrence( dateOfRecurrence, date + 1 ); 
 | 
    } 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |