1Hash::Layout(3) User Contributed Perl Documentation Hash::Layout(3)
2
3
4
6 Hash::Layout - hashes with predefined levels, composite keys and
7 default values
8
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
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
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 clone
210 Returns a new/cloned "Hash::Layout" instance
211
212 coerce
213 Dynamic method coerces supplied value into a new "Hash::Layout"
214 instance with a new set of loaded data. See unit tests for more info.
215
216 coercer
217 CodeRef wrapper around "coerce()", suitable for use in a Moo-compatible
218 attribute declaration
219
220 load
221 Loads new data into the hash.
222
223 Data can be supplied as hashrefs with normal/local keys or composite
224 keys, or both. Composite keys can also be supplied as sub-keys and are
225 resolved relative to the location in which they appear as one would
226 expect.
227
228 Composite keys can also be supplied as simple strings w/o corresponding
229 values in which case their value is set to whatever "default_value" is
230 set to (which defaults to 1).
231
232 See the unit tests for more details and lots of examples of using
233 "load()".
234
235 set
236 Simpler alternative to "load()". Expects exactly two arguments as
237 standard key/values.
238
239 resolve_key_path
240 Converts a composite key string into its full path and returns it as a
241 list. Called internally wherever composite keys are resolved.
242
243 path_to_composite_key
244 Inverse of "resolve_key_path"; takes a path as a list and returns a
245 single composite key string (i.e. joins using the delimiters for each
246 level). Obviously, it only returns fully-qualified, non-ambiguous (not
247 partial) composite keys.
248
249 exists
250 Returns true if the supplied composite key exists and false if it
251 doesn't. Does not consider default/fallback key paths.
252
253 exists_path
254 Like "exists()", but requires the key to be supplied as a
255 resolved/fully-qualified path as a list of arguments. Used internally
256 by "exists()".
257
258 get
259 Retrieves the real value of the supplied composite key, or undef if it
260 does not exist. Use "exists()" to distinguish undef values. Does not
261 consider default/fallback key paths (that is what "lookup()" is for).
262
263 get_path
264 Like "get()", but requires the key to be supplied as a
265 resolved/fully-qualified path as a list of arguments. Used internally
266 by "get()".
267
268 lookup
269 Returns the value of the supplied composite key, falling back to
270 default key paths if it does not exist, depending on the value of
271 "lookup_mode".
272
273 If the lookup_mode is set to 'get', lookup() behaves exactly the same
274 as get().
275
276 If the lookup_mode is set to 'fallback' and the supplied key does not
277 exist, lookup() will search the hierarchy of matching default key
278 paths, returning the first value that exists.
279
280 If the lookup_mode is set to 'merge', lookup() behaves the same as it
281 does in 'fallback' mode for all non-hashref values. For hashref values,
282 the hierarchy of default key paths is searched and all matches (that
283 are themselves hashrefs), including the exact/lowest value itself, are
284 merged and returned.
285
286 lookup_path
287 Like "lookup()", but requires the key to be supplied as a
288 resolved/fully-qualified path as a list of arguments. Used internally
289 by "lookup()".
290
291 lookup_leaf_path
292 Like "lookup_path()", but only returns the value if it is a "leaf"
293 (i.e. not a hashref with deeper sub-values). Empty hashrefs ("{}") are
294 also considered leaf values.
295
296 delete
297 Deletes the supplied composite key and returns the deleted value, or
298 undef if it does not exist. Does not consider default/fallback key
299 paths, or delete multiple items at once (e.g. like the Linux "rm"
300 command does with shell globs).
301
302 delete_path
303 Like "delete()", but requires the key to be supplied as a
304 resolved/fully-qualified path as a list of arguments. Used internally
305 by "delete()".
306
307 Data
308 Returns a read-only (i.e. cloned) copy of the full loaded hash
309 structure.
310
311 num_levels
312 Returns the number of levels defined for this "Hash::Layout" instance.
313
314 level_keys
315 Returns a hashref of all the keys that have been loaded/exist for the
316 supplied level index (the first level is at index 0).
317
318 def_key_bitmask_strings
319 Debug method. Returns a list of all the default key paths as a list of
320 bitmasks (in binary/string form). Any key path which has at least one
321 default key at any level is considered a default path and is indexed as
322 a bitmask, with '1' values representing the default key position(s).
323 For instance, the key path "{*}{*}{foo_rule}" from the 3-level example
324 from the SYNOPSIS is indexed as the bitmask 110 (6 in decimal).
325
326 These bitmasks are used internally to efficiently search for and
327 properly order default key values for quick fallback/merge lookups,
328 even when there are a very large number of levels (and thus very, VERY
329 large number of possible default paths). That is why they are tracked
330 and indexed ahead of time.
331
332 This is a debug method which should not be needed to be used for any
333 production code. I decided to leave it in just to help document some of
334 the internal workings of this module.
335
336 reset
337 Clears and removes all loaded data and resets internal key indexes and
338 counters.
339
341 For more examples, see the following:
342
343 · The SYNOPSIS
344
345 · The unit tests in "t/"
346
347 · DBIx::Class::Schema::Diff#filter
348
350 Henry Van Styn <vanstyn@cpan.org>
351
353 This software is copyright (c) 2014 by IntelliTree Solutions llc.
354
355 This is free software; you can redistribute it and/or modify it under
356 the same terms as the Perl 5 programming language system itself.
357
358
359
360perl v5.32.0 2020-07-28 Hash::Layout(3)