rgen 0.4.6 → 0.5.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.
Files changed (60) hide show
  1. data/CHANGELOG +95 -83
  2. data/Rakefile +4 -3
  3. data/lib/ea_support/ea_support.rb +54 -0
  4. data/lib/ea_support/id_store.rb +32 -0
  5. data/lib/ea_support/uml13_ea_metamodel.rb +562 -0
  6. data/lib/ea_support/uml13_ea_metamodel_ext.rb +45 -0
  7. data/lib/ea_support/uml13_ea_metamodel_generator.rb +43 -0
  8. data/lib/ea_support/uml13_ea_to_uml13.rb +72 -0
  9. data/lib/ea_support/uml13_to_uml13_ea.rb +82 -0
  10. data/lib/rgen/ecore/ecore.rb +16 -2
  11. data/lib/rgen/ecore/ecore_builder_methods.rb +81 -0
  12. data/lib/rgen/ecore/ecore_instantiator.rb +5 -1
  13. data/lib/rgen/metamodel_builder/builder_extensions.rb +11 -3
  14. data/lib/rgen/metamodel_builder/module_extension2.rb +205 -0
  15. data/lib/rgen/method_delegation.rb +99 -0
  16. data/lib/rgen/model_builder.rb +27 -0
  17. data/lib/rgen/model_builder/builder_context.rb +318 -0
  18. data/lib/rgen/model_builder/model_serializer.rb +201 -0
  19. data/lib/rgen/model_builder/reference_resolver.rb +156 -0
  20. data/lib/rgen/template_language/directory_template_container.rb +6 -2
  21. data/lib/rgen/template_language/output_handler.rb +2 -4
  22. data/lib/rgen/template_language/template_container.rb +212 -195
  23. data/lib/rgen/transformer.rb +95 -4
  24. data/lib/transformers/ecore_to_uml13.rb +66 -0
  25. data/lib/transformers/uml13_to_ecore.rb +16 -7
  26. data/test/ea_instantiator_test.rb +8 -14
  27. data/test/ea_serializer_test.rb +3 -9
  28. data/test/ea_serializer_test/ea_testmodel_regenerated.xml +2 -2
  29. data/test/ea_serializer_test/ea_testmodel_regenerated_import.log +3 -0
  30. data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +19 -19
  31. data/test/metamodel_roundtrip_test/houseMetamodel_Regenerated.ecore +44 -44
  32. data/test/method_delegation_test.rb +178 -0
  33. data/test/model_builder/builder_context_test.rb +59 -0
  34. data/test/model_builder/builder_test.rb +284 -0
  35. data/test/model_builder/ecore_internal.rb +103 -0
  36. data/test/model_builder/ecore_original.rb +163 -0
  37. data/test/model_builder/ecore_original_regenerated.rb +163 -0
  38. data/test/model_builder/reference_resolver_test.rb +156 -0
  39. data/test/model_builder/serializer_test.rb +63 -0
  40. data/test/model_builder_test.rb +4 -0
  41. data/test/rgen_test.rb +2 -0
  42. data/test/template_language_test.rb +41 -1
  43. data/test/template_language_test/expected_result1.txt +1 -3
  44. data/test/template_language_test/templates/define_local_test/local.tpl +8 -0
  45. data/test/template_language_test/templates/define_local_test/test.tpl +8 -0
  46. data/test/template_language_test/templates/evaluate_test/test.tpl +7 -0
  47. data/test/template_language_test/templates/no_indent_test/no_indent.tpl +3 -0
  48. data/test/template_language_test/templates/no_indent_test/sub1/no_indent.tpl +3 -0
  49. data/test/template_language_test/templates/no_indent_test/test.tpl +24 -0
  50. data/test/template_language_test/templates/no_indent_test/test2.tpl +13 -0
  51. data/test/template_language_test/templates/no_indent_test/test3.tpl +10 -0
  52. data/test/template_language_test/templates/template_resolution_test/sub1.tpl +9 -0
  53. data/test/template_language_test/templates/template_resolution_test/sub1/sub1.tpl +3 -0
  54. data/test/template_language_test/templates/template_resolution_test/test.tpl +4 -0
  55. data/test/template_language_test/testout.txt +1 -3
  56. data/test/testmodel/ea_testmodel_import.log +1 -0
  57. data/test/testmodel/ea_testmodel_regenerated.xml +808 -0
  58. data/test/transformer_test.rb +3 -5
  59. metadata +52 -3
  60. data/lib/instantiators/ea_instantiator.rb +0 -39
@@ -0,0 +1,156 @@
1
+ require 'rgen/array_extensions'
2
+
3
+ module RGen
4
+
5
+ module ModelBuilder
6
+
7
+ class ReferenceResolver
8
+ ResolverJob = Struct.new(:receiver, :reference, :namespace, :string)
9
+
10
+ class ResolverException < Exception
11
+ end
12
+
13
+ class ToplevelNamespace
14
+ def initialize(ns)
15
+ raise "Namespace must be an Enumerable" unless ns.is_a?(Enumerable)
16
+ @ns = ns
17
+ end
18
+ def elements
19
+ @ns
20
+ end
21
+ end
22
+
23
+ def initialize
24
+ @jobs = []
25
+ @elementName = {}
26
+ end
27
+
28
+ def addJob(job)
29
+ @jobs << job
30
+ end
31
+
32
+ def setElementName(element, name)
33
+ @elementName[element] = name
34
+ end
35
+
36
+ def resolve(ns=[])
37
+ @toplevelNamespace = ToplevelNamespace.new(ns)
38
+ (@jobs || []).each_with_index do |job, i|
39
+ target = resolveReference(job.namespace || @toplevelNamespace, job.string.split("."))
40
+ raise ResolverException.new("Can not resolve reference #{job.string}") unless target
41
+ if job.reference.many
42
+ job.receiver.addGeneric(job.reference.name, target)
43
+ else
44
+ job.receiver.setGeneric(job.reference.name, target)
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ # TODO: if a reference can not be fully resolved, but a prefix can be found,
52
+ # the exception reported is that its first path element can not be found on
53
+ # toplevel
54
+ def resolveReference(namespace, nameParts)
55
+ element = resolveReferenceDownwards(namespace, nameParts)
56
+ if element.nil? && parentNamespace(namespace)
57
+ element = resolveReference(parentNamespace(namespace), nameParts)
58
+ end
59
+ element
60
+ end
61
+
62
+ def resolveReferenceDownwards(namespace, nameParts)
63
+ firstPart, *restParts = nameParts
64
+ element = namespaceElementByName(namespace, firstPart)
65
+ return nil unless element
66
+ if restParts.size > 0
67
+ resolveReferenceDownwards(element, restParts)
68
+ else
69
+ element
70
+ end
71
+ end
72
+
73
+ def namespaceElementByName(namespace, name)
74
+ @namespaceElementsByName ||= {}
75
+ return @namespaceElementsByName[namespace][name] if @namespaceElementsByName[namespace]
76
+ hash = {}
77
+ namespaceElements(namespace).each do |e|
78
+ raise ResolverException.new("Multiple elements named #{elementName(e)} found in #{nsToS(namespace)}") if hash[elementName(e)]
79
+ hash[elementName(e)] = e if elementName(e)
80
+ end
81
+ @namespaceElementsByName[namespace] = hash
82
+ hash[name]
83
+ end
84
+
85
+ def parentNamespace(namespace)
86
+ if namespace.class.respond_to?(:ecore)
87
+ parents = elementParents(namespace)
88
+ raise ResolverException.new("Element #{nsToS(namespace)} has multiple parents") \
89
+ if parents.size > 1
90
+ parents.first || @toplevelNamespace
91
+ else
92
+ nil
93
+ end
94
+ end
95
+
96
+ def namespaceElements(namespace)
97
+ if namespace.is_a?(ToplevelNamespace)
98
+ namespace.elements
99
+ elsif namespace.class.respond_to?(:ecore)
100
+ elementChildren(namespace)
101
+ else
102
+ raise ResolverException.new("Element #{nsToS(namespace)} can not be used as a namespace")
103
+ end
104
+ end
105
+
106
+ def nsToS(namespace)
107
+ if namespace.is_a?(ToplevelNamespace)
108
+ "toplevel namespace"
109
+ else
110
+ result = namespace.class.name
111
+ result += ":\"#{elementName(namespace)}\"" if elementName(namespace)
112
+ result
113
+ end
114
+ end
115
+
116
+ def elementName(element)
117
+ @elementName[element]
118
+ end
119
+
120
+ def elementChildren(element)
121
+ @elementChildren ||= {}
122
+ return @elementChildren[element] if @elementChildren[element]
123
+ children = containmentRefs(element).collect do |r|
124
+ element.getGeneric(r.name)
125
+ end.flatten.compact
126
+ @elementChildren[element] = children
127
+ end
128
+
129
+ def elementParents(element)
130
+ @elementParents ||= {}
131
+ return @elementParents[element] if @elementParents[element]
132
+ parents = parentRefs(element).collect do |r|
133
+ element.getGeneric(r.name)
134
+ end.flatten.compact
135
+ @elementParents[element] = parents
136
+ end
137
+
138
+ def containmentRefs(element)
139
+ @containmentRefs ||= {}
140
+ @containmentRefs[element.class] ||= eAllReferences(element).select{|r| r.containment}
141
+ end
142
+
143
+ def parentRefs(element)
144
+ @parentRefs ||= {}
145
+ @parentRefs[element.class] ||= eAllReferences(element).select{|r| r.eOpposite && r.eOpposite.containment}
146
+ end
147
+
148
+ def eAllReferences(element)
149
+ @eAllReferences ||= {}
150
+ @eAllReferences[element.class] ||= element.class.ecore.eAllReferences
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+ end
@@ -13,6 +13,7 @@ class DirectoryTemplateContainer
13
13
 
14
14
  def initialize(metamodel=nil, output_path=nil, parent=nil)
15
15
  @containers = {}
16
+ @directoryContainers = {}
16
17
  @parent = parent
17
18
  @metamodel = metamodel
18
19
  @output_path = output_path
@@ -24,7 +25,7 @@ class DirectoryTemplateContainer
24
25
  if !File.directory?(qf) && f =~ /^(.*)\.tpl$/
25
26
  (@containers[$1] = TemplateContainer.new(@metamodel, @output_path, self,qf)).load
26
27
  elsif File.directory?(qf) && f != "." && f != ".."
27
- (@containers[f] = DirectoryTemplateContainer.new(@metamodel, @output_path, self)).load(qf)
28
+ (@directoryContainers[f] = DirectoryTemplateContainer.new(@metamodel, @output_path, self)).load(qf)
28
29
  end
29
30
  }
30
31
  end
@@ -64,9 +65,12 @@ class DirectoryTemplateContainer
64
65
  private
65
66
 
66
67
  def _expand(template, *all_args)
67
- if template =~ /^\/?([^:\/]+)(?:::|\/)([^:\/].*)/
68
+ if template =~ /^\/?(\w+)::(\w.*)/
68
69
  raise "Template not found: #{$1}" unless @containers[$1]
69
70
  @containers[$1].expand($2, *all_args)
71
+ elsif template =~ /^\/?(\w+)\/(\w.*)/
72
+ raise "Template not found: #{$1}" unless @directoryContainers[$1]
73
+ @directoryContainers[$1].expand($2, *all_args)
70
74
  else
71
75
  raise "Invalid template name: #{template}"
72
76
  end
@@ -7,6 +7,7 @@ module TemplateLanguage
7
7
 
8
8
  class OutputHandler
9
9
  attr_writer :indent
10
+ attr_accessor :noIndentNextLine
10
11
 
11
12
  def initialize(indent=0, indentString=" ", mode=:explicit)
12
13
  self.mode = mode
@@ -22,6 +23,7 @@ module TemplateLanguage
22
23
  #
23
24
  def concat(s)
24
25
  return @output.concat(s) if s.is_a? OutputHandler
26
+ #puts [object_id, noIndentNextLine, @state, @output.to_s, s].inspect
25
27
  s = s.to_str.gsub(/^[\t ]*\r?\n/,'') if @ignoreNextNL
26
28
  s = s.to_str.gsub(/^\s+/,'') if @ignoreNextWS
27
29
  @ignoreNextNL = @ignoreNextWS = false if s =~ /\S/
@@ -74,10 +76,6 @@ module TemplateLanguage
74
76
  @ignoreNextWS = true
75
77
  end
76
78
 
77
- def noIndentNextLine
78
- @noIndentNextLine = true
79
- end
80
-
81
79
  def mode=(m)
82
80
  raise StandardError.new("Unknown mode: #{m}") unless [:direct, :explicit].include?(m)
83
81
  @mode = m
@@ -8,208 +8,225 @@ require 'rgen/template_language/template_helper'
8
8
 
9
9
  module RGen
10
10
 
11
- module TemplateLanguage
12
-
13
- class TemplateContainer
14
- include TemplateHelper
15
-
16
- def initialize(metamodels, output_path, parent, filename)
17
- @templates = {}
18
- @parent = parent
19
- @filename = filename
20
- @indent = 0
21
- @output_path = output_path
22
- @metamodels = metamodels
23
- @metamodels = [ @metamodels ] unless @metamodels.is_a?(Array)
24
- end
25
-
26
- def load
27
- File.open(@filename,"rb") do |f|
28
- begin
29
- @@metamodels = @metamodels
30
- fileContent = f.read
31
- _detectNewLinePattern(fileContent)
32
- ERB.new(fileContent,nil,nil,'@output').result(binding)
33
- rescue Exception => e
34
- processAndRaise(e)
11
+ module TemplateLanguage
12
+
13
+ class TemplateContainer
14
+ include TemplateHelper
15
+
16
+ def initialize(metamodels, output_path, parent, filename)
17
+ @templates = {}
18
+ @parent = parent
19
+ @filename = filename
20
+ @indent = 0
21
+ @output_path = output_path
22
+ @metamodels = metamodels
23
+ @metamodels = [ @metamodels ] unless @metamodels.is_a?(Array)
35
24
  end
36
- end
37
- end
38
-
39
- # if this container can handle the call, the expansion result is returned
40
- # otherwise expand is called on the appropriate container and the result is added to @output
41
- def expand(template, *all_args)
42
- args, params = _splitArgsAndOptions(all_args)
43
- if params.has_key?(:foreach)
44
- raise StandardError.new("expand :foreach argument is not enumerable") \
45
- unless params[:foreach].is_a?(Enumerable)
46
- _expand_foreach(template, args, params)
47
- else
48
- _expand(template, args, params)
49
- end
50
- end
51
-
52
- def this
53
- @context
54
- end
55
-
56
- def method_missing(name, *args)
57
- @context.send(name, *args)
58
- end
59
-
60
- def self.const_missing(name)
61
- super unless @@metamodels
62
- @@metamodels.each do |mm|
63
- return mm.const_get(name) rescue NameError
64
- end
65
- super
66
- end
67
-
68
- private
69
-
70
- def nonl
71
- @output.ignoreNextNL
72
- end
73
-
74
- def nows
75
- @output.ignoreNextWS
76
- end
77
-
78
- def nl
79
- _direct_concat(@newLinePattern)
80
- end
81
-
82
- def ws
83
- _direct_concat(" ")
84
- end
85
-
86
- def iinc
87
- @indent += 1
88
- @output.indent = @indent
89
- end
90
-
91
- def idec
92
- @indent -= 1 if @indent > 0
93
- @output.indent = @indent
94
- end
95
-
96
- def define(template, params={}, &block)
97
- @templates[template] ||= {}
98
- cls = params[:for] || Object
99
- @templates[template][cls] = block
100
- end
101
-
102
- def file(name, indentString=nil)
103
- old_output, @output = @output, OutputHandler.new(@indent, indentString || @parent.indentString)
104
- begin
105
- yield
106
- rescue Exception => e
107
- processAndRaise(e)
108
- end
109
- path = ""
110
- path += @output_path+"/" if @output_path
111
- dirname = File.dirname(path+name)
112
- FileUtils.makedirs(dirname) unless File.exist?(dirname)
113
- File.open(path+name,"wb") { |f| f.write(@output) }
114
- @output = old_output
115
- end
116
-
117
- # private private
118
-
119
- def _expand_foreach(template, args, params)
120
- sep = params[:separator]
121
- params[:foreach].each_with_index {|e,i|
122
- single_params = params.dup
123
- single_params[:for] = e
124
- _direct_concat(sep.to_s) if sep && i > 0
125
- _expand(template, args, single_params)
126
- }
127
- end
128
-
129
- LOCAL_TEMPLATE_REGEX = /^:*(\w+)$/
130
-
131
- def _expand(template, args, params)
132
- raise StandardError.new("expand :for argument evaluates to nil") if params.has_key?(:for) && params[:for].nil?
133
- context = params[:for]
134
- @indent = params[:indent] || @indent
135
- # if this is the first call to expand within this container, @output is nil
136
- noIndentNextLine = params[:noIndentNextLine]
137
- noIndentNextLine = (@output.to_s.size > 0 && @output.to_s[-1] != "\n"[0]) if noIndentNextLine.nil?
138
- old_context, @context = @context, context if context
139
- local_output = nil
140
- if template =~ LOCAL_TEMPLATE_REGEX
141
- tplname = $1
142
- raise StandardError.new("Template not found: #{$1}") unless @templates[tplname]
143
- old_output, @output = @output, OutputHandler.new(@indent, @parent.indentString)
144
- @output.noIndentNextLine if noIndentNextLine
145
- _call_template(tplname, @context, args)
146
- local_output, @output = @output, old_output
147
- else
148
- local_output = @parent.expand(template, *(args.dup << {:for => @context, :indent => @indent, :noIndentNextLine => noIndentNextLine}))
149
- end
150
- _direct_concat(local_output)
151
- @context = old_context if old_context
152
- local_output
153
- end
154
-
155
- def processAndRaise(e, tpl=nil)
156
- bt = e.backtrace.dup
157
- e.backtrace.each_with_index do |t,i|
158
- if t =~ /\(erb\):(\d+):/
159
- bt[i] = "#{@filename}:#{$1}"
160
- bt[i] += ":in '#{tpl}'" if tpl
161
- break
25
+
26
+ def load
27
+ File.open(@filename,"rb") do |f|
28
+ begin
29
+ @@metamodels = @metamodels
30
+ fileContent = f.read
31
+ _detectNewLinePattern(fileContent)
32
+ ERB.new(fileContent,nil,nil,'@output').result(binding)
33
+ rescue Exception => e
34
+ processAndRaise(e)
35
+ end
36
+ end
162
37
  end
163
- end
164
- raise e, e.to_s, bt
165
- end
166
-
167
- def _call_template(tpl, context, args)
168
- found = false
169
- @templates[tpl].each_pair do |key, value|
170
- if context.is_a?(key)
171
- proc = @templates[tpl][key]
172
- arity = proc.arity
173
- arity = 0 if arity == -1 # if no args are given
174
- raise StandardError.new("Wrong number of arguments calling template #{tpl}: #{args.size} for #{arity} "+
175
- "(Beware: Hashes as last arguments are taken as options and are ignored)") \
176
- if arity != args.size
38
+
39
+ def expand(template, *all_args)
40
+ args, params = _splitArgsAndOptions(all_args)
41
+ if params.has_key?(:foreach)
42
+ raise StandardError.new("expand :foreach argument is not enumerable") \
43
+ unless params[:foreach].is_a?(Enumerable)
44
+ _expand_foreach(template, args, params)
45
+ else
46
+ _expand(template, args, params)
47
+ end
48
+ end
49
+
50
+ def evaluate(template, *all_args)
51
+ args, params = _splitArgsAndOptions(all_args)
52
+ raise StandardError.new(":foreach can not be used with evaluate") if params[:foreach]
53
+ _expand(template, args, params.merge({:_evalOnly => true}))
54
+ end
55
+
56
+ def this
57
+ @context
58
+ end
59
+
60
+ def method_missing(name, *args)
61
+ @context.send(name, *args)
62
+ end
63
+
64
+ def self.const_missing(name)
65
+ super unless @@metamodels
66
+ @@metamodels.each do |mm|
67
+ return mm.const_get(name) rescue NameError
68
+ end
69
+ super
70
+ end
71
+
72
+ private
73
+
74
+ def nonl
75
+ @output.ignoreNextNL
76
+ end
77
+
78
+ def nows
79
+ @output.ignoreNextWS
80
+ end
81
+
82
+ def nl
83
+ _direct_concat(@newLinePattern)
84
+ end
85
+
86
+ def ws
87
+ _direct_concat(" ")
88
+ end
89
+
90
+ def iinc
91
+ @indent += 1
92
+ @output.indent = @indent
93
+ end
94
+
95
+ def idec
96
+ @indent -= 1 if @indent > 0
97
+ @output.indent = @indent
98
+ end
99
+
100
+ TemplateDesc = Struct.new(:block, :local)
101
+
102
+ def define(template, params={}, &block)
103
+ _define(template, params, &block)
104
+ end
105
+
106
+ def define_local(template, params={}, &block)
107
+ _define(template, params.merge({:local => true}), &block)
108
+ end
109
+
110
+ def file(name, indentString=nil)
111
+ old_output, @output = @output, OutputHandler.new(@indent, indentString || @parent.indentString)
177
112
  begin
178
- @@metamodels = @metamodels
179
- proc.call(*args)
113
+ yield
180
114
  rescue Exception => e
181
- processAndRaise(e, tpl)
115
+ processAndRaise(e)
182
116
  end
183
- found = true
117
+ path = ""
118
+ path += @output_path+"/" if @output_path
119
+ dirname = File.dirname(path+name)
120
+ FileUtils.makedirs(dirname) unless File.exist?(dirname)
121
+ File.open(path+name,"wb") { |f| f.write(@output) }
122
+ @output = old_output
184
123
  end
124
+
125
+ # private private
126
+
127
+ def _define(template, params={}, &block)
128
+ @templates[template] ||= {}
129
+ cls = params[:for] || Object
130
+ @templates[template][cls] = TemplateDesc.new(block, params[:local])
131
+ end
132
+
133
+ def _expand_foreach(template, args, params)
134
+ sep = params[:separator]
135
+ params[:foreach].each_with_index {|e,i|
136
+ _direct_concat(sep.to_s) if sep && i > 0
137
+ output = _expand(template, args, params.merge({:for => e}))
138
+ }
139
+ end
140
+
141
+ LOCAL_TEMPLATE_REGEX = /^:*(\w+)$/
142
+
143
+ def _expand(template, args, params)
144
+ raise StandardError.new("expand :for argument evaluates to nil") if params.has_key?(:for) && params[:for].nil?
145
+ context = params[:for]
146
+ @indent = params[:indent] || @indent
147
+ noIndentNextLine = params[:_noIndentNextLine] ||
148
+ (@output.is_a?(OutputHandler) && @output.noIndentNextLine) ||
149
+ (@output.to_s.size > 0 && @output.to_s[-1] != "\n"[0])
150
+ caller = params[:_caller] || self
151
+ old_context, @context = @context, context if context
152
+ local_output = nil
153
+ if template =~ LOCAL_TEMPLATE_REGEX
154
+ tplname = $1
155
+ raise StandardError.new("Template not found: #{$1}") unless @templates[tplname]
156
+ old_output, @output = @output, OutputHandler.new(@indent, @parent.indentString)
157
+ @output.noIndentNextLine = noIndentNextLine
158
+ _call_template(tplname, @context, args, caller == self)
159
+ old_output.noIndentNextLine = false if old_output.is_a?(OutputHandler) && !old_output.noIndentNextLine
160
+ local_output, @output = @output, old_output
161
+ else
162
+ local_output = @parent.expand(template, *(args.dup << {:for => @context, :indent => @indent, :_noIndentNextLine => noIndentNextLine, :_evalOnly => true, :_caller => caller}))
163
+ end
164
+ _direct_concat(local_output) unless params[:_evalOnly]
165
+ @context = old_context if old_context
166
+ local_output.to_s
167
+ end
168
+
169
+ def processAndRaise(e, tpl=nil)
170
+ bt = e.backtrace.dup
171
+ e.backtrace.each_with_index do |t,i|
172
+ if t =~ /\(erb\):(\d+):/
173
+ bt[i] = "#{@filename}:#{$1}"
174
+ bt[i] += ":in '#{tpl}'" if tpl
175
+ break
176
+ end
177
+ end
178
+ raise e, e.to_s, bt
179
+ end
180
+
181
+ def _call_template(tpl, context, args, localCall)
182
+ found = false
183
+ @templates[tpl].each_pair do |key, value|
184
+ if context.is_a?(key)
185
+ templateDesc = @templates[tpl][key]
186
+ proc = templateDesc.block
187
+ arity = proc.arity
188
+ arity = 0 if arity == -1 # if no args are given
189
+ raise StandardError.new("Wrong number of arguments calling template #{tpl}: #{args.size} for #{arity} "+
190
+ "(Beware: Hashes as last arguments are taken as options and are ignored)") \
191
+ if arity != args.size
192
+ raise StandardError.new("Template can only be called locally: #{tpl}") \
193
+ if templateDesc.local && !localCall
194
+ begin
195
+ @@metamodels = @metamodels
196
+ proc.call(*args)
197
+ rescue Exception => e
198
+ processAndRaise(e, tpl)
199
+ end
200
+ found = true
201
+ end
202
+ end
203
+ raise StandardError.new("Template class not matching: #{tpl} for #{context.class.name}") unless found
204
+ end
205
+
206
+ def _direct_concat(s)
207
+ if @output.is_a? OutputHandler
208
+ @output.direct_concat(s)
209
+ else
210
+ @output << s
211
+ end
212
+ end
185
213
 
214
+ def _detectNewLinePattern(text)
215
+ tests = 0
216
+ rnOccurances = 0
217
+ text.scan(/(\r?)\n/) do |groups|
218
+ tests += 1
219
+ rnOccurances += 1 if groups[0] == "\r"
220
+ break if tests >= 10
221
+ end
222
+ if rnOccurances > (tests / 2)
223
+ @newLinePattern = "\r\n"
224
+ else
225
+ @newLinePattern = "\n"
226
+ end
227
+ end
228
+
186
229
  end
187
- raise StandardError.new("Template class not matching: #{tpl} for #{context.class.name}") unless found
188
- end
189
-
190
- def _direct_concat(s)
191
- if @output.is_a? OutputHandler
192
- @output.direct_concat(s)
193
- else
194
- @output << s
195
- end
196
- end
197
-
198
- def _detectNewLinePattern(text)
199
- tests = 0
200
- rnOccurances = 0
201
- text.scan(/(\r?)\n/) do |groups|
202
- tests += 1
203
- rnOccurances += 1 if groups[0] == "\r"
204
- break if tests >= 10
205
- end
206
- if rnOccurances > (tests / 2)
207
- @newLinePattern = "\r\n"
208
- else
209
- @newLinePattern = "\n"
210
- end
230
+
211
231
  end
212
- end
213
-
214
- end
215
232
 
216
233
  end