source: main/tags/2.52/gsdl/perllib/classify/DateList.pm@ 21093

Last change on this file since 21093 was 7177, checked in by kjdon, 20 years ago

when I chaged the options names to metadata and sort, I forgot to change them where you actually parse the args :-(. ooops.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1###########################################################################
2#
3# DateList.pm --
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
26# classifier plugin for sorting by date
27
28# date is assumed to be in the form yyyymmdd
29
30# at present dates are split by year - this should change
31# jrm21 - added option "bymonth", which splits by year and month.
32
33# 23/09/03 Added some more options -kjdon.
34# these include:
35# -nogroup, which makes each year (or year+month) an individual entry in
36# the horizontal list and prevents compaction
37# -metadata, use a different metadata for the date (instead of Date), still expects yyyymmdd format. this affects display cos greenstone displays Date metadata as dd month yyyy, whereas any other date metadata is displayed as yyyymmdd - this needs fixing
38# -sort specifies an additional metadata to use in sorting, will take affect when two docs have the same date.
39
40package DateList;
41
42use BasClas;
43use sorttools;
44
45sub BEGIN {
46 @ISA = ('BasClas');
47}
48
49my $arguments =
50 [ { 'name' => "metadata",
51 'desc' => "{DateList.metadata}",
52 'type' => "metadata",
53 'deft' => "Date",
54 'reqd' => "no" } ,
55 { 'name' => "sort",
56 'desc' => "{DateList.sort}",
57 'type' => "metadata",
58 'reqd' => "no" } ,
59 { 'name' => "bymonth",
60 'desc' => "{DateList.bymonth}",
61 'type' => "flag",
62 'reqd' => "no" },
63 { 'name' => "nogroup",
64 'desc' => "{DateList.nogroup}",
65 'type' => "flag",
66 'reqd' => "no" },
67
68 ];
69
70my $options = { 'name' => "DateList",
71 'desc' => "{DateList.desc}",
72 'abstract' => "no",
73 'inherits' => "yes",
74 'args' => $arguments };
75
76
77sub new {
78 my $class = shift (@_);
79 my $self = new BasClas($class, @_);
80
81 # 14-05-02 To allow for proper inheritance of arguments - John Thompson
82 my $option_list = $self->{'option_list'};
83 push( @{$option_list}, $options );
84
85 if ($self->{'info_only'}) {
86 # created from classinfo.pl - don't need to parse the arguments
87 return bless $self, $class;
88 }
89
90 $self->{'list'} = {};
91
92 my ($datemeta, $sortmeta);
93 $self->{'nogroup'}=0;
94 if (!parsargv::parse(\@_,
95 q^bymonth^, \$self->{'bymonth'},
96 q^nogroup^, \$self->{'nogroup'},
97 q^metadata/.*/^, \$datemeta,
98 q^sort/.*/^, \$sortmeta,
99 "allow_extra_options")) {
100 $self->print_txt_usage(""); # Use default resource bundle
101 die "\n";
102 }
103
104 if (!defined $datemeta || $datemeta eq "") {
105 $datemeta = "Date";
106 }
107 $self->{'datemeta'} = $datemeta;
108
109 if (defined $sortmeta && $sortmeta ne "") {
110 $self->{'sortmeta'} = $sortmeta;
111 }
112 return bless $self, $class;
113}
114
115sub init {
116 my $self = shift (@_);
117
118 $self->{'list'} = {};
119}
120
121sub classify {
122 my $self = shift (@_);
123 my ($doc_obj) = @_;
124
125 my $doc_OID = $doc_obj->get_OID();
126 my $date = $doc_obj->get_metadata_element ($doc_obj->get_top_section(), $self->{'datemeta'});
127
128 my $sort_other = "";
129 if (defined $self->{'sortmeta'} && $self->{'sortmeta'} ne "") {
130 $sort_other = $doc_obj->get_metadata_element ($doc_obj->get_top_section(), $self->{'sortmeta'});
131 }
132 # if this document doesn't contain Date element we won't
133 # include it in this classification
134 if (defined $date && $date =~ /\d/) {
135 if (defined $self->{'list'}->{$doc_OID}) {
136 my $outhandle = $self->{'outhandle'};
137 print $outhandle "WARNING: DateList::classify called multiple times for $doc_OID\n";
138 }
139
140
141 $self->{'list'}->{$doc_OID} = "$date$sort_other";
142 }
143}
144
145
146sub get_classify_info {
147 my $self = shift (@_);
148
149 my @classlist = sort {$self->{'list'}->{$a} cmp $self->{'list'}->{$b};} keys %{$self->{'list'}};
150
151 return $self->splitlist (\@classlist);
152}
153
154
155sub get_entry {
156 my $self = shift (@_);
157 my ($title, $childtype, $thistype) = @_;
158
159 # organise into classification structure
160 my %classifyinfo = ('childtype'=>$childtype,
161 'Title'=>$title,
162 'contains'=>[],
163 'mdtype'=>$self->{'datemeta'});
164 $classifyinfo{'thistype'} = $thistype
165 if defined $thistype && $thistype =~ /\w/;
166
167 return \%classifyinfo;
168}
169
170# splitlist takes an ordered list of classifications (@$classlistref) and
171# splits it up into sub-sections by date
172sub splitlist {
173 my $self = shift (@_);
174 my ($classlistref) = @_;
175 my $classhash = {};
176
177 # top level
178 my $childtype = "HList";
179
180 if (scalar (@$classlistref) <= 39 &&
181 !$self->{'nogroup'}) {$childtype = "DateList";}
182 my $classifyinfo = $self->get_entry ("Date", $childtype, "Invisible");
183 # don't need to do any splitting if there are less than 39 (max + min -1)
184 # classifications, unless nogroup is specified
185 if ((scalar @$classlistref) <= 39 && !$self->{'nogroup'}) {
186 foreach $subOID (@$classlistref) {
187 push (@{$classifyinfo->{'contains'}}, {'OID'=>$subOID});
188 }
189 return $classifyinfo;
190 }
191
192
193 if ($self->{'bymonth'}) {
194 # first split up the list into separate year+month classifications
195
196 if (!$self->{'nogroup'}) { # hlist of year+month pairs
197 # single level of classifications
198 foreach $classification (@$classlistref) {
199 my $date = $self->{'list'}->{$classification};
200 $date =~ s/^(\d\d\d\d)(\d\d).*$/$1&nbsp;_textmonth$2_/;
201 # sanity check if month is zero
202 if ($date =~ /00_$/) {
203 $date =~ s/^(\d\d\d\d).*$/$1/g;
204 }
205 $classhash->{$date} = [] unless defined $classhash->{$date};
206 push (@{$classhash->{$date}}, $classification);
207 }
208
209 } else { # don't group - individual years and months
210 foreach $classification (@$classlistref) {
211 my $date = $self->{'list'}->{$classification};
212 $date =~ s/^(\d\d\d\d)(\d\d).*$/$1&nbsp;_textmonth$2_/;
213 my ($year, $month)=($1,$2);
214 # sanity check if month is zero
215 if ($date =~ /00_$/) {
216 $date =~ s/^(\d\d\d\d).*$/$1/g;
217 }
218 # create subclass if it doesn't already exist
219 $classhash->{$year} = () unless defined $classhash->{$year};
220 $classhash->{$year}->{$month} = []
221 unless defined $classhash->{$year}->{$month};
222 push (@{$classhash->{$year}->{$month}}, $classification);
223 }
224 # create hlist of years containing hlists of months
225
226 foreach my $subclass (sort {$a <=> $b} keys %$classhash) {
227 my $yearclassify = $self->get_entry($subclass, "HList");
228 foreach my $subsubclass (sort {$a <=> $b}
229 (keys %{$classhash->{$subclass}})) {
230 my $monthname=$subsubclass;
231 if ($monthname >= 1 && $monthname <= 12) {
232 $monthname="_textmonth" . $monthname . "_";
233 }
234 my $monthclassify=$self->get_entry($monthname, "DateList");
235 push (@{$yearclassify->{'contains'}}, $monthclassify);
236
237 foreach $subsubOID
238 (@{$classhash->{$subclass}->{$subsubclass}}) {
239 push (@{$monthclassify->{'contains'}},
240 {'OID'=>$subsubOID});
241 }
242 }
243 push (@{$classifyinfo->{'contains'}}, $yearclassify);
244 }
245 return $classifyinfo;
246 } # nogroup
247 } else {
248 # not by month
249 # first split up the list into separate year classifications
250 foreach $classification (@$classlistref) {
251 my $date = $self->{'list'}->{$classification};
252 $date =~ s/^(\d\d\d\d).*$/$1/;
253 $classhash->{$date} = [] unless defined $classhash->{$date};
254 push (@{$classhash->{$date}}, $classification);
255 }
256 }
257
258 # only compact the list if nogroup not specified
259 if (!$self->{'nogroup'}) {
260 $classhash = $self->compactlist ($classhash);
261 }
262 foreach $subclass (sort keys %$classhash) {
263 my $tempclassify = $self->get_entry($subclass, "DateList");
264 foreach $subsubOID (@{$classhash->{$subclass}}) {
265 push (@{$tempclassify->{'contains'}}, {'OID'=>$subsubOID});
266 }
267 push (@{$classifyinfo->{'contains'}}, $tempclassify);
268 }
269
270 return $classifyinfo;
271}
272
273sub compactlist {
274 my $self = shift (@_);
275 my ($classhashref) = @_;
276 my $compactedhash = {};
277 my @currentOIDs = ();
278 my $currentfirstdate = "";
279 my $currentlastdate = "";
280 my $lastkey = "";
281
282 # minimum and maximum documents to be displayed per page.
283 # the actual maximum will be max + (min-1).
284 # the smallest sub-section is a single letter at present
285 # so in this case there may be many times max documents
286 # displayed on a page.
287 my $min = 10;
288 my $max = 30;
289 foreach my $subsection (sort keys %$classhashref) {
290 $currentfirstdate = $subsection if $currentfirstdate eq "";
291 if ((scalar (@currentOIDs) < $min) ||
292 ((scalar (@currentOIDs) + scalar (@{$classhashref->{$subsection}})) <= $max)) {
293 push (@currentOIDs, @{$classhashref->{$subsection}});
294 $currentlastdate = $subsection;
295 } else {
296
297 if ($currentfirstdate eq $currentlastdate) {
298 @{$compactedhash->{$currentfirstdate}} = @currentOIDs;
299 $lastkey = $currentfirstdate;
300 } else {
301 @{$compactedhash->{"$currentfirstdate-$currentlastdate"}} = @currentOIDs;
302 $lastkey = "$currentfirstdate-$currentlastdate";
303 }
304 if (scalar (@{$classhashref->{$subsection}}) >= $max) {
305 $compactedhash->{$subsection} = $classhashref->{$subsection};
306 @currentOIDs = ();
307 $currentfirstdate = "";
308 $lastkey = $subsection;
309 } else {
310 @currentOIDs = @{$classhashref->{$subsection}};
311 $currentfirstdate = $subsection;
312 $currentlastdate = $subsection;
313 }
314 }
315 }
316
317 # add final OIDs to last sub-classification if there aren't many otherwise
318 # add final sub-classification
319 if ((scalar (@currentOIDs) < $min) && (scalar (@currentOIDs) > 0)) {
320 # want every thing in previous up to the dash
321 my ($newkey) = $lastkey =~ /^([^\-]+)/;
322 @currentOIDs = (@{$compactedhash->{$lastkey}}, @currentOIDs);
323 delete $compactedhash->{$lastkey};
324 @{$compactedhash->{"$newkey-$currentlastdate"}} = @currentOIDs;
325 } else {
326 if ($currentfirstdate eq $currentlastdate) {
327 @{$compactedhash->{$currentfirstdate}} = @currentOIDs;
328 } else {
329 @{$compactedhash->{"$currentfirstdate-$currentlastdate"}} = @currentOIDs;
330 }
331 }
332
333 return $compactedhash;
334}
335
3361;
Note: See TracBrowser for help on using the repository browser.