# `Statifier.EventData`
[🔗](https://github.com/riddler/statifier-ex/blob/v2.0.0/lib/statifier/event_data.ex#L1)

`docs/datamodel.md`'s standing commitment discharged: one function, with
defined rules, that normalizes a value into `_event.data` per spec
B.2.8.1. `<param>` and `<content>` (under `<donedata>`) call it here;
`namelist`, `<send>`, and `<invoke>` extend it rather than reinventing it
when they land.

B.2.8.1's own ladder, and which rungs this function implements:

> If the value is not already in the indicated format, the Processor
> SHOULD convert it to the indicated format. ... If the data consists
> unambiguously of key/value pairs (e.g., the params of a <send> element,
> or the fields of an HTML form), the Processor MUST convert this data to
> a set of key/value pairs, ... If the Processor supports JSON [RFC4627],
> and the data is a well-formed JSON expression, the Processor MUST parse
> it into a data structure ... If the data is a well-formed external
> parsed entity, and the Processor supports XML, the Processor MUST parse
> it into a DOM document ... Otherwise, the Processor MUST treat the data
> as a space-normalized string.

| B.2.8.1 rung | Implemented here? |
|---|---|
| Indicated format (SHOULD) | No - no content-type channel exists yet. |
| Key-value pairs (MUST) | Yes - the `{:params, pairs}` arm. |
| JSON (MUST, if supported) | Substituted by a predicator literal-parse rung: this engine's value space is predicator's (ADR-0004), not ECMAScript's/JSON's, so the same ground (numbers, booleans, strings, lists, maps) is covered without a JSON dependency. |
| XML DOM (MUST, if interpretable as XML) | No - `Statifier.Document.Content`'s moduledoc already rejects carrying a DOM subtree in a `Document` struct. |
| Space-normalized string literal (MUST) | Yes - the fallback. |

**Duplicate `<param>` keys.** B.2.8.1: "In the case of duplicate keys, the
behavior is platform-specific." This project's call: fold in document
order with `Map.put` semantics, so the last occurrence of a duplicate
name wins - the same resolution an ECMAScript object literal gives
duplicate properties, and what a left-to-right fold produces with no
extra machinery.

**`:undefined` versus `nil`.** An empty rung - no `<content>` text, no
`<param>` pairs - returns `:undefined`: "no data", per
`docs/adr/0037-unbound-spelled-undefined-at-the-writer.md`. A genuinely
null *value* (`<content>null</content>`, `<param expr="null"/>`) returns
`nil`, predicator's own null, unchanged. The two are now distinguishable
end to end, all the way through `Evaluator.bind/3` and into `_event.data`.

# `input`

```elixir
@type input() ::
  {:value, term()} | {:text, String.t()} | {:params, [{String.t(), term()}]}
```

The three shapes a caller hands to `coerce/1`: an already-evaluated
value (never re-interpreted as text), raw `<content>` text (parsed or
space-normalized), or a `<param>` name/value list (folded into a map).

# `coerce`

```elixir
@spec coerce(input :: input()) :: term()
```

Normalizes `input` into an `_event.data` value per B.2.8.1, as detailed
in the moduledoc above.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
