In the past, I tried two times implementing a multi format converter. One was a Markup converter which should be able to convert GitHub, StackOverflow, MoinMoin, MediaWiki etc. The other is a photobook converter which currently converts ifolor to scribus but should support at least two more photo book formats plus pdf.
The problem is always the same: Different formats have different features. For example: MediaWiki and MoinMoin have different understandings of Macros while most other Markup languages don't support macros. Or ifolor had some border formats which were hard to implement in scribus and don't look nice.
I don't like the idea of implementing direct converters for every possible combination (for 4 formats this are 12 converters with a lot of redundancy). I started with a 'superset data structure' which contains all the features of all formats as a link between import and export filters of the given formats, but I wonder if there is a Best practice way to do such a thing or a something like a Design Pattern which could be helpful to know about, for example an architecture where import and export directly communicate without a 'super format'?
Well, the two projects are currently suspended because of a lack of time (and demand) but I'm willing to learn how I can do it better next time. The photobook did its job for my personal book and will probably be continued soon. Its code is on GitHub.
I would go with a base parent class which contains the common implementations of functionalities shared by all your converters. Then interfaces for functionalities that can be unique per converter and they can be used to know which converter supports what feature. And finally a factory implementation to create the type of converter needed.
Edit to explain myself better after the comment:
You are correct, the base class is a converter. From a quick look on your code and making some assumptions, the input you will have are classes you specify yourself (e.g, ScribusWriter). You can create a common Writter for those. So I would imagine something like:
public abstract class BaseConverter {
// common methods to avoid the redunduncies you mentioned
public abstract <T extends BaseWritter> void convert(XmlBuilder xml, String input, T writer);
}
For the interfaces, it came to my mind from what you wrote about some formats support macros and other do not. So an interface that points to macros support would help us know which do and do not and "force" the implementation where necessary.
What I propose, is that you use inheritance to both classify your types based on characteristics/features and to avoid redundancies in common functionalities.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With