RayApp
view release on metacpan or search on metacpan
lib/RayApp/DSD.pm view on Meta::CPAN
$visited{$id} = 1;
}
if (defined $id) {
$clone = $self->{id}{$id}[0]->cloneNode(1);
$subdsd = $self;
$subpointer = $self->{id}{$id}[1];
}
$clone->setNodeName($node->nodeName);
$node->replaceNode($clone);
delete $self->{typerefs}{$refpointer};
for my $ph (keys %{ $subdsd->{placeholders} }) {
if ($ph eq $subpointer) {
$self->{placeholders}{$refpointer}{type}
= $subdsd->{placeholders}{$ph}{type};
# FIXME: and maybe others
}
if ($ph =~ /^$subpointer(:.+)/) {
my $subid = $1;
$self->{placeholders}{$refpointer . $subid}
= { %{ $subdsd->{placeholders}{$ph} } };
}
}
}
$self->{is_dsd} = 1;
return $self;
}
my %DATA_ATTRIBUTES = (
'type' => {
'int' => 'int',
'integer' => 'int',
'num' => 'num',
'number' => 'num',
'string' => 'string',
'hash' => 'hash',
'struct' => 'hash',
'' => 'string',
},
'mandatory' => {
'yes' => 'yes',
'no' => 'no',
'' => 'no',
},
'multiple' => {
'list' => 'list',
'listelement' => 'listelement',
'hash' => 'hash',
'hashelement' => 'hashelement',
'' => 'no',
},
'hashorder' => {
'num' => 'num',
'string' => 'string',
'natural' => 'natural',
'' => 'natural',
},
'cdata' => {
'yes' => 'yes',
'no' => 'no',
'' => 'no',
},
);
my %PARAM_ATTRIBUTES = (
'type' => $DATA_ATTRIBUTES{'type'},
'multiple' => {
'yes' => 'yes',
'no' => 'no',
'' => 'no',
},
);
sub tidy_dsd_dom {
my ($self, $node, $pointer, $inside_placeholder,
$copy_attribs_in, $translate_attribs_in) = @_;
my $copy_attribs = { %{ $copy_attribs_in } };
my $translate_attribs = { %{ $translate_attribs_in } };
my $type = $node->nodeType;
my $name;
if ($type == 1) {
$name = $node->nodeName;
}
my $parent = $node->parentNode();
my $ln = $node->line_number;
if ($type == 1) { # elements have type 1
my $is_root = 0;
if (not exists $self->{'application'}) {
$is_root = 1;
$self->{'application'} = $node->getAttribute('application');
$self->{'rootelement'} = [ $node, $pointer ];
}
my $is_leaf = remove_children_from_leaf($node);
if ($name eq '_param') { # process and remove params
if ($is_root) {
die "Root element cannot be parameter element at line $ln\n";
}
process_param_element($self, $node, $parent, $ln);
return 0;
}
if ($name eq '_data') {
my $nameattr = $node->getAttributeNode('name');
if (not defined $nameattr) {
die "Data specification lacks attribute name at line $ln\n";
}
$node->removeAttribute('name');
$node->setNodeName($name = $nameattr->getValue);
}
my %attributes = ();
for my $attr ( $node->attributes ) {
next if $attr->nodeType != 2;
$attributes{ $attr->nodeName } = $attr->getValue;
}
lib/RayApp/DSD.pm view on Meta::CPAN
return 0;
}
my $parent = $node->parentNode;
my $prev = $node->previousSibling;
my $indent;
if (defined $prev and $prev->nodeType == 3) {
my $v = $prev->nodeValue;
if (defined $v and $v =~ /(\n[ \t]+)/) {
$indent = $1;
}
}
my $numkeys = keys %$data;
if ($numkeys == 0) {
removeChildNodeNicely($parent, $node);
}
my $i = 0;
for my $key (sort {
my $r = 0;
if ($spec->{'hashorder'} eq 'num') {
no warnings 'numeric';
$r = $a <=> $b;
}
if ($r == 0 and $spec->{'hashorder'} eq 'string') {
$r = $a cmp $b;
}
return $r;
} keys %$data) {
my $work = $node;
if ($i < $numkeys - 1) {
# $work = $node->cloneNode(1);
$work = clone_node($node);
$parent->insertBefore($work, $node);
if (defined $indent) {
$parent->insertBefore(
$dom->createTextNode($indent),
$node);
}
}
$i++;
$work->setAttribute($spec->{'idattr'}, $key);
$self->bind_data($dom, $work, $pointer,
$data->{$key}, $showname . "{$key}", 1);
}
} elsif ($spec->{'type'} ne 'hash') {
if (ref $data) {
$self->{errstr} .= "Scalar expected for $showname defined at line $spec->{'ln'}, got @{[ ref $data ]}\n";
removeChildNodeNicely($node->parentNode, $node);
return 0;
} elsif ($spec->{'type'} eq 'int'
and not $data =~ /^[+-]?\d+$/) {
$self->{errstr} .= "Value '$data' of $showname is not integer for data element defined at line $spec->{'ln'}\n";
removeChildNodeNicely($node->parentNode, $node);
return 0;
} elsif ($spec->{'type'} eq 'num'
and not $data =~ /^[+-]?\d*\.?\d+$/) {
$self->{errstr} .= "Value '$data' of $showname is not numeric for data element defined at line $spec->{'ln'}\n";
removeChildNodeNicely($node->parentNode, $node);
return 0;
}
if ($spec->{'cdata'} eq 'yes') {
while ($data =~ s/^(.*\])(?=\]>)//sg) {
$node->appendChild($dom->createCDATASection($1));
}
$node->appendChild($dom->createCDATASection($data));
} else {
$node->appendText($data);
}
return 1;
} elsif ($spec->{'type'} eq 'hash') {
if (not ref $data) {
$self->{errstr} .= "Scalar data '$data' found where structure expected for $showname at line $spec->{'ln'}\n";
removeChildNodeNicely($node->parentNode, $node);
return 0;
}
my %done = ();
my $total = 0;
my $i = 0;
my $arrayi = 0;
for my $child ($node->childNodes) {
my $newpointer = "$pointer:$i";
$i++;
next if not defined $self->{'placeholders'}{$newpointer};
if (ref $data eq 'ARRAY') {
$total += $self->bind_data($dom, $child,
$newpointer, $data->[ $arrayi ],
$showname . "[$arrayi]", 0);
$arrayi++;
} else {
my $newname = $self->{'placeholders'}{$newpointer}{'name'};
$total += $self->bind_data($dom, $child,
$newpointer, $data->{ $newname },
$showname . "{$newname}", 0);
$done{$newname} = 1;
}
}
if (ref $data eq 'HASH') {
for my $k (sort keys %$data) {
if (not exists $done{$k}) {
$self->{errstr} .= "Data $showname\{$k} does not match data structure description\n";
}
}
} elsif (ref $data eq 'ARRAY') {
if ($arrayi <= $#$data) {
my $view = $arrayi;
if ($arrayi < $#$data) {
$view .= "..$#$data";
}
$self->{errstr} .= "Data $showname\[$view] does not match data structure description\n";
}
} else {
die "We shouldn't have got here";
}
if ($total or $inmulti) {
return 1;
} else {
removeChildNodeNicely($node->parentNode, $node);
return 0;
}
} else {
die "We shouldn't have got here, " . $node->toString;
lib/RayApp/DSD.pm view on Meta::CPAN
Type of the placeholder. Except the scalar types which are the same as
for input parameters, B<hash> or B<struct> values can be used to denote
nested structure.
=item mandatory
By default, no data needs to be returned by the application for the
placeholder. When set to B<yes>, the value will be required.
=item id
An element can be assigned a unique identification which can be then
referenced by B<typeref> from other parts of the same DSD or from
remote DSD's.
=item multiple
When this attribute is specified, the value is expected to be an
aggregate and either the currect DSD element or its child is repeated
for each value.
=over 4
=item list
An array is expected as the value. The placeholder element
will be repeated.
=item listelement
An array is expected, the child of the placeholder will be repeated
for each of the array's element.
=item hash
An associative array is expected and placeholder element will
be repeated for all values of the array. The key of individual values
will be in an attribute B<id> or in an attribute named in DSD with
attribute B<idattr>.
=item hashelement
The same as B<hash>, except that the child of the placeholder will be
repeated.
=back
=item idattr
Specifies the name of attribute which will hold keys of
individual values for multiple values B<hash> and B<hashelement>,
the default is B<id>.
=item hashorder
Order of elements for values binded using multiple values B<hash> or
B<hashelement>. Possible values are B<num>, B<string>, and
(the default) B<natural>.
=item cdata
When set to yes, the scalar content of this element will be
output as a CDATA section.
=back
=head2 Conditions
The non-placeholder elements can have one of the B<if>, B<ifdef>,
B<ifnot> or B<ifnotdef> attributes that specify a top-level value
(from the data hash) that will be checked for presence or its value.
If the condition is not matched, this element with all its children
will be removed from the output stream.
=head2 Attributes
By default, only the special DSD attributes are allowed. However, with
an attribute B<attrs> a list of space separated attribute names can be
specified. These will be preserved on output.
With attribute B<xattrs>, a rename of attributes is possible. The
value is space separated list of space separated pairs of attribute
names.
=head2 Application name
The root element of the DSD can hold an B<application> attribute with
a URL (file name) of the application which should provide the data for
the DSD.
=head1 SEE ALSO
RayApp(3)
=head1 AUTHOR
Copyright (c) Jan Pazdziora 2001--2006
=head1 VERSION
This documentation is believed to describe accurately B<RayApp>
version 2.004.
( run in 0.773 second using v1.01-cache-2.11-cpan-2398b32b56e )