File Coverage

blib/lib/PRANG/XMLSchema/Types.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1              
2             package PRANG::XMLSchema::Types;
3             $PRANG::XMLSchema::Types::VERSION = '0.19';
4 1     1   3305 use strict;
  1         2  
  1         26  
5 1     1   4 use warnings;
  1         2  
  1         22  
6 1     1   4 use Moose::Util::TypeConstraints;
  1         2  
  1         6  
7              
8             subtype "PRANG::XMLSchema::normalizedString"
9             => as "Str"
10             => where { !m{[\n\r\t]} };
11              
12             subtype "PRANG::XMLSchema::token"
13             => as "Str"
14             => where {
15             !m{[\t\r\n]|^\s|\s$|\s\s};
16             };
17              
18             # automatically trim tokens if passed them.
19             coerce "PRANG::XMLSchema::token"
20             => from "Str",
21             => via {
22             my ($x) = m/\A\s*(.*?)\s*\Z/;
23             $x =~ s{\s+}{ }g;
24             $x;
25             },
26             ;
27              
28             # See https://rt.cpan.org/Ticket/Display.html?id=52309
29             # use Regexp::Common qw/URI/;
30             subtype "PRANG::XMLSchema::anyURI"
31             => as "Str"
32             => where {
33             m{^\w+:\S+$}; # validate using this instead
34             };
35              
36 1     1   4216 use I18N::LangTags qw(is_language_tag);
  1         2326  
  1         933  
37             subtype "PRANG::XMLSchema::language"
38             => as "Str"
39             => where {
40             is_language_tag($_);
41             };
42              
43             subtype "PRANG::XMLSchema::dateTime"
44             => as "Str"
45             => where {
46              
47             # from the XMLSchema spec... it'll do for now ;)
48             # how on earth is one supposed to encode Pacific/Guam
49             # or Pacific/Saipan dates before 1845 with this regex?
50             m{
51             ^
52             -?([1-9][0-9]{3,}|0[0-9]{3})
53             -(0[1-9]|1[0-2])
54             -(0[1-9]|[12][0-9]|3[01])
55             T(([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?|(24:00:00(\.0+)?))
56             (?:Z|(?:\+|-)(?:(?:0[0-9]|1[0-3]):[0-5][0-9]|14:00))?
57             $
58             }x;
59             };
60              
61             subtype "PRANG::XMLSchema::time"
62             => as "Str"
63             => where {
64              
65             # from the XMLSchema spec... it'll do for now ;)
66             m{
67             ^
68             (([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?|(24:00:00(\.0+)?))
69             (?:Z|(?:\+|-)(?:(?:0[0-9]|1[0-3]):[0-5][0-9]|14:00))?
70             $
71             }x;
72             };
73              
74             subtype "PRANG::XMLSchema::date"
75             => as "Str"
76             => where {
77              
78             # from the XMLSchema spec... it'll do for now ;)
79             # XXX: Note, since the XML Spec bizarrely has Timezones on Dates,
80             # we have chosen to ignore it (since it is optional anyway)
81             m{
82             ^
83             -?([1-9][0-9]{3,}|0[0-9]{3})
84             -(0[1-9]|1[0-2])
85             -(0[1-9]|[12][0-9]|3[01])
86             $
87             }x;
88             };
89              
90             subtype "PRANG::XMLSchema::duration"
91             => as "Str"
92             => where {
93             m{^\s* (?: [pP]? \s* )?
94             (?: C \s* \d+)?
95             (?: Y \s* \d+)?
96             (?: M \s* \d+)?
97             (?: D \s* \d+)?
98             (?: h \s* \d+)?
99             (?: m \s* \d+)?
100             (?: s \s* \d+(?:\.\d+) )? \s* $}x;
101             };
102              
103             # other built-in primitive datatypes.
104             subtype "PRANG::XMLSchema::string"
105             => as "Str";
106             subtype "PRANG::XMLSchema::boolean"
107             => as "Str"
108             => where {
109             m/^(?:0|1|true|false)$/;
110             };
111             coerce "Bool"
112             => from 'PRANG::XMLSchema::boolean'
113             => via { m{1|true} ? 1 : 0 };
114             subtype "PRANG::XMLSchema::decimal"
115             => as "Num";
116              
117             # floating point stuff...
118             subtype "PRANG::XMLSchema::float"
119             => as "Str"
120             => where {
121             m{^(?:[\-+]?(?:\d+(?:\.\d*)?(?:e[\-+]?(\d+))?|inf)|NaN)$}i;
122             };
123             our $inf = exp(~0 >> 1);
124             our $nan = $inf / $inf;
125             our $neg_inf = -$inf;
126             coerce "Num"
127             => from 'PRANG::XMLSchema::float'
128             => via {
129             m{^(?:([\-+])?inf|(nan)|(.))};
130             return eval $_ if defined $3;
131             return $nan if $2;
132             return $neg_inf if $1 and $1 eq "-";
133             return $inf;
134             };
135              
136             if ( 0.1 == 0.100000000000000006 ) {
137             subtype "PRANG::XMLSchema::double"
138             => as "PRANG::XMLSchema::float";
139             }
140             else {
141             subtype "PRANG::XMLSchema::double"
142             => as "PRANG::XMLSchema::float"
143             => where {
144             unpack('d',pack('d',$_))==$_;
145             };
146              
147             coerce "PRANG::XMLSchema::double"
148             => from "PRANG::XMLSchema::float"
149             => via {
150             unpack('d',pack('d',$_));
151             };
152             }
153              
154             # built-in derived types.
155             # this sub-typing might seem unnecessarily deep, but that's what the
156             # spec says... see http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/datatypes.html#built-in-derived
157             subtype "PRANG::XMLSchema::integer"
158             => as "Int";
159             subtype "PRANG::XMLSchema::nonPositiveInteger"
160             => as "PRANG::XMLSchema::integer"
161             => where {
162             $_ <= 0;
163             };
164             subtype "PRANG::XMLSchema::negativeInteger"
165             => as "PRANG::XMLSchema::nonPositiveInteger"
166             => where {
167             $_ <= -1;
168             };
169             subtype "PRANG::XMLSchema::nonNegativeInteger"
170             => as "PRANG::XMLSchema::integer"
171             => where {
172             $_ >= 0;
173             };
174             subtype "PRANG::XMLSchema::positiveInteger"
175             => as "PRANG::XMLSchema::nonNegativeInteger"
176             => where {
177             $_ >= 1;
178             };
179             subtype "PRANG::XMLSchema::long"
180             => as "PRANG::XMLSchema::integer"
181             => where {
182             $_ >= -9223372036854775808 and $_ <= 9223372036854775807;
183             };
184             subtype "PRANG::XMLSchema::int"
185             => as "PRANG::XMLSchema::long"
186             => where {
187             $_ >= -2147483648 and $_ <= 2147483647;
188             };
189             subtype "PRANG::XMLSchema::short"
190             => as "PRANG::XMLSchema::int"
191             => where {
192             $_ >= -32768 and $_ <= 32767;
193             };
194             subtype "PRANG::XMLSchema::byte"
195             => as "PRANG::XMLSchema::short"
196             => where {
197             $_ >= -128 and $_ <= 127;
198             };
199             subtype "PRANG::XMLSchema::unsignedLong"
200             => as "PRANG::XMLSchema::nonNegativeInteger"
201             => where {
202             $_ >= 0 and $_ < 18446744073709551615;
203             };
204             subtype "PRANG::XMLSchema::unsignedInt"
205             => as "PRANG::XMLSchema::unsignedLong"
206             => where {
207             $_ >= 0 and $_ < 2147483647;
208             };
209             subtype "PRANG::XMLSchema::unsignedShort"
210             => as "PRANG::XMLSchema::unsignedInt"
211             => where {
212             $_ >= 0 and $_ < 65536;
213             };
214             subtype "PRANG::XMLSchema::unsignedByte"
215             => as "PRANG::XMLSchema::unsignedShort"
216             => where {
217             $_ >= 0 and $_ < 256;
218             };
219              
220             1;
221              
222             =head1 NAME
223              
224             PRANG::XMLSchema::Types - type registry for XML Schema-related types
225              
226             =head1 SYNOPSIS
227              
228             package My::Class;
229             use Moose;
230             use PRANG::Graph;
231             use PRANG::XMLSchema::Types;
232              
233             has_attr 'foo' =>
234             is => "ro",
235             isa => "PRANG::XMLSchema::unsignedShort",
236             ;
237              
238             =head1 DESCRIPTION
239              
240             This module is a collection of types which make working with XML
241             Schema specifications easier. See the source for the complete list.
242              
243             These might be moved into a separate namespace, but if you include
244             this module you will get aliases for wherever these XML Schema types
245             end up.
246              
247             =head1 SEE ALSO
248              
249             L<PRANG>, L<PRANG::Graph::Meta::Attr>, L<PRANG::Graph::Meta::Element>
250              
251             =head1 AUTHOR AND LICENCE
252              
253             Development commissioned by NZ Registry Services, and carried out by
254             Catalyst IT - L<http://www.catalyst.net.nz/>
255              
256             Copyright 2009, 2010, NZ Registry Services. This module is licensed
257             under the Artistic License v2.0, which permits relicensing under other
258             Free Software licenses.
259              
260             =cut
261