blob: a83d1b69cb603ac13a85f3f74ad3e828e0021620 [file] [log] [blame]
Akron33f1dcb2016-10-29 17:27:23 +02001package Krawfish::Koral::Query::Token;
2use parent 'Krawfish::Koral::Query';
Akron3ab2e972017-08-02 19:10:10 +02003# use Krawfish::Koral::Query::Token;
Akron33f1dcb2016-10-29 17:27:23 +02004use Krawfish::Koral::Query::Term;
Akron3ab2e972017-08-02 19:10:10 +02005# use Krawfish::Query::Term;
Akron6b195632017-06-09 23:47:49 +02006use Krawfish::Log;
Akron33f1dcb2016-10-29 17:27:23 +02007use strict;
8use warnings;
Akron06eb4d32016-11-11 14:05:52 +01009use Scalar::Util qw/blessed/;
Akron33f1dcb2016-10-29 17:27:23 +020010
Akronbc7dd432017-07-18 14:21:51 +020011use constant DEBUG => 0;
Akron6b195632017-06-09 23:47:49 +020012
Akron4f9eef42017-07-24 11:41:09 +020013# Token based query containing boolean definition of terms.
14
15# TODO:
16# Token should probably introduce a unique-query to filter out multiple matches.
17# It should also remove classes, that are not allowed.
18
Akron33f1dcb2016-10-29 17:27:23 +020019sub new {
20 my $class = shift;
Akron06eb4d32016-11-11 14:05:52 +010021 my $token = shift;
22
23 # Any token
24 unless ($token) {
Akron5b6264f2017-07-19 01:14:01 +020025 return bless { operands => [] }, $class;
Akron06eb4d32016-11-11 14:05:52 +010026 };
27
28 # Token is a string
29 unless (blessed $token) {
30 return bless {
Akron5b6264f2017-07-19 01:14:01 +020031 operands => [Krawfish::Koral::Query::Term->new($token)]
Akron06eb4d32016-11-11 14:05:52 +010032 }, $class;
33 };
34
35 # Token is already a group or a term
Akron4f9eef42017-07-24 11:41:09 +020036
37 # TODO:
38 # Check that everything else is invalid!
Akron33f1dcb2016-10-29 17:27:23 +020039 bless {
Akron5b6264f2017-07-19 01:14:01 +020040 operands => [$token]
Akron06eb4d32016-11-11 14:05:52 +010041 };
Akron33f1dcb2016-10-29 17:27:23 +020042};
43
Akron4f9eef42017-07-24 11:41:09 +020044
45# Query type
Akron774c5db2016-11-09 16:11:38 +010046sub type { 'token' };
Akron6621e112016-11-05 17:21:39 +010047
Akron4f9eef42017-07-24 11:41:09 +020048
Akron5b6264f2017-07-19 01:14:01 +020049# There are no classes allowed in tokens
Akron5ddc38f2017-07-18 00:16:22 +020050sub remove_classes {
51 $_[0];
52};
Akron06eb4d32016-11-11 14:05:52 +010053
Akron4763ea62016-11-02 19:36:18 +010054
55# Overwrite is any
56sub is_any {
Akron8231ca72017-06-16 16:08:32 +020057 return if $_[0]->is_nothing;
Akron5b6264f2017-07-19 01:14:01 +020058 return 1 unless $_[0]->operand;
Akron4763ea62016-11-02 19:36:18 +010059 return;
60};
61
Akronce10cb42017-06-14 01:12:40 +020062
Akron704ec062017-07-24 15:46:21 +020063# A token always spans exactly one token
64sub min_span {
65 return 0 if $_[0]->is_null;
66 1;
67};
68
69
70# A token always spans exactly one token
71sub max_span {
72 return 0 if $_[0]->is_null;
73 1;
74};
75
76
Akron4f9eef42017-07-24 11:41:09 +020077# Normalize the token
Akron6b195632017-06-09 23:47:49 +020078sub normalize {
79 my $self = shift;
Akron5b6264f2017-07-19 01:14:01 +020080 my $op;
81
Akron6b195632017-06-09 23:47:49 +020082 print_log('kq_token', 'Normalize wrapper') if DEBUG;
Akron5b6264f2017-07-19 01:14:01 +020083
Akron4f9eef42017-07-24 11:41:09 +020084 # There is an operand defined
Akron5b6264f2017-07-19 01:14:01 +020085 if ($self->operand) {
86 my $op = $self->operand->normalize;
87 if ($op->is_nothing) {
88 $self->operands([]);
Akron8231ca72017-06-16 16:08:32 +020089 $self->is_nothing(1);
90 }
Akron5b6264f2017-07-19 01:14:01 +020091 elsif ($op->is_any) {
92 $self->operands([]);
Akron8231ca72017-06-16 16:08:32 +020093 $self->is_any(1);
94 }
95 elsif (!$self->is_optional && !$self->is_negative) {
Akron5b6264f2017-07-19 01:14:01 +020096 return $op;
97 }
98 else {
99 $self->operands([$op]);
Akronce10cb42017-06-14 01:12:40 +0200100 };
Akronc048b182017-06-13 01:29:03 +0200101 };
Akron4f9eef42017-07-24 11:41:09 +0200102
103 # No operand defined - ANY query
Akron6b195632017-06-09 23:47:49 +0200104 return $self;
105};
106
Akronce10cb42017-06-14 01:12:40 +0200107
Akronc048b182017-06-13 01:29:03 +0200108sub inflate {
109 my ($self, $dict) = @_;
110 print_log('kq_token', 'Inflate wrapper') if DEBUG;
Akron5b6264f2017-07-19 01:14:01 +0200111 $self->operands([$self->operand->inflate($dict)]);
Akronc048b182017-06-13 01:29:03 +0200112 return $self;
113};
Akron6b195632017-06-09 23:47:49 +0200114
Akronc048b182017-06-13 01:29:03 +0200115sub finalize {
116 my $self = shift;
Akron6b195632017-06-09 23:47:49 +0200117
118 # Token is null
119 if ($self->is_null) {
120 $self->error(000, 'Unable to search for null tokens');
121 return;
122 };
123
124 # No term defined
Akron5b6264f2017-07-19 01:14:01 +0200125 unless ($self->operand) {
Akron6b195632017-06-09 23:47:49 +0200126 $self->error(000, 'Unable to search for any tokens');
127 return;
128 };
129
Akronc048b182017-06-13 01:29:03 +0200130 return $self;
131};
132
Akron5ddc38f2017-07-18 00:16:22 +0200133
Akronc048b182017-06-13 01:29:03 +0200134sub optimize {
135 my ($self, $index) = @_;
136
Akron6b195632017-06-09 23:47:49 +0200137 # Create token query
Akron5b6264f2017-07-19 01:14:01 +0200138 unless ($self->operand) {
Akron5ddc38f2017-07-18 00:16:22 +0200139 warn "It's not possible to optimize an any query";
140 return;
141 };
142
Akron4f9eef42017-07-24 11:41:09 +0200143 # The operand is a single term - ignore the wrapping token
144 # However - this would ignore the unique constraint for cases,
145 # where terms are identical, but have different payload information
Akron3ab2e972017-08-02 19:10:10 +0200146 #if ($self->operand->type eq 'term') {
147 # return Krawfish::Query::Term->new(
148 # $index,
149 # $self->operand->to_string
150 # );
151 #};
Akron6b195632017-06-09 23:47:49 +0200152
153 print_log('kq_token', 'Optimize and return wrap token') if DEBUG;
Akron5b6264f2017-07-19 01:14:01 +0200154 return $self->operand->optimize($index);
Akron6b195632017-06-09 23:47:49 +0200155};
156
Akron6621e112016-11-05 17:21:39 +0100157
Akron6b195632017-06-09 23:47:49 +0200158
Akron6621e112016-11-05 17:21:39 +0100159# Stringify
Akrona211bf52016-10-29 18:03:29 +0200160sub to_string {
Akronce10cb42017-06-14 01:12:40 +0200161 my $self = shift;
162
Akron8231ca72017-06-16 16:08:32 +0200163 my $string = '[';
Akron5ddc38f2017-07-18 00:16:22 +0200164
Akronce10cb42017-06-14 01:12:40 +0200165 if ($self->is_nothing) {
Akron8231ca72017-06-16 16:08:32 +0200166 $string .= '0';
167 }
168 elsif ($self->is_any) {
169 $string .= '';
170 }
Akron5b6264f2017-07-19 01:14:01 +0200171 elsif ($self->operand) {
Akron5ddc38f2017-07-18 00:16:22 +0200172 if ($self->is_negative) {
173 $string .= '!';
174 };
175
Akron5b6264f2017-07-19 01:14:01 +0200176 $string .= $self->operand->to_string;
Akron8231ca72017-06-16 16:08:32 +0200177 }
Akronce10cb42017-06-14 01:12:40 +0200178
Akron8231ca72017-06-16 16:08:32 +0200179 $string .= ']';
180
Akronce10cb42017-06-14 01:12:40 +0200181 if ($self->is_null) {
Akronddf077a2016-11-05 15:00:00 +0100182 $string .= '{0}';
183 }
Akron8231ca72017-06-16 16:08:32 +0200184
Akronce10cb42017-06-14 01:12:40 +0200185 elsif ($self->is_optional) {
Akronddf077a2016-11-05 15:00:00 +0100186 $string .= '?';
187 };
Akron8231ca72017-06-16 16:08:32 +0200188
Akronddf077a2016-11-05 15:00:00 +0100189 return $string;
Akrona211bf52016-10-29 18:03:29 +0200190};
191
Akron4de66202016-11-11 14:13:43 +0100192
Akron1b09c5b2016-11-20 15:59:34 +0100193sub maybe_unsorted { 0 };
194
Akron944091b2016-11-24 16:40:58 +0100195sub from_koral {
196 my $class = shift;
197 my $kq = shift;
198 my $importer = $class->importer;
199
200 # No wrap
201 unless ($kq->{'wrap'}) {
202 return $class->new;
203 }
204
205 # Wrap is a term
206 else {
207 my $wrap = $kq->{wrap};
208 if ($wrap->{'@type'} eq 'koral:term') {
209 return $class->new($importer->term($wrap));
210 }
211 elsif ($wrap->{'@type'} eq 'koral:termGroup') {
212 return $class->new($importer->term_group($wrap));
213 }
214 else {
215 warn 'Wrap type not supported!'
216 };
217 }
218};
Akron1b09c5b2016-11-20 15:59:34 +0100219
Akron818e8522017-07-22 12:34:01 +0200220# Return Koral fragment
221sub to_koral_fragment {
222 my $self = shift;
223
224 my $token = {
225 '@type' => 'koral:token'
226 };
227
228 if ($self->operand) {
229 $token->{wrap} = $self->operand->to_koral_fragment;
230 };
231
232 $token;
233};
234
235
236
Akron33f1dcb2016-10-29 17:27:23 +02002371;