From 69f6220ba4c19407f13de44c09af263a16e55982 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Mon, 28 Nov 2022 22:02:04 -0500 Subject: [PATCH] Allow mutating the list of children from a derived Element Data and Field Element subclasses expect to be able to mutate the list of children on the original Element that they are derived from using parse. The way the new setChildren worked resulted in not actually mutating the original. Change this for a bindTo that makes sure all fields reference the original (and hence any mutation on the new object mutates the original) and also a replaceChildren that uses clear+addAll to ensure that the existing list is mutated rather than a new list being used. In practise, this affected room configuration and other data forms being properly filled out. --- .../java/eu/siacs/conversations/xml/Element.java | 14 ++++++++++++++ .../eu/siacs/conversations/xmpp/forms/Data.java | 5 ++--- .../eu/siacs/conversations/xmpp/forms/Field.java | 9 ++++----- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xml/Element.java b/src/main/java/eu/siacs/conversations/xml/Element.java index d70e45ef6093e330bf8d352eb8cd562ba194c102..3b5d87882b42b5c911c66ca69eda5ce00b19ab6d 100644 --- a/src/main/java/eu/siacs/conversations/xml/Element.java +++ b/src/main/java/eu/siacs/conversations/xml/Element.java @@ -134,12 +134,26 @@ public class Element implements Node { return this.children; } + // Deprecated: you probably want bindTo or replaceChildren public Element setChildren(List children) { this.childNodes = new ArrayList(children); this.children = children; return this; } + public void replaceChildren(List children) { + this.childNodes.clear(); + this.childNodes.addAll(children); + this.children.clear(); + this.children.addAll(children); + } + + public void bindTo(Element original) { + this.attributes = original.attributes; + this.childNodes = original.childNodes; + this.children = original.children; + } + public final String getContent() { return this.childNodes.stream().map(Node::getContent).filter(c -> c != null).collect(Collectors.joining()); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java b/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java index 16578967586c3f98a95074274b7950c48d6b8388..01b30a211c347b16e9b15fc75ffd125c992c2d27 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java +++ b/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java @@ -77,13 +77,12 @@ public class Data extends Element { } private void removeUnnecessaryChildren() { - setChildren(getChildren().stream().filter(element -> element.getName().equals("field") || element.getName().equals("title")).collect(Collectors.toList())); + replaceChildren(getChildren().stream().filter(element -> element.getName().equals("field") || element.getName().equals("title")).collect(Collectors.toList())); } public static Data parse(Element element) { Data data = new Data(); - data.setAttributes(element.getAttributes()); - data.setChildren(element.getChildren()); + data.bindTo(element); return data; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java b/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java index 6e97b552c70c2070434cf3bfd170343e62052a5c..f7a9eb355973330141483ff581363f3395b99279 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java +++ b/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java @@ -23,21 +23,20 @@ public class Field extends Element { } public void setValue(String value) { - setChildren(List.of(new Element("value").setContent(value))); + replaceChildren(List.of(new Element("value").setContent(value))); } public void setValues(Collection values) { - setChildren(values.stream().map(val -> new Element("value").setContent(val)).collect(Collectors.toList())); + replaceChildren(values.stream().map(val -> new Element("value").setContent(val)).collect(Collectors.toList())); } public void removeNonValueChildren() { - setChildren(getChildren().stream().filter(element -> element.getName().equals("value")).collect(Collectors.toList())); + replaceChildren(getChildren().stream().filter(element -> element.getName().equals("value")).collect(Collectors.toList())); } public static Field parse(Element element) { Field field = new Field(); - field.setAttributes(element.getAttributes()); - field.setChildren(element.getChildren()); + field.bindTo(element); return field; }