This method writes calendar data to an MSPDI file.

@param project Root node of the MSPDI file
557649
private void writeCalendars(Project project)
   {
      //
      // Create the new MSPDI calendar list
      //
      Project.Calendars calendars = m_factory.createProjectCalendars();
      project.setCalendars(calendars);
      List<Project.Calendars.Calendar> calendar = calendars.getCalendar();

      //
      // Process each calendar in turn
      //
      for (ProjectCalendar cal : m_projectFile.getCalendars())
      {
         calendar.add(writeCalendar(cal));
      }
   }
1048111
public ProjectCalendar addResourceCalendar() throws MPXJException
   {
      if (getResourceCalendar() != null)
      {
         throw new MPXJException(MPXJException.MAXIMUM_RECORDS);
      }

      ProjectCalendar calendar = new ProjectCalendar(getParentFile());
      setResourceCalendar(calendar);
      return calendar;
   }
1286729
private void writeExceptions(Project.Calendars.Calendar calendar, List<Project.Calendars.Calendar.WeekDays.WeekDay> dayList, List<ProjectCalendarException> exceptions)
   {
      // Always write legacy exception data:
      // Powerproject appears not to recognise new format data at all,
      // and legacy data is ignored in preference to new data post MSP 2003
      writeExceptions9(dayList, exceptions);

      if (m_saveVersion.getValue() > SaveVersion.Project2003.getValue())
      {
         writeExceptions12(calendar, exceptions);
      }
   }
783391
public void processProjectProperties(List<Row> rows, Integer projectID)
   {
      if (rows.isEmpty() == false)
      {
         Row row = rows.get(0);
         ProjectProperties properties = m_project.getProjectProperties();
         properties.setCreationDate(row.getDate("create_date"));
         properties.setFinishDate(row.getDate("plan_end_date"));
         properties.setName(row.getString("proj_short_name"));
         properties.setStartDate(row.getDate("plan_start_date")); // data_date?
         properties.setDefaultTaskType(TASK_TYPE_MAP.get(row.getString("def_duration_type")));
         properties.setStatusDate(row.getDate("last_recalc_date"));
         properties.setFiscalYearStartMonth(row.getInteger("fy_start_month_num"));
         properties.setUniqueID(projectID == null ? null : projectID.toString());
         properties.setExportFlag(row.getBoolean("export_flag"));
         // cannot assign actual calendar yet as it has not been read yet
         m_defaultCalendarID = row.getInteger("clndr_id");
      }
   }
1073902
private void readCalendars(Project project) throws MPXJException
   {
      Calendars calendars = project.getCalendars();
      if (calendars != null)
      {
         for (net.sf.mpxj.planner.schema.Calendar cal : calendars.getCalendar())
         {
            readCalendar(cal, null);
         }

         Integer defaultCalendarID = getInteger(project.getCalendar());
         m_defaultCalendar = m_projectFile.getCalendarByUniqueID(defaultCalendarID);
         if (m_defaultCalendar != null)
         {
            m_projectFile.getProjectProperties().setDefaultCalendarName(m_defaultCalendar.getName());
         }
      }
   }
345711
private void writeAssignmentTimephasedData(ResourceAssignment mpx, Project.Assignments.Assignment xml)
   {
      if (m_writeTimphasedData && mpx.getHasTimephasedData())
      {
         List<TimephasedDataType> list = xml.getTimephasedData();
         ProjectCalendar calendar = mpx.getCalendar();
         BigInteger assignmentID = xml.getUID();

         List<TimephasedWork> complete = mpx.getTimephasedActualWork();
         List<TimephasedWork> planned = mpx.getTimephasedWork();

         if (m_splitTimephasedAsDays)
         {
            TimephasedWork lastComplete = null;
            if (complete != null && !complete.isEmpty())
            {
               lastComplete = complete.get(complete.size() - 1);
            }

            TimephasedWork firstPlanned = null;
            if (planned != null && !planned.isEmpty())
            {
               firstPlanned = planned.get(0);
            }

            if (planned != null)
            {
               planned = splitDays(calendar, mpx.getTimephasedWork(), null, lastComplete);
            }

            if (complete != null)
            {
               complete = splitDays(calendar, complete, firstPlanned, null);
            }
         }

         if (planned != null)
         {
            writeAssignmentTimephasedData(assignmentID, list, planned, 1);
         }

         if (complete != null)
         {
            writeAssignmentTimephasedData(assignmentID, list, complete, 2);
         }
      }
   }
568328
private void writeExceptions(List<ProjectCalendar> records) throws IOException
   {
      for (ProjectCalendar record : records)
      {
         if (!record.getCalendarExceptions().isEmpty())
         {
            // Need to move HOLI up here and get 15 exceptions per line as per USACE spec.
            // for now, we'll write one line for each calendar exception, hope there aren't too many
            //
            // changing this would be a serious upgrade, too much coding to do today....
            for (ProjectCalendarException ex : record.getCalendarExceptions())
            {
               writeCalendarException(record, ex);
            }
         }
         m_eventManager.fireCalendarWrittenEvent(record); // left here from MPX template, maybe not needed???
      }
   }
175739
private void addCalendars(MpxjTreeNode parentNode, ProjectFile file)
   {
      for (ProjectCalendar calendar : file.getCalendars())
      {
         addCalendar(parentNode, calendar);
      }
   }
210307
private static void listProjectProperties(ProjectFile file)
   {
      SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm z");
      ProjectProperties properties = file.getProjectProperties();
      Date startDate = properties.getStartDate();
      Date finishDate = properties.getFinishDate();
      String formattedStartDate = startDate == null ? "(none)" : df.format(startDate);
      String formattedFinishDate = finishDate == null ? "(none)" : df.format(finishDate);

      System.out.println("MPP file type: " + properties.getMppFileType());
      System.out.println("Project Properties: StartDate=" + formattedStartDate + " FinishDate=" + formattedFinishDate);
      System.out.println();
   }
264221
private void write() throws IOException
   {
      m_projectFile.validateUniqueIDsForMicrosoftProject();

      writeFileCreationRecord();
      writeProjectHeader(m_projectFile.getProjectProperties());

      if (m_projectFile.getResources().isEmpty() == false)
      {
         m_resourceModel = new ResourceModel(m_projectFile, m_locale);
         m_writer.write(m_resourceModel.toString());
         for (Resource resource : m_projectFile.getResources())
         {
            writeResource(resource);
         }
      }

      if (m_projectFile.getTasks().isEmpty() == false)
      {
         m_taskModel = new TaskModel(m_projectFile, m_locale);
         m_writer.write(m_taskModel.toString());
         writeTasks(m_projectFile.getChildTasks());
      }

      m_writer.flush();
   }
297523
private void processWorkWeekDay(byte[] data, int offset, ProjectCalendarWeek week, Day day)
   {
      //System.out.println(ByteArrayHelper.hexdump(data, offset, 60, false));

      int dayType = MPPUtility.getShort(data, offset + 0);
      if (dayType == 1)
      {
         week.setWorkingDay(day, DayType.DEFAULT);
      }
      else
      {
         ProjectCalendarHours hours = week.addCalendarHours(day);
         int rangeCount = MPPUtility.getShort(data, offset + 2);
         if (rangeCount == 0)
         {
            week.setWorkingDay(day, DayType.NON_WORKING);
         }
         else
         {
            week.setWorkingDay(day, DayType.WORKING);
            Calendar cal = DateHelper.popCalendar();
            for (int index = 0; index < rangeCount; index++)
            {
               Date startTime = DateHelper.getCanonicalTime(MPPUtility.getTime(data, offset + 8 + (index * 2)));
               int durationInSeconds = MPPUtility.getInt(data, offset + 20 + (index * 4)) * 6;
               cal.setTime(startTime);
               cal.add(Calendar.SECOND, durationInSeconds);
               Date finishTime = DateHelper.getCanonicalTime(cal.getTime());
               hours.addRange(new DateRange(startTime, finishTime));
            }
            DateHelper.pushCalendar(cal);
         }
      }
   }
134863
private void readCalendars(Project project, HashMap<BigInteger, ProjectCalendar> map)
   {
      Project.Calendars calendars = project.getCalendars();
      if (calendars != null)
      {
         LinkedList<Pair<ProjectCalendar, BigInteger>> baseCalendars = new LinkedList<Pair<ProjectCalendar, BigInteger>>();
         for (Project.Calendars.Calendar cal : calendars.getCalendar())
         {
            readCalendar(cal, map, baseCalendars);
         }
         updateBaseCalendarNames(baseCalendars, map);
      }

      try
      {
         ProjectProperties properties = m_projectFile.getProjectProperties();
         BigInteger calendarID = new BigInteger(properties.getDefaultCalendarName());
         ProjectCalendar calendar = map.get(calendarID);
         m_projectFile.setDefaultCalendar(calendar);
      }

      catch (Exception ex)
      {
         // Ignore exceptions
      }
   }
1123692
private void processWorkingHours(ProjectCalendar mpxjCalendar, net.sf.mpxj.planner.schema.Calendar plannerCalendar) throws MPXJException
   {
      OverriddenDayTypes types = plannerCalendar.getOverriddenDayTypes();
      if (types != null)
      {
         List<OverriddenDayType> typeList = types.getOverriddenDayType();
         Iterator<OverriddenDayType> iter = typeList.iterator();
         OverriddenDayType odt = null;
         while (iter.hasNext())
         {
            odt = iter.next();
            if (getInt(odt.getId()) != 0)
            {
               odt = null;
               continue;
            }

            break;
         }

         if (odt != null)
         {
            List<Interval> intervalList = odt.getInterval();
            ProjectCalendarHours mondayHours = null;
            ProjectCalendarHours tuesdayHours = null;
            ProjectCalendarHours wednesdayHours = null;
            ProjectCalendarHours thursdayHours = null;
            ProjectCalendarHours fridayHours = null;
            ProjectCalendarHours saturdayHours = null;
            ProjectCalendarHours sundayHours = null;

            if (mpxjCalendar.isWorkingDay(Day.MONDAY))
            {
               mondayHours = mpxjCalendar.addCalendarHours(Day.MONDAY);
            }

            if (mpxjCalendar.isWorkingDay(Day.TUESDAY))
            {
               tuesdayHours = mpxjCalendar.addCalendarHours(Day.TUESDAY);
            }

            if (mpxjCalendar.isWorkingDay(Day.WEDNESDAY))
            {
               wednesdayHours = mpxjCalendar.addCalendarHours(Day.WEDNESDAY);
            }

            if (mpxjCalendar.isWorkingDay(Day.THURSDAY))
            {
               thursdayHours = mpxjCalendar.addCalendarHours(Day.THURSDAY);
            }

            if (mpxjCalendar.isWorkingDay(Day.FRIDAY))
            {
               fridayHours = mpxjCalendar.addCalendarHours(Day.FRIDAY);
            }

            if (mpxjCalendar.isWorkingDay(Day.SATURDAY))
            {
               saturdayHours = mpxjCalendar.addCalendarHours(Day.SATURDAY);
            }

            if (mpxjCalendar.isWorkingDay(Day.SUNDAY))
            {
               sundayHours = mpxjCalendar.addCalendarHours(Day.SUNDAY);
            }

            for (Interval interval : intervalList)
            {
               Date startTime = getTime(interval.getStart());
               Date endTime = getTime(interval.getEnd());

               m_defaultWorkingHours.add(new DateRange(startTime, endTime));

               if (mondayHours != null)
               {
                  mondayHours.addRange(new DateRange(startTime, endTime));
               }

               if (tuesdayHours != null)
               {
                  tuesdayHours.addRange(new DateRange(startTime, endTime));
               }

               if (wednesdayHours != null)
               {
                  wednesdayHours.addRange(new DateRange(startTime, endTime));
               }

               if (thursdayHours != null)
               {
                  thursdayHours.addRange(new DateRange(startTime, endTime));
               }

               if (fridayHours != null)
               {
                  fridayHours.addRange(new DateRange(startTime, endTime));
               }

               if (saturdayHours != null)
               {
                  saturdayHours.addRange(new DateRange(startTime, endTime));
               }

               if (sundayHours != null)
               {
                  sundayHours.addRange(new DateRange(startTime, endTime));
               }
            }
         }
      }
   }
1265083
private void writeCalendarException(ProjectCalendar parentCalendar, ProjectCalendarException record) throws IOException
   {
      m_buffer.setLength(0);
      Calendar stepDay = DateHelper.popCalendar(record.getFromDate()); // Start at From Date, then step through days...
      Calendar lastDay = DateHelper.popCalendar(record.getToDate()); // last day in this exception

      m_buffer.append("HOLI ");
      m_buffer.append(SDEFmethods.lset(parentCalendar.getUniqueID().toString(), 2));

      while (stepDay.compareTo(lastDay) <= 0)
      {
         m_buffer.append(m_formatter.format(stepDay.getTime()).toUpperCase() + " ");
         stepDay.add(Calendar.DAY_OF_MONTH, 1);
      }
      m_writer.println(m_buffer.toString());
      
      DateHelper.pushCalendar(stepDay);
      DateHelper.pushCalendar(lastDay);
   }
1211755
private void setWorkingDays(ProjectCalendar mpxjCalendar, Calendars gpCalendar)
   {
      DayTypes dayTypes = gpCalendar.getDayTypes();
      DefaultWeek defaultWeek = dayTypes.getDefaultWeek();
      if (defaultWeek == null)
      {
         mpxjCalendar.setWorkingDay(Day.SUNDAY, false);
         mpxjCalendar.setWorkingDay(Day.MONDAY, true);
         mpxjCalendar.setWorkingDay(Day.TUESDAY, true);
         mpxjCalendar.setWorkingDay(Day.WEDNESDAY, true);
         mpxjCalendar.setWorkingDay(Day.THURSDAY, true);
         mpxjCalendar.setWorkingDay(Day.FRIDAY, true);
         mpxjCalendar.setWorkingDay(Day.SATURDAY, false);
      }
      else
      {
         mpxjCalendar.setWorkingDay(Day.MONDAY, isWorkingDay(defaultWeek.getMon()));
         mpxjCalendar.setWorkingDay(Day.TUESDAY, isWorkingDay(defaultWeek.getTue()));
         mpxjCalendar.setWorkingDay(Day.WEDNESDAY, isWorkingDay(defaultWeek.getWed()));
         mpxjCalendar.setWorkingDay(Day.THURSDAY, isWorkingDay(defaultWeek.getThu()));
         mpxjCalendar.setWorkingDay(Day.FRIDAY, isWorkingDay(defaultWeek.getFri()));
         mpxjCalendar.setWorkingDay(Day.SATURDAY, isWorkingDay(defaultWeek.getSat()));
         mpxjCalendar.setWorkingDay(Day.SUNDAY, isWorkingDay(defaultWeek.getSun()));
      }

      for (Day day : Day.values())
      {
         if (mpxjCalendar.isWorkingDay(day))
         {
            ProjectCalendarHours hours = mpxjCalendar.addCalendarHours(day);
            hours.addRange(ProjectCalendarWeek.DEFAULT_WORKING_MORNING);
            hours.addRange(ProjectCalendarWeek.DEFAULT_WORKING_AFTERNOON);
         }
      }
   }
314613
private void writeCalendar(ProjectCalendar record) throws IOException
   {
      //
      // Test used to ensure that we don't write the default calendar used for the "Unassigned" resource
      //
      if (record.getParent() == null || record.getResource() != null)
      {
         m_buffer.setLength(0);

         if (record.getParent() == null)
         {
            m_buffer.append(MPXConstants.BASE_CALENDAR_RECORD_NUMBER);
            m_buffer.append(m_delimiter);
            if (record.getName() != null)
            {
               m_buffer.append(record.getName());
            }
         }
         else
         {
            m_buffer.append(MPXConstants.RESOURCE_CALENDAR_RECORD_NUMBER);
            m_buffer.append(m_delimiter);
            m_buffer.append(record.getParent().getName());
         }

         for (DayType day : record.getDays())
         {
            if (day == null)
            {
               day = DayType.DEFAULT;
            }
            m_buffer.append(m_delimiter);
            m_buffer.append(day.getValue());
         }

         m_buffer.append(MPXConstants.EOL);
         m_writer.write(m_buffer.toString());

         ProjectCalendarHours[] hours = record.getHours();
         for (int loop = 0; loop < hours.length; loop++)
         {
            if (hours[loop] != null)
            {
               writeCalendarHours(record, hours[loop]);
            }
         }

         if (!record.getCalendarExceptions().isEmpty())
         {
            //
            // A quirk of MS Project is that these exceptions must be
            // in date order in the file, otherwise they are ignored.
            // The getCalendarExceptions method now guarantees that
            // the exceptions list is sorted when retrieved.
            //
            for (ProjectCalendarException ex : record.getCalendarExceptions())
            {
               writeCalendarException(record, ex);
            }
         }

         m_eventManager.fireCalendarWrittenEvent(record);
      }
   }
664961
private void readCalendar(Calendar calendar)
   {
      ProjectCalendar mpxjCalendar = m_projectFile.addCalendar();
      mpxjCalendar.setName(calendar.getName());
      m_calendarMap.put(calendar.getID(), mpxjCalendar);

      for (WeekDay day : calendar.getWeekDays().getWeekDay())
      {
         readWeekDay(mpxjCalendar, day);
      }

      for (ExceptedDay day : calendar.getExceptedDays().getExceptedDay())
      {
         readExceptionDay(mpxjCalendar, day);
      }
   }