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 +6 -0
- data/Rakefile +1 -1
- data/lib/rgen/xsd/xsi_instantiator.rb +101 -43
- metadata +4 -4
data/CHANGELOG
CHANGED
data/Rakefile
CHANGED
@@ -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
|
-
|
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
|
59
|
-
|
60
|
-
|
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
|
-
|
68
|
-
f
|
69
|
-
|
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
|
-
|
75
|
-
|
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
|
-
|
98
|
+
report_problem "#{e}\n#{e.backtrace.join("\n")}", node
|
81
99
|
end
|
82
100
|
else
|
83
|
-
if
|
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
|
-
|
114
|
+
report_problem "#{e}\n#{e.backtrace.join("\n")}", node
|
89
115
|
end
|
90
116
|
else
|
91
|
-
|
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
|
-
|
120
|
-
f
|
121
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
156
|
-
|
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
|
192
|
-
|
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
|
-
|
208
|
-
@features_by_xml_name
|
209
|
-
@
|
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
|
-
@
|
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.
|
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-
|
12
|
+
date: 2012-09-19 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rgen
|
16
|
-
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: *
|
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
|