/[suikacvs]/webroot/swe/lib/SWE/Object/Document.pm
Suika

Contents of /webroot/swe/lib/SWE/Object/Document.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (hide annotations) (download)
Wed Sep 23 10:22:07 2009 UTC (16 years, 7 months ago) by wakaba
Branch: MAIN
Changes since 1.12: +2 -1 lines
++ swe/lib/SWE/Object/ChangeLog	23 Sep 2009 10:20:25 -0000
2009-09-23  Wakaba  <wakaba@suika.fam.cx>

	* Document.pm (prop_untainted): Typo.
	(untainted_prop): The |prop_untainted| property was not set.

1 wakaba 1.1 package SWE::Object::Document;
2     use strict;
3     use warnings;
4 wakaba 1.7 use SWE::Lang qw/%ContentMediaType/;
5     use UNIVERSAL::require;
6 wakaba 1.1
7     sub new ($%) {
8     my $class = shift;
9     my $self = bless {@_}, $class;
10    
11     return $self;
12     }
13    
14 wakaba 1.3 sub new_id ($%) {
15     my $self = shift->new (@_);
16    
17 wakaba 1.4 ## NOTE: MUST be executed in names_lock.
18    
19 wakaba 1.3 my $idgen = $self->db->id;
20     my $id = $idgen->get_next_id;
21     $self->{id} = $id;
22    
23     return $self;
24     } # new_id
25    
26 wakaba 1.12 sub db ($) { $_[0]->{db} }
27 wakaba 1.1
28 wakaba 1.12 sub repo ($) { $_[0]->{repo} }
29    
30     sub id ($) { $_[0]->{id} }
31 wakaba 1.1
32 wakaba 1.7 sub reblessed : lvalue { $_[0]->{reblessed} }
33    
34     sub rebless ($) {
35     my $self = shift;
36     return if $self->reblessed;
37    
38 wakaba 1.9 my $id = $self->id;
39     my $module;
40     if (defined $id) {
41     my $ct = $self->content_media_type;
42     $module = $ContentMediaType{$ct}->{module} || $ContentMediaType{'text/x-suikawiki'}->{module};
43     } else {
44     $module = 'SWE::Object::Document::NotYet';
45     }
46 wakaba 1.7 $module->require or die $@;
47     bless $self, $module;
48    
49     $self->reblessed = 1;
50     }
51    
52 wakaba 1.10 ## ------ Metadata ------
53    
54 wakaba 1.8 sub prop ($) {
55     my $self = shift;
56 wakaba 1.12 return $self->{prop} ||= do {
57     $self->prop_untainted = 0 unless $self->locked;
58     $self->db->id_prop->get_data ($self->id);
59     };
60 wakaba 1.8 } # prop
61    
62 wakaba 1.13 sub prop_untainted ($) : lvalue { $_[0]->{prop_untainted} }
63 wakaba 1.12
64     sub untainted_prop ($) {
65     my $self = shift;
66     delete $self->{prop} unless $self->prop_untainted;
67 wakaba 1.13 $self->prop_untainted = 1;
68 wakaba 1.12 return $self->prop;
69     } # untainted_prop
70    
71     sub save_prop ($) {
72     my $self = shift;
73    
74     $self->lock;
75    
76     unless ($self->prop_untainted) {
77     die "Can't save a tainted prop object";
78     }
79    
80     my $prop = $self->prop or die "Can't save an uncreated prop object";
81     $self->db->id_prop->set_data ($self->id => $prop);
82    
83     $self->unlock;
84     } # save_prop
85    
86 wakaba 1.7 sub content_media_type ($) {
87 wakaba 1.8 my $self = shift;
88     return $self->prop->{'content-type'} // 'text/x-suikawiki';
89     } # content_media_type
90 wakaba 1.7
91 wakaba 1.1 sub associate_names ($$%) {
92     my ($self, $names, %args) = @_;
93    
94     ## NOTE: names_lock MUST be executed before the invocation.
95    
96     my $id = $self->id;
97     my $time = $args{time} || time;
98     my $sw3_pages = $self->{sw3_pages}; ## TODO: ...
99    
100     my $vc = $self->db->vc;
101    
102     my $name_prop_db = $self->{name_prop_db}; ## TODO: ...
103     local $name_prop_db->{version_control} = $vc;
104    
105     my $name_history_db = $self->db->name_history;
106     local $name_history_db->{version_control} = $vc;
107    
108     for my $name (keys %$names) {
109     my $name_props = $name_prop_db->get_data ($name);
110     unless (defined $name_props) {
111     my $sw3id = $sw3_pages->get_data ($name);
112     main::convert_sw3_page ($sw3id => $name); ## TODO: ...
113    
114     $name_props = $name_prop_db->get_data ($name);
115     unless (defined $name_props) {
116     $name_history_db->append_data ($name => [$time, 'c']);
117     }
118     }
119    
120     push @{$name_props->{id} ||= []}, $id;
121     $name_props->{name} = $name;
122     $name_prop_db->set_data ($name => $name_props);
123    
124     $name_history_db->append_data ($name => [$time, 'a', $id]);
125     }
126    
127     my $user = $args{user} || '(anon)';
128     $vc->commit_changes ("id=$id created by $user");
129     } # associate_names
130    
131 wakaba 1.10 sub title ($) {
132     my $self = shift;
133    
134     my $prop = $self->prop;
135    
136     my $title = $prop->{title};
137     return $title if defined $title and length $title;
138    
139     $title = [keys %{$prop->{name}}]->[0] // ''; ## XXXTODO: title-type
140     return $title;
141     } # title
142    
143     ## ------ Indexing and Graph ------
144    
145 wakaba 1.2 sub update_tfidf ($$) {
146     my ($self, $doc) = @_; ## TODO: $doc should not be an argument
147    
148     ## It is REQUIRED to lock the $id before the invocation of this
149     ## method to keep the consistency of tfidf data for the $id.
150    
151     my $id = $self->id;
152    
153     my $tfidf_db = $self->db->id_tfidf;
154    
155     require SWE::Data::FeatureVector;
156    
157     my $deleted_terms = SWE::Data::FeatureVector->parse_stringref
158     ($tfidf_db->get_data ($id))->as_key_hashref;
159    
160     my $tc = $doc->document_element->text_content;
161    
162     ## TODO: use element semantics...
163    
164     my $orig_tfs = {};
165     my $all_terms = 0;
166     main::for_unique_words ($tc => sub {
167     $orig_tfs->{$_[0]} = $_[1];
168     $all_terms += $_[1];
169     }); ## TODO: XXX
170    
171     my $names_index_db = $self->db->name_inverted_index;
172     $names_index_db->lock;
173    
174     my $idgen = $self->db->id;
175     my $doc_number = $idgen->get_last_id;
176    
177     my $terms = SWE::Data::FeatureVector->new;
178     for my $term (keys %$orig_tfs) {
179     my $n_tf = $orig_tfs->{$term} / $all_terms;
180    
181     my $df = $names_index_db->get_count ($term);
182     my $idf = log ($doc_number / ($df + 1));
183    
184     my $tfidf = $n_tf * $idf;
185    
186     $terms->set_tfidf ($term, $tfidf);
187     $names_index_db->add_data ($term => $id => $tfidf);
188    
189     delete $deleted_terms->{$term};
190     }
191    
192     for my $term (keys %$deleted_terms) {
193     $names_index_db->delete_data ($term, $id);
194     }
195    
196     $tfidf_db->set_data ($id => \( $terms->stringify ));
197     } # update_tfidf
198    
199 wakaba 1.10 sub get_or_create_graph_node ($) {
200     my $self = shift;
201    
202 wakaba 1.12 $self->lock;
203 wakaba 1.10
204 wakaba 1.12 my $id_prop = $self->untainted_prop or do {
205     $self->unlock;
206     return;
207     };
208 wakaba 1.10
209 wakaba 1.12 my $graph = $self->repo->graph;
210 wakaba 1.10 my $node;
211     my $node_id = $id_prop->{node_id};
212     if (defined $node_id) {
213     $node = $graph->get_node_by_id ($node_id);
214     } else {
215 wakaba 1.12 $node = $graph->create_node ($self->id);
216 wakaba 1.10 $node_id = $node->id;
217    
218     $id_prop->{node_id} = $node_id;
219 wakaba 1.12 $self->save_prop;
220 wakaba 1.10 }
221    
222 wakaba 1.12 $self->unlock;
223    
224 wakaba 1.10 return $node;
225     } # get_or_create_graph_node
226    
227     # ------ Locking ------
228    
229 wakaba 1.5 sub lock ($) {
230     my $self = shift;
231 wakaba 1.11 my $lock = $self->{lock} ||= $self->db->id_lock->get_lock ($self->id);
232 wakaba 1.5 $self->{lock_n}++ or $self->lock;
233     } # lock
234    
235     sub unlock ($) {
236     my $self = shift;
237     my $lock = $self->{lock};
238     $self->{lock_n}--;
239     if ($lock and $self->{lock_n} <= 0) {
240     $lock->unlock;
241     delete $self->{lock};
242     delete $self->{lock_n};
243 wakaba 1.12 delete $self->{prop_untainted};
244 wakaba 1.5 }
245     } # unlock
246 wakaba 1.12
247     sub locked ($) {
248     return $_[0]->{lock_n} > 0;
249     } # locked
250 wakaba 1.10
251     # ------ Format Convertion ------
252 wakaba 1.5
253 wakaba 1.8 sub to_text ($) {
254     my $self = shift;
255    
256     return $self->{content_db}->get_data ($self->id); # XXX
257     } # to_text
258    
259     sub to_text_media_type ($) {
260     my $self = shift;
261     return $self->content_media_type;
262     } # to_text_media_type
263    
264     sub to_xml_media_type ($) {
265     return undef;
266     } # to_xml_media_type
267    
268     sub to_xml ($) {
269     return undef;
270     } # to_xml
271    
272     sub to_html_fragment ($) {
273     return (undef, undef);
274     } # to_html_fragment
275 wakaba 1.6
276 wakaba 1.1 1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24