blob: 7da68935d040cd00d85ccbda8325b3a4d8a993cc [file] [log] [blame]
package Krawfish::Koral::Query::Token;
use parent 'Krawfish::Koral::Query';
# use Krawfish::Koral::Query::Token;
use Krawfish::Util::Constants qw/:PREFIX/;
use Krawfish::Koral::Query::Term;
# use Krawfish::Query::Term;
use Krawfish::Log;
use strict;
use warnings;
use Scalar::Util qw/blessed/;
use constant DEBUG => 0;
# Token based query containing boolean definition of terms.
# TODO:
# Token should probably introduce a unique-query to filter out multiple matches.
# It should also remove classes, that are not allowed.
sub new {
my $class = shift;
my $token = shift;
# Any token
unless ($token) {
return bless { operands => [] }, $class;
};
# Token is a string
unless (blessed $token) {
return bless {
operands => [Krawfish::Koral::Query::Term->new(TOKEN_PREF . $token)]
}, $class;
};
# Token is already a group or a term
# TODO:
# Check that everything else is invalid!
bless {
operands => [$token]
};
};
# Query type
sub type { 'token' };
# There are no classes allowed in tokens
sub remove_classes {
$_[0];
};
# Overwrite is anywhere
sub is_anywhere {
return if $_[0]->is_nowhere;
return 1 unless $_[0]->operand;
return;
};
# A token always spans exactly one token
sub min_span {
return 0 if $_[0]->is_null;
1;
};
# A token always spans exactly one token
sub max_span {
return 0 if $_[0]->is_null;
1;
};
# Normalize the token
sub normalize {
my $self = shift;
my $op;
print_log('kq_token', 'Normalize wrapper') if DEBUG;
# There is an operand defined
if ($self->operand) {
my $op = $self->operand->normalize;
if ($op->is_nowhere) {
$self->operands([]);
$self->is_nowhere(1);
}
elsif ($op->is_anywhere) {
$self->operands([]);
$self->is_anywhere(1);
}
elsif (!$self->is_optional && !$self->is_negative) {
return $op;
}
else {
$self->operands([$op]);
};
};
# No operand defined - ANYWHERE query
return $self;
};
sub finalize {
my $self = shift;
# Token is null
if ($self->is_null) {
$self->error(000, 'Unable to search for null tokens');
return;
};
# No term defined
unless ($self->operand) {
$self->error(000, 'Unable to search for anywhere tokens');
return;
};
return $self;
};
sub optimize {
my ($self, $segment) = @_;
# Create token query
unless ($self->operand) {
warn "It's not possible to optimize an anywhere query";
return;
};
# The operand is a single term - ignore the wrapping token
# However - this would ignore the unique constraint for cases,
# where terms are identical, but have different payload information
#if ($self->operand->type eq 'term') {
# return Krawfish::Query::Term->new(
# $index,
# $self->operand->to_string
# );
#};
print_log('kq_token', 'Optimize and return wrap token') if DEBUG;
return $self->operand->optimize($segment);
};
# Stringify
sub to_string {
my ($self, $id) = @_;
my $string = '[';
if ($self->is_nowhere) {
$string .= '0';
}
elsif ($self->is_anywhere) {
$string .= '';
}
elsif ($self->operand) {
if ($self->is_negative) {
$string .= '!';
};
$string .= $self->operand->to_string;
}
$string .= ']';
if ($self->is_null) {
$string .= '{0}';
}
elsif ($self->is_optional) {
$string .= '?';
};
return $string;
};
sub maybe_unsorted { 0 };
sub from_koral {
my $class = shift;
my $kq = shift;
my $importer = $class->importer;
# No wrap
unless ($kq->{'wrap'}) {
return $class->new;
}
# Wrap is a term
else {
my $wrap = $kq->{wrap};
if ($wrap->{'@type'} eq 'koral:term') {
return $class->new($importer->term($wrap));
}
elsif ($wrap->{'@type'} eq 'koral:termGroup') {
return $class->new($importer->term_group($wrap));
}
else {
warn 'Wrap type not supported!'
};
}
};
# Return Koral fragment
sub to_koral_fragment {
my $self = shift;
my $token = {
'@type' => 'koral:token'
};
if ($self->operand) {
$token->{wrap} = $self->operand->to_koral_fragment;
};
$token;
};
1;