/*
 NAME
	pxmltree.h - protocols for XML classes
 VERSION
	$Id$
 CHANGELOG
	$Log$
 DESCRIPTION
 	These protocols are strongly depend on the interface of libxml2 
	library. If the other system must be supported by these protocol,
	all of the interface must be re-design.

 */

#if !defined(PXMLTREE_H_INCLUDED)
#define PXMLTREE_H_INCLUDED

#include <coconut/pstream.h>
#include <coconut/pstring.h>
#include <coconut/perror.h>

@protocol PXMLNode <PDebug>

 - (boolean) isElementNode ;
 - (boolean) isTextNode ;
   /* if the node is text node and it contains only spaces, return TRUE */
 - (boolean) isEmptyTextNode ;

 - (boolean) hasChildren ;
 - (boolean) hasAttrName: (const utf8_char *) name ;

 - (const utf8_char *) tagName ;
 - (int) type ;

   /* if the content string is not found, this method returns nil */
 - (id <PConstStr>) content ;
 - (selection_t) selection ;
 - (u_int) lineno ;
 - (id <PXMLNode>) rootNode ;

 - setTagName: (const utf8_char *) name ;
 - setContent: (const utf8_char *) content ;
 - setContent: (const utf8_char *) content length:(u_int) len ;
 - addContent: (const utf8_char *) content ;
 - addContent: (const utf8_char *) content length:(u_int) len ;

 - removeContentHeadSpaces ;
 - removeContentTailSpaces ;
 - removeContentSideSpaces ;

 - setSelection: (selection_t) sel ;
 - setUndetermined ;
 - setRejected ;
 - setAccepted ;

 - chooseTagNameByStr: (const utf8_char *) name ;
 - chooseTagNameByRegExp: (id <PRegExp>) regexp ;
 - chooseAttrNameByStr: (const utf8_char *) name ;
 - chooseAttrNameByRegExp: (id <PRegExp>) regexp ;

 - setAttr: (const utf8_char *) name value: (const utf8_char *) value ;
   /* if the attr name "name" is already set, change the value to "value" */
 - unsetAttr: (const utf8_char *) name ;
 - changeAttr: (const utf8_char *) name value: (const utf8_char *) value ;
 - removeAttrByRegExp: (id <PRegExp>) nameexp value: (id <PRegExp>) valexp ;

   /* if the attribute name is not found, return nil. */
 - (id <PConstStr>) getAttrValueByName: (const utf8_char *) attrname ;
 - (id <PConstStr>) getChildText ;

   /* if the attribute is exist, return TRUE */
 - (boolean) setFirstAttr ;
 - (const utf8_char *) attrName ;
 - (int) compareAttrName: (const utf8_char *) attrname ;
   /* if the attribute name is not found, return nil. */
 - (id <PConstStr>) getAttrValue ;
 - (boolean) moveNextAttr ;

   /* return next, prev, ... node */
 - (id <PXMLNode>) next ;
 - (id <PXMLNode>) prev ;
 - (id <PXMLNode>) child ;
 - (id <PXMLNode>) lastChild ;
 - (id <PXMLNode>) parent ;

 - (id <PXMLNode>) firstSibling ;
 - (id <PXMLNode>) lastSibling ;

   /* add the new node to the previous/next of the current node.
      WARNING: if the current node and new node are text node,
               they will be merged. */
 - addNextSibling: (id <PXMLNode>) node ;
 - addPrevSibling: (id <PXMLNode>) node ;

 - appendChild: (id <PXMLNode>) node ;
 - appendChildList: (id <PXMLNode>) node ;

 - prependChild: (id <PXMLNode>) node ;
 - prependChildList: (id <PXMLNode>) node ;

 - (int) compareTagName: (const utf8_char *) name ;

 - (id <PXMLNode>) duplicate ;
   /* duplicate self and following siblings */
 - (id <PXMLNode>) duplicateWithSiblings ;

 - unlink ;

 - foreach: (id) dstobj message: (SEL) message with: p1 ;
 - foreachCondition: (condition_func_t) func obj: (id) dstobj 
     message: (SEL) message with: p1 ;
 - foreachObject: (SEL) message with: p1 with: p2 ;
 - foreachConditionObject: (condition_func_t) func message: (SEL) message
     with: p1 with: p2 ;

   /* trace and search the child node whose tag name is "tagname". The
      argument "level" means the search depth. For example, when the "level"
      is 1, the direct child (not children's child) is searched.
      if you give -1 as "level", there are no limitation. */
 - (id <PXMLNode>) searchChildByTagName: (const utf8_char *) tagname 
     level: (int) level ;

 - (const utf8_char *) searchNameSpacePrefixByHref: (const utf8_char *) href ;

 - printTagName: (id <PStream>) stream withDepth: (id) withdepth ;
   /* the content of param:
        param->ptr_value == (id <PRegExp>) regexp for attrname
	param->bool_value1 == (boolean) do print attr name
	param->bool_value2 == (boolean) do print attr value */
 - printMatchedAttr: (id <PStream>) stream param: (param_pb2_t *) param ;

   /* CAUTION: do not use this one. except cxmlnode.m */
 - (struct _xmlNode *) getNodePtr ;

   /* CAUTION: do not use this one. except fxml.m */
 - resetNodePtr: (void *) p ;
@end

@protocol PXMLTree <PBuffer>

 /* document options */
   /* return value: 0 .. not compressed, ..., 9 most compressed */
 - setCompressMode: (int) mode ;
 - (int) compressMode ;

 - (id <PXMLNode>) currentNode ;
 - (id <PXMLNode>) rootNode ;
 - (u_int) count ;
 - clear ;

   /* before calling these methods, you must call "newDocument" or 
      "load" method. */

   /* the current node is changed to the new node */
 - (id <PXMLNode>) addRootNode: (const utf8_char *) name 
      content: (const utf8_char *) content ;
 - (id <PXMLNode>) addNextNode: (const utf8_char *) name 
      content: (const utf8_char *) content ;
 - (id <PXMLNode>) addPrevNode: (const utf8_char *) name 
      content: (const utf8_char *) content ;

   /* the current node is NOT changed to the new node */
 - (id <PXMLNode>) appendNode: (const utf8_char *) name
      content: (const utf8_char *) content ;
 - (id <PXMLNode>) prependNode: (const utf8_char *) name 
      content: (const utf8_char *) content ;
 - (id <PXMLNode>) appendChildNode: (const utf8_char *) name 
      content: (const utf8_char *) content ;

 /* text nodes for blanks */
 - addNewline ;
 - appendNewline ;

 - (id <PError>) removeNode ;

 - moveToHead ;
 - moveToTail ;
 - moveToRoot ;

   /* if the next, previous node has found, move there and return TRUE */
 - (id <PXMLNode>) moveNext ;
 - (id <PXMLNode>) movePrev ;

 - (id <PXMLNode>) moveToChild ;
 - (id <PXMLNode>) moveToParent ;

   /* move to the child and move next until the element node is found. 
      if the element node is not found, the current node is not changed
      and return FALSE. */
 - (id <PXMLNode>) skipToChild ;

   /* move next/prev until the element node is found. 
      if the element node is not found, the current node is not changed
      and return FALSE. */
 - (id <PXMLNode>) skipNext ;
 - (id <PXMLNode>) skipPrev ;

 - foreach_count: p1 with: p2 ;

   /* ok. I know this is not beautiful */
 - (struct _xmlDoc *) peekDocPtr ;
@end

@protocol PXMLFactory <PObject>
 + doExpandEntity: (boolean) flag ;
 + doValidCheck: (boolean) flag ;
 + setErrorHandler: (id <PStream>) stream ;

 + (const utf8_char *) nodeType2Str: (int) type ;

 + (u_int) nodeDepth: (id <PXMLNode>) node ;

 + pretty: (id <PXMLNode>) node indent: (const utf8_char *) sp ;

   /* search the tag node which named "name". if the "follower" is true,
      the next node of the "node" will be searched.
      the "depth" means the search depth, if you pass "-1" as depth,
      all subtree are searched. */
 + (id <PXMLNode>) searchNodeByName: (const utf8_char *) name 
     from: (id <PXMLNode>) node depth: (int) dep follower: (boolean) follower ;

 + removeFirstEmptyTextChildren: (id <PXMLNode>) parent ;
 + removeLastEmptyTextChildren: (id <PXMLNode>) parent ;

   /* remove empty text (spaces) from all of the "fromnode" and it's children */
 + removeEmptyTextChildren: (id <PXMLNode>) fromnode ;

 + errorByNode: (id <PXMLNode>) node file: (const char *) name
     format: (const char *) form, ... ;

@end

#endif /* PXMLTREE_H_INCLUDED */

