Utility functions
In order to ease the programmer of writing many redundant code, the library provides a lot of utility functions to deal with fields in the smoothest way possible. Most of theses functions are extension functions on fields of a specific type. While they are mainly a kotlin feature, it's still possible to call them in Java™ code through a static method, but it's a bit cumbersome. For this reason, it is suggested to use kotlin as much possible.
Most functions divide in two categories:
- Transformations: they provide default implementations for either one-way or two-way transformation of fields.
- Setters: available only on mutable fields, they easily allow to change the content of the field.
A thing to keep in mind is that the Field
class is declared as Field<out T>
, so any extension function of Field<A>
will also be present in Field<B : A>
, so for instance all extension functions of a Field<Collection>
can also be called in a Field<List>
, Field<Set>
and so on. The same thing does not hold for mutable fields.
Furthermore, some functions have been implemented with operator overloading or with infix notation so, additionally to the standard way, they can also be called with their specific syntax.
All these functions can be called in java code statically on their respective utils class. For extension functions the first parameter must always be the field you would call the function on in kotlin followed by the rest of the parameters. The utils class name is always FieldUtils
prefixed with the name of the type contained in the field (e.g. for booleans it's BooleanFieldUtils
).
Example:
Here you can find a non-exhaustive list of extension functions. For the complete list as well as a complete description of what they do, please visit the specific page of the documentation.
In the following examples all fields starting with f
(f
, f1
, f2
, etc.) are simple Field
, while all fields starting with mf
(mf
, mf1
, mf2
, etc.) are MutableField
.
//Transformations
val f1 : Field<T>? = ...
f1.orValue(v) //Yields f1 if f1 is not null, otherwise a constant field containing v
f1.orNull() //Yields f1 if f1 is not null, otherwise a constant field containing null
val f2 : Field<Field<T>> = ...
f2.reduce() //Yields a Field<T> representing the value of the innermost field
val f3 : Field<T?> = ...
f3.notNull(v) //Yields a Field<T> cotaining the value of f3 if this value is not null, otherwise v
val f4 : Field<T> = ...
f3 eq f4 //Yields a Field<Boolean> that is true if the values of f3 and f4 are equals()
f4 eq v //Yields a Field<Boolean> that is true if the value of f3 and v are equals()
f3 neq f4 //Yields a Field<Boolean> that is true if the values of f3 and f4 are NOT equals()
//Transformations
Field<T> f1 = ...; //f1 can be null
FieldUtils.orValue(f, v); //Yields f1 if f1 is not null, otherwise a constant field containing v
FieldUtils.orNull(f); //Yields f1 if f1 is not null, otherwise a constant field containing null
Field<Field<T>> f2 = ...;
FieldUtils.reduce(f2) //Yields a Field<T> representing the value of the innermost field
Field<T> f3 = ...; //the value contained by f3 can be null
f3.notNull(v) //Yields a Field<T> cotaining the value of f3 if this value is not null, otherwise v
Field<T> f4 = ...;
FieldUtils.eq(f3, f4); //Yields a Field<Boolean> that is true if the values of f3 and f4 are equals()
FieldUtils.eq(f4, v); //Yields a Field<Boolean> that is true if the value of f4 and v are equals()
FieldUtils.neq(f3, f4); //Yields a Field<Boolean> that is true if the values of f3 and f4 are NOT equals()
//Transformations
f.not()
f1 and f2 //Also or and xor
//Setters
mf.toggle()
//Transformations
BooleanFieldUtils.not(f);
BooleanFieldUtils.and(f1, f2); //Also or and xor
//Setters
BooleanFieldUtils.toggle(mf);
//Transformations
(((f1 + 5) / 4) % -f2) * 17 //All operations between two Int fields or a field and an Int
f.abs() //Absolute value
min(f, 5) //min and max between two Int fields or a field and an Int
f.toLong() //Convert to long, float and double
//Setters
mf.increment() //Also decrement()
mf.negate()
//Transformations
IntFieldUtils.times(IntFieldUtils.rem(IntFieldUtils.div(IntFieldUtils.plus(f1, 5), 4), IntFieldUtils.unaryMinus(f2)), 17); //All operations between two Integer fields or a field and an Integer. Since in java it's particularly verbose, in this case it is probably better using the transform() function manually
IntFieldUtils.abs(f) //Absolute value
IntFieldUtils.min(f, 5) //min and max between two Integer fields or a field and an Integer
IntFieldUtils.toLong(f) //Convert to long, float and double
//Setters
IntFieldUtils.increment(mf); //Also decrement()
IntFieldUtils.negate(mf);
The same functions that are available on Int
fields are also available on Long
fields with the appropriate modifications.
//Transformations
(((f1 + 5f) / 4f) % -f2) * 17f //All operations between two Float fields or a field and a Float
f1.pow(f2) //f1 elevated to the power of f2
sin(f3) //Sin of f3
f4.roundToLong() //f4 rounded to Long
//Setters
mf.increment(1.5f) //Also decrement()
mf.negate()
//Transformations
FloatFieldUtils.times(FloatFieldUtils.rem(FloatFieldUtils.div(FloatFieldUtils.plus(f1, 5f), 4f), FloatFieldUtils.unaryMinus(f2)), 17f); //All operations between two Float fields or a field and an Float. Since in java it's particularly verbose, in this case it is probably better using the transform() function manually
FloatFieldUtils.pow(f1, f2) //f1 elevated to the power of f2
FloatFieldUtils.sin(f3) //Sin of f3
FloatFieldUtils.roundToLong(f4) //f4 rounded to Long
//Setters
FloatFieldUtils.increment(mf, 1.5f); //Also decrement()
FloatFieldUtils.negate(mf);
The same functions that are available on Float
fields are also available on Double
fields with the appropriate modifications.
//Transformations
f1 + " world" //Concatenates the strings
f1 + f2 //Concatenates the strings
//Transformations
StringFieldUtils.concatenate(f1, " world"); //Concatenates the strings
StringFieldUtils.concatenate(f1, f2); //Concatenates the strings
//Transformations
f.length() //Yields a Field<Int> containing the length of the CharSequence
//Transformations
CharSequenceFieldUtils.length(f) //Yields a Field<Integer> containing the length of the CharSequence
//Transformations
f.first() //Yields a Field<T> containing the first element of the pair in f
f.second() //Yields a Field<T> containing the second element of the pair in f
//Transformations
PairFieldUtils.first(f); //Yields a Field<T> containing the first element of the pair in f
PairFieldUtils.second(f); //Yields a Field<T> containing the second element of the pair in f
//Transformations
f.first() //Yields a Field<T> containing the first element of the triple in f
f.second() //Yields a Field<T> containing the second element of the triple in f
f.third() //Yields a Field<T> containing the third element of the triple in f
//Transformations
TripleFieldUtils.first(f); //Yields a Field<T> containing the first element of the triple in f
TripleFieldUtils.second(f); //Yields a Field<T> containing the second element of the triple in f
TripleFieldUtils.third(f); //Yields a Field<T> containing the third element of the triple in f
//Transformations
f1 gt f2 //Yields a Field<Boolean> that is true when f1 > f2
f2 lte 5 //Yields a Field<Boolean> that is true when f2 <= 5
4 gte f3 //Yields a Field<Boolean> that is true when 4 >= f3
//Transformations
ComparableFieldUtils.gt(f1, f2); //Yields a Field<Boolean> that is true when f1 > f2
ComparableFieldUtils.lte(f2, 5); //Yields a Field<Boolean> that is true when f2 <= 5
ComparableFieldUtils.get(4, f3); //Yields a Field<Boolean> that is true when 4 >= f3
//Transformations
f.isEmpty() //Yields a Field<Boolean> that is true when the content of f is empty
f.size() //Yields a Field<Int> that contains the size of the collection contained in f
//Setters
mf.add(x) //Creates a new immutable collection consisting of the collection in f appended with x, then sets it to the field
mf.remove(y) //Creates a new immutable collection consisting of the collection in f without y, then sets it to the field
//Transformations
CollectionFieldUtils.isEmpty(f); //Yields a Field<Boolean> that is true when the content of f is empty
CollectionFieldUtils.size(f); //Yields a Field<Integer> that contains the size of the collection contained in f
//Setters
CollectionFieldUtils.add(f, x); /Creates a new immutable collection consisting of the collection in f appended with x, then sets it to the field
CollectionFieldUtils.remove(f, y); //Creates a new immutable collection consisting of the collection in f without y, then sets it to the field
Nearly all the extension functions of collections of Kotlin™ are available as an utility transformation function in Dataflow. A complete list can be found in the Kotlin documentation.
Most common ways of changing a collection are available but be careful! Each change you perform will create a new immutable list and discard the previous one, so you should consider every operation Ω(n)
with respect to the collection size. The reason for this behavior is explained in detail in the section Restrictions on field values.
//Transformations
f.contains(x) //Yields a Field<Boolean> that is true when the x is contained in the field
f.filter(/* predicate */) //Yields a Field<Iterable<T>> that contains the values in f that match the predicate
f.min() //Available on field of Iterable of numbers and Comparable, yields a Field<T> containing the min value (Also max())
//Transformations
IterableFieldUtils.contains(f, x) //Yields a Field<Boolean> that is true when the x is contained in the field
IterableFieldUtils.filter(f, /* predicate */) //Yields a Field<Iterable<T>> that contains the values in f that match the predicate
IterableFieldUtils.min(f); //Available on numbers and Comparable, yields a Field<T> containing the min value (Also max())
Nearly all the extension functions of iterables of Kotlin™ are available as an utility transformation function in Dataflow. A complete list can be found in the Kotlin documentation.
//Transformations
f.firstOrNull(x) //Yields a Field<T> that contains the first element of the list in f, or null if it doens't exist
//Setters
mf.add(x) //Creates a new immutable list consisting of the list in f appended with x, then sets this list to the field
mf.shuffle() //Creates a new immutable list with the same elements of the old one shuffled, then sets this list to the field
//Transformations
ListFieldUtils.firstOrNull(f, x) //Yields a Field<T> that contains the first element of the list in f, or null if it doens't exist
//Setters
ListFieldUtils.add(mf, x); //Creates a new immutable list consisting of the list in f appended with x, then sets this list to the field
ListFieldUtils.shuffle(mf); //Creates a new immutable list with the same elements of the old one shuffled, then sets this list to the field
Nearly all the extension functions of lists of Kotlin™ are available as an utility transformation function in Dataflow. A complete list can be found in the Kotlin documentation.
Most common ways of changing a list are available but be careful! Each change you perform will create a new immutable list and discard the previous one, so you should consider every operation Ω(n)
with respect to the list size. The reason for this behavior is explained in detail in the section Restrictions on field values.
//Setters
mf.add(x) //Creates a new immutable set consisting of the set in f appended with x, then sets it to the field
mf.clear() //Creates a new immutable empty set and sets to the field
//Setters
SetFieldUtils..add(mf, x); //Creates a new immutable set consisting of the set in f appended with x, then sets it to the field
SetFieldUtils.clear(mf); //Creates a new immutable empty set and sets to the field
//Transformations
f.keys() //Yields a Field<Set<K>> that contains the keys of the map in f
f.count { /* predicate */ } //Yields a Field<Int> that contains the number of entries that satisfy the predicate
//Setters
mf.put(v1, v2) //Creates a new immutable map consisting of the map in f with the mapping (v1)=>(v2) added, then sets it to the field
//Transformations
MapFieldUtils.keys(f); //Yields a Field<Set<K>> that contains the keys of the map in f
MapFieldUtils.count(f, /* predicate */); //Yields a Field<Integer> that contains the number of entries that satisfy the predicate
//Setters
MapFieldUtils.put(mf, v1, v2) //Creates a new immutable map consisting of the map in f with the mapping (v1)=>(v2) added, then sets it to the field
Nearly all the extension functions of maps of Kotlin™ are available as an utility transformation function in Dataflow. A complete list can be found in the Kotlin documentation.
Most common ways of changing a map are available but be careful! Each change you perform will create a new immutable map and discard the previous one, so you should consider every operation Ω(n)
with respect to the map size. The reason for this behavior is explained in detail in the section Restrictions on field values.