Module: RGen::XSD::Particle
- Included in:
- XSDToEcoreTransformer
- Defined in:
- lib/rgen/xsd/particle.rb
Defined Under Namespace
Classes: Particle
Instance Method Summary collapse
- #add_substitution_particles(particles) ⇒ Object
-
#build_particles_trees(node) ⇒ Object
builds the particle trees for the particles contained in node.
-
#element_particles(node) ⇒ Object
builds a flat list of the element particles contained in
nodeto be used for ComplexType and complex content extensions. -
#flatten_particle_tree(particle) ⇒ Object
flattens the particle tree with root
particleand calculates min/max occurrence returns a list of particles of kind “element” and “any” element names are unique throughout the list the order is the order of first occurrence.
Instance Method Details
#add_substitution_particles(particles) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/rgen/xsd/particle.rb', line 23 def add_substitution_particles(particles) result = [] particles.each do |p| result << p if p.kind == :element p.node.substitutes.each do |s| result << Particle.new(:element, [], p.minOccurs, p.maxOccurs, s) end end end result end |
#build_particles_trees(node) ⇒ Object
builds the particle trees for the particles contained in node
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/rgen/xsd/particle.rb', line 104 def build_particles_trees(node) trees = [] # ComplexType and extension type have only one choice, sequence, all, group choices = node.choice choices = [choices].compact unless choices.is_a?(Array) choices.each do |c| trees << Particle.new(:choice, build_particles_trees(c), c.minOccurs || "1", c.maxOccurs || "1", c) end sequences = node.sequence sequences = [sequences].compact unless sequences.is_a?(Array) sequences.each do |s| trees << Particle.new(:sequence, build_particles_trees(s), s.minOccurs || "1", s.maxOccurs || "1", s) end alls = node.all alls = [alls].compact unless alls.is_a?(Array) alls.each do |a| trees << Particle.new(:all, build_particles_trees(s), a.minOccurs || "1", a.maxOccurs || "1", a) end # Group definitions don't have group reference particles if node.respond_to?(:group) groups = node.group groups = [groups].compact unless groups.is_a?(Array) groups.each do |g| if g.ref # the referenced group is a Model Group Definition, i.e. a node wrapping a Model Group # it must contain at most one of Choice, Sequence, All # it must not contain another "group" tag because this would be a particle group_childs = g.ref.all + g.ref.choice + g.ref.sequence if group_childs.size == 1 gtc = build_particles_trees(g.ref).first gtc.minOccurs = g.minOccurs || "1" gtc.maxOccurs = g.maxOccurs || "1" trees << gtc elsif group_childs.size > 1 puts "WARN: ignoring model group definition containing more than one model group" else # empty, ignore end else puts "WARN: ignoring non-toplevel group without a ref" end end end # ComplexType and complex content extension don't have element particles if node.respond_to?(:element) node.element.each do |e| if e.ref trees << Particle.new(:element, [], e.minOccurs || "1", e.maxOccurs || "1", e.ref) else trees << Particle.new(:element, [], e.minOccurs || "1", e.maxOccurs || "1", e) end end end # ComplexType and complex content extension don't have 'any' particles if node.respond_to?(:any) node.any.each do |a| trees << Particle.new(:any, [], a.minOccurs || "1", a.maxOccurs || "1", a) end end trees end |
#element_particles(node) ⇒ Object
builds a flat list of the element particles contained in node to be used for ComplexType and complex content extensions
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/rgen/xsd/particle.rb', line 11 def element_particles(node) trees = build_particles_trees(node) if trees.size == 1 flatten_particle_tree(trees.first) elsif trees.size > 1 puts "WARN: only one particle expected as a content model" [] else [] end end |
#flatten_particle_tree(particle) ⇒ Object
flattens the particle tree with root particle and calculates min/max occurrence returns a list of particles of kind “element” and “any” element names are unique throughout the list the order is the order of first occurrence
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 |
# File 'lib/rgen/xsd/particle.rb', line 40 def flatten_particle_tree(particle) if particle.kind == :element || particle.kind == :any [particle] else eocc = {} elist = [] particle.children.each do |c| flatten_particle_tree(c).each do |e| if e.kind == :element name = e.node.name else name = "#any#" end if !eocc[name] eocc[name] = [] elist << name end eocc[name] << e end end is_unbounded = lambda do |particle, elements| (particle.maxOccurs == "unbounded" && elements.any?{|e| e.maxOccurs == "unbounded" || e.maxOccurs.to_i > 0}) || (particle.maxOccurs.to_i > 0 && elements.any?{|e| e.maxOccurs == "unbounded"}) end if particle.kind == :choice elist.collect do |n| if eocc[n].size < particle.children.size # element is not in every choice min = 0 else min = eocc[n].collect{|e| e.minOccurs.to_i}.min * particle.minOccurs.to_i end if is_unbounded.call(particle, eocc[n]) max = "unbounded" else max = eocc[n].collect{|e| e.maxOccurs.to_i}.max * particle.maxOccurs.to_i end if n == "#any#" Particle.new(:any, [], min, max, eocc[n].first.node) else Particle.new(:element, [], min, max, eocc[n].first.node) end end else # sequence or all elist.collect do |n| min = eocc[n].inject(0){|m, e| m + e.minOccurs.to_i} * particle.minOccurs.to_i if is_unbounded.call(particle, eocc[n]) max = "unbounded" else max = eocc[n].inject(0){|m, e| m + e.maxOccurs.to_i} * particle.maxOccurs.to_i end if n == "#any#" Particle.new(:any, [], min, max, eocc[n].first.node) else Particle.new(:element, [], min, max, eocc[n].first.node) end end end end end |