1 # $Id: Node.pm,v 1.4 2007-10-05 12:13:05 mike Exp $
3 package Net::Z3950::PQF::Node;
11 Net::Z3950::PQF::Node - Abstract class for nodes in a PQF parse tree
15 $node = new Net::Z3950::PQF::TermNode('unix');
16 $node->isa("Net::Z3950::PQF::Node") or die "oops";
20 This module implements the types for the nodes that make up a PQF
21 parse tree. Each such concrete type is a subclass of the abstract
24 and has a type whose name is of the form
25 C<Net::Z3950::PQF::>I<somethingNode>.
27 The following node types are defined:
33 Represents an actual query term such as
37 C<"Brian W. Kernighan">.
39 The term is accompanied by zero or more
41 each of which is a triple represented by a reference to a
42 three-element array. Each such array consists of an
43 I<attribute set identifier>
44 which may be either an OID or a short descriptive string,
49 which may be either an integer or a string.
53 Represents a result-set node, a reference to the name of a prior
54 result set. The result-set name is accompanied by zero or more
59 Represents an AND node with two sub-nodes.
63 Represents an OR node with two sub-nodes.
67 Represents a NOT node with two sub-nodes. In the Z39.50 Type-1 query,
68 and hence in PQF, NOT is a binary AND-NOT operator rather than than a
69 unary negation operator.
73 Represents a proximity node with two subnodes and five parameters:
76 a boolean indicating whether the condition indicated by the other
77 parameters should be inverted.
80 an integer indicating the number of units that may separate the
81 fragments identified by the subnodes.
84 a boolean indicating whether the elements indicated by the subnodes
85 are constrained to be in the same order as the subnodes themselves.
88 indicates the relation required on the specified distance in order
89 for the condition to be satisfied.
92 a short string indicating the units of proximity (C<word>,
97 Except where noted, the methods described below are defined for all of
98 the concrete node types.
105 $term1 = new Net::Z3950::PQF::TermNode('brian', [ "bib-1", 1, 1003 ]);
106 $term2 = new Net::Z3950::PQF::TermNode('unix', [ "bib-1", 1, 4 ]);
107 $and = new Net::Z3950::PQF::AndNode($term1, $term2);
109 Creates a new node object of the appropriate type. It is not possible
110 to instantiate the abstract node type, C<Net::Z3950::PQF::Node>, only its
113 The parameters required are different for different node types:
119 The first parameter is the actual term, and the remainder are
120 attributes, each represented by a triple of
121 [ I<attribute-set>, I<type>, I<value> ].
123 =item C<AndNode>, C<OrNode>, C<NotNode>
125 The two parameters are nodes representing the subtrees.
129 The seven parameters are, in order: the two nodes representing the
130 subtrees, and the five parameters exclusion, distance, ordered,
139 die "can't create an abstract $class";
147 Renders the contents of the tree rooted at the specified node,
148 indented to a level indicated by the parameter. This output is in a
149 human-readable form that is useful for debugging but probably not much
156 die "can't render an abstract $class";
160 =head2 toSimpleServer()
162 $node->toSimpleServer();
164 Transforms the contents of the tree rooted at the specified node,
165 returning a correpsonding tree of the Perl structures produced by the
166 Net::Z3950::SimpleServer module and passed as the {RPN} argument to
167 search handlers. This emulation is useful for testing code that
168 expects to receive queries in that format.
174 die "can't translate an abstract $class into SimpleServer form";
179 # PRIVATE base class, used as base by TermNode and RsetNode
180 package Net::Z3950::PQF::LeafNode;
181 our @ISA = qw(Net::Z3950::PQF::Node);
185 my($value, @attrs) = @_;
197 die "render() called with no level" if !defined $level;
198 my $text = ("\t" x $level) . $this->_name() . ": " . $this->{value} . "\n";
199 foreach my $attr (@{ $this->{attrs} }) {
200 my($set, $type, $val) = @$attr;
201 $text .= ("\t" x ($level+1)) . "attr: $set $type=$val\n";
210 my $attrs = bless [], "Net::Z3950::RPN::Attributes";
211 foreach my $attr (@{ $this->{attrs} }) {
212 my($set, $type, $val) = @$attr;
213 push @$attrs, bless {
214 attributeSet => $set,
215 attributeType => $type,
216 attributeValue => $val,
217 }, "Net::Z3950::RPN::Attribute";
221 $this->_ssname() => $this->{value},
222 attributes => $attrs,
223 }, $this->_ssclass();
228 package Net::Z3950::PQF::TermNode;
229 our @ISA = qw(Net::Z3950::PQF::LeafNode);
232 sub _ssname { "term" }
233 sub _ssclass { "Net::Z3950::RPN::Term" }
237 package Net::Z3950::PQF::RsetNode;
238 our @ISA = qw(Net::Z3950::PQF::LeafNode);
242 sub _ssclass { "Net::Z3950::RPN::RSID" }
246 # PRIVATE class, used as base by AndNode, OrNode and NotNode
247 package Net::Z3950::PQF::BooleanNode;
248 our @ISA = qw(Net::Z3950::PQF::Node);
263 die "render() called with no level" if !defined $level;
264 my $text = ("\t" x $level) . $this->_op() . "\n";
265 foreach my $sub (@{ $this->{sub} }) {
266 $text .= $sub->render($level+1);
276 foreach my $sub (@{ $this->{sub} }) {
277 push @$res, $sub->toSimpleServer();
280 return bless $res, $this->_ssclass();
285 package Net::Z3950::PQF::AndNode;
286 our @ISA = qw(Net::Z3950::PQF::BooleanNode);
289 sub _ssclass { "Net::Z3950::RPN::And" }
293 package Net::Z3950::PQF::OrNode;
294 our @ISA = qw(Net::Z3950::PQF::BooleanNode);
297 sub _ssclass { "Net::Z3950::RPN::Or" }
301 package Net::Z3950::PQF::NotNode;
302 our @ISA = qw(Net::Z3950::PQF::BooleanNode);
305 sub _ssclass { "Net::Z3950::RPN::AndNote" }
309 package Net::Z3950::PQF::ProxNode;
313 die "### class $class not yet implemented";
318 die "you shouldn't have been able to make $this";
326 This module is part of the Net::Z3950::PQF distribution. The
327 copyright, authorship and licence are all as for the distribution.