1

I want to implement a network protocol. To obtain a maintainable design I am looking for fitting patterns.

The protocol is based on XML and should be read with java. To simplify the discussion here I assume the example grammar:

<User>
  <GroupList>
    <Group>group1</Group>
    <Group>group2</Group>
  </GroupList>
</User>

Short question: What is a good design pattern to parse such thing?

Long version: I have found this and this question where different patterns (mostly state pattern) are proposed.

My actual (but lacking) solution is the folowing: I create for each possible entry in the XML a class to contain the data and a parser. Thus I have User, User.Parser, ... as classes. Further there is a ParserSelector that has a Map<String,AbstractParser> in which all possible subentries get registered. For each parser a ParserSelector gets instantiated and set up. For example the ParserSelector of the GroupList.Parser has one entry: The mapping from the string "Group" to an instance of Group.Parser. If I did not use the ParserSleector class, I would have to write this block of code into every single parser.

The problem is now how to get the read data to the superobjects. The Group.Parser would create a Group object with content group1. This object must now be registered in the GroupList object. I have read of using Visitor or Observer patterns but do not understand how they might fit here.

I give some pseudo code below to see the problem. You see, that I have to check via instanceof for the type as statically there is the type information not available.

I thought this should be possible to solve using polymorphism in java in a cleaner (more maintainable) way. I always face then the problem that java does only do dynamic binding on overriding. Thus I cannot add a parameter to the XMLParser.parse(...) method to allow of "remote updating" as in a visitor/observer like approach.

Side remark: The real grammar is "deep" that is, it is such that there are quite many XML entries (here only three: User, GroupList and Group) while most of them might contain only very few different subentries (User and GroupList may only contain one subentry here, while Group itself contains only text).

Here comes some lines of pseude java code to explain the problem:

class User extends AbstractObject {
    static class Parser implements XMLParser {

        ParserSelector ps = ...; // Initialize with GroupList.Parser

        void parse(XMLStreamReader xsr){
            XMLParser p = ps.getParser(...); // The corresponding parser.
            // We know only that it is XMLParser statically.

            p.parse(...);

            if(p instanceof GroupList.Parser){
                // Set the group list in the User class
            }
        }
    }
}

class GroupList extends AbstractObject{...}
class Group extends AbstractObject{...}

class ParserSelector{
    Map<String,XMLParser> = new Map<>();
    void registerParser(...){...} // Registers a possible parser for subentries

    XMLParser getParser(String elementName){
        return map.get(elementName); // Returns the parser registered with the given name
    }
}

interface XMLParser {
    void parse(XMLStreamReader xsr);
}

abstract class AbstractObject{}
Community
  • 1
  • 1
Christian Wolf
  • 1,187
  • 1
  • 12
  • 33
  • http://www.eaipatterns.com/EnvelopeWrapper.html – Donal Aug 26 '14 at 16:27
  • 3
    I'd use the "use an existing XML -> POJO library" pattern. – Dave Newton Aug 26 '14 at 16:30
  • 1
    You are reinventing a lot of wheels. First order of business is to learn the existing Java classes for reading and manipulating XML, `javax.xml.*`, `org.xml.sax.*`, `org.w3c.dom.*` to avoid rewriting versions of them. – Jim Garrison Aug 26 '14 at 16:40
  • @JimGarrison I have no intention to rewirite them. Instead I wand to parse using the STax classes (not SAX) to bring the relevant data to a pure java object structure. Later (in the rest of the program code) this data will be delt with. I do not want to have to handle these things in the other control logic. Think of it as an abstraction layer. – Christian Wolf Aug 26 '14 at 17:02
  • @DaveNewton The reason I wanted to code it myself was to allow different protocol versions (network application!). I wanted to add some attribute to the xml root node to qualify the protocol version. On modifications I could easyly use classes from a separate package with the old classes. On using a linbary I have the problem that I cannot change the protocol definition "on the fly". Any suggestions? – Christian Wolf Aug 26 '14 at 17:17

1 Answers1

0

To finish this question:

I ended up with JAXB. In fact I was not aware of the fact that it allows to easily create a XML Schema from java source code (using annotations).

Thus I just have to write the code with classical java objects which are used for transfer. Then the API handles the conversion to and from XML quite well.

Christian Wolf
  • 1,187
  • 1
  • 12
  • 33