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.
11 12 13 14 15 16 |
# File 'lib/om/xml/term.rb', line 11 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
116 117 118 119 120 121 122 |
# File 'lib/om/xml/term.rb', line 116 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.
9 10 11 |
# File 'lib/om/xml/term.rb', line 9 def children @children end |
#name ⇒ Object
Returns the value of attribute name.
9 10 11 |
# File 'lib/om/xml/term.rb', line 9 def name @name end |
#settings ⇒ Object
Returns the value of attribute settings.
9 10 11 |
# File 'lib/om/xml/term.rb', line 9 def settings @settings end |
#terminology_builder ⇒ Object
Returns the value of attribute terminology_builder.
9 10 11 |
# File 'lib/om/xml/term.rb', line 9 def terminology_builder @terminology_builder end |
Instance Method Details
#add_child(child) ⇒ Object
18 19 20 |
# File 'lib/om/xml/term.rb', line 18 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.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/om/xml/term.rb', line 94 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) 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
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 |
# File 'lib/om/xml/term.rb', line 26 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 begin target = self.terminology_builder.retrieve_term_builder(*@settings[:ref]) rescue OM::XML::Terminology::BadPointerError # Clarify message on BadPointerErrors raise OM::XML::Terminology::BadPointerError, "#{self.name} refers to a Term Builder that doesn't exist. The bad pointer is #{@settings[:ref].inspect}" end # 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.
61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/om/xml/term.rb', line 61 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
22 23 24 |
# File 'lib/om/xml/term.rb', line 22 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.
78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/om/xml/term.rb', line 78 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 |