koralify merging query on node levels

Change-Id: I9b2998ffdf1219be6f6c0cfbaa81da4104e9aeb0
diff --git a/lib/Krawfish/Koral/Compile/Limit.pm b/lib/Krawfish/Koral/Compile/Limit.pm
index 51bcf11..f47d341 100644
--- a/lib/Krawfish/Koral/Compile/Limit.pm
+++ b/lib/Krawfish/Koral/Compile/Limit.pm
@@ -14,15 +14,19 @@
 };
 
 
+# Items per page
 sub items_per_page {
   $_[0]->{items_per_page};
 };
 
+
+# Start index
 sub start_index {
   $_[0]->{start_index};
 };
 
 
+# Get query type
 sub type {
   'limit';
 };
@@ -57,10 +61,12 @@
 };
 
 
+# Stringification
 sub to_string {
   my $self = shift;
   return 'limit=[' . $self->start_index . '-'.
     ($self->start_index + $self->items_per_page) . ']';
 };
 
+
 1;
diff --git a/lib/Krawfish/Koral/Compile/Node.pm b/lib/Krawfish/Koral/Compile/Node.pm
new file mode 100644
index 0000000..aa4fb9e
--- /dev/null
+++ b/lib/Krawfish/Koral/Compile/Node.pm
@@ -0,0 +1,62 @@
+package Krawfish::Koral::Compile::Node;
+use Krawfish::Koral::Compile::Node::Merge;
+use Krawfish::Log;
+use strict;
+use warnings;
+
+# Koral class to join query results on node level
+
+use constant DEBUG => 1;
+
+sub new {
+  my $class = shift;
+
+  if (DEBUG) {
+    print_log('kq_node', 'Add node level merging');
+  };
+
+  # Pass top_k information
+  bless {
+    top_k => shift
+  }, $class;
+};
+
+
+# Query type
+sub type {
+  'node_merge';
+};
+
+
+# Normalize query
+sub normalize {
+  $_[0];
+};
+
+
+# Wrap query object
+sub wrap {
+  my ($self, $query) = @_;
+
+  if (DEBUG) {
+    print_log('kq_node', 'Wrap query in a node_merge query: ' . $query->to_string);
+  };
+
+  return Krawfish::Koral::Compile::Node::Merge->new(
+    $query,
+    $self->{top_k}
+  );
+};
+
+
+# Stringification
+sub to_string {
+  my $self = shift;
+  return 'node=[k=' . ($self->{top_k} // '-') . ']';
+};
+
+
+1;
+
+
+__END__
diff --git a/lib/Krawfish/Koral/Compile/Node/Merge.pm b/lib/Krawfish/Koral/Compile/Node/Merge.pm
new file mode 100644
index 0000000..2753a07
--- /dev/null
+++ b/lib/Krawfish/Koral/Compile/Node/Merge.pm
@@ -0,0 +1,94 @@
+package Krawfish::Koral::Compile::Node::Merge;
+
+# TODO:
+#   THIS IS WRONG HERE!
+
+use Krawfish::Compile::Node;
+
+# TODO:
+#   May require Node::nowhere!
+use Krawfish::Compile::Segment::Nowhere;
+use Krawfish::Log;
+use strict;
+use warnings;
+
+# TODO:
+#   This runs on the node level
+#   and is different to all other
+#   Krawfish::Koral::Compile::Node::* queries
+
+use constant DEBUG => 1;
+
+
+sub new {
+  my $class = shift;
+
+  bless {
+    query  => shift,
+    top_k  => shift,
+  }, $class;
+};
+
+
+# Query type
+sub type {
+  'node_merge';
+};
+
+
+# Identify query
+sub identify {
+  my ($self, $dict) = @_;
+  $self->{query} = $self->{query}->identify($dict);
+  return $self;
+};
+
+
+# Optimize query to segments
+sub optimize {
+  my ($self, $segments) = @_;
+
+  # Accept a single segment as well
+  $segments = ref $segments ne 'ARRAY' ? [$segments] : $segments;
+
+  if (DEBUG) {
+    print_log(
+      'kq_n_merge',
+      'Optimize query on node level'
+      );
+  };
+
+  # TODO:
+  #   Optimize all segments here!
+
+  # Create new node query
+  my $query = Krawfish::Compile::Node->new(
+    query => $self->{query},
+    top_k => $self->{top_k},
+    segments => $segments
+  );
+
+  if ($query->max_freq == 0) {
+    return Krawfish::Compile::Segment::Nowhere->new;
+  };
+
+  return $query;
+};
+
+
+
+# Stringification
+sub to_string {
+  my ($self, $id) = @_;
+
+  my $str = 'node(';
+
+  if ($self->{top_k}) {
+    $str .= 'k=' . $self->{top_k};
+  };
+
+  return $str . ':' . $self->{query}->to_string($id) . ')';
+};
+
+
+1;