Jev Query
A reusable set of questions declared as properties; each property name becomes the question id.
object Triage : JevQuery() {
val urgent by noul("Does this message convey urgency?")
val department by choice<Dept>("Which team should handle this?")
}
val result = jev.ask(Triage, state = ticket)
result[Triage.department].choiceQuestions are validated the first time questions is used, so an invalid definition fails on first use, with a JevValidationException, rather than from the object's initializer. That covers a problem found while a question is built too, such as an unsupported value passed to entry() in a Choice's options or in an enum option's JevOption.entry. An argument is evaluated before the builder runs, though, so a failing entry() or jsonEntry() passed as the instructions still throws from the initializer.
questions can be read once the first question has registered. A read before every property is initialized, from an init block or a base class, sees only the questions declared so far; the next read includes the rest. A read before any question has registered, such as from the init block of a base class with no questions of its own, fails with a JevValidationException, since a set needs at least one question.
The builders take the instructions first and an optional id second, the reverse of the inline QueryBuilder's (id, instructions). Both are strings, so pass id by name (noul("Is this urgent?", id = "urgent")): a question moved from an inline query with its arguments unchanged would otherwise compile and send its id as the instructions.
Properties
The declared questions, in declaration order (base-class questions first), with the images attached.
Functions
Attaches image to every request that asks these questions, and returns it, so a picture can be declared and attached at once: private val thumb = attach(JevImage.of(thumbBytes)). Reading a file here, with JevImage.read, does I/O in the object's initializer, and a missing file makes the object unusable: on the JVM its first use throws ExceptionInInitializerError, and every later use NoClassDefFoundError.
A Box: where, in an image attached to the request, the thing instructions describes is. Needs Jev 1.14.