diff options
author | Gurmeen Bindra <gurmeen.bindra@isode.com> | 2012-04-17 09:29:05 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2012-04-19 10:45:53 (GMT) |
commit | d9d9451156ee8a4315de30571131d114af205fa1 (patch) | |
tree | 24d0dfb36be867651c39ff6898c944ed035e7f5b /src/com | |
parent | b54bc5406f95902ce2438ac64a19390ae0f2f409 (diff) | |
download | stroke-d9d9451156ee8a4315de30571131d114af205fa1.zip stroke-d9d9451156ee8a4315de30571131d114af205fa1.tar.bz2 |
Port MUC Payload Parsers from Swiften to Stroke
This patch ports the MUC Payload parsers from swiften to stroke.
Test-information:
ported junits work fine
Diffstat (limited to 'src/com')
13 files changed, 707 insertions, 3 deletions
diff --git a/src/com/isode/stroke/parser/GenericPayloadTreeParser.java b/src/com/isode/stroke/parser/GenericPayloadTreeParser.java new file mode 100644 index 0000000..e414ac5 --- /dev/null +++ b/src/com/isode/stroke/parser/GenericPayloadTreeParser.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser; + +import java.util.LinkedList; + +import com.isode.stroke.elements.Payload; +import com.isode.stroke.parser.tree.ParserElement; + +/** + * Generic parser offering something a bit like a DOM to work with + * @param <T> Payload Type to parse + */ +public abstract class GenericPayloadTreeParser<T extends Payload> extends GenericPayloadParser<T> { + + private LinkedList<ParserElement> elementStack_ = new LinkedList<ParserElement>(); + private ParserElement root_; + + /** + * Create the parser for the given payload type + * @param payload payload type object, not null + */ + public GenericPayloadTreeParser(T payload) { + super(payload); + } + + @Override + public void handleCharacterData(String data) { + ParserElement current = elementStack_.getLast(); + current.appendCharacterData(data); + } + + @Override + public void handleEndElement(String element, String xmlns) { + elementStack_.removeLast(); + if (elementStack_.isEmpty()) { + handleTree(root_); + } + } + + @Override + public void handleStartElement(String element, String xmlns, + AttributeMap attributes) { + if (root_ == null) { + root_ = new ParserElement(element, xmlns, attributes); + elementStack_.addLast(root_); + }else { + ParserElement current = elementStack_.getLast(); + elementStack_.addLast(current.addChild(element, xmlns, attributes)); + } + } + + /** + * Parse children of the root element. Subclasses should implement + * this method to extract the items from child nodes + * @param root root of the node whose children contains items + */ + public abstract void handleTree(ParserElement root); +} diff --git a/src/com/isode/stroke/parser/payloadparsers/FullPayloadParserFactoryCollection.java b/src/com/isode/stroke/parser/payloadparsers/FullPayloadParserFactoryCollection.java index 6b67116..1abce76 100644 --- a/src/com/isode/stroke/parser/payloadparsers/FullPayloadParserFactoryCollection.java +++ b/src/com/isode/stroke/parser/payloadparsers/FullPayloadParserFactoryCollection.java @@ -46,9 +46,18 @@ public class FullPayloadParserFactoryCollection extends PayloadParserFactoryColl //addFactory(new PrivateStorageParserFactory(this)); //addFactory(new ChatStateParserFactory()); //addFactory(new DelayParserFactory()); - //addFactory(new MUCUserPayloadParserFactory()); - //addFactory(new NicknameParserFactory()); - + addFactory(new MUCUserPayloadParserFactory(this)); + addFactory(new MUCOwnerPayloadParserFactory(this)); + addFactory(new GenericPayloadParserFactory<MUCInvitationPayloadParser>("x", + "jabber:x:conference",MUCInvitationPayloadParser.class)); + addFactory(new GenericPayloadParserFactory<MUCAdminPayloadParser>("query", + "http://jabber.org/protocol/muc#admin",MUCAdminPayloadParser.class)); + addFactory(new GenericPayloadParserFactory<MUCDestroyPayloadParser>("destroy", + "http://jabber.org/protocol/muc#user",MUCDestroyPayloadParser.class)); + addFactory(new GenericPayloadParserFactory<MUCDestroyPayloadParser>("destroy", + "http://jabber.org/protocol/muc#owner",MUCDestroyPayloadParser.class)); + + //addFactory(new NicknameParserFactory()); PayloadParserFactory defaultFactory = new RawXMLPayloadParserFactory(); setDefaultFactory(defaultFactory); diff --git a/src/com/isode/stroke/parser/payloadparsers/MUCAdminPayloadParser.java b/src/com/isode/stroke/parser/payloadparsers/MUCAdminPayloadParser.java new file mode 100644 index 0000000..3c3dfb3 --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/MUCAdminPayloadParser.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.elements.MUCAdminPayload; +import com.isode.stroke.elements.MUCItem; +import com.isode.stroke.parser.GenericPayloadTreeParser; +import com.isode.stroke.parser.tree.ParserElement; + +/** + * Class representing a parser for MUC Admin payload + * + */ +public class MUCAdminPayloadParser extends GenericPayloadTreeParser<MUCAdminPayload>{ + + /** + * Create the parser + */ + public MUCAdminPayloadParser() { + super(new MUCAdminPayload()); + } + + @Override + public void handleTree(ParserElement root) { + for (ParserElement itemElement : root.getChildren("item", "http://jabber.org/protocol/muc#admin")) { + MUCItem item = MUCItemParser.itemFromTree(itemElement); + getPayloadInternal().addItem(item); + } + } +} diff --git a/src/com/isode/stroke/parser/payloadparsers/MUCDestroyPayloadParser.java b/src/com/isode/stroke/parser/payloadparsers/MUCDestroyPayloadParser.java new file mode 100644 index 0000000..f6b7790 --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/MUCDestroyPayloadParser.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.elements.MUCDestroyPayload; +import com.isode.stroke.jid.JID; +import com.isode.stroke.parser.GenericPayloadTreeParser; +import com.isode.stroke.parser.tree.ParserElement; + +/** + * Class representing a parser for MUC Destroy payload + * + */ +public class MUCDestroyPayloadParser extends GenericPayloadTreeParser<MUCDestroyPayload> { + + /** + * Create the parser + */ + public MUCDestroyPayloadParser() { + super(new MUCDestroyPayload()); + } + + @Override + public void handleTree(ParserElement root) { + String ns = root.getNamespace(); + String jid = root.getAttributes().getAttribute("jid"); + if (jid != null && !jid.isEmpty()) { + getPayloadInternal().setNewVenue(new JID(jid)); + } + getPayloadInternal().setReason(root.getChild("reason", ns).getText()); + } +} diff --git a/src/com/isode/stroke/parser/payloadparsers/MUCInvitationPayloadParser.java b/src/com/isode/stroke/parser/payloadparsers/MUCInvitationPayloadParser.java new file mode 100644 index 0000000..27ab0d8 --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/MUCInvitationPayloadParser.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.elements.MUCInvitationPayload; +import com.isode.stroke.jid.JID; +import com.isode.stroke.parser.GenericPayloadTreeParser; +import com.isode.stroke.parser.tree.ParserElement; + +/** + * Class representing a parser for MUC Invitation payload + * + */ +public class MUCInvitationPayloadParser extends GenericPayloadTreeParser<MUCInvitationPayload> { + + public MUCInvitationPayloadParser() { + super(new MUCInvitationPayload()); + } + + @Override + public void handleTree(ParserElement root) { + MUCInvitationPayload invite = getPayloadInternal(); + invite.setIsContinuation(root.getAttributes().getBoolAttribute("continue", false)); + invite.setJID(new JID(root.getAttributes().getAttribute("jid"))); + invite.setPassword(root.getAttributes().getAttribute("password")); + invite.setReason(root.getAttributes().getAttribute("reason")); + invite.setThread(root.getAttributes().getAttribute("thread")); + } +} diff --git a/src/com/isode/stroke/parser/payloadparsers/MUCItemParser.java b/src/com/isode/stroke/parser/payloadparsers/MUCItemParser.java new file mode 100644 index 0000000..1a1bb74 --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/MUCItemParser.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.elements.MUCItem; +import com.isode.stroke.elements.MUCOccupant.Affiliation; +import com.isode.stroke.elements.MUCOccupant.Role; +import com.isode.stroke.jid.JID; +import com.isode.stroke.parser.tree.ParserElement; + +/** + * Class containing parser functions for MUC Item + * + */ +public class MUCItemParser { + + /** + * Get the MUC Item from the node + * @param root XML node element + * @return MUC Item, not null + */ + public static MUCItem itemFromTree(ParserElement root) { + MUCItem item = new MUCItem(); + String affiliation = root.getAttributes().getAttribute("affiliation"); + String role = root.getAttributes().getAttribute("role"); + String nick = root.getAttributes().getAttribute("nick"); + String jid = root.getAttributes().getAttribute("jid"); + item.affiliation = parseAffiliation(affiliation); + item.role = parseRole(role); + if (!jid.isEmpty()) { + item.realJID = new JID(jid); + } + if (!nick.isEmpty()) { + item.nick = nick; + } + String xmlns = root.getNamespace(); + String reason = root.getChild("reason", xmlns).getText(); + String actor = root.getChild("actor", xmlns).getAttributes().getAttribute("jid"); + if (!reason.isEmpty()) { + item.reason = reason; + } + if (!actor.isEmpty()) { + item.actor = new JID(actor); + } + + return item; + } + + private static Role parseRole(String val) { + for(Role role : Role.values()) { + if(role.nodeName.equals(val)) { + return role; + } + } + return null; + } + + private static Affiliation parseAffiliation(String val) { + for(Affiliation aff : Affiliation.values()) { + if(aff.nodeName.equals(val)) { + return aff; + } + } + return null; + } +} diff --git a/src/com/isode/stroke/parser/payloadparsers/MUCOwnerPayloadParser.java b/src/com/isode/stroke/parser/payloadparsers/MUCOwnerPayloadParser.java new file mode 100644 index 0000000..dd5e186 --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/MUCOwnerPayloadParser.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.elements.MUCOwnerPayload; +import com.isode.stroke.parser.AttributeMap; +import com.isode.stroke.parser.GenericPayloadParser; +import com.isode.stroke.parser.PayloadParser; +import com.isode.stroke.parser.PayloadParserFactory; +import com.isode.stroke.parser.PayloadParserFactoryCollection; + + +/** + * Class representing a parser for MUC Owner payload + * + */ +public class MUCOwnerPayloadParser extends GenericPayloadParser<MUCOwnerPayload> { + private PayloadParserFactoryCollection factories_; + private int level; + private PayloadParser currentPayloadParser; + + /** + * Create the parser + * @param factories payload parser factory collection, not null + */ + public MUCOwnerPayloadParser(PayloadParserFactoryCollection factories) { + super(new MUCOwnerPayload()); + this.factories_ = factories; + level = 0; + } + + @Override + public void handleStartElement(String element, String ns, AttributeMap attributes) { + if (level == 1) { + PayloadParserFactory payloadParserFactory = factories_.getPayloadParserFactory( + element, ns, attributes); + if (payloadParserFactory != null) { + currentPayloadParser = payloadParserFactory.createPayloadParser(); + } + } + + if (level >= 1 && currentPayloadParser != null) { + currentPayloadParser.handleStartElement(element, ns, attributes); + } + ++level; + } + + @Override + public void handleEndElement(String element, String ns) { + --level; + if (currentPayloadParser != null) { + if (level >= 1) { + currentPayloadParser.handleEndElement(element, ns); + } + + if (level == 1) { + getPayloadInternal().setPayload(currentPayloadParser.getPayload()); + } + } + } + + @Override + public void handleCharacterData(String data) { + if (level > 1 && currentPayloadParser != null) { + currentPayloadParser.handleCharacterData(data); + } + } +} diff --git a/src/com/isode/stroke/parser/payloadparsers/MUCOwnerPayloadParserFactory.java b/src/com/isode/stroke/parser/payloadparsers/MUCOwnerPayloadParserFactory.java new file mode 100644 index 0000000..6d016d9 --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/MUCOwnerPayloadParserFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.parser.AttributeMap; +import com.isode.stroke.parser.PayloadParser; +import com.isode.stroke.parser.PayloadParserFactory; +import com.isode.stroke.parser.PayloadParserFactoryCollection; + +/** + * Factory for MUC Owner Payload Parser + * + */ +public class MUCOwnerPayloadParserFactory implements PayloadParserFactory { + + private PayloadParserFactoryCollection factories; + + /** + * Create the MUC Owner Payload Parser factory + * @param factories reference to Payload Parser Factory Collection, not null + */ + public MUCOwnerPayloadParserFactory(PayloadParserFactoryCollection factories) { + this.factories = factories; + } + + @Override + public boolean canParse(String element, String ns, AttributeMap map) { + return "query".equals(element) && "http://jabber.org/protocol/muc#owner".equals(ns); + } + + @Override + public PayloadParser createPayloadParser() { + return new MUCOwnerPayloadParser(factories); + } +} diff --git a/src/com/isode/stroke/parser/payloadparsers/MUCUserPayloadParser.java b/src/com/isode/stroke/parser/payloadparsers/MUCUserPayloadParser.java new file mode 100644 index 0000000..170e935 --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/MUCUserPayloadParser.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2010, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.elements.MUCItem; +import com.isode.stroke.elements.MUCUserPayload; +import com.isode.stroke.jid.JID; +import com.isode.stroke.parser.GenericPayloadTreeParser; +import com.isode.stroke.parser.PayloadParserFactoryCollection; +import com.isode.stroke.parser.tree.ParserElement; +import com.isode.stroke.parser.tree.TreeReparser; + +/** + * Class representing a parser for MUC User payload + * + */ +public class MUCUserPayloadParser extends GenericPayloadTreeParser<MUCUserPayload> { + + private PayloadParserFactoryCollection factories; + + /** + * Create the parser + * @param collection reference to payload parser factory collection, not null + */ + public MUCUserPayloadParser(PayloadParserFactoryCollection collection){ + super(new MUCUserPayload()); + this.factories = collection; + } + + @Override + public void handleTree(ParserElement root) { + for (ParserElement child : root.getAllChildren()) { + if ("item".equals(child.getName()) && child.getNamespace().equals(root.getNamespace())) { + MUCItem item = MUCItemParser.itemFromTree(child); + getPayloadInternal().addItem(item); + } else if ("password".equals(child.getName()) && child.getNamespace().equals(root.getNamespace())) { + getPayloadInternal().setPassword(child.getText()); + } else if ("invite".equals(child.getName()) && child.getNamespace().equals(root.getNamespace())) { + MUCUserPayload.Invite invite = new MUCUserPayload.Invite(); + String to = child.getAttributes().getAttribute("to"); + if (to != null && !to.isEmpty()) { + invite.to = JID.fromString(to); + } + String from = child.getAttributes().getAttribute("from"); + if (from != null && !from.isEmpty()) { + invite.from = JID.fromString(from); + } + ParserElement reason = child.getChild("reason", root.getNamespace()); + if (reason != null) { + invite.reason = reason.getText(); + } + getPayloadInternal().setInvite(invite); + } else if ("status".equals(child.getName()) && child.getNamespace().equals(root.getNamespace())) { + MUCUserPayload.StatusCode status = new MUCUserPayload.StatusCode(); + try { + status.code = Integer.parseInt(child.getAttributes().getAttribute("code")); + getPayloadInternal().addStatusCode(status); + }catch (NumberFormatException e) { + } + } else { + getPayloadInternal().setPayload(TreeReparser.parseTree(child, factories)); + } + } + } +} diff --git a/src/com/isode/stroke/parser/payloadparsers/MUCUserPayloadParserFactory.java b/src/com/isode/stroke/parser/payloadparsers/MUCUserPayloadParserFactory.java new file mode 100644 index 0000000..0712eea --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/MUCUserPayloadParserFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.parser.AttributeMap; +import com.isode.stroke.parser.PayloadParser; +import com.isode.stroke.parser.PayloadParserFactory; +import com.isode.stroke.parser.PayloadParserFactoryCollection; + +/** + * Factory for MUC User Payload Parser + * + */ +public class MUCUserPayloadParserFactory implements PayloadParserFactory { + + private PayloadParserFactoryCollection factories; + + /** + * Create the MUC User Payload Parser factory + * @param factories reference to Payload Parser Factory Collection, not null + */ + public MUCUserPayloadParserFactory(PayloadParserFactoryCollection factories) { + this.factories = factories; + } + + @Override + public boolean canParse(String element, String ns, AttributeMap map) { + return "x".equals(element) && "http://jabber.org/protocol/muc#user".equals(ns); + } + + @Override + public PayloadParser createPayloadParser() { + return new MUCUserPayloadParser(factories); + } +} diff --git a/src/com/isode/stroke/parser/tree/NullParserElement.java b/src/com/isode/stroke/parser/tree/NullParserElement.java new file mode 100644 index 0000000..83f8b6f --- /dev/null +++ b/src/com/isode/stroke/parser/tree/NullParserElement.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.tree; + +import com.isode.stroke.parser.AttributeMap; + +/** + * Class representing a Null Parser element + * + */ +public class NullParserElement extends ParserElement{ + /** + * Create the object + */ + public NullParserElement() { + super("", "", new AttributeMap()); + } + + /** + * Empty/Null Parser element + */ + public static NullParserElement element = new NullParserElement(); +} diff --git a/src/com/isode/stroke/parser/tree/ParserElement.java b/src/com/isode/stroke/parser/tree/ParserElement.java new file mode 100644 index 0000000..1a43696 --- /dev/null +++ b/src/com/isode/stroke/parser/tree/ParserElement.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.tree; + +import java.util.Vector; +import com.isode.stroke.parser.AttributeMap; + +/** + * Class representing a parser for nodes in the stanza + * + */ +public class ParserElement { + private Vector<ParserElement> children_ = new Vector<ParserElement>(); + private String name_ = ""; + private String xmlns_ =""; + private AttributeMap attributes_ = new AttributeMap(); + private String text_ = ""; + + /** + * Create the parser. + * @param name name of the parser node, e.g. query, reason, not null + * @param xmlns XML namespace, e.g. http://jabber.org/protocol/muc#user, not null + * @param attributes attributes of the node, not null + */ + public ParserElement(String name, String xmlns, AttributeMap attributes){ + this.name_ = name; + this.xmlns_ = xmlns; + this.attributes_ = attributes; + } + + /** + * Get the text data of the node + * @return not null, can be empty + */ + public String getText() { + return text_; + } + + /** + * Get the name of the node, not null + * @return name of node + */ + public String getName() { + return name_; + } + + /** + * Get the name space of the XML node, not null + * @return xml namespace + */ + public String getNamespace() { + return xmlns_; + } + + /** + * Get the attributes of the XML node + * @return XMP node attributes, not null + */ + public AttributeMap getAttributes() { + return attributes_; + } + + /** + * Add child of the XML node + * @param name name of child node, not null + * @param xmlns XML namespace, not null + * @param attributes attributes, not null + * @return child node, not null + */ + public ParserElement addChild(String name, String xmlns, AttributeMap attributes){ + ParserElement child = new ParserElement(name, xmlns, attributes); + children_.add(child); + return child; + } + + /** + * Append data to the text of the node + * @param data data to be appended, not null + */ + public void appendCharacterData(String data) { + text_ += data; + } + + /** + * Get the children of the node which have the given name + * and namespace value + * @param name name of node, not null + * @param xmlns namespace of node, not null + * @return list of children, not null but can be empty + */ + public Vector<ParserElement> getChildren(String name, String xmlns) { + Vector<ParserElement> result = new Vector<ParserElement>(); + for(ParserElement child : children_) { + if(child.name_.equals(name) && child.xmlns_.equals(xmlns)) { + result.add(child); + } + } + return result; + } + + /** + * Get all the child nodes of XML element + * @return list of all children, not null but can be empty + */ + public Vector<ParserElement> getAllChildren() { + return children_; + } + + /** + * Get the first child of the node which have the given name + * and namespace value + * @param name name of node, not null + * @param xmlns namespace of node, not null + * @return child node if exists or a parser element {@link NullParserElement} + * representing null value + */ + public ParserElement getChild(String name, String xmlns) { + Vector<ParserElement> results = getChildren(name, xmlns); + ParserElement result = results.isEmpty() ? NullParserElement.element : results.get(0); + return result; + } +} diff --git a/src/com/isode/stroke/parser/tree/TreeReparser.java b/src/com/isode/stroke/parser/tree/TreeReparser.java new file mode 100644 index 0000000..647ab9e --- /dev/null +++ b/src/com/isode/stroke/parser/tree/TreeReparser.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2011, Kevin Smith + * All rights reserved. + */ +package com.isode.stroke.parser.tree; + +import java.util.LinkedList; + +import com.isode.stroke.elements.Payload; +import com.isode.stroke.parser.PayloadParser; +import com.isode.stroke.parser.PayloadParserFactoryCollection; + +/** + * Class for parsing elements of a parser element + * + */ +public class TreeReparser { + /** + * Class representing an element and its handling state + * + */ + private static class ElementState { + ParserElement pe; + boolean state; + public ElementState(ParserElement pe, boolean state) { + super(); + this.pe = pe; + this.state = state; + } + } + + /** + * Parse the elements under the given root node + * @param root root node, not null + * @param collection payload parser factories, not null + * @return payload created from the elements of the given node, not null + */ + public static Payload parseTree(ParserElement root, PayloadParserFactoryCollection collection) { + PayloadParser parser = collection.getPayloadParserFactory(root.getName(), root.getNamespace(), + root.getAttributes()).createPayloadParser(); + LinkedList<ElementState> stack = new LinkedList<ElementState>(); + stack.addLast(new ElementState(root, true)); + while (!stack.isEmpty()) { + ElementState current = stack.getLast(); + stack.removeLast(); + if (current.state) { + stack.addLast(new ElementState(current.pe, false)); + parser.handleStartElement(current.pe.getName(), current.pe.getNamespace(), current.pe.getAttributes()); + for(ParserElement child : current.pe.getAllChildren()) { + stack.addLast(new ElementState(child, true)); + } + } else { + parser.handleCharacterData(current.pe.getText()); + parser.handleEndElement(current.pe.getName(), current.pe.getNamespace()); + } + } + + Payload payload = parser.getPayload(); + return payload; + } +} |