File Coverage

lib/Data/Identifier.pm
Criterion Covered Total %
statement 241 433 55.6
branch 133 320 41.5
condition 75 195 38.4
subroutine 26 37 70.2
pod 23 23 100.0
total 498 1008 49.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2              
3             # Copyright (c) 2023-2026 Philipp Schafft
4              
5             # licensed under Artistic License 2.0 (see LICENSE file)
6              
7             # ABSTRACT: format independent identifier object
8              
9              
10             package Data::Identifier;
11              
12 7     7   1141717 use v5.20;
  7         21  
13 7     7   26 use strict;
  7         9  
  7         127  
14 7     7   25 use warnings;
  7         16  
  7         316  
15              
16 7     7   22 use parent qw(Data::Identifier::Interface::Known Data::Identifier::Interface::Userdata);
  7         9  
  7         56  
17              
18 7     7   342 use Carp;
  7         10  
  7         356  
19 7     7   10072 use Math::BigInt lib => 'GMP';
  7         227319  
  7         103  
20 7     7   160878 use URI;
  7         31769  
  7         2474  
21              
22             our $VERSION = v0.30;
23              
24             use constant {
25 7         1018 RE_UUID => qr/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}\z/,
26             RE_OID => qr/^[0-2](?:\.(?:0|[1-9][0-9]*))+\z/,
27             RE_URI => qr/^[a-zA-Z][a-zA-Z0-9\+\.\-]+:/,
28             RE_UINT => qr/^(?:0|[1-9][0-9]*)\z/,
29             RE_SINT => qr/^(?:0|-?[1-9][0-9]*)\z/,
30             RE_QID => qr/^[QPL][1-9][0-9]*\z/,
31             RE_DOI => qr/^10\.[1-9][0-9]+(?:\.[0-9]+)*\/./,
32             RE_GTIN => qr/^[0-9]{8}(?:[0-9]{4,6})?\z/,
33             RE_UNICODE => qr/^U\+([0-9A-F]{4,7})\z/,
34             RE_SIMPLE_TAG => qr/^[^\p{upper case}\s]+\z/,
35 7     7   44 };
  7         10  
36              
37             use constant {
38 7         40106 WK_NULL => '00000000-0000-0000-0000-000000000000', # NULL, undef, ...
39             WK_UUID => '8be115d2-dc2f-4a98-91e1-a6e3075cbc31', # uuid
40             WK_OID => 'd08dc905-bbf6-4183-b219-67723c3c8374', # oid
41             WK_URI => 'a8d1637d-af19-49e9-9ef8-6bc1fbcf6439', # uri
42             WK_SID => 'f87a38cb-fd13-4e15-866c-e49901adbec5', # small-identifier
43             WK_WD => 'ce7aae1e-a210-4214-926a-0ebca56d77e3', # wikidata-identifier
44             WK_GTIN => '82d529be-0f00-4b4f-a43f-4a22de5f5312', # gtin
45             WK_IBAN => 'b1418262-6bc9-459c-b4b0-a054d77db0ea', # iban
46             WK_BIC => 'c8a3a132-f160-473c-b5f3-26a748f37e62', # bic
47             WK_DOI => '931f155e-5a24-499b-9fbb-ed4efefe27fe', # doi
48             WK_FC => 'd576b9d1-47d4-43ae-b7ec-bbea1fe009ba', # factgrid-identifier
49             WK_UNICODE_CP => '5f167223-cc9c-4b2f-9928-9fe1b253b560', # unicode-code-point
50             WK_SNI => '039e0bb7-5dd3-40ee-a98c-596ff6cce405', # sirtx-numerical-identifier
51             WK_HDI => 'f8eb04ef-3b8a-402c-ad7c-1e6814cb1998', # host-defined-identifier
52             WK_UDI => '05af99f9-4578-4b79-aabe-946d8e6f5888', # user-defined-identifier
53             WK_CHAT0W => '2c7e15ed-aa2f-4e2f-9a1d-64df0c85875a', # chat-0-word-identifier
54              
55             NS_WD => '9e10aca7-4a99-43ac-9368-6cbfa43636df', # Wikidata-namespace
56             NS_FC => '6491f7a9-0b29-4ef1-992c-3681cea18182', # factgrid-namespace
57             NS_INT => '5dd8ddbb-13a8-4d6c-9264-36e6dd6f9c99', # integer-namespace
58             NS_DATE => 'fc43fbba-b959-4882-b4c8-90a288b7d416', # gregorian-date-namespace
59             NS_GTIN => 'd95d8b1f-5091-4642-a6b0-a585313915f1', # gtin-namespace
60             NS_UNICODE_CP => '132aa723-a373-48bf-a88d-69f1e00f00cf', # unicode-character-namespace
61 7     7   28 };
  7         7  
62              
63             # Features:
64             my $enabled_oid = 1;
65              
66             my %uuid_to_uriid_org = (
67             WK_UUID() => 'uuid',
68             WK_OID() => 'oid',
69             WK_URI() => 'uri',
70             WK_SID() => 'sid',
71             WK_GTIN() => 'gtin',
72             WK_WD() => 'wikidata-identifier',
73             );
74              
75             my %uuid_org_to_uuid = map {$uuid_to_uriid_org{$_} => $_} keys %uuid_to_uriid_org;
76              
77             my $well_known_uuid = __PACKAGE__->new(ise => WK_UUID, validate => RE_UUID);
78              
79             my %well_known = (
80             uuid => $well_known_uuid,
81             oid => __PACKAGE__->new($well_known_uuid => WK_OID, validate => RE_OID),
82             uri => __PACKAGE__->new($well_known_uuid => WK_URI, validate => RE_URI),
83             sid => __PACKAGE__->new($well_known_uuid => WK_SID, validate => RE_UINT),
84             sni => __PACKAGE__->new($well_known_uuid => WK_SNI, validate => RE_UINT),
85             wd => __PACKAGE__->new($well_known_uuid => WK_WD, validate => RE_QID, generate => 'id-based'),
86             fc => __PACKAGE__->new($well_known_uuid => WK_FC, validate => RE_QID, generate => 'id-based'),
87             gtin => __PACKAGE__->new($well_known_uuid => WK_GTIN, validate => RE_GTIN, generate => 'id-based'),
88             iban => __PACKAGE__->new($well_known_uuid => WK_IBAN),
89             bic => __PACKAGE__->new($well_known_uuid => WK_BIC),
90             doi => __PACKAGE__->new($well_known_uuid => WK_DOI, validate => RE_DOI),
91              
92             # Unofficial, not part of public API:
93             # Also used by Data::Identifier::Util!
94             unicodecp => __PACKAGE__->new($well_known_uuid => WK_UNICODE_CP, validate => RE_UNICODE, generate => 'id-based'),
95              
96             hdi => __PACKAGE__->new($well_known_uuid => WK_HDI, validate => RE_UINT),
97             udi => __PACKAGE__->new($well_known_uuid => WK_UDI, validate => RE_UINT),
98             null => __PACKAGE__->new($well_known_uuid => WK_NULL),
99             );
100              
101             my %registered;
102              
103             $_->register foreach values %well_known;
104              
105             # Refill with namespaces:
106             {
107             my %ns = (
108             wd => NS_WD,
109             fc => NS_FC,
110             gtin => NS_GTIN,
111             unicodecp => NS_UNICODE_CP,
112             );
113              
114             foreach my $wk (keys %ns) {
115             $well_known{$wk}->{namespace} //= Data::Identifier->new(ise => $ns{$wk})->register;
116             }
117             }
118              
119             # Refill with sids:
120             {
121             my %wk_sids = (
122             WK_NULL() => 0, # NULL
123             'ddd60c5c-2934-404f-8f2d-fcb4da88b633' => 1, # also-shares-identifier
124             WK_UUID() => 2,
125             'bfae7574-3dae-425d-89b1-9c087c140c23' => 3, # tagname
126             '7f265548-81dc-4280-9550-1bd0aa4bf748' => 4, # has-type
127             WK_URI() => 5,
128             WK_OID() => 6,
129             # Unassigned: 7
130             'd0a4c6e2-ce2f-4d4c-b079-60065ac681f1' => 8, # language-tag-identifier
131             WK_WD() => 9,
132             '923b43ae-a50e-4db3-8655-ed931d0dd6d4' => 10, # specialises
133             'eacbf914-52cf-4192-a42c-8ecd27c85ee1' => 11, # unicode-string
134             '928d02b0-7143-4ec9-b5ac-9554f02d3fb1' => 12, # integer
135             'dea3782c-6bcb-4ce9-8a39-f8dab399d75d' => 13, # unsigned-integer
136             # Unassigned: 14, 15
137             '6ba648c2-3657-47c2-8541-9b73c3a9b2b4' => 16, # default-context
138             '52a516d0-25d8-47c7-a6ba-80983e576c54' => 17, # proto-file
139             '1cd4a6c6-0d7c-48d1-81e7-4e8d41fdb45d' => 18, # final-file-size
140             '6085f87e-4797-4bb2-b23d-85ff7edc1da0' => 19, # text-fragment
141             '4c9656eb-c130-42b7-9348-a1fee3f42050' => 20, # also-list-contains-also
142             '298ef373-9731-491d-824d-b2836250e865' => 21, # proto-message
143             '7be4d8c7-6a75-44cc-94f7-c87433307b26' => 22, # proto-entity
144             '65bb36f2-b558-48af-8512-bca9150cca85' => 23, # proxy-type
145             'a1c478b5-0a85-4b5b-96da-d250db14a67c' => 24, # flagged-as
146             '59cfe520-ba32-48cc-b654-74f7a05779db' => 25, # marked-as
147             '2bffc55d-7380-454e-bd53-c5acd525d692' => 26, # roaraudio-error-number
148             WK_SID() => 27,
149             'd2750351-aed7-4ade-aa80-c32436cc6030' => 28, # also-has-role
150             '11d8962c-0a71-4d00-95ed-fa69182788a8' => 29, # also-has-comment
151             '30710bdb-6418-42fb-96db-2278f3bfa17f' => 30, # also-has-description
152             # Unassigned: 31
153             '448c50a8-c847-4bc7-856e-0db5fea8f23b' => 32, # final-file-encoding
154             '79385945-0963-44aa-880a-bca4a42e9002' => 33, # final-file-hash
155             '3fde5688-6e34-45e9-8f33-68f079b152c8' => 34, # SEEK_SET
156             'bc598c52-642e-465b-b079-e9253cd6f190' => 35, # SEEK_CUR
157             '06aff30f-70e8-48b4-8b20-9194d22fc460' => 36, # SEEK_END
158             '59a5691a-6a19-4051-bc26-8db82c019df3' => 37, # inode
159             WK_CHAT0W() => 112, # chat-0-word-identifier
160             WK_SNI() => 113, # sirtx-numerical-identifier
161             WK_GTIN() => 160,
162             );
163              
164             foreach my $ise (keys %wk_sids) {
165             my $identifier = __PACKAGE__->new(ise => $ise);
166             $identifier->{id_cache} //= {};
167             $identifier->{id_cache}->{WK_SID()} //= $wk_sids{$ise};
168             $identifier->register; # re-register
169             }
170             }
171              
172             # Refill with snis:
173             {
174             my %wk_snis = (
175             WK_NULL() => 0, # NULL
176             '039e0bb7-5dd3-40ee-a98c-596ff6cce405' => 10, # sirtx-numerical-identifier
177             'f87a38cb-fd13-4e15-866c-e49901adbec5' => 115, # small-identifier
178             '2bffc55d-7380-454e-bd53-c5acd525d692' => 116, # roaraudio-error-number
179             WK_CHAT0W() => 118, # chat-0-word-identifier
180             WK_UUID() => 119,
181             WK_OID() => 120,
182             WK_URI() => 121,
183             WK_WD() => 123,
184             );
185              
186             foreach my $ise (keys %wk_snis) {
187             my $identifier = __PACKAGE__->new(ise => $ise);
188             $identifier->{id_cache} //= {};
189             $identifier->{id_cache}->{WK_SNI()} //= $wk_snis{$ise};
190             $identifier->register; # re-register
191             }
192             }
193              
194             # Update NULL:
195             {
196             my $identifier = __PACKAGE__->new(uuid => WK_NULL);
197             $identifier->{id_cache} //= {};
198             foreach my $type (WK_HDI, WK_CHAT0W) {
199             $identifier->{id_cache}->{$type} //= 0;
200             }
201             $identifier->register;
202             }
203              
204             # Some extra tags such as namespaces:
205             foreach my $ise (NS_WD, NS_INT, NS_DATE) {
206             my $identifier = __PACKAGE__->new(ise => $ise);
207             $identifier->register; # re-register
208             }
209              
210             # Refill with tagnames
211             {
212             my %tagnames = (
213             WK_NULL() => 'null',
214             WK_UUID() => 'uuid',
215             WK_OID() => 'oid',
216             WK_URI() => 'uri',
217             WK_SID() => 'small-identifier',
218             WK_WD() => 'wikidata-identifier',
219             WK_GTIN() => 'gtin',
220             WK_IBAN() => 'iban',
221             WK_BIC() => 'bic',
222             WK_DOI() => 'doi',
223             WK_FC() => 'factgrid-identifier',
224             WK_UNICODE_CP() => 'unicode-code-point',
225             WK_SNI() => 'sirtx-numerical-identifier',
226             WK_HDI() => 'host-defined-identifier',
227             WK_UDI() => 'user-defined-identifier',
228             WK_CHAT0W() => 'chat-0-word-identifier',
229             NS_WD() => 'Wikidata-namespace',
230             NS_FC() => 'factgrid-namespace',
231             NS_INT() => 'integer-namespace',
232             NS_DATE() => 'gregorian-date-namespace',
233             NS_UNICODE_CP() => 'unicode-character-namespace',
234              
235             'ddd60c5c-2934-404f-8f2d-fcb4da88b633' => 'also-shares-identifier',
236             'bfae7574-3dae-425d-89b1-9c087c140c23' => 'tagname',
237             '7f265548-81dc-4280-9550-1bd0aa4bf748' => 'has-type',
238             'd0a4c6e2-ce2f-4d4c-b079-60065ac681f1' => 'language-tag-identifier',
239             '923b43ae-a50e-4db3-8655-ed931d0dd6d4' => 'specialises',
240             'eacbf914-52cf-4192-a42c-8ecd27c85ee1' => 'unicode-string',
241             '928d02b0-7143-4ec9-b5ac-9554f02d3fb1' => 'integer',
242             'dea3782c-6bcb-4ce9-8a39-f8dab399d75d' => 'unsigned-integer',
243             '6ba648c2-3657-47c2-8541-9b73c3a9b2b4' => 'default-context',
244             '52a516d0-25d8-47c7-a6ba-80983e576c54' => 'proto-file',
245             '1cd4a6c6-0d7c-48d1-81e7-4e8d41fdb45d' => 'final-file-size',
246             '6085f87e-4797-4bb2-b23d-85ff7edc1da0' => 'text-fragment',
247             '4c9656eb-c130-42b7-9348-a1fee3f42050' => 'also-list-contains-also',
248             '298ef373-9731-491d-824d-b2836250e865' => 'proto-message',
249             '7be4d8c7-6a75-44cc-94f7-c87433307b26' => 'proto-entity',
250             '65bb36f2-b558-48af-8512-bca9150cca85' => 'proxy-type',
251             'a1c478b5-0a85-4b5b-96da-d250db14a67c' => 'flagged-as',
252             '59cfe520-ba32-48cc-b654-74f7a05779db' => 'marked-as',
253             '2bffc55d-7380-454e-bd53-c5acd525d692' => 'roaraudio-error-number',
254             'd2750351-aed7-4ade-aa80-c32436cc6030' => 'also-has-role',
255             '11d8962c-0a71-4d00-95ed-fa69182788a8' => 'also-has-comment',
256             '30710bdb-6418-42fb-96db-2278f3bfa17f' => 'also-has-description',
257             '448c50a8-c847-4bc7-856e-0db5fea8f23b' => 'final-file-encoding',
258             '79385945-0963-44aa-880a-bca4a42e9002' => 'final-file-hash',
259             '3fde5688-6e34-45e9-8f33-68f079b152c8' => 'SEEK_SET',
260             'bc598c52-642e-465b-b079-e9253cd6f190' => 'SEEK_CUR',
261             '06aff30f-70e8-48b4-8b20-9194d22fc460' => 'SEEK_END',
262             '59a5691a-6a19-4051-bc26-8db82c019df3' => 'inode',
263             '53863a15-68d4-448d-bd69-a9b19289a191' => 'unsigned-integer-generator',
264             'e8aa9e01-8d37-4b4b-8899-42ca0a2a906f' => 'signed-integer-generator',
265             'd74f8c35-bcb8-465c-9a77-01010e8ed25c' => 'unicode-character-generator',
266             '55febcc4-6655-4397-ae3d-2353b5856b34' => 'rgb-colour-generator',
267             '97b7f241-e1c5-4f02-ae3c-8e31e501e1dc' => 'date-generator',
268             '19659233-0a22-412c-bdf1-8ee9f8fc4086' => 'multiplicity-generator',
269             '5ec197c3-1406-467c-96c7-4b1a6ec2c5c9' => 'minimum-multiplicity-generator',
270             );
271              
272             foreach my $ise (keys %tagnames) {
273             my $identifier = __PACKAGE__->new(ise => $ise);
274             $identifier->{tagname} //= [$tagnames{$ise}];
275             $identifier->register; # re-register
276             }
277             }
278              
279             {
280             # ISE -> namespace
281             my %namespaces_uint = (
282             '4a7fc2e2-854b-42ec-b24f-c7fece371865' => 'ac59062c-6ba2-44de-9f54-09e28f2c0b5c', # e621-post-identifier: e621-post-namespace
283             'a0a4fae2-be6f-4a51-8326-6110ba845a16' => '69b7ff38-ca78-43a8-b9ea-66cb02312eef', # e621-pool-identifier: e621-pool-namespace
284             '6e3590b6-2a0c-4850-a71f-8ba196a52280' => 'b96e5d94-0767-40fa-9864-5977eb507ae0', # danbooru2chanjp-post-identifier: danbooru2chanjp-post-namespace
285             );
286             my %namespaces_sint = (
287             '2bffc55d-7380-454e-bd53-c5acd525d692' => '744eaf4e-ae93-44d8-9ab5-744105222da6', # roaraudio-error-number: roaraudio-error-namespace
288             );
289             my %namespaces_simple_tag = (
290             '6fe0dbf0-624b-48b3-b558-0394c14bad6a' => '3623de4d-0dd4-4236-946a-2613467d50f1', # e621tag: e621tag-namespace
291             'c5632c60-5da2-41af-8b60-75810b622756' => '93f2c36b-8cb6-4f2c-924b-98188f224235', # danbooru2chanjp-tag: danbooru2chanjp-tag-namespace
292             );
293              
294             foreach my $ise (keys %namespaces_uint) {
295             my $identifier = __PACKAGE__->new(ise => $ise);
296             $identifier->{namespace} //= __PACKAGE__->new(ise => $namespaces_uint{$ise});
297             $identifier->{validate} //= RE_UINT;
298             $identifier->{generate} //= 'id-based';
299             $identifier->register; # re-register
300             }
301              
302             foreach my $ise (keys %namespaces_sint) {
303             my $identifier = __PACKAGE__->new(ise => $ise);
304             $identifier->{namespace} //= __PACKAGE__->new(ise => $namespaces_sint{$ise});
305             $identifier->{validate} //= RE_SINT;
306             $identifier->{generate} //= 'id-based';
307             $identifier->register; # re-register
308             }
309              
310             foreach my $ise (keys %namespaces_simple_tag) {
311             my $identifier = __PACKAGE__->new(ise => $ise);
312             $identifier->{namespace} //= __PACKAGE__->new(ise => $namespaces_simple_tag{$ise});
313             $identifier->{validate} //= RE_SIMPLE_TAG;
314             $identifier->{generate} //= 'id-based';
315             $identifier->register; # re-register
316             }
317              
318             # validate => RE_QID, namespace => NS_FC, generate => 'id-based'
319             }
320              
321             # Call this after after we loaded all our stuff and before anyone else will register stuff:
322             __PACKAGE__->_known_provider('wellknown');
323              
324              
325             sub new {
326 1243     1243 1 7262 my ($pkg, $type, $id, %opts) = @_;
327 1243         1381 my $self = bless {};
328              
329 1243 50       1723 croak 'No type given' unless defined $type;
330 1243 50       1440 croak 'No id given' unless defined $id;
331              
332 1243 100 100     2669 if (!ref($type) && $type eq 'from') {
333 85 100       110 if (ref($id)) {
334 8         8 my $from = $id;
335 8 50 0     19 if ($id->isa('Data::Identifier')) {
    0 0        
    0 0        
    0 0        
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
336 8 50       11 if (scalar(keys %opts)) {
337 0         0 $type = $id->type;
338 0         0 $id = $id->id;
339             } else {
340 8         18 return $id;
341             }
342             } elsif ($id->isa('URI')) {
343 0         0 $type = 'uri';
344             } elsif ($id->isa('Mojo::URL')) {
345 0         0 $type = 'uri';
346 0         0 $id = $id->to_string;
347             } elsif ($id->isa('Data::URIID::Result')) {
348 0   0 0   0 $opts{displayname} //= sub { return $from->attribute('displayname', default => undef) };
  0         0  
349 0         0 $type = $id->id_type;
350 0         0 $id = $id->id;
351             } elsif ($id->isa('Data::URIID::Base') || $id->isa('Data::URIID::Colour') || $id->isa('Data::URIID::Service')) {
352             #$opts{displayname} //= $id->name if $id->isa('Data::URIID::Service');
353 0   0     0 $opts{displayname} //= $id->displayname(default => undef, no_defaults => 1);
354 0         0 $type = 'ise';
355 0         0 $id = $id->ise;
356             } elsif ($id->isa('Data::TagDB::Tag')) {
357 0   0 0   0 $opts{displayname} //= sub { $from->displayname };
  0         0  
358 0         0 $type = 'ise';
359 0         0 $id = $id->ise;
360             } elsif ($id->isa('File::FStore::File') || $id->isa('File::FStore::Adder') || $id->isa('File::FStore::Base')) {
361 0         0 $type = 'ise';
362 0         0 $id = $id->contentise;
363             } elsif ($id->isa('SIRTX::Datecode')) {
364 0         0 $id = $id->as('Data::Identifier');
365 0 0       0 unless (scalar(keys %opts)) {
366 0         0 return $id->as('Data::Identifier');
367             }
368 0         0 $type = $id->type;
369 0         0 $id = $id->id;
370             } elsif ($id->isa('Business::ISBN')) {
371 0         0 $type = $well_known{gtin};
372 0         0 $id = $id->as_isbn13->as_string([]);
373             } elsif ($id->isa('Data::Identifier::Interface::Simple')) {
374             # TODO: We cannot call $id->as('Data::Identifier') here as much as that would be fun,
375             # as this might in turn call exactly this code again resulting in a deep recursion.
376             # A future version might come up with some trick here.
377 0         0 $type = 'ise';
378 0         0 $id = $id->ise;
379             } elsif ($id->isa('JSON::PP::Boolean') || $id->isa('JSON::XS::Boolean')) {
380 0         0 require Data::Identifier::Util;
381 0         0 return Data::Identifier::Util->from_bool($id);
382             } else {
383 0         0 croak 'Unsupported input data';
384             }
385             } else {
386             # If it's not a ref, try as ise.
387 77         76 $type = 'ise';
388             }
389             }
390              
391 1235 100 100     2462 if (!ref($type) && $type eq 'ise') {
392 931 50       997 croak 'Undefined identifier but type is ISE' unless defined $id;
393              
394 931 100       3058 if ($id =~ /^[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\z/) { # allow less normalised form than RE_UUID
    50          
    50          
395 923         767 $type = $well_known_uuid;
396              
397             # For bootstrap only.
398 923 100 66     1349 if (!defined($type) && $id eq '8be115d2-dc2f-4a98-91e1-a6e3075cbc31') {
399 7         63 $self->{type} = $well_known_uuid = $type = $self;
400 7         11 $self->{id} = $id;
401             }
402             } elsif ($id =~ RE_OID) {
403 0         0 $type = 'oid';
404             } elsif ($id =~ RE_URI) {
405 8         9 $type = 'uri';
406             } else {
407 0         0 croak 'Not a valid ISE identifier';
408             }
409             }
410              
411 1235 100       1445 unless (ref $type) {
412 213 100       452 if ($type =~ /^[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\z/) { # allow less normalised form than RE_UUID
    100          
413 6         22 $type = $pkg->new(uuid => $type);
414 6         14 $type->register;
415             } elsif ($type eq 'wellknown') {
416 8         27 $self = $well_known{$id};
417 8 50       26 croak 'Unknown well-known' unless defined $self;
418 8         35 return $self;
419             } else {
420 199         255 $type = $well_known{$type};
421             }
422 205 50       299 croak 'Unknown type name' unless defined $type;
423             }
424              
425 1227 50       2304 croak 'Not a valid type' unless $type->isa(__PACKAGE__);
426              
427             # we normalise URIs first as they may then normalised again
428 1227 100 100     2419 if ($type == ($well_known{uri} // 0)) {
429 11         12 my $uri = $id.''; # force stringification
430              
431 11 100       106 if ($uri =~ m#^urn:uuid:([0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12})\z#) {
    50          
    50          
    50          
    100          
432 1         2 $id = $1;
433 1         2 $type = $well_known_uuid;
434             } elsif ($uri =~ m#^urn:oid:([0-2](?:\.(?:0|[1-9][0-9]*))+)\z#) {
435 0         0 $id = $1;
436 0         0 $type = $well_known{oid};
437             } elsif ($uri =~ m#^https?://www\.wikidata\.org/entity/([QPL][1-9][0-9]*)\z#) {
438 0         0 $id = $1;
439 0         0 $type = $well_known{wd};
440             } elsif ($uri =~ m#^https?://doi\.org/(10\..+)\z#) {
441 0         0 $id = $1;
442 0         0 $type = $well_known{doi};
443             } elsif ($uri =~ m#^https?://uriid\.org/([^/]+)/[^/]+#) {
444 2         6 my $ptype = $1;
445 2 50 66     11 if (defined($uuid_org_to_uuid{$ptype}) || $ptype =~ RE_UUID) {
446 2         9 my $u = URI->new($uri);
447 2         7488 my @path_segments = $u->path_segments;
448 2 50 33     116 if (scalar(@path_segments) == 3 && $path_segments[0] eq '') {
449 2   66     30 $type = $pkg->new(uuid => ($uuid_org_to_uuid{$path_segments[1]} // $path_segments[1]));
450 2         12 $id = $path_segments[2];
451             }
452             }
453             }
454             }
455              
456 1227 100 50     2040 if ($type == ($well_known_uuid // 0)) {
    100 50        
457 1135         1411 $id = lc($id); # normalise
458             } elsif ($type == ($well_known{oid} // 0)) {
459 1 50       5 if ($id =~ /^2\.25\.([1-9][0-9]*)\z/) {
460 1         4 my $hex = Math::BigInt->new($1)->as_hex;
461 1         433 $hex =~ s/^0x//;
462 1         4 $hex = ('0' x (32 - length($hex))) . $hex;
463 1         16 $hex =~ s/^(.{8})(.{4})(.{4})(.{4})(.{12})\z/$1-$2-$3-$4-$5/;
464 1         2 $type = $well_known_uuid;
465 1         2 $id = $hex;
466             }
467             }
468              
469 1227 100       1482 if (defined(my $v = $registered{$type->uuid}{$id})) {
470 617         1192 return $v;
471             }
472              
473              
474 610 100       846 if (defined $type->{validate}) {
475 601 50       3807 croak 'Identifier did not validate against type' unless $id =~ $type->{validate};
476             }
477              
478 610         951 $self->{type} = $type;
479 610         652 $self->{id} = $id;
480              
481 610         639 foreach my $key (qw(validate namespace generator request generate displayname)) {
482 3660 100       4273 next unless defined $opts{$key};
483 200   66     499 $self->{$key} //= $opts{$key};
484             }
485              
486 610         567 foreach my $key (qw(namespace generator)) {
487 1220 100       1674 if (defined(my $v = $self->{$key})) {
488 3 50       5 unless (ref $v) {
489 3         7 $self->{$key} = $pkg->new(from => $v)->register;
490             }
491             }
492             }
493              
494 610 50       753 if (defined(my $tagname = $opts{tagname})) {
495 0         0 my %tagnames;
496 0 0       0 $tagname = [$tagname] unless ref $tagname;
497 0         0 %tagnames = map {$_ => undef} grep {defined} @{$tagname};
  0         0  
  0         0  
  0         0  
498 0         0 $tagname = [keys %tagnames];
499 0 0       0 if (scalar(@{$tagname})) {
  0         0  
500 0         0 $self->{tagname} = $tagname;
501             }
502             }
503              
504 610         1257 return bless $self;
505             }
506              
507              
508             #@returns __PACKAGE__
509             sub random {
510 0     0 1 0 my ($pkg, %opts) = @_;
511 0   0     0 my $type = $opts{type} // 'uuid';
512              
513 0 0       0 if (ref $type) {
514 0 0       0 if ($type == $well_known_uuid) {
515 0         0 $type = 'uuid';
516             } else {
517 0         0 croak 'Invalid/Unsupported type';
518             }
519             }
520              
521 0 0 0     0 if ($type ne 'ise' && $type ne 'uuid') {
522 0         0 croak 'Invalid/Unsupported type';
523             }
524              
525 0         0 require Data::Identifier::Generate;
526 0         0 my $uuid = Data::Identifier::Generate->_random(%opts{'sources'});
527 0         0 return $pkg->new(uuid => $uuid, %opts{'displayname'});
528             }
529              
530              
531              
532             #@deprecated
533             sub wellknown {
534 0     0 1 0 my ($pkg, @args) = @_;
535 0         0 return $pkg->known('wellknown', @args);
536             }
537              
538              
539             #@returns __PACKAGE__
540             sub type {
541 58     58 1 1927 my ($self) = @_;
542 58         124 return $self->{type};
543             }
544              
545              
546              
547             sub id {
548 29     29 1 53 my ($self) = @_;
549 29         82 return $self->{id};
550             }
551              
552              
553             sub uuid {
554 8165     8165 1 14709 my ($self, %opts) = @_;
555              
556 8165 100 100     20483 return $self->{id_cache}{WK_UUID()} if !$opts{no_defaults} && defined($self->{id_cache}) && defined($self->{id_cache}{WK_UUID()});
      100        
557              
558 8161 100       9954 if ($self->{type} == $well_known_uuid) {
559 8116         17020 return $self->{id};
560             }
561              
562 45 100       62 unless ($opts{no_defaults}) {
563             # Try to generate a UUID and recheck cache:
564 23         38 $self->_generate;
565 23 100 66     76 return $self->{id_cache}{WK_UUID()} if defined($self->{id_cache}) && defined($self->{id_cache}{WK_UUID()});
566             }
567              
568 38 50       88 return $opts{default} if exists $opts{default};
569 0         0 croak 'Identifier has no valid UUID';
570             }
571              
572             sub oid {
573 1037     1037 1 1086 my ($self, %opts) = @_;
574 1037         947 my $type = $well_known{oid};
575              
576 1037 100 66     3087 return $self->{id_cache}{WK_OID()} if !$opts{no_defaults} && defined($self->{id_cache}) && defined($self->{id_cache}{WK_OID()});
      100        
577              
578 515 50       683 if ($self->{type} == $type) {
579 0         0 return $self->{id};
580             }
581              
582 515 50       691 unless ($opts{no_defaults}) {
583 515 100       569 if (defined(my $uuid = $self->uuid(default => undef))) {
584 507         1867 return $self->{id_cache}{WK_OID()} = sprintf('2.25.%s', Math::BigInt->new('0x'.$uuid =~ tr/-//dr));
585             }
586             }
587              
588 8 50       17 return $opts{default} if exists $opts{default};
589 0         0 croak 'Identifier has no valid OID';
590             }
591              
592             sub uri {
593 1038     1038 1 1384 my ($self, %opts) = @_;
594 1038         971 my $type = $well_known{uri};
595              
596 1038 100 66     4105 if (!$opts{no_defaults} && !defined($opts{style}) && defined($self->{id_cache}) && defined($self->{id_cache}{WK_URI()})) {
      100        
      100        
597 522         851 return $self->{id_cache}{WK_URI()};
598             }
599              
600 516 100       690 if ($self->{type} == $type) {
601 8         17 return $self->{id};
602             }
603              
604 508   100     1360 $opts{style} //= 'urn';
605              
606 508 50       654 unless ($opts{no_defaults}) {
607 508 100 66     1372 if ($self->{type} == $well_known{wd}) {
    50 33        
    100 33        
    50          
608 4         15 return $self->{id_cache}{WK_URI()} = sprintf('http://www.wikidata.org/entity/%s', $self->{id});
609             } elsif ($self->{type} == $well_known{doi}) {
610 0         0 return $self->{id_cache}{WK_URI()} = sprintf('https://doi.org/%s', $self->{id});
611             } elsif (defined(my $uuid = $self->uuid(default => undef)) && $opts{style} eq 'urn') {
612 503         1415 return $self->{id_cache}{WK_URI()} = sprintf('urn:uuid:%s', $uuid);
613             } elsif ($enabled_oid && defined(my $oid = $self->oid(default => undef)) && $opts{style} eq 'urn') {
614 0         0 return $self->{id_cache}{WK_URI()} = sprintf('urn:oid:%s', $oid);
615             } else {
616 1         466 my $u = URI->new("https://uriid.org/");
617 1         7616 my $type_uuid = $self->{type}->uuid;
618 1   33     8 $u->path_segments('', $uuid_to_uriid_org{$type_uuid} // $type_uuid, $self->{id});
619 1         117 return $self->{id_cache}{WK_URI()} = $u;
620             }
621             }
622              
623 0 0       0 return $opts{default} if exists $opts{default};
624 0         0 croak 'Identifier has no valid URI';
625             }
626              
627             sub sid {
628 1040     1040 1 1213 my ($self, %opts) = @_;
629 1040         937 my $type = $well_known{sid};
630 1040 100 100     2608 return $self->{id_cache}{WK_SID()} if defined($self->{id_cache}) && defined($self->{id_cache}{WK_SID()});
631 405 50       557 if ($self->{type} == $type) {
632 0         0 return $self->{id};
633             }
634              
635 405 50       987 return $opts{default} if exists $opts{default};
636 0         0 croak 'Identifier has no valid SID';
637             }
638              
639              
640              
641             sub ise {
642 22     22 1 28 my ($self, %opts) = @_;
643 22         30 my $type = $self->{type};
644 22         28 my $have_default = exists $opts{default};
645 22         19 my $default = delete $opts{default};
646 22         15 my $value;
647              
648 22 50 33     59 if ($type == $well_known{uuid} || $type == $well_known{oid} || $type == $well_known{uri}) {
      33        
649 22         27 $value = $self->{id};
650             } else {
651 0         0 $opts{default} = undef;
652 0   0     0 $value = $self->uuid(%opts) // $self->oid(%opts) // $self->uri(%opts);
      0        
653             }
654              
655 22 50       80 return $value if defined $value;
656 0 0       0 return $default if $have_default;
657 0         0 croak 'Identifier has no valid ISE';
658             }
659              
660              
661             sub as {
662 130     130 1 398 my ($self, $as, %opts) = @_;
663              
664 130 100 66     513 $as = $opts{rawtype} if $as eq 'raw' && defined($opts{rawtype});
665              
666 130 100 66     307 if (ref($as) && eval {$as->isa(__PACKAGE__)}) {
  6         28  
667 6         18 my $type_uuid = $as->uuid;
668 6         10 my $next_type;
669              
670 6 50       33 return $self->id if $self->type->eq($as);
671              
672 6         13 foreach my $test (qw(uuid oid uri sid)) {
673 24 100       60 if ($as == $well_known{$test}) {
674 3         5 $next_type = $test;
675 3         5 last;
676             }
677             }
678              
679 6 100       15 if (defined $next_type) {
680 3 0 33     9 return $self->{id_cache}{$type_uuid} if !$opts{no_defaults} && defined($self->{id_cache}) && defined($self->{id_cache}{$type_uuid});
      33        
681 3         7 $as = $next_type;
682             } else {
683 3 50 33     29 return $self->{id_cache}{$type_uuid} if defined($self->{id_cache}) && defined($self->{id_cache}{$type_uuid});
684 0 0       0 return $opts{default} if exists $opts{default};
685 0         0 croak 'Unknown/Unsupported as: '.$as;
686             }
687             }
688              
689 127 100 66     457 return $self if ($as =~ /^[A-Z]/ || $as =~ /::/) && eval {$self->isa($as)};
  124   66     780  
690              
691 3 50       17 if ($self->isa('Data::Identifier::Interface::Subobjects')) {
692 0         0 require Data::Identifier::Interface::Subobjects; # Is this required?
693 0   0     0 $opts{$_} //= $self->so_get($_, default => undef) foreach Data::Identifier::Interface::Subobjects->KEYS;
694             }
695              
696 3 50       9 if (defined(my $so = $opts{so})) {
697 0         0 require Data::Identifier::Interface::Subobjects; # Is this required?
698 0   0     0 $opts{$_} //= $so->so_get($_, default => undef) foreach Data::Identifier::Interface::Subobjects->KEYS;
699             }
700              
701 3 50       4 $self = __PACKAGE__->new(from => $self) unless eval {$self->isa(__PACKAGE__)};
  3         11  
702              
703 3 50 33     29 if ($as eq 'uuid' || $as eq 'oid' || $as eq 'uri' || $as eq 'sid' || $as eq 'ise') {
    0 33        
    0 33        
    0 33        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
704 3         10 my $func = $self->can($as);
705 3         9 return $self->$func(%opts);
706             } elsif ($as eq __PACKAGE__) {
707 0         0 return $self;
708             } elsif ($as eq 'URI') {
709 0         0 my $had_default = exists $opts{default};
710 0         0 my $default = delete $opts{default};
711 0         0 my $val = $self->uri(%opts, default => undef);
712              
713 0 0       0 return URI->new($val) if defined $val;
714 0 0       0 if ($had_default) {
715 0 0       0 return $default if ref $default;
716 0         0 return URI->new($default);
717             }
718 0         0 croak 'No value for URI';
719             } elsif ($as eq 'Mojo::URL') {
720 0         0 my $had_default = exists $opts{default};
721 0         0 my $default = delete $opts{default};
722 0         0 my $val = $self->uri(%opts, default => undef);
723              
724 0         0 require Mojo::URL;
725              
726 0 0       0 return Mojo::URL->new($val) if defined $val;
727 0 0       0 if ($had_default) {
728 0 0       0 return $default if ref $default;
729 0         0 return Mojo::URL->new($default);
730             }
731 0         0 croak 'No value for URI';
732             } elsif ($as eq 'Data::URIID::Result' && defined($opts{extractor})) {
733 0         0 return $opts{extractor}->lookup($self->type->uuid => $self->id);
734             } elsif ($as eq 'Data::URIID::Service' && defined($opts{extractor})) {
735 0         0 return $opts{extractor}->service($self->uuid);
736             } elsif ($as eq 'SIRTX::Datecode' && eval {
737 0         0 require SIRTX::Datecode;
738 0         0 SIRTX::Datecode->VERSION(v0.03);
739 0         0 1;
740             }) {
741 0         0 return SIRTX::Datecode->new(from => $self);
742             } elsif ($as eq 'Data::URIID::Colour' && eval {
743 0         0 require Data::URIID;
744 0         0 require Data::URIID::Colour;
745 0         0 Data::URIID::Colour->VERSION(v0.14);
746 0         0 1;
747             }) {
748 0         0 return Data::URIID::Colour->new(from => $self, %opts{qw(extractor db fii store)});
749             } elsif ($as eq 'Data::TagDB::Tag' && defined($opts{db})) {
750 0 0       0 if ($opts{autocreate}) {
751 0         0 return $opts{db}->create_tag($self);
752             } else {
753 0         0 return $opts{db}->tag_by_id($self);
754             }
755             } elsif ($as eq 'File::FStore::File' && defined($opts{store})) {
756 0         0 return scalar($opts{store}->query(ise => $self));
757             } elsif ($as eq 'Business::ISBN' && $self->type->eq('gtin')) {
758 0         0 require Business::ISBN;
759 0         0 my $val = Business::ISBN->new($self->id);
760 0 0 0     0 return $val if defined($val) && $val->is_valid;
761             }
762              
763 0 0       0 return $opts{default} if exists $opts{default};
764 0         0 croak 'Unknown/Unsupported as: '.$as;
765             }
766              
767              
768             sub eq {
769 41     41 1 88 my ($self, $other) = @_;
770              
771 41         75 foreach my $e ($self, $other) {
772 82 100 66     200 if (defined($e) && !scalar(eval {$e->isa(__PACKAGE__)})) {
  82         306  
773 4 50       10 if (defined $well_known{$e}) {
774 0         0 $e = $well_known{$e}
775             } else {
776 4         8 $e = Data::Identifier->new(from => $e);
777             }
778             }
779             }
780              
781 41 50       62 if (defined($self)) {
782 41 50       68 return undef unless defined $other;
783 41 100       179 return 1 if $self == $other;
784 11 50       20 return undef unless $self->type->eq($other->type);
785 11         21 return $self->id eq $other->id;
786             } else {
787 0         0 return !defined($other);
788             }
789             }
790              
791              
792             sub cmp {
793 0     0 1 0 my ($self, $other) = @_;
794              
795 0         0 foreach my $e ($self, $other) {
796 0 0 0     0 if (defined($e) && !scalar(eval {$e->isa(__PACKAGE__)})) {
  0         0  
797 0 0       0 if (defined $well_known{$e}) {
798 0         0 $e = $well_known{$e}
799             } else {
800 0         0 $e = Data::Identifier->new(from => $e);
801             }
802             }
803             }
804              
805 0 0       0 if (defined($self)) {
806 0 0       0 return undef unless defined $other;
807 0 0       0 return 0 if $self == $other;
808 0 0       0 if ((my $r = $self->type->cmp($other->type)) != 0) {
809 0         0 return $r;
810             }
811              
812             {
813 0         0 my $self_id = $self->id;
  0         0  
814 0         0 my $other_id = $other->id;
815              
816 0 0 0     0 if ((my ($sa, $sb) = $self_id =~ /^([^0-9]*)([0-9]+)\z/) && (my ($oa, $ob) = $other_id =~ /^([^0-9]*)([0-9]+)\z/)) {
817 0         0 my $r = $sa cmp $oa;
818 0 0       0 return $r if $r;
819 0         0 return $sb <=> $ob;
820             }
821              
822 0         0 return $self_id cmp $other_id;
823             }
824             } else {
825 0         0 return !defined($other);
826             }
827             }
828              
829              
830             sub null_to_undef {
831 0     0 1 0 my ($self, @opts) = @_;
832              
833 0 0       0 croak 'Stray options passed' if scalar @opts;
834              
835 0 0       0 return undef unless defined $self;
836              
837 0 0       0 unless (eval {$self->isa(__PACKAGE__)}) {
  0         0  
838 0         0 $self = __PACKAGE__->new(from => $self);
839             }
840              
841 0 0       0 return undef if $self->eq('null');
842              
843 0         0 return $self;
844             }
845              
846              
847             #@returns __PACKAGE__
848             sub namespace {
849 7     7 1 13 my ($self, %opts) = @_;
850 7         11 my $has_default = exists $opts{default};
851 7         7 my $default = delete $opts{default};
852              
853 7         7 delete $opts{no_defaults};
854              
855 7 50       48 croak 'Stray options passed' if scalar keys %opts;
856              
857 7 50       40 return $self->{namespace} if defined $self->{namespace};
858              
859 0 0       0 return $default if $has_default;
860              
861 0         0 croak 'No namespace';
862             }
863              
864              
865             #@returns __PACKAGE__
866             sub generator {
867 0     0 1 0 my ($self, %opts) = @_;
868 0         0 my $has_default = exists $opts{default};
869 0         0 my $default = delete $opts{default};
870              
871 0         0 delete $opts{no_defaults};
872              
873 0 0       0 croak 'Stray options passed' if scalar keys %opts;
874              
875 0 0       0 return $self->{generator} if defined $self->{generator};
876              
877 0 0       0 return $default if $has_default;
878              
879 0         0 croak 'No generator';
880             }
881              
882              
883             sub request {
884 0     0 1 0 my ($self, %opts) = @_;
885 0         0 my $has_default = exists $opts{default};
886 0         0 my $default = delete $opts{default};
887              
888 0         0 delete $opts{no_defaults};
889              
890 0 0       0 croak 'Stray options passed' if scalar keys %opts;
891              
892 0 0       0 return $self->{request} if defined $self->{request};
893              
894 0 0       0 return $default if $has_default;
895              
896 0         0 croak 'No request';
897             }
898              
899              
900             #@returns __PACKAGE__
901             sub register {
902 1030     1030 1 1115 my ($self) = @_;
903 1030         1266 $registered{$self->{type}->uuid}{$self->{id}} = $self;
904              
905 1030         1109 foreach my $type_name (qw(uuid oid uri sid)) {
906 4120   50     7027 my $f = $self->can($type_name) || next;
907 4120   100     4202 my $v = $self->$f(default => undef) // next;
908 3699         250671 $registered{$well_known{$type_name}->uuid}{$v} = $self;
909             }
910              
911 1030         816 foreach my $extra (keys %{$self->{id_cache}}) {
  1030         1971  
912 2887   50     3472 my $v = $self->{id_cache}{$extra} // next;
913 2887         3367 $registered{$extra}{$v} = $self;
914             }
915              
916 1030         3625 return $self;
917             }
918              
919              
920              
921             sub displayname {
922 13     13 1 24 my ($self, %opts) = @_;
923              
924 13 50       28 if (defined(my $displayname = $self->{displayname})) {
925 0 0       0 $displayname = $self->$displayname() if ref $displayname;
926              
927             # recheck and return as any of the above conversions could result in $displayname becoming invalid.
928 0 0 0     0 return $displayname if defined($displayname) && length($displayname);
929             }
930              
931 13 50       27 if (defined(my $tagname = $self->tagname(default => undef, no_defaults => 1))) {
932 13         37 return $tagname;
933             }
934              
935 0 0       0 return $self->id.'' unless $opts{no_defaults}; # force stringification.
936 0 0       0 return $opts{default} if exists $opts{default};
937 0         0 croak 'No value for displayname';
938             }
939              
940              
941 0     0 1 0 sub displaycolour { my ($self, %opts) = @_; return $opts{default}; }
  0         0  
942 0     0 1 0 sub icontext { my ($self, %opts) = @_; return $opts{default}; }
  0         0  
943 0     0 1 0 sub description { my ($self, %opts) = @_; return $opts{default}; }
  0         0  
944              
945              
946             sub tagname {
947 17     17 1 66 my ($self, %opts) = @_;
948 17         27 my $had_default = exists $opts{default};
949 17         19 my $default = delete $opts{default};
950 17         20 my $list = delete $opts{list};
951              
952 17         17 delete $opts{no_defaults}; # for compatibility.
953              
954 17 50       33 croak 'Stray options passed' if scalar keys %opts;
955              
956 17 100       30 if (defined(my $tagname = $self->{tagname})) {
957 13 50       20 return @{$tagname} if $list;
  0         0  
958              
959 13         30 return $tagname->[0];
960             }
961              
962 4 50       7 if ($had_default) {
963 4 50       7 return @{$default} if $list;
  4         13  
964 0         0 return $default;
965             }
966 0         0 croak 'No value for tagname found';
967             }
968              
969             # ---- Private helpers ----
970              
971             sub import {
972 15     15   934 my ($pkg, $opts) = @_;
973 15 50       3706 return unless defined $opts;
974 0 0       0 croak 'Bad options' unless ref($opts) eq 'HASH';
975              
976 0 0       0 if (defined(my $disable = $opts->{disable})) {
977 0 0       0 $disable = [split /\s*,\s*/, $disable] unless ref $disable;
978 0         0 foreach my $to_disable (@{$disable}) {
  0         0  
979 0 0       0 if ($to_disable eq 'oid') {
980 0         0 $enabled_oid = undef;
981 0         0 undef *oid;
982             } else {
983 0         0 croak 'Unknown feature: '.$to_disable;
984             }
985             }
986             }
987             }
988              
989             sub _generate {
990 23     23   26 my ($self) = @_;
991 23 100       34 unless (exists $self->{_generate}) {
992 15         22 my __PACKAGE__ $type = $self->type;
993              
994 15 100       57 if (defined(my $generate = $type->{generate})) {
995 7 50       26 unless (ref $generate) {
996 7         20 $self->{generate} = $generate = {style => $generate};
997             }
998              
999 7   50     28 $self->{id_cache} //= {};
1000              
1001 7 50       11 if (defined(my __PACKAGE__ $ns = eval {$type->namespace->uuid})) {
  7         17  
1002 7         10 my $style = $generate->{style};
1003 7         10 my $input;
1004              
1005 7 50       16 if ($style eq 'id-based') {
1006 7         14 $input = lc($self->id);
1007             } else {
1008 0         0 croak 'Unsupported generator style';
1009             }
1010              
1011 7 50       13 if (defined $input) {
1012 7         43 require Data::Identifier::Generate;
1013 7         27 $self->{id_cache}{WK_UUID()} = Data::Identifier::Generate->_uuid_v5($ns, $input);
1014             }
1015             }
1016             }
1017             }
1018 23         36 $self->{_generate} = undef;
1019             }
1020              
1021             sub _known_provider {
1022 9     9   22 my ($pkg, $class, %opts) = @_;
1023 9 50       38 croak 'Unsupported options passed' if scalar(keys %opts);
1024              
1025 9 100 33     30 if ($class eq 'wellknown') {
    50          
1026 8         24 state $wellknown = do {
1027 7         39 my %hash = map{$_ => $_} values(%well_known), map {values %{$_}} values(%registered);
  1743         2251  
  49         40  
  49         446  
1028 7         252 [values %hash];
1029             };
1030              
1031 8         23 return ($wellknown, rawtype => __PACKAGE__);
1032             } elsif ($class eq 'registered' || $class eq ':all') {
1033 1         6 my %hash = map{$_ => $_} values(%well_known), map {values %{$_}} values(%registered);
  249         632  
  7         10  
  7         82  
1034 1         73 return ([values %hash], rawtype => __PACKAGE__);
1035             }
1036              
1037 0           croak 'Unsupported class';
1038             }
1039              
1040             1;
1041              
1042             __END__