Class: Jinx::MergeVisitor

Inherits:
MatchVisitor show all
Defined in:
lib/jinx/resource/merge_visitor.rb

Overview

A MergeVisitor merges a domain object’s visitable attributes transitive closure into a target.

Direct Known Subclasses

CopyVisitor

Constant Summary

Constants inherited from MatchVisitor

Jinx::MatchVisitor::DEF_MATCHER

Instance Attribute Summary

Attributes inherited from MatchVisitor

#matches

Attributes inherited from Visitor

#lineage, #options, #visited

Instance Method Summary collapse

Methods inherited from MatchVisitor

#add_match, #copy_unmatched, #identifier_match, #match_for, #match_for_visited, #match_reference, #match_references, #visit_matched

Methods inherited from ReferenceVisitor

#attributes_to_visit

Methods inherited from Visitor

#clear, #current, #cyclic_nodes, #depth_first?, #filter, #from, #node_children, #root, #sync, #to_enum, #visit_children, #visit_node_and_children, #visit_recursive, #visit_root, #visited?

Constructor Details

#initialize(opts = nil) {|obj| ... } ⇒ MergeVisitor

Creates a new MergeVisitor on domain attributes. The domain attributes to visit are determined by calling the selector block given to this initializer as described in ReferenceVisitor#initialize.

Parameters:

  • opts (Hash) (defaults to: nil)

    a customizable set of options

  • opts (Symbol, {Symbol => Object}) (defaults to: nil)

    the visit options

Options Hash (opts):

  • :mergeable (Proc)

    the block which determines which attributes are merged

  • :matcher (Proc)

    the block which matches sources to targets

  • :copier (Proc)

    the block which copies an unmatched source

Yields:

  • (obj)

    returns the AttributeEnumerator of attributes to visit next from the current domain object

Yield Parameters:

  • source (Resource)

    the matched source object



16
17
18
19
20
21
22
23
24
25
# File 'lib/jinx/resource/merge_visitor.rb', line 16

def initialize(opts=nil, &selector)
  opts = Options.to_hash(opts)
  # Merge is depth-first, since the source references must be matched, and created if necessary,
  # before they can be merged into the target.
  opts[:depth_first] = true
  @mergeable = opts.delete(:mergeable) || selector
  # each mergeable attribute is matchable
  opts[:matchable] = @mergeable unless @mergeable == selector
  super
end

Instance Method Details

#merge(source, target) ⇒ Resource (private)

Merges the given source object into the target object.

Parameters:

  • source (Resource)

    the domain object to merge from

  • target (Resource)

    the domain object to merge into

Returns:



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/jinx/resource/merge_visitor.rb', line 52

def merge(source, target)
  # trivial case
  return target if source.equal?(target)
  # the domain attributes to merge
  mas = @mergeable.call(source)
  unless mas.empty? then
    logger.debug { "Merging #{source.qp} #{mas.to_series} into #{target.qp}..." }
  end
  # merge the non-domain attributes
  target.merge_attributes(source)
  # merge the source domain attributes into the target
  target.merge_attributes(source, mas, @matches, &@filter)
end

#visit(source, target) {|target, source| ... } ⇒ Object

Visits the source and target reference graphs and recursively merges each matching source reference into its corresponding target reference.

If a block is given to this method, then the block is called on each matched (source, target) pair.

Parameters:

  • source (Resource)

    the domain object to merge from

  • target (Resource)

    the domain object to merge into

Yields:

  • (target, source)

    the optional block to call on the visited source domain object and its matching target

Yield Parameters:

  • target (Resource)

    the domain object which matches the visited source

  • source (Resource)

    the visited source domain object



38
39
40
41
42
43
# File 'lib/jinx/resource/merge_visitor.rb', line 38

def visit(source, target)
  super(source, target) do |src, tgt|
     merge(src, tgt)
     block_given? ? yield(src, tgt) : tgt
  end
end