Commit 4d4170b

mo khan <mo.khan@gmail.com>
2020-01-21 18:47:15
Add an abstract visitor class
1 parent 0d7f8ac
Changed files (5)
lib/scim/kit/v2/filter/node.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'parslet'
+
+module Scim
+  module Kit
+    module V2
+      class Filter
+        # @private
+        class Node
+          def initialize(hash)
+            @hash = hash
+          end
+
+          def operator
+            self[:operator].to_sym
+          end
+
+          def attribute
+            self[:attribute].to_s
+          end
+
+          def value
+            self[:value].to_s[1..-2]
+          end
+
+          def not?
+            @hash.key?(:not)
+          end
+
+          def accept(visitor)
+            visitor.visit(self)
+          end
+
+          def left
+            self.class.new(self[:left])
+          end
+
+          def right
+            self.class.new(self[:right])
+          end
+
+          def inspect
+            @hash.inspect
+          end
+
+          private
+
+          def [](key)
+            @hash[key]
+          end
+        end
+      end
+    end
+  end
+end
lib/scim/kit/v2/filter/visitor.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'parslet'
+
+module Scim
+  module Kit
+    module V2
+      class Filter
+        # @private
+        class Visitor
+          VISITORS = {
+            and: :visit_and,
+            co: :visit_contains,
+            eq: :visit_equals,
+            ew: :visit_ends_with,
+            ge: :visit_greater_than_equals,
+            gt: :visit_greater_than,
+            le: :visit_less_than_equals,
+            lt: :visit_less_than,
+            ne: :visit_not_equals,
+            or: :visit_or,
+            pr: :visit_presence,
+            sw: :visit_starts_with
+          }.freeze
+
+          def visit(node)
+            visitor_for(node).call(node)
+          end
+
+          protected
+
+          def visitor_for(node)
+            method(VISITORS.fetch(node.operator, :visit_unknown))
+          end
+
+          def visit_and(node)
+            visit(node.left).merge(visit(node.right))
+            raise error_for(:visit_and)
+          end
+
+          def visit_or(_node)
+            raise error_for(:visit_or)
+          end
+
+          def visit_equals(_node)
+            raise error_for(:visit_equals)
+          end
+
+          def visit_not_equals(_node)
+            raise error_for(:visit_not_equals)
+          end
+
+          def visit_contains(_node)
+            raise error_for(:visit_contains)
+          end
+
+          def visit_starts_with(_node)
+            raise error_for(:visit_starts_with)
+          end
+
+          def visit_ends_with(_node)
+            raise error_for(:visit_ends_with)
+          end
+
+          def visit_greater_than(_node)
+            raise error_for(:visit_greater_than)
+          end
+
+          def visit_greater_than_equals(_node)
+            raise error_for(:visit_greater_than_equals)
+          end
+
+          def visit_less_than(_node)
+            raise error_for(:visit_less_than)
+          end
+
+          def visit_less_than_equals(_node)
+            raise error_for(:visit_less_than_equals)
+          end
+
+          def visit_presence(_node)
+            raise error_for(:visit_presence)
+          end
+
+          def visit_unknown(_node)
+            raise error_for(:visit_unknown)
+          end
+
+          private
+
+          def error_for(method)
+            ::Scim::Kit::NotImplementedError.new("#{method} is not implemented")
+          end
+        end
+      end
+    end
+  end
+end
lib/scim/kit/v2/filter.rb
@@ -126,138 +126,6 @@ module Scim
         rule(:version) { digit >> dot >> digit }
         rule(:assign) { str('=') }
 
-        # @private
-        class Node
-          def initialize(hash)
-            @hash = hash
-          end
-
-          def operator
-            self[:operator].to_sym
-          end
-
-          def attribute
-            self[:attribute].to_s
-          end
-
-          def value
-            self[:value].to_s[1..-2]
-          end
-
-          def not?
-            @hash.key?(:not)
-          end
-
-          def accept(visitor)
-            visitor.visit(self)
-          end
-
-          def left
-            self.class.new(self[:left])
-          end
-
-          def right
-            self.class.new(self[:right])
-          end
-
-          def inspect
-            @hash.inspect
-          end
-
-          private
-
-          def [](key)
-            @hash[key]
-          end
-        end
-
-        # @private
-        class Visitor
-          VISITORS = {
-            and: :visit_and,
-            co: :visit_contains,
-            eq: :visit_equals,
-            ew: :visit_ends_with,
-            ge: :visit_greater_than_equals,
-            gt: :visit_greater_than,
-            le: :visit_less_than_equals,
-            lt: :visit_less_than,
-            ne: :visit_not_equals,
-            or: :visit_or,
-            pr: :visit_presence,
-            sw: :visit_starts_with
-          }.freeze
-
-          def visit(node)
-            visitor_for(node).call(node)
-          end
-
-          protected
-
-          def visitor_for(node)
-            method(VISITORS.fetch(node.operator, :visit_unknown))
-          end
-
-          def visit_and(node)
-            visit(node.left).merge(visit(node.right))
-            raise error_for(:visit_and)
-          end
-
-          def visit_or(_node)
-            raise error_for(:visit_or)
-          end
-
-          def visit_equals(_node)
-            raise error_for(:visit_equals)
-          end
-
-          def visit_not_equals(_node)
-            raise error_for(:visit_not_equals)
-          end
-
-          def visit_contains(_node)
-            raise error_for(:visit_contains)
-          end
-
-          def visit_starts_with(_node)
-            raise error_for(:visit_starts_with)
-          end
-
-          def visit_ends_with(_node)
-            raise error_for(:visit_ends_with)
-          end
-
-          def visit_greater_than(_node)
-            raise error_for(:visit_greater_than)
-          end
-
-          def visit_greater_than_equals(_node)
-            raise error_for(:visit_greater_than_equals)
-          end
-
-          def visit_less_than(_node)
-            raise error_for(:visit_less_than)
-          end
-
-          def visit_less_than_equals(_node)
-            raise error_for(:visit_less_than_equals)
-          end
-
-          def visit_presence(_node)
-            raise error_for(:visit_presence)
-          end
-
-          def visit_unknown(_node)
-            raise error_for(:visit_unknown)
-          end
-
-          private
-
-          def error_for(method)
-            ::Scim::Kit::NotImplementedError.new("#{method} is not implemented")
-          end
-        end
-
         class << self
           def parse(filter)
             Node.new(new.parse(filter))
lib/scim/kit/v2.rb
@@ -12,6 +12,8 @@ require 'scim/kit/v2/mutability'
 require 'scim/kit/v2/resource'
 require 'scim/kit/v2/error'
 require 'scim/kit/v2/filter'
+require 'scim/kit/v2/filter/node'
+require 'scim/kit/v2/filter/visitor'
 require 'scim/kit/v2/resource_type'
 require 'scim/kit/v2/returned'
 require 'scim/kit/v2/schema'
spec/scim/kit/v2/filter_spec.rb
@@ -201,7 +201,17 @@ RSpec.describe Scim::Kit::V2::Filter do
       'title pr',
       'userName pr and not (userName eq "hello@example.com")'
     ].each do |filter|
+      let(:visitor) { Scim::Kit::V2::Filter::Visitor.new }
+
       specify { expect(subject.parse(filter)).to be_instance_of(Scim::Kit::V2::Filter::Node) }
+
+      specify do
+        node = subject.parse(filter)
+
+        expect do
+          node.accept(visitor)
+        end.to raise_error(Scim::Kit::NotImplementedError)
+      end
     end
   end
 end