[gxml] GomElement: re-implemented attributes using GomAttr
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml] GomElement: re-implemented attributes using GomAttr
- Date: Wed, 27 Mar 2019 23:46:10 +0000 (UTC)
commit 791f27dfd245b56ffe63a5a765ee40d23f47f4ff
Author: Daniel Espinosa <esodan gmail com>
Date: Wed Mar 27 17:35:05 2019 -0600
GomElement: re-implemented attributes using GomAttr
GomAttr now can hold references and update GomObject
attributes, so object's properties are updated too,
while a list of all attributes is available
gxml/GomAttr.vala | 37 ++++++++++++++++---
gxml/GomElement.vala | 93 +++++++++++++++++++++---------------------------
gxml/GomObject.vala | 14 ++++++--
gxml/XParser.vala | 4 +--
test/GomElementTest.vala | 89 ++++++++++++++++++++++++++++++++++++---------
5 files changed, 157 insertions(+), 80 deletions(-)
---
diff --git a/gxml/GomAttr.vala b/gxml/GomAttr.vala
index bc19273..734372e 100644
--- a/gxml/GomAttr.vala
+++ b/gxml/GomAttr.vala
@@ -28,6 +28,7 @@ using Gee;
*/
public class GXml.GomAttr : GXml.GomNode, GXml.DomAttr {
protected string _namespace_uri;
+ protected GomProperty prop = null;
public string local_name { owned get { return _local_name; } }
public string name {
owned get {
@@ -43,22 +44,48 @@ public class GXml.GomAttr : GXml.GomNode, GXml.DomAttr {
return _prefix;
}
}
- public string value { owned get { return _node_value; } set { _node_value = value; } }
+ public string value {
+ owned get {
+ if (prop != null) {
+ return prop.value;
+ }
+ return _node_value;
+ }
+ set {
+ if (prop != null) {
+ prop.value = value;
+ } else {
+ _node_value = value;
+ }
+ }
+ }
+
+ public bool is_referenced { get { return prop != null; } }
construct { _child_nodes = null; }
- public GomAttr (DomElement element, string name, string value) {
+ public GomAttr (DomElement element, string name, string val) {
_document = element.owner_document;
_parent = element;
_local_name = name;
- _node_value = value;
+ _node_value = val;
+ assert (node_value == val);
+ prop = null;
}
- public GomAttr.namespace (DomElement element, string namespace_uri, string? prefix, string name, string
value) {
+ public GomAttr.namespace (DomElement element, string namespace_uri, string? prefix, string name, string
val) {
_document = element.owner_document;
_parent = element;
_local_name = name;
- _node_value = value;
+ _node_value = val;
_namespace_uri = namespace_uri;
_prefix = prefix;
+ prop = null;
+ }
+ public GomAttr.reference (DomElement element, string name) {
+ _document = element.owner_document;
+ _parent = element;
+ _local_name = name;
+ _node_value = null;
+ prop = new GomStringRef (element as GomObject, name);
}
}
diff --git a/gxml/GomElement.vala b/gxml/GomElement.vala
index 9d084c8..ec8d4a2 100644
--- a/gxml/GomElement.vala
+++ b/gxml/GomElement.vala
@@ -161,7 +161,7 @@ public class GXml.GomElement : GomNode,
foreach (string k in _attributes.keys) {
if (!("xmlns" in k)) continue;
string ns_uri = null;
- var prop = _attributes.get (k);
+ var prop = _attributes.get (k) as DomAttr;
if (prop != null) {
ns_uri = prop.value;
}
@@ -186,7 +186,7 @@ public class GXml.GomElement : GomNode,
public new string? lookup_namespace_uri (string? prefix) {
foreach (string k in attributes.keys) {
if (!("xmlns" in k)) continue;
- var p = _attributes.get (k);
+ var p = _attributes.get (k) as DomAttr;
string nsp = null;
if (p != null) {
nsp = p.value;
@@ -315,7 +315,7 @@ public class GXml.GomElement : GomNode,
var p = _attributes.get (name.down ());
if (p == null) {
GomProperty prop = new GomStringRef (this, name);
- _attributes.add (name, prop);
+ _attributes.add_reference (name);
}
}
});
@@ -370,13 +370,15 @@ public class GXml.GomElement : GomNode,
* and it's value as value. Appends namespace prefix to attribute's name as
* key if is a namespaced attribute.
*/
- public class Attributes : HashMap<string,GomProperty>, DomNamedNodeMap {
+ public class Attributes : HashMap<string,DomNode>, DomNamedNodeMap {
private TreeMap<long,string> order = new TreeMap<long,string> ();
/**
* Holds {@link GomElement} refrence to attributes' parent element.
* Derived classes should not modify, but set at construction time.
*/
protected GomElement _element;
+
+ // DomNamedNodeMap
public int length { get { return size; } }
public DomNode? item (int index) {
if (index < 0 || index >= size) return null;
@@ -384,13 +386,9 @@ public class GXml.GomElement : GomNode,
foreach (Gee.Map.Entry<long,string> e in order.ascending_entries) {
i++;
if (i == index) {
- string name = e.value;
- string v = null;
- var o = get (name);
- if (o != null) {
- v = o.value;
- }
- return new GomAttr (_element, name, v);
+ var ret = get (e.value);
+ message ("Found %s at %ld - Val=%s - as node val = %s", e.value, i, (ret as DomAttr).value,
ret.node_value);
+ return ret;
}
}
return null;
@@ -421,7 +419,7 @@ public class GXml.GomElement : GomNode,
if (p != "xmlns" && p != "xml")
ns = _element.lookup_namespace_uri (p);
}
- var prop = get (n);
+ var prop = get (n) as DomAttr;
string val = null;
if (prop != null) {
val = prop.value;
@@ -446,45 +444,42 @@ public class GXml.GomElement : GomNode,
throw new DomError.INVALID_CHARACTER_ERROR (_("Invalid attribute name: %s"), (node as
DomAttr).local_name);
if (!(node is DomAttr))
throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid node type. DomAttr was expected"));
- GomProperty prop = null;
+ GomAttr attr = null;
var pprop = (_element as GomObject).find_property_name ((node as DomAttr).local_name);
if (pprop != null) {
(_element as GomObject).set_attribute ((node as DomAttr).local_name, node.node_value);
- prop = new GomStringRef (_element, (node as DomAttr).local_name);
+ attr = new GomAttr.reference (_element, (node as DomAttr).local_name);
} else {
- prop = new GomString.with_string (node.node_value);
+ attr = new GomAttr (_element, (node as DomAttr).local_name, node.node_value);
}
- set ((node as DomAttr).local_name.down (), prop);
- order.set (size, (node as DomAttr).local_name.down ());
- return new GomAttr (_element, (node as DomAttr).local_name, node.node_value);
+ set (attr.local_name.down (), attr);
+ order.set (size - 1, (node as DomAttr).local_name.down ());
+ return attr;
}
public DomNode? remove_named_item (string name) throws GLib.Error {
if (":" in name) return null;
string val = null;
- var prop = get (name.down ());
+ var prop = get (name.down ()) as DomAttr;
if (prop != null) {
- val = prop.value;
- prop.value = null;
- }
- var n = new GomAttr (_element, name, val);
- long i = index_of (name);
- unset (name.down ());
- if (i < 0) {
- warning (_("No index found for attribute %s").printf (name));
- } else {
- order.unset (i);
+ val = prop.value;
+ prop.value = null;
+ long i = index_of (name);
+ unset (name.down ());
+ if (i < 0) {
+ warning (_("No index found for attribute %s").printf (name));
+ } else {
+ order.unset (i);
+ }
}
- return n;
+ return prop as DomNode;
}
// Introduced in DOM Level 2:
public DomNode? remove_named_item_ns (string namespace_uri, string local_name) throws GLib.Error {
if (":" in local_name) return null;
var nsp = _element.lookup_prefix (namespace_uri);
if (nsp == null || nsp == "") return null;
- var v = get ((nsp+":"+local_name).down ());
+ var v = get ((nsp+":"+local_name).down ()) as DomAttr;
if (v == null) return null;
- string val = v.value;
- var n = new GomAttr.namespace (_element, namespace_uri, nsp, local_name, val);
string k = (nsp+":"+local_name).down ();
v.value = null;
unset (k);
@@ -494,7 +489,7 @@ public class GXml.GomElement : GomNode,
} else {
order.unset (i);
}
- return n;
+ return v as DomNode;
}
// Introduced in DOM Level 2:
public DomNode? get_named_item_ns (string namespace_uri, string local_name) throws GLib.Error {
@@ -502,10 +497,7 @@ public class GXml.GomElement : GomNode,
var nsp = _element.lookup_prefix (namespace_uri);
if (nsp == null) return null;
var v = get ((nsp+":"+local_name).down ());
- if (v == null) return null;
- string val = v.value;
- var n = new GomAttr.namespace (_element, namespace_uri, nsp, local_name, val);
- return n;
+ return v;
}
// Introduced in DOM Level 2:
public DomNode? set_named_item_ns (DomNode node) throws GLib.Error {
@@ -574,22 +566,16 @@ public class GXml.GomElement : GomNode,
&& (node as DomAttr).prefix != "")
p = (node as DomAttr).prefix + ":";
string k = (p+(node as DomAttr).local_name).down ();
- GomProperty prop = null;
+ GomAttr attr = null;
var pprop = (_element as GomObject).find_property_name ((node as DomAttr).local_name);
if (pprop != null) {
(_element as GomObject).set_attribute ((node as DomAttr).local_name, node.node_value);
- prop = new GomStringRef (_element, (node as DomAttr).local_name);
+ attr = new GomAttr.reference (_element, (node as DomAttr).local_name);
} else {
- prop = new GomString.with_string (node.node_value);
+ attr = new GomAttr.namespace (_element, (node as DomAttr).namespace_uri, (node as DomAttr).prefix,
(node as DomAttr).local_name, node.node_value);
}
- set (k, prop);
- order.set (size, k);
-
- var attr = new GomAttr.namespace (_element,
- (node as DomAttr).namespace_uri,
- (node as DomAttr).prefix,
- (node as DomAttr).local_name,
- node.node_value);
+ set (k, attr);
+ order.set (size - 1, k);
return attr;
}
private long index_of (string name) {
@@ -600,15 +586,16 @@ public class GXml.GomElement : GomNode,
}
return -1;
}
- public void add (string name, GomProperty prop) {
- set (name.down (), prop);
+ public void add_reference (string name) {
+ var attr = new GomAttr.reference (_element, name);
+ set (name.down (), attr);
order.set (size, name);
}
}
public DomNamedNodeMap attributes { owned get { return (DomNamedNodeMap) _attributes; } }
public string? get_attribute (string name) {
string str = null;
- var prop = _attributes.get (name.down ());
+ var prop = _attributes.get (name.down ()) as DomAttr;
if (prop != null) {
str = prop.value;
}
@@ -626,7 +613,7 @@ public class GXml.GomElement : GomNode,
if (nsp != null)
name = nsp + ":" + local_name;
string val = null;
- var prop = _attributes.get (name);
+ var prop = _attributes.get (name) as DomAttr;
if (prop != null) {
val = prop.value;
}
diff --git a/gxml/GomObject.vala b/gxml/GomObject.vala
index 6974a64..562c30e 100644
--- a/gxml/GomObject.vala
+++ b/gxml/GomObject.vala
@@ -342,9 +342,17 @@ public interface GXml.GomObject : GLib.Object,
public virtual bool remove_attribute (string name) {
var prop = get_class ().find_property (name);
if (prop != null) {
- Value v = Value (typeof (Object));
- (this as Object).set_property (name, v);
- return true;
+ if (prop.value_type.is_a (typeof (Object))) {
+ Value v = Value (typeof (Object));
+ (this as Object).set_property (name, v);
+ return true;
+ }
+ if (prop.value_type.is_a (typeof (string))) {
+ Value v = Value (typeof (string));
+ v.set_string (null);
+ set_property (prop.name, v);
+ return true;
+ }
}
return false;
}
diff --git a/gxml/XParser.vala b/gxml/XParser.vala
index 08212af..fdb7931 100644
--- a/gxml/XParser.vala
+++ b/gxml/XParser.vala
@@ -513,11 +513,11 @@ public class GXml.XParser : Object, GXml.Parser {
// DomElement attributes
var keys = (node as DomElement).attributes.keys;
foreach (string ak in keys) {
- var prop = ((node as DomElement).attributes as HashMap<string,GomProperty>).get (ak);
+ var prop = (node as DomElement).attributes.get (ak) as GomAttr;
if (prop == null) {
continue;
}
- if (prop is GomStringRef) {
+ if (prop.is_referenced) {
continue;
}
string v = prop.value;
diff --git a/test/GomElementTest.vala b/test/GomElementTest.vala
index a7ff1fb..1678188 100644
--- a/test/GomElementTest.vala
+++ b/test/GomElementTest.vala
@@ -36,6 +36,12 @@ class ObjectParent : GomElement {
public string text { get; set; }
[Description (nick="::prop")]
public ObjectProperty prop { get; set; }
+ [Description (nick="::prop1")]
+ public ObjectProperty prop1 { get; set; }
+ [Description (nick="::prop2")]
+ public ObjectProperty prop2 { get; set; }
+ [Description (nick="::prop3")]
+ public ObjectProperty prop3 { get; set; }
public class ObjectProperty : Object, GomProperty {
public string? value { owned get; set; }
public bool validate_value (string? val) {
@@ -748,7 +754,7 @@ class GomElementTest : GXmlTest {
assert_not_reached ();
}
});
- Test.add_func ("/gxml/gom-element/object-attributes", () => {
+ Test.add_func ("/gxml/gom-element/object-attributes/attributes-collection", () => {
try {
var e = new ObjectParent ();
assert (e.text == null);
@@ -763,37 +769,42 @@ class GomElementTest : GXmlTest {
assert (e.text != null);
assert (e.prop != null);
assert (e.attributes.length == 2);
- assert (e.attributes.item (0).node_value == "value1");
- assert (e.attributes.item (1).node_value == "value_prop");
+ message ("Attr 0: %s:%s", e.attributes.item (0).node_name, e.attributes.item
(0).node_value);
+ foreach (string k in e.attributes.keys) {
+ var a = e.attributes.get (k) as DomAttr;
+ message ("Attr: %s:%s", a.name, a.@value);
+ }
+ assert ((e.attributes.item (0) as DomAttr).@value == "value1");
+ assert ((e.attributes.item (1) as DomAttr).@value == "value_prop");
e.set_attribute ("p1", "prop1");
e.set_attribute ("p2", "prop2");
e.set_attribute ("p3", "prop3");
assert (e.attributes.length == 5);
- assert (e.attributes.item (0).node_value == "value1");
- assert (e.attributes.item (1).node_value == "value_prop");
- assert (e.attributes.item (2).node_value == "prop1");
- assert (e.attributes.item (3).node_value == "prop2");
- assert (e.attributes.item (4).node_value == "prop3");
+ assert ((e.attributes.item (0) as DomAttr).@value == "value1");
+ assert ((e.attributes.item (1) as DomAttr).@value == "value_prop");
+ assert ((e.attributes.item (2) as DomAttr).@value == "prop1");
+ assert ((e.attributes.item (3) as DomAttr).@value == "prop2");
+ assert ((e.attributes.item (4) as DomAttr).@value == "prop3");
e.set_attribute_ns ("http://www.w3.org/2000/xmlns/", "xmlns:t",
"http://www.gnome.org/gxml/test");
e.set_attribute_ns ("http://www.gnome.org/gxml/test", "t:p1", "prop1_test");
e.set_attribute_ns ("http://www.gnome.org/gxml/test", "t:p2", "prop2_test");
assert (e.get_attribute_ns ("http://www.gnome.org/gxml/test", "p1") ==
"prop1_test");
assert (e.get_attribute_ns ("http://www.gnome.org/gxml/test", "p2") ==
"prop2_test");
assert (e.attributes.length == 8);
- assert (e.attributes.item (0).node_value == "value1");
- assert (e.attributes.item (1).node_value == "value_prop");
- assert (e.attributes.item (2).node_value == "prop1");
- assert (e.attributes.item (3).node_value == "prop2");
- assert (e.attributes.item (4).node_value == "prop3");
- assert (e.attributes.item (5).node_value == "http://www.gnome.org/gxml/test");
- assert (e.attributes.item (6).node_value == "prop1_test");
- assert (e.attributes.item (7).node_value == "prop2_test");
+ assert ((e.attributes.item (0) as DomAttr).@value == "value1");
+ assert ((e.attributes.item (1) as DomAttr).@value == "value_prop");
+ assert ((e.attributes.item (2) as DomAttr).@value == "prop1");
+ assert ((e.attributes.item (3) as DomAttr).@value == "prop2");
+ assert ((e.attributes.item (4) as DomAttr).@value == "prop3");
+ assert ((e.attributes.item (5) as DomAttr).@value ==
"http://www.gnome.org/gxml/test");
+ assert ((e.attributes.item (6) as DomAttr).@value == "prop1_test");
+ assert ((e.attributes.item (7) as DomAttr).@value == "prop2_test");
e.id = "di1";
assert (e.id == "di1");
assert (e.get_attribute ("id") == "di1");
assert (e.attributes.length == 9);
assert (e.attributes.item (8) != null);
- assert (e.attributes.item (8).node_value == "di1");
+ assert ((e.attributes.item (8) as DomAttr).@value == "di1");
e.child = Object.new (typeof (ObjectParent.ObjectChild),
"owner-document", e.owner_document) as ObjectParent.ObjectChild;
e.append_child (e.child);
@@ -803,6 +814,50 @@ class GomElementTest : GXmlTest {
e2.read_from_string (e.write_string ());
message (e.write_string ());
assert (e2.child != null);
+ // Check attributes collection structure
+ assert (e.attributes is DomNamedNodeMap);
+ foreach (string k in e.attributes.keys) {
+ var item = e.attributes.get (k) as DomAttr;
+ assert (item != null);
+ }
+ } catch (GLib.Error e) {
+ GLib.message ("Error: "+e.message);
+ assert_not_reached ();
+ }
+ });
+ Test.add_func ("/gxml/gom-element/object-attributes/attributes-update", () => {
+ try {
+ var e = new ObjectParent ();
+ e.id = "id1";
+ assert (e.get_attribute ("id") == "id1");
+ e.set_attribute ("id", "id2");
+ assert (e.get_attribute ("id") == "id2");
+ assert (e.id == "id2");
+ assert ((e.attributes.item (0) as DomAttr).value == "id2");
+ e.set_attribute ("prop", "val_prop");
+ assert (e.prop != null);
+ assert (e.prop is ObjectParent.ObjectProperty);
+ assert (e.prop.value == "val_prop");
+ assert (e.get_attribute ("prop") == "val_prop");
+ assert ((e.attributes.item (1) as DomAttr).value == "val_prop");
+ e.set_attribute ("prop1", "val_prop1");
+ assert (e.prop1 != null);
+ assert (e.prop1 is ObjectParent.ObjectProperty);
+ assert (e.prop1.value == "val_prop1");
+ assert (e.get_attribute ("prop1") == "val_prop1");
+ assert ((e.attributes.item (2) as DomAttr).value == "val_prop1");
+ e.set_attribute ("prop2", "val_prop2");
+ assert (e.prop2 != null);
+ assert (e.prop2 is ObjectParent.ObjectProperty);
+ assert (e.prop2.value == "val_prop2");
+ assert (e.get_attribute ("prop2") == "val_prop2");
+ assert ((e.attributes.item (3) as DomAttr).value == "val_prop2");
+ e.set_attribute ("prop3", "val_prop3");
+ assert (e.prop3 != null);
+ assert (e.prop3 is ObjectParent.ObjectProperty);
+ assert (e.prop3.value == "val_prop3");
+ assert (e.get_attribute ("prop3") == "val_prop3");
+ assert ((e.attributes.item (4) as DomAttr).value == "val_prop3");
} catch (GLib.Error e) {
GLib.message ("Error: "+e.message);
assert_not_reached ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]