#!/usr/bin/perl -w
our
$VERSION
= v0.09;
RE_UUID
=>
qr/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/
,
RE_OID
=>
qr/^[0-2](?:\.(?:0|[1-9][0-9]*))+$/
,
RE_URI
=>
qr/^[a-zA-Z][a-zA-Z0-9\+\.\-]+/
,
RE_UINT
=>
qr/^(?:0|[1-9][0-9]*)$/
,
RE_QID
=>
qr/^[QPL][1-9][0-9]*$/
,
RE_DOI
=>
qr/^10\.[1-9][0-9]+(?:\.[0-9]+)*\/
./,
RE_UNICODE
=>
qr/^U\+([0-9A-F]{4,7})$/
,
};
WK_UUID
=>
'8be115d2-dc2f-4a98-91e1-a6e3075cbc31'
,
WK_OID
=>
'd08dc905-bbf6-4183-b219-67723c3c8374'
,
WK_URI
=>
'a8d1637d-af19-49e9-9ef8-6bc1fbcf6439'
,
WK_SID
=>
'f87a38cb-fd13-4e15-866c-e49901adbec5'
,
WK_WD
=>
'ce7aae1e-a210-4214-926a-0ebca56d77e3'
,
WK_GTIN
=>
'82d529be-0f00-4b4f-a43f-4a22de5f5312'
,
WK_IBAN
=>
'b1418262-6bc9-459c-b4b0-a054d77db0ea'
,
WK_BIC
=>
'c8a3a132-f160-473c-b5f3-26a748f37e62'
,
WK_DOI
=>
'931f155e-5a24-499b-9fbb-ed4efefe27fe'
,
WK_FC
=>
'd576b9d1-47d4-43ae-b7ec-bbea1fe009ba'
,
WK_UNICODE_CP
=>
'5f167223-cc9c-4b2f-9928-9fe1b253b560'
,
NS_WD
=>
'9e10aca7-4a99-43ac-9368-6cbfa43636df'
,
NS_FC
=>
'6491f7a9-0b29-4ef1-992c-3681cea18182'
,
NS_INT
=>
'5dd8ddbb-13a8-4d6c-9264-36e6dd6f9c99'
,
NS_DATE
=>
'fc43fbba-b959-4882-b4c8-90a288b7d416'
,
NS_UNICODE_CP
=>
'132aa723-a373-48bf-a88d-69f1e00f00cf'
,
};
my
$enabled_oid
= 1;
my
%uuid_to_uriid_org
= (
WK_UUID() =>
'uuid'
,
WK_OID() =>
'oid'
,
WK_URI() =>
'uri'
,
WK_SID() =>
'sid'
,
WK_GTIN() =>
'gtin'
,
WK_WD() =>
'wikidata-identifier'
,
);
my
%uuid_org_to_uuid
=
map
{
$uuid_to_uriid_org
{
$_
} =>
$_
}
keys
%uuid_to_uriid_org
;
my
$well_known_uuid
= __PACKAGE__->new(
ise
=> WK_UUID,
validate
=> RE_UUID);
my
%well_known
= (
uuid
=>
$well_known_uuid
,
oid
=> __PACKAGE__->new(
$well_known_uuid
=> WK_OID,
validate
=> RE_OID),
uri
=> __PACKAGE__->new(
$well_known_uuid
=> WK_URI,
validate
=> RE_URI),
sid
=> __PACKAGE__->new(
$well_known_uuid
=> WK_SID,
validate
=> RE_UINT),
wd
=> __PACKAGE__->new(
$well_known_uuid
=> WK_WD,
validate
=> RE_QID,
namespace
=> NS_WD,
generate
=>
'id-based'
),
fc
=> __PACKAGE__->new(
$well_known_uuid
=> WK_FC,
validate
=> RE_QID,
namespace
=> NS_FC,
generate
=>
'id-based'
),
gtin
=> __PACKAGE__->new(
$well_known_uuid
=> WK_GTIN,
validate
=> RE_UINT),
iban
=> __PACKAGE__->new(
$well_known_uuid
=> WK_IBAN),
bic
=> __PACKAGE__->new(
$well_known_uuid
=> WK_BIC),
doi
=> __PACKAGE__->new(
$well_known_uuid
=> WK_DOI,
validate
=> RE_DOI),
unicodecp
=> __PACKAGE__->new(
$well_known_uuid
=> WK_UNICODE_CP,
validate
=> RE_UNICODE,
namespace
=> NS_UNICODE_CP,
generate
=>
'id-based'
),
);
my
%registered
;
$_
->register
foreach
values
%well_known
;
{
my
%wk_sids
= (
'ddd60c5c-2934-404f-8f2d-fcb4da88b633'
=> 1,
WK_UUID() => 2,
'bfae7574-3dae-425d-89b1-9c087c140c23'
=> 3,
'7f265548-81dc-4280-9550-1bd0aa4bf748'
=> 4,
WK_URI() => 5,
WK_OID() => 6,
'd0a4c6e2-ce2f-4d4c-b079-60065ac681f1'
=> 8,
WK_WD() => 9,
'923b43ae-a50e-4db3-8655-ed931d0dd6d4'
=> 10,
'eacbf914-52cf-4192-a42c-8ecd27c85ee1'
=> 11,
'928d02b0-7143-4ec9-b5ac-9554f02d3fb1'
=> 12,
'dea3782c-6bcb-4ce9-8a39-f8dab399d75d'
=> 13,
'6ba648c2-3657-47c2-8541-9b73c3a9b2b4'
=> 16,
'52a516d0-25d8-47c7-a6ba-80983e576c54'
=> 17,
'1cd4a6c6-0d7c-48d1-81e7-4e8d41fdb45d'
=> 18,
'6085f87e-4797-4bb2-b23d-85ff7edc1da0'
=> 19,
'4c9656eb-c130-42b7-9348-a1fee3f42050'
=> 20,
'298ef373-9731-491d-824d-b2836250e865'
=> 21,
'7be4d8c7-6a75-44cc-94f7-c87433307b26'
=> 22,
'65bb36f2-b558-48af-8512-bca9150cca85'
=> 23,
'a1c478b5-0a85-4b5b-96da-d250db14a67c'
=> 24,
'59cfe520-ba32-48cc-b654-74f7a05779db'
=> 25,
'2bffc55d-7380-454e-bd53-c5acd525d692'
=> 26,
WK_SID() => 27,
'd2750351-aed7-4ade-aa80-c32436cc6030'
=> 28,
'448c50a8-c847-4bc7-856e-0db5fea8f23b'
=> 32,
'79385945-0963-44aa-880a-bca4a42e9002'
=> 33,
'3fde5688-6e34-45e9-8f33-68f079b152c8'
=> 34,
'bc598c52-642e-465b-b079-e9253cd6f190'
=> 35,
'06aff30f-70e8-48b4-8b20-9194d22fc460'
=> 36,
'59a5691a-6a19-4051-bc26-8db82c019df3'
=> 37,
'2c7e15ed-aa2f-4e2f-9a1d-64df0c85875a'
=> 112,
WK_GTIN() => 160,
);
foreach
my
$ise
(
keys
%wk_sids
) {
my
$identifier
= __PACKAGE__->new(
ise
=>
$ise
);
$identifier
->{id_cache} //= {};
$identifier
->{id_cache}->{WK_SID()} //=
$wk_sids
{
$ise
};
$identifier
->register;
}
}
foreach
my
$ise
(NS_WD, NS_INT, NS_DATE) {
my
$identifier
= __PACKAGE__->new(
ise
=>
$ise
);
$identifier
->register;
}
{
my
%displaynames
= (
WK_UUID() =>
'uuid'
,
WK_OID() =>
'oid'
,
WK_URI() =>
'uri'
,
WK_SID() =>
'small-identifier'
,
WK_WD() =>
'wikidata-identifier'
,
WK_GTIN() =>
'gtin'
,
WK_IBAN() =>
'iban'
,
WK_BIC() =>
'bic'
,
WK_DOI() =>
'doi'
,
WK_FC() =>
'factgrid-identifier'
,
WK_UNICODE_CP() =>
'unicode-code-point'
,
NS_WD() =>
'Wikidata-namespace'
,
NS_FC() =>
'factgrid-namespace'
,
NS_INT() =>
'integer-namespace'
,
NS_DATE() =>
'gregorian-date-namespace'
,
NS_UNICODE_CP() =>
'unicode-character-namespace'
,
'ddd60c5c-2934-404f-8f2d-fcb4da88b633'
=>
'also-shares-identifier'
,
'bfae7574-3dae-425d-89b1-9c087c140c23'
=>
'tagname'
,
'7f265548-81dc-4280-9550-1bd0aa4bf748'
=>
'has-type'
,
'd0a4c6e2-ce2f-4d4c-b079-60065ac681f1'
=>
'language-tag-identifier'
,
'923b43ae-a50e-4db3-8655-ed931d0dd6d4'
=>
'specialises'
,
'eacbf914-52cf-4192-a42c-8ecd27c85ee1'
=>
'unicode-string'
,
'928d02b0-7143-4ec9-b5ac-9554f02d3fb1'
=>
'integer'
,
'dea3782c-6bcb-4ce9-8a39-f8dab399d75d'
=>
'unsigned-integer'
,
'6ba648c2-3657-47c2-8541-9b73c3a9b2b4'
=>
'default-context'
,
'52a516d0-25d8-47c7-a6ba-80983e576c54'
=>
'proto-file'
,
'1cd4a6c6-0d7c-48d1-81e7-4e8d41fdb45d'
=>
'final-file-size'
,
'6085f87e-4797-4bb2-b23d-85ff7edc1da0'
=>
'text-fragment'
,
'4c9656eb-c130-42b7-9348-a1fee3f42050'
=>
'also-list-contains-also'
,
'298ef373-9731-491d-824d-b2836250e865'
=>
'proto-message'
,
'7be4d8c7-6a75-44cc-94f7-c87433307b26'
=>
'proto-entity'
,
'65bb36f2-b558-48af-8512-bca9150cca85'
=>
'proxy-type'
,
'a1c478b5-0a85-4b5b-96da-d250db14a67c'
=>
'flagged-as'
,
'59cfe520-ba32-48cc-b654-74f7a05779db'
=>
'marked-as'
,
'2bffc55d-7380-454e-bd53-c5acd525d692'
=>
'roaraudio-error-number'
,
'd2750351-aed7-4ade-aa80-c32436cc6030'
=>
'also-has-role'
,
'448c50a8-c847-4bc7-856e-0db5fea8f23b'
=>
'final-file-encoding'
,
'79385945-0963-44aa-880a-bca4a42e9002'
=>
'final-file-hash'
,
'3fde5688-6e34-45e9-8f33-68f079b152c8'
=>
'SEEK_SET'
,
'bc598c52-642e-465b-b079-e9253cd6f190'
=>
'SEEK_CUR'
,
'06aff30f-70e8-48b4-8b20-9194d22fc460'
=>
'SEEK_END'
,
'59a5691a-6a19-4051-bc26-8db82c019df3'
=>
'inode'
,
'2c7e15ed-aa2f-4e2f-9a1d-64df0c85875a'
=>
'chat-0-word-identifier'
,
);
foreach
my
$ise
(
keys
%displaynames
) {
my
$identifier
= __PACKAGE__->new(
ise
=>
$ise
);
$identifier
->{displayname} //=
$displaynames
{
$ise
};
$identifier
->register;
}
}
{
my
%namespaces_uint
= (
'2bffc55d-7380-454e-bd53-c5acd525d692'
=>
'744eaf4e-ae93-44d8-9ab5-744105222da6'
,
'4a7fc2e2-854b-42ec-b24f-c7fece371865'
=>
'ac59062c-6ba2-44de-9f54-09e28f2c0b5c'
,
'a0a4fae2-be6f-4a51-8326-6110ba845a16'
=>
'69b7ff38-ca78-43a8-b9ea-66cb02312eef'
,
);
foreach
my
$ise
(
keys
%namespaces_uint
) {
my
$identifier
= __PACKAGE__->new(
ise
=>
$ise
);
$identifier
->{namespace} //= __PACKAGE__->new(
ise
=>
$namespaces_uint
{
$ise
});
$identifier
->{validate} //= RE_UINT;
$identifier
->{generate} //=
'id-based'
;
$identifier
->register;
}
}
__PACKAGE__->_known_provider(
'wellknown'
);
sub
new {
my
(
$pkg
,
$type
,
$id
,
%opts
) =
@_
;
my
$self
=
bless
{};
if
(!
ref
(
$type
) &&
$type
eq
'from'
) {
if
(
ref
(
$id
)) {
my
$from
=
$id
;
if
(
$id
->isa(
'Data::Identifier'
)) {
if
(
scalar
(
keys
%opts
)) {
$type
=
$id
->type;
$id
=
$id
->id;
}
else
{
return
$id
;
}
}
elsif
(
$id
->isa(
'URI'
)) {
$type
=
'uri'
;
}
elsif
(
$id
->isa(
'Data::URIID::Result'
)) {
$opts
{displayname} //=
sub
{
return
$from
->attribute(
'displayname'
,
default
=>
undef
) };
$type
=
$id
->id_type;
$id
=
$id
->id;
}
elsif
(
$id
->isa(
'Data::URIID::Base'
) ||
$id
->isa(
'Data::URIID::Colour'
) ||
$id
->isa(
'Data::URIID::Service'
)) {
$opts
{displayname} //=
$id
->displayname(
default
=>
undef
,
no_defaults
=> 1);
$type
=
'ise'
;
$id
=
$id
->ise;
}
elsif
(
$id
->isa(
'Data::TagDB::Tag'
)) {
$opts
{displayname} //=
sub
{
$from
->displayname };
$type
=
'ise'
;
$id
=
$id
->ise;
}
elsif
(
$id
->isa(
'Business::ISBN'
)) {
$type
=
$well_known
{gtin};
$id
=
$id
->as_isbn13->as_string([]);
}
else
{
croak
'Unsupported input data'
;
}
}
else
{
$type
=
'ise'
;
}
}
if
(!
ref
(
$type
) &&
$type
eq
'ise'
) {
croak
'Undefined identifier but type is ISE'
unless
defined
$id
;
if
(
$id
=~ /^[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$/) {
$type
=
$well_known_uuid
;
if
(!
defined
(
$type
) &&
$id
eq
'8be115d2-dc2f-4a98-91e1-a6e3075cbc31'
) {
$self
->{type} =
$well_known_uuid
=
$type
=
$self
;
$self
->{id} =
$id
;
}
}
elsif
(
$id
=~ RE_OID) {
$type
=
'oid'
;
}
elsif
(
$id
=~ RE_URI) {
$type
=
'uri'
;
}
else
{
croak
'Not a valid ISE identifier'
;
}
}
unless
(
ref
$type
) {
if
(
$type
=~ /^[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$/) {
$type
=
$pkg
->new(
uuid
=>
$type
);
$type
->register;
}
elsif
(
$type
eq
'wellknown'
) {
$self
=
$well_known
{
$id
};
croak
'Unknown well-known'
unless
defined
$self
;
return
$self
;
}
else
{
$type
=
$well_known
{
$type
};
}
croak
'Unknown type name'
unless
defined
$type
;
}
croak
'Not a valid type'
unless
$type
->isa(__PACKAGE__);
if
(
$type
== (
$well_known
{uri} // 0)) {
my
$uri
=
$id
.
''
;
if
(
$uri
=~ m
$id
= $1;
$type
=
$well_known_uuid
;
}
elsif
(
$uri
=~ m
$id
= $1;
$type
=
$well_known
{oid};
}
elsif
(
$uri
=~ m
$id
= $1;
$type
=
$well_known
{wd};
}
elsif
(
$uri
=~ m
$id
= $1;
$type
=
$well_known
{doi};
}
elsif
(
$uri
=~ m
my
$ptype
= $1;
if
(
defined
(
$uuid_org_to_uuid
{
$ptype
}) ||
$ptype
=~ RE_UUID) {
my
$u
= URI->new(
$uri
);
my
@path_segments
=
$u
->path_segments;
if
(
scalar
(
@path_segments
) == 3 &&
$path_segments
[0] eq
''
) {
$type
=
$pkg
->new(
uuid
=> (
$uuid_org_to_uuid
{
$path_segments
[1]} //
$path_segments
[1]));
$id
=
$path_segments
[2];
}
}
}
}
if
(
$type
== (
$well_known_uuid
// 0)) {
$id
=
lc
(
$id
);
}
elsif
(
$type
== (
$well_known
{oid} // 0)) {
if
(
$id
=~ /^2\.25\.([1-9][0-9]*)$/) {
my
$hex
= Math::BigInt->new($1)->as_hex;
$hex
=~ s/^0x//;
$hex
= (
'0'
x (32 -
length
(
$hex
))) .
$hex
;
$hex
=~ s/^(.{8})(.{4})(.{4})(.{4})(.{12})$/$1-$2-$3-$4-$5/;
$type
=
$well_known_uuid
;
$id
=
$hex
;
}
}
if
(
defined
(
my
$v
=
$registered
{
$type
->uuid}{
$id
})) {
return
$v
;
}
if
(
defined
$type
->{validate}) {
croak
'Identifier did not validate against type'
unless
$id
=~
$type
->{validate};
}
$self
->{type} =
$type
;
$self
->{id} =
$id
;
foreach
my
$key
(
qw(validate namespace generate displayname)
) {
next
unless
defined
$opts
{
$key
};
$self
->{
$key
} //=
$opts
{
$key
};
}
foreach
my
$key
(
qw(namespace)
) {
if
(
defined
(
my
$v
=
$self
->{
$key
})) {
unless
(
ref
$v
) {
$self
->{
$key
} =
$pkg
->new(
ise
=>
$v
);
}
}
}
return
bless
$self
;
}
sub
random {
my
(
$pkg
,
%opts
) =
@_
;
my
$type
=
$opts
{type} //
'uuid'
;
if
(
ref
$type
) {
if
(
$type
==
$well_known_uuid
) {
$type
=
'uuid'
;
}
else
{
croak
'Invalid/Unsupported type'
;
}
}
if
(
$type
ne
'ise'
&&
$type
ne
'uuid'
) {
croak
'Invalid/Unsupported type'
;
}
my
$uuid
= Data::Identifier::Generate->_random(
%opts
{
'sources'
});
return
$pkg
->new(
uuid
=>
$uuid
,
%opts
{
'displayname'
});
}
sub
wellknown {
my
(
$pkg
,
@args
) =
@_
;
return
$pkg
->known(
'wellknown'
,
@args
);
}
sub
type {
my
(
$self
) =
@_
;
return
$self
->{type};
}
sub
id {
my
(
$self
) =
@_
;
return
$self
->{id};
}
sub
uuid {
my
(
$self
,
%opts
) =
@_
;
return
$self
->{id_cache}{WK_UUID()}
if
!
$opts
{no_defaults} &&
defined
(
$self
->{id_cache}) &&
defined
(
$self
->{id_cache}{WK_UUID()});
if
(
$self
->{type} ==
$well_known_uuid
) {
return
$self
->{id};
}
unless
(
$opts
{no_defaults}) {
$self
->_generate;
return
$self
->{id_cache}{WK_UUID()}
if
defined
(
$self
->{id_cache}) &&
defined
(
$self
->{id_cache}{WK_UUID()});
}
return
$opts
{
default
}
if
exists
$opts
{
default
};
croak
'Identifier has no valid UUID'
;
}
sub
oid {
my
(
$self
,
%opts
) =
@_
;
my
$type
=
$well_known
{oid};
return
$self
->{id_cache}{WK_OID()}
if
!
$opts
{no_defaults} &&
defined
(
$self
->{id_cache}) &&
defined
(
$self
->{id_cache}{WK_OID()});
if
(
$self
->{type} ==
$type
) {
return
$self
->{id};
}
unless
(
$opts
{no_defaults}) {
if
(
defined
(
my
$uuid
=
$self
->uuid(
default
=>
undef
))) {
return
$self
->{id_cache}{WK_OID()} =
sprintf
(
'2.25.%s'
, Math::BigInt->new(
'0x'
.
$uuid
=~
tr
/-//dr));
}
}
return
$opts
{
default
}
if
exists
$opts
{
default
};
croak
'Identifier has no valid OID'
;
}
sub
uri {
my
(
$self
,
%opts
) =
@_
;
my
$type
=
$well_known
{uri};
return
$self
->{id_cache}{WK_URI()}
if
!
$opts
{no_defaults} &&
defined
(
$self
->{id_cache}) &&
defined
(
$self
->{id_cache}{WK_URI()});
if
(
$self
->{type} ==
$type
) {
return
$self
->{id};
}
unless
(
$opts
{no_defaults}) {
if
(
$self
->{type} ==
$well_known
{wd}) {
}
elsif
(
$self
->{type} ==
$well_known
{doi}) {
}
elsif
(
defined
(
my
$uuid
=
$self
->uuid(
default
=>
undef
))) {
return
$self
->{id_cache}{WK_URI()} =
sprintf
(
'urn:uuid:%s'
,
$uuid
);
}
elsif
(
$enabled_oid
&&
defined
(
my
$oid
=
$self
->oid(
default
=>
undef
))) {
return
$self
->{id_cache}{WK_URI()} =
sprintf
(
'urn:oid:%s'
,
$oid
);
}
else
{
my
$type_uuid
=
$self
->{type}->uuid;
$u
->path_segments(
''
,
$uuid_to_uriid_org
{
$type_uuid
} //
$type_uuid
,
$self
->{id});
return
$self
->{id_cache}{WK_URI()} =
$u
;
}
}
return
$opts
{
default
}
if
exists
$opts
{
default
};
croak
'Identifier has no valid URI'
;
}
sub
sid {
my
(
$self
,
%opts
) =
@_
;
my
$type
=
$well_known
{sid};
return
$self
->{id_cache}{WK_SID()}
if
defined
(
$self
->{id_cache}) &&
defined
(
$self
->{id_cache}{WK_SID()});
if
(
$self
->{type} ==
$type
) {
return
$self
->{id};
}
return
$opts
{
default
}
if
exists
$opts
{
default
};
croak
'Identifier has no valid SID'
;
}
sub
ise {
my
(
$self
,
%opts
) =
@_
;
my
$type
=
$self
->{type};
my
$have_default
=
exists
$opts
{
default
};
my
$default
=
delete
$opts
{
default
};
my
$value
;
if
(
$type
==
$well_known
{uuid} ||
$type
==
$well_known
{oid} ||
$type
==
$well_known
{uri}) {
$value
=
$self
->{id};
}
else
{
$opts
{
default
} =
undef
;
$value
=
$self
->uuid(
%opts
) //
$self
->oid(
%opts
) //
$self
->uri(
%opts
);
}
return
$value
if
defined
$value
;
return
$default
if
$have_default
;
croak
'Identifier has no valid ISE'
;
}
sub
as {
my
(
$self
,
$as
,
%opts
) =
@_
;
$as
=
$opts
{rawtype}
if
$as
eq
'raw'
&&
defined
(
$opts
{rawtype});
return
$self
if
(
$as
=~ /^[A-Z]/ ||
$as
=~ /::/) &&
eval
{
$self
->isa(
$as
)};
$self
= __PACKAGE__->new(
from
=>
$self
)
unless
eval
{
$self
->isa(__PACKAGE__)};
if
(
$as
eq
'uuid'
||
$as
eq
'oid'
||
$as
eq
'uri'
||
$as
eq
'sid'
||
$as
eq
'ise'
) {
my
$func
=
$self
->can(
$as
);
return
$self
->
$func
(
%opts
);
}
elsif
(
$as
eq __PACKAGE__) {
return
$self
;
}
elsif
(
$as
eq
'URI'
) {
my
$had_default
=
exists
$opts
{
default
};
my
$default
=
delete
$opts
{
default
};
my
$val
=
$self
->uri(
%opts
,
default
=>
undef
);
return
URI->new(
$val
)
if
defined
$val
;
if
(
$had_default
) {
return
$default
if
ref
$default
;
return
URI->new(
$default
);
}
croak
'No value for URI'
;
}
elsif
(
$as
eq
'Data::URIID::Result'
&&
defined
(
$opts
{extractor})) {
return
$opts
{extractor}->lookup(
$self
->type->
uuid
=>
$self
->id);
}
elsif
(
$as
eq
'Data::URIID::Service'
&&
defined
(
$opts
{extractor})) {
return
$opts
{extractor}->service(
$self
->uuid);
}
elsif
(
$as
eq
'Data::TagDB::Tag'
&&
defined
(
$opts
{db})) {
if
(
$opts
{autocreate}) {
return
$opts
{db}->create_tag(
$self
);
}
else
{
return
$opts
{db}->tag_by_id(
$self
);
}
}
elsif
(
$as
eq
'Business::ISBN'
&&
$self
->type->eq(
'gtin'
)) {
my
$val
= Business::ISBN->new(
$self
->id);
return
$val
if
defined
(
$val
) &&
$val
->is_valid;
}
return
$opts
{
default
}
if
exists
$opts
{
default
};
croak
'Unknown/Unsupported as: '
.
$as
;
}
sub
eq {
my
(
$self
,
$other
) =
@_
;
foreach
my
$e
(
$self
,
$other
) {
if
(
defined
(
$e
) && !
scalar
(
eval
{
$e
->isa(__PACKAGE__)})) {
if
(
defined
$well_known
{
$e
}) {
$e
=
$well_known
{
$e
}
}
else
{
$e
= Data::Identifier->new(
from
=>
$e
);
}
}
}
if
(
defined
(
$self
)) {
return
undef
unless
defined
$other
;
return
1
if
$self
==
$other
;
return
undef
unless
$self
->type->eq(
$other
->type);
return
$self
->id eq
$other
->id;
}
else
{
return
!
defined
(
$other
);
}
}
sub
cmp {
my
(
$self
,
$other
) =
@_
;
foreach
my
$e
(
$self
,
$other
) {
if
(
defined
(
$e
) && !
scalar
(
eval
{
$e
->isa(__PACKAGE__)})) {
if
(
defined
$well_known
{
$e
}) {
$e
=
$well_known
{
$e
}
}
else
{
$e
= Data::Identifier->new(
from
=>
$e
);
}
}
}
if
(
defined
(
$self
)) {
return
undef
unless
defined
$other
;
return
0
if
$self
==
$other
;
if
((
my
$r
=
$self
->type->cmp(
$other
->type)) != 0) {
return
$r
;
}
{
my
$self_id
=
$self
->id;
my
$other_id
=
$other
->id;
if
((
my
(
$sa
,
$sb
) =
$self_id
=~ /^([^0-9]*)([0-9]+)$/) && (
my
(
$oa
,
$ob
) =
$other_id
=~ /^([^0-9]*)([0-9]+)$/)) {
my
$r
=
$sa
cmp
$oa
;
return
$r
if
$r
;
return
$sb
<=>
$ob
;
}
return
$self_id
cmp
$other_id
;
}
}
else
{
return
!
defined
(
$other
);
}
}
sub
namespace {
my
(
$self
) =
@_
;
return
$self
->{namespace} // croak
'No namespace'
;
}
sub
register {
my
(
$self
) =
@_
;
$registered
{
$self
->{type}->uuid}{
$self
->{id}} =
$self
;
foreach
my
$type_name
(
qw(uuid oid uri sid)
) {
my
$f
=
$self
->can(
$type_name
) ||
next
;
my
$v
=
$self
->
$f
(
default
=>
undef
) //
next
;
$registered
{
$well_known
{
$type_name
}->uuid}{
$v
} =
$self
;
}
}
sub
userdata {
my
(
$self
,
$package
,
$key
,
$value
) =
@_
;
$self
->{userdata} //= {};
$self
->{userdata}{
$package
} //= {};
return
$self
->{userdata}{
$package
}{
$key
} =
$value
//
$self
->{userdata}{
$package
}{
$key
};
}
sub
displayname {
my
(
$self
,
%opts
) =
@_
;
if
(
defined
(
my
$displayname
=
$self
->{displayname})) {
$displayname
=
$self
->
$displayname
()
if
ref
$displayname
;
return
$displayname
if
defined
(
$displayname
) &&
length
(
$displayname
);
}
return
$self
->id.
''
unless
$opts
{no_defaults};
return
$opts
{
default
}
if
exists
$opts
{
default
};
croak
'No value for displayname'
;
}
sub
displaycolour {
my
(
$self
,
%opts
) =
@_
;
return
$opts
{
default
}; }
sub
icontext {
my
(
$self
,
%opts
) =
@_
;
return
$opts
{
default
}; }
sub
description {
my
(
$self
,
%opts
) =
@_
;
return
$opts
{
default
}; }
sub
import
{
my
(
$pkg
,
$opts
) =
@_
;
return
unless
defined
$opts
;
croak
'Bad options'
unless
ref
(
$opts
) eq
'HASH'
;
if
(
defined
(
my
$disable
=
$opts
->{disable})) {
$disable
= [
split
/\s*,\s*/,
$disable
]
unless
ref
$disable
;
foreach
my
$to_disable
(@{
$disable
}) {
if
(
$to_disable
eq
'oid'
) {
$enabled_oid
=
undef
;
undef
*oid
;
}
else
{
croak
'Unknown feature: '
.
$to_disable
;
}
}
}
}
sub
_generate {
my
(
$self
) =
@_
;
unless
(
exists
$self
->{_generate}) {
my
__PACKAGE__
$type
=
$self
->type;
if
(
defined
(
my
$generate
=
$type
->{generate})) {
unless
(
ref
$generate
) {
$self
->{generate} =
$generate
= {
style
=>
$generate
};
}
$self
->{id_cache} //= {};
if
(
defined
(
my
__PACKAGE__
$ns
=
eval
{
$type
->namespace->uuid})) {
my
$style
=
$generate
->{style};
my
$input
;
if
(
$style
eq
'id-based'
) {
$input
=
lc
(
$self
->id);
}
else
{
croak
'Unsupported generator style'
;
}
if
(
defined
$input
) {
$self
->{id_cache}{WK_UUID()} = Data::Identifier::Generate->_uuid_v5(
$ns
,
$input
);
}
}
}
}
$self
->{_generate} =
undef
;
}
sub
_known_provider {
my
(
$pkg
,
$class
,
%opts
) =
@_
;
croak
'Unsupported options passed'
if
scalar
(
keys
%opts
);
if
(
$class
eq
'wellknown'
) {
state
$wellknown
=
do
{
my
%hash
=
map
{
$_
=>
$_
}
values
(
%well_known
),
map
{
values
%{
$_
}}
values
(
%registered
);
[
values
%hash
];
};
return
(
$wellknown
,
rawtype
=> __PACKAGE__);
}
elsif
(
$class
eq
'registered'
||
$class
eq
':all'
) {
my
%hash
=
map
{
$_
=>
$_
}
values
(
%well_known
),
map
{
values
%{
$_
}}
values
(
%registered
);
return
([
values
%hash
],
rawtype
=> __PACKAGE__);
}
croak
'Unsupported class'
;
}
1;