2 use strict; use warnings;
 
   3 use YAML::Base; use base 'YAML::Base';
 
   6 our @EXPORT = qw(ynode);
 
  10     if (ref($_[0]) eq 'HASH') {
 
  11         $self = tied(%{$_[0]});
 
  13     elsif (ref($_[0]) eq 'ARRAY') {
 
  14         $self = tied(@{$_[0]});
 
  19     return (ref($self) =~ /^yaml_/) ? $self : undef;
 
  23     my ($class, $node, $tag) = @_;
 
  25     $self->{NODE} = $node;
 
  26     my (undef, $type) = $class->node_info($node);
 
  27     $self->{KIND} = (not defined $type) ? 'scalar' :
 
  28                     ($type eq 'ARRAY') ? 'sequence' :
 
  29                     ($type eq 'HASH') ? 'mapping' :
 
  30                     $class->die("Can't create YAML::Node from '$type'");
 
  31     tag($self, ($tag || ''));
 
  32     if ($self->{KIND} eq 'scalar') {
 
  33         yaml_scalar->new($self, $_[1]);
 
  36     my $package = "yaml_" . $self->{KIND};    
 
  40 sub node { $_->{NODE} }
 
  41 sub kind { $_->{KIND} }
 
  43     my ($self, $value) = @_;
 
  45         $self->{TAG} = YAML::Tag->new($value);
 
  53     my ($self, $value) = @_;
 
  55         $self->{KEYS} = $value;
 
  63 #==============================================================================
 
  65 @yaml_scalar::ISA = qw(YAML::Node);
 
  68     my ($class, $self) = @_;
 
  69     tie $_[2], $class, $self;
 
  73     my ($class, $self) = @_;
 
  84     my ($self, $value) = @_;
 
  85     $self->{NODE} = $value
 
  88 #==============================================================================
 
  89 package yaml_sequence;
 
  90 @yaml_sequence::ISA = qw(YAML::Node);
 
  93     my ($class, $self) = @_;
 
  95     tie @$new, $class, $self;
 
 100     my ($class, $self) = @_;
 
 106     scalar @{$self->{NODE}};
 
 110     my ($self, $index) = @_;
 
 111     $self->{NODE}[$index]
 
 115     my ($self, $index, $value) = @_;
 
 116     $self->{NODE}[$index] = $value
 
 120     die "Not implemented yet"; # XXX
 
 123 *STORESIZE = *POP = *PUSH = *SHIFT = *UNSHIFT = *SPLICE = *DELETE = *EXISTS = 
 
 124 *STORESIZE = *POP = *PUSH = *SHIFT = *UNSHIFT = *SPLICE = *DELETE = *EXISTS = 
 
 125 *undone; # XXX Must implement before release
 
 127 #==============================================================================
 
 128 package yaml_mapping;
 
 129 @yaml_mapping::ISA = qw(YAML::Node);
 
 132     my ($class, $self) = @_;
 
 133     @{$self->{KEYS}} = sort keys %{$self->{NODE}}; 
 
 135     tie %$new, $class, $self;
 
 140     my ($class, $self) = @_;
 
 145     my ($self, $key) = @_;
 
 146     if (exists $self->{NODE}{$key}) {
 
 147         return (grep {$_ eq $key} @{$self->{KEYS}}) 
 
 148                ? $self->{NODE}{$key} : undef;
 
 150     return $self->{HASH}{$key};
 
 154     my ($self, $key, $value) = @_;
 
 155     if (exists $self->{NODE}{$key}) {
 
 156         $self->{NODE}{$key} = $value;
 
 158     elsif (exists $self->{HASH}{$key}) {
 
 159         $self->{HASH}{$key} = $value;
 
 162         if (not grep {$_ eq $key} @{$self->{KEYS}}) {
 
 163             push(@{$self->{KEYS}}, $key);
 
 165         $self->{HASH}{$key} = $value;
 
 171     my ($self, $key) = @_;
 
 173     if (exists $self->{NODE}{$key}) {
 
 174         $return = $self->{NODE}{$key};
 
 176     elsif (exists $self->{HASH}{$key}) {
 
 177         $return = delete $self->{NODE}{$key};
 
 179     for (my $i = 0; $i < @{$self->{KEYS}}; $i++) {
 
 180         if ($self->{KEYS}[$i] eq $key) {
 
 181             splice(@{$self->{KEYS}}, $i, 1);
 
 189     @{$self->{KEYS}} = ();
 
 190     %{$self->{HASH}} = ();
 
 201     $self->{KEYS}[++$self->{ITER}]
 
 205     my ($self, $key) = @_;
 
 206     exists $self->{NODE}{$key}
 
 215 YAML::Node - A generic data node that encapsulates YAML information
 
 222     my $ynode = YAML::Node->new({}, 'ingerson.com/fruit');
 
 223     %$ynode = qw(orange orange apple red grape green);
 
 228     --- !ingerson.com/fruit
 
 235 A generic node in YAML is similar to a plain hash, array, or scalar node
 
 236 in Perl except that it must also keep track of its type. The type is a
 
 237 URI called the YAML type tag.
 
 239 YAML::Node is a class for generating and manipulating these containers.
 
 240 A YAML node (or ynode) is a tied hash, array or scalar. In most ways it
 
 241 behaves just like the plain thing. But you can assign and retrieve and
 
 242 YAML type tag URI to it. For the hash flavor, you can also assign the
 
 243 order that the keys will be retrieved in. By default a ynode will offer
 
 244 its keys in the same order that they were assigned.
 
 246 YAML::Node has a class method call new() that will return a ynode. You
 
 247 pass it a regular node and an optional type tag. After that you can
 
 248 use it like a normal Perl node, but when you YAML::Dump it, the magical
 
 249 properties will be honored.
 
 251 This is how you can control the sort order of hash keys during a YAML
 
 252 serialization. By default, YAML sorts keys alphabetically. But notice
 
 253 in the above example that the keys were Dumped in the same order they
 
 256 YAML::Node exports a function called ynode(). This function returns the tied object so that you can call special methods on it like ->keys().
 
 258 keys() works like this:
 
 263     %$node = qw(orange orange apple red grape green);
 
 264     $ynode = YAML::Node->new($node);
 
 265     ynode($ynode)->keys(['grape', 'apple']);
 
 274 It tells the ynode which keys and what order to use.
 
 276 ynodes will play a very important role in how programs use YAML. They
 
 277 are the foundation of how a Perl class can marshall the Loading and
 
 278 Dumping of its objects.
 
 280 The upcoming versions of YAML.pm will have much more information on this.
 
 284 Ingy döt Net <ingy@cpan.org>
 
 288 Copyright (c) 2006. Ingy döt Net. All rights reserved.
 
 289 Copyright (c) 2002. Brian Ingerson. All rights reserved.
 
 291 This program is free software; you can redistribute it and/or modify it
 
 292 under the same terms as Perl itself.
 
 294 See L<http://www.perl.com/perl/misc/Artistic.html>