Class: CSDL::Processor

Inherits:
AST::Processor
  • Object
show all
Defined in:
lib/csdl/processor.rb

Overview

Processor is a class that can take a tree of AST::Node objects built with Builder and produce a valid CSDL string representation according to DataSift’s CSDL specification.

Examples:

# Generate your CSDL nodes using the Builder
root_node = CSDL::Builder.new.logical_group(:or) do
  #...
  condition("fb.content", :contains, "match this string")
  #...
end

# Process the root node and its children calling the instance method #process
CSDL::Processor.new.process(root_node)

See Also:

Instance Method Summary collapse

Instance Method Details

#on_and(node) ⇒ String

AND two or more child nodes together.

Examples:

node = s(:and,
         s(:string, "foo"),
         s(:string, "bar"),
         s(:string, "baz"))
CSDL::Processor.new.process(node) # => '"foo" AND "bar" AND "baz"'

Parameters:

  • node (AST::Node)

    The :and node to be processed.

Returns:

  • (String)

    Processed child nodes ANDed together into a raw CSDL string representation.

Raises:



39
40
41
# File 'lib/csdl/processor.rb', line 39

def on_and(node)
  logically_join_nodes("AND", node.children)
end

#on_argument(node) ⇒ String

TODO:

Raise if the node doesn’t have any children.

Process the first child node as the “argument” in a condition node tree (target + operator + argument).

Examples:

node = s(:argument,
         s(:string, "foo"))
CSDL::Processor.new.process(node) # => '"foo"'

Parameters:

  • node (AST::Node)

    The :argument node to be processed.

Returns:

  • (String)

    The first child node, processed by its node type into a raw CSDL string representation.



56
57
58
# File 'lib/csdl/processor.rb', line 56

def on_argument(node)
  process(node.children.first)
end

#on_condition(node) ⇒ String

TODO:

Raise when we don’t have a target node.

TODO:

Raise when we don’t have a operator node.

TODO:

Raise when we don’t have a argument node, assuming the operator is binary.

TODO:

Raise if the argument node’s child is not of a valid node type for the given operator.

Process :condition node and it’s expected children :target, :operator, and :argument nodes.

Examples:

node = s(:condition,
          s(:target, "fb.content"),
          s(:operator, :contains_any),
          s(:argument,
            s(:string, "foo")))
CSDL::Processor.new.process(node) # => 'fb.content contains_any "foo"'

Parameters:

  • node (AST::Node)

    The :condition node to be processed.

Returns:

  • (String)

    The child nodes :target, :operator, and :argument, processed and joined.



79
80
81
82
83
84
# File 'lib/csdl/processor.rb', line 79

def on_condition(node)
  target   = node.children.find { |child| child.type == :target }
  operator = node.children.find { |child| child.type == :operator }
  argument = node.children.find { |child| child.type == :argument }
  process_all([ target, operator, argument ].compact).join(" ")
end

#on_logical_group(node) ⇒ String

Wrap all processed child nodes in parentheses.

Examples:

node = s(:logical_group,
         s(:or,
          s(:string, "foo"),
          s(:string, "bar"),
          s(:string, "baz")))
CSDL::Processor.new.process(node) # => '("foo" OR "bar" OR "baz")'

Parameters:

  • node (AST::Node)

    The :logical_group node to be processed.

Returns:

  • (String)

    All child nodes processed by their node types into a raw CSDL string representation, wrapped in parentheses.



100
101
102
# File 'lib/csdl/processor.rb', line 100

def on_logical_group(node)
  "(" + process_all(node.children).join(" ") + ")"
end

#on_not(node) ⇒ String

TODO:

Raise when we don’t have a target node.

TODO:

Raise when we don’t have a operator node.

TODO:

Raise when we don’t have a argument node, assuming the operator is binary.

TODO:

Raise if the argument node’s child is not of a valid node type for the given operator.

TODO:

Support negating logical groupings.

Process :not node as a :condition node, prepending the logical operator NOT to the processed :condition node.

Examples:

node = s(:not,
          s(:target, "fb.content"),
          s(:operator, :contains_any),
          s(:argument,
            s(:string, "foo")))
CSDL::Processor.new.process(node) # => 'NOT fb.content contains_any "foo"'

Parameters:

  • node (AST::Node)

    The :not node to be processed.

Returns:

  • (String)

    The child nodes :target, :operator, and :argument, processed and joined.



124
125
126
# File 'lib/csdl/processor.rb', line 124

def on_not(node)
  "NOT " + process(node.updated(:condition))
end

#on_operator(node) ⇒ String

Process :operator nodes, ensuring the the given terminator value is a valid operator.

Examples:

node = s(:operator, :contains)
CSDL::Processor.new.process(node) # => 'contains'

Parameters:

  • node (AST::Node)

    The :operator node to be processed.

Returns:

  • (String)

    The first child, stringified.

Raises:



140
141
142
143
144
145
146
# File 'lib/csdl/processor.rb', line 140

def on_operator(node)
  operator = node.children.first.to_s
  unless ::CSDL.operator?(operator)
    fail ::CSDL::UnknownOperatorError, "Operator #{operator} is unknown"
  end
  operator
end

#on_or(node) ⇒ String

OR two or more child nodes together.

Examples:

node = s(:or,
          s(:string, "foo"),
          s(:string, "bar"),
          s(:string, "baz"))
CSDL::Processor.new.process(node) # => '"foo" OR "bar" OR "baz"'

Parameters:

  • node (AST::Node)

    The :or node to be processed.

Returns:

  • (String)

    Processed child nodes OR’d together into a raw CSDL string representation.

Raises:



163
164
165
# File 'lib/csdl/processor.rb', line 163

def on_or(node)
  logically_join_nodes("OR", node.children)
end

#on_raw(node) ⇒ String

TODO:

Raise if the node doesn’t have any children.

Process :raw nodes.

Examples:

node = s(:raw, %q{fb.content contains_any "foo" OR fb.parent.content contains_any "foo"})
CSDL::Processor.new.process(node) # => 'fb.content contains_any "foo" OR fb.parent.content contains_any "foo"'

Parameters:

  • node (AST::Node)

    The :raw node to be processed.

Returns:

  • (String)

    The first child node as a string.



179
180
181
# File 'lib/csdl/processor.rb', line 179

def on_raw(node)
  node.children.first.to_s
end

#on_root(node) ⇒ Object

Process all child nodes. Useful for grouping child nodes without any syntax introduction.

See Also:

  • InteractionFilterProcessor#_return
  • InteractionFilterProcessor#tag
  • InteractionFilterProcessor#tag_tree


189
190
191
# File 'lib/csdl/processor.rb', line 189

def on_root(node)
  process_all(node.children).join(" ")
end

#on_string(node) ⇒ String

TODO:

Raise if the node doesn’t have any children.

Wrap the stringified terminal value in quotes.

Examples:

node = s(:string, "foo")
CSDL::Processor.new.process(node) # => '"foo"'

Parameters:

  • node (AST::Node)

    The :string node to be processed.

Returns:

  • (String)

    The first child node, processed by its node type into a raw CSDL string representation.



205
206
207
# File 'lib/csdl/processor.rb', line 205

def on_string(node)
  '"' + node.children.first.to_s.gsub(/"/, '\"') + '"'
end

#on_target(node) ⇒ String

Process :target nodes, ensuring the the given terminator value is a valid operator.

Examples:

node = s(:target, "fb.content")
CSDL::Processor.new.process(node) # => 'fb.content'

Parameters:

  • node (AST::Node)

    The :target node to be processed.

Returns:

  • (String)

    The first child, stringified.

Raises:

See Also:



223
224
225
226
227
# File 'lib/csdl/processor.rb', line 223

def on_target(node)
  target = node.children.first.to_s
  validate_target!(target)
  target
end

#validate_target!(target_key) ⇒ void

This method returns an undefined value.

Raises an UnknownTargetError if the target isn’t a valid CSDL target. Useful for implenting a child processor that can ensure the target is known and valid for a given use-case (e.g. Interaction Filters vs Query Filters). Generally not useful to be called directly, use CSDL.target? instead.

Examples:

CSDL::Processor.new.validate_target!("fake") # => raises UnknownTargetError

Parameters:

  • target_key (String)

    The target to validate.

Raises:



243
244
245
246
247
# File 'lib/csdl/processor.rb', line 243

def validate_target!(target_key)
  unless ::CSDL.target?(target_key)
    fail ::CSDL::UnknownTargetError, "Target '#{target_key}' is not a known target type."
  end
end