Class: Canon::TreeDiff::OperationConverter

Inherits:
Object
  • Object
show all
Defined in:
lib/canon/tree_diff/operation_converter.rb

Overview

Converts TreeDiff Operations to DiffNodes for integration with Canon’s existing diff pipeline.

This class bridges the semantic tree diff system with Canon’s DOM-based diff architecture by mapping operations to match dimensions and creating DiffNode objects that can be processed by the standard diff formatter.

Examples:

Convert operations to diff nodes

converter = OperationConverter.new(format: :xml, match_options: opts)
diff_nodes = converter.convert(operations)

Constant Summary collapse

OPERATION_TO_DIMENSION =

Mapping from operation types to match dimensions

{
  insert: :element_structure,
  delete: :element_structure,
  update: :text_content, # Default, refined based on what changed
  move: :element_position,
  merge: :element_structure,
  split: :element_structure,
  upgrade: :element_hierarchy,
  downgrade: :element_hierarchy,
}.freeze
METADATA_ELEMENTS =

Metadata/presentation elements that should be treated as informative These elements don’t affect semantic equivalence

%w[
  semx fmt-concept fmt-name fmt-title fmt-xref fmt-eref
  fmt-termref fmt-element-name fmt-link autonum
  meta link base title style script
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(format:, match_options: {}) ⇒ OperationConverter

Initialize converter

Parameters:

  • format (Symbol)

    Document format (:xml, :html, :json, :yaml)

  • match_options (Hash) (defaults to: {})

    Match options for determining normative/informative



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/canon/tree_diff/operation_converter.rb', line 51

def initialize(format:, match_options: {})
  @format = format

  # Resolve match options using format-specific module
  match_opts_hash = case format
                    when :xml, :html, :html4, :html5
                      Canon::Comparison::MatchOptions::Xml.resolve(
                        format: format,
                        match: match_options,
                      )
                    when :json
                      Canon::Comparison::MatchOptions::Json.resolve(
                        format: format,
                        match: match_options,
                      )
                    when :yaml
                      Canon::Comparison::MatchOptions::Yaml.resolve(
                        format: format,
                        match: match_options,
                      )
                    else
                      raise ArgumentError, "Unknown format: #{format}"
                    end

  # Wrap in ResolvedMatchOptions
  @match_options = Canon::Comparison::ResolvedMatchOptions.new(
    match_opts_hash,
    format: format,
  )
end

Instance Attribute Details

#formatObject (readonly)

Returns the value of attribute format.



45
46
47
# File 'lib/canon/tree_diff/operation_converter.rb', line 45

def format
  @format
end

#match_optionsObject (readonly)

Returns the value of attribute match_options.



45
46
47
# File 'lib/canon/tree_diff/operation_converter.rb', line 45

def match_options
  @match_options
end

Instance Method Details

#convert(operations) ⇒ Array<DiffNode>

Convert array of Operations to array of DiffNodes

Parameters:

  • operations (Array<Operation>)

    Operations to convert

Returns:

  • (Array<DiffNode>)

    Converted diff nodes



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/canon/tree_diff/operation_converter.rb', line 86

def convert(operations)
  diff_nodes = operations.flat_map do |operation|
    convert_operation(operation)
  end

  # Post-process to detect attribute-order-only differences
  OperationConverterHelpers::PostProcessor.detect_attribute_order_diffs(
    diff_nodes,
    ->(dimension) { determine_normative(dimension) },
  )
end

#convert_operation(operation) ⇒ DiffNode

Convert a single Operation to a DiffNode

Parameters:

  • operation (Operation)

    Operation to convert

Returns:

  • (DiffNode)

    Converted diff node



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/canon/tree_diff/operation_converter.rb', line 104

def convert_operation(operation)
  case operation.type
  when :insert
    convert_insert(operation)
  when :delete
    convert_delete(operation)
  when :update
    convert_update(operation)
  when :move
    convert_move(operation)
  when :merge
    convert_merge(operation)
  when :split
    convert_split(operation)
  when :upgrade
    convert_upgrade(operation)
  when :downgrade
    convert_downgrade(operation)
  else
    raise ArgumentError, "Unknown operation type: #{operation.type}"
  end
end