File: Entry.pm

package info (click to toggle)
latexml 0.8.8-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 31,920 kB
  • sloc: xml: 109,048; perl: 30,224; sh: 179; javascript: 28; makefile: 13
file content (153 lines) | stat: -rw-r--r-- 5,053 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# /=====================================================================\ #
# |  LaTeXML::Util::ObjectDB::Entry                                     | #
# |  Database of Objects for crossreferencing, etc                      | #
# |=====================================================================| #
# | Part of LaTeXML:                                                    | #
# |  Public domain software, produced as part of work done by the       | #
# |  United States Government & not subject to copyright in the US.     | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Util::ObjectDB::Entry;
use strict;
use warnings;
use LaTeXML::Common::XML;

my $XMLParser = LaTeXML::Common::XML::Parser->new();    # [CONSTANT]

sub new {
  my ($class, $key, %data) = @_;
  return bless { key => $key, %data }, $class; }

sub key {
  my ($entry) = @_;
  return $$entry{key}; }

sub getAttributes {
  my ($self) = @_;
  return keys %$self; }

# Get/Set a value (column) in the DBRow entry, noting whether it modifies the entry.
# Note that XML data is stored in it's serialized form, prefixed by "XML::".
sub hasValue {
  my ($self, $attr) = @_;
  return exists $$self{$attr}; }

sub getValue {
  my ($self, $attr) = @_;
  return decodeValue($$self{$attr}); }

sub setValues {
  my ($self, %avpairs) = @_;
  foreach my $attr (keys %avpairs) {
    my $value = encodeValue($avpairs{$attr});
    if (!defined $value) {
      if (defined $$self{$attr}) {
        delete $$self{$attr}; } }
    elsif ((!defined $$self{$attr}) || ($$self{$attr} ne $value)) {
      $$self{$attr} = $value; } }
  return; }

sub pushValues {
  my ($self, $attr, @values) = @_;
  my $list = $$self{$attr};
  foreach my $value (@values) {
    push(@$list, encodeValue($value)) if defined $value; }
  return; }

sub pushNew {
  my ($self, $attr, @values) = @_;
  my $list = $$self{$attr};
  foreach my $value (@values) {
    my $value = encodeValue($value);
    push(@$list, $value) if (defined $value) && !grep { $_ eq $value } @$list; }
  return; }

# Note an association with this entry
# Roughly equivalent to $$entry{key1}{key2}{...}=1,
# but keeps track of modification timestamps. --- not any more!
sub noteAssociation {
  my ($self, @keys) = @_;
  my $hash = $self;
  while (@keys) {
    my $key = shift(@keys);
    if (defined $$hash{$key}) {
      $hash = $$hash{$key}; }
    else {
      $hash = $$hash{$key} = (@keys ? {} : 1); } }
  return; }

# Debugging aid
use Text::Wrap;

sub show {
  my ($self) = @_;
  my $string = "ObjectDB Entry for: $$self{key}\n";
  foreach my $attr (grep { $_ ne 'key' } keys %{$self}) {
    my $label = sprintf(' %16s : ', $attr);
    my $value = showvalue($self->getValue($attr));
    # hack around bug in Text::Wrap 2012.0818
    my $line;
    eval {
      local $LaTeXML::IGNORE_ERRORS = 1;
      $line = wrap($label, (' ' x 20), $value); };
    $string .= (defined $line ? $line : $label . $value) . "\n"; }
  return $string; }

sub showvalue {
  my ($value) = @_;
  if ((ref $value) =~ /^XML::/) {
    return $value->toString(1); }
  elsif (ref $value eq 'HASH') {
    return "{" . join(', ', map { "$_=>" . showvalue($$value{$_}) } keys %$value) . "}"; }
  elsif (ref $value eq 'ARRAY') {
    return "[" . join(', ', map { showvalue($_) } @$value) . "]"; }
  else {
    return "$value"; } }

#======================================================================
# Internal methods to encode/decode values; primarily to serialize/deserialize XML.
# Yikes, this ultimately needs to be recursive!
sub encodeValue {
  my ($value) = @_;
  my $ref = ref $value;
  if (!defined $value) {
    return $value; }
  elsif (!$ref) {
    return $value; }
  # The node is cloned so as to copy any inherited namespace nodes.
  elsif ($ref =~ /^XML::/) {
    if ($ref eq 'XML::LibXML::DocumentFragment') {
      my @c = $value->childNodes;
      if (scalar(@c) > 1) {
        warn "Encoding XML Document fragment; dropping all except 1st node!"; }
      $value = $c[0]; }
    return "XML::" . $value->cloneNode(1)->toString; }
  elsif ($ref eq 'ARRAY') {
    return [map { encodeValue($_) } @$value]; }
  elsif ($ref eq 'HASH') {
    my %h = map { ($_ => encodeValue($$value{$_})) } keys %$value;
    return \%h; }
  else {
    return $value; } }

sub decodeValue {
  my ($value) = @_;
  my $ref = ref $value;
  if (!defined $value) {
    return $value; }
  elsif ($value =~ /^XML::/) {
    return $XMLParser->parseChunk(substr($value, 5)); }
  elsif (!$ref) {
    return $value; }
  elsif ($ref eq 'ARRAY') {
    return [map { decodeValue($_) } @$value]; }
  elsif ($ref eq 'HASH') {
    my %h = map { ($_ => decodeValue($$value{$_})) } keys %$value;
    return \%h; }
  else {
    return $value; } }

#======================================================================
1;