[gxml.wiki] Update collections with examples for CollectionParent interface
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml.wiki] Update collections with examples for CollectionParent interface
- Date: Fri, 28 Feb 2020 01:08:17 +0000 (UTC)
commit adc80365ca9c4916fbfdf8338d8f6cf9d3af6394
Author: Daniel Espinosa Ortiz <esodan gmail com>
Date: Fri Feb 28 01:08:13 2020 +0000
Update collections with examples for CollectionParent interface
collections.md | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 156 insertions(+), 18 deletions(-)
---
diff --git a/collections.md b/collections.md
index 392ebe3..8fc00ef 100644
--- a/collections.md
+++ b/collections.md
@@ -4,11 +4,11 @@ GXml collections is a set of classes used to get access to `DomElement` nodes us
DOM4 provides bases API for accessing nodes, but is more like a list access, with an index and previous a
next method access.
-There are some classes to provide such collection like access to nodes in TNode derived classes, but they
are not maintained any more and will be removed.
+# GXml.Collection Interface
-# GomCollection Interface
+`BaseCollection`is an abstract class implementing `Collection` interface, and the base for different
collection implementations.
-`BaseCollection`is an abstract class implementing `GomCollection` inteface, and the base for different
collection implementations.
+> If you want to know all collections available in GXml see [BaseCollection}
(https://gnome.pages.gitlab.gnome.org/gxml/dev/GXml.BaseCollection.html)
It is designed to add `GObject` properties accessing nodes in the XML tree, arranged by its type.
@@ -17,46 +17,46 @@ Lets say you have a top most `DomElement` node called `store`, with children nod
In order to implement this you should have:
```vala
-public class Store : GomElement {
+public class Store : GXml.Element {
construct {
try { initialize ("store"); }
- catch (GLib.Error e) { warning ("Initialization error: %s".printf (e.message); }
+ catch (GLib.Error e) { warning ("Initialization error: %s", e.message); }
}
}
-public class Book : GomElement {
+public class Book : GXml.Element {
construct {
try { initialize ("book"); }
- catch (GLib.Error e) { warning ("Initialization error: %s".printf (e.message); }
+ catch (GLib.Error e) { warning ("Initialization error: %s", e.message); }
}
}
-public class News : GomElement {
+public class News : GXml.Element {
construct {
try { initialize ("news"); }
- catch (GLib.Error e) { warning ("Initialization error: %s".printf (e.message); }
+ catch (GLib.Error e) { warning ("Initialization error: %s", e.message); }
}
}
```
-Each class will take care to read store, book and news named nodes. But about if you want to access just all
book nodes or news ones. To do so use a `GomCollection`, it will take a node of a type and add a reference to
it in the DOM4 `child_nodes` collection.
+Each class will take care to read store, book and news named nodes. But what about if you want to access
just all `book` nodes or `news` ones. To do so use a `GXml.Collection`, it will take a node of a given type
and add a reference to it in the DOM4 `child_nodes` collection.
-For this example we will declare a new class derived from `GomArrayList`:
+For this example we will declare a new class derived from `GXml.ArrayList`:
```vala
-public class BookArray : GomArrayList {
+public class BookArray : GXml.ArrayList {
construct {
try { initialize (typeof (Book)); }
- catch (GLib.Error e) { warning ("Initialization error: %s".printf (e.message); }
+ catch (GLib.Error e) { warning ("Initialization error: %s", e.message); }
}
}
```
-Thats all, now add a property in `Store` to tell it you wan to keep all your book nodes in that collection:
+That is all, now add a property in `Store` to tell it you want to keep all your book nodes in that
collection:
```vala
-public class Store : GomElement {
+public class Store : GXml.Element {
public BookArray books { get; set; }
construct {
try {
@@ -66,7 +66,7 @@ public class Store : GomElement {
}
}
```
-Pay attention on `set_instance_property ("books")` it creates an instance of your collection, using current
class as its `DomElement` where its references are valid child nodes.
+Pay attention on `set_instance_property ("books")` it creates an instance of your collection, using current
class as its `DomElement` where its references are valid child nodes. If you don't initialize correctly this
property, will see errors at parsing time.
**Note** Your perperty name used in `set_instance_property`, should be canonicalized, so if your property
is called `books_for_sell`, you should use `books-for-sell` in order to initialize the correct property.
@@ -93,7 +93,145 @@ s.books.append (b);
In the above example, you create an item in the `books` collection so it is initialized with the same
`DomDocument` of the target parent.
+## Collection of different types
-## Array Collection
+`BaseCollection` requires to define just one instantiatable `GLib.Type`, so the parser can know what type to
use to create the object and set its properties. But what about a collection of objects derived from the same
type, maybe non-instantiatable like interfaces, for that you have
[GXml.CollectionParent](https://gnome.pages.gitlab.gnome.org/gxml/dev/GXml.CollectionParent.html) interface.
-`GomArrayCollection` is a collection you can use to access a set of nodes of the same time in the order they
appear in as child in the parent element node.
\ No newline at end of file
+Lets see this code:
+
+```vala
+// Base type for all items in a Store's shelf
+interface Item : GLib.Object, GXml.Object {}
+
+// A Collection you want to use to hold all this kind of objects
+class Items : GXml.ArrayList, GXml.CollectionParent {
+ construct {
+ // Used a non-instantiatable type interface 'Item'
+ try { initialize (typeof (Item)); } catch (GLib.Error e) { warning ("Error: %s", e.message); }
+ }
+ // Override supported types, adding all ones you want to add at parsing time
+ public GLib.HashTable<string,GLib.Type> types {
+ owned get {
+ var c = new GLib.HashTable<string,GLib.Type> (str_hash, str_equal);
+ GXml.CollectionParent.add_supported_types (c, items_type,
+ {
+ typeof (Monitor),
+ typeof (Keyword),
+ typeof (Cpu)
+ });
+ return c;
+ }
+ }
+}
+
+// Items classes definitions
+class Monitor : GXml.Element, Item {
+ [Description (nick="::size")]
+ public int size { get; set; }
+ construct {
+ try { initialize ("Monitor"); } catch (GLib.Error e) { warning ("Error: %s", e.message); }
+ }
+}
+class Keyword : GXml.Element, Item {
+ [Description (nick="::language")]
+ public string size { get; set; }
+ construct {
+ try { initialize ("Keyword"); } catch (GLib.Error e) { warning ("Error: %s", e.message); }
+ }
+}
+class Cpu : GXml.Element, Item {
+ [Description (nick="::language")]
+ public string size { get; set; }
+ construct {
+ try { initialize ("Cpu"); } catch (GLib.Error e) { warning ("Error: %s", e.message); }
+ }
+}
+
+// Base type for all containers, and for Store's Shelf
+abstract interface Container : GLib.Object, GXml.Object {}
+
+// This class is a Container
+class StoreShelf : GXml.Element, Container {
+ [Description (nick="::Id")]
+ public int id { get; set; default = 1; }
+ public Items items { get; set; }
+ construct {
+ try {
+ initialize ("Shelf");
+ set_instance_property ("items");
+ } catch (GLib.Error e) { warning ("Error: %s", e.message); }
+ }
+}
+
+// A Collection where to add any container found at parsing time
+class Containers : GXml.ArrayList, GXml.CollectionParent {
+ construct {
+ try { initialize (typeof (Container)); } catch (GLib.Error e) { warning ("Error: %s", e.message); }
+ }
+ // Override supported types, adding all ones you want to add at parsing time
+ public GLib.HashTable<string,GLib.Type> types {
+ owned get {
+ var c = new GLib.HashTable<string,GLib.Type> (str_hash, str_equal);
+ GXml.CollectionParent.add_supported_type (c, items_type, typeof (StoreShelf));
+ return c;
+ }
+ }
+}
+// This is the top level <ComputerStore/> node, parent for <StoreShelf/> nodes
+class ComputerStore : GXml.Element {
+ [Description (nick="::name")]
+ public string name { get; set; }
+ // Any <StoreShelf/> node will be added to this collection
+ // if you want more, just define a new class implementing 'Container' interface
+ // and modify 'Containers.types' property definition to add more types
+ public Containers containers { get; set; default = new Containers (); }
+ construct {
+ try {
+ initialize ("ComputerStore");
+ // This is necesary if you want to use your collection to hold parsed nodes
+ set_instance_property ("containers");
+ } catch (GLib.Error e) { warning ("Error: %s", e.message); }
+ }
+}
+```
+
+With above code, you can parse XML documents like:
+
+```xml
+<ComputerStore>
+ <Shelf Id="2">
+ <Cpu/>
+ <Monitor size="32"/>
+ <Keyword/>
+ </Shelf>
+</ComputerStore>
+```
+
+Above XML will be mapped to a set of `GLib.Object` classes. The top level node to `ComputerStore` class and
all its child nodes recognized by `Containers` class, will be instantiated as `GLib.Object` settings its
attributes. The same case is for the `Items` container, holding a set of objects of the type `Item`.
+
+Accessing the objects in `Containers` or `Items`, you can use the
[Collection](https://gnome.pages.gitlab.gnome.org/gxml/dev/GXml.Collection.html), then you can cast to the
required type.
+
+Lets take a close review of a collection definition:
+```vala
+// A Collection you want to use to hold all this kind of objects
+class Items : GXml.ArrayList, GXml.CollectionParent {
+ construct {
+ // Used a non-instantiatable type interface 'Item'
+ try { initialize (typeof (Item)); } catch (GLib.Error e) { warning ("Error: %s", e.message); }
+ }
+ // Override supported types, adding all ones you want to add at parsing time
+ public GLib.HashTable<string,GLib.Type> types {
+ owned get {
+ var c = new GLib.HashTable<string,GLib.Type> (str_hash, str_equal);
+ GXml.CollectionParent.add_supported_types (c, items_type,
+ {
+ typeof (Monitor),
+ typeof (Keyword),
+ typeof (Cpu)
+ });
+ return c;
+ }
+ }
+}
+```
+Any [BaseCollection](https://gnome.pages.gitlab.gnome.org/gxml/dev/GXml.BaseCollection.html) derived
implementations, can be converted to `CollectionParent` by declaring them implementing this interface, so is
easy to use any other collection type, jut need to override `CollectionParent.types` properties and add the
types you want your collection should instantiate and hold reference to.
\ No newline at end of file
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]