SchedulingChanges#

A set of edits to a project: added, updated and removed tasks, links, resources and assignments. Pass it to Project#apply to commit the edits, to Project#preview to see their effect, or in a Candidate to Project#evaluate. Create one with new SchedulingChanges() and fill its four groups. SuggestResult.changes also returns one.

Declaration#

public class SchedulingChanges extends ValueRecord implements DeepCloneable<SchedulingChanges>

Each group is a Changes value with add, update and remove lists. Fill them in place (changes.tasks.update.add(...)) or replace a whole group with a withX setter.

Constructors#

SchedulingChanges()#

public SchedulingChanges()

Creates an empty change set: baselineId is null and every group is an empty Changes.

Fields#

Field Type Default Description
baselineId String null Baseline token the edits were made against. null skips the baseline check.
tasks Changes<TaskData, TaskUpdate> new Changes<>() Tasks to add, update and remove.
links Changes<LinkAdd, LinkUpdate> new Changes<>() Links to add, update and remove.
resources Changes<ResourceData, ResourceUpdate> new Changes<>() Resources to add, update and remove.
assignments Changes<AssignmentData, AssignmentUpdate> new Changes<>() Assignments to add, update and remove.

Calendars and the project config have no group. Changing them takes a full solve(data, …).

baselineId#

public String baselineId = null;

Set it to the ScheduleResult.baselineId the user saw when making the edits. apply, preview and evaluate throw ProjectException with STALE_BASELINE when a non-null value doesn't name the project's current baseline.

tasks#

public Changes<TaskData, TaskUpdate> tasks = new Changes<TaskData, TaskUpdate>();

New tasks are full TaskData records. Updates are TaskUpdate records keyed by task id. Removals list task ids.

public Changes<LinkAdd, LinkUpdate> links = new Changes<LinkAdd, LinkUpdate>();

New links are LinkAdd records. Updates are LinkUpdate records keyed by link id. Removals list link ids.

resources#

public Changes<ResourceData, ResourceUpdate> resources = new Changes<ResourceData, ResourceUpdate>();

New resources are full ResourceData records. Updates are ResourceUpdate records keyed by resource id. Removals list resource ids.

assignments#

public Changes<AssignmentData, AssignmentUpdate> assignments = new Changes<AssignmentData, AssignmentUpdate>();

New assignments are full AssignmentData records. Updates are AssignmentUpdate records keyed by assignment id. Removals list assignment ids.

The order in which the operations of all four groups run is part of Project#apply.

Methods#

public SchedulingChanges withBaselineId(String value)
public SchedulingChanges withTasks(Changes<TaskData, TaskUpdate> value)
public SchedulingChanges withLinks(Changes<LinkAdd, LinkUpdate> value)
public SchedulingChanges withResources(Changes<ResourceData, ResourceUpdate> value)
public SchedulingChanges withAssignments(Changes<AssignmentData, AssignmentUpdate> value)

Each setter assigns its field and returns this instance for chaining.

Returns - this SchedulingChanges.

rooted#

public SchedulingChanges rooted(Id root)

Clears every task parent that equals root: on added tasks it becomes null, on task updates it becomes Patch.nullValue(). Ids compare as normalized keys, so Id.num(0) matches Id.str("0"). The engine calls it with config.rootId before applying changes, so a parent set to the virtual root reaches the project as "no parent". Calling it yourself isn't needed.

Parameters

Name Type Description
root Id The parent id that means "no parent".

Returns - a deep copy with the matching parents cleared, or this same instance when no task add or update has root as its parent. This instance is never modified.

deepClone#

public SchedulingChanges deepClone()

Returns a copy that shares no group, list or record with this instance. Ids are shared; they're immutable.

Returns - a new SchedulingChanges with the same values.

copy#

public SchedulingChanges copy()

Returns a shallow copy. The copy shares the four Changes groups with this instance, so adding to copy.tasks.update also changes the original.

Returns - a new SchedulingChanges with the same field values.

equals, hashCode, toString#

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

Inherited from ValueRecord. Two SchedulingChanges are equal when their public fields are equal, nested records compared by value. toString() lists the fields.

Example#

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

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

    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.str("design")).withStartDate(monday).withDuration(2.0),
            new TaskData(Id.str("build")).withStartDate(monday).withDuration(3.0)));

    Project project = new Project();
    ScheduleResult solved = project.solve(data, new SolveOptions());

    SchedulingChanges changes = new SchedulingChanges().withBaselineId(solved.baselineId);
    changes.tasks.update.add(new TaskUpdate(Id.str("build")).withDuration(Patch.of(4.0)));
    changes.tasks.add.add(new TaskData(Id.str("test")).withStartDate(monday).withDuration(1.0));
    changes.links.add.add(new LinkAdd()
        .withId(Id.str("l1")).withSource(Id.str("design")).withTarget(Id.str("build")));

    ApplyReport report = project.apply(changes);
    System.out.println("rejected: " + report.rejected.size());

    ScheduleResult result = project.solve(null, new SolveOptions());
    for (Mutation update : result.updates) {
      System.out.println(update.id + ": " + update.startDate + " - " + update.endDate);
    }
  }
}