Entity Layout Framework
Entity Layout Framework is a lightweight protocol for defining structured data types, intended to be used across different implementations of Eventsourcing and other software.
Copyright (c) 2016 Yurii Rashkovskii
This Specification is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
This Specification is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, see http://www.gnu.org/licenses.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
- To define basic data structures
- To eliminate a class of errors related to mismanaged data structures versioning
1. Data Types
Although this specification allows for defining an arbitrary number of custom types, there's a set of standard types that MUST be supported by every implementation that aims to conform to this specification.
No data type supports
null values. An implementation MAY coerce null values
to suggested default values.
BigDecimal is an arbitrary-precision signed decimal numbers. It consists of an arbitrary precision integer (unscaled value) and a 32-bit integer (scale).
If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. The value of the number represented is therefore
(unscaledValue * 10^-scale). This definition
mirrors the definition of Java's BigDecimal.
BigDecimal is an arbitrary precision integer.
ByteArray is an array of bytes.
Default value: empty array.
Default value: empty string
Default value: January 1, 1970, 00:00:00 GMT
List is a parametrized type and can take any other type as a parameter.
Default value: empty list
Optional is a type that signifies a value that might be either present or not.
Optional is a parametrized type and can take any other type as a parameter.
Default value: value not present
Enum represents a type with a closed set of possible ordinal (integer) values (for example,
OPEN = 0, CLOSED = 1). The ordinal values MUST start with 0
and form a consecutive sequence.
Default value: smallest ordinal value (0).
Map represents a collection of (key, value) pairs, such that each possible key appears at most once in the collection.
Default value: an empty map.
See 3. Object for the definition.
Object is represented as a sequence of all its (lexicographically sorted) properties representations.
Fingerprinting is a technique that gives a specific, byte-to-byte representation of type information. Every fingerprint is a sequence of bytes that MUST uniquely represents the data type.
It is RECOMMENDED that a human readable, latin1 encoded name is specified for types to avoid decentralized allocation problem. However, this is not a requirement but a suggestion, followed by standard types defined in this specification.
|Type||Fingerprint (hex)||Fingerprint (Human-readable)|
|List||0x4c6973745b + ? + 5d||List[?]|
|Optional||0x4f7074696f6e616c5b + ? + 5d||Optional[?]|
|Enum||0x456e756d5b + ? + 5d||Enum[?], where ? takes a form of NAME:ORDINAL[,...]. For example,
|Map||0x4d61705b + ? + 5d5b + ? + 5d||Map[?][?]|
|Entity Layout||?||Layout fingerprint (bytes)|
Object is a data type that consists of its own name and number of typed and named properties. Typically, this would be a a class or a record.
All entity's properties MUST be sorted lexicographically. This enforces the following:
- Actual entity deserialization happens without the knowledge of order of supplied properties and always follows the same order across implementations, allowing to avoid supplying property sequence number or type information.
- Fingerprints are always the same regardless of the order of supplied properties, producing a consistent versioning artifact (see 3.1.)
Entity layout fingerprint is formed by following the following procedure:
- Create a hasher (using hashing algorithm as defined in 5.1.)
- Update the hasher with the type name, serialized as UTF-8.
- For every property,
- update the hasher with the property name, serialized as UTF-8.
- update the hasher with the property type's fingerprint.
The resulting hash is used as a fingerprint of the entity layout.
Entity is a top-level object that can be recorded by Eventsourcing. Every entity MUST have the following base layout:
Any recorded entity MUST be identified with a UUID. UUID does not become a part of its layout.
There are two types of entities.
This entity type represents a request for changes.
This entity type represents a statement of fact.
5.1. Hashing Algorithm
This specification defines hashing algorithm as SHA-1.