ApplyReport#

The result of one Project#apply call. It lists which operations of the SchedulingChanges were applied and which were rejected. It also lists the records the edit removed, generated or dropped as a side effect, and gives the project's revision afterwards. apply returns a new instance on every call.

Declaration#

public class ApplyReport extends ValueRecord implements DeepCloneable<ApplyReport>

Fields#

Field Type Default Description
applied Vec<AppliedOperation> empty Operations that were applied, in the order they ran.
rejected Vec<RejectedOperation> empty Operations that were rejected, in the order they ran. Empty when everything was applied.
effects ChangeEffects new ChangeEffects() Records removed, generated or dropped by the applied operations.
needsResync boolean false true when rejected isn't empty.
revision long 0L The project's revision counter after this call.

applied#

public Vec<AppliedOperation> applied = new Vec<AppliedOperation>();

One entry per applied operation. Each entry's path names the operation in the change set.

rejected#

public Vec<RejectedOperation> rejected = new Vec<RejectedOperation>();

One entry per rejected operation, with its path and the reason. A rejected operation leaves no partial edit, and the operations after it still run.

effects#

public ChangeEffects effects = new ChangeEffects();

Side effects of the applied operations only. A rejected operation adds nothing here.

needsResync#

public boolean needsResync = false;

true exactly when at least one operation was rejected. From then on, apply, solve(null, โ€ฆ) and level throw ProjectException with code == ProjectError.NEEDS_RESYNC until a full solve(data, โ€ฆ). See Recover from rejected changes.

revision#

public long revision = 0L;

The project's revision counter after the apply. Every apply raises it, so a higher value means a later state of the same project.

Methods#

withApplied, withRejected, withEffects, withNeedsResync, withRevision#

public ApplyReport withApplied(Vec<AppliedOperation> value)
public ApplyReport withApplied(java.util.Collection<? extends AppliedOperation> value)
public ApplyReport withRejected(Vec<RejectedOperation> value)
public ApplyReport withRejected(java.util.Collection<? extends RejectedOperation> value)
public ApplyReport withEffects(ChangeEffects value)
public ApplyReport withNeedsResync(boolean value)
public ApplyReport withRevision(long value)

Each setter assigns its field and returns this instance for chaining. The Collection overloads copy the elements into a new Vec, and a null collection sets the field to null.

Returns: this ApplyReport.

deepClone#

public ApplyReport deepClone()

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

Returns: a new ApplyReport with the same values.

copy#

public ApplyReport copy()

Returns a shallow copy. The copy shares the applied and rejected lists and the effects record with this instance.

Returns: a new ApplyReport with the same field values.

equals, hashCode, toString#

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

Inherited from ValueRecord. Two reports are equal when their public fields are equal: the lists element by element, effects by value. toString() lists the fields.

AppliedOperation#

One applied operation, identified by its position in the change set.

public class AppliedOperation extends ValueRecord implements DeepCloneable<AppliedOperation> {
  public String path = null;

  public AppliedOperation withPath(String value);
  public AppliedOperation deepClone();
  public AppliedOperation copy();
}
Field Type Default Description
path String null The operation's group, list and index in the change set, in the form {group}.{list}[{index}], for example tasks.update[0], links.add[2] or assignments.remove[1]. Groups: tasks, links, resources, assignments. Lists: add, update, remove. Always set in a report.

withPath sets the field and returns this instance. equals, hashCode and toString come from ValueRecord.

ChangeEffects#

The records an apply removed, generated or dropped beyond the ones the change set names directly. Use it to keep a client-side copy of the project in sync.

public class ChangeEffects extends ValueRecord implements DeepCloneable<ChangeEffects> {
  public Vec<Id> removedTasks = new Vec<Id>();
  public Vec<Id> removedLinks = new Vec<Id>();
  public Vec<Id> generatedLinks = new Vec<Id>();
  public Vec<Id> droppedLinks = new Vec<Id>();
  public Vec<Id> removedAssignments = new Vec<Id>();
  public Vec<Id> generatedAssignments = new Vec<Id>();
  public Vec<Id> droppedAssignments = new Vec<Id>();

  public ChangeEffects deepClone();
  public ChangeEffects copy();
}

Every list holds Id values and is empty when nothing of that kind happened.

Field Type Description
removedTasks Vec<Id> Tasks deleted by tasks.remove, including every descendant of a removed task.
removedLinks Vec<Id> Links deleted by links.remove, plus links whose source or target was a removed task.
generatedLinks Vec<Id> Ids created for links.add entries without an id, in the form $generated_link_{n}.
droppedLinks Vec<Id> Links that stay in the data but were taken out of scheduling by this apply, for example because an endpoint became unscheduled. See Links that get dropped.
removedAssignments Vec<Id> Assignments deleted by assignments.remove, plus assignments of removed tasks and removed resources. Cascaded assignments without an id aren't listed.
generatedAssignments Vec<Id> Ids created for assignments.add entries without an id, in the form $generated_assignment_{n}.
droppedAssignments Vec<Id> Assignments that stay in the data but were taken out of scheduling by this apply because their task became unscheduled. They come back when the task is scheduled again.

Each field has a fluent setter in two forms, withRemovedTasks(Vec<Id>) and withRemovedTasks(Collection<? extends Id>), and the same for the other six lists. deepClone() copies every list. copy() returns a shallow copy that shares the lists. equals compares the seven lists element by element.

Example#

Remove a task that has a link and an assignment, and add a link without an id.

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

public class ApplyReportExample {
  public static void main(String[] args) throws Exception {
    Moment monday = Moment.fromYmdHm(2026, 8, 10, 8, 0);
    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.str("a")).withStartDate(monday).withDuration(1.0),
            new TaskData(Id.str("b")).withStartDate(monday).withDuration(2.0),
            new TaskData(Id.str("c")).withStartDate(monday).withDuration(1.0)))
        .withLinks(List.of(new LinkData()
            .withId(Id.str("ab")).withSource(Id.str("a")).withTarget(Id.str("b"))))
        .withResources(List.of(new ResourceData().withId(Id.str("dev"))))
        .withAssignments(List.of(new AssignmentData()
            .withId(Id.str("as1")).withTask(Id.str("b")).withResource(Id.str("dev")).withValue(1.0)));

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

    SchedulingChanges changes = new SchedulingChanges();
    changes.tasks.remove.add(Id.str("b"));
    changes.links.add.add(new LinkAdd().withSource(Id.str("a")).withTarget(Id.str("c")));

    ApplyReport report = project.apply(changes);

    for (AppliedOperation op : report.applied) {
      System.out.println("applied " + op.path);              // tasks.remove[0], links.add[0]
    }

    ChangeEffects effects = report.effects;
    System.out.println(effects.removedTasks);                // [b]
    System.out.println(effects.removedLinks);                // [ab]
    System.out.println(effects.removedAssignments);          // [as1]
    System.out.println(effects.generatedLinks);              // [$generated_link_1]
  }
}