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


# LinkData

A dependency between two tasks. It says which end of the source task drives which end of the target task, and how much working time lies between them. Links go in [`ProjectData.links`](<https://docs.dhtmlx.com/planning-engine/java/api/data/project-data.md>). Create one with `new LinkData()` and the fluent `withX` setters.

## Declaration

```java
public class LinkData extends ValueRecord implements DeepCloneable<LinkData>
```

## Constructors

### LinkData()

```java
public LinkData()
```

Creates a link with `id`, `source` and `target` set to `null`. Set all three before the link goes into a snapshot.

## Fields

| Field | Type | Default | Description |
|---|---|---|---|
| `id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | `null` | Link id, unique among the project's links. Required. |
| `source` | `Id` | `null` | Id of the predecessor task. Required. |
| `target` | `Id` | `null` | Id of the successor task. Required. |
| `linkType` | [`LinkType`](<https://docs.dhtmlx.com/planning-engine/java/api/data/link-data.md#linktype>) | `LinkType.FS` | Which end of `source` drives which end of `target`. JSON field `type`. |
| `lag` | `double` | `0.0` | Working time between the two ends, in `lagUnit`. Negative values are allowed. |
| `lagUnit` | [`TimeUnit`](<https://docs.dhtmlx.com/planning-engine/java/api/data/time-unit.md>) | `null` | Unit of `lag`. `null` uses [`config.durationUnit`](<https://docs.dhtmlx.com/planning-engine/java/api/data/scheduling-config.md#durationunit>). |

### id

The key results use to refer to this link: in [`Note.DroppedLink`](<https://docs.dhtmlx.com/planning-engine/java/api/results/note.md>), in a cycle's `links` and in the critical path of [`Analytics`](<https://docs.dhtmlx.com/planning-engine/java/api/results/analytics.md>). Build it with `Id.str("a")` or `Id.num(1)`.

### source, target

Ids of the two tasks the link connects. An id that names no task, or names an unscheduled task, doesn't fail validation. The link is dropped and reported as a [`Note.DroppedLink`](<https://docs.dhtmlx.com/planning-engine/java/api/results/note.md>) with the reason. See [Links that get dropped](<https://docs.dhtmlx.com/planning-engine/java/scheduling/links-constraints-summaries.md#links-that-get-dropped>) for every case.

### linkType

`FS` (finish-to-start), `SS`, `FF` or `SF`. See [`LinkType`](<https://docs.dhtmlx.com/planning-engine/java/api/data/link-data.md#linktype>) below.

### lag

Working time added between the source end and the target end, in `lagUnit`. A negative value lets the target overlap the source. Must be a finite number. Lag is an absolute amount, not a percentage of the predecessor's duration.

### lagUnit

Unit for this link's `lag`. `null` uses [`SchedulingConfig.durationUnit`](<https://docs.dhtmlx.com/planning-engine/java/api/data/scheduling-config.md#durationunit>).

:::note
Without a `lagUnit`, lag is measured in `config.durationUnit`.
:::

## Methods

### withId, withSource, withTarget, withLinkType, withLag, withLagUnit

```java
public LinkData withId(Id value)
public LinkData withSource(Id value)
public LinkData withTarget(Id value)
public LinkData withLinkType(LinkType value)
public LinkData withLag(double value)
public LinkData withLagUnit(TimeUnit value)
```

Each setter assigns its field and returns this instance.

**Returns** - this `LinkData`.

### deepClone

```java
public LinkData deepClone()
```

Returns a new `LinkData` with the same field values. `Id`, `LinkType` and `TimeUnit` are immutable, so the copy shares nothing that can change.

**Returns** - a new `LinkData`.

### copy

```java
public LinkData copy()
```

Returns a shallow copy with the same field values.

**Returns** - a new `LinkData`.

### equals, hashCode, toString

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

Inherited from [`ValueRecord`](<https://docs.dhtmlx.com/planning-engine/java/api/support/value-record.md>). Two `LinkData` are equal when all six fields are equal. `toString()` lists the fields, for logging.

## LinkType

The dependency type of a link: which end of the source task drives which end of the target task.

```java
public enum LinkType { FS, SS, FF, SF }
```

| Value | Description |
|---|---|
| `FS` | Finish-to-start: the target starts after the source finishes. The default. |
| `SS` | Start-to-start: the target starts after the source starts. |
| `FF` | Finish-to-finish: the target finishes after the source finishes. |
| `SF` | Start-to-finish: the target finishes after the source starts. |

`lag` is added for every type. [`LinkAdd`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-add.md>) and [`LinkUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-update.md>) use the same enum. In JSON, [`Decode`](<https://docs.dhtmlx.com/planning-engine/java/api/json/decode.md>) reads the values from the `type` field.

## Errors

The snapshot is validated when it's passed to [`Engine.schedule`](<https://docs.dhtmlx.com/planning-engine/java/api/engine-schedule.md>), [`Project#solve(data, …)`](<https://docs.dhtmlx.com/planning-engine/java/api/project-solve.md>) or [`Project#analyze(data, …)`](<https://docs.dhtmlx.com/planning-engine/java/api/project-analyze.md>). With strict validation, a link makes the call throw [`InputException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/input-exception.md>) when:

- its `id` repeats the id of an earlier link: path `links[i].id`
- its `lag` is `NaN` or infinite: path `links[i].lag`

A `null` `id`, `source` or `target` throws `NullPointerException`.

[`Validation.REPAIR`](<https://docs.dhtmlx.com/planning-engine/java/api/project/validation.md>) handles a repeated id without throwing. The later link replaces the earlier one at the earlier position, and a [`Note.Repaired`](<https://docs.dhtmlx.com/planning-engine/java/api/results/note.md>) records it.

Links added or edited after the first solve go through [`LinkAdd`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-add.md>) and [`LinkUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-update.md>).

## Example

Task `build` starts when `design` finishes. Task `test` starts four working hours after `build` starts, while the project counts durations in days:

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

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

    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.str("design")).withStartDate(monday).withDuration(2.0),
            new TaskData(Id.str("build")).withStartDate(monday).withDuration(3.0),
            new TaskData(Id.str("test")).withStartDate(monday).withDuration(1.0)))
        .withLinks(List.of(
            new LinkData()
                .withId(Id.str("a"))
                .withSource(Id.str("design"))
                .withTarget(Id.str("build")),
            new LinkData()
                .withId(Id.str("b"))
                .withSource(Id.str("build"))
                .withTarget(Id.str("test"))
                .withLinkType(LinkType.SS)
                .withLag(4.0)
                .withLagUnit(TimeUnit.HOUR)));

    ScheduleResult result = Engine.schedule(data, new SolveOptions());
    for (Mutation update : result.updates) {
      System.out.println(update.id + ": " + update.startDate + " - " + update.endDate);
    }
  }
}
```

Output:

```
build: 2026-04-08 08:00 - 2026-04-13 08:00
test: 2026-04-08 12:00 - 2026-04-09 12:00
```

`design` takes Monday and Tuesday, so `build` starts on Wednesday morning. `test` starts four working hours later, at 12:00 on Wednesday.

## Related

- [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/project-data.md>) - where links are listed
- [`LinkAdd`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-add.md>) - adding a link to a live project
- [`LinkUpdate`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/link-update.md>) - editing a link in a live project
- [`TimeUnit`](<https://docs.dhtmlx.com/planning-engine/java/api/data/time-unit.md>) - the unit of the lag
- [Links, constraints and summaries](<https://docs.dhtmlx.com/planning-engine/java/scheduling/links-constraints-summaries.md#link-types-and-lag>) - link types and lag
