jiraSOAP 0.6.1 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.yardopts +10 -0
  2. data/ChangeLog +18 -0
  3. data/{LICENSE → LICENSE.txt} +0 -0
  4. data/README.markdown +4 -6
  5. data/lib/jiraSOAP.rb +0 -2
  6. data/lib/jiraSOAP/JIRAservice.rb +5 -5
  7. data/lib/jiraSOAP/api.rb +77 -696
  8. data/lib/jiraSOAP/api/additions.rb +22 -0
  9. data/lib/jiraSOAP/api/attachments.rb +33 -0
  10. data/lib/jiraSOAP/api/avatars.rb +64 -0
  11. data/lib/jiraSOAP/api/comments.rb +33 -0
  12. data/lib/jiraSOAP/api/filters.rb +20 -0
  13. data/lib/jiraSOAP/api/issue_data_types.rb +51 -0
  14. data/lib/jiraSOAP/api/issues.rb +102 -0
  15. data/lib/jiraSOAP/api/project_roles.rb +49 -0
  16. data/lib/jiraSOAP/api/projects.rb +67 -0
  17. data/lib/jiraSOAP/api/schemes.rb +17 -0
  18. data/lib/jiraSOAP/api/server_info.rb +18 -0
  19. data/lib/jiraSOAP/api/users.rb +35 -0
  20. data/lib/jiraSOAP/api/versions.rb +50 -0
  21. data/lib/jiraSOAP/entities.rb +5 -1
  22. data/lib/jiraSOAP/entities/attachment_metadata.rb +9 -22
  23. data/lib/jiraSOAP/entities/avatar.rb +10 -23
  24. data/lib/jiraSOAP/entities/comment.rb +12 -31
  25. data/lib/jiraSOAP/entities/component.rb +1 -1
  26. data/lib/jiraSOAP/entities/custom_field_value.rb +5 -11
  27. data/lib/jiraSOAP/entities/described_entity.rb +4 -4
  28. data/lib/jiraSOAP/entities/dynamic_entity.rb +5 -5
  29. data/lib/jiraSOAP/entities/entity.rb +28 -13
  30. data/lib/jiraSOAP/entities/field.rb +1 -1
  31. data/lib/jiraSOAP/entities/filter.rb +5 -14
  32. data/lib/jiraSOAP/entities/issue.rb +29 -88
  33. data/lib/jiraSOAP/entities/issue_property.rb +4 -4
  34. data/lib/jiraSOAP/entities/issue_security_scheme.rb +1 -1
  35. data/lib/jiraSOAP/entities/issue_type.rb +4 -5
  36. data/lib/jiraSOAP/entities/named_entity.rb +4 -4
  37. data/lib/jiraSOAP/entities/notification_scheme.rb +1 -1
  38. data/lib/jiraSOAP/entities/permission.rb +7 -10
  39. data/lib/jiraSOAP/entities/permission_mapping.rb +5 -10
  40. data/lib/jiraSOAP/entities/permission_scheme.rb +3 -4
  41. data/lib/jiraSOAP/entities/priority.rb +4 -3
  42. data/lib/jiraSOAP/entities/project.rb +9 -30
  43. data/lib/jiraSOAP/entities/project_role.rb +1 -1
  44. data/lib/jiraSOAP/entities/resolution.rb +1 -1
  45. data/lib/jiraSOAP/entities/scheme.rb +1 -1
  46. data/lib/jiraSOAP/entities/server_configuration.rb +14 -53
  47. data/lib/jiraSOAP/entities/server_info.rb +8 -26
  48. data/lib/jiraSOAP/entities/status.rb +1 -1
  49. data/lib/jiraSOAP/entities/time_info.rb +5 -10
  50. data/lib/jiraSOAP/entities/user.rb +5 -15
  51. data/lib/jiraSOAP/entities/username.rb +4 -0
  52. data/lib/jiraSOAP/entities/version.rb +6 -20
  53. data/lib/jiraSOAP/handsoap_extensions.rb +4 -2
  54. data/lib/jiraSOAP/macruby_bonuses.rb +12 -5
  55. data/lib/jiraSOAP/url.rb +13 -24
  56. data/yard-jiraSOAP.rb +65 -0
  57. metadata +52 -92
  58. data/lib/jiraSOAP/api/convenience.rb +0 -12
  59. data/lib/jiraSOAP/entities/remote_entity.rb +0 -7
@@ -0,0 +1,10 @@
1
+ --protected
2
+ --private
3
+ --no-cache
4
+ --markup markdown
5
+ --readme README.markdown
6
+ --load './yard-jiraSOAP.rb'
7
+ lib/**/*.rb
8
+ -
9
+ LICENSE.txt
10
+ ChangeLog
data/ChangeLog CHANGED
@@ -1,3 +1,21 @@
1
+ Version 0.7.1
2
+ * Remove AOT compiled files from gem
3
+
4
+ Version 0.7
5
+
6
+ * Added YARD extension for documentation
7
+ * Removed URL class in favour of directly using underlying objects
8
+ * Added AOT compilation for MacRuby
9
+ * Moved RemoteAPI into the JIRA namespace
10
+ * Alias #get_favourite_filter to #get_favorite_filter
11
+
12
+ * Tweaked parsing logic more in preparation for the builder generalization
13
+ * Various documentation updates
14
+
15
+ * Removed jeweler development dependency
16
+ * Removed yardstick development dependency
17
+ * General tweaking of the rakefile, gemspec, gemfile, and .yardopts
18
+
1
19
  Version 0.6.1
2
20
 
3
21
  * Added RemoteAPIAdditions module for conveniences
File without changes
@@ -20,7 +20,7 @@ Pick up where `jira4r` left off:
20
20
  - Implement the current API; `jira4r` does not implement APIs from JIRA 4.x
21
21
  - More natural interface; not adhering to the API when the API is weird
22
22
  - Speed; network latency is bad enough
23
- - Excellent documentation, since the documentation given by Atlassian is so terse
23
+ - Excellent documentation, since the documentation given by Atlassian can be terse (the newer APIs are documented)
24
24
 
25
25
 
26
26
  Getting Started
@@ -33,8 +33,7 @@ Getting Started
33
33
 
34
34
  # Building from source
35
35
  git clone git://github.com/Marketcircle/jiraSOAP.git
36
- rake build
37
- rake install
36
+ rake build install
38
37
 
39
38
  Once installed, you can run a quick demo (making appropriate substitutions):
40
39
 
@@ -60,15 +59,14 @@ TODO
60
59
  - Performance optimizations; there are a number of places that can be optimized
61
60
  + Using GCD/Threads for parsing arrays of results; a significant speed up for large types and large arrays (ie. creating issues from JQL searches)
62
61
  - Public test suite
63
- + Needs a mock server
62
+ + Needs a lot of mock data
64
63
 
65
64
 
66
65
  Note on Patches/Pull Requests
67
66
  -----------------------------
68
67
 
69
68
  This project has a tendancy to change drastically between releases as it
70
- is still unstable, so patches may not cleanly apply. It may be better to
71
- just open an issue.
69
+ is still unstable, so patches may not cleanly apply.
72
70
 
73
71
  If you want to help by submitting patches:
74
72
 
@@ -1,4 +1,3 @@
1
- require 'logger'
2
1
  require 'time'
3
2
  require 'uri'
4
3
  require 'nokogiri'
@@ -15,7 +14,6 @@ end
15
14
 
16
15
  require 'jiraSOAP/entities'
17
16
  require 'jiraSOAP/api'
18
- require 'jiraSOAP/api/convenience'
19
17
  require 'jiraSOAP/JIRAservice'
20
18
 
21
19
  require 'jiraSOAP/macruby_bonuses' if RUBY_ENGINE == 'macruby'
@@ -10,8 +10,8 @@
10
10
  # It is best to treat this class as a singleton, but it is not enforced
11
11
  # in case you want to be able to login as multiple users to the same endpoint.
12
12
  class JIRA::JIRAService < Handsoap::Service
13
- include RemoteAPI
14
- include RemoteAPIAdditions
13
+ include JIRA::RemoteAPI
14
+ include JIRA::RemoteAPIAdditions
15
15
 
16
16
  # @return [String]
17
17
  attr_reader :auth_token
@@ -19,7 +19,7 @@ class JIRA::JIRAService < Handsoap::Service
19
19
  # @return [String]
20
20
  attr_reader :user
21
21
 
22
- # @return [URL]
22
+ # @return [String]
23
23
  attr_reader :endpoint_url
24
24
 
25
25
  # Initialize and log in.
@@ -33,9 +33,9 @@ class JIRA::JIRAService < Handsoap::Service
33
33
  jira
34
34
  end
35
35
 
36
- # @param [String,URL] endpoint_url for the JIRA server
36
+ # @param [String,URI::HTTP,NSURL] endpoint_url for the JIRA server
37
37
  def initialize endpoint_url
38
- @endpoint_url = endpoint_url
38
+ @endpoint_url = endpoint_url.to_s
39
39
  JIRA::JIRAService.endpoint({
40
40
  uri:"#{endpoint_url.to_s}/rpc/soap/jirasoapservice-v2",
41
41
  version:2
@@ -1,13 +1,31 @@
1
+ require 'jiraSOAP/api/users'
2
+ require 'jiraSOAP/api/avatars'
3
+ require 'jiraSOAP/api/versions'
4
+ require 'jiraSOAP/api/projects'
5
+ require 'jiraSOAP/api/project_roles'
6
+ require 'jiraSOAP/api/schemes'
7
+ require 'jiraSOAP/api/issues'
8
+ require 'jiraSOAP/api/filters'
9
+ require 'jiraSOAP/api/server_info'
10
+ require 'jiraSOAP/api/attachments'
11
+ require 'jiraSOAP/api/comments'
12
+ require 'jiraSOAP/api/issue_data_types'
13
+ require 'jiraSOAP/api/additions'
14
+
15
+ module JIRA
16
+
1
17
  # Contains the API defined by Atlassian for the [JIRA SOAP service](http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/soap/JiraSoapService.html).
2
18
  #
3
19
  # There are several cases where this API diverges from the one defined by
4
20
  # Atlassian; most notably, this API tries to be more idomatically Ruby by using
5
- # snake case for method names.
21
+ # snake case for method names, default values, varargs, etc..
6
22
  # @todo logging
7
- # @todo code refactoring and de-duplication
8
- # @todo break the API down by task, like Apple's developer documentation;
9
- # I can break the tasks down by CRUD or by what they affect, or both
10
- # @todo progressWorkflowAction and friends [target v0.7]
23
+ # @todo progressWorkflowAction and friends [target v0.8]
24
+ # @todo get Nokogiri element directly and monkey patch nokogiri directly
25
+ # instead of the handsoap wrapper
26
+ # @todo remove the get_ prefix from api methods that don't need them
27
+ # @todo monkey patch Array to include a #to_soap method
28
+ # @todo document how to override the url_class setting
11
29
  module RemoteAPI
12
30
 
13
31
  # XPath constant to get a node containing a response array.
@@ -15,713 +33,76 @@ module RemoteAPI
15
33
  # cannot use a more blunt XPath expression.
16
34
  RESPONSE_XPATH = '/node()[1]/node()[1]/node()[1]/node()[2]'
17
35
 
36
+
37
+ # @group Logging in/out
38
+
39
+ # @todo change method name to #login! since we are changing internal state?
18
40
  # The first method to call; other methods will fail until you are logged in.
19
41
  # @param [String] user JIRA user name to login with
20
42
  # @param [String] password
21
- # @return [true]
22
- def login(user, password)
23
- response = invoke('soap:login') { |msg|
24
- msg.add 'soap:in0', user
25
- msg.add 'soap:in1', password
26
- }
27
- # cache now that we know it is safe to do so
28
- @user = user
43
+ # @return [Boolean] true if successful
44
+ def login username, password
45
+ response = build 'login', username, password
29
46
  @auth_token = response.document.xpath('//loginReturn').first.to_s
47
+ @user = user
30
48
  true
31
49
  end
32
50
 
51
+ # @todo change method name to #logout! since we are changing internal state?
33
52
  # You only need to call this to make an explicit logout; normally, a session
34
53
  # will automatically expire after a set time (configured on the server).
35
- # @return [true,false] true if successful, otherwise false
54
+ # @return [Boolean] true if successful, otherwise false
36
55
  def logout
37
- response = invoke('soap:logout') { |msg|
38
- msg.add 'soap:in0', @auth_token
39
- }
40
- response.document.xpath('//logoutReturn').to_boolean
41
- end
42
-
43
- # @return [[JIRA::Priority]]
44
- def get_priorities
45
- response = invoke('soap:getPriorities') { |msg|
46
- msg.add 'soap:in0', @auth_token
47
- }
48
- response.document.xpath("#{RESPONSE_XPATH}/getPrioritiesReturn").map {
49
- |frag| JIRA::Priority.new_with_xml frag
50
- }
51
- end
52
-
53
- # @return [[JIRA::Resolution]]
54
- def get_resolutions
55
- response = invoke('soap:getResolutions') { |msg|
56
- msg.add 'soap:in0', @auth_token
57
- }
58
- response.document.xpath("#{RESPONSE_XPATH}/getResolutionsReturn").map {
59
- |frag| JIRA::Resolution.new_with_xml frag
60
- }
61
- end
62
-
63
- # @return [[JIRA::Field]]
64
- def get_custom_fields
65
- response = invoke('soap:getCustomFields') { |msg|
66
- msg.add 'soap:in0', @auth_token
67
- }
68
- response.document.xpath("#{RESPONSE_XPATH}/getCustomFieldsReturn").map {
69
- |frag| JIRA::Field.new_with_xml frag
70
- }
71
- end
72
-
73
- # @return [[JIRA::IssueType]]
74
- def get_issue_types
75
- response = invoke('soap:getIssueTypes') { |msg|
76
- msg.add 'soap:in0', @auth_token
77
- }
78
- response.document.xpath("#{RESPONSE_XPATH}/getIssueTypesReturn").map {
79
- |frag| JIRA::IssueType.new_with_xml frag
80
- }
81
- end
82
-
83
- # @return [[JIRA::Status]]
84
- def get_statuses
85
- response = invoke('soap:getStatuses') { |msg|
86
- msg.add 'soap:in0', @auth_token
87
- }
88
- response.document.xpath("#{RESPONSE_XPATH}/getStatusesReturn").map {
89
- |frag| JIRA::Status.new_with_xml frag
90
- }
91
- end
92
-
93
- # @return [[JIRA::NotificationScheme]]
94
- def get_notification_schemes
95
- response = invoke('soap:getNotificationSchemes') { |msg|
96
- msg.add 'soap:in0', @auth_token
97
- }
98
- response.document.xpath("#{RESPONSE_XPATH}/getNotificationSchemesReturn").map {
99
- |frag| JIRA::NotificationScheme.new_with_xml frag
100
- }
101
- end
102
-
103
- # @param [String] project_key
104
- # @return [[JIRA::Version]]
105
- def get_versions_for_project(project_key)
106
- response = invoke('soap:getVersions') { |msg|
107
- msg.add 'soap:in0', @auth_token
108
- msg.add 'soap:in1', project_key
109
- }
110
- response.document.xpath("#{RESPONSE_XPATH}/getVersionsReturn").map {
111
- |frag| JIRA::Version.new_with_xml frag
112
- }
113
- end
114
-
115
- # You need to explicitly ask for schemes in order to get them. By
116
- # default, most project fetching methods purposely leave out all
117
- # the scheme information as permission schemes can be very large.
118
- # @param [String] project_key
119
- # @return [JIRA::Project]
120
- def get_project_with_key(project_key)
121
- response = invoke('soap:getProjectByKey') { |msg|
122
- msg.add 'soap:in0', @auth_token
123
- msg.add 'soap:in1', project_key
124
- }
125
- JIRA::Project.new_with_xml response.document.xpath('//getProjectByKeyReturn').first
126
- end
127
-
128
- # @param [String] user_name
129
- # @return [JIRA::User]
130
- def get_user_with_name(user_name)
131
- response = invoke('soap:getUser') { |msg|
132
- msg.add 'soap:in0', @auth_token
133
- msg.add 'soap:in1', user_name
134
- }
135
- JIRA::User.new_with_xml response.document.xpath('//getUserReturn').first
136
- end
137
-
138
- # Gets you the default avatar image for a project; if you want all
139
- # the avatars for a project, use {#get_project_avatars_for_key}.
140
- # @param [String] project_key
141
- # @return [JIRA::Avatar]
142
- def get_project_avatar_for_key(project_key)
143
- response = invoke('soap:getProjectAvatar') { |msg|
144
- msg.add 'soap:in0', @auth_token
145
- msg.add 'soap:in1', project_key
146
- }
147
- JIRA::Avatar.new_with_xml response.document.xpath('//getProjectAvatarReturn').first
148
- end
149
-
150
- # Gets ALL avatars for a given project with this method; if you
151
- # just want the project avatar, use {#get_project_avatar_for_key}.
152
- # @param [String] project_key
153
- # @param [true,false] include_default_avatars
154
- # @return [[JIRA::Avatar]]
155
- def get_project_avatars_for_key(project_key, include_default_avatars = false)
156
- response = invoke('soap:getProjectAvatars') { |msg|
157
- msg.add 'soap:in0', @auth_token
158
- msg.add 'soap:in1', project_key
159
- msg.add 'soap:in2', include_default_avatars
160
- }
161
- response.document.xpath("#{RESPONSE_XPATH}/getProjectAvatarsReturn").map {
162
- |frag| JIRA::Avatar.new_with_xml frag
163
- }
164
- end
165
-
166
- # This method is the equivalent of making an advanced search from the
167
- # web interface.
168
- #
169
- # During my own testing, I found that HTTP requests could timeout for really
170
- # large requests (~2500 results). So I set a more reasonable upper limit;
171
- # feel free to override it, but be aware of the potential issues.
172
- #
173
- # The JIRA::Issue structure does not include any comments or attachments.
174
- # @param [String] jql_query JQL query as a string
175
- # @param [Fixnum] max_results limit on number of returned results;
176
- # the value may be overridden by the server if max_results is too large
177
- # @return [[JIRA::Issue]]
178
- def get_issues_from_jql_search(jql_query, max_results = 2000)
179
- response = invoke('soap:getIssuesFromJqlSearch') { |msg|
180
- msg.add 'soap:in0', @auth_token
181
- msg.add 'soap:in1', jql_query
182
- msg.add 'soap:in2', max_results
183
- }
184
- response.document.xpath("#{RESPONSE_XPATH}/getIssuesFromJqlSearchReturn").map {
185
- |frag| JIRA::Issue.new_with_xml frag
186
- }
187
- end
188
-
189
- # This method can update most, but not all, issue fields. Some limitations
190
- # are because of how the API is designed, and some are because I have not
191
- # yet implemented the ability to update fields made of custom objects (things
192
- # in the JIRA module).
193
- #
194
- # Fields known to not update via this method:
195
- # - status - use {#progress_workflow_action}
196
- # - attachments - use {#add_base64_encoded_attachments_to_issue_with_key}
197
- #
198
- # Though JIRA::FieldValue objects have an id field, they do not expect to be
199
- # given id values. You must use the name of the field you wish to update.
200
- # @example Usage With A Normal Field
201
- # summary = JIRA::FieldValue.new 'summary', ['My new summary']
202
- # @example Usage With A Custom Field
203
- # custom_field = JIRA::FieldValue.new 'customfield_10060', ['123456']
204
- # @example Setting a field to be blank/nil
205
- # description = JIRA::FieldValue.new 'description'
206
- # @example Calling the method to update an issue
207
- # jira_service_instance.update_issue 'PROJECT-1', description, custom_field
208
- # @param [String] issue_key
209
- # @param [JIRA::FieldValue] *field_values
210
- # @return [JIRA::Issue]
211
- def update_issue(issue_key, *field_values)
212
- response = invoke('soap:updateIssue') { |msg|
213
- msg.add 'soap:in0', @auth_token
214
- msg.add 'soap:in1', issue_key
215
- msg.add 'soap:in2' do |submsg|
216
- field_values.each { |fv| fv.soapify_for submsg }
217
- end
218
- }
219
- JIRA::Issue.new_with_xml response.document.xpath('//updateIssueReturn').first
220
- end
221
-
222
- # Some fields will be ignored when an issue is created.
223
- # - reporter - you cannot override this value at creation
224
- # - resolution
225
- # - attachments
226
- # - votes
227
- # - status
228
- # - due date - I think this is a bug in jiraSOAP or JIRA
229
- # - environment - I think this is a bug in jiraSOAP or JIRA
230
- # @param [JIRA::Issue] issue
231
- # @return [JIRA::Issue]
232
- def create_issue_with_issue(issue)
233
- response = invoke('soap:createIssue') { |msg|
234
- msg.add 'soap:in0', @auth_token
235
- msg.add 'soap:in1' do |submsg|
236
- issue.soapify_for submsg
237
- end
238
- }
239
- JIRA::Issue.new_with_xml response.document.xpath('//createIssueReturn').first
240
- end
241
-
242
- # @param [String] issue_key
243
- # @return [JIRA::Issue]
244
- def get_issue_with_key(issue_key)
245
- response = invoke('soap:getIssue') { |msg|
246
- msg.add 'soap:in0', @auth_token
247
- msg.add 'soap:in1', issue_key
248
- }
249
- JIRA::Issue.new_with_xml response.document.xpath('//getIssueReturn').first
250
- end
251
-
252
- # @param [String] issue_id
253
- # @return [JIRA::Issue]
254
- def get_issue_with_id(issue_id)
255
- response = invoke('soap:getIssueById') { |msg|
256
- msg.add 'soap:in0', @auth_token
257
- msg.add 'soap:in1', issue_id
258
- }
259
- JIRA::Issue.new_with_xml response.document.xpath('//getIssueByIdReturn').first
260
- end
261
-
262
- # @param [String] issue_key
263
- # @return [[JIRA::Attachment]]
264
- def get_attachments_for_issue_with_key(issue_key)
265
- response = invoke('soap:getAttachmentsFromIssue') { |msg|
266
- msg.add 'soap:in0', @auth_token
267
- msg.add 'soap:in1', issue_key
268
- }
269
- response.document.xpath("#{RESPONSE_XPATH}/getAttachmentsFromIssueReturn").map {
270
- |frag| JIRA::AttachmentMetadata.new_with_xml frag
271
- }
272
- end
273
-
274
- # New versions cannot have the archived bit set and the release date
275
- # field will ignore the time of day you give it and instead insert
276
- # the time zone offset as the time of day.
277
- #
278
- # Remember that the @release_date field is the tentative release date,
279
- # so its value is independant of the @released flag.
280
- #
281
- # Descriptions do not appear to be included with JIRA::Version objects
282
- # that SOAP API provides.
283
- # @param [String] project_key
284
- # @param [JIRA::Version] version
285
- # @return [JIRA::Version]
286
- def add_version_to_project_with_key(project_key, version)
287
- response = invoke('soap:addVersion') { |msg|
288
- msg.add 'soap:in0', @auth_token
289
- msg.add 'soap:in1', project_key
290
- msg.add 'soap:in2' do |submsg| version.soapify_for submsg end
291
- }
292
- JIRA::Version.new_with_xml response.document.xpath('//addVersionReturn').first
293
- end
294
-
295
- # The archive state can only be set to true for versions that have not been
296
- # released. However, this is not reflected by the return value of this method.
297
- # @param [String] project_key
298
- # @param [String] version_name
299
- # @param [true,false] state
300
- # @return [true]
301
- def set_archive_state_for_version_for_project(project_key, version_name, state)
302
- invoke('soap:archiveVersion') { |msg|
303
- msg.add 'soap:in0', @auth_token
304
- msg.add 'soap:in1', project_key
305
- msg.add 'soap:in2', version_name
306
- msg.add 'soap:in3', state
307
- }
308
- true
309
- end
310
-
311
- # Requires you to set at least a project name, key, and lead.
312
- # However, it is also a good idea to set other project properties, such as
313
- # the permission scheme as the default permission scheme can be too
314
- # restrictive in most cases.
315
- # @param [JIRA::Project] project
316
- # @return [JIRA::Project]
317
- def create_project_with_project(project)
318
- response = invoke('soap:createProjectFromObject') { |msg|
319
- msg.add 'soap:in0', @auth_token
320
- msg.add 'soap:in1' do |submsg| project.soapify_for submsg end
321
- }
322
- JIRA::Project.new_with_xml response.document.xpath('//createProjectFromObjectReturn').first
323
- end
324
-
325
- # You can set the release state for a project with this method.
326
- # @param [String] project_name
327
- # @param [JIRA::Version] version
328
- # @return [true]
329
- def release_state_for_version_for_project(project_name, version)
330
- invoke('soap:releaseVersion') { |msg|
331
- msg.add 'soap:in0', @auth_token
332
- msg.add 'soap:in1', project_name
333
- msg.add 'soap:in2' do |submsg| version.soapify_for submsg end
334
- }
335
- true
336
- end
337
-
338
- # The id of the project is the only field that you cannot update. Or, at
339
- # least the only field I know that you cannot update.
340
- # @param [JIRA::Project] project
341
- # @return [JIRA::Project]
342
- def update_project_with_project(project)
343
- response = invoke('soap:updateProject') { |msg|
344
- msg.add 'soap:in0', @auth_token
345
- msg.add 'soap:in1' do |submsg| project.soapify_for submsg end
346
- }
347
- JIRA::Project.new_with_xml response.document.xpath('//updateProjectReturn').first
348
- end
349
-
350
- # It seems that creating a user without any permission groups will trigger
351
- # an exception on some versions of JIRA. The irony is that this method provides
352
- # no way to add groups. The good news though, is that the creation will still
353
- # happen; but the user will have no permissions.
354
- # @param [String] username
355
- # @param [String] password
356
- # @param [String] full_name
357
- # @param [String] email
358
- # @return [JIRA::User,nil] depending on your JIRA version, this method may
359
- # always raise an exception instead of actually returning anythin
360
- def create_user(username, password, full_name, email)
361
- response = invoke('soap:createUser') { |msg|
362
- msg.add 'soap:in0', @auth_token
363
- msg.add 'soap:in1', username
364
- msg.add 'soap:in2', password
365
- msg.add 'soap:in3', full_name
366
- msg.add 'soap:in4', email
367
- }
368
- JIRA::User.new_with_xml response.document.xpath('//createUserReturn').first
369
- end
370
-
371
- # @param [String] username
372
- # @return [true]
373
- def delete_user_with_name(username)
374
- invoke('soap:deleteUser') { |msg|
375
- msg.add 'soap:in0', @auth_token
376
- msg.add 'soap:in1', username
377
- }
378
- true
379
- end
380
-
381
- # @param [String] project_id
382
- # @return [JIRA::Project]
383
- def get_project_with_id(project_id)
384
- response = invoke('soap:getProjectById') { |msg|
385
- msg.add 'soap:in0', @auth_token
386
- msg.add 'soap:in1', project_id
387
- }
388
- JIRA::Project.new_with_xml response.document.xpath('//getProjectByIdReturn').first
389
- end
390
-
391
- # @todo parse the permission scheme
392
- # Note: this method does not yet include the permission scheme.
393
- # @param [String] project_id
394
- # @return [JIRA::Project]
395
- def get_project_including_schemes_with_id(project_id)
396
- response = invoke('soap:getProjectWithSchemesById') { |msg|
397
- msg.add 'soap:in0', @auth_token
398
- msg.add 'soap:in1', project_id
399
- }
400
- JIRA::Project.new_with_xml response.document.xpath('//getProjectWithSchemesByIdReturn').first
401
- end
402
-
403
- # @param [String] issue_key
404
- # @param [JIRA::Comment] comment
405
- # @return [true]
406
- def add_comment_to_issue_with_key(issue_key, comment)
407
- invoke('soap:addComment') { |msg|
408
- msg.add 'soap:in0', @auth_token
409
- msg.add 'soap:in1', issue_key
410
- msg.add 'soap:in2' do |submsg| comment.soapify_for submsg end
411
- }
412
- true
413
- end
414
-
415
- # @param [String] id
416
- # @return [JIRA::Comment]
417
- def get_comment_with_id(id)
418
- response = invoke('soap:getComment') { |msg|
419
- msg.add 'soap:in0', @auth_token
420
- msg.add 'soap:in1', id
421
- }
422
- JIRA::Comment.new_with_xml response.document.xpath('//getCommentReturn').first
423
- end
424
-
425
- # @param [String] issue_key
426
- # @return [[JIRA::Comment]]
427
- def get_comments_for_issue_with_key(issue_key)
428
- response = invoke('soap:getComments') { |msg|
429
- msg.add 'soap:in0', @auth_token
430
- msg.add 'soap:in1', issue_key
431
- }
432
- response.document.xpath("#{RESPONSE_XPATH}/getCommentsReturn").map {
433
- |frag| JIRA::Comment.new_with_xml frag
434
- }
435
- end
436
-
437
- # @param [String] project_name
438
- # @return [[JIRA::IssueType]]
439
- def get_issue_types_for_project_with_id(project_id)
440
- response = invoke('soap:getIssueTypesForProject') { |msg|
441
- msg.add 'soap:in0', @auth_token
442
- msg.add 'soap:in1', project_id
443
- }
444
- response.document.xpath("#{RESPONSE_XPATH}/getIssueTypesForProjectReturn").map {
445
- |frag| JIRA::IssueType.new_with_xml frag
446
- }
447
- end
448
-
449
- # @param [JIRA::Comment] comment
450
- # @return [JIRA::Comment]
451
- def update_comment(comment)
452
- response = invoke('soap:editComment') { |msg|
453
- msg.add 'soap:in0', @auth_token
454
- msg.add 'soap:in1' do |submsg| comment.soapify_for submsg end
455
- }
456
- frag = response.document.xpath('//editCommentReturn').first
457
- JIRA::Comment.new_with_xml frag
458
- end
459
-
460
- # @return [[JIRA::IssueType]]
461
- def get_subtask_issue_types
462
- response = invoke('soap:getSubTaskIssueTypes') { |msg|
463
- msg.add 'soap:in0', @auth_token
464
- }
465
- response.document.xpath("#{RESPONSE_XPATH}/getSubTaskIssueTypesReturn").map {
466
- |frag| JIRA::IssueType.new_with_xml frag
467
- }
468
- end
469
-
470
- # @param [String] project_id
471
- # @return [[JIRA::IssueType]]
472
- def get_subtask_issue_types_for_project_with_id(project_id)
473
- response = invoke('soap:getSubTaskIssueTypesForProject') { |msg|
474
- msg.add 'soap:in0', @auth_token
475
- msg.add 'soap:in1', project_id
476
- }
477
- response.document.xpath("#{RESPONSE_XPATH}/getSubtaskIssueTypesForProjectReturn").map {
478
- |frag| JIRA::IssueType.new_with_xml frag
479
- }
480
- end
481
-
482
- # I have no idea what this method does.
483
- # @todo find out what this method does
484
- # @return [true]
485
- def refresh_custom_fields
486
- invoke('soap:refreshCustomFields') { |msg|
487
- msg.add 'soap:in0', @auth_token
488
- }
489
- true
490
- end
491
-
492
- # Retrieves favourite filters for the currently logged in user.
493
- # @return [[JIRA::Filter]]
494
- def get_favourite_filters
495
- response = invoke('soap:getFavouriteFilters') { |msg|
496
- msg.add 'soap:in0', @auth_token
497
- }
498
- response.document.xpath("#{RESPONSE_XPATH}/getFavouriteFiltersReturn").map {
499
- |frag| JIRA::Filter.new_with_xml frag
500
- }
501
- end
502
-
503
- # @param [String] id
504
- # @param [Fixnum] max_results
505
- # @param [Fixnum] offset
506
- # @return [[JIRA::Issue]]
507
- def get_issues_from_filter_with_id(id, max_results = 500, offset = 0)
508
- response = invoke('soap:getIssuesFromFilterWithLimit') { |msg|
509
- msg.add 'soap:in0', @auth_token
510
- msg.add 'soap:in1', id
511
- msg.add 'soap:in2', offset
512
- msg.add 'soap:in3', max_results
513
- }
514
- response.document.xpath("#{RESPONSE_XPATH}/getIssuesFromFilterWithLimitReturn").map {
515
- |frag| JIRA::Issue.new_with_xml frag
516
- }
517
- end
518
-
519
- # @param [String] id
520
- # @return [Fixnum]
521
- def get_issue_count_for_filter_with_id(id)
522
- response = invoke('soap:getIssueCountForFilter') { |msg|
523
- msg.add 'soap:in0', @auth_token
524
- msg.add 'soap:in1', id
525
- }
526
- response.document.xpath('//getIssueCountForFilterReturn').to_i
527
- end
528
-
529
- # @todo optimize building the message, try a single pass
530
- # Expect this method to be slow.
531
- # @param [String] issue_key
532
- # @param [[String]] filenames names to put on the files
533
- # @param [[String]] data base64 encoded data
534
- # @return [true]
535
- def add_base64_encoded_attachments_to_issue_with_key(issue_key, filenames, data)
536
- invoke('soap:addBase64EncodedAttachmentsToIssue') { |msg|
537
- msg.add 'soap:in0', @auth_token
538
- msg.add 'soap:in1', issue_key
539
- msg.add 'soap:in2' do |submsg|
540
- filenames.each { |filename| submsg.add 'filenames', filename }
56
+ call( 'logout' ).to_boolean
57
+ end
58
+
59
+ # @endgroup
60
+
61
+
62
+ private
63
+
64
+ # @todo make this method less ugly
65
+ # @todo double check the return type
66
+ # A generic method for calling a SOAP method and soapifying all
67
+ # the arguments, adapted for usage with jiraSOAP.
68
+ # @param [String] method
69
+ # @param [Object] *args
70
+ # @return [Handsoap::Response]
71
+ def build method, *args
72
+ invoke "soap:#{method}" do |msg|
73
+ for i in 0...args.size
74
+ arg = args.shift
75
+ case arg
76
+ when JIRA::Entity
77
+ msg.add "soap:in#{i}", do |submsg| arg.soapify_for submsg end
78
+ else
79
+ msg.add "soap:in#{i}", arg
80
+ end
541
81
  end
542
- msg.add 'soap:in3' do |submsg|
543
- data.each { |datum| submsg.add 'base64EncodedData', datum }
544
- end
545
- }
546
- true
82
+ end
547
83
  end
548
84
 
549
- # The @build_date attribute is a Time value, but does not include a time.
550
- # @return [JIRA::ServerInfo]
551
- def get_server_info
552
- response = invoke('soap:getServerInfo') { |msg|
553
- msg.add 'soap:in0', @auth_token
554
- }
555
- JIRA::ServerInfo.new_with_xml response.document.xpath('//getServerInfoReturn').first
85
+ # @todo find a less blunt XPath expression
86
+ # A simple call, for methods that will return a single object.
87
+ # @param [String] method
88
+ # @param [Object] *args
89
+ # @return [Handsoap::XmlQueryFront::NodeSelection]
90
+ def call method, *args
91
+ response = build method, @auth_token, *args
92
+ response .document.xpath "//#{method}Return"
556
93
  end
557
94
 
558
- # @return [JIRA::ServerConfiguration]
559
- def get_server_configuration
560
- response = invoke('soap:getConfiguration') { |msg|
561
- msg.add 'soap:in0', @auth_token
562
- }
563
- JIRA::ServerConfiguration.new_with_xml response.document.xpath('//getConfigurationReturn').first
95
+ # A more complex form of {#call} that does a little more work for
96
+ # you when you need to build an array of return values.
97
+ # @param [String] method
98
+ # @param [Object] *args
99
+ # @return [Handsoap::XmlQueryFront::NodeSelection]
100
+ def jira_call type, method, *args
101
+ response = build method, @auth_token, *args
102
+ frags = response.document.xpath("#{RESPONSE_XPATH}/#{method}Return")
103
+ frags.map { |frag| type.new_with_xml frag }
564
104
  end
565
105
 
566
- # @note This will not fill in JIRA::Scheme data for the projects.
567
- # @return [[JIRA::Project]]
568
- def get_projects_without_schemes
569
- response = invoke('soap:getProjectsNoSchemes') { |msg|
570
- msg.add 'soap:in0', @auth_token
571
- }
572
- response.document.xpath("#{RESPONSE_XPATH}/getProjectsNoSchemesReturn").map {
573
- |frag| JIRA::Project.new_with_xml frag
574
- }
575
- end
576
-
577
- # @param [#to_s] issue_id
578
- # @return [Time]
579
- def get_resolution_date_for_issue_with_id issue_id
580
- response = invoke('soap:getResolutionDateById') { |msg|
581
- msg.add 'soap:in0', @auth_token
582
- msg.add 'soap:in1', issue_id
583
- }
584
- response.document.xpath('//getResolutionDateByIdReturn').to_date
585
- end
586
-
587
- # @param [String] issue_key
588
- # @return [Time]
589
- def get_resolution_date_for_issue_with_key issue_key
590
- response = invoke('soap:getResolutionDateByKey') { |msg|
591
- msg.add 'soap:in0', @auth_token
592
- msg.add 'soap:in1', issue_key
593
- }
594
- response.document.xpath('//getResolutionDateByKeyReturn').to_date
595
- end
596
-
597
- # @param [String] project_key
598
- # @return [true]
599
- def delete_project_with_key project_key
600
- invoke('soap:deleteProject') { |msg|
601
- msg.add 'soap:in0', @auth_token
602
- msg.add 'soap:in1', project_key
603
- }
604
- true
605
- end
606
-
607
- # @todo add tests for this method
608
- # @note You cannot delete the system avatar
609
- # @note You need project administration permissions to delete an avatar
610
- # @param [#to_s] avatar_id
611
- # @return [true]
612
- def delete_project_avatar_with_id avatar_id
613
- invoke('soap:deleteProjectAvatar') { |msg|
614
- msg.add 'soap:in0', @auth_token
615
- msg.add 'soap:in1', avatar_id
616
- }
617
- true
618
- end
619
-
620
- # @note You need project administration permissions to edit an avatar
621
- # @note JIRA does not care if the avatar_id is valid
622
- # Change the project avatar to another existing avatar. If you want to
623
- # upload a new avatar and set it to be the new project avatar use
624
- # {#set_new_project_avatar} instead.
625
- # @return [true]
626
- def set_project_avatar_for_project_with_key project_key, avatar_id
627
- invoke('soap:setProjectAvatar') { |msg|
628
- msg.add 'soap:in0', @auth_token
629
- msg.add 'soap:in1', project_key
630
- msg.add 'soap:in2', avatar_id
631
- }
632
- true
633
- end
634
-
635
- # @note You need project administration permissions to edit an avatar
636
- # Use this method to create a new custom avatar for a project and set it
637
- # to be current avatar for the project.
638
- #
639
- # The image, provided as base64 encoded data, should be a 48x48 pixel square.
640
- # If the image is larger, the top left 48 pixels are taken, if it is smaller
641
- # then it will be upscaled to 48 pixels.
642
- # The small version of the avatar image (16 pixels) is generated
643
- # automatically.
644
- # If you want to switch a project avatar to an avatar that already exists on
645
- # the system then use {#set_project_avatar_for_project_with_key} instead.
646
- # @param [String] project_key
647
- # @param [String] mime_type
648
- # @param [#to_s] base64_image
649
- # @return [true]
650
- def set_new_project_avatar_for_project_with_key project_key, mime_type, base64_image
651
- invoke('soap:setNewProjectAvatar') { |msg|
652
- msg.add 'soap:in0', @auth_token
653
- msg.add 'soap:in1', project_key
654
- msg.add 'soap:in2', mime_type
655
- msg.add 'soap:in3', base64_image
656
- }
657
- true
658
- end
659
-
660
- # @return [[JIRA::ProjectRole]]
661
- def get_project_roles
662
- response = invoke('soap:getProjectRoles') { |msg|
663
- msg.add 'soap:in0', @auth_token
664
- }
665
- response.document.xpath("#{RESPONSE_XPATH}/getProjectRolesReturn").map {
666
- |frag| JIRA::ProjectRole.new_with_xml frag
667
- }
668
- end
669
-
670
- # @param [#to_s] role_id
671
- # @return [JIRA::ProjectRole]
672
- def get_project_role_with_id role_id
673
- response = invoke('soap:getProjectRole') { |msg|
674
- msg.add 'soap:in0', @auth_token
675
- msg.add 'soap:in1', role_id
676
- }
677
- JIRA::ProjectRole.new_with_xml response.document.xpath('//getProjectRoleReturn').first
678
- end
679
-
680
- # @param [JIRA::ProjectRole] project_role
681
- # @return [JIRA::ProjectRole] the role that was created
682
- def create_project_role_with_role project_role
683
- response = invoke('soap:createProjectRole') { |msg|
684
- msg.add 'soap:in0', @auth_token
685
- msg.add 'soap:in1' do |submsg| project_role.soapify_for submsg end
686
- }
687
- JIRA::ProjectRole.new_with_xml response.document.xpath('//createProjectRoleReturn').first
688
- end
689
-
690
- # @note JIRA 4.0 returns an exception if the name already exists
691
- # Returns true if the name does not exist.
692
- # @param [String] project_role_name
693
- # @return [true,false]
694
- def project_role_name_unique? project_role_name
695
- response = invoke('soap:isProjectRoleNameUnique') { |msg|
696
- msg.add 'soap:in0', @auth_token
697
- msg.add 'soap:in1', project_role_name
698
- }
699
- response.document.xpath('//isProjectRoleNameUniqueReturn').to_boolean
700
- end
701
-
702
- # @note the confirm argument appears to do nothing (at least on JIRA 4.0)
703
- # @param [JIRA::ProjectRole] project_role
704
- # @param [true,false] confirm
705
- # @return [true]
706
- def delete_project_role project_role, confirm = true
707
- invoke('soap:deleteProjectRole') { |msg|
708
- msg.add 'soap:in0', @auth_token
709
- msg.add 'soap:in1' do |submsg| project_role.soapify_for submsg end
710
- msg.add 'soap:in2', confirm
711
- }
712
- true
713
- end
714
-
715
- # @note JIRA 4.0 will not update project roles, it will instead throw
716
- # an exception telling you that the project role already exists
717
- # @param [JIRA::ProjectRole] project_role
718
- # @return [JIRA::ProjectRole] the role after the update
719
- def update_project_role_with_role project_role
720
- response = invoke('soap:updateProjectRole') { |msg|
721
- msg.add 'soap:in0', @auth_token
722
- msg.add 'soap:in1' do |submsg| project_role.soapify_for submsg end
723
- }
724
- JIRA::ProjectRole.new_with_xml response.document.xpath('//updateProjectRoleReturn').first
725
- end
106
+ end
726
107
 
727
108
  end