> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Level Configuration

This guide aims at providing the basic configuration tips to start defining levels with the fluent builder.

## Introduction

Hierarchies categorize data into levels for aggregation and visualization. For more info about hierarchies,
see [here](../concepts/dimensions_and_hierarchies).

* The levels in a hierarchy are organized with parent-child relationships.
* All non-slicing hierarchies have a parent level, called "AllMember", to aggregate data across all members of all
  levels. It is created and configured automatically.
* The level is often based on a column of the database from which they inherit a data type, a formatter and a
  comparator.

## Basic configuration

For a hierarchy, use:

* `withDimension("dimensionName")` to define the dimension
* `withHierarchy("hierarchy)` to define a hierarchy
* `withLevel("levelName")` to define the levels.

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
builder.withDimension("Time").withHierarchy("Time").withLevel("year").withLevel("month");
```

<Note>
  Here the order is important : the level "year" is defined first so it will be the parent of the level "month".
</Note>

Several shortcuts are provided by the builder.
For example, define a dimension, with one hierarchy and one level, all with the same name, with
`withSingleLevelDimension("dimensionName")`:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
StartBuilding.cube()
    .withName("Cube")
    .withDimensions(builder -> builder.withSingleLevelDimension("Currency"));
```

The level is based on the first reachable field, with the same name, in the database. The level inherits the data type
and other properties from the field.
Specify a field name after the level name to:

* Create a level with a different name to the selection field
* Create a level that is based on a specific selection field (i.e. not the first reachable field with the same name as
  the level)

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
builder.withDimension("Trader").withHierarchy("Trader").withLevel("Trader", "Trader_id");
```

## Defining the time levels

### Level types

There are mainly three level types:

* `ALL` the type of the "AllMember" level that exists as the first level of all [non-slicing hierarchies](./hierarchy_configuration#hierarchy-members-allmember-vs-slicing-members)
* `TIME` for time levels (with specific subtypes for the different time units)
* `REGULAR` for the other levels (it is the type defined by default).

<Note>
  The level type is different from the data type of the selection field the level is based on. The data type is the type
  of the members of the level: double, string, date...
</Note>

Use `withLevelType(ILevelInfo.LevelType.TIME)` to define the type of the levels representing time so that they are
correctly handled by time measures (for example, finding the first month of a quarter).

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
builder
    .withDimension("Time")
    .withType(IDimension.DimensionType.TIME)
    .withHierarchyOfSameName()
    .withLevel("Time")
    .withType(ILevelInfo.LevelType.TIME);
```

### Formatter

By default, each data type has a formatter to define how to display the level members:

* add a comma to group thousands in numbers
* format dates

Simple formatter can be used with their string representation:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
builder
    .withDimension("Time")
    .withType(IDimension.DimensionType.TIME)
    .withHierarchyOfSameName()
    .withLevel("year")
    .withFormatter("DATE[MM-DD-YY]");
```

To define a custom formatter, see [this page](../configuration/internationalization#formatter-factory).

## Ordering level members

By default, members of a hierarchy are ordered:

* Alphanumerically for data with type string
* Chronologically for dates

The order of the level members affects

* the order in which the members are displayed on the dashboard.
* the level member selected for some commutations (such as lag and lead measures).

### First objects

To fix the first objects so they always appear on top, use `withFirstObjects`:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
builder.withSingleLevelDimension("Currency").withFirstObjects("USD", "EUR", "GBP");
```

### Custom comparator

To define the comparator of a specific level, use `withComparator(key)` where `key` is one of the following:

* the plugin key of a built-in comparator provided by Atoti Server, see constants defined in `IComparator`.
* the plugin key of a custom comparator implementation.

Comparator classes should implement the `IComparator` interface which wraps a `java.util.Comparator` into a plugin
value for easier configuration.
Custom comparators are typically defined as follows:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@AtotiExtendedPluginValue(key = MyComparator.PLUGIN_KEY, intf = IComparator.class)
public static class MyComparator implements IComparator<Object> {
  public static final String PLUGIN_KEY = "MyComparator";
  @Override
  public String getType() {
    return PLUGIN_KEY;
  }
  @Override
  public int compare(Object o1, Object o2) {
    // define your compare function here
    return 0;
  }
}
```

They can then be used by passing their key to the level's fluent builder:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
builder.withSingleLevelDimension("Trades").withComparator(MyComparator.PLUGIN_KEY);
```

## Member properties

Each member can have additional properties. They are not used to aggregate data but can be displayed in the UI and used
to look up a member (like an alias for example).
For more details, see the [dedicated page](member_properties)
