[gxml] GomElement: Object properties now are included in attributes
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml] GomElement: Object properties now are included in attributes
- Date: Wed, 20 Mar 2019 16:53:08 +0000 (UTC)
commit 5995bb232690327453a733f241a2591858939b37
Author: Daniel Espinosa <esodan gmail com>
Date: Tue Mar 19 17:42:19 2019 -0600
GomElement: Object properties now are included in attributes
Fix https://gitlab.gnome.org/GNOME/gxml/issues/19
gxml/GomElement.vala | 105 +++++++++++++++++++++++++++++++++++------------
gxml/GomObject.vala | 23 +++++++++++
gxml/GomProperty.vala | 3 ++
gxml/GomStringRef.vala | 39 ++++++++++++++++++
gxml/meson.build | 1 +
test/GomElementTest.vala | 28 +++++++++++++
6 files changed, 173 insertions(+), 26 deletions(-)
---
diff --git a/gxml/GomElement.vala b/gxml/GomElement.vala
index 367db46..5c91216 100644
--- a/gxml/GomElement.vala
+++ b/gxml/GomElement.vala
@@ -164,7 +164,11 @@ public class GXml.GomElement : GomNode,
return _prefix;
foreach (string k in _attributes.keys) {
if (!("xmlns" in k)) continue;
- string ns_uri = _attributes.get (k);
+ string ns_uri = null;
+ var prop = _attributes.get (k);
+ if (prop != null) {
+ ns_uri = prop.value;
+ }
if (ns_uri == null) {
GLib.warning (_("Invalid namespace URI stored in element's attribute"));
return null;
@@ -186,7 +190,11 @@ public class GXml.GomElement : GomNode,
public new string? lookup_namespace_uri (string? prefix) {
foreach (string k in attributes.keys) {
if (!("xmlns" in k)) continue;
- string nsp = _attributes.get (k);
+ var p = _attributes.get (k);
+ string nsp = null;
+ if (p != null) {
+ nsp = p.value;
+ }
if (prefix == null && k == "xmlns") return nsp;
if (":" in k) {
string[] sa = k.split (":");
@@ -351,13 +359,12 @@ public class GXml.GomElement : GomNode,
_namespace_uri = namespace_uri;
_prefix = prefix;
}
-
/**
* Holds attributes in current node, using attribute's name as key
* and it's value as value. Appends namespace prefix to attribute's name as
- * key if a namespaced attribute.
+ * key if is a namespaced attribute.
*/
- public class Attributes : HashMap<string,string>, DomNamedNodeMap {
+ public class Attributes : HashMap<string,GomProperty>, DomNamedNodeMap {
private TreeMap<long,string> order = new TreeMap<long,string> ();
/**
* Holds {@link GomElement} refrence to attributes' parent element.
@@ -372,7 +379,11 @@ public class GXml.GomElement : GomNode,
i++;
if (i == index) {
string name = e.value;
- string v = get (name);
+ string v = null;
+ var o = get (name);
+ if (o != null) {
+ v = o.value;
+ }
return new GomAttr (_element, name, v);
}
}
@@ -404,7 +415,11 @@ public class GXml.GomElement : GomNode,
if (p != "xmlns" && p != "xml")
ns = _element.lookup_namespace_uri (p);
}
- string val = get (name);
+ var prop = get (name);
+ string val = null;
+ if (prop != null) {
+ val = prop.value;
+ }
if (val == null) return null;
DomNode attr = null;
if (p == null || p == "")
@@ -425,15 +440,27 @@ 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"));
- set ((node as DomAttr).local_name, node.node_value);
+ GomProperty prop = 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);
+ } else {
+ prop = new GomString.with_string (node.node_value);
+ }
+ set ((node as DomAttr).local_name, prop);
order.set (size, (node as DomAttr).local_name);
return new GomAttr (_element, (node as DomAttr).local_name, node.node_value);
}
public DomNode? remove_named_item (string name) throws GLib.Error {
if (":" in name) return null;
- var v = get (name);
- if (v == null) return null;
- var n = new GomAttr (_element, name, v);
+ string val = null;
+ var prop = get (name);
+ if (prop != null) {
+ val = prop.value;
+ prop.value = null;
+ }
+ var n = new GomAttr (_element, name, val);
unset (name);
long i = index_of (name);
if (i < 0) {
@@ -450,8 +477,10 @@ public class GXml.GomElement : GomNode,
if (nsp == null || nsp == "") return null;
var v = get (nsp+":"+local_name);
if (v == null) return null;
- var n = new GomAttr.namespace (_element, namespace_uri, nsp, local_name, v);
+ string val = v.value;
+ var n = new GomAttr.namespace (_element, namespace_uri, nsp, local_name, val);
string k = nsp+":"+local_name;
+ v.value = null;
unset (k);
long i = index_of (k);
if (i < 0) {
@@ -468,7 +497,8 @@ public class GXml.GomElement : GomNode,
if (nsp == null) return null;
var v = get (nsp+":"+local_name);
if (v == null) return null;
- var n = new GomAttr.namespace (_element, namespace_uri, nsp, local_name, v);
+ string val = v.value;
+ var n = new GomAttr.namespace (_element, namespace_uri, nsp, local_name, val);
return n;
}
// Introduced in DOM Level 2:
@@ -538,7 +568,15 @@ public class GXml.GomElement : GomNode,
&& (node as DomAttr).prefix != "")
p = (node as DomAttr).prefix + ":";
string k = p+(node as DomAttr).local_name;
- set (k, node.node_value);
+ GomProperty prop = 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);
+ } else {
+ prop = new GomString.with_string (node.node_value);
+ }
+ set (k, prop);
order.set (size, k);
var attr = new GomAttr.namespace (_element,
@@ -559,9 +597,12 @@ public class GXml.GomElement : GomNode,
}
public DomNamedNodeMap attributes { owned get { return (DomNamedNodeMap) _attributes; } }
public string? get_attribute (string name) {
- string s = (this as GomObject).get_attribute (name);
- if (s != null) return s;
- return _attributes.get (name);
+ string str = null;
+ var prop = _attributes.get (name);
+ if (prop != null) {
+ str = prop.value;
+ }
+ return str;
}
public string? get_attribute_ns (string? namespace_uri, string local_name) {
string nsp = null;
@@ -574,16 +615,20 @@ public class GXml.GomElement : GomNode,
string name = local_name;
if (nsp != null)
name = nsp + ":" + local_name;
- return _attributes.get (name);
+ string val = null;
+ var prop = _attributes.get (name);
+ if (prop != null) {
+ val = prop.value;
+ }
+ return val;
}
public void set_attribute (string name, string value) throws GLib.Error {
- bool res = (this as GomObject).set_attribute (name, value);
- if (res) return;
var a = new GomAttr (this, name, value);
attributes.set_named_item (a);
}
public void set_attribute_ns (string? namespace_uri,
- string name, string value) throws GLib.Error {
+ string name, string value) throws GLib.Error
+ {
string p = "";
string n = name;
if (":" in name) {
@@ -594,8 +639,9 @@ public class GXml.GomElement : GomNode,
n = s[1];
if (":" in n)
throw new DomError.NAMESPACE_ERROR (_("Invalid attribute name. Invalid use of colon: %s"), n);
- } else
+ } else {
n = name;
+ }
if (namespace_uri == null && p == "")
throw new DomError.NAMESPACE_ERROR (_("Invalid namespace. If prefix is null, namespace URI should not
be null"));
if (p == "xml" && namespace_uri != "http://www.w3.org/2000/xmlns/" && namespace_uri !=
"http://www.w3.org/2000/xmlns")
@@ -616,7 +662,6 @@ public class GXml.GomElement : GomNode,
}
}
public void remove_attribute (string name) {
- if ((this as GomObject).remove_attribute (name)) return;
try { attributes.remove_named_item (name); }
catch (GLib.Error e)
{ warning (_("Removing attribute Error: ")+e.message); }
@@ -630,9 +675,17 @@ public class GXml.GomElement : GomNode,
return _attributes.has_key (name);
}
public bool has_attribute_ns (string? namespace_uri, string local_name) {
- var p = lookup_prefix (namespace_uri);
- if (p == null) return false;
- return attributes.has_key (p+":"+local_name);
+ string nsp = null;
+ if ((namespace_uri == "http://www.w3.org/2000/xmlns/"
+ || namespace_uri == "http://www.w3.org/2000/xmlns")
+ && local_name != "xmlns")
+ nsp = "xmlns";
+ else
+ nsp = lookup_prefix (namespace_uri);
+ string name = local_name;
+ if (nsp != null)
+ name = nsp + ":" + local_name;
+ return attributes.has_key (name);
}
diff --git a/gxml/GomObject.vala b/gxml/GomObject.vala
index dcfe3de..4247e89 100644
--- a/gxml/GomObject.vala
+++ b/gxml/GomObject.vala
@@ -188,6 +188,29 @@ public interface GXml.GomObject : GLib.Object,
if (prop == null) return null;
return get_property_string (prop);
}
+ /**
+ * Search for a property of type {@link GomProperty}
+ * and returns it as object
+ */
+ public virtual GomProperty? find_property (string name) {
+ var prop = find_property_name (name);
+ if (prop != null) {
+ var v = Value (prop.value_type);
+ if (prop.value_type.is_a (typeof(GomProperty))
+ && prop.value_type.is_instantiatable ()) {
+ get_property (prop.name, ref v);
+ GomProperty so = (Object) v as GomProperty;
+ if (so == null) {
+ var obj = Object.new (prop.value_type);
+ v.set_object (obj);
+ set_property (prop.name, v);
+ so = obj as GomProperty;
+ }
+ return so;
+ }
+ }
+ return null;
+ }
/**
* Search for a {@link GLib.Object} property with
* given name, if found, given string representation
diff --git a/gxml/GomProperty.vala b/gxml/GomProperty.vala
index b999391..ccd1bd9 100644
--- a/gxml/GomProperty.vala
+++ b/gxml/GomProperty.vala
@@ -70,6 +70,9 @@ public class GXml.GomString : GomBaseProperty {
_value = value;
}
}
+ public GomString.with_string (string str) {
+ _value = str;
+ }
}
/**
diff --git a/gxml/GomStringRef.vala b/gxml/GomStringRef.vala
new file mode 100644
index 0000000..d890de4
--- /dev/null
+++ b/gxml/GomStringRef.vala
@@ -0,0 +1,39 @@
+/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
+/*
+ * AttributeStringRef.vala
+ *
+ * Copyright (C) 2019 Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Daniel Espinosa <esodan gmail com>
+ */
+public class GXml.GomStringRef : Object, GomProperty {
+ GomObject object;
+ string name;
+ public string? value {
+ owned get {
+ return object.get_attribute (name);
+ }
+ set {
+ object.set_attribute (name, value);
+ }
+ }
+ public bool validate_value (string val) { return true; }
+ public GomStringRef (GomObject obj, string name) {
+ object = obj;
+ this.name = name;
+ }
+}
diff --git a/gxml/meson.build b/gxml/meson.build
index cd16e8d..e59d8a1 100644
--- a/gxml/meson.build
+++ b/gxml/meson.build
@@ -69,6 +69,7 @@ valasources = files ([
'GomObject.vala',
'GomProperty.vala',
'GomSchema.vala',
+ 'GomStringRef.vala',
'GomText.vala',
'GXmlAttribute.vala',
'GXmlCDATA.vala',
diff --git a/test/GomElementTest.vala b/test/GomElementTest.vala
index 355962e..58a1e55 100644
--- a/test/GomElementTest.vala
+++ b/test/GomElementTest.vala
@@ -746,6 +746,8 @@ class GomElementTest : GXmlTest {
var e = new ObjectParent ();
assert (e.text == null);
assert (e.prop == null);
+ assert (e.attributes != null);
+ assert (e.attributes.length == 0);
e.set_attribute ("text", "value1");
assert (e.get_attribute ("text") == "value1");
e.set_attribute ("prop", "value_prop");
@@ -753,6 +755,32 @@ class GomElementTest : GXmlTest {
assert (e.get_attribute ("prop") == "value_prop");
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");
+ 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");
+ 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");
} 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]