# Struktura modelu danych

## Struktura drzewa

{% columns %}
{% column %}
Model danych ma strukturę drzewa ułatwiającą odwzorowanie hierarchicznej struktury obiektów domeny biznesowej.

**Liście** drzewa reprezentują najbardziej szczegółowy element struktury. Liście, zwane polami, nie posiadają już żadnych innych elementów podrzędnych (dzieci) i reprezentują pojedyncze pole danych. Przykładami mogą być "imię klienta" czy "numer rachunku bankowego".

**Węzły** drzewa reprezentują obiekty złożone z innych obiektów i/lub pól. Przykłady: "adres korespondencyjny", "dochód klienta".
{% endcolumn %}

{% column %}

<figure><img src="https://1082717226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2CssJT0zIo4SJQLbSZ6l%2Fuploads%2FpN14hRagp8jodNrtEt5Q%2Ftree_structure.png?alt=media&#x26;token=512337b9-4e0e-4ad3-982f-cbc14fff00f3" alt="" width="216"><figcaption><p><em><strong>Ilustracja 1.</strong> Struktura drzewa</em></p></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

### Węzły

Każdy węzeł modelu danych posiada atrybuty:

* klucz unikalny wśród swojego rodzeństwa (potomków tego samego węzła)
* liczebność wyrażoną wzorem `n..m` oznaczającym od `n` wystąpień minimalnie do `m` maksymalnie, np:
  * `1..1` - obiekt występuje tylko raz
  * `0..1` - obiekt jest opcjonalny
  * `1..null` - obiekt występuje co najmniej raz, bez ograniczenia na maksymalną liczbę wystąpień
* opis znaczenia obiektu dla aplikacji

{% hint style="info" %}
Węzły można zatem jednoznacznie wskazać za pomocą klucza powstałego poprzez złączenie kluczy węzłów nadrzędnych, np: `client.email`.
{% endhint %}

### Liście

Poza atrybutami węzłów, liście posiadają dodatkowo:

* źródła danych - określają jak i skąd pobierana jest wartość
* domyślna wartość - co zwróci pole, jeżeli żadne ze źródeł danych nie zwróci wartości

Pole może mieć zdefiniowaną listę źródeł danych. Rozstrzyganie wartości pola polega na wywoływaniu źródeł danych w kolejności ich zdefiniowania aż do uzyskania niepustej wartości. Zatem pierwsze źródło zwracające niepustą wartość wygrywa.

Dane z modelu możemy pobierać tylko dla wybranych przez nas pojedynczych kluczy, tj. nie możemy pobierać wartości kluczy, które mają pod sobą dzieci, tak jak nie możemy pobrać całego modelu w jednym zapytaniu.

## Tablice w modelu danych <a href="#strukturamodeludanychbudowanieiuzywanie-definiowanietablicowychpolmodeludanych" id="strukturamodeludanychbudowanieiuzywanie-definiowanietablicowychpolmodeludanych"></a>

Węzły modelu oznaczone jako wielokrotne (liczebność maksymalna `>1`) tworzą tablicę prostych wartości (dla pól) oraz złożonych obiektów (dla węzłów nie będących liśćmi). Możliwe jest również zdefiniowanie kolekcji zagnieżdżonych.

### Klucze i identyfikatory <a href="#strukturamodeludanychbudowanieiuzywanie-kluczeiidentyfikatory" id="strukturamodeludanychbudowanieiuzywanie-kluczeiidentyfikatory"></a>

Odwołując się do węzłów modelu danych zdefiniowanych jako tablica (lub będącymi potomkami tablicy) należy zawsze używać notacji tablicowej:

* tablica\[].pole - pobiera wszystkie wystąpienia pola; zależnie od używanego API zwróci kolekcję lub pojedynczy string z separatorem ","
* tablica\[0].pole - pobierze pojedynczą wartość rozwiązaną wierszem kolekcji wskazanym w kluczu (w przykładzie 0 oznacza pierwszy element tablicy),
* tablica.pole - spowoduje błąd, nie ma możliwości odniesienia się do tablicowego węzła bez notacji tablicy,

### Definiowanie tablicy <a href="#strukturamodeludanychbudowanieiuzywanie-definiowanietablicywmodeludanych" id="strukturamodeludanychbudowanieiuzywanie-definiowanietablicywmodeludanych"></a>

W celu zdefiniowania tablicowego pola konieczne jest:

* wielokrotny węzeł modelu danych musi posiadać krotność większą niż `multiplicityMax=1`, np. `1..null`,
* wielokrotny węzeł modelu danych musi mieć zdefiniowane źródła wskazujące na tablicę, indeksy tej kolekcji zostaną użyte do indeksacji powtórzeń wartości modelu,
* węzły poniżej wielokrotnego węzła modelu danych mogą w mapowaniu stosować indeks iterowanego węzła modelu do wskazania konkretnych elementów wyjścia usługi,
  * nadrzędny węzeł zawsze udostępni w kontekście wykonania swój bieżący indeks (w trakcie rozwiązywania wartości dla kolekcji) pod identyfikatorem *`nazwaWezłaIdx`,*
  * pola iterowane rodzicem powinny wskazywać na obiekty wewnątrz kolekcji, po której iteruje rodzic,
  * nie jest to jednak stricte konieczne, możliwe jest wykorzystanie tego indeksu do iterowania po zupełnie innym polu lub do wyciągania pól w ogóle nie będących tablicami.

{% hint style="info" %}
Przykładowo, mając wynik usługi, który składa się ze stałego pola i dwóch tablic - o których wiadomo, że mają tę samą długość (tablicaA, tablicaB, poleC) - możliwe jest stworzenie mapowania, w którym model iteruje po tablicyA, ale jego podpola wyciągają kolejne pola tablicyB i stałą wartość z polaC.
{% endhint %}

## Powiązanie providera z modelem danych

Provider to lokalne źródło danych napisane w [ScriptCode](https://docs.eximee.com/budowanie-aplikacji/logika-biznesowa/scriptcode/wprowadzenie-do-scriptcode), które definiuje sposób pozyskiwania wartości dla pól modelu. Może być wykorzystywane przez pola do zasilania ich watości. Źródłem danych może być funkcja:

* skryptowa,
* wywołująca zewnętrzną usługę REST,
* odwołująca się do innego elementu modelu,
* pobierająca wartość z konfiguracji aplikacji.

Opisany poniżej provider stanowi **źródło danych dla liścia modelu danych**. Służy ono do pobrania aktualnego kursu waluty z zewnętrznego API (NBP):

* `exchangeRate` jest **liściem (polem)** w drzewie,
* pole to nie posiada dzieci i reprezentuje pojedynczą wartość (kurs waluty),
* może być zagnieżdżone w węźle, np.: `exchangeRates.exchangeRateEUR`.

<figure><img src="https://1082717226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2CssJT0zIo4SJQLbSZ6l%2Fuploads%2Fgit-blob-74883de5f437263604a380103f4f7162dfe2e315%2FkodProvidera.png?alt=media" alt="przykład z kodem providera"><figcaption><p><em><strong>Ilustracja 2.</strong> Przykład providera pobierającego aktualny kurs waluty z API (NBP)</em></p></figcaption></figure>

Przebieg działania:

* z parametrów wejściowych providera pobierany jest klucz, czyli kod waluty (`currencyCode`), np. „EUR” lub „USD”,
* wartość ta jest przekazywana do providera z modelu danych,
* provider wykonuje zapytanie GET do skonfigurowanego endpointu `nbpExchangeRate` przy użyciu `api.rest.v1.get`,
* parametry ścieżki (`pathParams`) budują adres zapytania w postaci: `/rates/A/{currencyCode}` (litera „A” oznacza tabelę średnich kursów walut publikowanych przez NBP),
* odpowiedź z API zawiera obiekt `body`, w którym znajduje się tablica `rates`, a z tablicy pobierany jest pierwszy element (`rates[0]`), następnie jego pole `mid`, które reprezentuje średni kurs waluty,
* provider zwraca obiekt zawierający pole `exchangeRate`, wartość tego pola odpowiada pobranemu kursowi waluty i może być dalej wykorzystana w modelu danych lub formularzu.

### Konfiguracja źródeł danych dla pola

Każde pole w modelu danych posiada możliwość zdefiniowania **źródeł danych**.\
Konfiguracja dostępna jest po kliknięciu ikony ołówka przy wybranym polu, co otwiera szufladę ustawień źródeł danych powiązanych z tym polem. Jeżeli dla danego klucza zostały już zdefiniowane źródła danych, ich nazwy są widoczne w panelu - w przedstawionym przykładzie jest to `exchangeRateFromNBPProvider`. Po wybraniu źródła możliwa jest konfiguracja parametrów wejściowych oraz mapowania wyjścia.

<figure><img src="https://1082717226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2CssJT0zIo4SJQLbSZ6l%2Fuploads%2Fgit-blob-a86d2faadc46924920ac10b4eee1c1654cadf497%2FzrodlaDanychParametryMapowanie.png?alt=media" alt="przykład z kodem providera"><figcaption><p><em><strong>Ilustracja 3.</strong> Przykład wykorzystania providera jako źródła danych w modelu</em></p></figcaption></figure>

W zakładce **Parametry** definiowane są wartości przekazywane do providera.\
W opisywanym przypadku:

* klucz: `currencyCode`
* wartość: `EUR`

Parametr ten jest wykorzystywany przez provider do wywołania zewnętrznego API.

W sekcji **Mapowanie** określane jest, które dane z odpowiedzi providera zostaną przypisane do pola w modelu. W tym przykładzie mapowana jest wartość `exchangeRate`.

Uzyskana wartość może być następnie wykorzystana w modelu danych lub bezpośrednio w formularzu. Więcej o wykorzystaniu modelu danych na wniosku w zakładce [Model danych na interfejsie](https://docs.eximee.com/~/revisions/6RARJsssdz6tDsOideLu/budowanie-aplikacji/interfejs-uzytkownika/formularze/praca-z-komponentami-bazowymi/model-danych-na-interfejsie).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.eximee.com/budowanie-aplikacji/model-danych/struktura-modelu-danych.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
