source: trunk/gsdl/perllib/classify/AZSectionList.pm@ 425

Last change on this file since 425 was 424, checked in by sjboddie, 25 years ago

fixed some bugs - made it easier to use as sub-classification of
another classifier

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 6.1 KB
Line 
1# classifier plugin for sorting sections alphabetically
2
3# this is very similar to AZList except it sorts by
4# section level metadata (excluding the top level)
5# instead of just top level metadata
6
7# the only change is to the classify() subroutine which
8# must now iterate through each section, adding each
9# to the classification
10
11package AZSectionList;
12
13use sorttools;
14
15sub new {
16 my ($class, @options) = @_;
17
18 if (!defined @options || !scalar @options) {
19 die "AZSectionList used with no metadata name to classify by\n";
20 }
21
22 return bless {
23 'list'=>{},
24 'metaname' => $options[0]
25 }, $class;
26}
27
28sub init {
29 my $self = shift (@_);
30
31 $self->{'list'} = {};
32}
33
34sub classify {
35 my $self = shift (@_);
36 my ($doc_obj) = @_;
37
38 my $doc_OID = $doc_obj->get_OID();
39 my $thissection = $doc_obj->get_next_section ($doc_obj->get_top_section());
40
41 while (defined $thissection) {
42 $self->classify_section ($thissection, $doc_obj);
43 $thissection = $doc_obj->get_next_section ($thissection);
44 }
45}
46
47sub classify_section {
48 my $self = shift (@_);
49 my ($section, $doc_obj) = @_;
50
51 my $doc_OID = $doc_obj->get_OID();
52 my $metavalue = $doc_obj->get_metadata_element ($section, $self->{'metaname'});
53
54 # if this section doesn't contain the metadata element we're
55 # sorting by we won't include it in this classification
56 if (defined $metavalue && $metavalue =~ /\w/) {
57 if ($self->{'metaname'} eq 'Creator') {
58 &sorttools::format_string_name_english (\$metavalue);
59 } else {
60 &sorttools::format_string_english (\$metavalue);
61 }
62 if (defined $self->{'list'}->{"$doc_OID.$section"}) {
63 print STDERR "WARNING: AZSectionList::classify called multiple times for $doc_OID.$section\n";
64 }
65 $self->{'list'}->{"$doc_OID.$section"} = $metavalue;
66 }
67}
68
69sub get_classify_info {
70 my $self = shift (@_);
71
72 my @classlist = sort {$self->{'list'}->{$a} cmp $self->{'list'}->{$b};} keys %{$self->{'list'}};
73
74 return $self->splitlist (\@classlist);
75}
76
77sub get_entry {
78 my $self = shift (@_);
79 my ($title, $classifytype) = @_;
80
81 # organise into classification structure
82 my %classifyinfo = ('classifytype'=>$classifytype,
83 'Title'=>$title,
84 'contains'=>[]);
85
86 return \%classifyinfo;
87}
88
89# splitlist takes an ordered list of classifications (@$classlistref) and splits it
90# up into alphabetical sub-sections.
91sub splitlist {
92 my $self = shift (@_);
93 my ($classlistref) = @_;
94 my $classhash = {};
95
96 # top level
97 my $classifyinfo = $self->get_entry ($self->{'metaname'}, "AZList");
98
99 # don't need to do any splitting if there are less than 20 classifications
100 if ((scalar @$classlistref) <= 20) {
101 foreach $subOID (@$classlistref) {
102 push (@{$classifyinfo->{'contains'}}, {'OID'=>$subOID});
103 }
104 return $classifyinfo;
105 }
106
107 # first split up the list into separate A-Z and 0-9 classifications
108 foreach $classification (@$classlistref) {
109 my $title = $self->{'list'}->{$classification};
110 $title =~ s/^(.).*$/$1/;
111 $title =~ tr/[a-z]/[A-Z]/;
112 if ($title =~ /^[0-9]$/) {$title = '0-9';}
113 elsif ($title !~ /^[A-Z]$/) {
114 print STDERR "AZSectionList: WARNING $classification has badly formatted title ($title)\n";
115 }
116 $classhash->{$title} = [] unless defined $classhash->{$title};
117 push (@{$classhash->{$title}}, $classification);
118 }
119 $classhash = $self->compactlist ($classhash);
120
121 my @tmparr = ();
122 foreach $subsection (sort keys (%$classhash)) {
123 push (@tmparr, $subsection);
124 }
125
126 # if there's a 0-9 section it will have been sorted to the beginning
127 # but we want it at the end
128 if ($tmparr[0] eq '0-9') {
129 shift @tmparr;
130 push (@tmparr, '0-9');
131 }
132
133 foreach $subclass (@tmparr) {
134 my $tempclassify = $self->get_entry($subclass, "AZList");
135 foreach $subsubOID (@{$classhash->{$subclass}}) {
136 push (@{$tempclassify->{'contains'}}, {'OID'=>$subsubOID});
137 }
138 push (@{$classifyinfo->{'contains'}}, $tempclassify);
139 }
140
141 return $classifyinfo;
142}
143
144sub compactlist {
145 my $self = shift (@_);
146 my ($classhashref) = @_;
147 my $compactedhash = {};
148 my @currentOIDs = ();
149 my $currentfirstletter = "";
150 my $currentlastletter = "";
151 my $lastkey = "";
152
153 # minimum and maximum documents to be displayed per page.
154 # the actual maximum will be max + (min-1).
155 # the smallest sub-section is a single letter at present
156 # so in this case there may be many times max documents
157 # displayed on a page.
158 my $min = 10;
159 my $max = 30;
160
161 foreach $subsection (sort keys %$classhashref) {
162 if ($subsection eq '0-9') {
163 @{$compactedhash->{$subsection}} = @{$classhashref->{$subsection}};
164 next;
165 }
166 $currentfirstletter = $subsection if $currentfirstletter eq "";
167 if ((scalar (@currentOIDs) < $min) ||
168 ((scalar (@currentOIDs) + scalar (@{$classhashref->{$subsection}})) <= $max)) {
169 push (@currentOIDs, @{$classhashref->{$subsection}});
170 $currentlastletter = $subsection;
171 } else {
172
173 if ($currentfirstletter eq $currentlastletter) {
174 @{$compactedhash->{$currentfirstletter}} = @currentOIDs;
175 $lastkey = $currentfirstletter;
176 } else {
177 @{$compactedhash->{"$currentfirstletter-$currentlastletter"}} = @currentOIDs;
178 $lastkey = "$currentfirstletter-$currentlastletter";
179 }
180 if (scalar (@{$classhashref->{$subsection}}) >= $max) {
181 $compactedhash->{$subsection} = $classhashref->{$subsection};
182 @currentOIDs = ();
183 $currentfirstletter = "";
184 } else {
185 @currentOIDs = @{$classhashref->{$subsection}};
186 $currentfirstletter = $subsection;
187 $currentlastletter = $subsection;
188 }
189 }
190 }
191
192 # add final OIDs to last sub-classification if there aren't many otherwise
193 # add final sub-classification
194 if (scalar (@currentOIDs) < $min) {
195 my ($newkey) = $lastkey =~ /^(.)/;
196 @currentOIDs = (@{$compactedhash->{$lastkey}}, @currentOIDs);
197 delete $compactedhash->{$lastkey};
198 @{$compactedhash->{"$newkey-$currentlastletter"}} = @currentOIDs;
199 } else {
200 if ($currentfirstletter eq $currentlastletter) {
201 @{$compactedhash->{$currentfirstletter}} = @currentOIDs;
202 } else {
203 @{$compactedhash->{"$currentfirstletter-$currentlastletter"}} = @currentOIDs;
204 }
205 }
206
207 return $compactedhash;
208}
209
2101;
Note: See TracBrowser for help on using the repository browser.