xmlconv2 2.0.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 (108) hide show
  1. data/History.txt +6 -0
  2. data/LICENCE.txt +339 -0
  3. data/Manifest.txt +107 -0
  4. data/README.txt +25 -0
  5. data/Rakefile +28 -0
  6. data/bin/admin +65 -0
  7. data/bin/xmlconvd +19 -0
  8. data/data/grammar/i2.grammar +73 -0
  9. data/src/conversion/bdd_geh.rb +281 -0
  10. data/src/conversion/bdd_i2.rb +102 -0
  11. data/src/conversion/bdd_xml.rb +242 -0
  12. data/src/conversion/geh_bdd.rb +165 -0
  13. data/src/conversion/i2_bdd.rb +271 -0
  14. data/src/conversion/xml_bdd.rb +125 -0
  15. data/src/custom/lookandfeel.rb +47 -0
  16. data/src/i2/address.rb +33 -0
  17. data/src/i2/date.rb +37 -0
  18. data/src/i2/document.rb +26 -0
  19. data/src/i2/header.rb +24 -0
  20. data/src/i2/order.rb +44 -0
  21. data/src/i2/parser.rb +25 -0
  22. data/src/i2/position.rb +37 -0
  23. data/src/i2/record.rb +11 -0
  24. data/src/model/address.rb +20 -0
  25. data/src/model/agreement.rb +10 -0
  26. data/src/model/bdd.rb +26 -0
  27. data/src/model/bsr.rb +16 -0
  28. data/src/model/delivery.rb +15 -0
  29. data/src/model/delivery_item.rb +18 -0
  30. data/src/model/freetext_container.rb +26 -0
  31. data/src/model/id_container.rb +15 -0
  32. data/src/model/invoice.rb +18 -0
  33. data/src/model/invoice_item.rb +11 -0
  34. data/src/model/item.rb +19 -0
  35. data/src/model/item_container.rb +15 -0
  36. data/src/model/name.rb +27 -0
  37. data/src/model/part_info.rb +10 -0
  38. data/src/model/part_info_container.rb +15 -0
  39. data/src/model/party.rb +23 -0
  40. data/src/model/party_container.rb +20 -0
  41. data/src/model/price.rb +10 -0
  42. data/src/model/price_container.rb +18 -0
  43. data/src/model/transaction.rb +28 -0
  44. data/src/state/global.rb +28 -0
  45. data/src/state/global_predefine.rb +11 -0
  46. data/src/state/login.rb +38 -0
  47. data/src/state/transaction.rb +13 -0
  48. data/src/state/transactions.rb +130 -0
  49. data/src/util/application.rb +143 -0
  50. data/src/util/destination.rb +130 -0
  51. data/src/util/invoicer.rb +72 -0
  52. data/src/util/known_user.rb +16 -0
  53. data/src/util/polling_manager.rb +78 -0
  54. data/src/util/session.rb +23 -0
  55. data/src/util/transaction.rb +105 -0
  56. data/src/util/validator.rb +20 -0
  57. data/src/view/foot.rb +27 -0
  58. data/src/view/head.rb +13 -0
  59. data/src/view/login.rb +36 -0
  60. data/src/view/navigation.rb +30 -0
  61. data/src/view/navigationlink.rb +21 -0
  62. data/src/view/pager.rb +73 -0
  63. data/src/view/preformatted.rb +39 -0
  64. data/src/view/template.rb +17 -0
  65. data/src/view/transaction.rb +42 -0
  66. data/src/view/transactions.rb +90 -0
  67. data/test/mock.rb +149 -0
  68. data/test/suite.rb +16 -0
  69. data/test/test_conversion/bdd_geh.rb +533 -0
  70. data/test/test_conversion/bdd_i2.rb +314 -0
  71. data/test/test_conversion/bdd_xml.rb +556 -0
  72. data/test/test_conversion/geh_bdd.rb +372 -0
  73. data/test/test_conversion/i2_bdd.rb +804 -0
  74. data/test/test_conversion/xml_bdd.rb +203 -0
  75. data/test/test_i2/address.rb +88 -0
  76. data/test/test_i2/date.rb +49 -0
  77. data/test/test_i2/document.rb +62 -0
  78. data/test/test_i2/header.rb +39 -0
  79. data/test/test_i2/order.rb +94 -0
  80. data/test/test_i2/parser.rb +309 -0
  81. data/test/test_i2/position.rb +65 -0
  82. data/test/test_integration/geh_i2.rb +312 -0
  83. data/test/test_integration/i2_geh.rb +449 -0
  84. data/test/test_integration/i2_xml.rb +162 -0
  85. data/test/test_integration/xml_i2.rb +254 -0
  86. data/test/test_model/address.rb +35 -0
  87. data/test/test_model/agreement.rb +22 -0
  88. data/test/test_model/bdd.rb +55 -0
  89. data/test/test_model/bsr.rb +38 -0
  90. data/test/test_model/delivery.rb +79 -0
  91. data/test/test_model/delivery_item.rb +52 -0
  92. data/test/test_model/freetext_container.rb +45 -0
  93. data/test/test_model/invoice.rb +65 -0
  94. data/test/test_model/invoice_item.rb +41 -0
  95. data/test/test_model/name.rb +57 -0
  96. data/test/test_model/part_info.rb +24 -0
  97. data/test/test_model/party.rb +96 -0
  98. data/test/test_model/price.rb +24 -0
  99. data/test/test_util/application.rb +168 -0
  100. data/test/test_util/destination.rb +197 -0
  101. data/test/test_util/invoicer.rb +36 -0
  102. data/test/test_util/polling_manager.rb +111 -0
  103. data/test/test_util/transaction.rb +129 -0
  104. data/user-stories/UserStories_XmlConv2.txt +381 -0
  105. data/user-stories/doku/ABB.incoming.HTTP.invoice.xml +315 -0
  106. data/user-stories/doku/ABB.received.xml +259 -0
  107. data/user-stories/doku/BO_OrderProcessing.sxw +0 -0
  108. metadata +195 -0
data/src/view/foot.rb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Foot -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'htmlgrid/composite'
5
+ require 'view/navigation'
6
+ require 'date'
7
+
8
+ module XmlConv
9
+ module View
10
+ class Foot < HtmlGrid::Composite
11
+ COMPONENTS = {
12
+ [0,0] => :copyright,
13
+ [1,0] => Navigation,
14
+ }
15
+ CSS_CLASS = 'foot composite'
16
+ LEGACY_INTERFACE = false
17
+ def copyright(model)
18
+ link = HtmlGrid::Link.new(:copyright, model, @session, self)
19
+ link.href = 'http://www.ywesee.com'
20
+ link.value = @lookandfeel.lookup(:copyright, Date.today.strftime('%Y'))
21
+ link.css_class = 'foot'
22
+ link.target = '_blank'
23
+ link
24
+ end
25
+ end
26
+ end
27
+ end
data/src/view/head.rb ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Head -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'htmlgrid/composite'
5
+
6
+ module XmlConv
7
+ module View
8
+ class Head < HtmlGrid::Composite
9
+ COMPONENTS = {
10
+ }
11
+ end
12
+ end
13
+ end
data/src/view/login.rb ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Login -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'view/template'
5
+ require 'htmlgrid/form'
6
+ require 'htmlgrid/pass'
7
+
8
+ module XmlConv
9
+ module View
10
+ class LoginForm < HtmlGrid::Form
11
+ COMPONENTS = {
12
+ [0,0] => :pass,
13
+ [1,1] => :submit,
14
+ }
15
+ CSS_CLASS = 'component'
16
+ EVENT = :login
17
+ LABELS = true
18
+ SYMBOL_MAP = {
19
+ :pass => HtmlGrid::Pass,
20
+ }
21
+ end
22
+ class LoginComposite < HtmlGrid::Composite
23
+ COMPONENTS = {
24
+ [0,0] => "login_welcome",
25
+ [0,1] => LoginForm,
26
+ }
27
+ CSS_CLASS = 'composite'
28
+ CSS_MAP = {
29
+ [0,0] => 'th',
30
+ }
31
+ end
32
+ class Login < Template
33
+ CONTENT = LoginComposite
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Navigation -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'htmlgrid/composite'
5
+ require 'view/navigationlink'
6
+
7
+ module XmlConv
8
+ module View
9
+ class Navigation < HtmlGrid::Composite
10
+ COMPONENTS = {}
11
+ CSS_CLASS = "navigation"
12
+ #HTML_ATTRIBUTES = {"align"=>"right"}
13
+ SYMBOL_MAP = {
14
+ :navigation_divider => HtmlGrid::Text,
15
+ }
16
+ def init
17
+ build_navigation()
18
+ super
19
+ end
20
+ def build_navigation
21
+ @lookandfeel.navigation.each_with_index { |state, idx|
22
+ evt = state.is_a?(Symbol) ? state : state.direct_event
23
+ symbol_map.store(evt, NavigationLink)
24
+ components.store([idx*2,0], evt)
25
+ components.store([idx*2-1,0], :navigation_divider) if(idx > 0)
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # View::NavigationLink -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'htmlgrid/link'
5
+
6
+ module XmlConv
7
+ module View
8
+ class NavigationLink < HtmlGrid::Link
9
+ #CSS_CLASS = "navigation"
10
+ def init
11
+ super
12
+ unless(@lookandfeel.direct_event == @name)
13
+ @attributes.store("href", @lookandfeel.event_url(@name))
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+
21
+
data/src/view/pager.rb ADDED
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Pager -- xmlconv2 -- 01.07.2004 -- ywesee@ywesee.com
3
+
4
+ require 'htmlgrid/link'
5
+ require 'htmlgrid/list'
6
+
7
+ module XmlConv
8
+ module View
9
+ class Pager < HtmlGrid::List
10
+ BACKGROUND_SUFFIX = ''
11
+ COMPONENTS = {
12
+ [0,0] => :number_link,
13
+ }
14
+ CSS_CLASS = 'pager'
15
+ CSS_HEAD_MAP = {
16
+ #[0,0] => 'pager-head',
17
+ }
18
+ CSS_MAP = {
19
+ #[0,0] => 'pager',
20
+ }
21
+ LEGACY_INTERFACE = false
22
+ OFFSET_STEP = [1,0]
23
+ SORT_DEFAULT = :to_i
24
+ SORT_HEADER = false
25
+ def init
26
+ @page = @container.model
27
+ super
28
+ end
29
+ def compose_header(offset)
30
+ @grid.add(page_number(@model), *offset)
31
+ @grid.add_style('head', *offset)
32
+ offset = resolve_offset(offset, self::class::OFFSET_STEP)
33
+ if(@page != @model.first)
34
+ link = page_link(@page.previous)
35
+ link.value = @lookandfeel.lookup(:page_back)
36
+ @grid.add(link, *offset)
37
+ end
38
+ #@grid.add_attribute('class', 'pager', *offset)
39
+ resolve_offset(offset, self::class::OFFSET_STEP)
40
+ end
41
+ def compose_footer(offset)
42
+ if(@page != @model.last)
43
+ link = page_link(@page.next)
44
+ link.value = @lookandfeel.lookup(:page_fwd)
45
+ @grid.add(link, *offset)
46
+ else
47
+ @grid.add(nil, *offset)
48
+ end
49
+ end
50
+ private
51
+ def number_link(model)
52
+ page_link(model)
53
+ end
54
+ def page_link(page)
55
+ if(page != @page)
56
+ link = HtmlGrid::Link.new(:self, page, @session, self)
57
+ link.value = page.to_s
58
+ #link.set_attribute("class", "pager")
59
+ values = {
60
+ :page => page.to_i.to_s,
61
+ }
62
+ link.href = @lookandfeel.event_url(:self, values)
63
+ link
64
+ else
65
+ page.to_s
66
+ end
67
+ end
68
+ def page_number(model)
69
+ @lookandfeel.lookup(:page_number, @page, @page.total)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Preformatted -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'htmlgrid/value'
5
+
6
+ module XmlConv
7
+ module View
8
+ BREAK_WIDTH = 65
9
+ class Preformatted < HtmlGrid::Value
10
+ def init
11
+ super
12
+ if(@value)
13
+ raw = @value.gsub(/>\s+</, "><").gsub(/\r\n?/, "\n")
14
+ pretty = CGI.pretty(raw)
15
+ wrap = ''
16
+ pretty.each_line { |line|
17
+ if(line.length < BREAK_WIDTH)
18
+ wrap << line
19
+ else
20
+ parts = line.split('" "')
21
+ wrapline = parts.shift
22
+ while(part = parts.shift)
23
+ if((wrapline.length + part.length) >= BREAK_WIDTH)
24
+ wrap << wrapline
25
+ wrap << "\"\n"
26
+ wrapline = " \"" << part
27
+ else
28
+ wrapline << '" "' << part
29
+ end
30
+ end
31
+ wrap << wrapline
32
+ end
33
+ }
34
+ @value = CGI.escapeHTML(wrap)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Template -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'htmlgrid/divtemplate'
5
+ require 'view/foot'
6
+
7
+ module XmlConv
8
+ module View
9
+ class Template < HtmlGrid::DivTemplate
10
+ COMPONENTS = {
11
+ [0,0] => :content,
12
+ [0,1] => :foot,
13
+ }
14
+ FOOT = Foot
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Transaction -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'htmlgrid/value'
5
+ require 'view/template'
6
+ require 'view/preformatted'
7
+
8
+ module XmlConv
9
+ module View
10
+ class TransactionComposite < HtmlGrid::Composite
11
+ COMPONENTS = {
12
+ [0,0] => 'th_input',
13
+ [1,0] => 'th_output',
14
+ [0,1] => :input,
15
+ [1,1] => :output,
16
+ [0,2] => 'th_error',
17
+ [0,3] => :error_string,
18
+ }
19
+ CSS_CLASS = 'composite'
20
+ CSS_MAP = {
21
+ [0,0,2] => 'th',
22
+ [0,1,2] => 'helfti preformatted',
23
+ [0,2] => 'th',
24
+ [0,3] => 'list preformatted bg',
25
+ }
26
+ COLSPAN_MAP = {
27
+ [0,2] => 2,
28
+ [0,3] => 2,
29
+ }
30
+ DEFAULT_CLASS = View::Preformatted
31
+ LEGACY_INTERFACE = false
32
+ def error_string(model)
33
+ if(err = model.error)
34
+ [err.class, err.message, err.backtrace].join("\n")
35
+ end
36
+ end
37
+ end
38
+ class Transaction < Template
39
+ CONTENT = TransactionComposite
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+ # View::Transactions -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'htmlgrid/list'
5
+ require 'htmlgrid/value'
6
+ require 'view/template'
7
+ require 'view/pager'
8
+
9
+ module XmlConv
10
+ module View
11
+ class TransactionsList < HtmlGrid::List
12
+ BACKGROUND_SUFFIX = ' bg'
13
+ COMPONENTS = {
14
+ [0,0] => :transaction_id,
15
+ [1,0] => :origin,
16
+ [2,0] => :commit_time,
17
+ [3,0] => :uri_comparable,
18
+ [4,0] => :status_comparable,
19
+ }
20
+ CSS_CLASS = 'composite'
21
+ CSS_HEAD_MAP = {
22
+ [0,0] => 'right',
23
+ }
24
+ CSS_MAP = {
25
+ [0,0] => 'list right',
26
+ [1,0,4] => 'list',
27
+ }
28
+ DEFAULT_CLASS = HtmlGrid::Value
29
+ LEGACY_INTERFACE = false
30
+ SORT_DEFAULT = nil #:commit_time
31
+ SORT_REVERSE = false
32
+ def commit_time(model)
33
+ time_format(model.commit_time || model.start_time)
34
+ end
35
+ def origin(model)
36
+ uri_fmt(model.origin)
37
+ end
38
+ def uri_comparable(model)
39
+ uri_fmt(model.uri)
40
+ end
41
+ def uri_fmt(uri)
42
+ uri = uri.to_s
43
+ if((i1 = uri.index(/([^\/])\/[^\/]/, 1)) \
44
+ && (i2 = uri.rindex(/(\/[^\/]+){3}/)) \
45
+ && (i2 > i1))
46
+ uri[0..(i1.next)] << '...' << uri[i2..-1]
47
+ else
48
+ uri
49
+ end
50
+ end
51
+ def status_comparable(model)
52
+ model.update_status
53
+ status = model.status
54
+ @lookandfeel.lookup("status_#{status}") or status.to_s
55
+ end
56
+ def time_format(a_time)
57
+ if(a_time.respond_to?(:strftime))
58
+ a_time.strftime("%d.%m.%Y %H:%M:%S")
59
+ end
60
+ end
61
+ def transaction_id(model)
62
+ link = HtmlGrid::Link.new(:transaction_id, model, @session, self)
63
+ args = {
64
+ 'transaction_id' => model.transaction_id,
65
+ }
66
+ link.href = @lookandfeel.event_url(:transaction, args)
67
+ link.value = model.transaction_id
68
+ link
69
+ end
70
+ end
71
+ class TransactionsComposite < HtmlGrid::Composite
72
+ COMPONENTS = {
73
+ [0,0] => :pager,
74
+ [0,1] => :transactions,
75
+ }
76
+ CSS_CLASS = 'composite'
77
+ LEGACY_INTERFACE = false
78
+ def pager(model)
79
+ Pager.new(model.pages, @session, self)
80
+ end
81
+ def transactions(page)
82
+ TransactionsList.new(page.model, @session, self)
83
+ end
84
+ end
85
+ class Transactions < Template
86
+ CONTENT = TransactionsComposite
87
+ #CONTENT = TransactionsList
88
+ end
89
+ end
90
+ end
data/test/mock.rb ADDED
@@ -0,0 +1,149 @@
1
+ # Ruby/Mock version 1.0
2
+ #
3
+ # A class for conveniently building mock objects in RUnit test cases.
4
+ # Copyright (c) 2001 Nat Pryce, all rights reserved
5
+ #
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
+
19
+ require 'runit/error'
20
+
21
+
22
+ class Mock
23
+ # Creates a new, named mock object. The name is reported in exceptions
24
+ # thrown by the mock object when method invocations are incorrect.
25
+ #
26
+ def initialize( mock_name = self.to_s )
27
+ @mock_calls = []
28
+ @next_call = 0
29
+ @name = mock_name
30
+ end
31
+
32
+ # Mock the next method call to be made to this mock object.
33
+ #
34
+ # A mock method is defined by the method name (a symbol) and a block
35
+ # that defines the arity of the method and the mocked behaviour for
36
+ # this call. The mocked behaviour should assert preconditions and
37
+ # return a value. Mocked behaviour should rarely be any more complex
38
+ # than that. If it is, that's probably an indication that the tests
39
+ # need some restructuring or that the tested code needs refactoring.
40
+ #
41
+ # If no block is given and preconditions have been defined for the named
42
+ # method, a block is created for the mocked methodthat has the same arity
43
+ # as the precondition and returns self.
44
+ #
45
+ def __next( name, &test )
46
+ if test == nil
47
+ if respond_to?( Mock.__pre(name) )
48
+ test = proc { |*args| self }
49
+ else
50
+ raise "no block given for mocked method #{name}"
51
+ end
52
+ end
53
+ @mock_calls.push( [name,test] )
54
+ end
55
+
56
+ # Call this at the end of a test to ensure that all scheduled calls
57
+ # have been made to the mock
58
+ #
59
+ def __verify
60
+ if @next_call != @mock_calls.length
61
+ raise RUNIT::AssertionFailedError,
62
+ "not all expected method calls were made to #{@name}",
63
+ caller
64
+ end
65
+ end
66
+
67
+
68
+ private
69
+ # Dispatches aribtrary method calls to the next mocked behaviour
70
+ #
71
+ def method_missing( name, *args, &block )
72
+ __mock_call( name, args, (block_given? ? block : nil) )
73
+ end
74
+
75
+ # Implements a method call using the next mocked behaviour and asserts
76
+ # that the expected method is called with the expected number of
77
+ # arguments.
78
+ #
79
+ def __mock_call( name, args, block )
80
+ if @next_call >= @mock_calls.length
81
+ raise RUNIT::AssertionFailedError,
82
+ "unexpected call to #{name} method of #{@name}",
83
+ caller(2)
84
+ end
85
+
86
+ expected_name,body = @mock_calls[@next_call]
87
+ @next_call += 1
88
+
89
+ if name != expected_name
90
+ raise RUNIT::AssertionFailedError,
91
+ "wrong method called on #{@name}; " +
92
+ "expected #{expected_name}, was #{name}",
93
+ caller(2)
94
+ end
95
+
96
+ args_length = args.length + (block ? 1 : 0)
97
+
98
+ if body.arity < 0
99
+ if (body.arity+1).abs > args_length
100
+ raise RUNIT::AssertionFailedError,
101
+ "too few arguments to #{name} method of #{@name}; " +
102
+ "require #{(body.arity+1).abs}, got #{args.length}",
103
+ caller(2)
104
+ end
105
+ else
106
+ if body.arity != args_length
107
+ raise RUNIT::AssertionFailedError,
108
+ "wrong number of arguments to " +
109
+ "#{name} method of #{@name}; " +
110
+ "require #{body.arity}, got #{args.length}",
111
+ caller(2)
112
+ end
113
+ end
114
+
115
+ if respond_to? Mock.__pre(name)
116
+ if block
117
+ precondition_ok = __send__( Mock.__pre(name), *args, &block )
118
+ else
119
+ precondition_ok = __send__( Mock.__pre(name), *args )
120
+ end
121
+
122
+ if not precondition_ok
123
+ raise RUNIT::AssertionFailedError,
124
+ "precondition of #{name} method violated",
125
+ caller(2)
126
+ end
127
+ end
128
+
129
+ if block
130
+ instance_eval { body.call( block, *args ) }
131
+ else
132
+ instance_eval { body.call( *args ) }
133
+ end
134
+ end
135
+
136
+ # The name of a precondition for a method
137
+ def Mock.__pre( method )
138
+ "__pre_#{method.to_i}".intern
139
+ end
140
+
141
+
142
+ def Mock.method_added( name )
143
+ unless(/^__pre_/.match(name.to_s))
144
+ pre = self.__pre(name)
145
+ alias_method( pre, name )
146
+ undef_method(name)
147
+ end
148
+ end
149
+ end