-
Notifications
You must be signed in to change notification settings - Fork 4
default projections
Request input/update/output projections can be specified only partially by the client (or not specified at all, in case of update/input), in which case they will be expanded to their full version by the framework.
Lets name absent or partially built projections "partial", and fully built projections "full". This document describes how and when partial projections are converted into full ones.
Expansion is performed by the projection string parser or should be explicitly performed if using projection builders (TBD). Parser creates default projections in the following situations:
- No tags are specified for an entity type, and it has no
retro
tag - No fields are specified for a record type
- Map or list item projection is not specified
The way they default projections are created depends on projection type.
Output projections are expanded based on operation projection.
Operation projection may mark certain fields and models as "include in
default" using +
flag.
For example, given the following schema
entity Person { id: Long, rec: PersonRecord }
record PersonRecord {
name: String
bestFriend: Person
worstEnemy: PersonRecord
friends: map[Long, Person]
enemies: list[Person]
}
resource me: PersonRecord {
read {
outputProjection (
+name,
bestFriend :(+id, rec(+name)),
worstEnemy (+name),
friends [] :(+id, rec(+name)),
enemies * :(+id, rec(+name))
)
}
}
a simple GET
request to /me
will be expanded into
/me(
name,
bestFriend :(id,rec(name)),
worstEnemy (name),
friends [] :(id,rec(name)),
enemies * :(id,rec(name))
)
Some default projection creation rules:
- Unspecified parameters which have default values are created based on default values
-
required
parameters without default values will cause a failure (i.e. they must be specified explicitly if corresponding projection branch is requested) -
required
map keys can't be auto-expanded and will cause a failure
Partial input and update projections get completed based on operation
input/update projection and provided update data.
Defaults are expanded in a similar way to
outut projections, but this time expansion is guided by the actual
data: only tags, fields and keys present in the data will be
reflected in auto-constructed request projection. Map keys from
the data will be put in the projection, which means that keys required
in the operation projection won't cause a failure in this case.
There are several ways a request is delivered to the operation implementation. Each of the following sections describe corresponding sequence of steps and request projection transformations
-
OperationRequest
with full projections is constructed- By either parsing projection strings, with parser performing the expansion
- Or by using projection builders, with explicit calls to create default projections
-
LocalOperationInvocation
delivers request to operation implementation- optionally invocation is transformed using
OperationFilterChains.defaultFilterChains()
to perform usual request validation and response data pruning
- optionally invocation is transformed using
- On the wire: partial projections in the URL + data in the body
- data is deserialized using operation input/update projection
- partial request output projection is expanded by request parser based on operation output projection
- partial request input/update projection is expanded by request parser based on operation input/update projection and data
- full projections are used to construct
OperationRequest
instance - rest as in Local operation invocation
-
OperationRequest
with full projections is constructed as in Local operation invocation -
*RemoteOperationInvocation
sends HTTP request using full projections and data from theOperationRequest
. Data is serialized using full input/update request projection - rest as in HTTP call
Notes:
-
OperationRequest
always contains fully expanded projections - projections may be partial on the wire, to make life easier for non-native epigraph clients