Java Strategy Pattern – Generic File Parser Design

designjavaparsingxml

I am working on a product in which the responsibility of one of the modules is to parse XML files and dump the required content in a database. Even though the present requirement is only to parse XML files, I want to design my parsing module in a fashion that I can support any kind of files in the future. The reason for this approach is that we are building this product for a specific client but plan to sell it to other clients in the near future. All the systems in the ecosystem for the current client produce and consume XML files but this may not be the case for other clients.

What have I tried so far? (The Present)
I have the following design in mind which is based on the Strategy pattern. I have quickly written down the code in eclipse to convey my design so it would be great if other aspects such as proper way of handling exceptions are ignored for now.

Parser : The strategy interface that exposes a parse method.

 public interface Parser<T> {
        public T parse(String inputFile);
    }

*The reason for using a generic parameter is to allow any return type as well as ensure type safety at compile time.

ProductDataXmlParser A concrete class for parsing a product.xml file that contains product related information. (using XMLBeans)

public class ProductDataXmlParser implements Parser<ProductDataTYPE> {

    public ProductDataTYPE parse(String inputFile) {
        ProductDataTYPE productDataDoc = null;
            File inputXMLFile = new File(inputFile);

        try {
            productDataDoc = ProductDataDocument.Factory.parse(inputXMLFile);
        } catch(XmlException e) {
            System.out.println("XmlException while parsing file : "+inputXMLFile);
        } catch(IOException e) { 
                 System.out.println("IOException while parsing file : "+inputXMLFile);
        }
        return productDataDoc.getProductData();
    }
} 

where : ProductDataTYPE and ProductDataDocument are XMlBean POJO classes generated using an xsd and the scomp command.

The future

If I have a product.txt file to be parsed in the future, I can define my own POJO called ProductData that will hold the required contents of the file. I can then create a concrete class called ProductDataFlatFileParser that implements the Parser interface and have the parse method populate the ProductData POJO for me after parsing the file.

Does this design make sense? Are there any obvious flaws in this design? As the design stands, I am allowing the concrete classes to define the algorithm to parse a file and letting the concrete class decide where to populate the data. The design seems to be more dependent on the domain objects rather than the file formats. Is this a bad thing? Any inputs on how I can improve my design will be highly appreciated.

Best Answer

I have a couple of concerns:

  1. I would make sure you actually need a generic design before implementing one. Are you sure you're going to need file types other than XML? If not, why code for them? If you eventually need it, you can retrofit your code at that point. It won't take much longer, you will probably have other requirements that will make the code look different than what you're currently proposing, and you will probably never need to write it anyway. As they say, YAGNI (You Ain't Gonna Need It).
  2. If you do actually need a generic design, and you're quite sure of this, then I'd say that Parser<T> is basically sound. I do see two potential problems: (1) it assumes file input -- what if you're trying to parse a JSON stream that you retrieved from an HTTP response, for example? and (2) it doesn't necessarily provide much value except as part of some larger generic framework where you have lots of different types of parsers for lots of different types of data. But I'm not convinced you need any such large generic framework. You just have a very simple, concrete use case right now, as far as I can tell: parse an XML file into a list of ProductDatas.
  3. It's almost never a good idea to swallow exceptions as you are doing in ProductDataXmlParser. I would convert it to some sort of RuntimeException instead.
Related Topic