[Canonical page](<https://docs.dhtmlx.com/planning-engine/java/api/changes/scheduling-changes/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# SchedulingChanges

A set of edits to a project: added, updated and removed tasks, links, resources and assignments. Pass it to [`Project#apply`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md>) to commit the edits, to [`Project#preview`](<https://docs.dhtmlx.com/planning-engine/java/api/project-preview.md>) to see their effect, or in a [`Candidate`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/candidate.md>) to [`Project#evaluate`](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate.md>). Create one with `new SchedulingChanges()` and fill its four groups. [`SuggestResult.changes`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-result.md>) also returns one.

## Declaration

```java
public class SchedulingChanges extends ValueRecord implements DeepCloneable<SchedulingChanges>
```

Each group is a [`Changes`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/changes.md>) 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()

```java
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`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/changes.md>)`<`[`TaskData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/task-data.md>)`, `[`TaskUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/task-update.md>)`>` | `new Changes<>()` | Tasks to add, update and remove. |
| `links` | `Changes<`[`LinkAdd`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-add.md>)`, `[`LinkUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-update.md>)`>` | `new Changes<>()` | Links to add, update and remove. |
| `resources` | `Changes<`[`ResourceData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/resource-data.md>)`, `[`ResourceUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/resource-update.md>)`>` | `new Changes<>()` | Resources to add, update and remove. |
| `assignments` | `Changes<`[`AssignmentData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/assignment-data.md>)`, `[`AssignmentUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/assignment-update.md>)`>` | `new Changes<>()` | Assignments to add, update and remove. |

Calendars and the project `config` have no group. Changing them takes a full [`solve(data, …)`](<https://docs.dhtmlx.com/planning-engine/java/api/project-solve.md>).

### baselineId

```java
public String baselineId = null;
```

Set it to the [`ScheduleResult.baselineId`](<https://docs.dhtmlx.com/planning-engine/java/api/results/schedule-result.md#baselineid>) the user saw when making the edits. `apply`, `preview` and `evaluate` throw [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md>) with `STALE_BASELINE` when a non-`null` value doesn't name the project's current baseline.

### tasks

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

New tasks are full [`TaskData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/task-data.md>) records. Updates are [`TaskUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/task-update.md>) records keyed by task id. Removals list task ids.

### links

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

New links are [`LinkAdd`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-add.md>) records. Updates are [`LinkUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-update.md>) records keyed by link id. Removals list link ids.

### resources

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

New resources are full [`ResourceData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/resource-data.md>) records. Updates are [`ResourceUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/resource-update.md>) records keyed by resource id. Removals list resource ids.

### assignments

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

New assignments are full [`AssignmentData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/assignment-data.md>) records. Updates are [`AssignmentUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/assignment-update.md>) 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`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md#behavior>).

## Methods

### withBaselineId, withTasks, withLinks, withResources, withAssignments

```java
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

```java
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`](<https://docs.dhtmlx.com/planning-engine/java/api/data/scheduling-config.md#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`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | 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

```java
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

```java
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

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

Inherited from [`ValueRecord`](<https://docs.dhtmlx.com/planning-engine/java/api/support/value-record.md>). Two `SchedulingChanges` are equal when their public fields are equal, nested records compared by value. `toString()` lists the fields.

## Example

```java
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);
    }
  }
}
```

## Related

- [`Project#apply`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md>) - commits a change set
- [`Project#preview`](<https://docs.dhtmlx.com/planning-engine/java/api/project-preview.md>) - tries a change set without committing it
- [`ApplyReport`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/apply-report.md>) - what `apply` returns
- [Data Updates](<https://docs.dhtmlx.com/planning-engine/java/live-projects/editing-a-project.md>) - building and applying change sets
- [Previewing Changes](<https://docs.dhtmlx.com/planning-engine/java/live-projects/previewing-changes.md>) - previewing an edit with baseline tokens
