+use strict;
+use warnings;
+
package QueryParser;
+use OpenSRF::Utils::JSON;
our %parser_config = (
QueryParser => {
filters => [],
my $func = shift;
my $params = shift || [];
- return $func if (grep { $_ eq $func } @{$pkg->query_normalizers->{$class}->{$field}});
+ # do not add if function AND params are identical to existing member
+ return $func if (grep {
+ $_->{function} eq $func and
+ OpenSRF::Utils::JSON->perl2JSON($_->{params}) eq OpenSRF::Utils::JSON->perl2JSON($params)
+ } @{$pkg->query_normalizers->{$class}->{$field}});
push(@{$pkg->query_normalizers->{$class}->{$field}}, { function => $func, params => $params });
return $parser_config{$pkg}{normalizers};
}
+sub add_filter_normalizer {
+ my $pkg = shift;
+ $pkg = ref($pkg) || $pkg;
+ my $filter = shift;
+ my $func = shift;
+ my $params = shift || [];
+
+ return $func if (grep { $_ eq $func } @{$pkg->filter_normalizers->{$filter}});
+
+ push(@{$pkg->filter_normalizers->{$filter}}, { function => $func, params => $params });
+
+ return $func;
+}
+
+sub filter_normalizers {
+ my $pkg = shift;
+ $pkg = ref($pkg) || $pkg;
+
+ my $filter = shift;
+
+ $parser_config{$pkg}{filter_normalizers} ||= {};
+ if ($filter) {
+ $parser_config{$pkg}{filter_normalizers}{$filter} ||= [];
+ return $parser_config{$pkg}{filter_normalizers}{$filter};
+ }
+
+ return $parser_config{$pkg}{filter_normalizers};
+}
+
sub default_search_class {
my $pkg = shift;
$pkg = ref($pkg) || $pkg;
# Build the filter and modifier uber-regexps
- my $facet_re = '^\s*((?:' . join( '|', @{$pkg->facet_classes}) . ')(?:\|\w+)*)\[(.+?)\]';
+ my $facet_re = '^\s*(-?)((?:' . join( '|', @{$pkg->facet_classes}) . ')(?:\|\w+)*)\[(.+?)\]';
warn " Facet RE: $facet_re\n" if $self->debug;
- my $filter_re = '^\s*(' . join( '|', @{$pkg->filters}) . ')\(([^()]+)\)';
- my $filter_as_class_re = '^\s*(' . join( '|', @{$pkg->filters}) . '):\s*(\S+)';
+ my $filter_re = '^\s*(-?)(' . join( '|', @{$pkg->filters}) . ')\(([^()]+)\)';
+ my $filter_as_class_re = '^\s*(-?)(' . join( '|', @{$pkg->filters}) . '):\s*(\S+)';
my $modifier_re = '^\s*'.$modifier_tag_re.'(' . join( '|', @{$pkg->modifiers}) . ')\b';
my $modifier_as_class_re = '^\s*(' . join( '|', @{$pkg->modifiers}) . '):\s*(\S+)';
$last_type = '';
} elsif ($self->filter_count && /$filter_re/) { # found a filter
- warn "Encountered search filter: $1 set to $2\n" if $self->debug;
+ warn "Encountered search filter: $1$2 set to $3\n" if $self->debug;
+ my $negate = ($1 eq '-') ? 1 : 0;
$_ = $';
- $struct->new_filter( $1 => [ split '[, ]+', $2 ] );
+ $struct->new_filter( $2 => [ split '[,]+', $3 ], $negate );
$last_type = '';
} elsif ($self->filter_count && /$filter_as_class_re/) { # found a filter
- warn "Encountered search filter: $1 set to $2\n" if $self->debug;
+ warn "Encountered search filter: $1$2 set to $3\n" if $self->debug;
+ my $negate = ($1 eq '-') ? 1 : 0;
$_ = $';
- $struct->new_filter( $1 => [ split '[, ]+', $2 ] );
+ $struct->new_filter( $2 => [ split '[,]+', $3 ], $negate );
$last_type = '';
} elsif ($self->modifier_count && /$modifier_re/) { # found a modifier
$last_type = 'OR';
} elsif ($self->facet_class_count && /$facet_re/) { # changing current class
- warn "Encountered facet: $1 => $2\n" if $self->debug;
+ warn "Encountered facet: $1$2 => $3\n" if $self->debug;
- my $facet = $1;
- my $facet_value = [ split '\s*#\s*', $2 ];
- $struct->new_facet( $facet => $facet_value );
+ my $negate = ($1 eq '-') ? 1 : 0;
+ my $facet = $2;
+ my $facet_value = [ split '\s*#\s*', $3 ];
+ $struct->new_facet( $facet => $facet_value, $negate );
$_ = $';
$last_type = '';
my $pkg = ref($self) || $self;
my $name = shift;
my $args = shift;
+ my $negate = shift;
- my $node = do{$pkg.'::facet'}->new( plan => $self, name => $name, 'values' => $args );
+ my $node = do{$pkg.'::facet'}->new( plan => $self, name => $name, 'values' => $args, negate => $negate );
$self->add_node( $node );
return $node;
my $pkg = ref($self) || $self;
my $name = shift;
my $args = shift;
+ my $negate = shift;
- my $node = do{$pkg.'::filter'}->new( plan => $self, name => $name, args => $args );
+ my $node = do{$pkg.'::filter'}->new( plan => $self, name => $name, args => $args, negate => $negate );
$self->add_filter( $node );
return $node;
return $self->{name};
}
+sub negate {
+ my $self = shift;
+ return $self->{negate};
+}
+
sub args {
my $self = shift;
return $self->{args};
return $self->{name};
}
+sub negate {
+ my $self = shift;
+ return $self->{negate};
+}
+
sub values {
my $self = shift;
return $self->{'values'};