source: trunk/gsdl/perllib/lucenebuildproc.pm@ 9919

Last change on this file since 9919 was 9919, checked in by kjdon, 19 years ago

made a base buildproc class, and shifted most of the buildproc code into it. mainly the subclasses just need to implement the text method

  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1###########################################################################
2#
3# lucenebuildproc.pm -- perl wrapper for building index with Lucene
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26package lucenebuildproc;
27
28# This document processor outputs a document
29# for lucene to process
30
31# Use same basic XML structure setup by mgppbuilder/mgppbuildproc
32
33use mgppbuildproc;
34use ghtml;
35
36sub BEGIN {
37 @lucenebuildproc::ISA = ('mgppbuildproc');
38}
39
40
41sub new {
42 my $class = shift @_;
43 my $self = new mgppbuildproc (@_);
44
45 return bless $self, $class;
46}
47
48sub preprocess_text {
49 my $self = shift (@_);
50 my ($text, $strip_html, $para) = @_;
51
52 my ($outtext) = "";
53 if ($strip_html) {
54 while ($text =~ /<([^>]*)>/ && $text ne "") {
55
56 my $tag = $1;
57 $outtext .= $`." "; #add everything before the matched tag
58 $text = $'; #'everything after the matched tag
59 if ($para && $tag =~ /^\s*p\s/i) {
60 $outtext .= $para;
61 }
62 elsif ($tag =~ /^pre$/) { # a pre tag
63 $text =~ /<\/pre>/; # find the closing pre tag
64 my $tmp_text = $`; #everything before the closing pre tag
65 $text = $'; #'everything after the </pre>
66 $tmp_text =~ s/[<>]//g; # remove all < and >
67 $outtext.= $tmp_text . " ";
68 }
69 }
70
71 $outtext .= $text; # add any remaining text
72 } #if strip_html
73 else {
74 $outtext = $text;
75 }
76 #if ($para) {
77 #$text =~ s/(<p\b)/$para$1/gi;
78 #return $text;
79 #}
80
81 # remove entities
82 $outtext =~ s/&\w{1,10};//g;
83
84 return $outtext;
85}
86
87sub text {
88 my $self = shift (@_);
89 my ($doc_obj,$file) = @_;
90 my $handle = $self->{'output_handle'};
91 my $outhandle = $self->{'outhandle'};
92 my $indexed_doc = 1;
93
94 # only output this document if it is one to be indexed
95 return if ($doc_obj->get_doc_type() ne "indexed_doc");
96
97 # see if this document belongs to this subcollection
98 foreach my $indexexp (@{$self->{'indexexparr'}}) {
99 $indexed_doc = 0;
100 my ($field, $exp, $options) = split /\//, $indexexp;
101 if (defined ($field) && defined ($exp)) {
102 my ($bool) = $field =~ /^(.)/;
103 $field =~ s/^.// if $bool eq '!';
104 if ($field =~ /^filename$/i) {
105 $field = $doc_obj->get_source_filename();
106 } else {
107 $field = $doc_obj->get_metadata_element($doc_obj->get_top_section(), $field);
108 }
109 next unless defined $field;
110 if ($bool eq '!') {
111 if ($options =~ /^i$/i) {
112 if ($field !~ /$exp/i) {$indexed_doc = 1; last;}
113 } else {
114 if ($field !~ /$exp/) {$indexed_doc = 1; last;}
115 }
116 } else {
117 if ($options =~ /^i$/i) {
118 if ($field =~ /$exp/i) {$indexed_doc = 1; last;}
119 } else {
120 if ($field =~ /$exp/) {$indexed_doc = 1; last;}
121 }
122 }
123 }
124 }
125
126 # if this doc is so far in the sub collection, and we have lang info,
127 # now we check the languages to see if it matches
128 if($indexed_doc && defined $self->{'lang_meta'}) {
129 $indexed_doc = 0;
130 my $field = $doc_obj->get_metadata_element($doc_obj->get_top_section(), $self->{'lang_meta'});
131 if (defined $field) {
132 foreach my $lang (@{$self->{'langarr'}}) {
133 my ($bool) = $lang =~ /^(.)/;
134 if ($bool eq '!') {
135 $lang =~ s/^.//;
136 if ($field !~ /$lang/) {
137 $indexed_doc = 1; last;
138 }
139 } else {
140 if ($field =~ /$lang/) {
141 $indexed_doc = 1; last;
142 }
143 }
144 }
145 }
146 }
147
148 # this is another document
149 $self->{'num_docs'} += 1;
150
151 # get the parameters for the output
152 # split on : just in case there is subcoll and lang stuff
153 my ($fields) = split (/:/, $self->{'index'});
154
155 my $doc_level = $mgppbuildproc::level_map{'document'};
156 my $gs2ns = 'xmlns:gs2="http://www.greenstone.org/gs2"';
157
158 my $levels = $self->{'levels'};
159 my $ldoc_level = $levels->{'document'};
160 my $lsec_level = $levels->{'section'};
161 my $lpar_level = $levels->{'paragraph'};
162
163 my $docid="";
164 if ($ldoc_level) {
165 if ($self->{'gdbm_level'} eq 'document') {
166 my $doc_sec_num = $self->{'num_docs'};
167 $docid = "gs2:id=\"$doc_sec_num\"";
168 } else {
169 # default is section level
170 my $doc_sec_num = $self->{'num_sections'}+1;
171 $docid = "gs2:id=\"$doc_sec_num\"";
172 }
173 }
174 my $documenttag = "<$doc_level $gs2ns file=\"$file\" $docid >\n";
175 my $documentendtag = "\n</$doc_level>\n";
176
177 my ($sectiontag) = "";
178 if ($lsec_level) {
179 $sectiontag = $mgppbuildproc::level_map{'section'};
180 }
181 my ($parastarttag) = "";
182 my ($paraendtag) = "";
183 if ($self->{'levels'}->{'paragraph'}) {
184 if ($self->{'strip_html'}) {
185 $parastarttag = "<".$mgppbuildproc::level_map{'paragraph'}.">";
186 $paraendtag = "</".$mgppbuildproc::level_map{'paragraph'}.">";
187 } else {
188 print $outhandle "Paragraph level can not be used with no_strip_html!. Not indexing Paragraphs.\n";
189 }
190 }
191
192 my $doc_section = 0; # just for this document
193
194 my $text = "";
195 $text .= $documenttag;
196 # get the text for this document
197 my $section = $doc_obj->get_top_section();
198 while (defined $section) {
199 # update a few statistics
200 $doc_section++;
201 $self->{'num_sections'} += 1;
202
203 if ($sectiontag ne "") {
204 my $secid = "gs2:id=\"".$self->{'num_sections'}."\"";
205 $text .= "\n<$sectiontag $secid >\n";
206 }
207
208 # if we are doing subcollections, then some docs shouldn't be indexed.
209 # but we need to put the section tag placeholders in there so the
210 # sections match up with gdbm db
211 if ($indexed_doc) {
212 #if ($self->{'indexing_text'}) {
213 # $text .= "$parastarttag"; # only add para tags for indexing
214 # note that we assume that metadata will not be asked for for the compressed text, so we add para tags without checking for indexing_text
215 # }
216 $self->{'num_bytes'} += $doc_obj->get_text_length ($section);
217 foreach my $field (split (/,/, $fields)) {
218 # only deal with this field if it doesn't start with top or
219 # this is the first section
220 my $real_field = $field;
221 if (!($real_field =~ s/^top//) || ($doc_section == 1)) {
222 my $new_text = "";
223 my $tmp_text = "";
224 if ($real_field eq "text") {
225 if ($self->{'indexing_text'}) { #tag the text with <Text>...</Text>, add the <Paragraph> tags and strip out html if needed
226 $new_text .= "$parastarttag<TX index=\"1\">\n";
227 $tmp_text .= $doc_obj->get_text ($section);
228 if ($parastarttag =~ "") {
229 # we don't want to individually tag each paragraph if not doing para indexing
230 $tmp_text = $self->preprocess_text($tmp_text, $self->{'strip_html'}, "");
231 } else {
232 $tmp_text = $self->preprocess_text($tmp_text, $self->{'strip_html'}, "</TX>$paraendtag$parastarttag<TX index=\"1\">");
233 }
234
235 $new_text .= "$tmp_text</TX>$paraendtag\n";
236 #if (!defined $self->{'indexfields'}->{'TextOnly'}) {
237 #$self->{'indexfields'}->{'TextOnly'} = 1;
238 #}
239 }
240 else { # leave html stuff in, but escape the tags, and dont add Paragraph tags - never retrieve paras at the moment
241 if ($self->{'store_text'}) {
242 $tmp_text .= $doc_obj->get_text ($section);
243 &ghtml::htmlsafe($tmp_text);
244 $new_text .= $tmp_text;
245 }
246 }
247 } else { # metadata field
248 if ($real_field eq "allfields") { #ignore
249 }
250 elsif ($real_field eq "metadata") { # insert all metadata
251 #except gsdl stuff
252 my $shortname = "";
253 my $metadata = $doc_obj->get_all_metadata ($section);
254 foreach $pair (@$metadata) {
255 my ($mfield, $mvalue) = (@$pair);
256 # check fields here, maybe others dont want - change to use dontindex!!
257 if ($mfield ne "Identifier"
258 && $mfield !~ /^gsdl/
259 && $mfield ne "classifytype"
260 && $mfield ne "assocfilepath"
261 && defined $mvalue && $mvalue ne "") {
262
263 if (defined $self->{'indexfieldmap'}->{$mfield}) {
264 $shortname = $self->{'indexfieldmap'}->{$mfield};
265 }
266 else {
267 $shortname = $self->create_shortname($mfield);
268 $self->{'indexfieldmap'}->{$mfield} = $shortname;
269 $self->{'indexfieldmap'}->{$shortname} = 1;
270 }
271 $new_text .= "$parastarttag<$shortname index=\"1\">$mvalue</$shortname>$paraendtag\n";
272 if (!defined $self->{'indexfields'}->{$mfield}) {
273 $self->{'indexfields'}->{$mfield} = 1;
274 }
275 }
276 }
277
278 }
279 else { #individual metadata specified
280 my $shortname="";
281 #if (!defined $self->{'indexfields'}->{$real_field}) {
282 #$self->{'indexfields'}->{$real_field} = 1;
283 #}
284 if (defined $self->{'indexfieldmap'}->{$real_field}) {
285 $shortname = $self->{'indexfieldmap'}->{$real_field};
286 }
287 else {
288 $shortname = $self->create_shortname($real_field);
289 $self->{'indexfieldmap'}->{$real_field} = $shortname;
290 $self->{'indexfieldmap'}->{$shortname} = 1;
291 }
292 foreach $item (@{$doc_obj->get_metadata ($section, $real_field)}) {
293 $new_text .= "$parastarttag<$shortname index=\"1\">$item</$shortname>$paraendtag\n";
294 # remove entities
295 $new_text =~ s/&\w{1,10};//g;
296 }
297 }
298
299 }
300
301 # filter the text
302 $self->filter_text ($field, $new_text);
303 $self->{'num_processed_bytes'} += length ($new_text);
304 $text .= "$new_text";
305 }
306 }
307 } # if (indexed_doc)
308
309 $text .= "\n</$sectiontag>\n" if ($sectiontag ne "");
310
311 $section = $doc_obj->get_next_section($section);
312 } #while defined section
313 print $handle "$text\n$documentendtag";
314}
315
3161;
317
Note: See TracBrowser for help on using the repository browser.