RejectedOperation#

One operation of a change set that Project#apply didn't apply: where it sits in the change set, and why it was rejected. Instances come from ApplyReport.rejected, and from CandidateResult.error when Project#evaluate can't score a candidate.

Declaration#

package org.dhtmlx.plen;

public class RejectedOperation extends ValueRecord implements DeepCloneable<RejectedOperation>

Constructors#

RejectedOperation()#

public RejectedOperation()

Creates an instance with path and message set to null. The library fills both fields on every instance it returns.

Fields#

Field Type Default Description
path String null Position of the operation in the change set, as {group}.{verb}[{index}].
message String null Why the operation was rejected.

path#

public String path = null;

group is tasks, links, resources or assignments. verb is add, update or remove. index is the zero-based position in that list of SchedulingChanges. For example, links.add[0] is the first entry of changes.links.add. AppliedOperation.path uses the same form, so every operation of a change set shows up exactly once, in either applied or rejected.

In CandidateResult.error, a failure while solving or leveling the candidate carries the input path of that error instead, such as a field path. When that error has no path, path is an empty string.

message#

public String message = null;

The validation message, without the path, e.g. duplicate link id or lag must be finite. Each change-set type lists the messages its operations can produce; see LinkAdd for an example. The text is for logs and diagnostics, not for matching in code.

Methods#

withPath, withMessage#

public RejectedOperation withPath(String value)
public RejectedOperation withMessage(String value)

Each setter assigns its field and returns this instance.

Returns: this RejectedOperation.

deepClone#

public RejectedOperation deepClone()

Returns a new instance with the same path and message.

Returns: a new RejectedOperation.

copy#

public RejectedOperation copy()

Returns a shallow copy. Both fields are strings, so it's equivalent to deepClone().

Returns: a new RejectedOperation.

equals, hashCode, toString#

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

Inherited from ValueRecord. Two instances are equal when path and message are equal. toString() prints both fields, e.g. RejectedOperation{path=links.add[0], message=duplicate link id}, for logging.

Example#

Add a link whose id already exists, and read the rejection:

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

public class RejectedOperationExample {
  public static void main(String[] args) throws Exception {
    Moment start = Moment.fromYmdHm(2026, 4, 6, 8, 0);

    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.num(1)).withStartDate(start).withDuration(2.0),
            new TaskData(Id.num(2)).withStartDate(start).withDuration(3.0)))
        .withLinks(List.of(
            new LinkData().withId(Id.str("L1")).withSource(Id.num(1)).withTarget(Id.num(2))));

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

    SchedulingChanges changes = new SchedulingChanges();
    changes.links.add.add(new LinkAdd()
        .withId(Id.str("L1"))
        .withSource(Id.num(2))
        .withTarget(Id.num(1)));

    ApplyReport report = project.apply(changes);
    for (RejectedOperation rejected : report.rejected) {
      System.out.println(rejected.path + ": " + rejected.message);
    }
  }
}

Output:

links.add[0]: duplicate link id

A rejection sets ApplyReport.needsResync. To continue, see Recover from rejected changes.