Class: OM::XML::Term::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/om/xml/term.rb

Overview

Term::Builder Class Definition

When coding against Builders, remember that they rely on MethodMissing, so any time you call a method on the Builder that it doesn’t explicitly recognize, the Builder will add your method & arguments to the it’s settings and return itself.

Examples:

tb2 = OM::XML::Term::Builder.new("my_term_name").path("fooPath").attributes({:lang=>"foo"}).index_as([:searchable, :facetable]).required(true).data_type(:text)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, terminology_builder = nil) ⇒ Builder

Returns a new instance of Builder.



20
21
22
23
24
25
# File 'lib/om/xml/term.rb', line 20

def initialize(name, terminology_builder=nil)
  @name = name.to_sym
  @terminology_builder = terminology_builder
  @settings = {:required=>false, :data_type=>:string}
  @children = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

Any unknown method calls will add an entry to the settings hash and return the current object



120
121
122
123
124
125
126
# File 'lib/om/xml/term.rb', line 120

def method_missing method, *args, &block
  if args.length == 1
    args = args.first
  end
  @settings[method] = args
  return self
end

Instance Attribute Details

#childrenObject

Returns the value of attribute children.



18
19
20
# File 'lib/om/xml/term.rb', line 18

def children
  @children
end

#nameObject

Returns the value of attribute name.



18
19
20
# File 'lib/om/xml/term.rb', line 18

def name
  @name
end

#settingsObject

Returns the value of attribute settings.



18
19
20
# File 'lib/om/xml/term.rb', line 18

def settings
  @settings
end

#terminology_builderObject

Returns the value of attribute terminology_builder.



18
19
20
# File 'lib/om/xml/term.rb', line 18

def terminology_builder
  @terminology_builder
end

Instance Method Details

#add_child(child) ⇒ Object



27
28
29
# File 'lib/om/xml/term.rb', line 27

def add_child(child)
  @children[child.name] = child
end

#build(terminology = nil) ⇒ Object

Builds a new OM::XML::Term based on the Builder object’s current settings If no path has been provided, uses the Builder object’s name as the term’s path Recursively builds any children, appending the results as children of the Term that’s being built.

Parameters:



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/om/xml/term.rb', line 98

def build(terminology=nil)
  self.resolve_refs!
  if term.self.settings.has_key?(:proxy)
    term = OM::XML::NamedTermProxy.new(self.name, self.settings[:proxy], terminology, self.settings)
  else
    term = OM::XML::Term.new(self.name, {}, terminology)

    self.settings.each do |name, values|
      if term.respond_to?(name.to_s+"=")
        term.instance_variable_set("@#{name}", values)
      end
    end
    @children.each_value do |child|
      term.add_child child.build(terminology)
    end
    term.generate_xpath_queries!
  end

  return term
end

#lookup_refs(nodes_visited = []) ⇒ Object



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
# File 'lib/om/xml/term.rb', line 35

def lookup_refs(nodes_visited=[])
  result = []
  if @settings[:ref]
    # Fail if we do not have terminology builder
    if self.terminology_builder.nil?
      raise "Cannot perform lookup_ref for the #{self.name} builder.  It doesn't have a reference to any terminology builder"
    end
    target = self.terminology_builder.retrieve_term_builder(*@settings[:ref])

    # Fail on circular references and return an intelligible error message
    if nodes_visited.include?(target)
      nodes_visited << self
      nodes_visited << target
      trail = ""
      nodes_visited.each_with_index do |node, z|
        trail << node.name.inspect
        unless z == nodes_visited.length-1
          trail << " => "
        end
      end
      raise OM::XML::Terminology::CircularReferenceError, "Circular reference in Terminology: #{trail}"
    end
    result << target
    result.concat( target.lookup_refs(nodes_visited << self) )
  end
  return result
end

#resolve_refs!Object

If a :ref value has been set, looks up the target of that ref and merges the target’s settings & children with the current builder’s settings & children operates recursively, so it is possible to apply refs that in turn refer to other nodes.



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/om/xml/term.rb', line 65

def resolve_refs!
  name_of_last_ref = nil
  lookup_refs.each_with_index do |ref,z|
    @settings = two_layer_merge(@settings, ref.settings)
    @children.merge!(ref.children)
    name_of_last_ref = ref.name
  end
  if @settings[:path].nil? && !name_of_last_ref.nil?
    @settings[:path] = name_of_last_ref.to_s
  end
  @settings.delete :ref
  return self
end

#retrieve_child(child_name) ⇒ Object



31
32
33
# File 'lib/om/xml/term.rb', line 31

def retrieve_child(child_name)
  child = @children.fetch(child_name, nil)
end

#two_layer_merge(downstream_hash, upstream_hash) ⇒ Object

Returns a new Hash that merges downstream_hash with upstream_hash similar to calling upstream_hash.merge(downstream_hash) only it also merges any internal values that are themselves Hashes.



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/om/xml/term.rb', line 82

def two_layer_merge(downstream_hash, upstream_hash)
  up = upstream_hash.dup
  dn = downstream_hash.dup
  up.each_pair do |setting_name, value|
    if value.kind_of?(Hash) && downstream_hash.has_key?(setting_name)
      dn[setting_name] = value.merge(downstream_hash[setting_name])
      up.delete(setting_name)
    end
  end
  return up.merge(dn)
end