Class: OM::XML::Term::Builder
- Inherits:
-
Object
- Object
- OM::XML::Term::Builder
- 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.
Instance Attribute Summary collapse
-
#children ⇒ Object
Returns the value of attribute children.
-
#name ⇒ Object
Returns the value of attribute name.
-
#settings ⇒ Object
Returns the value of attribute settings.
-
#terminology_builder ⇒ Object
Returns the value of attribute terminology_builder.
Instance Method Summary collapse
- #add_child(child) ⇒ Object
-
#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.
-
#initialize(name, terminology_builder = nil) ⇒ Builder
constructor
A new instance of Builder.
- #lookup_refs(nodes_visited = []) ⇒ Object
-
#method_missing(method, *args, &block) ⇒ Object
Any unknown method calls will add an entry to the settings hash and return the current object.
-
#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.
- #retrieve_child(child_name) ⇒ Object
-
#two_layer_merge(downstream_hash, upstream_hash) ⇒ Object
Returns a new Hash that merges
downstream_hash
withupstream_hash
similar to callingupstream_hash
.merge(downstream_hash
) only it also merges any internal values that are themselves Hashes.
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
#children ⇒ Object
Returns the value of attribute children.
18 19 20 |
# File 'lib/om/xml/term.rb', line 18 def children @children end |
#name ⇒ Object
Returns the value of attribute name.
18 19 20 |
# File 'lib/om/xml/term.rb', line 18 def name @name end |
#settings ⇒ Object
Returns the value of attribute settings.
18 19 20 |
# File 'lib/om/xml/term.rb', line 18 def settings @settings end |
#terminology_builder ⇒ Object
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.
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 |