Added lots more modules from lintian. Maemian appears to work.
[maemian] / lib / Maemian / Data.pm
1 # -*- perl -*-
2 # Maemian::Data -- interface to query lists of keywords
3
4 # Copyright (C) 2008 Russ Allbery
5 #
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by the Free
8 # Software Foundation; either version 2 of the License, or (at your option)
9 # any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14 # more details.
15 #
16 # You should have received a copy of the GNU General Public License along with
17 # this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 package Maemian::Data;
20 use strict;
21
22 use Carp qw(croak);
23
24 # The constructor loads a list into a hash in %data, which is private to this
25 # module.  Use %data as a cache to avoid loading the same list more than once
26 # (which means lintian doesn't support having the list change over the life of
27 # the proces.  The returned object knows what list, stored in %data, it is
28 # supposed to act on.
29 {
30     my %data;
31     sub new {
32         my ($class, $type, $separator) = @_;
33         croak('no data type specified') unless $type;
34         unless (exists $data{$type}) {
35             my $dir = $ENV{MAEMIAN_ROOT} . '/data';
36             open(LIST, '<', "$dir/$type")
37                 or croak("unknown data type $type");
38             local ($_, $.);
39             while (<LIST>) {
40                 chomp;
41                 s/^\s+//;
42                 next if /^\#/;
43                 next if /^$/;
44                 my ($key, $val);
45                 if (defined $separator) {
46                     ($key, $val) = split(/$separator/, $_, 2);
47                 } else {
48                     ($key, $val) = ($_ => 1);
49                 }
50                 $data{$type}{$key} = $val;
51             }
52         }
53         my $self = { data => $data{$type} };
54         bless($self, $class);
55         return $self;
56     }
57 }
58
59 # Query a data object for whether a particular keyword is valid.
60 sub known {
61     my ($self, $keyword) = @_;
62     return (exists $self->{data}{$keyword}) ? 1 : undef;
63 }
64
65 # Return all known keywords (in no particular order).
66 sub all {
67     my ($self) = @_;
68     return keys(%{ $self->{data} });
69 }
70
71 # Query a data object for the value attached to a particular keyword.
72 sub value {
73     my ($self, $keyword) = @_;
74     return (exists $self->{data}{$keyword}) ? $self->{data}{$keyword} : undef;
75 }
76
77 1;
78
79 =head1 NAME
80
81 Maemian::Data - Maemian interface to query lists of keywords
82
83 =head1 SYNOPSIS
84
85     my $list = Maemian::Data->new('type');
86     if ($list->known($keyword)) {
87         # do something ...
88     }
89     my $hash = Maemian::Data->new('another-type', '\s+');
90     if ($list->value($keyword) > 1) {
91         # do something ...
92     }
93     my @keywords = $list->all;
94
95 =head1 DESCRIPTION
96
97 Maemian::Data provides a way of loading a list of keywords or key/value
98 pairs from a file in the Maemian root and then querying that list.
99 The lists are stored in the F<data> directory of the Maemian root and
100 consist of one keyword or key/value pair per line.  Blank lines and
101 lines beginning with C<#> are ignored.  Leading and trailing whitespace
102 is stripped.
103
104 If requested, the lines are split into key/value pairs with a given
105 separator regular expression.  Otherwise, keywords are taken verbatim
106 as they are listed in the file and may include spaces.
107
108 This module allows lists such as menu sections, doc-base sections,
109 obsolete packages, package fields, and so forth to be stored in simple,
110 easily editable files.
111
112 =head1 CLASS METHODS
113
114 =over 4
115
116 =item new(TYPE [,SEPARATOR])
117
118 Creates a new Maemian::Data object for the given TYPE.  TYPE is a partial
119 path relative to the F<data> directory and should correspond to a file in
120 that directory.  The contents of that file will be loaded into memory and
121 returned as part of the newly created object.  On error, new() throws an
122 exception.
123
124 If SEPARATOR is given, it will be used as a regular expression for splitting
125 the lines into key/value pairs.
126
127 A given file will only be loaded once.  If new() is called again with the
128 same TYPE argument, the data previously loaded will be reused, avoiding
129 multiple file reads.
130
131 =back
132
133 =head1 INSTANCE METHODS
134
135 =over 4
136
137 =item all()
138
139 Returns all keywords listed in the data file as a list (in no particular
140 order; the original order is not preserved).  In a scalar context, returns
141 the number of keywords.
142
143 =item known(KEYWORD)
144
145 Returns true if KEYWORD was listed in the data file represented by this
146 Maemian::Data instance and false otherwise.
147
148 =item value(KEYWORD)
149
150 Returns the value attached to KEYWORD if it was listed in the data
151 file represented by this Maemian::Data instance and the undefined value
152 otherwise. If SEPARATOR was not given, the value will '1'.
153
154 =back
155
156 =head1 DIAGNOSTICS
157
158 =over 4
159
160 =item no data type specified
161
162 new() was called without a TYPE argument.
163
164 =item unknown data type %s
165
166 The TYPE argument to new() did not correspond to a file in the F<data>
167 directory of the Maemian root.
168
169 =back
170
171 =head1 FILES
172
173 =over 4
174
175 =item MAEMIAN_ROOT/data
176
177 The files loaded by this module must be located in this directory.
178 Relative paths containing a C</> are permitted, so files may be organized
179 in subdirectories in this directory.
180
181 =back
182
183 =head1 ENVIRONMENT
184
185 =over 4
186
187 =item MAEMIAN_ROOT
188
189 This variable must be set to Maemian's root directory (normally
190 F</usr/share/lintian> when Maemian is installed as a Debian package).  The
191 B<lintian> program normally takes care of doing this.  This module doesn't
192 care about the contents of this directory other than expecting the F<data>
193 subdirectory of this directory to contain its files.
194
195 =back
196
197 =head1 AUTHOR
198
199 Originally written by Russ Allbery <rra@debian.org> for Maemian.
200
201 =head1 SEE ALSO
202
203 lintian(1)
204
205 =cut
206
207 1;
208
209 # Local Variables:
210 # indent-tabs-mode: nil
211 # cperl-indent-level: 4
212 # End:
213 # vim: syntax=perl sw=4 sts=4 ts=4 et shiftround