ApplyReport#
The outcome of one Project.Apply call. It lists which operations of the SchedulingChanges were applied and which were rejected, the records the edit removed, generated or dropped as a side effect, and the project's revision afterwards.
Apply returns a new instance on every call.
Declaration#
public sealed class ApplyReport : IDeepCloneable<ApplyReport>, IEquatable<ApplyReport>
{
public List<AppliedOperation> Applied { get; set; } = [];
public List<RejectedOperation> Rejected { get; set; } = [];
public ChangeEffects Effects { get; set; } = new();
public bool NeedsResync { get; set; }
public ulong Revision { get; set; }
public ApplyReport DeepClone();
public bool Equals(ApplyReport? other);
public override string ToString();
}
Properties#
| Property | Type | Description |
|---|---|---|
Applied |
List<AppliedOperation> |
Operations that were applied, in execution order. |
Rejected |
List<RejectedOperation> |
Operations that were rejected, in execution order. Empty when everything was applied. |
Effects |
ChangeEffects |
Records removed, generated or dropped by the applied operations. |
NeedsResync |
bool |
true when Rejected isn't empty. |
Revision |
ulong |
The project's revision counter after this call. |
Applied#
public List<AppliedOperation> Applied { get; set; } = [];
One entry per applied operation, in the order the operations ran. Each entry's Path names the operation. For the execution order, see Operation order.
Rejected#
public List<RejectedOperation> Rejected { get; set; } = [];
One entry per rejected operation, with its path and the reason. A rejected operation leaves no partial edit; operations after it still run.
Effects#
public ChangeEffects Effects { get; set; } = new();
Side effects of the applied operations only. A rejected operation contributes nothing here.
NeedsResync#
public bool NeedsResync { get; set; }
true exactly when at least one operation was rejected. From then on, Apply, Solve(null, …) and Level throw a ProjectException with Code == ProjectError.NeedsResync until a full Solve(data, …). See Recover from rejected changes.
Revision#
public ulong Revision { get; set; }
The project's revision counter after the apply. Every Apply raises it, so a higher value means a later state of the same project. A Clone() starts from the source's counter.
Methods#
DeepClone#
public ApplyReport DeepClone()
Returns a copy that shares no list or nested record with this instance.
Equals#
public bool Equals(ApplyReport? other)
Value equality: the three lists element by element, Effects by value, NeedsResync and Revision by ==.
ToString#
public override string ToString()
Returns a debug dump of all five properties.
AppliedOperation#
One applied operation, identified by its position in the change set.
public sealed class AppliedOperation : IDeepCloneable<AppliedOperation>, IEquatable<AppliedOperation>
{
public required string Path { get; set; }
public AppliedOperation DeepClone();
public bool Equals(AppliedOperation? other);
public override string ToString();
}
| Property | Type | Description |
|---|---|---|
Path |
string |
The operation's bucket, list and index in the change set, in the form {bucket}.{list}[{index}]: tasks.update[0], links.add[2], assignments.remove[1]. Buckets: tasks, links, resources, assignments; lists: add, update, remove. |
ChangeEffects#
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 sealed class ChangeEffects : IDeepCloneable<ChangeEffects>, IEquatable<ChangeEffects>
{
public List<Id> RemovedTasks { get; set; } = [];
public List<Id> RemovedLinks { get; set; } = [];
public List<Id> GeneratedLinks { get; set; } = [];
public List<Id> DroppedLinks { get; set; } = [];
public List<Id> RemovedAssignments { get; set; } = [];
public List<Id> GeneratedAssignments { get; set; } = [];
public List<Id> DroppedAssignments { get; set; } = [];
public ChangeEffects DeepClone();
public bool Equals(ChangeEffects? other);
public override string ToString();
}
Every list holds Id values and is empty when nothing of that kind happened.
| Property | Type | Description |
|---|---|---|
RemovedTasks |
List<Id> |
Tasks deleted by tasks.remove, including every descendant of a removed task. |
RemovedLinks |
List<Id> |
Links deleted by links.remove, plus links whose source or target was a removed task. |
GeneratedLinks |
List<Id> |
Ids created for links.add entries without an Id, in the form $generated_link_{n}. |
DroppedLinks |
List<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 |
List<Id> |
Assignments deleted by assignments.remove, plus assignments of removed tasks and removed resources. Cascaded assignments without an id aren't listed. |
GeneratedAssignments |
List<Id> |
Ids created for assignments.add entries without an Id, in the form $generated_assignment_{n}. |
DroppedAssignments |
List<Id> |
Assignments that stay in the data but were taken out of scheduling by this apply because their task became unscheduled. They return when the task is scheduled again. |
DeepClone() copies every list. 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.
using Plen;
var monday = Moment.FromYmdHm(2026, 8, 10, 8, 0) ?? throw new InvalidOperationException("invalid date");
var data = new ProjectData
{
Tasks =
[
new TaskData("a") { StartDate = monday, Duration = 1.0 },
new TaskData("b") { StartDate = monday, Duration = 2.0 },
new TaskData("c") { StartDate = monday, Duration = 1.0 },
],
Links = [new LinkData { Id = "ab", Source = "a", Target = "b" }],
Resources = [new ResourceData { Id = "dev" }],
Assignments = [new AssignmentData { Id = "as1", Task = "b", Resource = "dev", Value = 1.0 }],
};
var project = new Project();
project.Solve(data, new SolveOptions());
var changes = new SchedulingChanges();
changes.Tasks.Remove.Add("b");
changes.Links.Add.Add(new LinkAdd { Source = "a", Target = "c" });
var report = project.Apply(changes);
foreach (var op in report.Applied)
Console.WriteLine($"applied {op.Path}"); // tasks.remove[0], links.add[0]
var effects = report.Effects;
Console.WriteLine(string.Join(", ", effects.RemovedTasks)); // b
Console.WriteLine(string.Join(", ", effects.RemovedLinks)); // ab
Console.WriteLine(string.Join(", ", effects.RemovedAssignments)); // as1
Console.WriteLine(string.Join(", ", effects.GeneratedLinks)); // $generated_link_1
Related#
Project.Apply- the call that returns the reportSchedulingChanges- the change set the report describesRejectedOperation- one rejected entry- Editing a project - applying edits and reading the report
- Recover from rejected changes - resyncing after a rejection