ruby_aem 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,131 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ require 'ruby_aem/handlers/file'
18
+ require 'ruby_aem/handlers/html'
19
+ require 'ruby_aem/handlers/json'
20
+ require 'ruby_aem/handlers/simple'
21
+ require 'ruby_aem/handlers/xml'
22
+ require 'ruby_aem/swagger'
23
+ require 'swagger_aem'
24
+
25
+ module RubyAem
26
+ # Client class makes Swagger AEM API calls and handles the response as
27
+ # configured in conf/spec.yaml .
28
+ class Client
29
+
30
+ # Initialise a client.
31
+ #
32
+ # @param apis a hash of Swagger AEM client's API instances
33
+ # @param spec ruby_aem specification
34
+ # @return new RubyAem::Client instance
35
+ def initialize(apis, spec)
36
+ @apis = apis
37
+ @spec = spec
38
+ end
39
+
40
+ # Make an API call using the relevant Swagger AEM API client.
41
+ # Clazz and action parameters are used to identify the action, API, and params
42
+ # from ruby_aem specification, alongside the response handlers.
43
+ #
44
+ # @param clazz the class name of the caller resource
45
+ # @param action the action of the API call
46
+ # @param info additional information of the API call
47
+ # @return RubyAem::Result
48
+ def call(clazz, action, info)
49
+
50
+ component = clazz.name.downcase.sub('rubyaem::', '')
51
+ action_spec = @spec[component]['actions'][action]
52
+
53
+ api = @apis[action_spec['api'].to_sym]
54
+ operation = action_spec['operation']
55
+
56
+ params = []
57
+ required_params = action_spec['params']['required'] || {}
58
+ required_params.each { |key, value|
59
+ params.push(value % info)
60
+ }
61
+ params.push({})
62
+ optional_params = action_spec['params']['optional'] || {}
63
+ optional_params.each { |key, value|
64
+ add_optional_param(key, value, params, info)
65
+ }
66
+
67
+ base_responses = @spec[component]['responses'] || {}
68
+ action_responses = action_spec['responses'] || {}
69
+ responses = base_responses.merge(action_responses)
70
+
71
+ begin
72
+ method = RubyAem::Swagger.operation_to_method(operation)
73
+ data, status_code, headers = api.send("#{method}_with_http_info", *params)
74
+ handle(data, status_code, headers, responses, info)
75
+ rescue SwaggerAemClient::ApiError => err
76
+ handle(err.response_body, err.code, err.response_headers, responses, info)
77
+ end
78
+ end
79
+
80
+ # Add optional param into params list.
81
+ #
82
+ # @param key optional param key
83
+ # @param value optional param value
84
+ # @param params combined list of required and optional parameters
85
+ # @param info additional information
86
+ def add_optional_param(key, value, params, info)
87
+ # if there is no value in optional param spec,
88
+ # then only add optional param that is set in info
89
+ if !value
90
+ if info.key? key.to_sym
91
+ params[-1][key.to_sym] = info[key.to_sym]
92
+ end
93
+ # if value is provided in optional param spec,
94
+ # then apply variable interpolation the same way as required param
95
+ else
96
+ if value.class == String
97
+ if value == '__FILE__'
98
+ File.open("#{info[:file_path]}/#{info[:package_name]}-#{info[:package_version]}.zip", 'r') { |file|
99
+ params[-1][key.to_sym] = file
100
+ }
101
+ else
102
+ params[-1][key.to_sym] = value % info
103
+ end
104
+ else
105
+ params[-1][key.to_sym] = value
106
+ end
107
+ end
108
+ end
109
+
110
+ # Handle a response based on status code and a given list of response specifications.
111
+ # If none of the response specifications contains the status code, a failure result
112
+ # will then be returned.
113
+ #
114
+ # @param data data payload
115
+ # @param status_code response HTTP status code
116
+ # @param headers response HTTP headers
117
+ # @param responses a list of response specifications as configured in conf/spec.yaml
118
+ # @param info additional information
119
+ # @return RubyAem::Result
120
+ def handle(data, status_code, headers, responses, info)
121
+ if responses.key?(status_code)
122
+ response_spec = responses[status_code]
123
+ handler = response_spec['handler']
124
+ result = Handlers.send(handler, data, status_code, headers, response_spec, info)
125
+ else
126
+ result = Result.new('failure', "Unexpected response\nstatus code: #{status_code}\nheaders: #{headers}\ndata: #{data}")
127
+ end
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,53 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ module RubyAem
18
+ # ConfigProperty class contains API calls related to managing an AEM config property.
19
+ class ConfigProperty
20
+
21
+ # Initialise a config property
22
+ #
23
+ # @param client RubyAem::Client
24
+ # @param name the property's name
25
+ # @param type the property's type, e.g. Boolean
26
+ # @param value the property's value, e.g. true
27
+ # @return new RubyAem::ConfigProperty instance
28
+ def initialize(client, name, type, value)
29
+ @client = client
30
+ @info = {
31
+ name: name,
32
+ type: type,
33
+ value: value
34
+ }
35
+ end
36
+
37
+ # Create a new config property.
38
+ #
39
+ # @param run_mode AEM run mode: author or publish
40
+ # @return RubyAem::Result
41
+ def create(run_mode)
42
+
43
+ name = RubyAem::Swagger.property_to_parameter(@info[:name])
44
+
45
+ @info[:run_mode] = run_mode
46
+ @info["#{name}".to_sym] = @info[:value]
47
+ @info["#{name}_type_hint".to_sym] = @info[:type]
48
+
49
+ @client.call(self.class, __callee__.to_s, @info)
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,65 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ module RubyAem
18
+ # FlushAgent class contains API calls related to managing an AEM flush agent.
19
+ class FlushAgent
20
+
21
+ # Initialise a flush agent.
22
+ #
23
+ # @param client RubyAem::Client
24
+ # @param run_mode AEM run mode: author or publish
25
+ # @param name the flush agent's name, e.g. some-flush-agent
26
+ # @return new RubyAem::FlushAgent instance
27
+ def initialize(client, run_mode, name)
28
+ @client = client
29
+ @info = {
30
+ run_mode: run_mode,
31
+ name: name
32
+ }
33
+ end
34
+
35
+ # Create or update a flush agent.
36
+ #
37
+ # @param title flush agent title
38
+ # @param description flush agent description
39
+ # @param dest_base_url base URL of the agent target destination, e.g. http://somedispatcher:8080
40
+ # @return RubyAem::Result
41
+ def create_update(title, description, dest_base_url)
42
+ @info[:title] = title
43
+ @info[:description] = description
44
+ @info[:dest_base_url] = dest_base_url
45
+ @client.call(self.class, __callee__.to_s, @info)
46
+ end
47
+
48
+ # Delete the flush agent.
49
+ #
50
+ # @return RubyAem::Result
51
+ def delete()
52
+ @client.call(self.class, __callee__.to_s, @info)
53
+ end
54
+
55
+ # Check whether the flush agent exists or not.
56
+ # If the flush agent exists, this method returns a success result.
57
+ # Otherwise it returns a failure result.
58
+ #
59
+ # @return RubyAem::Result
60
+ def exists()
61
+ @client.call(self.class, __callee__.to_s, @info)
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,101 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ module RubyAem
18
+ # Group class contains API calls related to managing an AEM group.
19
+ class Group
20
+
21
+ # Initialise a group.
22
+ #
23
+ # @param client RubyAem::Client
24
+ # @param path the path to group node, e.g. /home/groups/s/
25
+ # @param name the name of the AEM group, e.g. somegroup
26
+ # @return new RubyAem::Group instance
27
+ def initialize(client, path, name)
28
+ @client = client
29
+ @info = {
30
+ path: path,
31
+ name: name
32
+ }
33
+ end
34
+
35
+ # Create a new group.
36
+ #
37
+ # @return RubyAem::Result
38
+ def create()
39
+ if !@info[:path].match(/^\//)
40
+ @info[:path] = "/#{@info[:path]}"
41
+ end
42
+ @client.call(self.class, __callee__.to_s, @info)
43
+ end
44
+
45
+ # Delete the group.
46
+ #
47
+ # @return RubyAem::Result
48
+ def delete()
49
+ result = find_authorizable_id
50
+ if result.data
51
+ @info[:path] = RubyAem::Swagger.path(@info[:path])
52
+ @client.call(self.class, __callee__.to_s, @info)
53
+ else
54
+ result
55
+ end
56
+ end
57
+
58
+ # Check whether the group exists or not.
59
+ # If the group exists, this method returns a success result.
60
+ # Otherwise it returns a failure result.
61
+ #
62
+ # @return RubyAem::Result
63
+ def exists()
64
+ @info[:path] = RubyAem::Swagger.path(@info[:path])
65
+ @client.call(self.class, __callee__.to_s, @info)
66
+ end
67
+
68
+ # Set the group's permission.
69
+ #
70
+ # @param permission_path the path that the group's permission is to be set against, e.g. /etc/replication
71
+ # @param permission_csv comma-separated-values of the group's permission, e.g. read:true,modify:true
72
+ # @return RubyAem::Result
73
+ def set_permission(permission_path, permission_csv)
74
+ @info[:permission_path] = permission_path
75
+ @info[:permission_csv] = permission_csv
76
+ @client.call(self.class, __callee__.to_s, @info)
77
+ end
78
+
79
+ # Add another group as a member of this group.
80
+ #
81
+ # @param member the name of the member group to be added
82
+ # @return RubyAem::Result
83
+ def add_member(member)
84
+ result = find_authorizable_id
85
+ if result.data
86
+ @info[:member] = member
87
+ @client.call(self.class, __callee__.to_s, @info)
88
+ else
89
+ result
90
+ end
91
+ end
92
+
93
+ # Find the group's authorizable ID.
94
+ #
95
+ # @return RubyAem::Result
96
+ def find_authorizable_id()
97
+ @client.call(self.class, __callee__.to_s, @info)
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,42 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ module RubyAem
18
+ # Response handlers for file payload.
19
+ module Handlers
20
+
21
+ # Handle downloaded file by copying from temporary location to file_path info.
22
+ # The downloaded file in temporary location will then be deleted.
23
+ # data, status_code, and headers are all returned from RubyAem::Client call.
24
+ #
25
+ # @param data data payload
26
+ # @param status_code response HTTP status code
27
+ # @param headers response HTTP headers
28
+ # @param response_spec response specification as configured in conf/spec.yaml
29
+ # @param info additional information
30
+ # @return RubyAem::Result
31
+ def Handlers.file_download(data, status_code, headers, response_spec, info)
32
+
33
+ FileUtils.cp(data.path, "#{info[:file_path]}/#{info[:package_name]}-#{info[:package_version]}.zip")
34
+ data.delete
35
+
36
+ message = response_spec['message'] % info
37
+
38
+ RubyAem::Result.new('success', message)
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,46 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ require 'nokogiri'
18
+
19
+ module RubyAem
20
+ # Response handlers for HTML payload.
21
+ module Handlers
22
+
23
+ # Parse authorizable ID from response body data.
24
+ # This is used to get the authorizable ID of a newly created user/group.
25
+ #
26
+ # @param data data payload
27
+ # @param status_code response HTTP status code
28
+ # @param headers response HTTP headers
29
+ # @param response_spec response specification as configured in conf/spec.yaml
30
+ # @param info additional information
31
+ # @return RubyAem::Result
32
+ def Handlers.html_authorizable_id(data, status_code, headers, response_spec, info)
33
+
34
+ html = Nokogiri::HTML(data)
35
+ authorizable_id = html.xpath('//title/text()').to_s
36
+ authorizable_id.slice! "Content created #{info[:path]}"
37
+ info[:authorizable_id] = authorizable_id.sub(/^\//, '')
38
+
39
+ status = response_spec['status']
40
+ message = response_spec['message'] % info
41
+
42
+ RubyAem::Result.new(status, message)
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,96 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ require 'json'
18
+
19
+ module RubyAem
20
+ # Response handlers for JSON payload.
21
+ module Handlers
22
+
23
+ # Handle JSON response payload containing authorizable ID.
24
+ #
25
+ # @param data data payload
26
+ # @param status_code response HTTP status code
27
+ # @param headers response HTTP headers
28
+ # @param response_spec response specification as configured in conf/spec.yaml
29
+ # @param info additional information
30
+ # @return RubyAem::Result
31
+ def Handlers.json_authorizable_id(data, status_code, headers, response_spec, info)
32
+
33
+ json = JSON.parse(data)
34
+ authorizable_id = nil
35
+ if json['success'] == true && json['hits'].length == 1
36
+ authorizable_id = json['hits'][0]['name']
37
+ info[:authorizable_id] = authorizable_id
38
+ message = response_spec['message'] % info
39
+ else
40
+ message = "User/Group #{info[:name]} authorizable ID not found"
41
+ end
42
+
43
+ status = response_spec['status']
44
+
45
+ result = RubyAem::Result.new(status, message)
46
+ result.data = authorizable_id
47
+ result
48
+ end
49
+
50
+ # Handle package JSON payload. Result status is determined directly by success field.
51
+ #
52
+ # @param data data payload
53
+ # @param status_code response HTTP status code
54
+ # @param headers response HTTP headers
55
+ # @param response_spec response specification as configured in conf/spec.yaml
56
+ # @param info additional information
57
+ # @return RubyAem::Result
58
+ def Handlers.json_package_service(data, status_code, headers, response_spec, info)
59
+
60
+ json = JSON.parse(data)
61
+
62
+ status = json['success'] == true ? 'success' : 'failure'
63
+ message = json['msg']
64
+
65
+ RubyAem::Result.new(status, message)
66
+ end
67
+
68
+ # Handle package filter JSON payload.
69
+ #
70
+ # @param data data payload
71
+ # @param status_code response HTTP status code
72
+ # @param headers response HTTP headers
73
+ # @param response_spec response specification as configured in conf/spec.yaml
74
+ # @param info additional information
75
+ # @return RubyAem::Result
76
+ def Handlers.json_package_filter(data, status_code, headers, response_spec, info)
77
+
78
+ json = JSON.parse(data)
79
+
80
+ filter = []
81
+ json.each do |key, value|
82
+ if json[key]['root'] != nil
83
+ filter.push(json[key]['root'])
84
+ end
85
+ end
86
+
87
+ message = response_spec['message'] % info
88
+
89
+ result = RubyAem::Result.new('success', message)
90
+ result.data = filter
91
+ result
92
+
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,41 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ require 'ruby_aem/result'
18
+
19
+ module RubyAem
20
+ # Response handlers for no payload.
21
+ module Handlers
22
+
23
+ # Simple handler by returning result that contains status and message as
24
+ # configured in conf/spec.yaml AS-IS.
25
+ #
26
+ # @param data data payload
27
+ # @param status_code response HTTP status code
28
+ # @param headers response HTTP headers
29
+ # @param response_spec response specification as configured in conf/spec.yaml
30
+ # @param info additional information
31
+ # @return RubyAem::Result
32
+ def Handlers.simple(data, status_code, headers, response_spec, info)
33
+
34
+ status = response_spec['status']
35
+ message = response_spec['message'] % info
36
+
37
+ RubyAem::Result.new(status, message)
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,50 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ require 'nokogiri'
18
+
19
+ module RubyAem
20
+ # Response handlers for XML payload.
21
+ module Handlers
22
+
23
+ # Handle package list XML by removing non-packages data.
24
+ #
25
+ # @param data data payload
26
+ # @param status_code response HTTP status code
27
+ # @param headers response HTTP headers
28
+ # @param response_spec response specification as configured in conf/spec.yaml
29
+ # @param info additional information
30
+ # @return RubyAem::Result
31
+ def Handlers.xml_package_list(data, status_code, headers, response_spec, info)
32
+
33
+ xml = Nokogiri::XML(data)
34
+
35
+ status_code = xml.xpath('//crx/response/status/@code').to_s
36
+ status_text = xml.xpath('//crx/response/status/text()').to_s
37
+
38
+ if status_code == '200' && status_text == 'ok'
39
+ message = response_spec['message'] % info
40
+ result = RubyAem::Result.new('success', message)
41
+ result.data = xml.xpath('//crx/response/data/packages')
42
+ else
43
+ result = RubyAem::Result.new('failure', "Unable to retrieve package list, getting status code #{status_code} and status text #{status_text}")
44
+ end
45
+
46
+ result
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,63 @@
1
+ =begin
2
+ Copyright 2016 Shine Solutions
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ module RubyAem
18
+ # Node class contains API calls related to managing an AEM node.
19
+ class Node
20
+
21
+ # Initialise a node.
22
+ #
23
+ # @param client RubyAem::Client
24
+ # @param path the path to the node, e.g. /apps/system/
25
+ # @param name the node name, e.g. somenode
26
+ # @return new RubyAem::Node instance
27
+ def initialize(client, path, name)
28
+ @client = client
29
+ @info = {
30
+ path: path,
31
+ name: name
32
+ }
33
+
34
+ @info[:path] = RubyAem::Swagger.path(@info[:path])
35
+ end
36
+
37
+ # Create a new node.
38
+ #
39
+ # @param type the node type, e.g. sling:Folder
40
+ # @return RubyAem::Result
41
+ def create(type)
42
+ @info[:type] = type
43
+ @client.call(self.class, __callee__.to_s, @info)
44
+ end
45
+
46
+ # Delete the node.
47
+ #
48
+ # @return RubyAem::Result
49
+ def delete()
50
+ @client.call(self.class, __callee__.to_s, @info)
51
+ end
52
+
53
+ # Check whether the node exists or not.
54
+ # If the node exists, this method returns a success result.
55
+ # Otherwise it returns a failure result.
56
+ #
57
+ # @return RubyAem::Result
58
+ def exists()
59
+ @client.call(self.class, __callee__.to_s, @info)
60
+ end
61
+
62
+ end
63
+ end