ProjectData#

A full project snapshot: scheduling config, calendars, tasks, links, resources and assignments. It's the input of Project#solve, Engine.schedule and Project#analyze. Create one with new ProjectData() and the fluent withX setters, or decode JSON with Decode.fromJson(json, ProjectData.class).

Declaration#

public class ProjectData extends ValueRecord implements DeepCloneable<ProjectData>

ProjectData is an import format, not stored state. Project#solve deep-copies it, so later changes to the caller's object don't reach the project.

Constructors#

ProjectData()#

public ProjectData()

Creates an empty project: default config and empty lists.

Fields#

Field Type Default Description
config SchedulingConfig new SchedulingConfig() Project-wide scheduling settings.
calendars Vec<CalendarData> empty Working calendars. Empty means only the built-in "global" calendar: Mon-Fri, 08:00-12:00 and 13:00-17:00.
tasks Vec<TaskData> empty Tasks, summaries and milestones.
links Vec<LinkData> empty Dependencies between tasks.
resources Vec<ResourceData> empty Resources that assignments book.
assignments Vec<AssignmentData> empty Resource assignments to tasks.

Every list field holds an empty Vec by default. Pass an empty list for "none", not null.

Methods#

withConfig#

public ProjectData withConfig(SchedulingConfig value)

Sets config and returns this instance.

Returns - this ProjectData.

public ProjectData withCalendars(Vec<CalendarData> value)
public ProjectData withCalendars(java.util.Collection<? extends CalendarData> value)
public ProjectData withTasks(Vec<TaskData> value)
public ProjectData withTasks(java.util.Collection<? extends TaskData> value)
public ProjectData withLinks(Vec<LinkData> value)
public ProjectData withLinks(java.util.Collection<? extends LinkData> value)
public ProjectData withResources(Vec<ResourceData> value)
public ProjectData withResources(java.util.Collection<? extends ResourceData> value)
public ProjectData withAssignments(Vec<AssignmentData> value)
public ProjectData withAssignments(java.util.Collection<? extends AssignmentData> value)

Each setter assigns its list and returns this instance. The Vec overload stores the given list itself. The Collection overload copies the elements into a new Vec, so List.of(...) works.

Returns - this ProjectData.

canonicalizeRoots#

public void canonicalizeRoots()

Sets parent to null on every task whose parent equals config.rootId (default Id.num(0.0)). Project#solve calls it on the data it ingests, so callers rarely need it.

deepClone#

public ProjectData deepClone()

Returns a copy that shares no list or nested record with this instance.

Returns - a new ProjectData with the same values.

copy#

public ProjectData copy()

Returns a shallow copy. The copy shares config and every list with this instance.

Returns - a new ProjectData with the same field values.

equals, hashCode, toString#

public boolean equals(Object other)
public int hashCode()
public String toString()

Inherited from ValueRecord. Two ProjectData are equal when all six fields are equal, lists and nested records compared by value. toString() lists the fields.

Validation#

The calls that take a ProjectData validate it before scheduling. With strict validation (the default), invalid data throws an InputException whose path names the wire field, for example tasks[3].constraint_date. Strict validation rejects:

  • duplicate task, link or calendar ids
  • a hierarchy cycle in task parent values
  • a summary with a start and a duration (it takes both dates or neither), or a summary with no dates and no dated children
  • a leaf task with fewer than two of start, end and duration, or with all three mutually inconsistent
  • a dated constraint without constraintDate
  • a task priority outside 0..1000
  • a non-finite link lag
  • a calendar with no working time, or worktime.days without exactly 7 entries
  • config.maxIterations = 0, or a negative or non-finite config.defaultResourceCapacity

Validation.REPAIR fixes most of these instead of rejecting them. See Accept messy input.

Example#

import java.util.List;
import org.dhtmlx.plen.*;

public class ProjectDataExample {
  public static void main(String[] args) throws Exception {
    Moment monday = Moment.fromYmdHm(2026, 1, 5, 8, 0);

    ProjectData data = new ProjectData()
        .withConfig(new SchedulingConfig().withDurationUnit(TimeUnit.DAY))
        .withTasks(List.of(
            new TaskData(Id.str("design")).withStartDate(monday).withDuration(2.0),
            new TaskData(Id.str("build")).withStartDate(monday).withDuration(3.0)))
        .withLinks(List.of(
            new LinkData().withId(Id.str("l1")).withSource(Id.str("design")).withTarget(Id.str("build"))));

    ScheduleResult result = Engine.schedule(data, new SolveOptions());

    for (Mutation update : result.updates) {
      System.out.println(update.id + ": " + update.startDate + " - " + update.endDate);
    }
  }
}