blob: 908c145a466e373415ee67e2f537ad4248b77e47 [file] [log] [blame]
Akron8a679332016-11-01 16:18:55 +01001package Krawfish::Koral::Corpus::Field;
Akronc3ebcbb2018-04-02 16:30:18 +02002use Krawfish::Util::String qw/normalize_nfkc/;
Akron7dc2a642017-08-02 15:39:49 +02003use Krawfish::Koral::Corpus::FieldID;
Akron4335bdc2018-03-08 17:15:33 +01004use Role::Tiny;
Akron8a679332016-11-01 16:18:55 +01005use strict;
6use warnings;
7
Akronbc7dd432017-07-18 14:21:51 +02008use constant DEBUG => 0;
Akron8a271422017-06-08 01:58:32 +02009
Akron61e8bce2017-05-24 15:55:27 +020010# TODO:
11# - Check for valid parameters
12# - Only support positive terms
13# - Wrap in negative field!
Akron8a679332016-11-01 16:18:55 +010014
Akron93271d82016-11-24 09:18:41 +010015sub type {
16 'field';
17};
18
Akron2c6c7162017-05-15 18:15:33 +020019sub is_leaf { 1 };
20
Akron61e8bce2017-05-24 15:55:27 +020021# Equal
Akron8a679332016-11-01 16:18:55 +010022sub eq {
23 my $self = shift;
24 $self->{match} = 'eq';
Akron1bbe60e2018-03-25 09:28:37 +020025 $self->value(shift) or return;
Akron8a679332016-11-01 16:18:55 +010026 return $self;
27};
28
Akron61e8bce2017-05-24 15:55:27 +020029
30# Not equal
Akron8a679332016-11-01 16:18:55 +010031sub ne {
32 my $self = shift;
Akrond3355ba2017-05-17 21:16:35 +020033 $self->{match} = 'eq';
Akron373df822016-12-28 15:25:14 +010034 $self->is_negative(1);
Akron1bbe60e2018-03-25 09:28:37 +020035 $self->value(shift) or return;
Akron8a679332016-11-01 16:18:55 +010036 return $self;
37};
38
Akron61e8bce2017-05-24 15:55:27 +020039
40# Check for negativity
Akrond3355ba2017-05-17 21:16:35 +020041sub is_negative {
42 my $self = shift;
43 if (scalar @_ == 1) {
44 $self->{negative} = shift;
45
46 my $op = $self->match;
47 if ($self->{negative}) {
48
49 # Reverse operation
50 if ($op eq 'eq') {
51 $self->{match} = 'ne';
52 }
53 elsif ($op eq 'contains') {
54 $self->{match} = 'excludes'
55 };
56 }
57
58 else {
59
60 # Reverse operation
61 if ($op eq 'ne') {
62 $self->{match} = 'eq';
63 }
64 elsif ($op eq 'excludes') {
65 $self->{match} = 'contains'
66 };
67 };
68 };
69 return $self->{negative} // 0;
70};
71
Akron4335bdc2018-03-08 17:15:33 +010072
Akron76caadc2018-03-27 18:41:01 +020073# Toggle negativity
74sub toggle_negative {
75 my $self = shift;
76 my $op = $self->match;
77
78 # Reverse operation
79 if ($op eq 'eq') {
80 $self->{match} = 'ne';
81 $self->is_negative(1);
82 }
83 elsif ($op eq 'ne') {
84 $self->{match} = 'eq';
85 $self->is_negative(0);
86 }
87 elsif ($op eq 'contains') {
88 $self->{match} = 'excludes';
89 $self->is_negative(1);
90 }
91 elsif ($op eq 'excludes') {
92 $self->{match} = 'contains';
93 $self->is_negative(0);
94 }
95 else {
96 warn 'Unknown operation';
97 };
98
99 return $self;
100};
101
102
Akron61e8bce2017-05-24 15:55:27 +0200103# Contains the value in multi-token field
Akron8a679332016-11-01 16:18:55 +0100104sub contains {
105 my $self = shift;
106 $self->{match} = 'contains';
Akron1bbe60e2018-03-25 09:28:37 +0200107 $self->value(shift) or return;
Akron8a679332016-11-01 16:18:55 +0100108 return $self;
109};
110
Akron61e8bce2017-05-24 15:55:27 +0200111
112# Does not contain the value in multi-token field
Akron8a679332016-11-01 16:18:55 +0100113sub excludes {
114 my $self = shift;
115 $self->{match} = 'excludes';
Akron1bbe60e2018-03-25 09:28:37 +0200116 $self->value(shift) or return;
Akron8a679332016-11-01 16:18:55 +0100117 return $self;
118};
119
Akron290f59f2017-08-17 21:55:07 +0200120sub can_toggle_negativity {
121 ...
122};
Akron61e8bce2017-05-24 15:55:27 +0200123
Akronc3ebcbb2018-04-02 16:30:18 +0200124sub normalize {
125 my $self = shift;
126 $self->{value} = normalize_nfkc($self->value) if $self->value;
127 return $self;
128};
Akronbc7dd432017-07-18 14:21:51 +0200129
Akron4335bdc2018-03-08 17:15:33 +0100130sub optimize {
131 'Irrelevant';
132};
133
Akron7dc2a642017-08-02 15:39:49 +0200134
135sub operands {
Akron3ee72ec2018-03-26 22:49:36 +0200136 warn 'operands() called in leaf node';
Akron7dc2a642017-08-02 15:39:49 +0200137};
138
139
Akron3ee72ec2018-03-26 22:49:36 +0200140sub identify {
141 warn 'Override';
142};
143
Akronca4cd542018-03-09 18:20:56 +0100144# TODO: Support existence
Akron8a679332016-11-01 16:18:55 +0100145sub match {
Akronca4cd542018-03-09 18:20:56 +0100146 my $self = shift;
147 if (@_) {
148 $self->{match} = shift;
149 return $self;
150 };
151 return ($self->{match} // 'eq');
Akron8a679332016-11-01 16:18:55 +0100152};
153
Akrond3355ba2017-05-17 21:16:35 +0200154
Akron8a679332016-11-01 16:18:55 +0100155sub key {
156 $_[0]->{key};
157};
158
159
160sub value {
Akron1bbe60e2018-03-25 09:28:37 +0200161 my $self = shift;
162 if (@_) {
163 $self->{value} = shift;
164 return $self;
165 };
166 return $self->{value};
Akron8a679332016-11-01 16:18:55 +0100167};
168
Akrond3355ba2017-05-17 21:16:35 +0200169
Akron8a679332016-11-01 16:18:55 +0100170sub to_koral_fragment {
171 my $self = shift;
172
173 my $field = {
174 '@type' => 'koral:field',
175 key => $self->key,
176 match => 'match:' . $self->match,
Akron93271d82016-11-24 09:18:41 +0100177 type => 'type:' . $self->key_type
Akron8a679332016-11-01 16:18:55 +0100178 };
179
180 # No value defined
181 unless ($self->value) {
182
183 # Check for existence
184 if ($field->{match} ne 'match:contains' ||
185 $field->{match} ne 'match:excludes') {
186
187 # Set to existence default
188 $field->{match} = 'match:contains';
189 };
190 }
191
192 # Set value
193 else {
194 $field->{value} = $self->value;
195 };
196
197 return $field;
198};
199
200
Akrone21cb602018-03-10 11:35:52 +0100201# Stringification
Akronded01ae2016-11-23 13:43:54 +0100202sub to_string {
203 my $self = shift;
Akron2c6c7162017-05-15 18:15:33 +0200204
205 return 0 if $self->is_null;
206
Akron38ec3052018-03-08 19:50:18 +0100207 my $str = ''; # $self->key_type . ':';
208 $str .= $self->{key};
Akronded01ae2016-11-23 13:43:54 +0100209 my $op = $self->match;
Akron22b68582017-01-19 12:05:21 +0100210
211 unless ($self->{value}) {
212 return $str unless $op eq 'excludes';
Akron38ec3052018-03-08 19:50:18 +0100213 return $str; # KEY_PREF . $str;
Akron22b68582017-01-19 12:05:21 +0100214 };
215
Akrone21cb602018-03-10 11:35:52 +0100216 $str .= $self->match_short;
217
Akron3c896682018-03-24 12:00:55 +0100218 return $str . $self->value_string;
Akrone21cb602018-03-10 11:35:52 +0100219};
220
221
Akron3c896682018-03-24 12:00:55 +0100222sub value_string {
223 $_[0]->{value};
224};
225
Akrone21cb602018-03-10 11:35:52 +0100226sub match_short {
227 my $self = shift;
228 my $op = $self->match;
Akronded01ae2016-11-23 13:43:54 +0100229 if ($op eq 'eq') {
Akrone21cb602018-03-10 11:35:52 +0100230 return '=';
Akronded01ae2016-11-23 13:43:54 +0100231 }
232 elsif ($op eq 'ne') {
Akrone21cb602018-03-10 11:35:52 +0100233 return '!=';
Akronded01ae2016-11-23 13:43:54 +0100234 }
235 elsif ($op eq 'geq') {
Akrone21cb602018-03-10 11:35:52 +0100236 return '>=';
Akronded01ae2016-11-23 13:43:54 +0100237 }
238 elsif ($op eq 'leq') {
Akrone21cb602018-03-10 11:35:52 +0100239 return '<=';
Akronded01ae2016-11-23 13:43:54 +0100240 }
241 elsif ($op eq 'contains') {
Akrone21cb602018-03-10 11:35:52 +0100242 return '~'
Akronded01ae2016-11-23 13:43:54 +0100243 }
244 elsif ($op eq 'excludes') {
Akrone21cb602018-03-10 11:35:52 +0100245 return '!=';
Akronded01ae2016-11-23 13:43:54 +0100246 };
Akrone21cb602018-03-10 11:35:52 +0100247 return '?';
248};
249
250
251# Stringification for sorting
252sub to_sort_string {
Akron1bbe60e2018-03-25 09:28:37 +0200253 # TODO:
254 # Maybe date, string etc. implementations are generalizable!
Akrone21cb602018-03-10 11:35:52 +0100255 return $_[0]->to_string;
Akronded01ae2016-11-23 13:43:54 +0100256};
257
Akronce7f2282018-03-12 13:46:01 +0100258sub is_relational {
Akronce7f2282018-03-12 13:46:01 +0100259 return 0;
260};
261
Akronded01ae2016-11-23 13:43:54 +0100262sub to_term {
263 my $self = shift;
264 my $term = $self->to_string;
265 $term =~ s/^([^=!><~\?]+?)(?:[!<>]?[=~\?])/$1:/;
266 return $term;
267};
268
Akron57569552017-06-20 13:31:25 +0200269
Akronacde0ba2017-12-08 14:05:13 +0100270sub from_koral {
271 ...
272};
273
Akron57569552017-06-20 13:31:25 +0200274sub to_neutral {
275 $_[0]->to_term;
276};
277
278
Akron4335bdc2018-03-08 17:15:33 +0100279
Akron8a679332016-11-01 16:18:55 +01002801;