]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/DEVEL/pxp/pxp/doc/manual/html/x1439.html
Initial revision
[helm.git] / helm / DEVEL / pxp / pxp / doc / manual / html / x1439.html
diff --git a/helm/DEVEL/pxp/pxp/doc/manual/html/x1439.html b/helm/DEVEL/pxp/pxp/doc/manual/html/x1439.html
new file mode 100644 (file)
index 0000000..2677305
--- /dev/null
@@ -0,0 +1,464 @@
+<HTML
+><HEAD
+><TITLE
+>The class type extension</TITLE
+><META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.46"><LINK
+REL="HOME"
+TITLE="The PXP user's guide"
+HREF="index.html"><LINK
+REL="UP"
+TITLE="The objects representing the document"
+HREF="c893.html"><LINK
+REL="PREVIOUS"
+TITLE="The class type node"
+HREF="x939.html"><LINK
+REL="NEXT"
+TITLE="Details of the mapping from XML text to the tree representation"
+HREF="x1496.html"><LINK
+REL="STYLESHEET"
+TYPE="text/css"
+HREF="markup.css"></HEAD
+><BODY
+CLASS="SECT1"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><DIV
+CLASS="NAVHEADER"
+><TABLE
+WIDTH="100%"
+BORDER="0"
+CELLPADDING="0"
+CELLSPACING="0"
+><TR
+><TH
+COLSPAN="3"
+ALIGN="center"
+>The PXP user's guide</TH
+></TR
+><TR
+><TD
+WIDTH="10%"
+ALIGN="left"
+VALIGN="bottom"
+><A
+HREF="x939.html"
+>Prev</A
+></TD
+><TD
+WIDTH="80%"
+ALIGN="center"
+VALIGN="bottom"
+>Chapter 3. The objects representing the document</TD
+><TD
+WIDTH="10%"
+ALIGN="right"
+VALIGN="bottom"
+><A
+HREF="x1496.html"
+>Next</A
+></TD
+></TR
+></TABLE
+><HR
+ALIGN="LEFT"
+WIDTH="100%"></DIV
+><DIV
+CLASS="SECT1"
+><H1
+CLASS="SECT1"
+><A
+NAME="AEN1439"
+>3.3. The class type <TT
+CLASS="LITERAL"
+>extension</TT
+></A
+></H1
+><P
+>&#13;<PRE
+CLASS="PROGRAMLISTING"
+>class type [ 'node ] extension =
+  object ('self)
+    method clone : 'self
+      (* "clone" should return an exact deep copy of the object. *)
+    method node : 'node
+      (* "node" returns the corresponding node of this extension. This method
+       * intended to return exactly what previously has been set by "set_node".
+       *)
+    method set_node : 'node -&#62; unit
+      (* "set_node" is invoked once the extension is associated to a new
+       * node object.
+       *)
+  end</PRE
+>
+
+This is the type of classes used for node extensions. For every node of the
+document tree, there is not only the <TT
+CLASS="LITERAL"
+>node</TT
+> object, but also
+an <TT
+CLASS="LITERAL"
+>extension</TT
+> object. The latter has minimal
+functionality; it has only the necessary methods to be attached to the node
+object containing the details of the node instance. The extension object is
+called extension because its purpose is extensibility.</P
+><P
+>For some reasons, it is impossible to derive the
+<TT
+CLASS="LITERAL"
+>node</TT
+> classes (i.e. <TT
+CLASS="LITERAL"
+>element_impl</TT
+> and
+<TT
+CLASS="LITERAL"
+>data_impl</TT
+>) such that the subclasses can be extended by new
+new methods. But
+subclassing nodes is a great feature, because it allows the user to provide
+different classes for different types of nodes. The extension objects are a
+workaround that is as powerful as direct subclassing, the costs are
+some notation overhead.</P
+><DIV
+CLASS="FIGURE"
+><A
+NAME="EXTENSION-GENERAL"
+></A
+><P
+><B
+>Figure 3-6. The structure of nodes and extensions</B
+></P
+><P
+><IMG
+SRC="pic/extension_general.gif"></P
+></DIV
+><P
+>The picture shows how the nodes and extensions are linked
+together. Every node has a reference to its extension, and every extension has
+a reference to its node. The methods <TT
+CLASS="LITERAL"
+>extension</TT
+> and
+<TT
+CLASS="LITERAL"
+>node</TT
+> follow these references; a typical phrase is 
+
+<PRE
+CLASS="PROGRAMLISTING"
+>self # node # attribute "xy"</PRE
+>
+
+to get the value of an attribute from a method defined in the extension object;
+or 
+
+<PRE
+CLASS="PROGRAMLISTING"
+>self # node # iter
+  (fun n -&gt; n # extension # my_method ...)</PRE
+>
+
+to iterate over the subnodes and to call <TT
+CLASS="LITERAL"
+>my_method</TT
+> of the
+corresponding extension objects.</P
+><P
+>Note that extension objects do not have references to subnodes
+(or "subextensions") themselves; in order to get one of the children of an
+extension you must first go to the node object, then get the child node, and
+finally reach the extension that is logically the child of the extension you
+started with.</P
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN1460"
+>3.3.1. How to define an extension class</A
+></H2
+><P
+>At minimum, you must define the methods
+<TT
+CLASS="LITERAL"
+>clone</TT
+>, <TT
+CLASS="LITERAL"
+>node</TT
+>, and
+<TT
+CLASS="LITERAL"
+>set_node</TT
+> such that your class is compatible with the type
+<TT
+CLASS="LITERAL"
+>extension</TT
+>. The method <TT
+CLASS="LITERAL"
+>set_node</TT
+> is called
+during the initialization of the node, or after a node has been cloned; the
+node object invokes <TT
+CLASS="LITERAL"
+>set_node</TT
+> on the extension object to tell
+it that this node is now the object the extension is linked to. The extension
+must return the node object passed as argument of <TT
+CLASS="LITERAL"
+>set_node</TT
+>
+when the <TT
+CLASS="LITERAL"
+>node</TT
+> method is called.</P
+><P
+>The <TT
+CLASS="LITERAL"
+>clone</TT
+> method must return a copy of the
+extension object; at least the object itself must be duplicated, but if
+required, the copy should deeply duplicate all objects and values that are
+referred by the extension, too. Whether this is required, depends on the
+application; <TT
+CLASS="LITERAL"
+>clone</TT
+> is invoked by the node object when one of
+its cloning methods is called.</P
+><P
+>A good starting point for an extension class:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class custom_extension =
+  object (self)
+
+    val mutable node = (None : custom_extension node option)
+
+    method clone = {&#60; &#62;} 
+
+    method node =
+      match node with
+          None -&#62;
+            assert false
+        | Some n -&#62; n
+
+    method set_node n =
+      node &#60;- Some n
+
+  end</PRE
+>
+
+This class is compatible with <TT
+CLASS="LITERAL"
+>extension</TT
+>. The purpose of
+defining such a class is, of course, adding further methods; and you can do it
+without restriction. </P
+><P
+>Often, you want not only one extension class. In this case,
+it is the simplest way that all your classes (for one kind of document) have
+the same type (with respect to the interface; i.e. it does not matter if your
+classes differ in the defined private methods and instance variables, but
+public methods count). This approach avoids lots of coercions and problems with
+type incompatibilities. It is simple to implement:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class custom_extension =
+  object (self)
+    val mutable node = (None : custom_extension node option)
+
+    method clone = ...      (* see above *)
+    method node = ...       (* see above *)
+    method set_node n = ... (* see above *)
+
+    method virtual my_method1 : ...
+    method virtual my_method2 : ...
+    ... (* etc. *)
+  end
+
+class custom_extension_kind_A =
+  object (self)
+    inherit custom_extension
+
+    method my_method1 = ...
+    method my_method2 = ...
+  end
+
+class custom_extension_kind_B =
+  object (self)
+    inherit custom_extension
+
+    method my_method1 = ...
+    method my_method2 = ...
+  end</PRE
+>
+
+If a class does not need a method (e.g. because it does not make sense, or it
+would violate some important condition), it is possible to define the method
+and to always raise an exception when the method is invoked
+(e.g. <TT
+CLASS="LITERAL"
+>assert false</TT
+>).</P
+><P
+>The latter is a strong recommendation: do not try to further
+specialize the types of extension objects. It is difficult, sometimes even
+impossible, and almost never worth-while.</P
+></DIV
+><DIV
+CLASS="SECT2"
+><H2
+CLASS="SECT2"
+><A
+NAME="AEN1481"
+>3.3.2. How to bind extension classes to element types</A
+></H2
+><P
+>Once you have defined your extension classes, you can bind them
+to element types. The simplest case is that you have only one class and that
+this class is to be always used. The parsing functions in the module
+<TT
+CLASS="LITERAL"
+>Pxp_yacc</TT
+> take a <TT
+CLASS="LITERAL"
+>spec</TT
+> argument which
+can be customized. If your single class has the name <TT
+CLASS="LITERAL"
+>c</TT
+>,
+this argument should be 
+
+<PRE
+CLASS="PROGRAMLISTING"
+>let spec =
+  make_spec_from_alist
+    ~data_exemplar:            (new data_impl c)
+    ~default_element_exemplar: (new element_impl c)
+    ~element_alist:            []
+    ()</PRE
+>
+
+This means that data nodes will be created from the exemplar passed by
+~data_exemplar and that all element nodes will be made from the exemplar
+specified by ~default_element_exemplar. In ~element_alist, you can 
+pass that different exemplars are to be used for different element types; but
+this is an optional feature. If you do not need it, pass the empty list.</P
+><P
+>Remember that an exemplar is a (node, extension) pair that serves as pattern
+when new nodes (and the corresponding extension objects) are added to the
+document tree. In this case, the exemplar contains <TT
+CLASS="LITERAL"
+>c</TT
+> as
+extension, and when nodes are created, the exemplar is cloned, and cloning
+makes also a copy of <TT
+CLASS="LITERAL"
+>c</TT
+> such that all nodes of the document
+tree will have a copy of <TT
+CLASS="LITERAL"
+>c</TT
+> as extension.</P
+><P
+>The <TT
+CLASS="LITERAL"
+>~element_alist</TT
+> argument can bind
+specific element types to specific exemplars; as exemplars may be instances of
+different classes it is effectively possible to bind element types to
+classes. For example, if the element type "p" is implemented by class "c_p",
+and "q" is realized by "c_q", you can pass the following value:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>let spec =
+  make_spec_from_alist
+    ~data_exemplar:            (new data_impl c)
+    ~default_element_exemplar: (new element_impl c)
+    ~element_alist:            
+      [ "p", new element_impl c_p;
+        "q", new element_impl c_q;
+      ]
+    ()</PRE
+>
+
+The extension object <TT
+CLASS="LITERAL"
+>c</TT
+> is still used for all data nodes and
+for all other element types.</P
+></DIV
+></DIV
+><DIV
+CLASS="NAVFOOTER"
+><HR
+ALIGN="LEFT"
+WIDTH="100%"><TABLE
+WIDTH="100%"
+BORDER="0"
+CELLPADDING="0"
+CELLSPACING="0"
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+><A
+HREF="x939.html"
+>Prev</A
+></TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="index.html"
+>Home</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+><A
+HREF="x1496.html"
+>Next</A
+></TD
+></TR
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+>The class type <TT
+CLASS="LITERAL"
+>node</TT
+></TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="c893.html"
+>Up</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+>Details of the mapping from XML text to the tree representation</TD
+></TR
+></TABLE
+></DIV
+></BODY
+></HTML
+>
\ No newline at end of file