emacs/lisp/net/soap-inspect.el

547 lines
20 KiB
EmacsLisp
Raw Normal View History

;;; soap-inspect.el --- Interactive WSDL inspector -*- lexical-binding: t -*-
;; Copyright (C) 2010-2018 Free Software Foundation, Inc.
;; Author: Alexandru Harsanyi <AlexHarsanyi@gmail.com>
;; Created: October 2010
;; Keywords: soap, web-services, comm, hypermedia
;; Package: soap-client
Sync with soap-client repository, version 3.0.1 * soap-client.el, soap-inspect.el: Bump version to 3.0.1. * soap-client.el, soap-inspect.el: Update home page. * soap-client.el, soap-inspect.el: Bump version to 3.0.0. * soap-inspect.el: Merge in changes from Emacs master branch. * soap-client.el: Merge in changes from Emacs master branch. * soap-inspect.el: Shorten first line description. * soap-client.el: Make a small whitespace fix. * soap-inspect.el: Update copyright years. * soap-client.el (soap-encoded-namespaces): Move above first use in soap-encode-xs-element. * soap-client.el (soap-type-is-array?): new defun (soap-encode-xs-element): handle array elements in this function (soap-encode-xs-complex-type): flag error if asked to encode an array type, this is handled in `soap-encode-xs-element' * soap-inspect.el (soap-inspect-xs-attribute-group): Do not print type for attribute group. * soap-inspect.el (soap-sample-value-for-xs-attribute-group): New function. (soap-inspect-xs-attribute-group): Likewise. * soap-inspect.el (soap-resolve-references-for-xs-attribute-group): Resolve references of attributes in an attribute group. * soap-client.el (soap-decode-xs-attributes): Process attribute type directly, not through soap-wsdl-get. * soap-client.el (soap-xs-parse-attribute): Leave reference nil if reference attribute is nil. * soap-client.el (soap-resolve-references-for-xs-attribute): Convert XML schema attributes to xsd:string. * soap-inspect.el (soap-sample-value-for-xs-attribute): New function. (soap-sample-value-for-xs-simple-type): Prepend attributes to result. (soap-sample-value-for-xs-complex-type): Likewise. (soap-inspect-xs-attribute): New function. (soap-inspect-xs-simple-type): Print attributes. (soap-inspect-xs-complex-type): Likewise. * soap-inspect.el (soap-resolve-references-for-xs-simple-type): Resolve references for attributes. (soap-resolve-references-for-xs-complex-type): Likewise. * soap-client.el (soap-xml-node-find-matching-child): Rename from soap-xml-node-first-child. (soap-xs-parse-attribute): Call soap-xml-node-find-matching-child. (soap-xs-parse-simple-type): Likewise. * soap-client.el (soap-invoke-async): Add error checking. * soap-client.el (soap-invoke-internal): New function. (soap-invoke-async): Call soap-invoke-internal. (soap-invoke): Likewise. * soap-client.el (soap-invoke-async): Ensure buffer passed to url-retrieve callback is killed. * soap-client.el (soap-parse-wsdl-phase-validate-node): Rename function. (soap-parse-wsdl-phase-fetch-imports): Likewise. (soap-parse-wsdl-phase-parse-schema): Likewise. (soap-parse-wsdl-phase-fetch-schema): Likewise. (soap-parse-wsdl-phase-finish-parsing): Likewise. (soap-parse-wsdl): Update calls. * soap-client.el (soap-invoke-async): Fix callback invocation. * soap-client.el (soap-invoke-async): New function. (soap-invoke): Reimplement using soap-invoke-async. * soap-client.el (soap-parse-server-response): Improve docstring. (soap-invoke): Inline call to soap-parse-server-response. * soap-client.el (soap-decode-xs-complex-type): Prevent incorrect warning. * soap-client.el (soap-parse-server-response): Rename soap-process-url-response. Destroy the mime part. (soap-invoke): Call soap-parse-server-response. * soap-client.el: Update copyright date. * soap-client.el: Fix checkdoc issues. * soap-client.el: Fix indentation and long lines. * soap-client.el (soap-time-format): Remove variable. (soap-encode-xs-basic-type): Simplify date-time format detection. (soap-decode-xs-basic-type): Remove soap-time-format support. * soap-client.el (soap-process-url-response): New function. (soap-fetch-xml-from-url): Call soap-process-url-response. (soap-parse-wsdl-phase-1): New function. (soap-parse-wsdl-phase-2): Likewise. (soap-parse-wsdl-phase-3): Likewise. (soap-parse-wsdl-phase-4): Likewise. (soap-parse-wsdl-phase-5): Likewise. (soap-parse-wsdl): Call phase functions. * soap-client.el (soap-decode-xs-basic-type): Remove one-argument and call. * soap-client.el (soap-decode-date-time): Improve docstring. * soap-client.el (soap-xmlschema-imports): Remove variable. (soap-parse-schema): Add wsdl argument. Look up XML schema imports from wsdl. (soap-load-wsdl): Do not set soap-xmlschema-imports. (soap-parse-wsdl): Get XML schema imports from wsdl. * soap-client.el (soap-current-file): Remove variable. (soap-wsdl): Add current-file slot. (soap-fetch-xml-from-url): Add wsdl argument. Look up current file from wsdl. (soap-fetch-xml-from-file): Likewise. (soap-fetch-xml): Likewise. (soap-load-wsdl): Always create wsdl object first. (soap-parse-wsdl): Pass wsdl to soap-fetch-xml. * soap-client.el (soap-xs-element): Add is-group slot. (soap-xs-parse-element): Set is-group slot. (soap-resolve-references-for-xs-element): Skip is-group elements. (soap-xs-complex-type): Add is-group slot. (soap-xs-parse-complex-type): Set is-group slot. (soap-xs-parse-sequence): Parse xsd:group elements. (soap-resolve-references-for-xs-complex-type): Inline elements from referenced xsd:group nodes. (soap-parse-schema): Parse xsd:group nodes. * soap-client.el (soap-invoke): Don't set url-http-version to 1.0. * soap-client.el (soap-decode-xs-complex-type): Allow choice nodes to accept multiple values. * soap-client.el (soap-encode-body): Check parameters argument for extra header values. * soap-client.el (soap-well-known-xmlns): Add wsa and wsaw tags. (soap-operation): Add input-action and output-action slots. (soap-parse-operation): Parse wsaw:Action nodes. (soap-encode-body): Encode service-url for WS-Addressing. (soap-create-envelope): Likewise. (soap-invoke): Update soap-create-envelope call to provide service-url argument. * soap-client.el (soap-decode-xs-complex-type): Support xsi:type override attribute. (soap-decode-array): Likewise. * soap-client.el (soap-parse-schema): Handle location attribute. * soap-client.el (soap-decode-type): Check that multiRef matched validation regexp. * soap-client.el (soap-encode-xs-simple-type): Encode xsd:list nodes. (soap-decode-xs-simple-type): Decode xsd:list nodes. * soap-client.el (soap-get-candidate-elements): Fix reference handling. * soap-client.el (soap-xs-simple-type): Add is-list slot. (soap-xs-parse-simple-type): Call soap-xs-add-list for xsd:list nodes. (soap-xs-add-list): New function. * soap-client.el (soap-encode-xs-element): When a boolean is expected, interpret nil as "false". * soap-client.el (soap-make-xs-basic-types): Add gYearMonth, gYear, gMonthDay, gDay and gMonth. * soap-client.el (soap-time-format): New variable. (soap-encode-xs-basic-type): Handle dateTime, time, date, gYearMonth, gYear, gMonthDay, gDay and gMonth. (soap-decode-date-time): New function. (soap-decode-xs-basic-type): Use soap-decode-date-time. * soap-client.el (soap-encode-xs-basic-type): Validate value after encoding. (soap-decode-xs-basic-type): Validate value before decoding. * soap-client.el (soap-validate-xs-basic-type): New function. (soap-validate-xs-simple-type): Call soap-validate-xs-basic-type. * soap-client.el (soap-xs-add-union): Append result to base instead of overwriting it. (soap-validate-xs-simple-type): Add union support. * soap-client.el (soap-xs-add-restriction): Translate pattern to Emacs regexp using xsdre-translate. (soap-validate-xs-simple-type): Validate value against pattern. * soap-client.el (soap-xs-add-union): Preserve WSDL order of inline simpleType nodes. (soap-decode-type): Handle union types. * soap-client.el (soap-decode-xs-attributes): Decode basic-type attributes. * soap-client.el (soap-get-xs-attributes-from-groups): renamed from soap-xs-attribute-group-consolidate, all callers updated (soap-get-xs-attributes): renamed from soap-xs-attributes-consolidate, all callers updated * soap-client.el (soap-xs-type): Add attribute-group slot. (soap-xs-attribute-group): New type. (soap-xs-parse-attribute-group): New function. (soap-resolve-references-for-xs-attribute-group): Likewise. (soap-xs-add-extension): Handle attribute groups. (soap-resolve-references-for-xs-simple-type): Likewise. (soap-xs-parse-complex-type): Likewise. (soap-xs-parse-extension-or-restriction): Likewise. (soap-resolve-references-for-xs-complex-type): Likewise. (soap-xs-attribute-group-consolidate): New function. (soap-xs-attributes-consolidate): Handle attribute groups. (soap-parse-schema): Likewise. * soap-client.el (soap-encode-xs-basic-type): Fix boolean encoding. * soap-client.el (soap-encode-xs-complex-type): Print ref element names in warnings. * soap-client.el (soap-decode-xs-complex-type): Fix splicing. * soap-client.el (soap-decode-xs-complex-type): Eliminate invalid warnings for choice types. * soap-client.el (soap-encode-xs-complex-type-attributes): Also encode base type attributes. * soap-client.el (soap-encode-xs-complex-type): Fix compilation warning. Print e-name in warnings, or element if e-name is nil. * soap-client.el (soap-xs-element): Add alternatives slot. (soap-xs-parse-element): Set substitution-group. (soap-resolve-references-for-xs-element): Populate alternatives slot. (soap-get-candidate-elements): New function. (soap-encode-xs-complex-type): Iterate through all candidate elements. Handle types with nil type indicator. Fix warning logic. * soap-client.el (soap-current-wsdl): moved declaration earlier in the file to prevent compiler warning. * soap-client.el (soap-node-optional): New function. (soap-node-multiple): Likewise. (soap-xs-parse-element): Call soap-node-optional and soap-node-multiple. (soap-xs-complex-type): Add optional? and multiple? slots. (soap-xml-get-children-fq): New function. (soap-xs-element-get-fq-name): Likewise. (soap-xs-complex-type-optional-p): Likewise. (soap-xs-complex-type-multiple-p): Likewise. (soap-xs-attributes-consolidate): Likewise. (soap-decode-xs-attributes): Likewise. (soap-decode-xs-complex-type): Decode types with nil type indicator. Support children that use local namespaces. Decode attributes. Add type considerations to optional? and multiple? warnings. * soap-client.el (soap-xs-parse-extension-or-restriction): Store parsed attributes. (soap-encode-xs-complex-type-attributes): Encode custom attributes. * soap-client.el (soap-encode-xs-complex-type-attributes): don't add the xsi:type attribute (Exchange refuses requests which have this attribute) * soap-client.el, soap-inspect.el: converted to lexical binding, corrected compiler warnings about unused function arguments and local variables. * soap-client.el (soap-decode-xs-complex-type): Handle nil type indicator. (soap-parse-envelope): Handle response headers. (soap-parse-response): Likewise. Only return non-nil decoded values. * soap-client.el (soap-validate-xs-simple-type): Return validated value. * soap-client.el (soap-xs-parse-element) (soap-xs-parse-simple-type) (soap-xs-parse-complex-type) (soap-parse-message) (soap-parse-operation): add the current namespace to the element being created (soap-resolve-references-for-xs-element) (soap-resolve-references-for-xs-simple-type) (soap-resolve-references-for-xs-complex-type) (soap-resolve-references-for-operation): resolve the namespace to the namespace tag (soap-make-wsdl): specify a namespace tag when creating the xsd and soapenc namespaces (soap-wsdl-resolve-references): don't update namespace tags in elements here (soap-parse-port-type): bind the urn: to soap-target-xmlns (soap-encode-body): don't add nil namespace tags to soap-encoded-namespaces * soap-inspect.el: use `soap-make-wsdl` to construct the object for registering the soap-inspect method.Make debbugs tests pass * soap-client.el (soap-decode-any-type): use soap-l2fq on the type name, also skip string only nodes when decoding a structure. (soap-xs-parse-complex-type): (BUG) dispatch parsing for choice types too (soap-encode-body): grab the header value from the param table * soap-client.el (soap-should-encode-value-for-xs-element): new function (soap-encode-xs-element): don't encode nil value unless needed * soap-client.el (soap-bound-operation): new slot `soap-body` (soap-parse-binding): parse the message parts required in the body (soap-encode-body): encode only the parts that are declared to be part of the body * soap-client.el (soap-encode-xs-element): use the fq name when writing out the tag. (soap-encode-body): remove hack that inserts the xmlns in the element attributes list. * soap-client.el (soap-xs-attribute): add "default" slot (soap-xs-parse-attribute): default slot is set from the XML "fixed" attribute. (soap-encode-xs-complex-type-attributes): encode any attributes that have a default value. Also, don't put the xsi:nil attribute when the complex type has no content anyway. * soap-client.el (soap-well-known-xmlns): add the xml namespace (soap-local-xmlns): start with the xml namespace (soap-xml-node-first-child): skip xsd:annotation nodes too (soap-make-xs-basic-types): more xsd types added (soap-encode-xs-basic-type, soap-decode-xs-basic-type): handle "language", "time", "date", "nonNegativeInteger" (soap-resolve-references-for-xs-element): don't signal an error if the element does not have a type. (soap-xs-parse-simple-type): subtypes are handled with ecase, added stum for xsd:list (soap-xs-add-union): call soap-l2fq on all union members (soap-xs-add-extension): call soap-l2fq on the base member (soap-resolve-references-for-xs-simple-type): don't signal an error if the simple type has no base. (soap-resolve-references-for-xs-simple-type): bugfix, call soap-wsdl-get on each type of the base * soap-client.el (soap-resolve-references-for-xs-attribute): referenced type can be eiher a simple type or a basic type (soap-xs-add-restriction) (soap-xs-parse-extension-or-restriction): use `soap-l2fq' on base (soap-make-xs-basic-types) (soap-encode-xs-basic-type, soap-decode-xs-basic-type): add support for more XMLSchema basic types (soap-current-file, soap-xmlschema-imports): new defvars (soap-parse-schema): add locations from xsd:import tags to `soap-xmlschema-imports' (soap-wsdl): make destructor private (soap-make-wsdl): new defun, SOAP-WSDL object constructor (soap-wsdl-add-alias): check if we try to replace aliases (soap-fetch-xml-from-url, soap-fetch-xml-from-file) (soap-fetch-xml): new defuns (soap-load-wsdl): updated to load the WSDL from either a file or an url (soap-load-wsdl-from-url): now an alias to `soap-load-wsdl' (soap-parse-wsdl): process wsdl:import tags and imports from `soap-xmlschema-imports' * soap-client.el (soap-l2wk): bugfix: call symbolp instead of symbol-name (soap-l2fq): make the name part always a string (soap-name-p): new defun, used for name tests * soap-inspect.el (soap-sample-value-for-xs-complex-type): supply sample values for choice types with a special tag * soap-client.el (soap-encode-xs-complex-type): handle anonymous elements correctly (soap-encode-value): accept nodes that have no namespace tag * soap-client.el (soap-invoke): encode the string for `url-request-data' as UTF-8. Fixes issue 16 Co-authored-by: Alexandru Harsanyi <AlexHarsanyi@gmail.com>
2015-10-25 17:00:37 -04:00
;; Homepage: https://github.com/alex-hhh/emacs-soap-client
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; This package provides an inspector for a WSDL document loaded with
;; `soap-load-wsdl' or `soap-load-wsdl-from-url'. To use it, evaluate:
;;
;; (soap-inspect *wsdl*)
;;
;; This will pop-up the inspector buffer. You can click on ports, operations
;; and types to explore the structure of the wsdl document.
;;
;;; Code:
(require 'cl-lib)
(require 'soap-client)
;;; sample-value
(defun soap-sample-value (type)
"Provide a sample value for TYPE, a WSDL type.
A sample value is a LISP value which soap-client.el will accept
for encoding it using TYPE when making SOAP requests.
This is a generic function, depending on TYPE a specific function
will be called."
(let ((sample-value (get (aref type 0) 'soap-sample-value)))
(if sample-value
(funcall sample-value type)
(error "Cannot provide sample value for type %s" (aref type 0)))))
(defun soap-sample-value-for-xs-basic-type (type)
"Provide a sample value for TYPE, an xs-basic-type.
This is a specialization of `soap-sample-value' for xs-basic-type
objects."
(cl-case (soap-xs-basic-type-kind type)
(string "a string")
(anyURI "an URI")
(QName "a QName")
(dateTime "a time-value-p or string")
(boolean "t or nil")
((long int integer byte unsignedInt) 42)
((float double) 3.14)
(base64Binary "a string")
(t (format "%s" (soap-xs-basic-type-kind type)))))
(defun soap-sample-value-for-xs-element (element)
"Provide a sample value for ELEMENT, a WSDL element.
This is a specialization of `soap-sample-value' for xs-element
objects."
(if (soap-xs-element-name element)
(cons (intern (soap-xs-element-name element))
(soap-sample-value (soap-xs-element-type element)))
(soap-sample-value (soap-xs-element-type element))))
(defun soap-sample-value-for-xs-attribute (attribute)
"Provide a sample value for ATTRIBUTE, a WSDL attribute.
This is a specialization of `soap-sample-value' for
soap-xs-attribute objects."
(if (soap-xs-attribute-name attribute)
(cons (intern (soap-xs-attribute-name attribute))
(soap-sample-value (soap-xs-attribute-type attribute)))
(soap-sample-value (soap-xs-attribute-type attribute))))
(defun soap-sample-value-for-xs-attribute-group (attribute-group)
"Provide a sample value for ATTRIBUTE-GROUP, a WSDL attribute group.
This is a specialization of `soap-sample-value' for
soap-xs-attribute objects."
(let ((sample-values nil))
(dolist (attribute (soap-xs-attribute-group-attributes attribute-group))
(if (soap-xs-attribute-name attribute)
(setq sample-values
(append sample-values
(cons (intern (soap-xs-attribute-name attribute))
(soap-sample-value (soap-xs-attribute-type
attribute)))))
(setq sample-values
(append sample-values
(soap-sample-value
(soap-xs-attribute-type attribute))))))))
(defun soap-sample-value-for-xs-simple-type (type)
"Provide a sample value for TYPE, a `soap-xs-simple-type'.
This is a specialization of `soap-sample-value' for
`soap-xs-simple-type' objects."
(append
(mapcar 'soap-sample-value-for-xs-attribute
(soap-xs-type-attributes type))
(cond
((soap-xs-simple-type-enumeration type)
(let ((enumeration (soap-xs-simple-type-enumeration type)))
(nth (random (length enumeration)) enumeration)))
((soap-xs-simple-type-pattern type)
(format "a string matching %s" (soap-xs-simple-type-pattern type)))
((soap-xs-simple-type-length-range type)
(cl-destructuring-bind (low . high) (soap-xs-simple-type-length-range type)
(cond
((and low high)
(format "a string between %d and %d chars long" low high))
(low (format "a string at least %d chars long" low))
(high (format "a string at most %d chars long" high))
(t (format "a string OOPS")))))
((soap-xs-simple-type-integer-range type)
(cl-destructuring-bind (min . max) (soap-xs-simple-type-integer-range type)
(cond
((and min max) (+ min (random (- max min))))
(min (+ min (random 10)))
(max (random max))
(t (random 100)))))
((consp (soap-xs-simple-type-base type)) ; an union of values
(let ((base (soap-xs-simple-type-base type)))
(soap-sample-value (nth (random (length base)) base))))
((soap-xs-basic-type-p (soap-xs-simple-type-base type))
(soap-sample-value (soap-xs-simple-type-base type))))))
(defun soap-sample-value-for-xs-complex-type (type)
"Provide a sample value for TYPE, a `soap-xs-complex-type'.
This is a specialization of `soap-sample-value' for
`soap-xs-complex-type' objects."
(append
(mapcar 'soap-sample-value-for-xs-attribute
(soap-xs-type-attributes type))
(cl-case (soap-xs-complex-type-indicator type)
(array
(let* ((element-type (soap-xs-complex-type-base type))
(sample1 (soap-sample-value element-type))
(sample2 (soap-sample-value element-type)))
;; Our sample value is a vector of two elements, but any number of
;; elements are permissible
(vector sample1 sample2 '&etc)))
((sequence choice all)
(let ((base (soap-xs-complex-type-base type)))
(let ((value (append (and base (soap-sample-value base))
(mapcar #'soap-sample-value
(soap-xs-complex-type-elements type)))))
(if (eq (soap-xs-complex-type-indicator type) 'choice)
(cons '***choice-of*** value)
value)))))))
(defun soap-sample-value-for-message (message)
"Provide a sample value for a WSDL MESSAGE.
This is a specialization of `soap-sample-value' for
`soap-message' objects."
;; NOTE: parameter order is not considered.
(let (sample-value)
(dolist (part (soap-message-parts message))
(push (soap-sample-value (cdr part)) sample-value))
(nreverse sample-value)))
(progn
;; Install soap-sample-value methods for our types
(put (aref (make-soap-xs-basic-type) 0)
'soap-sample-value
'soap-sample-value-for-xs-basic-type)
(put (aref (make-soap-xs-element) 0)
'soap-sample-value
'soap-sample-value-for-xs-element)
(put (aref (make-soap-xs-attribute) 0)
'soap-sample-value
'soap-sample-value-for-xs-attribute)
(put (aref (make-soap-xs-attribute) 0)
'soap-sample-value
'soap-sample-value-for-xs-attribute-group)
(put (aref (make-soap-xs-simple-type) 0)
'soap-sample-value
'soap-sample-value-for-xs-simple-type)
(put (aref (make-soap-xs-complex-type) 0)
'soap-sample-value
'soap-sample-value-for-xs-complex-type)
(put (aref (make-soap-message) 0)
'soap-sample-value
'soap-sample-value-for-message))
;;; soap-inspect
(defvar soap-inspect-previous-items nil
"A stack of previously inspected items in the *soap-inspect* buffer.
Used to implement the BACK button.")
(defvar soap-inspect-current-item nil
"The current item being inspected in the *soap-inspect* buffer.")
(progn
(make-variable-buffer-local 'soap-inspect-previous-items)
(make-variable-buffer-local 'soap-inspect-current-item))
(defun soap-inspect (element)
"Inspect a SOAP ELEMENT in the *soap-inspect* buffer.
The buffer is populated with information about ELEMENT with links
to its sub elements. If ELEMENT is the WSDL document itself, the
entire WSDL can be inspected."
(let ((inspect (get (aref element 0) 'soap-inspect)))
(unless inspect
(error "Soap-inspect: no inspector for element"))
(with-current-buffer (get-buffer-create "*soap-inspect*")
(setq buffer-read-only t)
(let ((inhibit-read-only t))
(erase-buffer)
(when soap-inspect-current-item
(push soap-inspect-current-item
soap-inspect-previous-items))
(setq soap-inspect-current-item element)
(funcall inspect element)
(unless (null soap-inspect-previous-items)
(insert "\n\n")
(insert-text-button
"[back]"
'type 'soap-client-describe-back-link
'item element)
(insert "\n"))
(goto-char (point-min))
(pop-to-buffer (current-buffer))))))
(define-button-type 'soap-client-describe-link
'face 'link
'help-echo "mouse-2, RET: describe item"
'follow-link t
'action (lambda (button)
(let ((item (button-get button 'item)))
(soap-inspect item)))
'skip t)
(define-button-type 'soap-client-describe-back-link
'face 'link
'help-echo "mouse-2, RET: browse the previous item"
'follow-link t
'action (lambda (_button)
(let ((item (pop soap-inspect-previous-items)))
(when item
(setq soap-inspect-current-item nil)
(soap-inspect item))))
'skip t)
(defun soap-insert-describe-button (element)
"Insert a button to inspect ELEMENT when pressed."
(insert-text-button
(soap-element-fq-name element)
'type 'soap-client-describe-link
'item element))
(defun soap-inspect-xs-basic-type (type)
"Insert information about TYPE, a soap-xs-basic-type, in the current buffer."
(insert "Basic type: " (soap-element-fq-name type))
(insert "\nSample value:\n")
(pp (soap-sample-value type) (current-buffer)))
(defun soap-inspect-xs-element (element)
"Insert information about ELEMENT, a soap-xs-element, in the current buffer."
(insert "Element: " (soap-element-fq-name element))
(insert "\nType: ")
(soap-insert-describe-button (soap-xs-element-type element))
(insert "\nAttributes:")
(when (soap-xs-element-optional? element)
(insert " optional"))
(when (soap-xs-element-multiple? element)
(insert " multiple"))
(insert "\nSample value:\n")
(pp (soap-sample-value element) (current-buffer)))
(defun soap-inspect-xs-attribute (attribute)
"Insert information about ATTRIBUTE in the current buffer.
ATTRIBUTE is a soap-xs-attribute."
(insert "Attribute: " (soap-element-fq-name attribute))
(insert "\nType: ")
(soap-insert-describe-button (soap-xs-attribute-type attribute))
(insert "\nSample value:\n")
(pp (soap-sample-value attribute) (current-buffer)))
(defun soap-inspect-xs-attribute-group (attribute-group)
"Insert information about ATTRIBUTE-GROUP in the current buffer.
ATTRIBUTE is a soap-xs-attribute-group."
(insert "Attribute group: " (soap-element-fq-name attribute-group))
(insert "\nSample values:\n")
(pp (soap-sample-value attribute-group) (current-buffer)))
(defun soap-inspect-xs-simple-type (type)
"Insert information about TYPE, a soap-xs-simple-type, in the current buffer."
(insert "Simple type: " (soap-element-fq-name type))
(insert "\nBase: " )
(if (listp (soap-xs-simple-type-base type))
(let ((first-time t))
(dolist (b (soap-xs-simple-type-base type))
(unless first-time
(insert ", ")
(setq first-time nil))
(soap-insert-describe-button b)))
(soap-insert-describe-button (soap-xs-simple-type-base type)))
(insert "\nAttributes: ")
(dolist (attribute (soap-xs-simple-type-attributes type))
(let ((name (or (soap-xs-attribute-name attribute) "*inline*"))
(type (soap-xs-attribute-type attribute)))
(insert "\n\t")
(insert name)
(insert "\t")
(soap-insert-describe-button type)))
(when (soap-xs-simple-type-enumeration type)
(insert "\nEnumeration values: ")
(dolist (e (soap-xs-simple-type-enumeration type))
(insert "\n\t")
(pp e)))
(when (soap-xs-simple-type-pattern type)
(insert "\nPattern: " (soap-xs-simple-type-pattern type)))
(when (car (soap-xs-simple-type-length-range type))
(insert "\nMin length: "
(number-to-string (car (soap-xs-simple-type-length-range type)))))
(when (cdr (soap-xs-simple-type-length-range type))
(insert "\nMin length: "
(number-to-string (cdr (soap-xs-simple-type-length-range type)))))
(when (car (soap-xs-simple-type-integer-range type))
(insert "\nMin value: "
(number-to-string (car (soap-xs-simple-type-integer-range type)))))
(when (cdr (soap-xs-simple-type-integer-range type))
(insert "\nMin value: "
(number-to-string (cdr (soap-xs-simple-type-integer-range type)))))
(insert "\nSample value:\n")
(pp (soap-sample-value type) (current-buffer)))
(defun soap-inspect-xs-complex-type (type)
"Insert information about TYPE in the current buffer.
TYPE is a `soap-xs-complex-type'"
(insert "Complex type: " (soap-element-fq-name type))
(insert "\nKind: ")
(cl-case (soap-xs-complex-type-indicator type)
((sequence all)
(insert "a sequence ")
(when (soap-xs-complex-type-base type)
(insert "extending ")
(soap-insert-describe-button (soap-xs-complex-type-base type)))
(insert "\nAttributes: ")
(dolist (attribute (soap-xs-complex-type-attributes type))
(let ((name (or (soap-xs-attribute-name attribute) "*inline*"))
(type (soap-xs-attribute-type attribute)))
(insert "\n\t")
(insert name)
(insert "\t")
(soap-insert-describe-button type)))
(insert "\nElements: ")
(let ((name-width 0)
(type-width 0))
(dolist (element (soap-xs-complex-type-elements type))
(let ((name (or (soap-xs-element-name element) "*inline*"))
(type (soap-xs-element-type element)))
(setq name-width (max name-width (length name)))
(setq type-width
(max type-width (length (soap-element-fq-name type))))))
(setq name-width (+ name-width 2))
(setq type-width (+ type-width 2))
(dolist (element (soap-xs-complex-type-elements type))
(let ((name (or (soap-xs-element-name element) "*inline*"))
(type (soap-xs-element-type element)))
(insert "\n\t")
(insert name)
(insert (make-string (- name-width (length name)) ?\ ))
(soap-insert-describe-button type)
(insert
(make-string
(- type-width (length (soap-element-fq-name type))) ?\ ))
(when (soap-xs-element-multiple? element)
(insert " multiple"))
(when (soap-xs-element-optional? element)
(insert " optional"))))))
(choice
(insert "a choice ")
(when (soap-xs-complex-type-base type)
(insert "extending ")
(soap-insert-describe-button (soap-xs-complex-type-base type)))
(insert "\nElements: ")
(dolist (element (soap-xs-complex-type-elements type))
(insert "\n\t")
(soap-insert-describe-button element)))
(array
(insert "an array of ")
(soap-insert-describe-button (soap-xs-complex-type-base type))))
(insert "\nSample value:\n")
(pp (soap-sample-value type) (current-buffer)))
(defun soap-inspect-message (message)
"Insert information about MESSAGE into the current buffer."
(insert "Message name: " (soap-element-fq-name message) "\n")
(insert "Parts:\n")
(dolist (part (soap-message-parts message))
(insert "\t" (symbol-name (car part))
" type: ")
(soap-insert-describe-button (cdr part))
(insert "\n")))
(defun soap-inspect-operation (operation)
"Insert information about OPERATION into the current buffer."
(insert "Operation name: " (soap-element-fq-name operation) "\n")
(let ((input (soap-operation-input operation)))
(insert "\tInput: " (symbol-name (car input)) " (" )
(soap-insert-describe-button (cdr input))
(insert ")\n"))
(let ((output (soap-operation-output operation)))
(insert "\tOutput: " (symbol-name (car output)) " (")
(soap-insert-describe-button (cdr output))
(insert ")\n"))
(insert "\n\nSample invocation:\n")
(let ((sample-message-value
(soap-sample-value (cdr (soap-operation-input operation))))
(funcall (list 'soap-invoke '*WSDL* "SomeService"
(soap-element-name operation))))
(let ((sample-invocation
(append funcall (mapcar 'cdr sample-message-value))))
(pp sample-invocation (current-buffer)))))
(defun soap-inspect-port-type (port-type)
"Insert information about PORT-TYPE into the current buffer."
(insert "Port-type name: " (soap-element-fq-name port-type) "\n")
(insert "Operations:\n")
(cl-loop for o being the hash-values of
(soap-namespace-elements (soap-port-type-operations port-type))
do (progn
(insert "\t")
(soap-insert-describe-button (car o)))))
(defun soap-inspect-binding (binding)
"Insert information about BINDING into the current buffer."
(insert "Binding: " (soap-element-fq-name binding) "\n")
(insert "\n")
(insert "Bound operations:\n")
(let* ((ophash (soap-binding-operations binding))
(operations (cl-loop for o being the hash-keys of ophash
collect o))
op-name-width)
(setq operations (sort operations 'string<))
(setq op-name-width (cl-loop for o in operations maximizing (length o)))
(dolist (op operations)
(let* ((bound-op (gethash op ophash))
(soap-action (soap-bound-operation-soap-action bound-op))
(use (soap-bound-operation-use bound-op)))
(unless soap-action
(setq soap-action ""))
(insert "\t")
(soap-insert-describe-button (soap-bound-operation-operation bound-op))
(when (or use (not (equal soap-action "")))
(insert (make-string (- op-name-width (length op)) ?\s))
(insert " (")
(insert soap-action)
(when use
(insert " " (symbol-name use)))
(insert ")"))
(insert "\n")))))
(defun soap-inspect-port (port)
"Insert information about PORT into the current buffer."
(insert "Port name: " (soap-element-name port) "\n"
"Service URL: " (soap-port-service-url port) "\n"
"Binding: ")
(soap-insert-describe-button (soap-port-binding port)))
(defun soap-inspect-wsdl (wsdl)
"Insert information about WSDL into the current buffer."
(insert "WSDL Origin: " (soap-wsdl-origin wsdl) "\n")
(insert "Ports:")
(dolist (p (soap-wsdl-ports wsdl))
(insert "\n--------------------\n")
;; (soap-insert-describe-button p)
(soap-inspect-port p))
(insert "\n--------------------\nNamespace alias table:\n")
(dolist (a (soap-wsdl-alias-table wsdl))
(insert "\t" (car a) " => " (cdr a) "\n")))
(progn
;; Install the soap-inspect methods for our types
(put (aref (make-soap-xs-basic-type) 0) 'soap-inspect
'soap-inspect-xs-basic-type)
(put (aref (make-soap-xs-element) 0) 'soap-inspect
'soap-inspect-xs-element)
(put (aref (make-soap-xs-simple-type) 0) 'soap-inspect
'soap-inspect-xs-simple-type)
(put (aref (make-soap-xs-complex-type) 0) 'soap-inspect
'soap-inspect-xs-complex-type)
(put (aref (make-soap-xs-attribute) 0) 'soap-inspect
'soap-inspect-xs-attribute)
(put (aref (make-soap-xs-attribute-group) 0) 'soap-inspect
'soap-inspect-xs-attribute-group)
(put (aref (make-soap-message) 0) 'soap-inspect
'soap-inspect-message)
(put (aref (make-soap-operation) 0) 'soap-inspect
'soap-inspect-operation)
(put (aref (make-soap-port-type) 0) 'soap-inspect
'soap-inspect-port-type)
(put (aref (make-soap-binding) 0) 'soap-inspect
'soap-inspect-binding)
(put (aref (make-soap-port) 0) 'soap-inspect
'soap-inspect-port)
(put (aref (soap-make-wsdl "origin") 0) 'soap-inspect
'soap-inspect-wsdl))
(provide 'soap-inspect)
;;; soap-inspect.el ends here