EN · DE · RU · FR · ES

#467: GanttUtils.java

projectforge-business/src/main/java/org/projectforge/business/gantt/GanttUtils.java Тип: Java · Роль: Диаграмма Ганта · Исходник: projectforge-business/src/main/java/org/projectforge/business/gantt/GanttUtils.java 258 строк · 209 кода · 38 комментариев · 11 пустых
Статические служебные методы для Ганта. Набор чистых функций без побочных эффектов, предоставляющих общие вспомогательные операции.

Структура кода

Пакет: org.projectforge.business.gantt

Классы: GanttUtils

Методы (7): compare, getCalculatedStartDate, getCalculatedStartDate, getPredecessorRelDate, getCalculatedEndDate, getCalculatedEndDate, calculateDate

Поля (1): GANTT_OBJECT_COMPARATOR

Импорты: 12 пакетов

Исходный код (сокращён)

package org.projectforge.business.gantt;

import org.apache.commons.lang3.StringUtils;
import org.projectforge.common.StringHelper;
import org.projectforge.framework.time.PFDay;
import org.projectforge.framework.time.PFDayUtils;
import org.projectforge.framework.utils.NumberHelper;

import java.io.Serializable;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public class GanttUtils {
  private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GanttUtils.class);

  public static Comparator<GanttTask> GANTT_OBJECT_COMPARATOR = new Comparator<GanttTask>() {
    @Override
    public int compare(final GanttTask o1, final GanttTask o2) {
      if (Objects.equals(o1.getId(), o2.getId())) {
        return 0;
      }
      final LocalDate start1 = o1.getCalculatedStartDate();
      final LocalDate start2 = o2.getCalculatedStartDate();
      if (start1 == null) {
        if (start2 != null) {
          return 1;
        }
      } else if (start2 == null) {
        return -1;
      } else {
        final int result = start1.compareTo(start2);
        if (result != 0) {
          return result;
        }
      }
      final LocalDate end1 = o1.getCalculatedEndDate();
      final LocalDate end2 = o2.getCalculatedEndDate();
      if (end1 == null) {
        if (end2 != null) {
          return 1;
        }
      } else if (end2 == null) {
        return -1;
      } else {
        final int result = end1.compareTo(end2);
        if (result != 0) {
          return result;
        }
      }
      if (!StringUtils.equals(o1.getTitle(), o2.getTitle())) {
        return StringHelper.compareTo(o1.getTitle(), o2.getTitle());
      }
      return StringHelper.compareTo(String.valueOf(o1.getId()), String.valueOf(o2.getId()));
    }
  };

  /**
   * Пожалуйста, обратите внимание: если дата начала находится после даты начала самой ранней задачи среди дочерних,
   * то возвращается дата начала этой дочерней задачи.
   * В противном случае возвращается установленная дата начала или, если она не установлена, вычисленная дата начала.
   *
   * @param node
   */
  public static LocalDate getCalculatedStartDate(final GanttTask node) {
    final LocalDate start = getCalculatedStartDate(node, new HashSet<>(), new HashSet<>());
    return start;
  }

  private static LocalDate getCalculatedStartDate(final GanttTask node, final Set<Serializable> startDateSet, final Set<Serializable> endDateSet) {
    if (node == null) {
      return null;
    }
    if (node.getStartDate() != null) {
      return node.getStartDate();
    }
    if (node.isStartDateCalculated()) {
      return node.getCalculatedStartDate();
    }
    final int durationDays = node.getDuration() != null ? node.getDuration().setScale(0, RoundingMode.HALF_UP).intValue() : 0;
    if (node.getDuration() != null && node.getEndDate() != null) {
      final LocalDate startDate = calculateDate(node.getEndDate(), -durationDays);
      node.setCalculatedStartDate(startDate).setStartDateCalculated(true);
      if (log.isDebugEnabled()) {
        log.debug("вычисленная дата начала=" + startDate + " для: " + node);
      }
      return startDate;
    }
    if (startDateSet.contains(node.getId())) {
      log.error("Обнаружена циклическая ссылка (не удалось вычислить дату начала: " + node);
      return null;
    } else {
      startDateSet.add(node.getId());
    }
    LocalDate startDate = null;
    final GanttTask predecessor = node.getPredecessor();
    if (predecessor != null) {
      startDate = getPredecessorRelDate(node.getRelationType(), predecessor, startDateSet, endDateSet);
      if (startDate != null) {
        if (NumberHelper.isNotZero(node.getPredecessorOffset())) {
          startDate = calculateDate(startDate, node.getPredecessorOffset());
        }
        if (node.getRelationType() == GanttRelationType.START_FINISH || node.getRelationType() == GanttRelationType.FINISH_FINISH) {
          if (durationDays > 0) {
            startDate = calculateDate(startDate, -durationDays);
          }
        }
      }
    }
    if ((predecessor == null || (node.getRelationType() != null && node.getRelationType().isIn(GanttRelationType.FINISH_FINISH,
            GanttRelationType.START_FINISH)))
            && node.getChildren() != null) {
      // Вычисляем дату начала от самого раннего дочернего элемента.
      for (final GanttTask child : node.getChildren()) {
        final LocalDate date = getCalculatedStartDate(child, startDateSet, endDateSet);
        if (startDate == null) {
          startDate = date;
// ... (сокращено, всего 236 строк)

История Git

868d6abb7 2025 -> 2026
63081666f Заголовки исходных файлов: 2024 -> 2025.
b6092df09 Авторские права 2023 -> 2024
ab45d51fa Авторские права 2001-2022 -> 2001-2023.
5f7ef41b8 Авторские права 2021 -> 2022