Class: YAMLTools::Combiner

Inherits:
Object
  • Object
show all
Defined in:
lib/tools/combine.rb

Instance Method Summary collapse

Instance Method Details

#combine(source, difference) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/tools/combine.rb', line 140

def combine(source, difference)
  # Load files
  sourceDocument = YAML.parse(source)
  differenceDocument = YAML.parse(difference)

  # Flatten merge keys for older ArchivesSpace files
  sourceDocument = YAMLTools.flatten_merge_keys(sourceDocument.root.children)
  differenceDocument = YAMLTools.flatten_merge_keys(differenceDocument.root.children)

  @combined = combine_levels(sourceDocument, differenceDocument)

  if (@combined.length > 0) then
    output = YAMLTools.createDocument(@combined)
  else
    output = ''
  end

  output
end

#combine_files(sourceFilePath, differenceFilePath) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/tools/combine.rb', line 126

def combine_files(sourceFilePath, differenceFilePath)
  sourceFile = File.open(sourceFilePath, "r")
  differenceFile = File.open(differenceFilePath, "r")

  begin
    output = combine(sourceFile, differenceFile)
  ensure
    sourceFile.close
    differenceFile.close
  end

  output
end

#combine_levels(s, d) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/tools/combine.rb', line 5

def combine_levels (s, d)
  level = []

  # Split into key/value pairs
  sourceChildren = s.each_slice(2).to_a
  differenceChildren = d.each_slice(2).to_a

  sourceChildren.each {|sourcePair|
    sourceKey = sourcePair[0]
    sourceValue = sourcePair[1]

    # Find difference pair
    differencePairs = differenceChildren.find_all {|i| i[0].value == sourceKey.value}

    if (differencePairs.length > 1) then
      if (sourceKey.value == "<<") then
        # Find merge key with matching alias
        differencePair = differencePairs.find {|i|
          (i[1].is_a?(Psych::Nodes::Alias) && i[1].anchor == sourceValue.anchor) ||
          (i[1].is_a?(Psych::Nodes::Sequence) && i[1].children.any? {|a| a.is_a?(Psych::Nodes::Alias) && a.anchor == sourceValue.anchor})}
      else
        # Some ArchivesSpace files have duplicate keys so use the last one
        differencePair = differencePairs.last
      end
    else
      differencePair = differencePairs.first
    end

    if (differencePair == nil) then
      # difference not found so copy node
      level << sourceKey
      level << sourceValue
    else
      differenceKey = differencePair[0]
      differenceValue = differencePair[1]

      if (differenceKey.value == '<<') then
        # If aliases or sequences of aliases then merge
        if ((sourceValue.is_a?(Psych::Nodes::Alias) || sourceValue.is_a?(Psych::Nodes::Sequence)) && (differenceValue.is_a?(Psych::Nodes::Alias) || differenceValue.is_a?(Psych::Nodes::Sequence))) then
          if (sourceValue.is_a?(Psych::Nodes::Alias) && (differenceValue.is_a?(Psych::Nodes::Sequence) && differenceValue.children.all? {|a| a.is_a?(Psych::Nodes::Alias)})) then
            # Merge aliases
            if (differenceValue.children.none? {|a| a.anchor == sourceValue.anchor}) then
              # Add alias to sequence
              differenceValue.children = differenceValue.children << sourceValue
            end

            level.insert(0, sourceKey)
            level.insert(1, differenceValue)

          elsif (differenceValue.is_a?(Psych::Nodes::Alias) && (sourceValue.is_a?(Psych::Nodes::Sequence) && sourceValue.children.all? {|a| a.is_a?(Psych::Nodes::Alias)})) then
            # Merge aliases
            if (sourceValue.children.none? {|a| a.anchor == differenceValue.anchor}) then
              # Add alias to sequence
              sourceValue.children = sourceValue.children << differenceValue
            end

            level.insert(0, sourceKey)
            level.insert(1, sourceValue)
          elsif (sourceValue.is_a?(Psych::Nodes::Sequence) && differenceValue.is_a?(Psych::Nodes::Sequence))
            newSequence = Psych::Nodes::Sequence.new(sourceValue.anchor, sourceValue.tag, sourceValue.implicit, Psych::Nodes::Sequence::FLOW)

            newSequence.children
              .concat(sourceValue.children, differenceValue.children)
              .uniq! {|a| a.anchor}

            level.insert(0, sourceKey)
            level.insert(1, newSequence)
          elsif (sourceValue.is_a?(Psych::Nodes::Alias) && differenceValue.is_a?(Psych::Nodes::Alias))
            if (sourceValue.anchor == differenceValue.anchor) then
              level.insert(0, sourceKey)
              level.insert(1, sourceValue)
            else
              newSequence = Psych::Nodes::Sequence.new(sourceValue.anchor, sourceValue.tag, sourceValue.implicit, Psych::Nodes::Sequence::FLOW)

              newSequence.children
                .concat([sourceValue, differenceValue])
                .uniq! {|a| a.anchor}

              level.insert(0, sourceKey)
              level.insert(1, newSequence)
            end
          end
        end
      elsif (differenceValue.is_a?(Psych::Nodes::Mapping)) then
        childLevel = combine_levels(sourceValue.children, differenceValue.children)

        newMapping = Psych::Nodes::Mapping.new(sourceValue.anchor, sourceValue.tag, sourceValue.implicit, sourceValue.style)

        if (childLevel.length > 0) then
          newMapping.children.push(*childLevel)
        end

        level << differenceKey
        level << newMapping
      else
        level << differenceKey
        level << differenceValue
      end
    end
  }

  # Add all difference pairs that don't exist in the source

  differenceChildren.each {|differencePair|
    differenceKey = differencePair[0]
    differenceValue = differencePair[1]

    if (sourceChildren.none? {|i| i[0].value == differenceKey.value}) then
      if (differenceKey.value == '<<') then
        level.insert(0, differenceKey)
        level.insert(1, differenceValue)
      else
        level << differenceKey
        level << differenceValue
      end
    end
  }

  level
end