EFL 1.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/README.txt +36 -0
- data/lib/EFL.rb +494 -0
- data/lib/EFL_array.rb +20 -0
- data/lib/EFL_errors.rb +48 -0
- data/lib/EFL_hash.rb +18 -0
- data/lib/EFL_production.rb +49 -0
- data/lib/EFL_regexp.rb +112 -0
- data/lib/EFL_regexp_generator.rb +70 -0
- data/lib/EFL_substitution.rb +221 -0
- data/lib/EFL_syntactic_sugar.rb +67 -0
- data/lib/Hash Doc.doc +0 -0
- data/lib/Limitaciones.txt +3 -0
- data/lib/doc/classes/Generator.html +634 -0
- data/lib/doc/classes/Generator.src/M000008.html +18 -0
- data/lib/doc/classes/Generator.src/M000009.html +18 -0
- data/lib/doc/classes/Generator.src/M000010.html +18 -0
- data/lib/doc/classes/Generator.src/M000011.html +18 -0
- data/lib/doc/classes/Generator.src/M000012.html +18 -0
- data/lib/doc/classes/Generator.src/M000013.html +18 -0
- data/lib/doc/classes/Generator.src/M000014.html +18 -0
- data/lib/doc/classes/Generator.src/M000015.html +18 -0
- data/lib/doc/classes/Generator.src/M000016.html +28 -0
- data/lib/doc/classes/Generator.src/M000017.html +24 -0
- data/lib/doc/classes/Generator.src/M000018.html +157 -0
- data/lib/doc/classes/Generator.src/M000019.html +25 -0
- data/lib/doc/classes/Generator.src/M000020.html +30 -0
- data/lib/doc/classes/Generator.src/M000021.html +32 -0
- data/lib/doc/classes/Generator.src/M000022.html +22 -0
- data/lib/doc/classes/Generator.src/M000023.html +18 -0
- data/lib/doc/classes/Generator.src/M000024.html +27 -0
- data/lib/doc/classes/Generator.src/M000025.html +22 -0
- data/lib/doc/classes/Generator.src/M000026.html +18 -0
- data/lib/doc/classes/Generator.src/M000027.html +27 -0
- data/lib/doc/classes/Regexp.html +271 -0
- data/lib/doc/classes/Regexp.src/M000028.html +37 -0
- data/lib/doc/classes/Regexp.src/M000029.html +29 -0
- data/lib/doc/classes/Regexp.src/M000030.html +32 -0
- data/lib/doc/created.rid +1 -0
- data/lib/doc/files/EFL_rb.html +147 -0
- data/lib/doc/files/EFL_regexp_generator_rb.html +242 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000003.html +27 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000004.html +27 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000005.html +19 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000006.html +20 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000007.html +19 -0
- data/lib/doc/files/EFL_regexp_rb.html +139 -0
- data/lib/doc/files/EFL_syntactic_sugar_rb.html +208 -0
- data/lib/doc/files/EFL_syntactic_sugar_rb.src/M000001.html +29 -0
- data/lib/doc/files/EFL_syntactic_sugar_rb.src/M000002.html +19 -0
- data/lib/doc/fr_class_index.html +28 -0
- data/lib/doc/fr_file_index.html +30 -0
- data/lib/doc/fr_method_index.html +56 -0
- data/lib/doc/index.html +24 -0
- data/tests/Add_Sup_1.rb +223 -0
- data/tests/Add_Sup_1.rb.bak +223 -0
- data/tests/Add_Sup_1_NI.rb +25 -0
- data/tests/Add_Sup_2.rb +142 -0
- data/tests/Add_Sup_2.rb.bak +140 -0
- data/tests/All.rb +2 -0
- data/tests/All_1.rb +7 -0
- data/tests/All_2.rb +7 -0
- data/tests/All_2.rb.bak +5 -0
- data/tests/BeforeAfter.rb +83 -0
- data/tests/Bloques.rb +34 -0
- data/tests/Bloques.rb.bak +34 -0
- data/tests/Complementary.rb +144 -0
- data/tests/ComplementaryZoom.rb +78 -0
- data/tests/Del.rb +126 -0
- data/tests/Dup.rb +55 -0
- data/tests/Dup.rb.bak +54 -0
- data/tests/Error.rb +11 -0
- data/tests/ErrorArgClass.rb +169 -0
- data/tests/ErrorArgClass.rb.bak +158 -0
- data/tests/ErrorCollision.rb +218 -0
- data/tests/ErrorCollision.rb.bak +219 -0
- data/tests/ErrorWithoutDeclaration.rb +60 -0
- data/tests/ErrorWithoutDeclaration.rb.bak +60 -0
- data/tests/Extract.rb +56 -0
- data/tests/ExtractDollar.rb +17 -0
- data/tests/HashTest.rb +54 -0
- data/tests/HashTest.rb.bak +54 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/List.cpp +75 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/ListTransformer.rb +69 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/ListTransformer.rb.bak +100 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/ejecutame.bat +1 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/outDir/MyClassList.cpp +75 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/runme.bat +1 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/specification1.txt +5 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/specification2.txt +3 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/specification3.txt +5 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/List.cpp +75 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/ListTransformer.rb +58 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/ListTransformer.rb.bak +57 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/ejecutame.bat +1 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/outDir/MyClassList.cpp +75 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/outDir/NewClassList.cpp +75 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/specification1.txt +5 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/specification1.txt.bak +5 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/specification2.txt +3 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/specification3.txt +5 -0
- data/tests/Minus.rb +89 -0
- data/tests/Plus.rb.bak +48 -0
- data/tests/REVit.rb +84 -0
- data/tests/RenameTest.rb +46 -0
- data/tests/RenameTest.rb.bak +46 -0
- data/tests/SubCrash.rb +26 -0
- data/tests/SubList.rb.bak +43 -0
- data/tests/archAuxiliares/1.txt +328 -0
- data/tests/archAuxiliares/2.txt +328 -0
- data/tests/archAuxiliares/Bloques/s1.txt +328 -0
- data/tests/archAuxiliares/Copia de Matriz.java +19 -0
- data/tests/archAuxiliares/Gen/Tesis_156_1.lgi +10 -0
- data/tests/archAuxiliares/Gen/Tesis_156_2.lgi +10 -0
- data/tests/archAuxiliares/Gen/t01.txt +328 -0
- data/tests/archAuxiliares/Gen/t01.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t02.txt +328 -0
- data/tests/archAuxiliares/Gen/t02.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t03.txt +328 -0
- data/tests/archAuxiliares/Gen/t03.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t04.txt +328 -0
- data/tests/archAuxiliares/Gen/t04.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t1.txt +328 -0
- data/tests/archAuxiliares/Gen/t1.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t2.txt +328 -0
- data/tests/archAuxiliares/Gen/t2.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t5.txt +328 -0
- data/tests/archAuxiliares/Gen/t9.txt +328 -0
- data/tests/archAuxiliares/Gen/t9.txt.bak +328 -0
- data/tests/archAuxiliares/GenTesis_156_1.lgi +10 -0
- data/tests/archAuxiliares/Matriz.java +74 -0
- data/tests/archAuxiliares/MatrizOut.java +74 -0
- data/tests/archAuxiliares/MatrizOut10.java +68 -0
- data/tests/archAuxiliares/MatrizOut11.java +86 -0
- data/tests/archAuxiliares/MatrizOut2.java +74 -0
- data/tests/archAuxiliares/MatrizOut3.java +74 -0
- data/tests/archAuxiliares/MatrizOut4.java +74 -0
- data/tests/archAuxiliares/MatrizOut5.java +21 -0
- data/tests/archAuxiliares/MatrizOut6.java +21 -0
- data/tests/archAuxiliares/MatrizOut7.java +21 -0
- data/tests/archAuxiliares/MatrizOut8.java +16 -0
- data/tests/archAuxiliares/MatrizOut9.java +86 -0
- data/tests/archAuxiliares/MatrizOut_9.java +86 -0
- data/tests/archAuxiliares/Matriz_1.java +74 -0
- data/tests/archAuxiliares/Matriz_10.java +68 -0
- data/tests/archAuxiliares/Matriz_11.java +86 -0
- data/tests/archAuxiliares/Matriz_2.java +74 -0
- data/tests/archAuxiliares/Matriz_3.java +74 -0
- data/tests/archAuxiliares/Matriz_4.java +74 -0
- data/tests/archAuxiliares/Matriz_5.java +21 -0
- data/tests/archAuxiliares/Matriz_6.java +21 -0
- data/tests/archAuxiliares/Matriz_7.java +21 -0
- data/tests/archAuxiliares/Matriz_8.java +16 -0
- data/tests/archAuxiliares/Matriz_9.java +86 -0
- data/tests/archAuxiliares/Matriz_N_1.java +21 -0
- data/tests/archAuxiliares/Matriz_N_2.java +91 -0
- data/tests/archAuxiliares/N1.txt +18 -0
- data/tests/archAuxiliares/N1_EXPECTED.txt +18 -0
- data/tests/archAuxiliares/N1_OUT.txt +18 -0
- data/tests/archAuxiliares/N2_EXPECTED.txt +18 -0
- data/tests/archAuxiliares/N2_OUT.txt +18 -0
- data/tests/archAuxiliares/N3.txt +23 -0
- data/tests/archAuxiliares/N3_EXPECTED.txt +22 -0
- data/tests/archAuxiliares/N3_OUT.txt +22 -0
- data/tests/archAuxiliares/N4_EXPECTED.txt +10 -0
- data/tests/archAuxiliares/N4_OUT.txt +10 -0
- data/tests/archAuxiliares/N5_OUT.txt +18 -0
- data/tests/archAuxiliares/N6_OUT.txt +18 -0
- data/tests/archAuxiliares/PedidorTerceroWS.jsp +142 -0
- data/tests/archAuxiliares/Tesis_156.lgi +7 -0
- data/tests/archAuxiliares/aspectgen.rb +328 -0
- data/tests/archAuxiliares/aspectgenCopy.rb +328 -0
- data/tests/archAuxiliares/extract_dollar.txt +1 -0
- data/tests/archAuxiliares/minus.txt +26 -0
- data/tests/archAuxiliares/minus_expected_1.txt +26 -0
- data/tests/archAuxiliares/minus_expected_2.txt +26 -0
- data/tests/archAuxiliares/minus_out_1.txt +26 -0
- data/tests/archAuxiliares/minus_out_2.txt +26 -0
- data/tests/archAuxiliares/p1.txt +328 -0
- data/tests/archAuxiliares/p2.txt +328 -0
- data/tests/archAuxiliares/s1.txt +328 -0
- data/tests/archAuxiliares/s2.txt +328 -0
- data/tests/archAuxiliares/s3.txt +328 -0
- data/tests/archAuxiliares/s4.txt +328 -0
- data/tests/archAuxiliares/s5.txt +328 -0
- data/tests/archAuxiliares/s7.txt +328 -0
- data/tests/archAuxiliares/s8.txt +328 -0
- data/tests/archAuxiliares/s9.txt +328 -0
- data/tests/archAuxiliares/text.txt +1 -0
- data/tests/delay.rb +33 -0
- data/tests/delay.rb.bak +33 -0
- data/tests/satisfy.rb +44 -0
- data/tests/satisfy.rb.bak +34 -0
- metadata +252 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# Author:: Ruben Heradio Gil (mailto:rheradio@lsi.uned.es)
|
|
2
|
+
|
|
3
|
+
#Auxiliar AspectGen class that represents a Pointcut
|
|
4
|
+
class Pointcut < Regexp
|
|
5
|
+
#Pointcut name (a String)
|
|
6
|
+
attr_accessor :name
|
|
7
|
+
#Pointcut value (a Regexp)
|
|
8
|
+
attr_accessor :regExp
|
|
9
|
+
#Pointcut scope ('local' or 'global')
|
|
10
|
+
attr_accessor :scope
|
|
11
|
+
|
|
12
|
+
# * 'name' = Pointcut name (a String)
|
|
13
|
+
# * 'regExp' = Pointcut value (a Regexp)
|
|
14
|
+
# * 'scope' = Pointcut scope ('local' or 'global')
|
|
15
|
+
def initialize(name, regExp, scope='local')
|
|
16
|
+
raise "First argument of Pointcut constructor must be a String" if !name.kind_of?(String)
|
|
17
|
+
raise "Second argument of Pointcut constructor must be a Regular Expression" if !regExp.kind_of?(Regexp)
|
|
18
|
+
raise "Pointcut scope must be 'local' or 'global'" if (scope != 'local') and
|
|
19
|
+
(scope != 'global')
|
|
20
|
+
super(regExp)
|
|
21
|
+
@name = name
|
|
22
|
+
@regExp = regExp
|
|
23
|
+
@scope = scope
|
|
24
|
+
end #initialize
|
|
25
|
+
|
|
26
|
+
def clone
|
|
27
|
+
result = Pointcut.new(@name.clone, @regExp.clone, @scope.clone)
|
|
28
|
+
end #clone
|
|
29
|
+
|
|
30
|
+
#Determine if two Pointcuts ('self' and 'pointcut') applied over the same input file ('fin') go crash
|
|
31
|
+
def crash?(pointcut, fin)
|
|
32
|
+
|
|
33
|
+
raise "First argument of Pointcut#crash? must be a Pointcut" if !pointcut.kind_of?(Pointcut)
|
|
34
|
+
# crash? inner auxiliar method that determines if two local Pointcuts ('pointcut1' and 'pointcut2') applied over the String tr' go crash
|
|
35
|
+
def crashAux1?(pointcut1, pointcut2, str)
|
|
36
|
+
position1 = str =~ pointcut1
|
|
37
|
+
match1 = $&
|
|
38
|
+
position2 = str =~ pointcut2
|
|
39
|
+
match2 = $&
|
|
40
|
+
return false if (position1 == nil) or (position2 == nil)
|
|
41
|
+
if (position1 <= position2)
|
|
42
|
+
return true if (position1 + match1.length - 1) >= position2
|
|
43
|
+
else
|
|
44
|
+
return true if (position2 + match2.length - 1) >= position1
|
|
45
|
+
end #if
|
|
46
|
+
return false
|
|
47
|
+
end #crashAux1?
|
|
48
|
+
|
|
49
|
+
# crash? inner auxiliar method that determines if a global Pointcut ('globalPointcut') and a local
|
|
50
|
+
# Pointcut ('localPointcut') applied over the String tr' go crash
|
|
51
|
+
def crashAux2?(globalPointcut, localPointcut, str)
|
|
52
|
+
crash = false
|
|
53
|
+
while (str.index(globalPointcut) != nil) and (crash == false)
|
|
54
|
+
crash = crashAux1?(globalPointcut, localPointcut, str)
|
|
55
|
+
str =~ globalPointcut
|
|
56
|
+
str = $'
|
|
57
|
+
end #while
|
|
58
|
+
return crash
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
crash = false
|
|
62
|
+
File.open(fin) { |f|
|
|
63
|
+
fcode = f.read
|
|
64
|
+
if (self.scope == 'local') and (pointcut.scope == 'local')
|
|
65
|
+
crash = crashAux1?(self, pointcut, fcode)
|
|
66
|
+
elsif (self.scope == 'local') and (pointcut.scope == 'global')
|
|
67
|
+
crash = crashAux2?(pointcut, self, fcode)
|
|
68
|
+
elsif (self.scope == 'global') and (pointcut.scope == 'local')
|
|
69
|
+
crash = crashAux2?(self, pointcut, fcode)
|
|
70
|
+
else #if (self.scope == 'global') and (pointcut.scope == 'global')
|
|
71
|
+
crash = ( crashAux2?(self, pointcut, fcode) or
|
|
72
|
+
crashAux2?(pointcut, self, fcode) )
|
|
73
|
+
end #if
|
|
74
|
+
}
|
|
75
|
+
return crash
|
|
76
|
+
end #crash?
|
|
77
|
+
|
|
78
|
+
end #Pointcut
|
|
79
|
+
|
|
80
|
+
#Auxiliar AspectGen class that represents an Advice
|
|
81
|
+
class Advice
|
|
82
|
+
#Advice name (a String)
|
|
83
|
+
attr_accessor :name
|
|
84
|
+
#Name of the Pointcut associated with the Advice (a String)
|
|
85
|
+
attr_accessor :pointcut
|
|
86
|
+
#Advice value. String that will replace the text matched by the Pointcut value
|
|
87
|
+
attr_accessor :subText
|
|
88
|
+
|
|
89
|
+
# * 'name' = Advice name (a String)
|
|
90
|
+
# * 'pointcut' = Name of the Pointcut associated with the Advice (a String)
|
|
91
|
+
# * 'subtext' = Advice value. String that will replace the text matched by the Pointcut value
|
|
92
|
+
def initialize(name, pointcut, subText)
|
|
93
|
+
|
|
94
|
+
raise "Arguments of Advice constructor must be a String" if (!name.kind_of?(String)) or
|
|
95
|
+
(!pointcut.kind_of?(String)) or (!subText.kind_of?(String))
|
|
96
|
+
@name = name
|
|
97
|
+
@pointcut = pointcut
|
|
98
|
+
@subText = subText
|
|
99
|
+
end #initialize
|
|
100
|
+
|
|
101
|
+
def clone
|
|
102
|
+
result = Advice.new(@name.clone, @pointcut.clone, @subText.clone)
|
|
103
|
+
end #clone
|
|
104
|
+
|
|
105
|
+
end #Advice
|
|
106
|
+
|
|
107
|
+
#Auxiliar AspectGen class that represents a Generation
|
|
108
|
+
class Generation
|
|
109
|
+
#Generation name (a String)
|
|
110
|
+
attr_accessor :name
|
|
111
|
+
#Generation sterotype file (a String)
|
|
112
|
+
attr_accessor :fin
|
|
113
|
+
#Generation output file (a String)
|
|
114
|
+
attr_accessor :fout
|
|
115
|
+
#List of Advice names associated with the Generation (a String List)
|
|
116
|
+
attr_accessor :adviceList
|
|
117
|
+
|
|
118
|
+
# * 'name' = Generation name (a String)
|
|
119
|
+
# * 'fin' = Generation sterotype file (a String)
|
|
120
|
+
# * 'fout' = Generation output file (a String)
|
|
121
|
+
# * 'adviceList' = List of Advice names associated with the Generation (a String List)
|
|
122
|
+
def initialize(name, fin, fout, adviceList = [])
|
|
123
|
+
raise "First argument of Generation constructor must be a String" if !name.kind_of?(String)
|
|
124
|
+
raise "Fourth argument of Generation constructor must be a String List" if !adviceList.kind_of?(Array)
|
|
125
|
+
adviceList.each { |a|
|
|
126
|
+
raise "Fourth argument of Generation constructor must be a String List" if !a.kind_of?(String)
|
|
127
|
+
} #adviceList.each
|
|
128
|
+
@name = name
|
|
129
|
+
@fin = fin
|
|
130
|
+
@fout = fout
|
|
131
|
+
@adviceList = adviceList
|
|
132
|
+
end #initialize
|
|
133
|
+
|
|
134
|
+
def clone
|
|
135
|
+
result = Generation.new(@name, @fin, @fout, @adviceList.clone)
|
|
136
|
+
end #clone
|
|
137
|
+
|
|
138
|
+
end #Generation
|
|
139
|
+
|
|
140
|
+
class AspectGen
|
|
141
|
+
|
|
142
|
+
# Counter used by cloneSuffix
|
|
143
|
+
@@suffixes = 0
|
|
144
|
+
|
|
145
|
+
# Protected Binding object that describes the variable and method bindings at the point of constructor call
|
|
146
|
+
attr_accessor :args
|
|
147
|
+
# Protected hash table that stores the Pointcuts of 'self'
|
|
148
|
+
attr_accessor :pointcutHash
|
|
149
|
+
# Protected hash table that stores the Advices of 'self'
|
|
150
|
+
attr_accessor :adviceHash
|
|
151
|
+
# Protected hash table that stores the Generations of 'self'
|
|
152
|
+
attr_accessor :generationHash
|
|
153
|
+
|
|
154
|
+
#@pointcutHash = {}
|
|
155
|
+
@adviceHash = {}
|
|
156
|
+
@generationHash = {}
|
|
157
|
+
|
|
158
|
+
#Esto habr�a que verlo
|
|
159
|
+
protected :pointcutHash, :adviceHash, :generationHash
|
|
160
|
+
|
|
161
|
+
def clone
|
|
162
|
+
result = AspectGen.new(@args)
|
|
163
|
+
result.pointcutHash = @pointcutHash.clone
|
|
164
|
+
result.adviceHash = @adviceHash.clone
|
|
165
|
+
result.generationHash = @generationHash.clone
|
|
166
|
+
return result
|
|
167
|
+
end #clone
|
|
168
|
+
|
|
169
|
+
# + auxiliar method that produces a clone where all elements (Pointcuts, Advices and Generations) have been added
|
|
170
|
+
# a numerical suffix (@@suffixes is a private class attribute that will be incremented everytime method '+' is
|
|
171
|
+
# called).
|
|
172
|
+
# For example, if @suffixes value is 8, then
|
|
173
|
+
#
|
|
174
|
+
# pointcut('p1', /expReg/, 'global') -> pointcut('p1_8', /expReg/, 'global')
|
|
175
|
+
def cloneSuffix
|
|
176
|
+
result = self.clone
|
|
177
|
+
@generationHash.each { |k, g|
|
|
178
|
+
result.generationHash[k + '_' + @@suffixes.to_s] =
|
|
179
|
+
@generationHash[k]
|
|
180
|
+
result.generationHash[k + '_' + @@suffixes.to_s].name +=
|
|
181
|
+
'_' + @@suffixes.to_s
|
|
182
|
+
result.generationHash[k + '_' + @@suffixes.to_s].adviceList.collect! { |e|
|
|
183
|
+
e + '_' + @@suffixes.to_s
|
|
184
|
+
} #collect
|
|
185
|
+
result.generationHash.delete(k)
|
|
186
|
+
} #@generationHash.each
|
|
187
|
+
@adviceHash.each { |k, g|
|
|
188
|
+
result.adviceHash[k + '_' + @@suffixes.to_s] =
|
|
189
|
+
@adviceHash[k]
|
|
190
|
+
result.adviceHash[k + '_' + @@suffixes.to_s].name +=
|
|
191
|
+
'_' + @@suffixes.to_s
|
|
192
|
+
result.adviceHash[k + '_' + @@suffixes.to_s].pointcut +=
|
|
193
|
+
'_' + @@suffixes.to_s
|
|
194
|
+
result.adviceHash.delete(k)
|
|
195
|
+
} #@generationHash.each
|
|
196
|
+
@pointcutHash.each { |k, g|
|
|
197
|
+
result.pointcutHash[k + '_' + @@suffixes.to_s] =
|
|
198
|
+
@pointcutHash[k]
|
|
199
|
+
result.pointcutHash[k + '_' + @@suffixes.to_s].name +=
|
|
200
|
+
'_' + @@suffixes.to_s
|
|
201
|
+
result.pointcutHash.delete(k)
|
|
202
|
+
} #@generationHash.each
|
|
203
|
+
@@suffixes += 1
|
|
204
|
+
return result
|
|
205
|
+
end #cloneSuffix
|
|
206
|
+
|
|
207
|
+
# Adds a new Pointcut to 'self'
|
|
208
|
+
# * 'name' = Pointcut name (a String)
|
|
209
|
+
# * 'regExp' = Pointcut value (a Regexp)
|
|
210
|
+
# * 'scope' = Pointcut scope ('local' or 'global')
|
|
211
|
+
def pointcut(name, regExp, scope = 'local')
|
|
212
|
+
@pointcutHash = {} unless @pointcutHash
|
|
213
|
+
@pointcutHash[name] = Pointcut.new(name, regExp, scope)
|
|
214
|
+
end #pointcut
|
|
215
|
+
|
|
216
|
+
# Adds a new Advice to 'self'
|
|
217
|
+
# * 'name' = Advice name (a String)
|
|
218
|
+
# * 'pointcut' = Name of the Pointcut associated with the Advice (a String)
|
|
219
|
+
# * 'subtext' = Advice value. String that will replace the text matched by the Pointcut value
|
|
220
|
+
def advice(name, pointcut, subText)
|
|
221
|
+
raise "Pointcut referenced by AspectGen#advice doesn't exist" if pointcutHash[pointcut] == nil
|
|
222
|
+
@adviceHash = {} unless @adviceHash
|
|
223
|
+
@adviceHash[name] = Advice.new(name, pointcut, subText)
|
|
224
|
+
end #advice
|
|
225
|
+
|
|
226
|
+
# Adds a new Generation to 'self'
|
|
227
|
+
# * 'name' = Generation name (a String)
|
|
228
|
+
# * 'fin' = Generation sterotype file (a String)
|
|
229
|
+
# * 'fout' = Generation output file (a String)
|
|
230
|
+
# * 'adviceList' = List of Advice names associated with the Generation (a String List)
|
|
231
|
+
def generation(name, fin, fout, adviceList = [])
|
|
232
|
+
@generationHash = {} unless @generationHash
|
|
233
|
+
|
|
234
|
+
raise "Fourth argument of Generation constructor must be a String List" if !adviceList.kind_of?(Array)
|
|
235
|
+
adviceList.each { |a|
|
|
236
|
+
raise "Advice referenced by AspectGen#generation doesn't exist" if adviceHash[a] == nil
|
|
237
|
+
} #adviceList.each
|
|
238
|
+
adviceListAux = adviceList
|
|
239
|
+
adviceList.each { |a1|
|
|
240
|
+
adviceListAux -= [a1]
|
|
241
|
+
adviceListAux.each { |a2|
|
|
242
|
+
if @pointcutHash[@adviceHash[a1].pointcut].crash?(@pointcutHash[@adviceHash[a2].pointcut], fin)
|
|
243
|
+
raise 'several pointcuts are crashing'
|
|
244
|
+
end #if
|
|
245
|
+
} #adviceListAux.each
|
|
246
|
+
} #adviceList.each
|
|
247
|
+
generationHash.each { |k, g|
|
|
248
|
+
raise "There is another generation with the same output file" if (fout == g.fout) and (name != g.name)
|
|
249
|
+
} #generationHash.each
|
|
250
|
+
@generationHash[name] =
|
|
251
|
+
Generation.new(name, fin, fout, adviceList)
|
|
252
|
+
end #generation
|
|
253
|
+
|
|
254
|
+
# Executes all Generations of 'self'
|
|
255
|
+
def generate()
|
|
256
|
+
@generationHash.each_value { |g|
|
|
257
|
+
File.open(g.fin) {|fin|
|
|
258
|
+
stereotypeCode = fin.read
|
|
259
|
+
g.adviceList.each {|adviceKey|
|
|
260
|
+
if @pointcutHash[@adviceHash[adviceKey].pointcut].scope == 'global'
|
|
261
|
+
stereotypeCode.gsub!(@pointcutHash[@adviceHash[adviceKey].pointcut],
|
|
262
|
+
@adviceHash[adviceKey].subText)
|
|
263
|
+
|
|
264
|
+
else
|
|
265
|
+
stereotypeCode.sub!(@pointcutHash[@adviceHash[adviceKey].pointcut],
|
|
266
|
+
@adviceHash[adviceKey].subText)
|
|
267
|
+
end #if
|
|
268
|
+
} #g.adviceList.each
|
|
269
|
+
File.open(g.fout, "w+") {|fout|
|
|
270
|
+
fout.write(stereotypeCode)
|
|
271
|
+
} #File.open(g.fout, "w+")
|
|
272
|
+
} #File.open(g.fin)
|
|
273
|
+
} #@generationHash.each
|
|
274
|
+
end #generate
|
|
275
|
+
|
|
276
|
+
# Combines two AspectGen objects ('self' and 'aspectGen'). It can raise exceptions when:
|
|
277
|
+
# * Several Generations have the same output file but different stereotype files.
|
|
278
|
+
# * Several Generations have Pointcuts wich overlap ("crash")
|
|
279
|
+
def +(aspectGen)
|
|
280
|
+
raise "Argument of AspectGen#+ must be a AspectGen" if !aspectGen.kind_of?(AspectGen)
|
|
281
|
+
a1 = self.cloneSuffix
|
|
282
|
+
a2 = aspectGen.cloneSuffix
|
|
283
|
+
a1.generationHash.each { |k1, g1|
|
|
284
|
+
a2.generationHash.each { |k2, g2|
|
|
285
|
+
if g1.fout == g2.fout
|
|
286
|
+
File.open(g1.fin) {|fin1|
|
|
287
|
+
stereotypeCode1 = fin1.read
|
|
288
|
+
File.open(g2.fin) {|fin2|
|
|
289
|
+
stereotypeCode2 = fin2.read
|
|
290
|
+
if stereotypeCode1 != stereotypeCode2
|
|
291
|
+
raise "Two generations with the same 'generation file' but different 'stereotype files'"
|
|
292
|
+
else
|
|
293
|
+
g1.adviceList.each {|ad1|
|
|
294
|
+
g2.adviceList.each {|ad2|
|
|
295
|
+
if a1.pointcutHash[a1.adviceHash[ad1].pointcut].crash?(
|
|
296
|
+
a2.pointcutHash[a2.adviceHash[ad2].pointcut], g1.fin)
|
|
297
|
+
raise 'several pointcuts are crashing'
|
|
298
|
+
end #if
|
|
299
|
+
} #g2.adviceList
|
|
300
|
+
} #g1.adviceList
|
|
301
|
+
g1.adviceList += g2.adviceList
|
|
302
|
+
a2.generationHash.delete(k2)
|
|
303
|
+
end #if
|
|
304
|
+
} #File.open(g2.fin)
|
|
305
|
+
} #File.open(g1.fin)
|
|
306
|
+
end #if
|
|
307
|
+
} #a2.generationHash.each
|
|
308
|
+
} #a1.generationHash.each
|
|
309
|
+
a1.generationHash.update(a2.generationHash)
|
|
310
|
+
a1.adviceHash.update(a2.adviceHash)
|
|
311
|
+
a1.pointcutHash.update(a2.pointcutHash)
|
|
312
|
+
return a1
|
|
313
|
+
end #+
|
|
314
|
+
|
|
315
|
+
def AspectGen.init(*ids)
|
|
316
|
+
# Falta gestion de errores
|
|
317
|
+
for id in ids
|
|
318
|
+
id_value = eval(id.id2name, @args)
|
|
319
|
+
eval "@#{id.id2name} = id_value"
|
|
320
|
+
end #for
|
|
321
|
+
yield if block_given?
|
|
322
|
+
end #interface
|
|
323
|
+
|
|
324
|
+
end #AspectGen
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# Author:: Ruben Heradio Gil (mailto:rheradio@lsi.uned.es)
|
|
2
|
+
|
|
3
|
+
#Auxiliar AspectGen class that represents a PTO DE CORTE!!!!
|
|
4
|
+
class PTO DE CORTE!!!! < Regexp
|
|
5
|
+
#PTO DE CORTE!!!! NOMBRE!!!! (a String)
|
|
6
|
+
attr_accessor :NOMBRE!!!!
|
|
7
|
+
#PTO DE CORTE!!!! value (a Regexp)
|
|
8
|
+
attr_accessor :regExp
|
|
9
|
+
#PTO DE CORTE!!!! scope ('local' or 'global')
|
|
10
|
+
attr_accessor :scope
|
|
11
|
+
|
|
12
|
+
# * 'NOMBRE!!!!' = PTO DE CORTE!!!! NOMBRE!!!! (a String)
|
|
13
|
+
# * 'regExp' = PTO DE CORTE!!!! value (a Regexp)
|
|
14
|
+
# * 'scope' = PTO DE CORTE!!!! scope ('local' or 'global')
|
|
15
|
+
def CONSTRUCTORRR!!!!(NOMBRE!!!!, regExp, scope='local')
|
|
16
|
+
LANZAAL!!!! "First argument of PTO DE CORTE!!!! constructor must be a String" if !NOMBRE!!!!.kind_of?(String)
|
|
17
|
+
LANZAAL!!!! "Second argument of PTO DE CORTE!!!! constructor must be a Regular Expression" if !regExp.kind_of?(Regexp)
|
|
18
|
+
LANZAAL!!!! "PTO DE CORTE!!!! scope must be 'local' or 'global'" if (scope != 'local') and
|
|
19
|
+
(scope != 'global')
|
|
20
|
+
super(regExp)
|
|
21
|
+
@NOMBRE!!!! = NOMBRE!!!!
|
|
22
|
+
@regExp = regExp
|
|
23
|
+
@scope = scope
|
|
24
|
+
end #initialize
|
|
25
|
+
|
|
26
|
+
def clone
|
|
27
|
+
result = PTO DE CORTE!!!!.new(@NOMBRE!!!!.clone, @regExp.clone, @scope.clone)
|
|
28
|
+
end #clone
|
|
29
|
+
|
|
30
|
+
#Determine if two PTO DE CORTE!!!!s ('self' and 'PTO DE CORTE!!!!') applied over the same input file ('fin') go crash
|
|
31
|
+
def crash?(PTO DE CORTE!!!!, fin)
|
|
32
|
+
|
|
33
|
+
LANZAAL!!!! "First argument of PTO DE CORTE!!!!#crash? must be a PTO DE CORTE!!!!" if !PTO DE CORTE!!!!.kind_of?(PTO DE CORTE!!!!)
|
|
34
|
+
# crash? inner auxiliar method that determines if two local PTO DE CORTE!!!!s ('PTO DE CORTE!!!!1' and 'PTO DE CORTE!!!!2') applied over the String tr' go crash
|
|
35
|
+
def crashAux1?(PTO DE CORTE!!!!1, PTO DE CORTE!!!!2, str)
|
|
36
|
+
position1 = str =~ PTO DE CORTE!!!!1
|
|
37
|
+
match1 = $&
|
|
38
|
+
position2 = str =~ PTO DE CORTE!!!!2
|
|
39
|
+
match2 = $&
|
|
40
|
+
return false if (position1 == nil) or (position2 == nil)
|
|
41
|
+
if (position1 <= position2)
|
|
42
|
+
return true if (position1 + match1.length - 1) >= position2
|
|
43
|
+
else
|
|
44
|
+
return true if (position2 + match2.length - 1) >= position1
|
|
45
|
+
end #if
|
|
46
|
+
return false
|
|
47
|
+
end #crashAux1?
|
|
48
|
+
|
|
49
|
+
# crash? inner auxiliar method that determines if a global PTO DE CORTE!!!! ('globalPTO DE CORTE!!!!') and a local
|
|
50
|
+
# PTO DE CORTE!!!! ('localPTO DE CORTE!!!!') applied over the String tr' go crash
|
|
51
|
+
def crashAux2?(globalPTO DE CORTE!!!!, localPTO DE CORTE!!!!, str)
|
|
52
|
+
crash = false
|
|
53
|
+
while (str.index(globalPTO DE CORTE!!!!) != nil) and (crash == false)
|
|
54
|
+
crash = crashAux1?(globalPTO DE CORTE!!!!, localPTO DE CORTE!!!!, str)
|
|
55
|
+
str =~ globalPTO DE CORTE!!!!
|
|
56
|
+
str = $'
|
|
57
|
+
end #while
|
|
58
|
+
return crash
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
crash = false
|
|
62
|
+
File.open(fin) { |f|
|
|
63
|
+
fcode = f.read
|
|
64
|
+
if (self.scope == 'local') and (PTO DE CORTE!!!!.scope == 'local')
|
|
65
|
+
crash = crashAux1?(self, PTO DE CORTE!!!!, fcode)
|
|
66
|
+
elsif (self.scope == 'local') and (PTO DE CORTE!!!!.scope == 'global')
|
|
67
|
+
crash = crashAux2?(PTO DE CORTE!!!!, self, fcode)
|
|
68
|
+
elsif (self.scope == 'global') and (PTO DE CORTE!!!!.scope == 'local')
|
|
69
|
+
crash = crashAux2?(self, PTO DE CORTE!!!!, fcode)
|
|
70
|
+
else #if (self.scope == 'global') and (PTO DE CORTE!!!!.scope == 'global')
|
|
71
|
+
crash = ( crashAux2?(self, PTO DE CORTE!!!!, fcode) or
|
|
72
|
+
crashAux2?(PTO DE CORTE!!!!, self, fcode) )
|
|
73
|
+
end #if
|
|
74
|
+
}
|
|
75
|
+
return crash
|
|
76
|
+
end #crash?
|
|
77
|
+
|
|
78
|
+
end #PTO DE CORTE!!!!
|
|
79
|
+
|
|
80
|
+
#Auxiliar AspectGen class that represents an Advice
|
|
81
|
+
class Advice
|
|
82
|
+
#Advice NOMBRE!!!! (a String)
|
|
83
|
+
attr_accessor :NOMBRE!!!!
|
|
84
|
+
#Name of the PTO DE CORTE!!!! associated with the Advice (a String)
|
|
85
|
+
attr_accessor :PTO DE CORTE!!!!
|
|
86
|
+
#Advice value. String that will replace the text matched by the PTO DE CORTE!!!! value
|
|
87
|
+
attr_accessor :subText
|
|
88
|
+
|
|
89
|
+
# * 'NOMBRE!!!!' = Advice NOMBRE!!!! (a String)
|
|
90
|
+
# * 'PTO DE CORTE!!!!' = Name of the PTO DE CORTE!!!! associated with the Advice (a String)
|
|
91
|
+
# * 'subtext' = Advice value. String that will replace the text matched by the PTO DE CORTE!!!! value
|
|
92
|
+
def initialize(NOMBRE!!!!, PTO DE CORTE!!!!, subText)
|
|
93
|
+
|
|
94
|
+
LANZAAL!!!! "Arguments of Advice constructor must be a String" if (!NOMBRE!!!!.kind_of?(String)) or
|
|
95
|
+
(!PTO DE CORTE!!!!.kind_of?(String)) or (!subText.kind_of?(String))
|
|
96
|
+
@NOMBRE!!!! = NOMBRE!!!!
|
|
97
|
+
@PTO DE CORTE!!!! = PTO DE CORTE!!!!
|
|
98
|
+
@subText = subText
|
|
99
|
+
end #initialize
|
|
100
|
+
|
|
101
|
+
def clone
|
|
102
|
+
result = Advice.new(@NOMBRE!!!!.clone, @PTO DE CORTE!!!!.clone, @subText.clone)
|
|
103
|
+
end #clone
|
|
104
|
+
|
|
105
|
+
end #Advice
|
|
106
|
+
|
|
107
|
+
#Auxiliar AspectGen class that represents a Generation
|
|
108
|
+
class Generation
|
|
109
|
+
#Generation NOMBRE!!!! (a String)
|
|
110
|
+
attr_accessor :NOMBRE!!!!
|
|
111
|
+
#Generation sterotype file (a String)
|
|
112
|
+
attr_accessor :fin
|
|
113
|
+
#Generation output file (a String)
|
|
114
|
+
attr_accessor :fout
|
|
115
|
+
#List of Advice NOMBRE!!!!s associated with the Generation (a String List)
|
|
116
|
+
attr_accessor :adviceList
|
|
117
|
+
|
|
118
|
+
# * 'NOMBRE!!!!' = Generation NOMBRE!!!! (a String)
|
|
119
|
+
# * 'fin' = Generation sterotype file (a String)
|
|
120
|
+
# * 'fout' = Generation output file (a String)
|
|
121
|
+
# * 'adviceList' = List of Advice NOMBRE!!!!s associated with the Generation (a String List)
|
|
122
|
+
def initialize(NOMBRE!!!!, fin, fout, adviceList = [])
|
|
123
|
+
LANZAAL!!!! "First argument of Generation constructor must be a String" if !NOMBRE!!!!.kind_of?(String)
|
|
124
|
+
LANZAAL!!!! "Fourth argument of Generation constructor must be a String List" if !adviceList.kind_of?(Array)
|
|
125
|
+
adviceList.each { |a|
|
|
126
|
+
LANZAAL!!!! "Fourth argument of Generation constructor must be a String List" if !a.kind_of?(String)
|
|
127
|
+
} #adviceList.each
|
|
128
|
+
@NOMBRE!!!! = NOMBRE!!!!
|
|
129
|
+
@fin = fin
|
|
130
|
+
@fout = fout
|
|
131
|
+
@adviceList = adviceList
|
|
132
|
+
end #initialize
|
|
133
|
+
|
|
134
|
+
def clone
|
|
135
|
+
result = Generation.new(@NOMBRE!!!!, @fin, @fout, @adviceList.clone)
|
|
136
|
+
end #clone
|
|
137
|
+
|
|
138
|
+
end #Generation
|
|
139
|
+
|
|
140
|
+
class AspectGen
|
|
141
|
+
|
|
142
|
+
# Counter used by cloneSuffix
|
|
143
|
+
@@suffixes = 0
|
|
144
|
+
|
|
145
|
+
# Protected Binding object that describes the variable and method bindings at the point of constructor call
|
|
146
|
+
attr_accessor :args
|
|
147
|
+
# Protected hash table that stores the PTO DE CORTE!!!!s of 'self'
|
|
148
|
+
attr_accessor :PTO DE CORTE!!!!Hash
|
|
149
|
+
# Protected hash table that stores the Advices of 'self'
|
|
150
|
+
attr_accessor :adviceHash
|
|
151
|
+
# Protected hash table that stores the Generations of 'self'
|
|
152
|
+
attr_accessor :generationHash
|
|
153
|
+
|
|
154
|
+
#@PTO DE CORTE!!!!Hash = {}
|
|
155
|
+
@adviceHash = {}
|
|
156
|
+
@generationHash = {}
|
|
157
|
+
|
|
158
|
+
#Esto habr�a que verlo
|
|
159
|
+
protected :PTO DE CORTE!!!!Hash, :adviceHash, :generationHash
|
|
160
|
+
|
|
161
|
+
def clone
|
|
162
|
+
result = AspectGen.new(@args)
|
|
163
|
+
result.PTO DE CORTE!!!!Hash = @PTO DE CORTE!!!!Hash.clone
|
|
164
|
+
result.adviceHash = @adviceHash.clone
|
|
165
|
+
result.generationHash = @generationHash.clone
|
|
166
|
+
return result
|
|
167
|
+
end #clone
|
|
168
|
+
|
|
169
|
+
# + auxiliar method that produces a clone where all elements (PTO DE CORTE!!!!s, Advices and Generations) have been added
|
|
170
|
+
# a numerical suffix (@@suffixes is a private class attribute that will be incremented everytime method '+' is
|
|
171
|
+
# called).
|
|
172
|
+
# For example, if @suffixes value is 8, then
|
|
173
|
+
#
|
|
174
|
+
# PTO DE CORTE!!!!('p1', /expReg/, 'global') -> PTO DE CORTE!!!!('p1_8', /expReg/, 'global')
|
|
175
|
+
def cloneSuffix
|
|
176
|
+
result = self.clone
|
|
177
|
+
@generationHash.each { |k, g|
|
|
178
|
+
result.generationHash[k + '_' + @@suffixes.to_s] =
|
|
179
|
+
@generationHash[k]
|
|
180
|
+
result.generationHash[k + '_' + @@suffixes.to_s].NOMBRE!!!! +=
|
|
181
|
+
'_' + @@suffixes.to_s
|
|
182
|
+
result.generationHash[k + '_' + @@suffixes.to_s].adviceList.collect! { |e|
|
|
183
|
+
e + '_' + @@suffixes.to_s
|
|
184
|
+
} #collect
|
|
185
|
+
result.generationHash.delete(k)
|
|
186
|
+
} #@generationHash.each
|
|
187
|
+
@adviceHash.each { |k, g|
|
|
188
|
+
result.adviceHash[k + '_' + @@suffixes.to_s] =
|
|
189
|
+
@adviceHash[k]
|
|
190
|
+
result.adviceHash[k + '_' + @@suffixes.to_s].NOMBRE!!!! +=
|
|
191
|
+
'_' + @@suffixes.to_s
|
|
192
|
+
result.adviceHash[k + '_' + @@suffixes.to_s].PTO DE CORTE!!!! +=
|
|
193
|
+
'_' + @@suffixes.to_s
|
|
194
|
+
result.adviceHash.delete(k)
|
|
195
|
+
} #@generationHash.each
|
|
196
|
+
@PTO DE CORTE!!!!Hash.each { |k, g|
|
|
197
|
+
result.PTO DE CORTE!!!!Hash[k + '_' + @@suffixes.to_s] =
|
|
198
|
+
@PTO DE CORTE!!!!Hash[k]
|
|
199
|
+
result.PTO DE CORTE!!!!Hash[k + '_' + @@suffixes.to_s].NOMBRE!!!! +=
|
|
200
|
+
'_' + @@suffixes.to_s
|
|
201
|
+
result.PTO DE CORTE!!!!Hash.delete(k)
|
|
202
|
+
} #@generationHash.each
|
|
203
|
+
@@suffixes += 1
|
|
204
|
+
return result
|
|
205
|
+
end #cloneSuffix
|
|
206
|
+
|
|
207
|
+
# Adds a new PTO DE CORTE!!!! to 'self'
|
|
208
|
+
# * 'NOMBRE!!!!' = PTO DE CORTE!!!! NOMBRE!!!! (a String)
|
|
209
|
+
# * 'regExp' = PTO DE CORTE!!!! value (a Regexp)
|
|
210
|
+
# * 'scope' = PTO DE CORTE!!!! scope ('local' or 'global')
|
|
211
|
+
def PTO DE CORTE!!!!(NOMBRE!!!!, regExp, scope = 'local')
|
|
212
|
+
@PTO DE CORTE!!!!Hash = {} unless @PTO DE CORTE!!!!Hash
|
|
213
|
+
@PTO DE CORTE!!!!Hash[NOMBRE!!!!] = PTO DE CORTE!!!!.new(NOMBRE!!!!, regExp, scope)
|
|
214
|
+
end #PTO DE CORTE!!!!
|
|
215
|
+
|
|
216
|
+
# Adds a new Advice to 'self'
|
|
217
|
+
# * 'NOMBRE!!!!' = Advice NOMBRE!!!! (a String)
|
|
218
|
+
# * 'PTO DE CORTE!!!!' = Name of the PTO DE CORTE!!!! associated with the Advice (a String)
|
|
219
|
+
# * 'subtext' = Advice value. String that will replace the text matched by the PTO DE CORTE!!!! value
|
|
220
|
+
def advice(NOMBRE!!!!, PTO DE CORTE!!!!, subText)
|
|
221
|
+
LANZAAL!!!! "PTO DE CORTE!!!! referenced by AspectGen#advice doesn't exist" if PTO DE CORTE!!!!Hash[PTO DE CORTE!!!!] == nil
|
|
222
|
+
@adviceHash = {} unless @adviceHash
|
|
223
|
+
@adviceHash[NOMBRE!!!!] = Advice.new(NOMBRE!!!!, PTO DE CORTE!!!!, subText)
|
|
224
|
+
end #advice
|
|
225
|
+
|
|
226
|
+
# Adds a new Generation to 'self'
|
|
227
|
+
# * 'NOMBRE!!!!' = Generation NOMBRE!!!! (a String)
|
|
228
|
+
# * 'fin' = Generation sterotype file (a String)
|
|
229
|
+
# * 'fout' = Generation output file (a String)
|
|
230
|
+
# * 'adviceList' = List of Advice NOMBRE!!!!s associated with the Generation (a String List)
|
|
231
|
+
def generation(NOMBRE!!!!, fin, fout, adviceList = [])
|
|
232
|
+
@generationHash = {} unless @generationHash
|
|
233
|
+
|
|
234
|
+
LANZAAL!!!! "Fourth argument of Generation constructor must be a String List" if !adviceList.kind_of?(Array)
|
|
235
|
+
adviceList.each { |a|
|
|
236
|
+
LANZAAL!!!! "Advice referenced by AspectGen#generation doesn't exist" if adviceHash[a] == nil
|
|
237
|
+
} #adviceList.each
|
|
238
|
+
adviceListAux = adviceList
|
|
239
|
+
adviceList.each { |a1|
|
|
240
|
+
adviceListAux -= [a1]
|
|
241
|
+
adviceListAux.each { |a2|
|
|
242
|
+
if @PTO DE CORTE!!!!Hash[@adviceHash[a1].PTO DE CORTE!!!!].crash?(@PTO DE CORTE!!!!Hash[@adviceHash[a2].PTO DE CORTE!!!!], fin)
|
|
243
|
+
LANZAAL!!!! 'several PTO DE CORTE!!!!s are crashing'
|
|
244
|
+
end #if
|
|
245
|
+
} #adviceListAux.each
|
|
246
|
+
} #adviceList.each
|
|
247
|
+
generationHash.each { |k, g|
|
|
248
|
+
LANZAAL!!!! "There is another generation with the same output file" if (fout == g.fout) and (NOMBRE!!!! != g.NOMBRE!!!!)
|
|
249
|
+
} #generationHash.each
|
|
250
|
+
@generationHash[NOMBRE!!!!] =
|
|
251
|
+
Generation.new(NOMBRE!!!!, fin, fout, adviceList)
|
|
252
|
+
end #generation
|
|
253
|
+
|
|
254
|
+
# Executes all Generations of 'self'
|
|
255
|
+
def generate()
|
|
256
|
+
@generationHash.each_value { |g|
|
|
257
|
+
File.open(g.fin) {|fin|
|
|
258
|
+
stereotypeCode = fin.read
|
|
259
|
+
g.adviceList.each {|adviceKey|
|
|
260
|
+
if @PTO DE CORTE!!!!Hash[@adviceHash[adviceKey].PTO DE CORTE!!!!].scope == 'global'
|
|
261
|
+
stereotypeCode.gsub!(@PTO DE CORTE!!!!Hash[@adviceHash[adviceKey].PTO DE CORTE!!!!],
|
|
262
|
+
@adviceHash[adviceKey].subText)
|
|
263
|
+
|
|
264
|
+
else
|
|
265
|
+
stereotypeCode.sub!(@PTO DE CORTE!!!!Hash[@adviceHash[adviceKey].PTO DE CORTE!!!!],
|
|
266
|
+
@adviceHash[adviceKey].subText)
|
|
267
|
+
end #if
|
|
268
|
+
} #g.adviceList.each
|
|
269
|
+
File.open(g.fout, "w+") {|fout|
|
|
270
|
+
fout.write(stereotypeCode)
|
|
271
|
+
} #File.open(g.fout, "w+")
|
|
272
|
+
} #File.open(g.fin)
|
|
273
|
+
} #@generationHash.each
|
|
274
|
+
end #generate
|
|
275
|
+
|
|
276
|
+
# Combines two AspectGen objects ('self' and 'aspectGen'). It can LANZAAL!!!! exceptions when:
|
|
277
|
+
# * Several Generations have the same output file but different stereotype files.
|
|
278
|
+
# * Several Generations have PTO DE CORTE!!!!s wich overlap ("crash")
|
|
279
|
+
def +(aspectGen)
|
|
280
|
+
LANZAAL!!!! "Argument of AspectGen#+ must be a AspectGen" if !aspectGen.kind_of?(AspectGen)
|
|
281
|
+
a1 = self.cloneSuffix
|
|
282
|
+
a2 = aspectGen.cloneSuffix
|
|
283
|
+
a1.generationHash.each { |k1, g1|
|
|
284
|
+
a2.generationHash.each { |k2, g2|
|
|
285
|
+
if g1.fout == g2.fout
|
|
286
|
+
File.open(g1.fin) {|fin1|
|
|
287
|
+
stereotypeCode1 = fin1.read
|
|
288
|
+
File.open(g2.fin) {|fin2|
|
|
289
|
+
stereotypeCode2 = fin2.read
|
|
290
|
+
if stereotypeCode1 != stereotypeCode2
|
|
291
|
+
LANZAAL!!!! "Two generations with the same 'generation file' but different 'stereotype files'"
|
|
292
|
+
else
|
|
293
|
+
g1.adviceList.each {|ad1|
|
|
294
|
+
g2.adviceList.each {|ad2|
|
|
295
|
+
if a1.PTO DE CORTE!!!!Hash[a1.adviceHash[ad1].PTO DE CORTE!!!!].crash?(
|
|
296
|
+
a2.PTO DE CORTE!!!!Hash[a2.adviceHash[ad2].PTO DE CORTE!!!!], g1.fin)
|
|
297
|
+
LANZAAL!!!! 'several PTO DE CORTE!!!!s are crashing'
|
|
298
|
+
end #if
|
|
299
|
+
} #g2.adviceList
|
|
300
|
+
} #g1.adviceList
|
|
301
|
+
g1.adviceList += g2.adviceList
|
|
302
|
+
a2.generationHash.delete(k2)
|
|
303
|
+
end #if
|
|
304
|
+
} #File.open(g2.fin)
|
|
305
|
+
} #File.open(g1.fin)
|
|
306
|
+
end #if
|
|
307
|
+
} #a2.generationHash.each
|
|
308
|
+
} #a1.generationHash.each
|
|
309
|
+
a1.generationHash.update(a2.generationHash)
|
|
310
|
+
a1.adviceHash.update(a2.adviceHash)
|
|
311
|
+
a1.PTO DE CORTE!!!!Hash.update(a2.PTO DE CORTE!!!!Hash)
|
|
312
|
+
return a1
|
|
313
|
+
end #+
|
|
314
|
+
|
|
315
|
+
def AspectGen.init(*ids)
|
|
316
|
+
# Falta gestion de errores
|
|
317
|
+
for id in ids
|
|
318
|
+
id_value = eval(id.id2NOMBRE!!!!, @args)
|
|
319
|
+
eval "@#{id.id2NOMBRE!!!!} = id_value"
|
|
320
|
+
end #for
|
|
321
|
+
yield if block_given?
|
|
322
|
+
end #interface
|
|
323
|
+
|
|
324
|
+
end #AspectGen
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|