codemodels 0.2.2-java
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/.gitignore +19 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +23 -0
- data/Rakefile +9 -0
- data/codemodels.gemspec +29 -0
- data/lib/codemodels/foreign_ast.rb +11 -0
- data/lib/codemodels/info_extraction.rb +139 -0
- data/lib/codemodels/language.rb +65 -0
- data/lib/codemodels/metamodel.rb +11 -0
- data/lib/codemodels/model_building.rb +81 -0
- data/lib/codemodels/monkey_patching.rb +30 -0
- data/lib/codemodels/parsing.rb +184 -0
- data/lib/codemodels/query_serialized.rb +81 -0
- data/lib/codemodels/rgen_ext.rb +186 -0
- data/lib/codemodels/serialization.rb +142 -0
- data/lib/codemodels/version.rb +3 -0
- data/lib/codemodels.rb +5 -0
- data/test/data/node_setCompleted.json +443 -0
- data/test/test_foreign_ast.rb +28 -0
- data/test/test_helper.rb +10 -0
- data/test/test_info_extraction.rb +90 -0
- data/test/test_language.rb +28 -0
- data/test/test_monkey_patching.rb +38 -0
- data/test/test_query_serialized.rb +40 -0
- data/test/test_rgen_ext.rb +187 -0
- data/test/test_serialization.rb +83 -0
- metadata +167 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
# This module permits to manipulate Objects serialized
|
2
|
+
# as Hash
|
3
|
+
|
4
|
+
module CodeModels
|
5
|
+
|
6
|
+
module QuerySerialized
|
7
|
+
|
8
|
+
def self.rel_conts(root)
|
9
|
+
root.keys.select {|k| k.start_with? 'relcont_'}
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.rel_non_conts(root)
|
13
|
+
root.keys.select {|k| k.start_with? 'relnoncont_'}
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.attrs(root)
|
17
|
+
root.keys.select {|k| k.start_with? 'attr_'}
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.print_tree(root,depth=0)
|
21
|
+
traverse(root) do |n,d|
|
22
|
+
s = ""
|
23
|
+
d.times { s = s + " " }
|
24
|
+
s = s + n['type'] if n
|
25
|
+
s = s + '<NIL>' unless n
|
26
|
+
puts s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.values(root,feat)
|
31
|
+
raw = root[feat]
|
32
|
+
return [] if raw==nil
|
33
|
+
return raw if raw.is_a? Array
|
34
|
+
return [raw]
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.traverse(root,depth=0,&op)
|
38
|
+
return traverse(root['root'],depth,&op) if root and (root.key? 'root')
|
39
|
+
op.call(root,depth)
|
40
|
+
return unless root
|
41
|
+
rel_conts(root).each do |r|
|
42
|
+
if root[r].is_a? Array
|
43
|
+
root[r].each do |c|
|
44
|
+
raise "expected an object but it is a #{c.class} (relation: #{r})" unless c.is_a? Hash
|
45
|
+
traverse(c,depth+1,&op)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
traverse(root[r],depth+1,&op)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# the set of values appearing in the object and its children
|
54
|
+
def self.collect_values(el)
|
55
|
+
values = Set.new
|
56
|
+
rel_conts(el).each do |r|
|
57
|
+
values(el,r).each {|c| values.merge(collect_values(c))}
|
58
|
+
end
|
59
|
+
attrs(el).each do |a|
|
60
|
+
values(el,a).each {|v| values.add(v)}
|
61
|
+
end
|
62
|
+
values
|
63
|
+
end
|
64
|
+
|
65
|
+
# a counting map values appearing in the object and its children
|
66
|
+
def self.collect_values_with_count(el)
|
67
|
+
values = Hash.new {|h,k| h[k]=0}
|
68
|
+
rel_conts(el).each do |r|
|
69
|
+
values(el,r).each do |ch|
|
70
|
+
collect_values_with_count(ch).each {|v,count| values[v]+=count}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
attrs(el).each do |a|
|
74
|
+
values(el,a).each {|v| values[v]+=1 }
|
75
|
+
end
|
76
|
+
values
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# Extensions to RGen objects
|
2
|
+
|
3
|
+
require 'rgen/metamodel_builder'
|
4
|
+
|
5
|
+
class RGen::MetamodelBuilder::MMBase
|
6
|
+
|
7
|
+
module ClassAddOn
|
8
|
+
|
9
|
+
def build(values={})
|
10
|
+
instance = self.new
|
11
|
+
if values.is_a? Hash
|
12
|
+
values.each do |k,v|
|
13
|
+
attribute = self.ecore.eAllAttributes.find {|x| x.name==k.to_s}
|
14
|
+
reference = self.ecore.eAllReferences.find {|x| x.name==k.to_s}
|
15
|
+
raise EMF::UnexistingFeature.new(k.to_s) unless (attribute or reference)
|
16
|
+
setter = (k.to_s+'=').to_sym
|
17
|
+
instance.send setter, v
|
18
|
+
end
|
19
|
+
else
|
20
|
+
has_dynamic = false
|
21
|
+
self.ecore.eAllAttributes.each {|a| has_dynamic|=a.name=='dynamic'}
|
22
|
+
d = 0
|
23
|
+
d = 1 if has_dynamic
|
24
|
+
|
25
|
+
raise EMF::SingleAttributeRequired.new(self.ecore.name,self.ecore.eAllAttributes) if self.ecore.eAllAttributes.count!=1+d
|
26
|
+
attribute = self.ecore.eAllAttributes[0]
|
27
|
+
set_attr(instance,attribute,values)
|
28
|
+
end
|
29
|
+
instance
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def set_attr(instance,attribute,value)
|
35
|
+
setter = (attribute.name+'=').to_sym
|
36
|
+
instance.send setter, value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module SingletonAddOn
|
41
|
+
|
42
|
+
# It does not check references, it is needed to avoid infinite recursion
|
43
|
+
def shallow_eql?(other)
|
44
|
+
return false if other==nil
|
45
|
+
return false unless self.class==other.class
|
46
|
+
self.class.ecore.eAllAttributes.each do |attrib|
|
47
|
+
raise "Attrib <nil> for class #{self.class.ecore.name}" unless attrib
|
48
|
+
if attrib.name != 'dynamic' # I have to understand this...
|
49
|
+
self_value = self.get(attrib)
|
50
|
+
other_value = other.get(attrib)
|
51
|
+
#puts "returning false on #{attrib.name}" unless self_value.eql?(other_value)
|
52
|
+
return false unless self_value == other_value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
def eql?(other)
|
59
|
+
# it should ignore relations which has as opposite a containement
|
60
|
+
return false unless self.shallow_eql?(other)
|
61
|
+
self.class.ecore.eAllReferences.each do |ref|
|
62
|
+
self_value = self.get(ref)
|
63
|
+
other_value = other.get(ref)
|
64
|
+
to_ignore = ref.getEOpposite and ref.getEOpposite.containment
|
65
|
+
unless to_ignore
|
66
|
+
if ref.containment
|
67
|
+
return false unless self_value == other_value
|
68
|
+
else
|
69
|
+
if (self_value.is_a? Array) or (other_value.is_a? Array)
|
70
|
+
return false unless self_value.count==other_value.count
|
71
|
+
for i in 0..(self_value.count-1)
|
72
|
+
unless self_value[i].shallow_eql?(other_value[i])
|
73
|
+
return false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
else
|
77
|
+
if self_value==nil
|
78
|
+
return false unless other_value==nil
|
79
|
+
else
|
80
|
+
return false unless self_value.shallow_eql?(other_value)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
def ==(other)
|
90
|
+
eql? other
|
91
|
+
end
|
92
|
+
|
93
|
+
def get(attr_or_ref)
|
94
|
+
getter = (attr_or_ref.name).to_sym
|
95
|
+
send getter
|
96
|
+
end
|
97
|
+
|
98
|
+
def all_children
|
99
|
+
arr = []
|
100
|
+
ecore = self.class.ecore
|
101
|
+
ecore.eAllReferences.select {|r| r.containment}.each do |ref|
|
102
|
+
res = self.send(ref.name.to_sym)
|
103
|
+
if ref.many
|
104
|
+
d = arr.count
|
105
|
+
res.each do |el|
|
106
|
+
arr << el unless res==nil
|
107
|
+
end
|
108
|
+
elsif res!=nil
|
109
|
+
d = arr.count
|
110
|
+
arr << res
|
111
|
+
end
|
112
|
+
end
|
113
|
+
arr
|
114
|
+
end
|
115
|
+
|
116
|
+
def all_children_deep
|
117
|
+
arr = []
|
118
|
+
all_children.each do |c|
|
119
|
+
arr << c
|
120
|
+
c.all_children_deep.each do |cc|
|
121
|
+
arr << cc
|
122
|
+
end
|
123
|
+
end
|
124
|
+
arr
|
125
|
+
end
|
126
|
+
|
127
|
+
def traverse(&op)
|
128
|
+
op.call(self)
|
129
|
+
all_children_deep.each do |c|
|
130
|
+
op.call(c)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def collect_values_with_count
|
135
|
+
values = Hash.new {|h,k| h[k]=0}
|
136
|
+
self.class.ecore.eAllAttributes.each do |a|
|
137
|
+
v = self.send(:"#{a.name}")
|
138
|
+
if v!=nil
|
139
|
+
if a.many
|
140
|
+
v.each {|el| values[el]+=1}
|
141
|
+
else
|
142
|
+
values[v]+=1
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
values
|
147
|
+
end
|
148
|
+
|
149
|
+
def collect_values_with_count_subtree
|
150
|
+
values = collect_values_with_count
|
151
|
+
all_children_deep.each do |c|
|
152
|
+
c.collect_values_with_count.each do |k,v|
|
153
|
+
values[k]+=v
|
154
|
+
end
|
155
|
+
end
|
156
|
+
values
|
157
|
+
end
|
158
|
+
|
159
|
+
def all_children_of_type(type)
|
160
|
+
all_children.select {|c| c and c.is_a?(type)}
|
161
|
+
end
|
162
|
+
|
163
|
+
def all_children_deep_of_type(type)
|
164
|
+
all_children_deep.select {|c| c and c.is_a?(type)}
|
165
|
+
end
|
166
|
+
|
167
|
+
def only_child_of_type(type)
|
168
|
+
selected = all_children_of_type(type)
|
169
|
+
raise "Exactly one child of type #{type} expected, #{selected.count} found on #{self}" unless selected.count==1
|
170
|
+
selected[0]
|
171
|
+
end
|
172
|
+
|
173
|
+
def only_child_deep_of_type(type)
|
174
|
+
selected = all_children_deep_of_type(type)
|
175
|
+
raise "Exactly one child of type #{type} expected, #{selected.count} found on #{self}" unless selected.count==1
|
176
|
+
selected[0]
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
class << self
|
182
|
+
include ClassAddOn
|
183
|
+
end
|
184
|
+
|
185
|
+
include SingletonAddOn
|
186
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# This code permit to transform RGen-Objects in Hash objects
|
2
|
+
# containing lists and single values
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'rgen/metamodel_builder'
|
7
|
+
|
8
|
+
module CodeModels
|
9
|
+
module Serialization
|
10
|
+
|
11
|
+
module SerializationFunctionalities
|
12
|
+
|
13
|
+
# It could be a simple hash with a block passed to the
|
14
|
+
# constructor...
|
15
|
+
class SerializationMemory
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@next_id = 1
|
19
|
+
@id_map = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def id(rgen_object)
|
23
|
+
unless @id_map[rgen_object]
|
24
|
+
@id_map[rgen_object] = @next_id
|
25
|
+
@next_id += 1
|
26
|
+
end
|
27
|
+
@id_map[rgen_object]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_json(serialization_memory=SerializationMemory.new,adapters={},with_source_info=true)
|
33
|
+
e_object = self
|
34
|
+
map = { 'type' => qname, 'id' => serialization_memory.id(e_object) }
|
35
|
+
if with_source_info
|
36
|
+
if self.respond_to?(:source) && self.source
|
37
|
+
source_map = {}
|
38
|
+
if self.source.begin_pos
|
39
|
+
source_map['begin_pos'] = {'line'=> self.source.begin_pos.line, 'column'=>self.source.begin_pos.column}
|
40
|
+
end
|
41
|
+
if self.source.end_pos
|
42
|
+
source_map['end_pos'] = {'line'=> self.source.end_pos.line, 'column'=>self.source.end_pos.column}
|
43
|
+
end
|
44
|
+
map['source'] = source_map
|
45
|
+
end
|
46
|
+
end
|
47
|
+
e_class = e_object.class.ecore
|
48
|
+
e_class.eAllAttributes.each do |a|
|
49
|
+
jsonize_attr_value(map,a)
|
50
|
+
end
|
51
|
+
e_class.eAllReferences.each do |r|
|
52
|
+
id = jsonize_ref_value(map,r,adapters,serialization_memory)
|
53
|
+
end
|
54
|
+
if adapters.has_key? qname
|
55
|
+
adapters[qname].adapt(self,map)
|
56
|
+
end
|
57
|
+
map
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def qname
|
63
|
+
self.class.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
def jsonize_attr_value(map,e_attr)
|
67
|
+
value = self.send(e_attr.name.to_sym)
|
68
|
+
if e_attr.upperBound==1
|
69
|
+
map["attr_#{e_attr.name}"] = value
|
70
|
+
else
|
71
|
+
l = []
|
72
|
+
value.each do |e|
|
73
|
+
l << e
|
74
|
+
end
|
75
|
+
map["attr_#{e_attr.name}"] = l
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def jsonize_ref_value(map,e_ref,adapters,serialization_memory)
|
80
|
+
value = self.send e_ref.name.to_sym
|
81
|
+
|
82
|
+
propname = "relcont_#{e_ref.name}" if e_ref.containment
|
83
|
+
propname = "relnoncont_#{e_ref.name}" if not e_ref.containment
|
84
|
+
|
85
|
+
if e_ref.upperBound==1
|
86
|
+
map[propname] = jsonize_ref_single_el(value,e_ref.containment,adapters,serialization_memory)
|
87
|
+
else
|
88
|
+
l = []
|
89
|
+
(0...(value.size)).each do |i|
|
90
|
+
l << jsonize_ref_single_el(value.at(i),e_ref.containment,adapters,serialization_memory)
|
91
|
+
end
|
92
|
+
map[propname] = l
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def jsonize_ref_single_el(single_value,containment,adapters,serialization_memory)
|
97
|
+
if containment
|
98
|
+
single_value.to_json(serialization_memory,adapters)
|
99
|
+
else
|
100
|
+
serialization_memory.id(single_value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
class ::RGen::MetamodelBuilder::MMBase
|
107
|
+
include SerializationFunctionalities
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.load_file(path,max_nesting=500)
|
111
|
+
JSON.parse(File.read(path),{max_nesting: max_nesting})
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.save_model(model,model_path, max_nesting=500)
|
115
|
+
dir = File.dirname(model_path)
|
116
|
+
FileUtils.mkdir_p(dir)
|
117
|
+
|
118
|
+
File.open(model_path, 'w') do |file|
|
119
|
+
file.write(JSON.pretty_generate(model, :max_nesting => max_nesting))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.rgenobject_to_model(root,adapters={})
|
124
|
+
model = {}
|
125
|
+
external_elements = []
|
126
|
+
|
127
|
+
sm = SerializationFunctionalities::SerializationMemory.new
|
128
|
+
model['root'] = root.to_json(sm,adapters)
|
129
|
+
model['external_elements'] = []
|
130
|
+
external_elements.each do |ee|
|
131
|
+
model['external_elements'] << ee.to_json(sm,adapters)
|
132
|
+
end
|
133
|
+
model
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.save_as_model(root,model_path)
|
137
|
+
model = to_model(root)
|
138
|
+
save_model(model,model_path)
|
139
|
+
end
|
140
|
+
|
141
|
+
end # module
|
142
|
+
end # module
|