1 package Net::Z3950::GRS1;
10 my ($class, $href, $map) = @_;
13 $self->{ELEMENTS} = [];
14 $self->{FH} = *STDOUT; ## Default output handle is STDOUT
17 if (defined($href) && ref($href) eq 'HASH') {
19 croak "Usage: new Net::Z3950::GRS1($href, $map);";
21 $self->Hash2grs($href);
29 my ($self, $href, $mapping) = @_;
34 $mapping = defined($mapping) ? $mapping : $self->{MAP};
35 foreach $key (keys %$href) {
36 $content = $href->{$key};
37 if (!defined($aref = $mapping->{$key})) {
38 print STDERR "Hash2grs: Unmapped key: '$key'\n";
41 if (ref($content) eq 'HASH') { ## Subtree?
42 my $subtree = new Net::Z3950::GRS1($content);
43 $self->AddElement($aref->[0], $aref->[1], &Net::Z3950::GRS1::ElementData::Subtree, $subtree);
44 } elsif (ref($content) eq '') { ## Regular string?
45 $self->AddElement($aref->[0], $aref->[1], &Net::Z3950::GRS1::ElementData::String, $content);
47 print STDERR "Hash2grs: Unsupported content type\n";
55 return $self->{ELEMENTS};
59 sub CreateTaggedElement {
60 my ($self, $type, $value, $element_data) = @_;
63 $tagged->{TYPE} = $type;
64 $tagged->{VALUE} = $value;
65 $tagged->{OCCURANCE} = undef;
66 $tagged->{META} = undef;
67 $tagged->{VARIANT} = undef;
68 $tagged->{ELEMENTDATA} = $element_data;
75 my ($self, $TaggedElement) = @_;
77 return ($TaggedElement->{TYPE}, $TaggedElement->{VALUE});
82 my ($self, $TaggedElement) = @_;
84 return $TaggedElement->{ELEMENTDATA};
89 my ($self, $which, $content) = @_;
91 if ($which == &Net::Z3950::GRS1::ElementData::String) {
92 if (ref($content) eq '') {
95 croak "Wrong content type, expected a scalar";
97 } elsif ($which == &Net::Z3950::GRS1::ElementData::Subtree) {
98 if (ref($content) eq __PACKAGE__) {
101 croak "Wrong content type, expected a blessed reference";
104 croak "Content type currently not supported";
109 sub CreateElementData {
110 my ($self, $which, $content) = @_;
111 my $ElementData = {};
113 $self->CheckTypes($which, $content);
114 $ElementData->{WHICH} = $which;
115 $ElementData->{CONTENT} = $content;
122 my ($self, $type, $value, $which, $content) = @_;
123 my $Elements = $self->GetElementList;
124 my $ElmData = $self->CreateElementData($which, $content);
125 my $TaggedElm = $self->CreateTaggedElement($type, $value, $ElmData);
127 push(@$Elements, $TaggedElm);
132 my ($self, $level) = @_;
135 foreach (1..$level - 1) {
144 my ($self, $level, $pool, @args) = @_;
145 my $fh = $self->{FH};
146 my $str = sprintf($self->_Indent($level) . shift(@args), @args);
149 if (defined($pool)) {
158 FORMAT => &Net::Z3950::GRS1::Render::Plain,
164 my @Elements = @{$self->GetElementList};
166 my $fh = $args{HANDLE};
167 my $level = ++$args{LEVEL};
168 my $ref = $args{POOL};
170 if (!defined($fh) && defined($args{FILE})) {
171 open(FH, '> ' . $args{FILE}) or croak "Render: Unable to open file '$args{FILE}' for writing: $!";
175 $self->{FH} = defined($fh) ? $fh : $self->{FH};
177 foreach $TaggedElement (@Elements) {
178 my ($type, $value) = $self->GetTypeValue($TaggedElement);
179 if ($self->GetElementData($TaggedElement)->{WHICH} == &Net::Z3950::GRS1::ElementData::String) {
180 $self->_RecordLine($level, $ref, "(%s,%s) %s\n", $type, $value, $self->GetElementData($TaggedElement)->{CONTENT});
181 } elsif ($self->GetElementData($TaggedElement)->{WHICH} == &Net::Z3950::GRS1::ElementData::Subtree) {
182 $self->_RecordLine($level, $ref, "(%s,%s) {\n", $type, $value);
183 $self->GetElementData($TaggedElement)->{CONTENT}->Render(%args);
184 $self->_RecordLine($level, $ref, "}\n");
188 $self->_RecordLine($level, $ref, "(0,0)\n");
193 package Net::Z3950::GRS1::ElementData;
195 ## Define some constants according to the GRS-1 specification
202 sub TrueOrFalse { 6 }
205 sub ElementNotThere { 9 }
206 sub ElementEmpty { 10 }
207 sub NoDataRequested { 11 }
208 sub Diagnostic { 12 }
212 package Net::Z3950::GRS1::Render;
214 ## Define various types of rendering formats
228 Net::Z3950::Record::GRS1 - Perl package used to encode GRS-1 records.
232 use Net::Z3950::GRS1;
234 my $a_grs1_record = new Net::Z3950::Record::GRS1;
235 my $another_grs1_record = new Net::Z3950::Record::GRS1;
237 $a_grs1_record->AddElement($type, $value, $content);
238 $a_grs1_record->Render();
242 This Perl module helps you to create and manipulate GRS-1 records (generic record syntax).
243 So far, you have only access to three methods:
247 Creates a new GRS-1 object,
249 my $grs1 = new Net::Z3950::GRS1;
253 Lets you add entries to a GRS-1 object. The method should be called this way,
255 $grs1->AddElement($type, $value, $which, $content);
257 where $type should be an integer, and $value is free text. The $which argument should
258 contain one of the constants listed in Appendix A. Finally, $content contains the "thing"
259 that should be stored in this entry. The structure of $content should match the chosen
260 element data type. For
262 $which == Net::Z3950::GRS1::ElementData::String;
264 $content should be some kind of scalar. If on the other hand,
266 $which == Net::Z3950::GRS1::ElementData::Subtree;
268 $content should be a GRS1 object.
272 This method digs through the GRS-1 data structure and renders the record. You call it
277 If you want to access the rendered record through a variable, you can do it like this,
279 my $record_as_string;
280 $grs1->Render(POOL => \$record_as_string);
282 If you want it stored in a file, Render should be called this way,
284 $grs1->Render(FILE => 'record.grs1');
286 When no file name is specified, you can choose to stream the rendered record, for instance,
288 $grs1->Render(HANDLE => *STDOUT); ## or
289 $grs1->Render(HANDLE => *STDERR); ## or
290 $grs1->Render(HANDLE => *MY_HANDLE);
294 These element data types are specified in the Z39.50 protocol:
296 Net::Z3950::GRS1::ElementData::Octets
297 Net::Z3950::GRS1::ElementData::Numeric
298 Net::Z3950::GRS1::ElementData::Date
299 Net::Z3950::GRS1::ElementData::Ext
300 Net::Z3950::GRS1::ElementData::String <---
301 Net::Z3950::GRS1::ElementData::TrueOrFalse
302 Net::Z3950::GRS1::ElementData::OID
303 Net::Z3950::GRS1::ElementData::IntUnit
304 Net::Z3950::GRS1::ElementData::ElementNotThere
305 Net::Z3950::GRS1::ElementData::ElementEmpty
306 Net::Z3950::GRS1::ElementData::NoDataRequested
307 Net::Z3950::GRS1::ElementData::Diagnostic
308 Net::Z3950::GRS1::ElementData::Subtree <---
310 Only the '<---' marked types are so far supported in this package.
314 Anders Sønderberg Mortensen <sondberg@indexdata.dk>
315 Index Data ApS, Copenhagen, Denmark.
320 Specification of the GRS-1 standard, for instance in the Z39.50 protocol specification.
325 #Revision 1.3 2001-05-17 13:43:04 sondberg
326 #Added method Hash2grs into GRS1 module.
328 #Revision 1.2 2001/03/13 14:53:15 sondberg
329 #Added a few lines of documentation into GRS1.pm.
331 #Revision 1.1 2001/03/13 14:17:15 sondberg
332 #Added support for GRS-1.