Function: icalendar-ast-node-valid-children-p

icalendar-ast-node-valid-children-p is a byte-compiled function defined in icalendar-ast.el.gz.

Signature

(icalendar-ast-node-valid-children-p NODE)

Documentation

Validate that NODE's children satisfy its type's :child-spec.

The :child-spec is associated with NODE's type by icalendar-define-component, icalendar-define-property, icalendar-define-param, or icalendar-define-type, which see. Signals an icalendar-validation-error if NODE is invalid, or returns NODE.

Note that this function does not check that the children of NODE are themselves valid; for that, see ical:ast-node-valid-p.

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/icalendar-ast.el.gz
(defun ical:ast-node-valid-children-p (node)
  "Validate that NODE's children satisfy its type's :child-spec.

The :child-spec is associated with NODE's type by
`icalendar-define-component', `icalendar-define-property',
`icalendar-define-param', or `icalendar-define-type', which see.
Signals an `icalendar-validation-error' if NODE is invalid, or returns
NODE.

Note that this function does not check that the children of NODE
are themselves valid; for that, see `ical:ast-node-valid-p'."
  (let* ((type (ical:ast-node-type node))
         (child-spec (get type 'ical:child-spec))
         (child-counts (ical:count-children-by-type node)))

    (when child-spec

      (dolist (child-type (plist-get child-spec :one))
        (unless (= 1 (alist-get child-type child-counts 0))
          (ical:signal-validation-error
            (format "iCalendar `%s' node must contain exactly one `%s'"
                    type child-type)
            :node node)))

      (dolist (child-type (plist-get child-spec :one-or-more))
        (unless (<= 1 (alist-get child-type child-counts 0))
          (ical:signal-validation-error
           (format "iCalendar `%s' node must contain one or more `%s'"
                   type child-type)
           :node node)))

      (dolist (child-type (plist-get child-spec :zero-or-one))
        (unless (<= (alist-get child-type child-counts 0)
                    1)
          (ical:signal-validation-error
           (format "iCalendar `%s' node may contain at most one `%s'"
                   type child-type)
           :node node)))

      ;; check that all child nodes are allowed:
      (unless (plist-get child-spec :allow-others)
        (let ((allowed-types (append (plist-get child-spec :one)
                                     (plist-get child-spec :one-or-more)
                                     (plist-get child-spec :zero-or-one)
                                     (plist-get child-spec :zero-or-more)))
              (appearing-types (mapcar #'car child-counts)))

          (dolist (child-type appearing-types)
            (unless (member child-type allowed-types)
              (ical:signal-validation-error
               (format "`%s' may not contain `%s'" type child-type)
               :node node))))))
    ;; success:
    node))