1Hash::Layout(3)       User Contributed Perl Documentation      Hash::Layout(3)
2
3
4

NAME

6       Hash::Layout - hashes with predefined levels, composite keys and
7       default values
8

SYNOPSIS

10        use Hash::Layout;
11
12        # Create new Hash::Layout object with 3 levels and unique delimiters:
13        my $HL = Hash::Layout->new({
14         levels => [
15           { delimiter => ':' },
16           { delimiter => '/' },
17           {}, # <-- last level never has a delimiter
18         ]
19        });
20
21        # load using actual hash structure:
22        $HL->load({
23          '*' => {
24            '*' => {
25              foo_rule => 'always deny',
26              blah     => 'thing'
27            },
28            NewYork => {
29              foo_rule => 'prompt'
30            }
31          }
32        });
33
34        # load using composite keys:
35        $HL->load({
36          'Office:NewYork/foo_rule' => 'allow',
37          'Store:*/foo_rule'        => 'other',
38          'Store:London/blah'       => 'purple'
39        });
40
41        # load composite keys w/o values (uses default_value):
42        $HL->load(qw/baz:bool_key flag01/);
43
44        # get a copy of the hash data:
45        my $hash = $HL->Data;
46
47        #  $hash now contains:
48        #
49        #    {
50        #      "*" => {
51        #        "*" => {
52        #          blah => "thing",
53        #          flag01 => 1,
54        #          foo_rule => "always deny"
55        #        },
56        #        NewYork => {
57        #          foo_rule => "prompt"
58        #        }
59        #      },
60        #      Office => {
61        #        NewYork => {
62        #          foo_rule => "allow"
63        #        }
64        #      },
65        #      Store => {
66        #        "*" => {
67        #          foo_rule => "other"
68        #        },
69        #        London => {
70        #          blah => "purple"
71        #        }
72        #      },
73        #      baz => {
74        #        "*" => {
75        #          bool_key => 1
76        #        }
77        #      }
78        #    }
79        #
80
81
82        # lookup values by composite keys:
83        $HL->lookup('*:*/foo_rule')              # 'always deny'
84        $HL->lookup('foo_rule')                  # 'always deny'
85        $HL->lookup('ABC:XYZ/foo_rule')          # 'always deny'  # (virtual/fallback)
86        $HL->lookup('Lima/foo_rule')             # 'always deny'  # (virtual/fallback)
87        $HL->lookup('NewYork/foo_rule')          # 'prompt'
88        $HL->lookup('Office:NewYork/foo_rule')   # 'allow'
89        $HL->lookup('Store:foo_rule')            # 'other'
90        $HL->lookup('baz:Anything/bool_key')     # 1              # (virtual/fallback)
91
92        # lookup values by full/absolute paths:
93        $HL->lookup_path(qw/ABC XYZ foo_rule/)   # 'always deny'  # (virtual/fallback)
94        $HL->lookup_path(qw/Store * foo_rule/)   # 'other'
95

DESCRIPTION

97       "Hash::Layout" provides deep hashes with a predefined number of levels
98       which you can access using special "composite keys". These are
99       essentially string paths that inflate into actual hash keys according
100       to the defined levels and delimiter mappings, which can be the same or
101       different for each level.  This is useful both for shorter keys as well
102       as merge/fallback to default values, such as when defining overlapping
103       configs ranging from broad to narrowing scope (see example in SYNOPIS
104       above).
105
106       This module is general-purpose, but was written specifically for the
107       flexible filter() feature of DBIx::Class::Schema::Diff, so refer to its
108       documentation as well for a real-world example application. There are
109       also lots of examples and use scenarios in the unit tests under "t/".
110

METHODS

112   new
113       Create a new Hash::Layout instance. The following build options are
114       supported:
115
116       levels
117           Required. ArrayRef of level config definitions, or a numeric number
118           of levels for default level configs. Each level can define its own
119           "delimiter" (except the last level) and list of "registered_keys",
120           both of which are optional and determine how ambiguous/partial
121           composite keys are resolved.
122
123           Level-specific delimiters provide a mechanism to supply partial
124           paths in composite keys but resolve to a specific level. The
125           word/string to the left of a delimiter character that is specific
126           to a given level is resolved as the key of that level, however, the
127           correct path order is required (keys are only tokenized in order
128           from left to right).
129
130           Specific strings can also be declared to belong to a particular
131           level with "registered_keys". This also only effects how ambiguity
132           is resolved with partial composite keys. See also the "no_fill" and
133           "no_pad" options.
134
135           See the unit tests for examples of exactly how this works.
136
137           Internally, the level configs are coerced into Hash::Layout::Level
138           objects.
139
140           For Hash::Layouts that don't need/want level-specific delimiters,
141           or level-specific registered_keys, a simple integer value can be
142           supplied instead for default level configs all using "/" as the
143           delimiter.
144
145           So, this:
146
147            my $HL = Hash::Layout->new({ levels => 5 });
148
149           Is equivalent to:
150
151            $HL = Hash::Layout->new({
152             levels => [
153               { delimiter => '/' }
154               { delimiter => '/' }
155               { delimiter => '/' }
156               { delimiter => '/' }
157               {} #<-- last level never has a delimiter
158             ]
159            });
160
161           "levels" is the only required parameter.
162
163       default_value
164           Value to assign keys when supplied to "load()" as simple strings
165           instead of key/value pairs.  Defaults to the standard bool/true
166           value of 1.
167
168       default_key
169           Value to use for the key for levels which are not specified, as
170           well as the key to use for default/fallback when looking up non-
171           existant keys (see also "lookup_mode"). Defaults to a single
172           asterisk "(*)".
173
174       no_fill
175           If true, partial composite keys are not expanded with the
176           default_key (in the middle) to fill to the last level.  Defaults to
177           0.
178
179       no_pad
180           If true, partial composite keys are not expanded with the
181           default_key (at the front or middle) to fill to the last level.
182           "no_pad" implies "no_fill". Again, see the tests for a more
183           complete explanation. Defaults to 0.
184
185       allow_deep_values
186           If true, values at the bottom level are allowed to be hashes, too,
187           for the purposes of addressing the deeper paths using composite
188           keys (see "deep_delimiter" below). Defaults to 1.
189
190       deep_delimiter
191           When "allow_deep_values" is enabled, the deep_delimiter character
192           is used to resolve composite key mappings into the deep hash values
193           (i.e. beyond the predefined levels). Must be different from the
194           delimiter used by any of the levels. Defaults to a single dot
195           "(.)".
196
197           For example:
198
199             $HL->lookup('something/foo.deeper.hash.path')
200
201       lookup_mode
202           One of either "get", "fallback" or "merge". In "fallback" mode,
203           when a non-existent composite key is looked up, the value of the
204           first closest found key path using default keys is returned instead
205           of "undef" as is the case with "get" mode. "merge" mode is like
206           "fallback" mode, except hashref values are merged with matching
207           default key paths which are also hashrefs. Defaults to "merge".
208
209       enable_globmatch
210           If true, key value lookup calls will automatically try to match
211           wildcard (text glob) expressions.  Defaults to false (0).
212
213   clone
214       Returns a new/cloned "Hash::Layout" instance
215
216   coerce
217       Dynamic method coerces supplied value into a new "Hash::Layout"
218       instance with a new set of loaded data.  See unit tests for more info.
219
220   coercer
221       CodeRef wrapper around "coerce()", suitable for use in a Moo-compatible
222       attribute declaration
223
224   load
225       Loads new data into the hash.
226
227       Data can be supplied as hashrefs with normal/local keys or composite
228       keys, or both. Composite keys can also be supplied as sub-keys and are
229       resolved relative to the location in which they appear as one would
230       expect.
231
232       Composite keys can also be supplied as simple strings w/o corresponding
233       values in which case their value is set to whatever "default_value" is
234       set to (which defaults to 1).
235
236       See the unit tests for more details and lots of examples of using
237       "load()".
238
239   set
240       Simpler alternative to "load()". Expects exactly two arguments as
241       standard key/values.
242
243   resolve_key_path
244       Converts a composite key string into its full path and returns it as a
245       list. Called internally wherever composite keys are resolved.
246
247   path_to_composite_key
248       Inverse of "resolve_key_path"; takes a path as a list and returns a
249       single composite key string (i.e. joins using the delimiters for each
250       level). Obviously, it only returns fully-qualified, non-ambiguous (not
251       partial) composite keys.
252
253   exists
254       Returns true if the supplied composite key exists and false if it
255       doesn't. Does not consider default/fallback key paths.
256
257   exists_path
258       Like "exists()", but requires the key to be supplied as a
259       resolved/fully-qualified path as a list of arguments.  Used internally
260       by "exists()".
261
262   get
263       Retrieves the real value of the supplied composite key, or undef if it
264       does not exist. Use "exists()" to distinguish undef values. Does not
265       consider default/fallback key paths (that is what "lookup()" is for).
266
267   get_path
268       Like "get()", but requires the key to be supplied as a
269       resolved/fully-qualified path as a list of arguments.  Used internally
270       by "get()".
271
272   lookup
273       Returns the value of the supplied composite key, falling back to
274       default key paths if it does not exist, depending on the value of
275       "lookup_mode".
276
277       If the lookup_mode is set to 'get', lookup() behaves exactly the same
278       as get().
279
280       If the lookup_mode is set to 'fallback' and the supplied key does not
281       exist, lookup() will search the hierarchy of matching default key
282       paths, returning the first value that exists.
283
284       If the lookup_mode is set to 'merge', lookup() behaves the same as it
285       does in 'fallback' mode for all non-hashref values. For hashref values,
286       the hierarchy of default key paths is searched and all matches (that
287       are themselves hashrefs), including the exact/lowest value itself, are
288       merged and returned.
289
290   lookup_path
291       Like "lookup()", but requires the key to be supplied as a
292       resolved/fully-qualified path as a list of arguments.  Used internally
293       by "lookup()".
294
295   lookup_leaf_path
296       Like "lookup_path()", but only returns the value if it is a "leaf"
297       (i.e. not a hashref with deeper sub-values).  Empty hashrefs ("{}") are
298       also considered leaf values.
299
300   lookup_path_globmatch
301       Like "lookup_path()", but matches/returns by comparing a full composite
302       key string with wildcard (text glob) expressions.
303
304   delete
305       Deletes the supplied composite key and returns the deleted value, or
306       undef if it does not exist.  Does not consider default/fallback key
307       paths, or delete multiple items at once (e.g. like the Linux "rm"
308       command does with shell globs).
309
310   delete_path
311       Like "delete()", but requires the key to be supplied as a
312       resolved/fully-qualified path as a list of arguments.  Used internally
313       by "delete()".
314
315   Data
316       Returns a read-only (i.e. cloned) copy of the full loaded hash
317       structure.
318
319   num_levels
320       Returns the number of levels defined for this "Hash::Layout" instance.
321
322   level_keys
323       Returns a hashref of all the keys that have been loaded/exist for the
324       supplied level index (the first level is at index 0).
325
326   def_key_bitmask_strings
327       Debug method. Returns a list of all the default key paths as a list of
328       bitmasks (in binary/string form).  Any key path which has at least one
329       default key at any level is considered a default path and is indexed as
330       a bitmask, with '1' values representing the default key position(s).
331       For instance, the key path "{*}{*}{foo_rule}" from the 3-level example
332       from the SYNOPSIS is indexed as the bitmask 110 (6 in decimal).
333
334       These bitmasks are used internally to efficiently search for and
335       properly order default key values for quick fallback/merge lookups,
336       even when there are a very large number of levels (and thus very, VERY
337       large number of possible default paths). That is why they are tracked
338       and indexed ahead of time.
339
340       This is a debug method which should not be needed to be used for any
341       production code. I decided to leave it in just to help document some of
342       the internal workings of this module.
343
344   reset
345       Clears and removes all loaded data and resets internal key indexes and
346       counters.
347

EXAMPLES

349       For more examples, see the following:
350
351       •   The SYNOPSIS
352
353       •   The unit tests in "t/"
354
355       •   DBIx::Class::Schema::Diff#filter
356

AUTHOR

358       Henry Van Styn <vanstyn@cpan.org>
359
361       This software is copyright (c) 2014 by IntelliTree Solutions llc.
362
363       This is free software; you can redistribute it and/or modify it under
364       the same terms as the Perl 5 programming language system itself.
365
366
367
368perl v5.36.0                      2022-07-22                   Hash::Layout(3)
Impressum