[gxml] Added utilities for one element properties child
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml] Added utilities for one element properties child
- Date: Tue, 21 Feb 2017 18:34:10 +0000 (UTC)
commit 24384905961d1b8f63645f7aff74857b73db1a7a
Author: Daniel Espinosa <esodan gmail com>
Date: Tue Feb 21 10:08:06 2017 -0600
Added utilities for one element properties child
New GomObject.clean_property_elements() to search and remove redundant
nodes of requested property.
New GomObject.find_elements() to search and return a list of all child
elements of same type.
Added documentation on how to define properties removing redundant
child nodes.
gxml/GomObject.vala | 85 ++++++++++++++++++++++++++++++-----
gxml/GomProperty.vala | 2 +-
test/GomSerializationTest.vala | 95 ++++++++++++++++++++++++++++++++++++----
3 files changed, 160 insertions(+), 22 deletions(-)
---
diff --git a/gxml/GomObject.vala b/gxml/GomObject.vala
index f2586fd..a31bdd9 100644
--- a/gxml/GomObject.vala
+++ b/gxml/GomObject.vala
@@ -283,7 +283,7 @@ public interface GXml.GomObject : GLib.Object,
public virtual DomElement? get_child (string name) {
var prop = get_class ().find_property (name);
if (prop != null) {
- if (prop.value_type == typeof(DomElement)) {
+ if (prop.value_type.is_a (typeof(DomElement))) {
var vo = Value(prop.value_type);
get_property (prop.name, ref vo);
return (DomElement) ((Object) vo);
@@ -297,19 +297,31 @@ public interface GXml.GomObject : GLib.Object,
return null;
}
/**
+ * From a given property name of type {@link GomElement}, search all
+ * child nodes with node's local name equal to property.
+ */
+ public virtual DomElementList find_elements (string name) {
+ var l = new DomElementList ();
+ var prop = get_class ().find_property (name);
+ if (prop != null) {
+ if (prop.value_type.is_a (typeof(DomElement))) {
+ var o = Object.new (prop.value_type) as DomElement;
+ foreach (DomNode n in this.child_nodes) {
+ if (!(n is DomElement)) continue;
+ if ((n as DomElement).local_name.down () == o.local_name.down ())
+ l.add (n as DomElement);
+ }
+ }
+ }
+ return l;
+ }
+ /**
* Search for a property and set it to null if possible returning true,
* if value can't be removed or located, returns false without change.
*/
public virtual bool remove_attribute (string name) {
var prop = get_class ().find_property (name);
if (prop != null) {
- if (prop.value_type.is_a (typeof (SerializableProperty))) {
- (this as SerializableProperty).set_serializable_property_value (null);
- return true;
- }
- if (prop.value_type.is_a (typeof (SerializableCollection))) {
- return true;
- }
Value v = Value (typeof (Object));
(this as Object).set_property (name, v);
return true;
@@ -317,9 +329,9 @@ public interface GXml.GomObject : GLib.Object,
return false;
}
/**
- * Convenient method to create an instance of given property's
+ * Convenient method to set an instance of given property's
* name and initialize according to have same {@link DomNode.owner_document}
- * and set its {@link DomNode.parent_node} to this.
+ * and set its {@link DomNode.parent_node} to this appending it as a child.
* If property is a {@link GomCollection} it is initialize to use
* this as its {@link GomCollection.element}.
*
@@ -347,7 +359,7 @@ public interface GXml.GomObject : GLib.Object,
*
* Returns: true if property has been set and initialized, false otherwise.
*/
- public bool create_instance_property (string name) {
+ public virtual bool set_instance_property (string name) {
var prop = find_object_property_name (name);
if (prop == null) return false;
Value v = Value (prop.value_type);
@@ -359,7 +371,7 @@ public interface GXml.GomObject : GLib.Object,
return true;
}
if (prop.value_type.is_a (typeof (GomElement))) {
- obj = Object.new (prop.value_type,"owner_document", this.owner_document);
+ obj = Object.new (prop.value_type,"owner-document", this.owner_document);
try { this.append_child (obj as GomElement); }
catch (GLib.Error e) {
warning (_("Error while attempting to instantiate property object: %s").printf (e.message));
@@ -371,4 +383,53 @@ public interface GXml.GomObject : GLib.Object,
}
return false;
}
+ /**
+ * Utility method to remove all instances of a property being child elements
+ * of object. Is useful if you have a {@link GomElement} property, it should be
+ * just one child of this type and you want to overwrite it.
+ *
+ * In this example you have defined an element MyClass to be child of
+ * MyParentClass, but it should have just one element, once you set child_elements
+ * it calls {@link clean_property_elements} using property's canonicals name.
+ *
+ * {{{
+ * public class MyClass : GomElement {
+ * public string name { get; set; }
+ * }
+ * public class MyParentClass : GomElement {
+ * private Myclass _child_elements = null;
+ * public MyClass child_elements {
+ * get { return _child_elements; }
+ * set {
+ * try {
+ * clean_property_elements ("child-elements");
+ * _child_elements = value;
+ * append_child (_child_elements);
+ * } catch (GLib.Error e) {
+ * warning (e.message);
+ * }
+ * }
+ * }
+ * }
+ * }}}
+ *
+ * @param name property name to search value type, use canonical names.
+ *
+ * @throws DomError if property is not a {@link GomElement}.
+ */
+ public virtual
+ void clean_property_elements (string name) throws GLib.Error
+ {
+ var prop = get_class ().find_property (name);
+ if (prop != null) {
+ if (!prop.value_type.is_a (typeof (GomElement)))
+ throw new DomError.TYPE_MISMATCH_ERROR (_("Can't set value. It is not a GXmlGomElement type"));
+ var l = find_elements (name);
+ if (l.length != 0) {
+ foreach (DomElement e in l) {
+ e.remove ();
+ }
+ }
+ }
+ }
}
diff --git a/gxml/GomProperty.vala b/gxml/GomProperty.vala
index 329c3c3..6cdea51 100644
--- a/gxml/GomProperty.vala
+++ b/gxml/GomProperty.vala
@@ -422,7 +422,7 @@ public class GXml.GomDateTime : GomBaseProperty {
return _value.format (s);
}
set {
- var tv = new TimeVal ();
+ var tv = TimeVal ();
if (tv.from_iso8601 (value)) {
_value = new DateTime.from_timeval_local (tv);
} else
diff --git a/test/GomSerializationTest.vala b/test/GomSerializationTest.vala
index 3671b8f..5e12e60 100644
--- a/test/GomSerializationTest.vala
+++ b/test/GomSerializationTest.vala
@@ -210,10 +210,23 @@ class GomSerializationTest : GXmlTest {
FEBRUARY
}
}
- public class BookRegister : GomElement {
+ public class BookRegister : GomElement, MappeableElement {
+ private Book _book = null;
[Description (nick="::Year")]
public int year { get; set; }
- public Book book { get; set; }
+ public Book book {
+ get { return _book; }
+ set {
+ try {
+ clean_property_elements ("book");
+ _book = value;
+ append_child (_book);
+ } catch (GLib.Error e) {
+ warning (e.message);
+ assert_not_reached ();
+ }
+ }
+ }
construct {
try { initialize ("BookRegister"); }
catch { assert_not_reached (); }
@@ -221,6 +234,15 @@ class GomSerializationTest : GXmlTest {
public BookRegister.document (DomDocument doc) {
_document = doc;
}
+ public string get_map_key () {
+ return "%d".printf (year)+"-"+book.name;
+ }
+ public Book create_book (string name) {
+ return Object.new (typeof (Book),
+ "owner-document", this.owner_document,
+ "name", name)
+ as Book;
+ }
public string to_string () {
var parser = new XParser (this);
string s = "";
@@ -234,6 +256,7 @@ class GomSerializationTest : GXmlTest {
}
}
public class BookStand : GomElement {
+ HashRegisters _hashmap_registers = null;
[Description (nick="::Classification")]
public string classification { get; set; default = "Science"; }
public Dimension dimension_x { get; set; }
@@ -242,10 +265,26 @@ class GomSerializationTest : GXmlTest {
[Description (nick="DimensionZ")]
public DimensionZ dimension_z { get; set; }
public Registers registers { get; set; }
+ public HashRegisters hashmap_registers {
+ get {
+ if (_hashmap_registers == null)
+ _hashmap_registers = Object.new (typeof (HashRegisters),"element",this)
+ as HashRegisters;
+ return _hashmap_registers;
+ }
+ set {
+ _hashmap_registers = value;
+ }
+ }
public Books books { get; set; }
construct {
try { initialize ("BookStand"); } catch { assert_not_reached (); }
}
+ public BookRegister create_register () {
+ return Object.new (typeof (BookRegister),
+ "element", this)
+ as BookRegister;
+ }
public string to_string () {
var parser = new XParser (this);
string s = "";
@@ -284,6 +323,12 @@ class GomSerializationTest : GXmlTest {
catch { assert_not_reached (); }
}
}
+ public class HashRegisters : GomHashMap {
+ construct {
+ try { initialize (typeof (BookRegister)); }
+ catch { assert_not_reached (); }
+ }
+ }
public class Books : GomHashMap {
construct {
try { initialize_with_key (typeof (Book), "Name"); }
@@ -530,7 +575,7 @@ class GomSerializationTest : GXmlTest {
assert ("<BookStand Classification=\"Science\"/>" in s);
assert (bs.owner_document != null);
assert (bs.registers == null);
- assert (bs.create_instance_property ("registers"));
+ assert (bs.set_instance_property ("registers"));
s = bs.to_string ();
assert (s != null);
#if DEBUG
@@ -567,7 +612,7 @@ class GomSerializationTest : GXmlTest {
assert ((bs.registers.get_item (0) as BookRegister).year == 2016);
assert ((bs.registers.get_item (1) as BookRegister).year == 2010);
assert ((bs.registers.get_item (2) as BookRegister).year == 2000);
- assert (bs.create_instance_property("Dimension-X"));
+ assert (bs.set_instance_property("Dimension-X"));
assert (bs.dimension_x != null);
assert (bs.dimension_x.length == 1.0);
s = bs.to_string ();
@@ -576,7 +621,7 @@ class GomSerializationTest : GXmlTest {
GLib.message ("DOC:"+s);
//#endif
assert ("<BookStand Classification=\"Science\"><BookRegister Year=\"2016\"/><BookRegister
Year=\"2010\"/><Test/><BookRegister Year=\"2000\"/><Dimension Length=\"1\" Type=\"x\"/></BookStand>" in s);
- assert (bs.create_instance_property("DimensionY"));
+ assert (bs.set_instance_property("DimensionY"));
assert (bs.dimension_y != null);
assert (bs.dimension_y.length == 1.0);
s = bs.to_string ();
@@ -585,7 +630,7 @@ class GomSerializationTest : GXmlTest {
GLib.message ("DOC:"+s);
//#endif
assert ("<BookStand Classification=\"Science\"><BookRegister Year=\"2016\"/><BookRegister
Year=\"2010\"/><Test/><BookRegister Year=\"2000\"/><Dimension Length=\"1\" Type=\"x\"/><Dimension
Length=\"1\" Type=\"y\"/></BookStand>" in s);
- assert (bs.create_instance_property("::DimensionZ"));
+ assert (bs.set_instance_property("::DimensionZ"));
assert (bs.dimension_z != null);
assert (bs.dimension_z.length == 1.0);
s = bs.to_string ();
@@ -609,7 +654,7 @@ class GomSerializationTest : GXmlTest {
#endif
assert ("<BookStore/>" in s);
assert (bs.books == null);
- bs.create_instance_property ("books");
+ bs.set_instance_property ("books");
s = bs.to_string ();
assert (s != null);
#if DEBUG
@@ -654,6 +699,33 @@ class GomSerializationTest : GXmlTest {
assert_not_reached ();
}
});
+ Test.add_func ("/gxml/gom-serialization/mappeable", () => {
+ try {
+ var bs = new BookStand ();
+ assert (bs.hashmap_registers != null);
+ var br = bs.hashmap_registers.create_item () as BookRegister;
+ var book = br.create_book ("Book1");
+ br.book = book;
+ br.year = 2017;
+ bs.hashmap_registers.append (br);
+ assert (bs.hashmap_registers.length == 1);
+ assert (bs.hashmap_registers.has_key ("2017-Book1"));
+ var b1 = bs.hashmap_registers.get ("2017-Book1") as BookRegister;
+ assert (b1 != null);
+ assert (b1.year == 2017);
+ assert (b1.book != null);
+ assert (b1.book.name == "Book1");
+ assert (b1.child_nodes.length == 1);
+ var book2 = b1.create_book ("Book2");
+ b1.append_child (book2);
+ assert (b1.child_nodes.length == 2);
+ b1.book = book2;
+ assert (b1.child_nodes.length == 1);
+ } catch (GLib.Error e) {
+ GLib.message ("Error: "+e.message);
+ assert_not_reached ();
+ }
+ });
Test.add_func ("/gxml/gom-serialization/write/gom-property", () => {
try {
var m = new Motor ();
@@ -779,6 +851,7 @@ class GomSerializationTest : GXmlTest {
}
});
Test.add_func ("/gxml/gom-serialization/read/bad-node-name", () => {
+ try {
var b = new Book ();
b.read_from_string ("<chair name=\"Tall\"/>");
#if DEBUG
@@ -789,6 +862,10 @@ class GomSerializationTest : GXmlTest {
assert (b.child_nodes.size == 0);
assert (b.owner_document.document_element != null);
assert (b.owner_document.document_element.node_name == "Book");
+ } catch (GLib.Error e) {
+ GLib.message ("Error: "+e.message);
+ assert_not_reached ();
+ }
});
Test.add_func ("/gxml/gom-serialization/read/object-property", () => {
try {
@@ -800,9 +877,9 @@ class GomSerializationTest : GXmlTest {
assert ("<BookRegister Year=\"0\"/>" in s);
b.read_from_string ("<bookRegister><Book/></bookRegister>");
s = b.to_string ();
-#if DEBUG
+//#if DEBUG
GLib.message ("doc:"+s);
-#endif
+//#endif
assert ("<BookRegister Year=\"0\"><Book/></BookRegister>" in s);
} catch (GLib.Error e) {
GLib.message ("Error: "+e.message);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]