prepare_filter() works as of early testing
authorLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Wed, 21 Mar 2012 14:32:11 +0000 (10:32 -0400)
committerLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Wed, 21 Mar 2012 16:16:05 +0000 (12:16 -0400)
Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Open-ILS/scratch-recur2.pl [new file with mode: 0644]
Open-ILS/src/perlmods/lib/OpenILS/Application/Fielder.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Flattener.pm

diff --git a/Open-ILS/scratch-recur2.pl b/Open-ILS/scratch-recur2.pl
new file mode 100644 (file)
index 0000000..a751afa
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use Data::Dumper;
+
+my $one = {
+    -and => [
+        {foo => "bar"},
+        {baz => {">=" => 3}}
+    ]
+};
+
+my $two = {
+    "xact_start" => {">" => "today"},
+    "circ_lib" => "BR1"
+};
+
+my $three = {
+    -not => [
+        {abc => {between => [1,32]}},
+        {def => {">=" => 1}},
+        {"ghi" => [1,2,3,4], "jkl" => 5}
+    ]
+};
+
+sub newkey {
+    my ($key) = @_;
+
+    return ("+sometable", "XXX$key");
+}
+
+sub expand_key {
+    my ($o, $key) = @_;
+
+    my ($table, $column) = newkey($key);
+
+    $o->{$table} ||= {};
+
+    $o->{$table}{$column} = $o->{$key};
+    delete $o->{$key};
+
+    return $o->{$table}{$column};
+}
+
+sub recursively_mark_column_names {
+    my ($o, $state) = @_;
+
+    $state ||= {};
+
+    if (ref $o eq 'HASH') {
+        foreach my $key (keys %$o) {
+            if (not $state->{in_expr} and $key =~ /^[a-z]/) {
+                $state->{in_expr} = 1;
+
+                print "attempting replacement of $key\n";
+                my $deeper = expand_key($o, $key);
+
+                recursively_mark_column_names($deeper, $state);
+
+                $state->{in_expr} = 0;
+            } else {
+                recursively_mark_column_names($o->{$key}, $state);
+            }
+        }
+    } elsif (ref $o eq 'ARRAY') {
+        recursively_mark_column_names($_, $state) foreach @$o;
+    } # else scalar, nothing to do?
+}
+
+recursively_mark_column_names($one);
+recursively_mark_column_names($two);
+recursively_mark_column_names($three);
+
+print Dumper($one, $two, $three), "\n";
index 2cfc979..486ad78 100644 (file)
@@ -167,27 +167,29 @@ sub flattened_search {
     # filter.
     my $filter = OpenILS::Application::Flattener::prepare_filter($map, $where);
 
-    # Process the supplied sort/limit/offset clause and use it to finish the
-    # jffolo.
-    $jffolo = OpenILS::Application::Flattener::finish_jffolo(
-        $map, $jffolo, $slo
-    );
-
-    # Reach out and touch some service.
-    my $pcrud = create OpenSRF::AppSession("open-ils.pcrud");
-    my $req = $pcrud->request(
-        "open-ils.pcrud.search.$hint", $auth, $filter, $jffolo
-    );
-
-    # Stream back flattened results.
-    while (my $resp = $req->recv(timeout => 60)) {
-        $conn->respond(
-            OpenILS::Application::Flattener::process_result($map, $resp)
-        );
-    }
-
-    # Clean up.
-    $pcrud->kill_me;
+    return [$filter, $jffolo];
+#    # Process the supplied sort/limit/offset clause and use it to finish the
+#    # jffolo.
+#    $jffolo = OpenILS::Application::Flattener::finish_jffolo(
+#        $map, $jffolo, $slo
+#    );
+
+    # Reach out and touch pcrud (could be cstore, if we wanted to offer
+    # this as a private service).
+#    my $pcrud = create OpenSRF::AppSession("open-ils.pcrud");
+#    my $req = $pcrud->request(
+#        "open-ils.pcrud.search.$hint", $auth, $filter, $jffolo
+#    );
+#
+#    # Stream back flattened results.
+#    while (my $resp = $req->recv(timeout => 60)) {
+#        $conn->respond(
+#            OpenILS::Application::Flattener::process_result($map, $resp)
+#        );
+#    }
+#
+#    # Clean up.
+#    $pcrud->kill_me;
 
     return;
 }
index c984ab4..4da71d1 100644 (file)
@@ -1,7 +1,7 @@
 package OpenILS::Application::Flattener;
 
 # This package is not meant to be registered as a stand-alone OpenSRF
-# application, but to be mixed into other services
+# application, but to be used by high level methods in other services.
 
 use base qw/OpenILS::Application/;
 
@@ -11,36 +11,19 @@ use warnings;
 use OpenSRF::EX qw/:try/;
 use OpenSRF::Utils::Logger qw/:logger/;
 use OpenILS::Utils::CStoreEditor q/:funcs/;
-
-
-sub _fm_class_by_hint {
-    my ($hint) = @_;
-
-    my ($class) = grep {
-        Fieldmapper->publish_fieldmapper->{$_}{hint} eq $hint
-    } keys %{ Fieldmapper->publish_fieldmapper };
-
-    return $class;
-
-}
-
-sub _fm_identity_from_class {
-    my ($class) = @_;
-
-    return Fieldmapper->publish_fieldmapper->{$class}{identity};
-}
+use OpenSRF::Utils::JSON;
 
 sub _fm_link_from_class {
-    my ($class, $piece) = @_;
+    my ($class, $field) = @_;
 
-    return Fieldmapper->publish_fieldmapper->{$class}{links}{$piece};
+    return Fieldmapper->publish_fieldmapper->{$class}{links}{$field};
 }
 
 sub _flattened_search_single_flesh_wad {
     my ($hint, $path)  = @_;
 
     $path = [ @$path ]; # clone for processing here
-    my $class = _fm_class_by_hint($hint);
+    my $class = OpenSRF::Utils::JSON->lookup_class($hint);
 
     my $flesh_depth = 0;
     my $flesh_fields = {};
@@ -56,7 +39,7 @@ sub _flattened_search_single_flesh_wad {
             $flesh_fields->{$hint} ||= [];
             push @{ $flesh_fields->{$hint} }, $piece;
             $hint = $link->{class};
-            $class = _fm_class_by_hint($hint);
+            $class = OpenSRF::Utils::JSON->lookup_class($hint);
             $flesh_depth++;
         } else {
             throw OpenSRF::EX::ERROR("no link $piece on $class");
@@ -74,8 +57,8 @@ sub _flattened_search_single_flesh_wad {
 sub _flattened_search_single_join_clause {
     my ($column_name, $hint, $path)  = @_;
 
-    my $class = _fm_class_by_hint($hint);
-    my $last_ident = _fm_identity_from_class($class);
+    my $class = OpenSRF::Utils::JSON->lookup_class($hint);
+    my $last_ident = $class->Identity;
 
     $path = [ @$path ]; # clone for processing here
 
@@ -92,7 +75,7 @@ sub _flattened_search_single_join_clause {
         my $link = _fm_link_from_class($class, $piece);
         if ($link) {
             $hint = $link->{class};
-            $class = _fm_class_by_hint($hint);
+            $class = OpenSRF::Utils::JSON->lookup_class($hint);
 
             my $reltype = $link->{reltype};
             my $field = $link->{key};
@@ -129,7 +112,7 @@ sub _flattened_search_single_join_clause {
                 $core_join->{$alias} = $new_join;
             }
 
-            $last_ident = _fm_identity_from_class($class);
+            $last_ident = $class->Identity;
             $last_join = $new_join;
         } else {
             throw new OpenSRF::EX::ERROR("no link '$piece' on $class");
@@ -201,6 +184,62 @@ sub _flattened_search_merge_join_clause {
     %$old = ( %$old, %$new );
 }
 
+sub _flattened_search_expand_filter_column {
+    my ($o, $key, $map) = @_;
+
+    if ($map->{$key}) {
+        my $table = $map->{$key}{last_join_alias};
+        my $column = $map->{$key}{path}[-1];
+
+        if ($table) {
+            $o->{$table} ||= {};
+
+            $o->{$table}{$column} = $o->{$key};
+            delete $o->{$key};
+
+            return $o->{$table}{$column};
+        } else {    # field must be on core class
+            $o->{$column} = $o->{$key};
+            delete $o->{$key};
+            return $o->{$column};
+        }
+    } else {
+        return $o->{$key};
+    }
+}
+
+sub _flattened_search_recursively_apply_map_to_filter {
+    my ($o, $map, $state) = @_;
+
+    $state ||= {};
+
+    if (ref $o eq 'HASH') {
+        foreach my $key (keys %$o) {
+            if (not $state->{in_expr} and $key =~ /^[a-z]/) {
+                $state->{in_expr} = 1;
+
+                my $deeper = _flattened_search_expand_filter_column(
+                    $o, $key, $map
+                );
+
+                _flattened_search_recursively_apply_map_to_filter(
+                    $deeper, $map, $state
+                );
+
+                $state->{in_expr} = 0;
+            } else {
+                _flattened_search_recursively_apply_map_to_filter(
+                    $o->{$key}, $map, $state
+                );
+            }
+        }
+    } elsif (ref $o eq 'ARRAY') {
+        _flattened_search_recursively_apply_map_to_filter(
+            $_, $map, $state
+        ) foreach @$o;
+    } # else scalar, nothing to do?
+}
+
 # returns a normalized version of the map, and the jffolo (see below)
 sub process_map {
     my ($hint, $map) = @_;
@@ -241,17 +280,11 @@ sub process_map {
 sub prepare_filter {
     my ($map, $where) = @_;
 
-    my $filter = {};
+    my $filter = {%$where};
 
-    # XXX find scratch-recur.pl and do something like that.
-#    foreach my $key (keys(%$where)) {
-#        next unless exists $map->{$key};
-#
-#        my $field = $map->{$key}{path}[-1];
-#        my $last_join_alias = $map->{$key}{last_join_alias};
-#
-#
-#    }
+    _flattened_search_recursively_apply_map_to_filter($filter, $map);
+
+    return $filter;
 }
 
 1;