Merge pull request #153 from KrzysiekJ/auth-source-search-port
[org-jira.git] / org-jira-sdk.el
blob8873f9056d0f4f5d0436658505f10d7bb53b76cf
1 ;;; org-jira-sdk.el -- SDK Layer for entities
3 ;; Copyright (C) 2018 Matthew Carter <m@ahungry.com>
4 ;;
5 ;; Authors:
6 ;; Matthew Carter <m@ahungry.com>
7 ;;
8 ;; Maintainer: Matthew Carter <m@ahungry.com>
9 ;; URL: https://github.com/ahungry/org-jira
10 ;; Version: 3.1.1
11 ;; Keywords: ahungry jira org bug tracker
12 ;; Package-Requires: ((emacs "24.5") (cl-lib "0.5") (request "0.2.0") (s "0.0.0"))
14 ;; This file is not part of GNU Emacs.
16 ;; This program is free software: you can redistribute it and/or modify
17 ;; it under the terms of the GNU General Public License as published by
18 ;; the Free Software Foundation, either version 3 of the License, or
19 ;; (at your option) any later version.
21 ;; This program is distributed in the hope that it will be useful,
22 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 ;; GNU General Public License for more details.
26 ;; You should have received a copy of the GNU General Public License
27 ;; along with this program. If not, see
28 ;; <http://www.gnu.org/licenses/> or write to the Free Software
29 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 ;; 02110-1301, USA.
32 ;;; Commentary:
34 ;; This provides an SDK wrapper for more strictly defining the entities we interact with.
36 ;;; Code:
38 (require 'jiralib)
39 (require 'cl-lib)
40 (require 's)
41 (require 'eieio)
42 (require 'dash)
43 (require 'cl-generic)
45 (defclass org-jira-sdk-record ()
46 ((id :initarg :id :type string :required t)
47 (data :initarg :data :documentation "The area to hold a big alist of data.")
48 (hydrate-fn :initform (lambda (id) (message "Not implemented."))))
49 "The ID of the record.")
51 (defun org-jira-sdk-string-but-first (s) (cl-subseq s 1))
53 (defun org-jira-sdk-to-string (s) (format "%s" s))
55 (defun org-jira-sdk-to-prefixed-string (s) (format "org-jira-sdk-%s" s))
57 (defun org-jira-sdk-record-type-to-symbol (record-type)
58 (-> record-type symbol-name org-jira-sdk-string-but-first org-jira-sdk-to-prefixed-string intern))
60 (defun org-jira-sdk-create-from-id (record-type id &optional parent-id callback)
61 (let ((rec (funcall (org-jira-sdk-record-type-to-symbol record-type)
62 :id (format "%s" id)
63 :parent-id parent-id)))
64 (with-slots (data) rec
65 (setf data (org-jira-sdk-hydrate rec callback))
66 (org-jira-sdk-from-data rec))))
68 (defun org-jira-sdk-create-from-data (record-type data)
69 (let ((rec (funcall (org-jira-sdk-record-type-to-symbol record-type) :data data)))
70 (org-jira-sdk-from-data rec)))
72 (cl-defmethod org-jira-sdk-hydrate ((rec org-jira-sdk-record) &optional callback)
73 "Populate the record with data from the remote endpoint."
74 (with-slots (id hydrate-fn) rec
75 (funcall hydrate-fn id callback)))
77 (cl-defgeneric org-jira-sdk-from-data ((rec org-jira-sdk-record)))
79 (cl-defmethod org-jira-sdk-dump ((rec org-jira-sdk-record))
80 "A decent pretty print/object dump for working with the class items."
81 (let ((slots (mapcar (lambda (slot) (aref slot 1)) (eieio-class-slots (eieio-object-class rec)))))
82 (setq slots (cl-remove-if (lambda (s) (not (slot-boundp rec s))) slots))
83 (apply #'concat
84 (mapcar (lambda (slot)
85 (let ((slot (intern (org-jira-sdk-to-string slot))))
86 (format "\n%+16s: %s" slot (slot-value rec (intern (org-jira-sdk-to-string slot)))))
88 slots))))
90 (defun org-jira-sdk-path (alist key-chain)
91 "Query a nested path in some type of ALIST by traversing down the keys of KEY-CHAIN."
92 (cl-reduce (lambda (a k) (alist-get k a)) key-chain :initial-value alist))
94 (defclass org-jira-sdk-issue (org-jira-sdk-record)
95 ((assignee :type (or null string) :initarg :assignee)
96 (components :type string :initarg :components)
97 (created :type string :initarg :created)
98 (description :type (or null string) :initarg :description)
99 (duedate :type (or null string) :initarg :duedate)
100 (headline :type string :initarg :headline)
101 (id :type string :initarg :id) ; TODO: Probably remove me
102 (issue-id :type string :initarg :issue-id :documentation "The common ID/key, such as EX-1.")
103 (issue-id-int :type string :initarg :issue-id-int :documentation "The internal Jira ID, such as 12345.")
104 (priority :type string :initarg :priority)
105 (proj-key :type string :initarg :proj-key)
106 (reporter :type (or null string) :initarg :reporter)
107 (resolution :type (or null string) :initarg :resolution)
108 (start-date :type (or null string) :initarg :start-date)
109 (status :type string :initarg :status)
110 (summary :type string :initarg :summary)
111 (type :type string :initarg :type)
112 (updated :type string :initarg :updated)
113 (data :initarg :data :documentation "The remote Jira data object (alist).")
114 (hydrate-fn :initform #'jiralib-get-issue :initarg :hydrate-fn))
115 "An issue on the end. ID of the form EX-1, or a numeric such as 10000.")
117 (defclass org-jira-sdk-comment (org-jira-sdk-record)
118 ((author :type string :initarg :author)
119 (body :type string :initarg :body)
120 (comment-id :type string :initarg :comment-id :documentation "The comment ID, such as 12345.")
121 (created :type string :initarg :created)
122 (headline :type string :initarg :headline)
123 (parent-id :type string :initarg :parent-id :documentation "The parent issue-id such as EX-1.")
124 (updated :type string :initarg :updated)
125 (data :initarg :data :documentation "The reomte Jira data object (alist).")
126 (hydrate-fn :initform #'jiralib-get-comment :initarg :hydrate-fn)))
128 (defclass org-jira-sdk-board (org-jira-sdk-record)
129 ((name :type string :initarg :name :required t)
130 (url :type string :initarg :url :required t)
131 (board-type :type string :initarg :board-type)
132 (jql :type string :initarg :jql)
133 (limit :type integer :initarg :limit)
134 ;; unused
135 (parent-id :type string :initarg :parent-id)
136 (hydrate-fn :initform #'jiralib-get-board :initarg :hydrate-fn)))
138 (cl-defmethod org-jira-sdk-hydrate ((rec org-jira-sdk-comment) &optional callback)
139 "Populate the record with data from the remote endpoint."
140 (with-slots (id proj-key hydrate-fn) rec
141 (funcall hydrate-fn proj-key id callback)))
143 (cl-defmethod org-jira-sdk-from-data ((rec org-jira-sdk-issue))
144 (cl-flet ((path (keys) (org-jira-sdk-path (oref rec data) keys)))
145 (org-jira-sdk-issue
146 :assignee (path '(fields assignee name))
147 :components (mapconcat (lambda (c) (org-jira-sdk-path c '(name))) (path '(fields components)) ", ")
148 :created (path '(fields created)) ; confirm
149 :description (or (path '(fields description)) "")
150 :duedate (path '(fields duedate)) ; confirm
151 :headline (path '(fields summary)) ; Duplicate of summary, maybe different.
152 :id (path '(key))
153 :issue-id (path '(key))
154 :issue-id-int (path '(id))
155 :priority (path '(fields priority name))
156 :proj-key (path '(fields project key))
157 :reporter (path '(fields reporter name)) ; reporter could be an object of its own slot values
158 :resolution (path '(fields resolution name)) ; confirm
159 :start-date (path '(fields start-date)) ; confirm
160 :status (org-jira-decode (path '(fields status name)))
161 :summary (path '(fields summary))
162 :type (path '(fields issuetype name))
163 :updated (path '(fields updated)) ; confirm
164 ;; TODO: Remove this
165 ;; :data (oref rec data)
168 (cl-defmethod org-jira-sdk-from-data ((rec org-jira-sdk-comment))
169 (cl-flet ((path (keys) (org-jira-sdk-path (oref rec data) keys)))
170 (org-jira-sdk-comment
171 :author (path '(author displayName))
172 :body (path '(body))
173 :comment-id (path '(id))
174 :created (path '(created))
175 :headline (format "Comment: %s" (path '(author displayName)))
176 :parent-id (if (slot-boundp rec 'parent-id) (oref rec parent-id) "")
177 :updated (path '(updated))
178 ;; TODO: Remove this
179 ;; :data (oref rec data)
182 (cl-defmethod org-jira-sdk-from-data ((rec org-jira-sdk-board))
183 (with-slots (data) rec
184 (org-jira-sdk-board
185 :id (int-to-string (alist-get 'id data))
186 :name (alist-get 'name data)
187 :url (alist-get 'self data)
188 ;; TODO: remove it? used by org-jira-sdk-create-from-id
189 :parent-id ""
190 :board-type (alist-get 'type data))))
192 ;; Issue
193 (defun org-jira-sdk-create-issue-from-data (d) (org-jira-sdk-create-from-data :issue d))
194 (defun org-jira-sdk-create-issues-from-data-list (ds) (mapcar #'org-jira-sdk-create-issue-from-data ds))
196 ;; Comment
197 (defun org-jira-sdk-create-comment-from-data (d) (org-jira-sdk-create-from-data :comment d))
198 (defun org-jira-sdk-create-comments-from-data-list (ds) (mapcar #'org-jira-sdk-create-comment-from-data ds))
200 (defun org-jira-sdk-isa-record? (i) (typep i 'org-jira-sdk-record))
201 (defun org-jira-sdk-isa-issue? (i) (typep i 'org-jira-sdk-issue))
202 (defun org-jira-sdk-isa-comment? (i) (typep i 'org-jira-sdk-comment))
204 ;; Board
205 (defun org-jira-sdk-create-board-from-data (d) (org-jira-sdk-create-from-data :board d))
206 (defun org-jira-sdk-create-boards-from-data-list (ds) (mapcar #'org-jira-sdk-create-board-from-data ds))
208 (provide 'org-jira-sdk)
210 ;;; org-jira-sdk.el ends here