blob: 722e9868521dc5a1ead3707ac7b0c0c9f860d698 [file] [log] [blame]
package Krawfish::Koral::Query::Builder;
use strict;
use warnings;
use Krawfish::Util::Constants qw/:PREFIX/;
use Krawfish::Koral::Query::Term;
use Krawfish::Koral::Query::Token;
use Krawfish::Koral::Query::Span;
use Krawfish::Koral::Query::Sequence;
use Krawfish::Koral::Query::Repetition;
use Krawfish::Koral::Query::TermGroup;
use Krawfish::Koral::Query::Extension;
use Krawfish::Koral::Query::Exclusion;
use Krawfish::Koral::Query::Unique;
use Krawfish::Koral::Query::Class;
use Krawfish::Koral::Query::Constraints;
use Krawfish::Koral::Query::Length;
use Krawfish::Koral::Query::Nowhere;
use Krawfish::Koral::Query::Or;
use Krawfish::Koral::Query::Filter;
use Krawfish::Koral::Query::Match;
# TODO: Not all constraints need to be wrapped
use Krawfish::Koral::Query::Constraint::Position;
use Krawfish::Koral::Query::Constraint::ClassDistance;
use Krawfish::Koral::Query::Constraint::NotBetween;
use Krawfish::Koral::Query::Constraint::InBetween;
use Krawfish::Koral::Corpus::Builder;
use Scalar::Util qw/blessed/;
use constant DOC_IDENTIFIER => 'id';
sub new {
my $class = shift;
my $text_span = shift // 'base/s=t';
bless [$text_span], $class;
};
#########################
# KoralQuery constructs #
#########################
# Sequence construct
sub seq {
shift;
return Krawfish::Koral::Query::Sequence->new(@_);
};
sub repeat {
shift;
return Krawfish::Koral::Query::Repetition->new(@_);
};
# Token construct
# Should probably be like:
# ->token('Der') or
# ->token(->term_or('Der', 'Die', 'Das'))
sub token {
shift;
Krawfish::Koral::Query::Token->new(@_);
};
sub term {
shift;
my $term = shift;
return Krawfish::Koral::Query::Term->new(TOKEN_PREF . $term);
};
sub term_neg {
shift;
Krawfish::Koral::Query::Term->new(@_)->match('!=');
};
sub term_re {
shift;
Krawfish::Koral::Query::Term->new(@_)->match('~');
};
sub bool_and {
shift;
Krawfish::Koral::Query::TermGroup->new('and' => @_);
};
sub bool_and_not {
shift;
my ($pos, $neg) = @_;
Krawfish::Koral::Query::Exclusion->new(['matches'], $pos, $neg);
};
sub bool_or {
my $self = shift;
my $first_type = blessed $_[0] ? $_[0]->type : 'term';
my $second_type = blessed $_[1] ? $_[1]->type : 'term';
if (
($first_type eq 'term' || $first_type eq 'termGroup') &&
($second_type eq 'term' || $second_type eq 'termGroup')
) {
return Krawfish::Koral::Query::TermGroup->new('or' => @_);
};
return Krawfish::Koral::Query::Or->new(@_);
};
# Span construct
sub span {
shift;
Krawfish::Koral::Query::Span->new(@_);
};
# Create an in-text construct
sub in_text {
my $self = shift;
return $self->position(
['endsWith', 'isAround', 'startsWith', 'matches'],
$self->span($self->[0]),
shift
);
};
# Position construct
sub position {
my $self = shift;
my $frames = shift;
return $self->constraints(
[$self->c_position(@$frames)],
@_
);
};
# Position construct
sub exclusion {
shift;
Krawfish::Koral::Query::Exclusion->new(@_);
};
# Create reference query
sub reference {
shift;
Krawfish::Koral::Query::Reference->new(shift);
};
sub constraints {
shift;
Krawfish::Koral::Query::Constraints->new(@_);
};
sub c_position {
shift;
Krawfish::Koral::Query::Constraint::Position->new(@_);
};
sub c_class_distance {
shift;
Krawfish::Koral::Query::Constraint::ClassDistance->new(@_);
};
sub c_not_between {
shift;
Krawfish::Koral::Query::Constraint::NotBetween->new(@_);
};
sub c_in_between {
shift;
Krawfish::Koral::Query::Constraint::InBetween->new(@_);
};
# Make all positions be in order
sub c_in_order {
shift;
Krawfish::Koral::Query::Constraint::Position->new(
qw/precedesDirectly precedes endsWith isAround overlapsLeft alignsLeft matches/
);
};
sub length {
shift;
Krawfish::Koral::Query::Length->new(@_);
};
sub class {
shift;
Krawfish::Koral::Query::Class->new(@_);
};
# Extension to the left
sub ext_left {
shift;
Krawfish::Koral::Query::Extension->new(1, @_);
};
sub ext_right {
shift;
Krawfish::Koral::Query::Extension->new(0, @_);
};
# Matches anywhere
sub anywhere {
Krawfish::Koral::Query::Token->new;
};
# Null element - only for plan testing purposes
sub null {
Krawfish::Koral::Query::Term->new;
};
# No match
sub nowhere {
Krawfish::Koral::Query::Nowhere->new;
};
# Unique results
sub unique {
shift;
Krawfish::Koral::Query::Unique->new(@_);
};
# Filter a query with a corpus
sub filter_by {
shift;
Krawfish::Koral::Query::Filter->new(@_);
};
# Find exactly one single match
sub match {
my $self = shift;
my ($doc_id, $start, $end) = @_;
my $cb = Krawfish::Koral::Corpus::Builder->new;
Krawfish::Koral::Query::Match->new(
$cb->string(DOC_IDENTIFIER)->eq($doc_id),
$start,
$end
);
};
1;