rgen-xsd 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -2,3 +2,9 @@
2
2
 
3
3
  * First public release
4
4
 
5
+ =0.2.0
6
+
7
+ * Made XSI instantiator support XML patterns (wrapper, reference, attribute)
8
+ * Made XSI instantiator a lot faster
9
+ * XSI instantiator options to output problems and unresolved refs and set fragment refs
10
+
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ DocFiles = [
6
6
 
7
7
  RTextGemSpec = Gem::Specification.new do |s|
8
8
  s.name = %q{rgen-xsd}
9
- s.version = "0.1.0"
9
+ s.version = "0.2.0"
10
10
  s.date = Time.now.strftime("%Y-%m-%d")
11
11
  s.summary = %q{RGen XML schema support}
12
12
  s.email = %q{martin dot thiede at gmx de}
@@ -17,8 +17,16 @@ class XSIInstantiator
17
17
  @namespaces = []
18
18
  end
19
19
 
20
+ # options:
21
+ # :unresolved_refs: an array to which unresolved references will be appended
22
+ # :problems: an array to which problems during instantiation will be appended
23
+ # :fragment_ref: a fragment ref object which will be set on every model element created
20
24
  def instantiate(file, options={})
21
- @unresolved_refs = []
25
+ @unresolved_refs = options[:unresolved_refs] || []
26
+ @fragment_ref = options[:fragment_ref]
27
+ @problems = options[:problems]
28
+ @target_identifier_provider = options[:target_identifier_provider] ||
29
+ lambda do |node| node["id"] end
22
30
  root = nil
23
31
  root_class = options[:root_class].andand.ecore || root_class(doc.root.name)
24
32
  File.open(file) do |f|
@@ -42,7 +50,7 @@ class XSIInstantiator
42
50
  if prefix == "xml"
43
51
  href = "http://www.w3.org/XML/1998/namespace"
44
52
  elsif prefix
45
- puts "WARN: Can not resolve namespace prefix #{prefix}"
53
+ report_problem "WARN: Can not resolve namespace prefix #{prefix}"
46
54
  end
47
55
  end
48
56
  [href, name]
@@ -54,41 +62,59 @@ class XSIInstantiator
54
62
  node.attribute_nodes.find{|n| is_xsi_type?(n)}.andand.text
55
63
  end
56
64
 
57
- def instantiate_node(node, eclass)
58
- element = eclass.instanceClass.new
59
- @env << element
60
- set_attribute_values(element, node)
65
+ def instantiate_node(node, eclass, element=nil, wrapper_features=nil)
66
+ if !element
67
+ element = eclass.instanceClass.new
68
+ element.fragment_ref = @fragment_ref if @fragment_ref
69
+ @env << element
70
+ end
71
+ set_attribute_values(element, node, wrapper_features)
61
72
  simple_content = ""
62
- can_take_any = eclass.eAllAttributes.any?{|a| a.name == "anyObject"}
63
73
  node.children.each do |c|
64
74
  if c.text?
65
75
  simple_content << c.text
66
76
  elsif c.element?
67
- feats = features_by_xml_name(c.name).select{|f|
68
- f.eContainingClass == element.class.ecore ||
69
- f.eContainingClass.eAllSubTypes.include?(element.class.ecore)
70
- }
77
+ if wrapper_features
78
+ feats = wrapper_features.select{|f| xml_name(f) == c.name}
79
+ else
80
+ feats = features_by_xml_name(element.class, c.name) || []
81
+ end
71
82
  if feats.size == 1
72
83
  begin
73
84
  if feats.first.is_a?(RGen::ECore::EReference)
74
- element.setOrAddGeneric(feats.first.name,
75
- instantiate_node(c, reference_target_type(feats.first, xsi_type_value(c))))
85
+ if feats.first.containment
86
+ element.setOrAddGeneric(feats.first.name,
87
+ instantiate_node(c, reference_target_type(feats.first, xsi_type_value(c))))
88
+ else
89
+ proxy = RGen::MetamodelBuilder::MMProxy.new(@target_identifier_provider.call(c))
90
+ @unresolved_refs <<
91
+ RGen::Instantiator::ReferenceResolver::UnresolvedReference.new(element, feats.first.name, proxy)
92
+ element.setOrAddGeneric(feats.first.name, proxy)
93
+ end
76
94
  else
77
95
  element.setOrAddGeneric(feats.first.name, value_from_string(element, feats.first, c.text))
78
96
  end
79
97
  rescue Exception => e
80
- puts "Line: #{node.line}: #{e}"
98
+ report_problem "#{e}\n#{e.backtrace.join("\n")}", node
81
99
  end
82
100
  else
83
- if can_take_any
101
+ if wrapper_features
102
+ # already inside a wrapper
103
+ wrapper_feats = []
104
+ else
105
+ wrapper_feats = features_by_xml_wrapper_name(element.class, c.name) || []
106
+ end
107
+ if wrapper_feats.size > 0
108
+ instantiate_node(c, eclass, element, wrapper_feats)
109
+ elsif can_take_any(eclass)
84
110
  begin
85
- # currently the XML node is added to the model
86
- element.setOrAddGeneric("anyObject", c)
111
+ # TODO: currently the XML node is added to the model
112
+ # element.setOrAddGeneric("anyObject", c)
87
113
  rescue Exception => e
88
- puts "Line: #{node.line}: #{e}"
114
+ report_problem "#{e}\n#{e.backtrace.join("\n")}", node
89
115
  end
90
116
  else
91
- problem "could not determine reference for tag #{c.name}, #{feats.size} options", node
117
+ report_problem "could not determine reference for tag #{c.name}, #{feats.size} options", node
92
118
  end
93
119
  end
94
120
  end
@@ -112,13 +138,15 @@ class XSIInstantiator
112
138
  attr_node.namespace.andand.href == "http://www.w3.org/2001/XMLSchema-instance" && attr_node.node_name == "type"
113
139
  end
114
140
 
115
- def set_attribute_values(element, node)
141
+ def set_attribute_values(element, node, wrapper_features)
116
142
  node.attribute_nodes.each do |attrnode|
117
143
  next if is_xsi_type?(attrnode)
118
144
  name = attrnode.node_name
119
- feats = (features_by_xml_name(name) || []).select{|f|
120
- f.eContainingClass == element.class.ecore ||
121
- f.eContainingClass.eAllSubTypes.include?(element.class.ecore)}
145
+ if wrapper_features
146
+ feats = wrapper_features.select{|f| xml_name(f) == name}
147
+ else
148
+ feats = features_by_xml_name(element.class, name) || []
149
+ end
122
150
  if feats.size == 1
123
151
  f = feats.first
124
152
  str = node.attr(name)
@@ -135,25 +163,27 @@ class XSIInstantiator
135
163
  elsif name == "schemaLocation" || name == "noNamespaceSchemaLocation"
136
164
  # ignore, this may occure with any XML element
137
165
  else
138
- problem "could not determine feature for attribute #{name}, #{feats.size} options", node
166
+ report_problem "could not determine feature for attribute #{name}, #{feats.size} options", node
139
167
  end
140
168
  end
141
169
  end
142
170
 
143
171
  def value_from_string(element, f, str)
144
172
  if f.is_a?(RGen::ECore::EAttribute)
145
- case f.eType
146
- when RGen::ECore::EInt
147
- str.to_i
148
- when RGen::ECore::EFloat
149
- str.to_f
150
- when RGen::ECore::EEnum
173
+ if f.eType.is_a?(RGen::ECore::EEnum)
151
174
  str.to_sym
152
- when RGen::ECore::EBoolean
153
- (str == "true")
154
175
  else
155
- str
156
- end
176
+ case f.eType.instanceClassName
177
+ when "Integer"
178
+ str.to_i
179
+ when "Float"
180
+ str.to_f
181
+ when "Boolean"
182
+ (str == "true")
183
+ else
184
+ str
185
+ end
186
+ end
157
187
  else
158
188
  proxy = RGen::MetamodelBuilder::MMProxy.new(str)
159
189
  @unresolved_refs <<
@@ -188,8 +218,12 @@ class XSIInstantiator
188
218
  end
189
219
  end
190
220
 
191
- def problem(desc, node)
192
- raise desc + " at [#{node.name}]"
221
+ def report_problem(desc, node=nil)
222
+ if node
223
+ @problems << "#{desc} at line #{node.line}"
224
+ else
225
+ @problems << desc
226
+ end
193
227
  end
194
228
 
195
229
  def classes_by_xml_name(name)
@@ -203,21 +237,45 @@ class XSIInstantiator
203
237
  @classes_by_xml_name[name]
204
238
  end
205
239
 
206
- def features_by_xml_name(name)
207
- return @features_by_xml_name[name] || [] if @features_by_xml_name
208
- @features_by_xml_name = {}
209
- @mm.ecore.eAllClasses.eStructuralFeatures.each do |f|
240
+ def features_by_xml_name(clazz, name)
241
+ @features_by_xml_name ||= {}
242
+ return @features_by_xml_name[clazz][name] || [] if @features_by_xml_name[clazz]
243
+ @features_by_xml_name[clazz] = {}
244
+ clazz.ecore.eAllStructuralFeatures.each do |f|
210
245
  n = xml_name(f)
211
- @features_by_xml_name[n] ||= []
212
- @features_by_xml_name[n] << f
246
+ @features_by_xml_name[clazz][n] ||= []
247
+ @features_by_xml_name[clazz][n] << f
248
+ end
249
+ @features_by_xml_name[clazz][name]
250
+ end
251
+
252
+ def features_by_xml_wrapper_name(clazz, name)
253
+ @features_by_xml_wrapper_name ||= {}
254
+ return @features_by_xml_wrapper_name[clazz][name] || [] if @features_by_xml_wrapper_name[clazz]
255
+ @features_by_xml_wrapper_name[clazz] = {}
256
+ clazz.ecore.eAllStructuralFeatures.each do |f|
257
+ n = xml_wrapper_name(f)
258
+ if n
259
+ @features_by_xml_wrapper_name[clazz][n] ||= []
260
+ @features_by_xml_wrapper_name[clazz][n] << f
261
+ end
213
262
  end
214
- @features_by_xml_name[name]
263
+ @features_by_xml_wrapper_name[clazz][name]
264
+ end
265
+
266
+ def can_take_any(eclass)
267
+ @can_take_any ||= {}
268
+ @can_take_any[eclass] ||= eclass.eAllAttributes.any?{|a| a.name == "anyObject"}
215
269
  end
216
270
 
217
271
  def xml_name(o)
218
272
  annotation_value(o, "xmlName") || o.name
219
273
  end
220
274
 
275
+ def xml_wrapper_name(o)
276
+ annotation_value(o, "xmlWrapperName")
277
+ end
278
+
221
279
  def annotation_value(o, key)
222
280
  anno = o.eAnnotations.find{|a| a.source == "xsd"}
223
281
  anno.andand.details.andand.find{|d| d.key == key}.andand.value
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgen-xsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-13 00:00:00.000000000Z
12
+ date: 2012-09-19 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rgen
16
- requirement: &23972604 !ruby/object:Gem::Requirement
16
+ requirement: &24218064 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 0.6.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *23972604
24
+ version_requirements: *24218064
25
25
  description: Derive RGen/ECore metamodels from XML schema and load/store XML documents
26
26
  conforming to the schema as RGen models
27
27
  email: martin dot thiede at gmx de