lightmodels 0.1.2-java → 0.2.1-java

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ Gemfile.lock
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ coverage
7
+ InstalledFiles
8
+ lib/bundler/man
9
+ pkg
10
+ rdoc
11
+ spec/reports
12
+ test/tmp
13
+ test/version_tmp
14
+ tmp
15
+
16
+ # YARD artifacts
17
+ .yardoc
18
+ _yardoc
19
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 ftomassetti
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,8 @@
1
+ lightmodels
2
+ ===========
3
+
4
+ lightmodels is a library to manipulate models and save them in a lightweight format (JSON is used for serialization).
5
+
6
+ EMF models and RGen models can be converted to lightmodels.
7
+
8
+ Other projects permit to obtain lightmodels representation of Ruby (ruby_to_emf_parser) and Java (java_model_jrb) code, Properties (properties_lightmodels) and XML (xml_lightmodels) files.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ desc "Run tests"
9
+ task :default => :test
@@ -0,0 +1,133 @@
1
+ module LightModels
2
+
3
+ module InfoExtraction
4
+
5
+ class TermsBreaker
6
+
7
+ attr_accessor :sequences, :inv_sequences
8
+
9
+ def initialize(language_specific_logic)
10
+ @language_specific_logic = language_specific_logic
11
+ @sequences = Hash.new {|h,k|
12
+ h[k] = Hash.new {|h,k|
13
+ h[k]=0
14
+ }
15
+ }
16
+ @inv_sequences = Hash.new {|h,k|
17
+ h[k] = Hash.new {|h2,k2|
18
+ h2[k2]=0
19
+ }
20
+ }
21
+ end
22
+
23
+ def self.from_context(language_specific_logic,context)
24
+ ser_context = LightModels::Serialization.jsonize_obj(context)
25
+ values_map = LightModels::QuerySerialized.collect_values_with_count(ser_context)
26
+ instance = new(language_specific_logic)
27
+ values_map.each do |value,c|
28
+ value = value.to_s.strip
29
+ if language_specific_logic.terms_containing_value?(value)
30
+ words = language_specific_logic.to_words(value)
31
+ first_words = words[0...-1]
32
+ instance.inv_sequences[words[0].downcase][:start] += c
33
+ first_words.each_with_index do |w,i|
34
+ instance.sequences[w.downcase][words[i+1].downcase] += c
35
+ instance.inv_sequences[words[i+1].downcase][w.downcase] += c
36
+ end
37
+ last_word = words.last
38
+ instance.sequences[last_word.downcase][:end] += c
39
+ else
40
+ # who cares, it will be never considered for composed names...
41
+ end
42
+ end
43
+ instance
44
+ end
45
+
46
+ def terms_in_value(value)
47
+ value = value.to_s.strip
48
+ if @language_specific_logic.terms_containing_value?(value)
49
+ words = @language_specific_logic.to_words(value)
50
+ group_words_in_terms(words).map{|w| w.downcase}
51
+ else
52
+ [value]
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def frequent_straight_sequence?(w1,w2)
59
+ w1 = w1.downcase
60
+ w2 = w2.downcase
61
+ all_sequences_of_w1 = 0
62
+ @sequences[w1].each do |k,v|
63
+ all_sequences_of_w1 += v
64
+ end
65
+ sequences_w1_w2 = @sequences[w1][w2]
66
+ (sequences_w1_w2.to_f/all_sequences_of_w1.to_f)>0.5
67
+ end
68
+
69
+ def frequent_inverse_sequence?(w1,w2)
70
+ w1 = w1.downcase
71
+ w2 = w2.downcase
72
+ all_inv_sequences_of_w1 = 0
73
+ @inv_sequences[w1].each do |k,v|
74
+ all_inv_sequences_of_w1 += v
75
+ end
76
+ inv_sequences_w1_w2 = @inv_sequences[w1][w2]
77
+ (inv_sequences_w1_w2.to_f/all_inv_sequences_of_w1.to_f)>0.5
78
+ end
79
+
80
+ def frequent_sequence?(w1,w2)
81
+ return false unless w2
82
+ frequent_straight_sequence?(w1,w2) && frequent_inverse_sequence?(w2,w1)
83
+ end
84
+
85
+ def group_words_in_terms(words)
86
+ # getNotSoGoodFieldName is not a term because
87
+ # notSoGoodFieldName is more frequently alone that preceded by get
88
+
89
+ return words if words.count==1
90
+ start_term = 0
91
+ end_term = 0
92
+ term = words[0]
93
+ while end_term < words.count && frequent_sequence?(words[end_term],words[end_term+1])
94
+ end_term += 1
95
+ term = @language_specific_logic.concat(term,words[end_term])
96
+ end
97
+ return [term] if end_term==(words.count-1)
98
+ [term] + group_words_in_terms(words[(end_term+1)..-1])
99
+ end
100
+
101
+ end
102
+
103
+ def self.values_map(model_node)
104
+ ser_model_node = LightModels::Serialization.jsonize_obj(model_node)
105
+ LightModels::QuerySerialized.collect_values_with_count(ser_model_node)
106
+ end
107
+
108
+ def self.terms_map(language_specific_logic,model_node,context=nil)
109
+ # context default to root
110
+ unless context
111
+ context = model_node
112
+ while context.eContainer
113
+ context = context.eContainer
114
+ end
115
+ end
116
+
117
+ # look into context to see how frequent are certain series of words,
118
+ # frequent series are recognized as composed terms
119
+ terms_breaker = TermsBreaker.from_context(language_specific_logic,context)
120
+
121
+ values_map = values_map(model_node)
122
+ terms_map = Hash.new {|h,k| h[k]=0}
123
+ values_map.each do |v,n|
124
+ terms_breaker.terms_in_value(v).each do |t|
125
+ terms_map[t] += n
126
+ end
127
+ end
128
+ terms_map
129
+ end
130
+
131
+ end
132
+
133
+ end
@@ -3,20 +3,30 @@
3
3
 
4
4
  module LightModels
5
5
 
6
- module Query
6
+ module QuerySerialized
7
7
 
8
8
  def self.rel_conts(root)
9
9
  root.keys.select {|k| k.start_with? 'relcont_'}
10
10
  end
11
11
 
12
12
  def self.rel_non_conts(root)
13
- root.keys.select {|k| k.start_with? 'relcont_'}
13
+ root.keys.select {|k| k.start_with? 'relnoncont_'}
14
14
  end
15
15
 
16
16
  def self.attrs(root)
17
17
  root.keys.select {|k| k.start_with? 'attr_'}
18
18
  end
19
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
+
20
30
  def self.values(root,feat)
21
31
  raw = root[feat]
22
32
  return [] if raw==nil
@@ -40,16 +50,6 @@ module Query
40
50
  end
41
51
  end
42
52
 
43
- def self.print_tree(root,depth=0)
44
- traverse(root) do |n,d|
45
- s = ""
46
- d.times { s = s + " " }
47
- s = s + n['type'] if n
48
- s = s + '<NIL>' unless n
49
- puts s
50
- end
51
- end
52
-
53
53
  end
54
54
 
55
55
  end
@@ -8,6 +8,34 @@ class << self
8
8
  attr_accessor :verbose
9
9
  end
10
10
 
11
+ def self.handle_serialized_models_in_dir(src,src_extension,error_handler=nil,model_handler,&model_creator)
12
+ puts "== #{src} ==" if LightModels::ModelBuilding.verbose
13
+ Dir["#{src}/*"].each do |fd|
14
+ if File.directory? fd
15
+ basename = File.basename(fd)
16
+ handle_serialized_models_in_dir("#{src}/#{basename}",src_extension,error_handler,model_handler,&model_creator)
17
+ else
18
+ if File.extname(fd)==".#{src_extension}"
19
+ handle_serialized_model_per_file(fd,error_handler,model_handler,&model_creator)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.handle_models_in_dir(src,src_extension,error_handler=nil,model_handler,&model_creator)
26
+ puts "== #{src} ==" if LightModels::ModelBuilding.verbose
27
+ Dir["#{src}/*"].each do |fd|
28
+ if File.directory? fd
29
+ basename = File.basename(fd)
30
+ handle_models_in_dir("#{src}/#{basename}",src_extension,error_handler,model_handler,&model_creator)
31
+ else
32
+ if File.extname(fd)==".#{src_extension}"
33
+ handle_model_per_file(fd,error_handler,model_handler,&model_creator)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
11
39
  def self.generate_models_in_dir(src,dest,src_extension,dest_extension,max_nesting=500,error_handler=nil,&model_creator)
12
40
  puts "== #{src} -> #{dest} ==" if LightModels::ModelBuilding.verbose
13
41
  Dir["#{src}/*"].each do |fd|
@@ -25,9 +53,46 @@ def self.generate_models_in_dir(src,dest,src_extension,dest_extension,max_nestin
25
53
  end
26
54
  end
27
55
 
56
+ def self.handle_model_per_file(src,error_handler=nil,model_handler,&models_generator)
57
+ puts "<Model from #{src}>" if LightModels::ModelBuilding.verbose
58
+
59
+ if error_handler
60
+ begin
61
+ m = models_generator.call(src)
62
+ model_handler.call(src,m)
63
+ rescue Exception => e
64
+ error_handler.call(src,e)
65
+ rescue
66
+ error_handler.call(src,nil)
67
+ end
68
+ else
69
+ m = models_generator.call(src)
70
+ model_handler.call(src,m)
71
+ end
72
+ end
73
+
74
+ def self.handle_serialized_model_per_file(src,error_handler=nil,model_handler,&models_generator)
75
+ puts "<Model from #{src}>" if LightModels::ModelBuilding.verbose
76
+
77
+ if error_handler
78
+ begin
79
+ m = models_generator.call(src)
80
+ model_handler.call(src,m)
81
+ rescue Exception => e
82
+ error_handler.call(src,e)
83
+ rescue
84
+ error_handler.call(src,nil)
85
+ end
86
+ else
87
+ m = models_generator.call(src)
88
+ model_handler.call(src,m)
89
+ end
90
+ end
91
+
92
+
28
93
  def self.generate_model_per_file(src,dest,max_nesting=500,error_handler=nil,&models_generator)
29
94
  if not File.exist? dest
30
- puts "<Model from #{src}>"
95
+ puts "<Model from #{src}>" if LightModels::ModelBuilding.verbose
31
96
 
32
97
  if error_handler
33
98
  begin
@@ -0,0 +1,30 @@
1
+ class Module
2
+
3
+ def simple_name
4
+ if (i = (r = name).rindex(':')) then r[0..i] = '' end
5
+ r
6
+ end
7
+
8
+ end
9
+
10
+ class String
11
+
12
+ def remove_postfix(postfix)
13
+ raise "'#{self}'' have not the right postfix '#{postfix}'" unless end_with?(postfix)
14
+ self[0..-(1+postfix.length)]
15
+ end
16
+
17
+ def remove_prefix(prefix)
18
+ raise "'#{self}'' have not the right prefix '#{prefix}'" unless start_with?(prefix)
19
+ self[prefix.length..-1]
20
+ end
21
+
22
+ def proper_capitalize
23
+ self[0, 1].upcase + self[1..-1]
24
+ end
25
+
26
+ def proper_uncapitalize
27
+ self[0, 1].downcase + self[1..-1]
28
+ end
29
+
30
+ end
@@ -0,0 +1,186 @@
1
+ require 'lightmodels/monkey_patching'
2
+
3
+ module LightModels
4
+
5
+ class ParsingError < Exception
6
+ attr_reader :node
7
+ attr_reader :line
8
+
9
+ def initialize(node,msg,line=nil)
10
+ @node = node
11
+ @msg = msg
12
+ @line = lin
13
+ end
14
+
15
+ def to_s
16
+ "#{@msg}, start line: #{@line}"
17
+ end
18
+
19
+ end
20
+
21
+ class UnknownNodeType < ParsingError
22
+
23
+ def initialize(node,line=nil,node_type=nil,where=nil)
24
+ super(node,"UnknownNodeType: type=#{node_type} , where: #{where}")
25
+ end
26
+
27
+ end
28
+
29
+ module ParserWrapper
30
+
31
+ @@verbose = false
32
+
33
+ JavaCollection = ::Java::JavaClass.for_name("java.util.Collection")
34
+
35
+ def adapter(model_class,ref)
36
+ if adapter_specific_class(model_class,ref)
37
+ adapter_specific_class(model_class,ref)
38
+ else
39
+ if model_class.superclass!=Object
40
+ adapter(model_class.superclass,ref)
41
+ else
42
+ nil
43
+ end
44
+ end
45
+ end
46
+
47
+ def reference_to_method(model_class,ref)
48
+ s = ref.name
49
+ #s = 'value' if s=='body'
50
+ adapted = adapter(model_class,ref)
51
+ s = adapted if adapted
52
+ s.to_sym
53
+ end
54
+
55
+ def attribute_to_method(model_class,att)
56
+ s = att.name
57
+ adapted = adapter(model_class,att)
58
+ s = adapted if adapted
59
+ s.to_sym
60
+ end
61
+
62
+ def assign_ref_to_model(model,ref,value)
63
+ return unless value==nil # we do not need to assign a nil...
64
+ if ref.many
65
+ adder_method = :"add#{ref.name.capitalize}"
66
+ value.each {|el| model.send(adder_method,node_to_model(el))}
67
+ else
68
+ setter_method = :"#{ref.name}="
69
+ raise "Trying to assign an array to a single property. Class #{model.class}, property #{ref.name}" if value.is_a?(::Array)
70
+ model.send(setter_method,node_to_model(value))
71
+ end
72
+ rescue Object => e
73
+ puts "Problem while assigning ref #{ref.name} (many? #{ref.many}) to #{model.class}. Value: #{value.class}"
74
+ puts "\t<<#{e}>>"
75
+ raise e
76
+ end
77
+
78
+ def assign_att_to_model(model,att,value)
79
+ if att.many
80
+ adder_method = :"add#{att.name.capitalize}"
81
+ value.each {|el| model.send(adder_method,el)}
82
+ else
83
+ setter_method = :"#{att.name}="
84
+ raise "Trying to assign an array to a single property. Class #{model.class}, property #{att.name}" if value.is_a?(::Array)
85
+ model.send(setter_method,value)
86
+ end
87
+ end
88
+
89
+ def populate_attr(node,att,model)
90
+ value = get_feature_value(node,att)
91
+ #puts "Value got for #{node.class} #{att} : #{value.class}"
92
+ # nil are ignored
93
+ model.send(:"#{att.name}=",value) if value!=nil
94
+ rescue Object => e
95
+ puts "Problem while populating attribute #{att.name} of #{model} from #{node}. Value: #{value}"
96
+ raise e
97
+ end
98
+
99
+ def populate_ref(node,ref,model)
100
+ log("populate ref #{ref.name}, node: #{node.class}, model: #{model.class}")
101
+ value = get_feature_value(node,ref)
102
+ log("\tvalue=#{value.class}")
103
+ if value!=nil
104
+ if value==node
105
+ puts "avoiding loop... #{ref.name}, class #{node.class}"
106
+ return
107
+ end
108
+ if JavaCollection.assignable_from?(value.java_class)
109
+ log("\tvalue is a collection")
110
+ capitalized_name = ref.name.proper_capitalize
111
+ value.each do |el|
112
+ unless el.respond_to?(:parent)
113
+ class << el
114
+ attr_accessor :parent
115
+ end
116
+ end
117
+ el.parent = node
118
+ model.send(:"add#{capitalized_name}",node_to_model(el))
119
+ end
120
+ else
121
+ log("\tvalue is not a collection")
122
+ unless value.respond_to?(:parent)
123
+ class << value
124
+ attr_accessor :parent
125
+ end
126
+ end
127
+ value.parent = node
128
+ model.send(:"#{ref.name}=",node_to_model(value))
129
+ end
130
+ end
131
+ end
132
+
133
+ def log(msg)
134
+ puts msg if @@verbose
135
+ end
136
+
137
+ def node_to_model(node)
138
+ log("node_to_model #{node.class}")
139
+ metaclass = get_corresponding_metaclass(node)
140
+ instance = metaclass.new
141
+ metaclass.ecore.eAllAttributes.each do |attr|
142
+ populate_attr(node,attr,instance)
143
+ end
144
+ metaclass.ecore.eAllReferences.each do |ref|
145
+ populate_ref(node,ref,instance)
146
+ end
147
+ instance
148
+ end
149
+
150
+ def transform_enum_values(value)
151
+ if value.respond_to?(:java_class) && value.java_class.enum?
152
+ value.name
153
+ else
154
+ value
155
+ end
156
+ end
157
+
158
+ def get_feature_value_through_getter(node,feat_name)
159
+ capitalized_name = feat_name.proper_capitalize
160
+ methods = [:"get#{capitalized_name}",:"is#{capitalized_name}"]
161
+
162
+ methods.each do |m|
163
+ if node.respond_to?(m)
164
+ begin
165
+ return transform_enum_values(node.send(m))
166
+ rescue Object => e
167
+ raise "Problem invoking #{m} on #{node.class}: #{e}"
168
+ end
169
+ end
170
+ end
171
+ raise "how should I get this... #{feat_name} on #{node.class}. It does not respond to #{methods}"
172
+ end
173
+
174
+ def get_feature_value(node,feat)
175
+ adapter = adapter(node.class,feat)
176
+ if adapter
177
+ #puts "Using adapter for #{node.class} #{feat_name}"
178
+ adapter[:adapter].call(node)
179
+ else
180
+ get_feature_value_through_getter(node,feat.name)
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ end