Made TermNode and BooleanNode be subclasses of Node.
[perl-pqf.git] / lib / Net / Z3950 / PQF / Node.pm
1 # $Id: Node.pm,v 1.2 2004-12-20 09:23:11 mike Exp $
2
3 package Net::Z3950::PQF::Node;
4
5 use strict;
6 use warnings;
7
8
9 =head1 NAME
10
11 Net::Z3950::PQF::Node - Abstract class for nodes in a PQF parse tree
12
13 =head1 SYNOPSIS
14
15  $node = new Net::Z3950::PQF::TermNode('unix');
16  $node->isa("Net::Z3950::PQF::Node") or die "oops";
17
18 =head1 DESCRIPTION
19
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
22 base class
23 C<Net::Z3950::Node>,
24 and has a type whose name is of the form
25 C<Net::Z3950::PQF::>I<somethingNode>.
26
27 The following node types are defined:
28
29 =over 4
30
31 =item C<TermNode>
32
33 Represents an actual query term such as
34 C<brian>,
35 C<"brian">
36 or
37 C<"Brian W. Kernighan">.
38
39 The term is accompanied by zero or more 
40 I<attributes>,
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,
45 an integer
46 I<type>,
47 and a
48 I<value>
49 which may be either an integer or a string.
50
51 =item C<AndNode>
52
53 Represents an AND node with two sub-nodes.
54
55 =item C<OrNode>
56
57 Represents an OR node with two sub-nodes.
58
59 =item C<NotNode>
60
61 Represents a NOT node with two sub-nodes.  In the Z39.50 Type-1 query,
62 and hence in PQF, NOT is a binary AND-NOT operator rather than than a
63 unary negation operator.
64
65 =item C<ProxNode>
66
67 Represents a proximity node with two subnodes and five parameters:
68
69 I<exclusion>:
70 a boolean indicating whether the condition indicated by the other
71 parameters should be inverted.
72
73 I<distance>:
74 an integer indicating the number of units that may separate the
75 fragments identified by the subnodes.
76
77 I<ordered>:
78 a boolean indicating whether the elements indicated by the subnodes
79 are constrained to be in the same order as the subnodes themselves.
80
81 I<relation>:
82 indicates the relation required on the specified distance in order
83 for the condition to be satisfied.
84
85 I<unit>:
86 a short string indicating the units of proximity (C<word>,
87 C<sentence>, etc.)
88
89 =back
90
91 Except where noted, the methods described below are defined for all of
92 the concrete node types.
93
94
95 =head1 METHODS
96
97 =head2 new()
98
99  $term1 = new Net::Z3950::PQF::TermNode('brian', [ "bib-1", 1, 1003 ]);
100  $term2 = new Net::Z3950::PQF::TermNode('unix', [ "bib-1", 1, 4 ]);
101  $and = new Net::Z3950::PQF::AndNode($term1, $term2);
102
103 Creates a new node object of the appropriate type.  It is not possible
104 to instantiate the abstract node type, C<Net::Z3950::PQF::Node>, only its
105 concrete subclasses.
106
107 The parameters required are different for different node types:
108
109 =over 4
110
111 =item C<TermNode>
112
113 The first parameter is the actual term, and the remainder are
114 attributes, each represented by a triple of
115 [ I<attribute-set>, I<type>, I<value> ].
116
117 =item C<AndNode>, C<OrNode>, C<NotNode>
118
119 The two parameters are nodes representing the subtrees.
120
121 =item C<ProxNode>
122
123 The seven parameters are, in order: the two nodes representing the
124 subtrees, and the five parameters exclusion, distance, ordered,
125 relation and unit.
126
127 =back
128
129 =cut
130
131 sub new {
132     my $class = shift();
133     die "can't create an abstract $class";
134 }
135
136
137 =head2 render()
138
139  $node->render(0);
140
141 Renders the contents of the tree rooted at the specified node,
142 indented to a level indicated by the parameter.  This output is in a
143 human-readable form that is useful for debugging but probably not much
144 else.
145
146 =cut
147
148 sub render {
149     my $class = shift();
150     die "can't render an abstract $class";
151 }
152
153
154
155 package Net::Z3950::PQF::TermNode;
156 our @ISA = qw(Net::Z3950::PQF::Node);
157
158 sub new {
159     my $class = shift();
160     my($term, @attrs) = @_;
161
162     return bless {
163         term => $term,
164         attrs => [ @attrs ],
165     }, $class;
166 }
167
168 sub render {
169     my $this = shift();
170     my($level) = @_;
171
172     die "render() called with no level" if !defined $level;
173     my $text = ("\t" x $level) . "term: " . $this->{term} . "\n";
174     foreach my $attr (@{ $this->{attrs} }) {
175         my($set, $type, $val) = @$attr;
176         $text .= ("\t" x ($level+1)) . "attr: $set $type=$val\n";
177     }
178
179     return $text;
180 }
181
182
183
184 # PRIVATE class, used as base by AndNode, OrNode and NotNode
185 package Net::Z3950::PQF::BooleanNode;
186 our @ISA = qw(Net::Z3950::PQF::Node);
187
188 sub new {
189     my $class = shift();
190     my(@sub) = @_;
191
192     return bless {
193         sub => [ @sub ],
194     }, $class;
195 }
196
197 sub render {
198     my $this = shift();
199     my($level) = @_;
200
201     die "render() called with no level" if !defined $level;
202     my $text = ("\t" x $level) . $this->_op() . "\n";
203     foreach my $sub (@{ $this->{sub} }) {
204         $text .= $sub->render($level+1);
205     }
206
207     return $text;
208 }
209
210
211
212 package Net::Z3950::PQF::AndNode;
213 our @ISA = qw(Net::Z3950::PQF::BooleanNode);
214
215 sub _op { "and" }
216
217
218
219 package Net::Z3950::PQF::OrNode;
220 our @ISA = qw(Net::Z3950::PQF::BooleanNode);
221
222 sub _op { "or" }
223
224
225
226 package Net::Z3950::PQF::NotNode;
227 our @ISA = qw(Net::Z3950::PQF::BooleanNode);
228
229 sub _op { "not" }
230
231
232
233 package Net::Z3950::PQF::ProxNode;
234
235 sub new {
236     my $class = shift();
237     die "### class $class not yet implemented";
238 }
239
240 sub render {
241     my $this = shift();
242     die "you shouldn't have been able to make $this";
243 }
244
245
246
247
248 =head1 PROVENANCE
249
250 This module is part of the Net::Z3950::PQF distribution.  The
251 copyright, authorship and licence are all as for the distribution.
252
253 =cut
254
255
256 1;