=== Value API

The javadoc:Value[Value] is an unified and type-safe API across all parameter types:

- <<http-header, Header>>
- <<path, Path>>
- <<query, Query>>
- <<formdata, Formdata>>
- <<multipart, Multipart>> 

For learning purpose we are going to show all the javadoc:Value[Value] features using query
parameters, but keep in mind these features apply to all the parameter types.

==== Single value

Single value is available via `value()` or `[type]Value()` functions: 

.Java
[source, java, role="primary"]
----
{
  get("/", ctx -> {
    String name = ctx.query("name").value();                          // <1>

    float score = ctx.query("score").floatValue();                    // <2>

    boolean enabled = ctx.query("enabled").booleanValue();            // <3>
    
    BigDecimal decimal = ctx.query("decimal").value(BigDecimal::new); // <4>
    ...
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  get("/") {
    val name = ctx.query("name").value()                     // <1>

    val score = ctx.query("score").floatValue()              // <2>

    val enabled = ctx.query("enabled").booleanValue()        // <3>
    
    val decimal = ctx.query("decimal").value(::BigDecimal)   // <4>
    ...
  });
}
----

The `value()` family methods always retrieve a `value`. If there is no value, a
`BadRequest(400)` response is generated. So single value parameters *are required*: 

<1> Access to query parameter `q` and convert to `String`:

- `/?name=foo` => `foo`
- `/`          => `Bad Request(400): Missing value: "q"`

<2> Access to query parameter `score` and convert to `float`:

- `/?score=1`      => `1.0`
- `/?score=string` => `Bad Request(400)` (Type mismatch: cannot convert to number)
- `/`              => `Bad Request(400)` (Required parameter `score` is not present)

<3> Access to query parameter `enabled` and convert to `boolean`:

- `/?enabled=true`   => `true`
- `/?enabled=string` => `Bad Request(400)` (Type mismatch: cannot convert to boolean)
- `/`                => `Bad Request(400): Missing value: "enabled"`

<4> Access to query parameter `decimal` and convert to `BigDecimal`:

- `/?decimal=2.3`    => `2.3`
- `/?decimal=string` => `Bad Request(400)` (Type mismatch: cannot convert to BigDecimal)
- `/`                => `Bad Request(400): Missing value: "decimal"`

==== Default and Optional value

Default and optional value are available in two different ways:

- Providing a default value
- Requesting an `java.util.Optional` object

.Java
[source, java,role="primary"]
----
{
  get("/search", ctx -> {
    String q = ctx.query("q").value("*:*");             // <1>
    return q;
  });

  get("/search", ctx -> {
    Optional<String> q = ctx.query("q").toOptional();   // <2>
    return q;
  });
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
{
  get("/search") {
    val q = ctx.query("q").value("*:*")    // <1>
    q
  });

  get("/search") {
    val q = ctx.query("q").toOptional();   // <2>
    q
  });
}
----

<1> Access to query variable `q` and convert to `String` with a default value of `*:*`.

- `/search?q=foo` => `foo`
- `/search`       => `*:*`

<2> Access to query variable `q` and convert to `Optional<String>`:

- `/search?q=foo` => `Optional[foo]`
- `/search`       => `Optional.empty`

==== Multiple values

Multiple values are available via functions:

- javadoc:Value[toList]: Returns a `java.util.List` of values
- javadoc:Value[toSet]: Returns a `java.util.Set` of values

.Java
[source, java,role="primary"]
----
{
  get("/", ctx -> {
    List<String> q = ctx.query("q").toList();                            // <1>

    List<Integer> n = ctx.query("n").toList(Integer.class);              // <2>

    List<BigDecimal> decimals = ctx.query("d").toList(BigDecimal::new);  // <3>

    ...
  });
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
{
  get("/") {
    val q = ctx.query("q").toList()                     // <1>

    val n = ctx.query("n").toList(Integer.class)        // <2>

    val decimals = ctx.query("d").toList(::BigDecimal)  // <3>

    ...
  });
}
----

<1> Multi-value query parameter `q` as `List<String>`:

- `/`             => `[]` (empty list)
- `/?q=foo`       => `[foo]`
- `/?q=foo&q=bar` => `[foo, bar]`

<2> Multi-value query parameter as `List<Integer>`

- `/`         => `[]` (empty list)
- `/?n=1`     => `[1]`
- `/?n=1&n=2` => `[1, 2]`

<3> Multi-value query parameter as `List<BigDecimal>`

- `/`         => `[]` (empty list)
- `/?d=1`     => `[1]`
- `/?d=1&n=2` => `[1, 2]`

==== Structured data

The javadoc:Value[Value API] provides a way to traverse and parse structured data:

----
/?user.name=root&user.pass=pass
----

.Traversal
[source, java, role="primary"]
----
{
  get("/", ctx -> {
    Value user = ctx.query("user");                  // <1>
    String name  = user.get("name").value();         // <2>
    String pass  = user.get("pass").value();         // <3>
    String email = user.get("email").value("none");  // <4>
    ...
  }}
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  get("/") {
    val user = ctx.query("user")              // <1>
    val name  = user["name"].value()          // <2>
    val pass  = user["pass"].value()          // <3>
    val email = user["email"].value("none")   // <4>
    ...
  }}
}
----

<1> Get the `user` node
<2> Get the `name` value from `user` node
<3> Get the `pass` value from `user` node
<4> Get the `email` value from `user` node. This is an optional value.

The javadoc:Value[get, java.lang.String] takes a `path` and returns another value. The returning
value may or may not exists.

===== Syntax

Structured data decoder supports `dot` and `bracket` notation:

.Dot notation
----
?member.firstname=Pedro&member.lastname=Picapiedra
----

.Bracket object notation
----
?member[firstname]=Pedro&member[lastname]=Picapiedra
----

.Bracket array notation for tabular data
----
?members[0]firstname=Pedro&members[0]lastname=Picapiedra
----

===== POJO

Structured data decoder is able to reconstruct a POJO (Plain Old Java Object) from:

- <<query, Query>> encoded as https://tools.ietf.org/html/rfc3986#section-2[RFC 3986]
- <<formdata, Formdata>> encoded as `application/x-www-form-urlencoded`
- <<multipart, Multipart>> encoded as `multipart/form-data`

We are going to use a `Group` and `Member` objects to demonstrate how the decoder works:

.Example
[source, java, role="primary"]
----
class Member {
  public final String firstname;
  public final String lastName;

  public Member(String firstname, String lastname) {
    this.firstname = firstname;
    this.lastname = lastname;
  }
}

class Group {
  public final String id;
  public final List<Member> members;

  public Member(String id, List<Member> members) {
    this.id = id;
    this.members = members;
  }
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
class Member (val firstname: String, lastName: String)

class Group (val id: String, val members: List<Member>)
----

.Member parsing example:
----
/?firstname=Pedro&lastName=Picapiedra
----

.Java
[source, java,role="primary"]
----
{
  get("/", ctx -> {
    Member member = ctx.query(Member.class);
    ...
  });
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
{
  get("/") {
    val member = ctx.query<Member>()
    ...
  }
}
----

.Member parsing example from base node:
----
/?member.firstname=Pedro&member.lastName=Picapiedra
----

.Java
[source, java,role="primary"]
----
{
  get("/", ctx -> {
    Member member = ctx.query("member").to(Member.class);
    ...
  });
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
{
  get("/") {
    val member = ctx.query("member").to<Member>()
    ...
  });
}
----

Tabular data uses the bracket array notation:

.Member as tabular data:
----
/?[0]firstname=Pedro&[0]lastName=Picapiedra&[1]firstname=Pablo&[2]lastname=Marmol
----

.Java
[source, java,role="primary"]
----
{
  get("/", ctx -> {
    List<Member> members = ctx.query().toList(Member.class);
    ...
  });
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
{
  get("/") {
    val members = ctx.query<List<Member>>()
    ...
  });
}
----

.Group with members as tabular data:
----
/?id=flintstones&members[0]firstname=Pedro&members[0]lastName=Picapiedra
----

.Java
[source, java,role="primary"]
----
{
  get("/", ctx -> {
    Group group = ctx.query(Group.class);
    ...
  });
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
{
  get("/") {
    val group = ctx.query<Group>()
    ...
  });
}
----

The target `POJO` must follow one of these rules:

- Has a zero argguments/default constructor, or
- Has only one constructor
- Has multiple constructors, but only one is annotated with 
https://static.javadoc.io/javax.inject/javax.inject/1/javax/inject/Inject.html[Inject]

The decoder matches HTTP parameters in the following order:

- As constructor arguments
- As setter method

HTTP parameter name which are not a valid Java identifier must be annotated with https://static.javadoc.io/javax.inject/javax.inject/1/javax/inject/Named.html[Named]:

.Java
[source, java,role="primary"]
----
class Member {
  public final String firstname;
  
  public final String lastname;
  
  public Member(@Named("first-name") String firstname, @Named("last-name") String lastname) {
    ....
  }
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
class Member (@Named("first-name") val firstname: String, @Named("last-name") val lastName: String)
----

{love}{love}
