jiraSOAP 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ require 'jiraSOAP/entities/abstract'
2
+ require 'jiraSOAP/entities/read_only'
3
+ require 'jiraSOAP/entities/field_value'
4
+ require 'jiraSOAP/entities/user'
5
+
6
+ require 'jiraSOAP/entities/avatar'
7
+ require 'jiraSOAP/entities/comment'
8
+ require 'jiraSOAP/entities/issue'
9
+
10
+ require 'jiraSOAP/entities/filter'
11
+ require 'jiraSOAP/entities/version'
12
+ require 'jiraSOAP/entities/attachments'
13
+ require 'jiraSOAP/entities/project'
14
+ require 'jiraSOAP/entities/schemes'
15
+ require 'jiraSOAP/entities/issue_properties'
16
+
17
+ module JIRA
18
+ # Represents a field mapping.
19
+ class Field < JIRA::NamedEntity
20
+ end
21
+
22
+ # Represents a component description for a project. It does not include
23
+ # the component lead.
24
+ class Component < JIRA::NamedEntity
25
+ end
26
+ end
@@ -0,0 +1,95 @@
1
+ module JIRA
2
+
3
+ # @abstract
4
+ # The base class for all JIRA objects that can be created by the server.
5
+ class Entity
6
+
7
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
8
+ # @return [JIRA::Entity]
9
+ def self.new_with_xml_fragment(frag)
10
+ entity = allocate
11
+ entity.initialize_with_xml_fragment frag
12
+ entity
13
+ end
14
+
15
+ # @raise [NotImplementedError] this method MUST be implemented in a non
16
+ # abstract descendant
17
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
18
+ def initialize_with_xml_fragment(frag)
19
+ raise NotImplementedError.new, 'Subclasses should override and implement'
20
+ end
21
+ end
22
+
23
+ # @abstract
24
+ # Most JIRA objects will have an id attribute as a unique identifier in
25
+ # their area.
26
+ class DynamicEntity < JIRA::Entity
27
+
28
+ # @return [String] usually holds a numerical value but for consistency with
29
+ # with id's from custom fields this attribute is always a String
30
+ attr_accessor :id
31
+
32
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
33
+ def initialize_with_xml_fragment(frag)
34
+ @id = (frag/'id').to_s
35
+ end
36
+ end
37
+
38
+ # @abstract
39
+ # Many JIRA objects include a name.
40
+ class NamedEntity < JIRA::DynamicEntity
41
+
42
+ # @return [String] a plain language name
43
+ attr_accessor :name
44
+
45
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
46
+ def initialize_with_xml_fragment(frag)
47
+ super frag
48
+ @name = (frag/'name').to_s
49
+ end
50
+ end
51
+
52
+ # @abstract
53
+ # Several JIRA objects include a short description.
54
+ class DescribedEntity < JIRA::NamedEntity
55
+
56
+ # @return [String] usually a short blurb
57
+ attr_accessor :description
58
+
59
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
60
+ def initialize_with_xml_fragment(frag)
61
+ super frag
62
+ @description = (frag/'description').to_s
63
+ end
64
+ end
65
+
66
+ # @abstract
67
+ # Represents a scheme used by the server. Not very useful for the sake of the
68
+ # API; a more useful case might be if you wanted to emulate the server's
69
+ # behaviour.
70
+ class Scheme < JIRA::DescribedEntity
71
+ # Schemes that inherit this class will have to be careful when they try
72
+ # to encode the scheme type in an xml message.
73
+ # @return [String]
74
+ def type
75
+ self.class.to_s
76
+ end
77
+ end
78
+
79
+ # @abstract
80
+ # A common base for most issue properties. Core issue properties have
81
+ # an icon to go with them to help identify properties of issues more
82
+ # quickly.
83
+ class IssueProperty < JIRA::DescribedEntity
84
+
85
+ # @return [URL] A NSURL on MacRuby and a URI::HTTP object in CRuby
86
+ attr_accessor :icon
87
+
88
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
89
+ def initialize_with_xml_fragment(frag)
90
+ super frag
91
+ @icon = (frag/'icon').to_url
92
+ end
93
+ end
94
+
95
+ end
@@ -0,0 +1,35 @@
1
+ module JIRA
2
+
3
+ # Only contains the metadata for an attachment. The URI for an attachment
4
+ # appears to be of the form
5
+ # "{JIRA::JIRAService.endpoint_url}/secure/attachment/{#id}/{#filename}"
6
+ class AttachmentMetadata < JIRA::NamedEntity
7
+
8
+ # @return [String]
9
+ attr_accessor :author
10
+
11
+ # @return [Time]
12
+ attr_accessor :create_date
13
+
14
+ # @return [String]
15
+ attr_accessor :filename
16
+
17
+ # @return [Fixnum] measured in bytes
18
+ attr_accessor :file_size
19
+
20
+ # @return [String]
21
+ attr_accessor :mime_type
22
+
23
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
24
+ def initialize_with_xml_fragment(frag)
25
+ super frag
26
+ @author, @filename, @mime_type, @file_size, @create_date =
27
+ frag.nodes( ['author', :to_s],
28
+ ['filename', :to_s],
29
+ ['mimetype', :to_s],
30
+ ['filesize', :to_i],
31
+ ['created', :to_date] )
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,36 @@
1
+ module JIRA
2
+
3
+ # Contains a base64 encoded avatar image and metadata about the avatar.
4
+ class Avatar < JIRA::DynamicEntity
5
+
6
+ # @return [String]
7
+ attr_accessor :owner
8
+
9
+ # @return [String] the place where the avatar is used
10
+ attr_accessor :type
11
+
12
+ # @return [String]
13
+ attr_accessor :mime_type
14
+
15
+ # @return [String]
16
+ attr_accessor :base64_data
17
+
18
+ # @return [boolean] indicates if the image is the system default
19
+ attr_accessor :system
20
+
21
+ # @return [boolean] true if avatar is the default system avatar, else false
22
+ def system?; @system; end
23
+
24
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
25
+ def initialize_with_xml_fragment(frag)
26
+ super frag
27
+ @owner, @type, @mime_type, @base64_data, @system =
28
+ frag.nodes( ['owner', :to_s],
29
+ ['type', :to_s],
30
+ ['contentType', :to_s],
31
+ ['base64Data', :to_s],
32
+ ['system', :to_boolean] )
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,54 @@
1
+ module JIRA
2
+
3
+ # Contains a comments body and its metadata.
4
+ class Comment < JIRA::DynamicEntity
5
+
6
+ # @return [String]
7
+ attr_accessor :original_author
8
+
9
+ # @return [String]
10
+ attr_accessor :role_level
11
+
12
+ # @return [String]
13
+ attr_accessor :group_level
14
+
15
+ # @return [String]
16
+ attr_accessor :body
17
+
18
+ # @return [Time]
19
+ attr_accessor :create_date
20
+
21
+ # @return [Time]
22
+ attr_accessor :last_updated
23
+
24
+ # @return [String]
25
+ attr_accessor :update_author
26
+
27
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
28
+ def initialize_with_xml_fragment(frag)
29
+ super frag
30
+ @original_author, @body, @group_level, @role_level,
31
+ @update_author, @create_date, @last_updated =
32
+ frag.nodes( ['author', :to_s],
33
+ ['body', :to_s],
34
+ ['groupLevel', :to_s],
35
+ ['roleLevel', :to_s],
36
+ ['updateAuthor', :to_s],
37
+ ['created', :to_date],
38
+ ['updated', :to_date] )
39
+ end
40
+
41
+ # @todo make this method shorter
42
+ # @param [Handsoap::XmlMason::Node] msg
43
+ # @return [Handsoap::XmlMason::Node]
44
+ def soapify_for(msg)
45
+ msg.add 'id', @id
46
+ msg.add 'author', @original_author
47
+ msg.add 'body', @body
48
+ msg.add 'groupLevel', @group_level
49
+ msg.add 'roleLevel', @role_level
50
+ msg.add 'updateAuthor', @update_author
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,73 @@
1
+ module JIRA
2
+
3
+ # A structure that is a bit of a hack. It is essentially just a key-value pair
4
+ # that is used by {RemoteAPI#update_issue}.
5
+ class FieldValue
6
+
7
+ # @return [String] the name for regular fields, and the id for custom fields
8
+ attr_accessor :field_name
9
+
10
+ # @return [[String,Time,URL,nil]] Whatever the type, just make sure it is
11
+ # wrapped in an array.
12
+ attr_accessor :values
13
+
14
+ # @param [String] field_name
15
+ # @param [Array] values
16
+ def initialize(field_name = nil, values = nil)
17
+ @field_name = field_name
18
+ @values = values
19
+ end
20
+
21
+ # @todo soapify properly for custom objects (JIRA module).
22
+ # @param [Handsoap::XmlMason::Node] message the node to add the object to
23
+ # @param [String] label name for the tags that wrap the message
24
+ # @return [Handsoap::XmlMason::Element]
25
+ def soapify_for(message, label = 'fieldValue')
26
+ message.add label do |message|
27
+ message.add 'id', @field_name
28
+ message.add_simple_array 'values', @values unless @values.nil?
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+ # Represents an instance of a custom field (with values). This object is used
35
+ # as a member of {JIRA::Issue} objects.
36
+ #
37
+ # The structure of this class resembles JIRA::FieldValue, it is different
38
+ # in that @values will always be stored as an Array of String objects for
39
+ # custom fields and a field value is more flexible. You can expect the classes
40
+ # to merge in the near future.
41
+ # @todo see if @key is always nil from the server, maybe we can remove it
42
+ # @todo merge this class with JIRA::FieldValue
43
+ class CustomFieldValue < JIRA::DynamicEntity
44
+
45
+ # @return [String]
46
+ attr_accessor :key
47
+
48
+ # @return [[String]]
49
+ attr_accessor :values
50
+
51
+ # @note careful, value of id is actually customfieldId
52
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
53
+ def initialize_with_xml_fragment(frag)
54
+ @id, @key, @values =
55
+ frag.nodes( ['customfieldId', :to_s],
56
+ ['key', :to_s],
57
+ ['values/*', :to_ss] )
58
+ end
59
+
60
+ # Generate a SOAP message fragment for the object.
61
+ # @param [Handsoap::XmlMason::Node] msg SOAP message to add the object to
62
+ # @param [String] label tag name used in wrapping tags
63
+ # @return [Handsoap::XmlMason::Element]
64
+ def soapify_for(msg, label = 'customFieldValues')
65
+ msg.add label do |submsg|
66
+ submsg.add 'customfieldId', @id
67
+ submsg.add 'key', @key
68
+ submsg.add_simple_array 'values', @values
69
+ end
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,26 @@
1
+ module JIRA
2
+
3
+ # Represents a filter, but does not seem to include the filters JQL query.
4
+ # @todo find out what @project is supposed to be for
5
+ class Filter < JIRA::DescribedEntity
6
+
7
+ # @return [String]
8
+ attr_accessor :author
9
+
10
+ # @return [String]
11
+ attr_accessor :project
12
+
13
+ # @return [nil]
14
+ attr_accessor :xml
15
+
16
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
17
+ def initialize_with_xml_fragment(frag)
18
+ super frag
19
+ @author, @project, @xml =
20
+ frag.nodes( ['author', :to_s],
21
+ ['project', :to_s],
22
+ ['xml', :to_s] )
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,166 @@
1
+ module JIRA
2
+
3
+ # Contains most of the data and metadata for a JIRA issue, but does
4
+ # not contain the {JIRA::Comment}'s or {JIRA::AttachmentMetadata}.
5
+ #
6
+ # This class is easily the most convoluted structure in the API, and will
7
+ # likely be the greatest source of bugs. The irony of the situation is that
8
+ # this structure is also the most critical to have in working order.
9
+ #
10
+ # Issues with an UNRESOLVED status will have nil for the value of @resolution.
11
+ class Issue < JIRA::DynamicEntity
12
+
13
+ # @return [String]
14
+ attr_accessor :key
15
+
16
+ # @return [String]
17
+ attr_accessor :summary
18
+
19
+ # @return [String]
20
+ attr_accessor :description
21
+
22
+ # @return [String]
23
+ attr_accessor :type_id
24
+
25
+ # @return [Time]
26
+ attr_accessor :last_updated
27
+
28
+ # @return [Fixnum]
29
+ attr_accessor :votes
30
+
31
+ # @return [String]
32
+ attr_accessor :status_id
33
+
34
+ # @return [String]
35
+ attr_accessor :assignee_name
36
+
37
+ # @return [String]
38
+ attr_accessor :reporter_name
39
+
40
+ # @return [String]
41
+ attr_accessor :priority_id
42
+
43
+ # @return [String]
44
+ attr_accessor :project_name
45
+
46
+ # @return [[JIRA::Version]]
47
+ attr_accessor :affects_versions
48
+
49
+ # @return [Time]
50
+ attr_accessor :create_date
51
+
52
+ # @return [Time]
53
+ attr_accessor :due_date
54
+
55
+ # @return [[JIRA::Version]]
56
+ attr_accessor :fix_versions
57
+
58
+ # @return [String]
59
+ attr_accessor :resolution_id
60
+
61
+ # @return [String]
62
+ attr_accessor :environment
63
+
64
+ # @return [[JIRA::Component]]
65
+ attr_accessor :components
66
+
67
+ # @return [[String]]
68
+ attr_accessor :attachment_names
69
+
70
+ # @return [[JIRA::CustomFieldValue]]
71
+ attr_accessor :custom_field_values
72
+
73
+ # @param [Handsoap::XmlQueryFront::NokogiriDriver] frag
74
+ def initialize_with_xml_fragment(frag)
75
+ super frag
76
+ @key, @summary, @description, @type_id, @status_id,
77
+ @assignee_name, @reporter_name, @priority_id, @project_name,
78
+ @resolution_id, @environment, @votes, @last_updated, @create_date,
79
+ @due_date, @affects_versions, @fix_versions, @components,
80
+ @custom_field_values, @attachment_names =
81
+ frag.nodes( ['key', :to_s],
82
+ ['summary', :to_s],
83
+ ['description', :to_s],
84
+ ['type', :to_s],
85
+ ['status', :to_s],
86
+ ['assignee', :to_s],
87
+ ['reporter', :to_s],
88
+ ['priority', :to_s],
89
+ ['project', :to_s],
90
+ ['resolution', :to_s],
91
+ ['environment', :to_s],
92
+ ['votes', :to_i],
93
+ ['updated', :to_date],
94
+ ['created', :to_date],
95
+ ['duedate', :to_date],
96
+ ['affectsVersions/*', :to_objects, JIRA::Version],
97
+ ['fixVersions/*', :to_objects, JIRA::Version],
98
+ ['components/*', :to_objects, JIRA::Component],
99
+ ['customFieldValues/*', :to_objects, JIRA::CustomFieldValue],
100
+ ['attachmentNames/*', :to_ss] )
101
+ end
102
+
103
+ # Generate the SOAP message fragment for an issue. Can you spot the oddities
104
+ # and inconsistencies? (hint: there are many).
105
+ #
106
+ # We don't bother including fields that are ignored. I tried to only
107
+ # ignore fields that will never be needed at creation time, but I may have
108
+ # messed up.
109
+ #
110
+ # We don't wrap the whole thing in 'issue' tags for
111
+ # {#RemoteAPI#create_issue_with_issue} calls; this is an inconsistency in the
112
+ # way jiraSOAP works and may need to be worked around for other {RemoteAPI}
113
+ # methods.
114
+ #
115
+ # Servers only seem to accept issues if components/versions are just ids
116
+ # and do not contain the rest of the {JIRA::Component}/{JIRA::Version}
117
+ # structure.
118
+ #
119
+ # To get the automatic assignee we pass '-1' as the value for @assignee.
120
+ #
121
+ # Passing an environment/due date field with a value of nil causes the
122
+ # server to complain about the formatting of the message.
123
+ # @todo see if we can use the simple and complex array builders
124
+ # @todo make this method shorter
125
+ # @param [Handsoap::XmlMason::Node] msg message the node to add the object to
126
+ def soapify_for(msg)
127
+ #might be going away, since it appears to have no effect at creation time
128
+ msg.add 'reporter', @reporter_name unless @reporter.nil?
129
+
130
+ msg.add 'priority', @priority_id
131
+ msg.add 'type', @type_id
132
+ msg.add 'project', @project_name
133
+
134
+ msg.add 'summary', @summary
135
+ msg.add 'description', @description
136
+
137
+ msg.add 'components' do |submsg|
138
+ (@components || []).each { |component|
139
+ submsg.add 'components' do |component_msg|
140
+ component_msg.add 'id', component.id
141
+ end
142
+ }
143
+ end
144
+ msg.add 'affectsVersions' do |submsg|
145
+ (@affects_versions || []).each { |version|
146
+ submsg.add 'affectsVersions' do |version_msg|
147
+ version_msg.add 'id', version.id
148
+ end
149
+ }
150
+ end
151
+ msg.add 'fixVersions' do |submsg|
152
+ (@fix_versions || []).each { |version|
153
+ submsg.add 'fixVersions' do |version_msg|
154
+ version_msg.add 'id', version.id end
155
+ }
156
+ end
157
+
158
+ msg.add 'assignee', (@assignee_name || '-1')
159
+ msg.add_complex_array 'customFieldValues', (@custom_field_values || [])
160
+
161
+ msg.add 'environment', @environment unless @environment.nil?
162
+ msg.add 'duedate', @due_date.xmlschema unless @due_date.nil?
163
+ end
164
+ end
165
+
166
+ end