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


# DeepCloneable<T>

A record that can be deep-copied. Input records, options classes, change sets and result classes in `org.dhtmlx.plen` implement it, each with `T` set to its own type. There's nothing to construct: call `deepClone()` on a record such as [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/project-data.md>), [`TaskData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/task-data.md>) or [`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/java/api/results/schedule-result.md>).

## Declaration

```java
package org.dhtmlx.plen;

public interface DeepCloneable<T> {
    T deepClone();
}
```

## Methods

### deepClone

```java
T deepClone()
```

Returns a deep copy of the record. Nested records that implement `DeepCloneable` are cloned with their own `deepClone()`, and lists of them are rebuilt as new [`Vec`](<https://docs.dhtmlx.com/planning-engine/java/api/support/vec.md>) instances, so a change to the copy's fields, lists or nested records leaves the original as it was.

**Returns** - a new instance of `T`.

Immutable values aren't copied. [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) and [`Moment`](<https://docs.dhtmlx.com/planning-engine/java/api/data/moment.md>) instances are shared, and that's safe because neither can change. Field-less values can also return themselves: `DayRule.Off` and `DayRule.On` do (see [`Worktime`](<https://docs.dhtmlx.com/planning-engine/java/api/data/worktime.md>)). A type can share other fields on purpose, and its own `deepClone` section says which. For example, [`LevelingResult#deepClone`](<https://docs.dhtmlx.com/planning-engine/java/api/resources/leveling-result.md>) keeps the same `schedule` object.

`deepClone()` differs from the `copy()` method every record has: `copy()` is shallow, so the copy and the original share lists and nested records.

## Type bound

[`Changes<TAdd, TUpdate>`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/changes.md>) requires both type arguments to implement `DeepCloneable`, so its own `deepClone()` can copy every record in `add` and `update`:

```java
public class Changes<TAdd extends DeepCloneable<TAdd>, TUpdate extends DeepCloneable<TUpdate>>
    extends ValueRecord implements DeepCloneable<Changes<TAdd, TUpdate>>
```

## Example

[`Project#solve`](<https://docs.dhtmlx.com/planning-engine/java/api/project-solve.md>) can return the same cached result object on later calls. Change a deep copy and the cached result stays as it was:

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

public class DeepCloneExample {
    public static void main(String[] args) throws Exception {
        ProjectData data = new ProjectData()
                .withTasks(List.of(
                        new TaskData(Id.num(1))
                                .withStartDate(Moment.fromYmdHm(2026, 4, 6, 8, 0))
                                .withDuration(2.0)));

        Project project = new Project();
        SolveOptions options = new SolveOptions().withIncludeUnchanged(true);
        ScheduleResult result = project.solve(data, options);

        ScheduleResult copy = result.deepClone();
        copy.updates.clear();

        System.out.println(result.updates.size());                       // 1
        System.out.println(project.solve(null, options).updates.size()); // 1
    }
}
```

## Related

- [`ValueRecord`](<https://docs.dhtmlx.com/planning-engine/java/api/support/value-record.md>) - the base class with shallow copy()
- [`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/java/api/results/schedule-result.md>) - a shared result to clone before changing
- [Copies and shared results](<https://docs.dhtmlx.com/planning-engine/java/records-ids-and-dates.md#copies-and-shared-results>) - when to deep-clone
