Blob Blame History Raw
/*
 * wsman-xml.i
 *
 * xml structure accessors for openwsman swig bindings
 *
 */

/*
 * Document-class: XmlNs
 * Xml namespace
 *
 */
 
%rename(XmlNs) __WsXmlNs;
%nodefault __WsXmlNs;   /* part of WsXmlAttr */
struct __WsXmlNs {}; /* without empty struct, the %rename isn't executed. */
typedef struct __WsXmlNs* WsXmlNsH;

/*
 * XmlDoc
 *
 * Implementation advice
 *
 * DONT do a %newobject on functions returning WsXmlDoc. Swig will
 * free the WsXmlDocH immediately after wrapping !
 *
 */

%rename(XmlDoc) _WsXmlDoc;
%nodefault _WsXmlDoc;
struct _WsXmlDoc {};
typedef struct _WsXmlDoc* WsXmlDocH;

/*
 * Document-class: XmlDoc
 *
 * XmlDoc holds an XML document and thus represents the root of an XML
 * tree. XmlDoc is optimized for SOAP type documents, giving accessors
 * to the SOAP envelope, header and body.
 *
 * Instances of the other XML related classes like XmlAttr and XmlNode
 * can only be created with an associated XmlDoc instance.
 *
 * Main properties of the XML document are
 * * name of the root element
 * * encoding (defaults to _UTF-8_)
 *
 */
%extend _WsXmlDoc {
  /*
   * Create XmlDoc with node name
   * optionally pass namespace as 2nd arg (defaults to NULL)
   *
   */
  _WsXmlDoc(const char *name, const char *ns = NULL) {
    return ws_xml_create_doc(ns, name);
  }
  /* destructor */
  ~_WsXmlDoc() {
    ws_xml_destroy_doc( $self );
  }
  %typemap(newfree) char * "free($1);";
#if defined(SWIGRUBY)
  %alias string "to_xml";
#endif
#if defined(SWIGPYTHON)
  %rename("__str__") string();
#endif
#if defined(SWIGJAVA)
  %rename("toString") string();
#endif
  %newobject string;
  /*
   * generic (indented) string representation of the XmlDoc UTF-8 encoded.
   * see encode for setting the encoding.
   *
   * alias: to_xml
   *
   * call-seq:
   *  doc.string -> String
   *  doc.to_xml -> String
   *
   */
  char *string() {
    int size;
    char *buf;
    /* force utf-8 encoding since e.g. winrm sends utf-16 */
    ws_xml_dump_memory_node_tree_enc( ws_xml_get_doc_root($self), &buf, &size, "UTF-8" );
    return buf;
  }

#if defined(SWIGRUBY)
  %alias encode "to_s";
#endif
  %newobject encode;
  /*
   * encode document as string with specific encoding
   * (non-indented representation)
   *
   * encoding defaults to 'utf-8'
   *
   * alias: to_s
   *
   * call-seq:
   *  doc.encode -> String
   *  doc.encode("UTF-16") -> String
   *  doc.to_s -> string
   *
   */
  char *encode(const char *encoding = "utf-8") {
    int size;
    char *buf;
    ws_xml_dump_memory_enc( $self, &buf, &size, encoding );
    return buf;
  }

  /*
   * dump document to file
   *
   * call-seq:
   *   doc.dump(IO) -> nil
   *
   */
  void dump_file(FILE *fp) {
    ws_xml_dump_doc( fp, $self );
  }			      
  /*
   * get root node of doc
   * call-seq:
   *  doc.root -> XmlNode
   *
   */
  WsXmlNodeH root() {
    return ws_xml_get_doc_root( $self );
  }
  /*
   * get soap envelope node
   * call-seq:
   *  doc.envelope -> XmlNode
   *
   */
  WsXmlNodeH envelope() {
    return ws_xml_get_soap_envelope( $self );
  }
  /*
   * get soap header node
   * call-seq:
   *  doc.header -> XmlNode
   *
   */
  WsXmlNodeH header() {
    return ws_xml_get_soap_header( $self );
  }
  /*
   * get soap body node
   * call-seq:
   *  doc.body -> XmlNode
   *
   */
  WsXmlNodeH body() {
    return ws_xml_get_soap_body( $self );
  }
  /*
   * get soap element node by name
   * returns nil if no element with the name can be found
   *
   * call-seq:
   *  doc.element(String) -> XmlNode
   *
   */
  WsXmlNodeH element(const char *name) {
    return ws_xml_get_soap_element( $self, name );
  }
  %newobject context;
  /*
   * get enumeration context as string
   * return nil if context not present or empty
   *
   * call-seq:
   *  doc.context -> String
   *
   */
  const char *context() {
    char *c = wsmc_get_enum_context( $self );
    if (c) {
      if (*c)
        return c;
      u_free(c);
    }
    return NULL;
  }
  /*
   * Generate fault document based on given status
   *
   * This creates a new XmlDoc instance representing a fault
   *
   * call-seq:
   *  doc.generate_fault(Openwsman::Status) -> XmlDoc
   *
   */
  WsXmlDocH generate_fault(WsmanStatus *s) {
    return wsman_generate_fault( $self, s->fault_code, s->fault_detail_code, s->fault_msg);
  }
  
#if defined(SWIGRUBY)
  %rename("fault?") is_fault();
  %typemap(out) int is_fault
    "$result = ($1 != 0) ? Qtrue : Qfalse;";
#endif
#if defined(SWIGJAVA)
  %rename("isFault") is_fault();
  %typemap(jstype) int is_fault "boolean"
  %typemap(javaout) int is_fault {
	  return ( $jnicall != 0 ) ? true : false;
  }
#endif
  /*
   * Check if document represents a fault
   *
   * call-seq:
   *  doc.fault?(XmlDoc) -> Boolean
   *
   */
  int is_fault() {
    return wsmc_check_for_fault( $self );
  }
  
  %newobject fault;
  /*
   * retrieve fault data
   *
   * call-seq:
   *  doc.fault(XmlDoc) -> Openwsman::Fault
   *  doc.fault(XmlDoc) -> nil # if XmlDoc is not a fault
   *
   */
  WsManFault *fault() {
    WsManFault *f = NULL;
    if (wsmc_check_for_fault($self)) {
      f = (WsManFault *)calloc(1, sizeof(WsManFault));
      wsmc_get_fault_data($self, f);
    }
    return f;
  }
  
  /*
   * Generate response envelope document, optionally relating to a
   * specific action.
   *
   * This creates a new XmlDoc instance representing a response.
   *
   * call-seq:
   *  doc.create_response_envelope(String action) -> XmlDoc
   *
   */
  WsXmlDocH create_response_envelope(const char *action = NULL) {
    return wsman_create_response_envelope($self, action);
  }
  
#if defined(SWIGRUBY)
  %rename("end_of_sequence?") is_end_of_sequence();
  %typemap(out) int is_end_of_sequence
    "$result = ($1 != 0) ? Qtrue : Qfalse;";
#endif
  /*
   * Check if document represents an end of sequence (last enumeration item)
   *
   * call-seq:
   *  doc.is_end_of_sequence() -> Boolean
   *
   */
  int is_end_of_sequence() {
    return NULL != ws_xml_find_in_tree( ws_xml_get_soap_body( $self ), XML_NS_ENUMERATION, WSENUM_END_OF_SEQUENCE, 1 );
  }

}


/*
 * Document-class: XmlNode
 *
 * XmlNode is a node inside the XML document tree.
 * 
 * A node has
 * * a name
 * * a namespace (optional)
 * * attributes
 * * text (optional)
 * * a parent
 * * a document (root)
 * * children (empty for tail nodes)
 *
 */
 
%rename(XmlNode) __WsXmlNode;
%nodefault __WsXmlNode;
struct __WsXmlNode {}; /* without empty struct, the %rename isn't executed. */
typedef struct __WsXmlNode* WsXmlNodeH;

%extend __WsXmlNode {
  ~__WsXmlNode() {
    ws_xml_unlink_node($self);
  }
#if defined(SWIGRUBY)
  %alias text "to_s";
  %alias string "to_xml";
#endif
#if defined(SWIGPYTHON)
  %rename("__str__") text();
#endif
#if defined(SWIGJAVA)
  %rename("toString") text();
  %rename("toXML") string();
#endif

  %newobject string;
  /*
   * dump node as XML string
   *
   * alias: to_xml
   *
   * call-seq:
   *  node.string(XmlNode) -> String
   *
   */
  char *string() {
    int size;
    char *buf;
    ws_xml_dump_memory_node_tree( $self, &buf, &size );
    return buf;
  }
  
  /*
   * dump node to file
   *
   * call-seq:
   *  node.dump_file(IO) -> nil
   *
   */
  void dump_file(FILE *fp) {
    ws_xml_dump_node_tree( fp, $self );
  }
  
#if defined(SWIGRUBY)
  %alias equal "==";
  %typemap(out) int equal
    "$result = ($1 != 0) ? Qtrue : Qfalse;";
#endif
#if defined(SWIGPERL)
  int __eq__( WsXmlNodeH n )
#else
  int equal( WsXmlNodeH n )
#endif
  /*
   * Test for identity (same object)
   *
   * call-seq:
   *  XmlNode == XmlNode -> Boolean
   *
   */
  { return $self == n; }	  
  
  /*
   * get text (without xml tags) of node
   *
   * alias: to_s
   *
   * call-seq:
   *  node.text(XmlNode) -> String
   *
   */
  char *text() {
    return ws_xml_get_node_text( $self );
  }
#if defined(SWIGRUBY)
  %rename( "text=" ) set_text( const char *text );
#endif
  /*
   * Set text of node
   *
   * call-seq:
   *  node.text = String
   *
   */
  void set_text( const char *text ) {
    ws_xml_set_node_text( $self, text );
  }
  
  /*
   * get XmlDoc to which node belongs
   *
   * call-seq:
   *  node.doc -> XmlDoc
   *
   */
  WsXmlDocH doc() {
    return ws_xml_get_node_doc( $self );
  }
  
  /*
   * get parent for node
   *
   * call-seq:
   *  node.parent -> XmlNode
   *
   */
  WsXmlNodeH parent() {
    return ws_xml_get_node_parent( $self );
  }
#if defined(SWIGRUBY)
  %alias child "first";
#endif

  /*
   * get first child of node
   *
   * call-seq:
   *  node.child -> XmlNode
   *
   */
  WsXmlNodeH child() {
    return xml_parser_get_first_child($self);
  }
  
  /*
   * get name for node
   *
   * call-seq:
   *  node.name -> String
   *
   */
  char *name() {
    return ws_xml_get_node_local_name( $self );
  }
#if defined(SWIGRUBY)
  %rename("name=") set_name( const char *name);
#endif

  /*
   * set name of node
   *
   * call-seq:
   *  node.name = String
   *
   */
  void set_name( const char *name ) {
    ws_xml_set_node_name( $self, ws_xml_get_node_name_ns( $self ), name );
  }
  
  /*
   * get namespace for node
   *
   * call-seq:
   *  node.ns -> String
   *
   */
  char *ns() {
    return ws_xml_get_node_name_ns( $self );
  }

#if defined(SWIGRUBY)
  %rename("ns=") set_ns( const char *nsuri );
#endif
  /*
   * set namespace of node
   *
   * call-seq:
   *  node.ns = String
   *
   */
  void set_ns( const char *ns ) {
    ws_xml_set_ns( $self, ns, ws_xml_get_node_name_ns_prefix($self) );
  }

  /*
   * get prefix of nodes namespace
   *
   * call-seq:
   *  node.prefix -> String
   *
   */
  const char *prefix() {
    return ws_xml_get_node_name_ns_prefix($self);
  }

#if defined(SWIGRUBY)
  %rename("lang=") set_lang(const char *lang);
#endif
  /*
   * set language
   *
   * call-seq:
   *  node.lang = String
   *
   */
  void set_lang(const char *lang) {
    ws_xml_set_node_lang($self, lang);
  }

  /*
   * find node within tree
   * a NULL passed as 'ns' (namespace) is treated as wildcard
   *
   * call-seq:
   *  node.find("namespace", "name") -> String # recursive
   *  node.find("namespace", "name", 0) -> String # non-recursive
   *
   */
  WsXmlNodeH find( const char *ns, const char *name, int recursive = 1) {
    return ws_xml_find_in_tree( $self, ns, name, recursive );
  }
				 
  /*
   * iterate over siblings
   *
   * finds next sibling with same namespace and name
   *
   * See also XmlNode#each
   *
   * XmlNode#each iterates over children, XmlNode#next over siblings
   *
   * Example:
   *    <Foo>
   *      <Bar>...
   *      <Bar>...
   *      <Bar>...
   *      <Bar>...
   *      <Other>...
   *      <Other>...
   *    </Foo>
   *
   * node = root.Foo # points to <Foo> node
   *
   *   bar = node.Bar
   *   while bar do
   *     bar = bar.next
   *   end
   *
   * will give you four iterations (all <Bar> nodes)
   *
   *   child = node.Bar
   *   while child do
   *     child = child.next(1)
   *   end
   *
   * will give you six iterations (all children of <Foo>)
   * The latter example is equal to
   *
   *   node.each do |child|
   *     ...
   *   end
   *
   */
  WsXmlNodeH next(int all = 0) {
    WsXmlNodeH next_node = xml_parser_get_next_child($self);
    if (next_node && !all) {
      const char *ns_uri = ws_xml_get_node_name_ns($self);
      const char *name = ws_xml_get_node_local_name($self);
      if (ws_xml_is_node_qname(next_node, ns_uri, name) == 0) {
        next_node = NULL;
      }
    }
    return next_node;
  }
				 
  /*
   * count node children
   * if name given, count children with this name
   * if name + ns given, count children with this namespace and name
   *
   */
  int size(const char *name = NULL, const char *ns = NULL) {
    return ws_xml_get_child_count_by_qname($self, ns, name);
  }
  
  /*
   * add child (namespace, name, text) to node
   *
   */
  WsXmlNodeH add( const char *ns, const char *name, const char *text = NULL ) {
    return ws_xml_add_child( $self, ns, name, text );
  }

  /*
   * add child (namespace, name, text) before(!) node
   *
   */
  WsXmlNodeH add_before( const char *ns, const char *name, const char *text = NULL ) {
    return ws_xml_add_prev_sibling( $self, ns, name, text );
  }

#if defined(SWIGRUBY)
  %alias add "<<";
#endif
  /*
   * add node as child
   *
   */
  WsXmlNodeH add(WsXmlNodeH node) {
    ws_xml_duplicate_tree( $self, node );
    return $self;
  }
  
#if defined(SWIGRUBY)
  /*
   * iterate over children
   *
   * See also XmlNode#next
   *
   * XmlNode#each iterates over children, XmlNode#next over siblings
   *
   * can be limited to children with specific name (and specific namespace)
   *
   * for array-like constructs, e.g
   *  <Parent>
   *    <Child>..
   *    <Child>..
   *    <Child>..
   *    <OtherChild>..
   *    <OtherChild>..
   *    <OtherChild>..
   *
   *   doc.Parent.each do |child|
   *     ... iterates over all 6 children ...
   *   end
   *
   * use XmlNode#next as in
   *   node = doc.OtherChild
   *   while node do
   *     ... do something with node ...
   *    node = node.next
   *   end
   *
   * call-seq:
   *  node.each { |XmlNode| ... }
   *  node.each("name") { |XmlNode| ... }
   *  node.each("name", "namespace") { |XmlNode| ... }
   *
   */

  void each(const char *name = NULL, const char *ns = NULL) {
    int i = 0;
    WsXmlNodeH node = $self;
    int count = ws_xml_get_child_count_by_qname( node, ns, name );
    while ( i < count ) {
      rb_yield( SWIG_NewPointerObj((void*) ws_xml_get_child(node, i, ns, name), SWIGTYPE_p___WsXmlNode, 0));
      ++i;
    }
  }
#endif

#if defined(SWIGPYTHON)
  /*
   * iterate over children
   *
   */
  %pythoncode %{
    def __iter__(self):
      r = range(0,self.size())
      while r:
        yield self.get(r.pop(0))
  %}
#endif

#if defined(SWIGRUBY)
  %alias get "[]";
#endif
  /*
   * get child by index
   *
   * call-seq:
   *  node.get(42) -> XmlNode
   *  node.get(42, "name") -> XmlNode
   *  node.get(42, "name", "namespace") -> XmlNode
   *
   */
  WsXmlNodeH get(int i, const char *name = NULL, const char *ns = NULL) {
    if (i < 0 || i >= ws_xml_get_child_count_by_qname($self,ns,name))
      return NULL;
    return ws_xml_get_child($self, i, ns, name);
  }
  
  /*
   * get first child by name (and namespace)
   *
   * call-seq:
   *  node.get("name") -> XmlNode
   *  node.get("name", "namespace") -> XmlNode
   *
   */
  WsXmlNodeH get(const char *name, const char *ns = NULL) {
    return ws_xml_get_child($self, 0, ns, name);
  }

#if defined(SWIGRUBY)
  /*
   * get node attribute by index or name
   *
   * call-seq:
   *  node.attr(1) -> XmlAttr
   *  node.attr("name") -> XmlAttr
   *  node.attr("name", "namespace") -> XmlAttr
   *
   */
  WsXmlAttrH attr(VALUE index = Qnil, VALUE namespace = Qnil) {
    if (NIL_P(index)) { /* nil */
      return ws_xml_get_node_attr( $self, 0 );
    } else if (FIXNUM_P(index)) { /* numeric */
      return ws_xml_get_node_attr( $self, FIX2INT(index) );      
    } else { /* convert to string */
      const char *ns = NULL;
      const char *name = as_string(index);
      if (!NIL_P(namespace)) {
        ns = as_string(namespace);
      }
      return ws_xml_find_node_attr( $self, ns, name );
    }
  }
#else
  /* get node attribute */
  WsXmlAttrH attr(int index = 0) {
    return ws_xml_get_node_attr( $self, index );
  }
#endif
  /*
   * count node attribute
   *
   * call-seq:
   *  node.attr_count -> Integer
   *
   */
  int attr_count() {
    return ws_xml_get_node_attr_count( $self );
  }
  /*
   * find node attribute by name
   *
   * call-seq:
   *  node.attr_find("namespace", "name") -> XmlAttr
   *
   */
  WsXmlAttrH attr_find( const char *ns, const char *name ) {
    return ws_xml_find_node_attr( $self, ns, name );
  }
  /*
   * add attribute to node
   *
   * call-seq:
   *  node.attr_add("namespace", "name", "value") -> XmlAttr
   *
   */
  WsXmlAttrH attr_add( const char *ns, const char *name, const char *value ) {
    return ws_xml_add_node_attr( $self, ns, name, value );
  }
  /*
   * get end point reference
   *
   * call-seq:
   *  node.epr("namespace", "epr_node_name", Integer embedded) -> EndPointReference
   *
   */
  epr_t *epr( const char *ns, const char *epr_node_name, int embedded) {
    return epr_deserialize($self, ns, epr_node_name, embedded);
  }  


#if defined(SWIGRUBY)
  /*
   * enumerate attributes
   *
   * call-seq:
   *   node.each_attr { |XmlAttr| ... }
   *
   */
  void each_attr() {
    int i = 0;
    while ( i < ws_xml_get_node_attr_count( $self ) ) {
      rb_yield( SWIG_NewPointerObj((void*) ws_xml_get_node_attr($self, i), SWIGTYPE_p___WsXmlAttr, 0));
      ++i;
    }
  }
#endif
}


/*
 * Document-class: XmlAttr
 *
 * An XmlAttr is a key/value pair representing an attribute of a node.
 *
 * An attribute has
 * * a name (the key)
 * * a namespace (optional)
 * * a value
 *
 * There is no standalone constructor available for XmlAttr, use
 * XmlNode.add_attr() to create a new attribute.
 *
 */
 
%rename(XmlAttr) __WsXmlAttr;
%nodefault __WsXmlAttr; /* part of WsXmlNode */
struct __WsXmlAttr {}; /* without empty struct, the %rename isn't executed. */
typedef struct __WsXmlAttr* WsXmlAttrH;

%extend __WsXmlAttr {
#if defined(SWIGRUBY)
  %alias value "to_s";
#endif
  /*
   * get name for attr
   *
   * call-seq:
   *   attr.name -> String
   *
   */
  char *name() {
    return ws_xml_get_attr_name( $self );
  }
  /*
   * get namespace for attr
   *
   * call-seq:
   *   attr.ns -> String
   *
   */
  char *ns() {
    return ws_xml_get_attr_ns( $self );
  }
  /*
   * get value for attr
   *
   * call-seq:
   *   attr.value -> String
   *
   */
  char *value() {
    return ws_xml_get_attr_value( $self );
  }
  /*
   * remove note attribute
   *
   * call-seq:
   *   attr.remove -> nil
   *
   */
  void remove() {
    ws_xml_remove_node_attr( $self );
  }
}