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, TaskData or ScheduleResult.

Declaration#

package org.dhtmlx.plen;

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

Methods#

deepClone#

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 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 and Moment 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). A type can share other fields on purpose, and its own deepClone section says which. For example, LevelingResult#deepClone 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> requires both type arguments to implement DeepCloneable, so its own deepClone() can copy every record in add and update:

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

Example#

Project#solve can return the same cached result object on later calls. Change a deep copy and the cached result stays as it was:

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
    }
}