summaryrefslogtreecommitdiff
path: root/main/xmldoc.c
diff options
context:
space:
mode:
authorKinsey Moore <kmoore@digium.com>2014-07-24 13:00:59 +0000
committerKinsey Moore <kmoore@digium.com>2014-07-24 13:00:59 +0000
commit4445ee7fc093810e791e9855815f07da2a60619d (patch)
tree9d10faa91a9927c01486dc635d56485b534abb7e /main/xmldoc.c
parentccc6e8bd170ed6a53158e2307237c99b6f33d6e6 (diff)
AMI: Allow for command response documentation
Allow for responses to AMI actions/commands to be documented properly in XML and displayed via the CLI. Response events are documented exactly as standard AMI events are documented. Review: https://reviewboard.asterisk.org/r/3812/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419342 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/xmldoc.c')
-rw-r--r--main/xmldoc.c181
1 files changed, 158 insertions, 23 deletions
diff --git a/main/xmldoc.c b/main/xmldoc.c
index 28bea86bd..a84b05982 100644
--- a/main/xmldoc.c
+++ b/main/xmldoc.c
@@ -2300,9 +2300,9 @@ static void ast_xml_doc_item_destructor(void *obj)
ast_free(doc->description);
ast_string_field_free_memory(doc);
- if (doc->next) {
- ao2_ref(doc->next, -1);
- doc->next = NULL;
+ if (AST_LIST_NEXT(doc, next)) {
+ ao2_ref(AST_LIST_NEXT(doc, next), -1);
+ AST_LIST_NEXT(doc, next) = NULL;
}
}
@@ -2428,6 +2428,139 @@ static struct ast_xml_doc_item *xmldoc_build_documentation_item(struct ast_xml_n
return item;
}
+/*!
+ * \internal
+ * \brief Build the list responses for an item
+ *
+ * \param manager_action The action node to parse
+ *
+ * \note This method exists for when you already have the node. This
+ * prevents having to lock the documentation tree twice
+ *
+ * \retval A list of ast_xml_doc_items
+ * \retval NULL on failure
+ *
+ * \since 13.0.0
+ */
+static struct ast_xml_doc_item *xmldoc_build_list_responses(struct ast_xml_node *manager_action)
+{
+ struct ast_xml_node *event;
+ struct ast_xml_node *responses;
+ struct ast_xml_node *list_elements;
+ struct ast_xml_doc_item_list root;
+
+ AST_LIST_HEAD_INIT(&root);
+
+ responses = ast_xml_find_element(ast_xml_node_get_children(manager_action), "responses", NULL, NULL);
+ if (!responses) {
+ return NULL;
+ }
+
+ list_elements = ast_xml_find_element(ast_xml_node_get_children(responses), "list-elements", NULL, NULL);
+ if (!list_elements) {
+ return NULL;
+ }
+
+ /* Iterate over managerEvent nodes */
+ for (event = ast_xml_node_get_children(list_elements); event; event = ast_xml_node_get_next(event)) {
+ struct ast_xml_node *event_instance;
+ const char *name = ast_xml_get_attribute(event, "name");
+ struct ast_xml_doc_item *new_item;
+
+ if (!name || strcmp(ast_xml_node_get_name(event), "managerEvent")) {
+ continue;
+ }
+
+ event_instance = ast_xml_find_element(ast_xml_node_get_children(event),
+ "managerEventInstance", NULL, NULL);
+ new_item = xmldoc_build_documentation_item(event_instance, name, "managerEvent");
+ if (!new_item) {
+ ao2_cleanup(AST_LIST_FIRST(&root));
+ return NULL;
+ }
+
+ AST_LIST_INSERT_TAIL(&root, new_item, next);
+ }
+
+ return AST_LIST_FIRST(&root);
+}
+
+struct ast_xml_doc_item *ast_xmldoc_build_list_responses(const char *type, const char *name, const char *module)
+{
+ struct ast_xml_node *node;
+
+ if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
+ return NULL;
+ }
+
+ node = xmldoc_get_node(type, name, module, documentation_language);
+
+ if (!node || !ast_xml_node_get_children(node)) {
+ return NULL;
+ }
+
+ return xmldoc_build_list_responses(node);
+}
+
+/*!
+ * \internal
+ * \brief Build the final response for an item
+ *
+ * \param manager_action The action node to parse
+ *
+ * \note This method exists for when you already have the node. This
+ * prevents having to lock the documentation tree twice
+ *
+ * \retval An ast_xml_doc_item
+ * \retval NULL on failure
+ *
+ * \since 13.0.0
+ */
+static struct ast_xml_doc_item *xmldoc_build_final_response(struct ast_xml_node *manager_action)
+{
+ struct ast_xml_node *responses;
+ struct ast_xml_node *final_response_event;
+ struct ast_xml_node *event_instance;
+
+ responses = ast_xml_find_element(ast_xml_node_get_children(manager_action),
+ "responses", NULL, NULL);
+ if (!responses) {
+ return NULL;
+ }
+
+ final_response_event = ast_xml_find_element(ast_xml_node_get_children(responses),
+ "managerEvent", NULL, NULL);
+ if (!final_response_event) {
+ return NULL;
+ }
+
+ event_instance = ast_xml_find_element(ast_xml_node_get_children(final_response_event),
+ "managerEventInstance", NULL, NULL);
+ if (!event_instance) {
+ return NULL;
+ }
+
+ return xmldoc_build_documentation_item(event_instance,
+ ast_xml_get_attribute(final_response_event, "name"), "managerEvent");
+}
+
+struct ast_xml_doc_item *ast_xmldoc_build_final_response(const char *type, const char *name, const char *module)
+{
+ struct ast_xml_node *node;
+
+ if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
+ return NULL;
+ }
+
+ node = xmldoc_get_node(type, name, module, documentation_language);
+
+ if (!node || !ast_xml_node_get_children(node)) {
+ return NULL;
+ }
+
+ return xmldoc_build_final_response(node);
+}
+
struct ast_xml_xpath_results *__attribute__((format(printf, 1, 2))) ast_xmldoc_query(const char *fmt, ...)
{
struct ast_xml_xpath_results *results = NULL;
@@ -2455,7 +2588,7 @@ struct ast_xml_xpath_results *__attribute__((format(printf, 1, 2))) ast_xmldoc_q
return results;
}
-static void build_config_docs(struct ast_xml_node *cur, struct ast_xml_doc_item **tail)
+static void build_config_docs(struct ast_xml_node *cur, struct ast_xml_doc_item_list *root)
{
struct ast_xml_node *iter;
struct ast_xml_doc_item *item;
@@ -2478,9 +2611,8 @@ static void build_config_docs(struct ast_xml_node *cur, struct ast_xml_doc_item
ast_string_field_set(item, ref, name);
ast_xml_free_attr(name);
}
- (*tail)->next = item;
- *tail = (*tail)->next;
- build_config_docs(iter, tail);
+ AST_LIST_INSERT_TAIL(root, item, next);
+ build_config_docs(iter, root);
}
}
@@ -2536,7 +2668,6 @@ int ast_xmldoc_regenerate_doc_item(struct ast_xml_doc_item *item)
struct ao2_container *ast_xmldoc_build_documentation(const char *type)
{
struct ao2_container *docs;
- struct ast_xml_doc_item *item = NULL, *root = NULL;
struct ast_xml_node *node = NULL, *instance = NULL;
struct documentation_tree *doctree;
const char *name;
@@ -2555,6 +2686,8 @@ struct ao2_container *ast_xmldoc_build_documentation(const char *type)
}
for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+ struct ast_xml_doc_item *item = NULL;
+
/* Ignore empty nodes or nodes that aren't of the type requested */
if (!ast_xml_node_get_children(node) || strcasecmp(ast_xml_node_get_name(node), type)) {
continue;
@@ -2566,6 +2699,10 @@ struct ao2_container *ast_xmldoc_build_documentation(const char *type)
switch (xmldoc_get_syntax_type(type)) {
case MANAGER_EVENT_SYNTAX:
+ {
+ struct ast_xml_doc_item_list root;
+
+ AST_LIST_HEAD_INIT(&root);
for (instance = ast_xml_node_get_children(node); instance; instance = ast_xml_node_get_next(instance)) {
struct ast_xml_doc_item *temp;
if (!ast_xml_node_get_children(instance) || strcasecmp(ast_xml_node_get_name(instance), "managerEventInstance")) {
@@ -2575,28 +2712,27 @@ struct ao2_container *ast_xmldoc_build_documentation(const char *type)
if (!temp) {
break;
}
- if (!item) {
- item = temp;
- root = item;
- } else {
- item->next = temp;
- item = temp;
- }
+ AST_LIST_INSERT_TAIL(&root, temp, next);
}
- item = root;
+ item = AST_LIST_FIRST(&root);
break;
+ }
case CONFIG_INFO_SYNTAX:
{
- struct ast_xml_doc_item *tail;
RAII_VAR(const char *, name, ast_xml_get_attribute(node, "name"), ast_xml_free_attr);
- if (item || !ast_xml_node_get_children(node) || strcasecmp(ast_xml_node_get_name(node), "configInfo")) {
+
+ if (!ast_xml_node_get_children(node) || strcasecmp(ast_xml_node_get_name(node), "configInfo")) {
break;
}
- if (!(item = xmldoc_build_documentation_item(node, name, "configInfo"))) {
- break;
+
+ item = xmldoc_build_documentation_item(node, name, "configInfo");
+ if (item) {
+ struct ast_xml_doc_item_list root;
+
+ AST_LIST_HEAD_INIT(&root);
+ AST_LIST_INSERT_TAIL(&root, item, next);
+ build_config_docs(node, &root);
}
- tail = item;
- build_config_docs(node, &tail);
break;
}
default:
@@ -2607,7 +2743,6 @@ struct ao2_container *ast_xmldoc_build_documentation(const char *type)
if (item) {
ao2_link(docs, item);
ao2_t_ref(item, -1, "Dispose of creation ref");
- item = NULL;
}
}
}