(Quick Reference)
2 Using the Smartionary Interface - Reference Documentation
Authors: Aaron Brown
Version: 1.0.0
2 Using the Smartionary Interface
From a progremmatic standpoint, the plugin tries to abstract the
Smartionary
domain into the overloaded
Smartionary
object. The
Smartionary
object
provides an interface that abides by the following goals:
- Be dyanamic
- Automatically create
Domains
as necessary.
- Update
Domains
that already exist.
- Be flexible
- Multiple ways to do the same thing.
- Attempt to reduce the number of
Exceptions
that would occur.
- Don't mind the illogical
- Deleting a
Domain
that doesn't exist is just fine.
- Pretend to be a
Map
- Treat interaction for the developer like they're working with a
Map
- Provide some
Map
-methods so they can be used without needing to work
with an actual Map
.
2.1 Setting
Creating and updating
Domains
is done via the s
et()
method. There are
several forms, but only the more complex (and flexible) ones will be discussed
here.
Through all examples here use Strings
, any Object
can be used just like a
Map
. The caveat is that it gets converted to a String
when placed in the
Domain
, and will be a String
when retrieved.See get()
for details.
The primary strength of
Smartionary is that it can convert a
Map
directly
into a
Smartionary
domain:
Map toSmartionary = [
a: "apple",
b: "banana",
c: "cantaloupe",
d: "durian"
]Smartionary.set(toSmartionary, 'fruits', 'A few fruits, by letter.')
That is a very straightforward approach, however just like when creating a
Domain
object, the method signature allows you to put the
Map
directly into
the parameter body:
Smartionary.set(
'fruits',
'A few fruits, by letter',
a: "apple",
b: "banana",
c: "cantaloupe",
d: "durian")
In the above sample, the
description was moved to be the second positional
parameter. This makes it a bit more readable than the explicit form.
In the above case, s
et()
does the following:
- Retrieve the
Smartionary
that exists by the name of fruits .
- If it does not exist, create it.
- Replace the values in the corresponding
SmartionaryEntries
.
- If it does not exist, create it.
Therefore, the same
Smartionary
domain can be updated with a successive call,
and a subset of values can be replaced, and others can be added:
Smartionary.set(
'fruits',
c: "cherry",
t: "tomato",
w: "watermelon")
By using this method, it is impossible to encounter the unique naming
constraints.
Due to the nature of setting, be very mindful if you wish to only update the
description . For more information, read about
setting Smartionary descriptons
Setting from JSON
An extension of the s
et()
method is the
fromJson()
method. This provides
a convenient way of converting a JSON string which would describe a set of
parameters or criteria into an equivalent
Smartionary
.
String json = '{"a": "apple", "b": "banana", "c": "carrot", "d": "durian"}'Smartionary.set('fruits', json, 'A few fruits, by letter.')json = '{"c": "cherry", "t": "tomato", "w": "watermelon"}'Smartionary.set('fruits', json)
Note that the order of the parameters differs. It is not shown here, but in
all instances of set()
, the smartionaryName is the first parameter with
the exception of the example above. This is due to the way Groovy handles
that particular method signature.
{warn}
When working with JSON, an array such as the following is not supported:
'["apple", "banana", "cantaloupe", "durian"]'
This will throw an
IllegalArgumentException
.
null
Nested Maps
and Lists
inside the JSON will be converted to Strings
, so
this is not very appropriate for complex schemas.
2.1.1 Setting Descriptions
There are certain considerations to bear in mind when it comes to the
descriptions of
Smartionary
and
SmartionaryEntry
. Both
Domains
allow
for a description, which is primarily for when looking at the view. While
developing, it is best-practice to put some form of description with the
instances, even though the
Smartionary has no methods to retrieve them.
Smartionary
Description
The description for a
Smartionary
can be set using any form of the
set()
method. There is no harm in omitting the description; if the domain already
has one, it will keep it.
SmartionaryEntry
Description
The description for a
SmartionaryEntry
can only be updated (via the
Smartionary) by the
set()
methods (or
fromJson()
). The explicit methods
are fairly starightforward, but for the named-parameter signature there is a
specific way:
Smartionary.set(
'fruits',
a: "apple",
b: "banana",
c: "cantaloupe",
d: "durian",
smartionaryDescriptions: [
a: "Can be green, yellow, or red; sour or sweet.",
b: 'Grows in bunches, called "hands."',
c: "A kind of melon with a lattuce skin.",
d: "A spiney fruit like a pineapple, that's really stinky.",
t: "A red, fragile bulb; debated to be a vegetable."
]
)
The
smartionaryDescriptions
key is sort of a "reserved" key for this method.
It follows a simple rule:
only update the keys that appear in the outer
Map
. In this example, the key
t
does not appear in the outer
Map
,
therefore, even if a
SmartionaryEntry
exists for
t
, it will not be updated.
The rationality behind this is two-fold:
- Enforces awareness of value modification
- Prevents accidental and ambiguous behavior when dealing with
null
.
This behavior applies to all versions of
set()
(as well as
fromJson()
). If
it is necessary to update only the description, it is best and safer to use the
web-interface.
Should you choose to update the descriptions through the Smartionary, be
aware that if you pass null
for the value of that key, then that is what will
be written to the Domain
.
2.2 Getting
Accessing the information in a
Smartionary
domain progremmatically is done
via the
get()
method.
The
get()
method
does not automatically create a
Smartionary
domain if it
does not exist (that can only be done by the
set()
methods).
Map data = Smartionary.get('fruits')
Depending on the state of the
Domain
, the following conditions apply:
Smartionary exists | Has SmartionaryEntries | Returns |
---|
| | null |
| | [:] |
| | a=apple, b=banana, c=cantaloupe, d=durian |
The philosophy behind the plugin is that
get()
is used more frequently than
set()
. While it may be tempting to cache or somehow store the information,
that ruins the advantages of being able to change the values of a
Smartionary
while in production, on-the-fly. Therefore, the following
is not best
practice:
class MyClass {
Map myInfo = Smartionary.get('myInfoParams') private final static MyInfo INSTANCE = new MyInfo() private myInfo() { } static getInstance() { return INSTANCE }
}
The contents of myInfo
can only be updated on application restart.
Getting as JSON
Just like
withJson()
there is a method for retrieving a
Smartionary
as a
JSON string directly. It uses the internal Groovy
JsonBuilder to fascilitate this:
try {
Smartionary.getAsJson('fruits')
} catch (IllegalArgumentException e) {
// The Smartionary may not exist.
} catch (JsonException e) {
// Something went awry.
}
Please note the
try/catch
statement.
Since the
JsonBuilder
is used, by passing
true
(or explicitly
false
) you
can specify that the
String
should (not) be pretty-formatted:
try {
Smartionary.getAsJson('fruits', true)
} catch (IllegalArgumentException e) {
// The Smartionary may not exist.
} catch (JsonException e) {
// Something went awry.
}
2.3 Map-like Interface
The
Smartionary comes with several basic
Map
-like functions, so that some
operations can be performed directly, rather than making it necessary to
retrieve
Map
through
gettingThey are exactly like their
Map
counterpart, with one exception.
Method | example |
---|
contains | Smartionary.contains('fruits', 'apple') |
containsKey | Smartionary.containsKey('fruits', 'a') |
size | Smartionary.size('fruits') |
The exception to this rule is the
size()
method:
Condition | Result |
---|
Smartionary does not exist | -1 |
Smartionary exists, but SmartionaryEntries do not | 0 |
Otherwise | Normal size() behavior for Map . |