[Canonical page](<https://docs.dhtmlx.com/planning-engine/java/how-to/clear-leveling/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Clear leveling

Remove the delays and splits that [`level`](<https://docs.dhtmlx.com/planning-engine/java/api/project-level.md>) wrote into a project, so every task goes back to its unleveled dates.

Leveling stores its result in two task fields: `levelingDelay` and `pauses`. To clear leveling, set `levelingDelay` to 0 and `pauses` to an empty list on every task that has either, then reschedule. For how leveling sets these fields, see [Leveling resources](<https://docs.dhtmlx.com/planning-engine/java/resources-and-assignment/leveling-resources.md>).

## Prerequisites

- A solved [`Project`](<https://docs.dhtmlx.com/planning-engine/java/api/project/project.md>) that carries leveling, either from a `level` call or from loaded data with a non-zero `levelingDelay` or non-empty `pauses`.
- The ids of the tasks that carry a delay or pauses. Take them from your own model, or from `schedule.updates` of the [`LevelingResult`](<https://docs.dhtmlx.com/planning-engine/java/api/resources/leveling-result.md>).

## Steps

1. Build one [`TaskUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/task-update.md>) per leveled task. Set `levelingDelay` to [`Patch.of(0.0)`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/patch.md#of>) and `pauses` to `Patch.of(new Vec<Pause>())`, and put all the updates into one [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/scheduling-changes.md>):

   ```java
   static SchedulingChanges clearLeveling(List<Id> ids) {
     var changes = new SchedulingChanges();
     for (var id : ids) {
       changes.tasks.update.add(
           new TaskUpdate(id)
               .withLevelingDelay(Patch.of(0.0))
               .withPauses(Patch.of(new Vec<Pause>())));
     }
     return changes;
   }
   ```

   Don't put dates in the update. When the update has no date, the `levelingDelay` change moves the stored start back by the delay. The `pauses` change keeps the start and duration and recomputes the end.

2. Apply the changes with [`apply`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md>) and check the [`ApplyReport`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/apply-report.md>):

   ```java
   var report = project.apply(clearLeveling(ids));
   if (!report.rejected.isEmpty()) {
     // Resync with project.solve(data, ...) before the next edit.
   }
   ```

3. Reschedule with [`solve(null, …)`](<https://docs.dhtmlx.com/planning-engine/java/api/project-solve.md>) and write `result.updates` back to your model:

   ```java
   var result = project.solve(null, new SolveOptions());
   ```

   The cleared dates become the accepted baseline. The resource contention that leveling resolved shows up again in `result.overallocations`.

The full example below levels three 2-day tasks that share `dev1`, then clears the leveling. It uses the default calendar (Monday to Friday, 08:00-12:00 and 13:00-17:00) and starts on Monday, August 10, 2026:

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

public class ClearLeveling {
  static Moment aug(int day) {
    return Moment.fromYmdHm(2026, 8, day, 8, 0);
  }

  static TaskData task(String id) {
    return new TaskData(Id.str(id)).withStartDate(aug(10)).withDuration(2.0);
  }

  static AssignmentData booking(String task) {
    return new AssignmentData()
        .withTask(Id.str(task))
        .withResource(Id.str("dev1"))
        .withValue(1.0);
  }

  static SchedulingChanges clearLeveling(List<Id> ids) {
    var changes = new SchedulingChanges();
    for (var id : ids) {
      changes.tasks.update.add(
          new TaskUpdate(id)
              .withLevelingDelay(Patch.of(0.0))
              .withPauses(Patch.of(new Vec<Pause>())));
    }
    return changes;
  }

  public static void main(String[] args) throws Exception {
    var data = new ProjectData()
        .withTasks(List.of(task("A"), task("B"), task("C")))
        .withResources(List.of(new ResourceData().withId(Id.str("dev1"))))
        .withAssignments(List.of(booking("A"), booking("B"), booking("C")));

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

    // B is delayed to Wednesday, C to Friday.
    var leveled = project.level(new LevelingOptions());

    // The tasks that leveling delayed or split.
    var ids = new ArrayList<Id>();
    for (var m : leveled.schedule.updates) {
      boolean delayed = m.levelingDelay != null && m.levelingDelay != 0.0;
      boolean split = m.pauses != null && !m.pauses.isEmpty();
      if (delayed || split) ids.add(m.id);
    }

    var report = project.apply(clearLeveling(ids));
    if (!report.rejected.isEmpty()) {
      throw new IllegalStateException("clearing was rejected, resync with solve(data, ...)");
    }

    var result = project.solve(null, new SolveOptions());
    for (var m : result.updates) {
      if (m.startDate != null && m.endDate != null) {
        System.out.println(m.id + ": " + m.startDate + " .. " + m.endDate);
      }
    }
    for (var over : result.overallocations) {
      for (var w : over.windows) {
        System.out.println(over.resource + ": " + w.from + " .. " + w.to + ", peak " + w.peak);
      }
    }
  }
}
```

## Re-level from scratch instead

To replace old leveling with a fresh run, skip the steps above and call [`level`](<https://docs.dhtmlx.com/planning-engine/java/api/project-level.md>) again. [`LevelingOptions.clearFirst`](<https://docs.dhtmlx.com/planning-engine/java/api/resources/leveling-options.md#clearfirst>) is `true` by default. The run first sets `levelingDelay` to 0 and `pauses` to an empty list on every in-scope task that has either, then levels the clean plan:

```java
var result = project.level(new LevelingOptions());
```

`result.schedule.updates` is a diff against the state the call started from. A task whose old delay was cleared and not replaced still gets an update entry, so writing the updates back keeps your model in sync.

With a `scope`, the run clears only in-scope tasks. Set `clearFirst` to `false` to keep the existing delays and pauses and level on top of them.

## Things to know

- [`Patch.nullValue()`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/patch.md#nullvalue>) also works. On `levelingDelay` it restores the default of 0, and on `pauses` it clears the list. Don't use `Patch.of(null)` on `pauses`: it throws `NullPointerException` when applied.
- Only leveling produces pauses. Every pause counts as leveling-owned, whether or not its [`by`](<https://docs.dhtmlx.com/planning-engine/java/api/data/pause.md#by>) is set, so clearing removes all of them.
- To see what clearing would do before you commit it, pass the same changes to [`preview`](<https://docs.dhtmlx.com/planning-engine/java/api/project-preview.md>). The project stays untouched. See [Previewing changes](<https://docs.dhtmlx.com/planning-engine/java/live-projects/previewing-changes.md>).
- In a live editor, set `changes.baselineId` to the baseline your model shows. [`apply`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md>) then throws [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md>) with code [`ProjectError.STALE_BASELINE`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md#projecterror>) if the project has moved on. See [Error handling](<https://docs.dhtmlx.com/planning-engine/java/error-handling.md>).
- If `apply` rejects an operation, `report.needsResync` is `true`, and [`solve(null, …)`](<https://docs.dhtmlx.com/planning-engine/java/api/project-solve.md>) throws `ProjectError.NEEDS_RESYNC` until you send the full data with `solve(data, …)`. See [Recover from rejected changes](<https://docs.dhtmlx.com/planning-engine/java/how-to/recover-from-rejected-changes.md>).

## Result

The example prints `B` and `C` back on Monday, and the overallocation window on `dev1` returns:

```text
B: 2026-08-10 08:00 .. 2026-08-12 08:00
C: 2026-08-10 08:00 .. 2026-08-12 08:00
dev1: 2026-08-10 08:00 .. 2026-08-11 17:00, peak 3.0
```
