rgen-xsd 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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