Class: Quickbooks::XSD::Element

Inherits:
Object
  • Object
show all
Includes:
Validation
Defined in:
lib/quickbooks/xsd/element.rb

Overview

The basic Element.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Validation

#validate_these

Constructor Details

#initialize(attributes = {}) ⇒ Element

Returns a new instance of Element.



10
11
12
13
14
15
16
17
18
19
# File 'lib/quickbooks/xsd/element.rb', line 10

def initialize(attributes={})
  @parent = attributes.delete(:parent)
  @name = attributes.delete('name')
  self.type = attributes.delete('type') if attributes.has_key?('type')
  @default = attributes.delete('default') # or nil
  @minOccurs = (attributes.delete('minOccurs') || 1).to_i # default is 1, unless otherwise stated
  @maxOccurs = attributes.delete('maxOccurs') # or nil
  @ref = attributes.delete('ref') # or nil
  warn "!! Unhandled attributes: #{attributes.keys.join(', ')}" if !attributes.empty?
end

Instance Attribute Details

#maxOccursObject (readonly)

Returns the value of attribute maxOccurs.



7
8
9
# File 'lib/quickbooks/xsd/element.rb', line 7

def maxOccurs
  @maxOccurs
end

#minOccursObject (readonly)

Returns the value of attribute minOccurs.



7
8
9
# File 'lib/quickbooks/xsd/element.rb', line 7

def minOccurs
  @minOccurs
end

#refObject (readonly)

Returns the value of attribute ref.



7
8
9
# File 'lib/quickbooks/xsd/element.rb', line 7

def ref
  @ref
end

Instance Method Details

#<<(something) ⇒ Object



84
85
86
87
88
89
90
91
92
93
# File 'lib/quickbooks/xsd/element.rb', line 84

def <<(something)
  case something
  when SimpleType
    self.type = something
  when ComplexType
    self.type = something
  else
    warn "Something (#{something.inspect}) not handled by #{inspect}"
  end
end

#attributesObject



200
201
202
# File 'lib/quickbooks/xsd/element.rb', line 200

def attributes
  children.collect {|i| i.name}
end

#childrenObject

Return the closest-descended child elements



205
206
207
208
209
210
211
# File 'lib/quickbooks/xsd/element.rb', line 205

def children
  begin
    @children ||= type.children
  rescue => e
    raise e, "In object #{inspect}"
  end
end

#cloneObject



66
67
68
# File 'lib/quickbooks/xsd/element.rb', line 66

def clone
  self.class.new(:parent => @parent, 'name' => "#{name}", 'type' => type.clone, 'default' => @default, 'minOccurs' => @minOccurs, 'maxOccurs' => @maxOccurs, 'ref' => @ref)
end

#complex?Boolean Also known as: is_element?

Returns:



33
34
35
# File 'lib/quickbooks/xsd/element.rb', line 33

def complex?
  type.is_a?(ComplexType)
end

#exists_in?(object) ⇒ Boolean

Returns:



154
155
156
# File 'lib/quickbooks/xsd/element.rb', line 154

def exists_in?(object)
  !(object[name].is_a?(Enumerable) ? object[name].empty? : object[name].nil?)
end

#find(key) ⇒ Object Also known as: []



158
159
160
# File 'lib/quickbooks/xsd/element.rb', line 158

def find(key)
  name == key ? self : children.select {|i| i.name == key}[0]
end

#gsub(*args, &block) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/quickbooks/xsd/element.rb', line 59

def gsub(*args,&block)
  if block_given?
    clone.gsub!(*args) {|*a| yield(*a)}
  else
    clone.gsub!(*args)
  end
end

#gsub!(*args, &block) ⇒ Object



49
50
51
52
53
54
55
56
57
58
# File 'lib/quickbooks/xsd/element.rb', line 49

def gsub!(*args,&block)
  if block_given?
    @name = name.gsub(*args) {|*a| yield(*a)} if name.is_a?(String)
    children.each {|c| c.gsub!(*args) {|*a| yield(*a)}}
  else
    @name = name.gsub(*args) if name.is_a?(String)
    children.each {|c| c.gsub!(*args)}
  end
  self
end

#include?(key_or_xsd) ⇒ Boolean

Report whether a named Quickbooks::XSD::Element or any xsd object is a descendent of self.

Returns:



164
165
166
167
168
169
# File 'lib/quickbooks/xsd/element.rb', line 164

def include?(key_or_xsd)
  raise "#{self} not defined properly! This is a BUG! Please report to behindlogic.lighthouseapp.com." if !key_or_xsd.is_a?(String) && type.nil?
  key_or_xsd.is_a?(String) ?
    (name == key_or_xsd ? true : children.collect {|e| e.name}.include?(key_or_xsd)) :
    (key_or_xsd == self || type.include?(key_or_xsd))
end

#index(key) ⇒ Object

Report the position of a named Quickbooks::XSD::Element



172
173
174
# File 'lib/quickbooks/xsd/element.rb', line 172

def index(key)
  children.collect {|e| e.name}.index(key.to_s)
end

#inspectObject



95
96
97
# File 'lib/quickbooks/xsd/element.rb', line 95

def inspect
  sprintf("\n<%s%s %s", name || ref, (@minOccurs == 0 ? (@maxOccurs == 'unbounded' ? '*' : '?') : (@maxOccurs == 'unbounded' ? '+' : '')), type.inspect) + (type.is_a?(ComplexType) ? '' : '>')
end

#is_model?Boolean

Returns:



41
42
43
# File 'lib/quickbooks/xsd/element.rb', line 41

def is_model?
  name.to_s =~ /Ret$/
end

#kindObject



44
45
46
47
# File 'lib/quickbooks/xsd/element.rb', line 44

def kind
  # TODO: [Multi-mode] Should return Quickbooks::V6_0::Element or Quickbooks::VCA3_0::Element
  complex? ? Quickbooks::Element : Quickbooks::Property
end

#merge(attributes) ⇒ Object



70
71
72
# File 'lib/quickbooks/xsd/element.rb', line 70

def merge(attributes)
  self.class.new({:parent => self, 'name' => name, 'type' => type, 'default' => @default, 'minOccurs' => @minOccurs, 'maxOccurs' => @maxOccurs, 'ref' => @ref}.merge(attributes))
end

#merge!(attributes) ⇒ Object



74
75
76
77
78
79
80
81
82
# File 'lib/quickbooks/xsd/element.rb', line 74

def merge!(attributes)
  @name = attributes.delete('name') || @name
  self.type = attributes.delete('type') if attributes.has_key?('type')
  @default = attributes.delete('default') || @default
  @minOccurs = (attributes.delete('minOccurs') || @minOccurs).to_i
  @maxOccurs = attributes.delete('maxOccurs') || @maxOccurs
  @ref = attributes.delete('ref') || @ref
  return self
end

#repeatable?(key = nil) ⇒ Boolean

Reports whether the named Quickbooks::XSD::Element or other xsd object is allowed more than once in its parent.

Returns:



177
178
179
180
181
182
183
184
185
# File 'lib/quickbooks/xsd/element.rb', line 177

def repeatable?(key=nil)
  if key
    found = find(key)
    return nil unless found
    found.repeatable? || type.repeatable?(key)
  else
    @maxOccurs == 'unbounded'
  end
end

#required?(key_or_xsd) ⇒ Boolean

Reports whether the named Quickbooks::XSD::Element or other xsd object is required within its container.

Returns:



188
189
190
191
192
193
194
195
196
197
198
# File 'lib/quickbooks/xsd/element.rb', line 188

def required?(key_or_xsd)
  if key_or_xsd.is_a?(String)
    if found = find(key_or_xsd)
      found.required?(found) || type.required?(found)
    else
      nil
    end
  else
    (key_or_xsd == self && @minOccurs > 0) || type.required?(key_or_xsd)
  end
end

#simple?Boolean Also known as: is_property?

Returns:



37
38
39
# File 'lib/quickbooks/xsd/element.rb', line 37

def simple?
  type.is_a?(SimpleType)
end

#to_class(klass_name) ⇒ Object



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
125
126
# File 'lib/quickbooks/xsd/element.rb', line 99

def to_class(klass_name)
  puts "Classifying #{klass_name}/#{kind}..." if $DEBUG
  begin
    if name == klass_name+'Ret' || name == klass_name+'Add' || name == klass_name+'Mod'
      # Generate a Model
      # TODO: [Multi-mode] Should generate Quickbooks::V6_0::Models or Quickbooks::VCA3_0::Models container modules on-demand
      const = Quickbooks::Models.const_set(klass_name, ::Class.new(Quickbooks::Model))

      const.write_xsd(Quickbooks.xsd["#{klass_name}Add"].gsub(/Add$/,'')) if Quickbooks.xsd.include?("#{klass_name}Add")
      const.read_write_xsd(
        Quickbooks.xsd["#{klass_name}Mod"].gsub(/(.*)Mod$/) {|m| Quickbooks.xsd.include?(m.gsub(/Mod$/,'Ret')) ? m.gsub(/Mod$/,'') : m}
      )                                                                   if Quickbooks.xsd.include?("#{klass_name}Mod")

      const.read_xsd(Quickbooks.xsd["#{klass_name}Ret"].gsub(/Ret$/,''))  if Quickbooks.xsd.include?("#{klass_name}Ret")

      const.query_xsd(Quickbooks.xsd["#{klass_name}QueryRq"])             if Quickbooks.xsd.include?("#{klass_name}QueryRq")

    else
      # Generate an Element
      # TODO: [Multi-mode] Should generate Quickbooks::V6_0::Elements or Quickbooks::VCA3_0::Elements container modules on-demand
      const = kind.pluralize.const_set(klass_name, ::Class.new(kind))
      const.xsd = self
    end
  rescue => e
    raise e, "Error: #{e.inspect}\n#{e.backtrace.join("\n")}"
  end
  return const
end

#type=(type_or_name) ⇒ Object



21
22
23
24
25
26
27
28
# File 'lib/quickbooks/xsd/element.rb', line 21

def type=(type_or_name)
  return unless type_or_name
  if (@type ||= nil).nil?
    @type = type_or_name.is_a?(Quickbooks::XSD::Type) ? type_or_name : SimpleType.new('name' => type_or_name)
  else
    @type.merge!(type) if type_or_name.is_a?(Quickbooks::XSD::Type)
  end
end

#validate(object, required = true) ⇒ Object

Validate the object’s properties, or validate that this property exists within the object.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/quickbooks/xsd/element.rb', line 130

def validate(object,required=true)
  if object.class.short_name == name || (object.is_a?(Hash) && object.has_key?(name))
    # Validate the object's contents
    object = object[name] if object.is_a?(Hash)
    puts "#{$DEBUG<<"\t"}Validating\n#{object.inspect}\n#{$DEBUG} CONFORMS TO #{name} (#{required ? 'REQUIRED' : 'OPTIONAL'})" if $DEBUG
    r = type.validate(object,required?(type))
    $DEBUG.chop! if $DEBUG
  else
    puts "#{$DEBUG<<"\t"}Validating #{required ? 'REQUIRED' : 'OPTIONAL'} #{name}" if $DEBUG
    # Validate this (self) property of object
    # puts "Validating #{inspect} IN #{object.inspect}"
    # A) am I required?
    r = Valean.new(name,required)
    # B) do I exist?
    r.exists! if exists_in?(object)
    # C) if exists, do I validate with my own requirements?
    objects = object[name].is_a?(Enumerable) ? object[name] : [object[name]]
    r << validate_these(objects) if r.exists?
    $DEBUG.chop! if $DEBUG
  end
  puts "#{$DEBUG}\t- #{r}" if $DEBUG
  r
end