I had an idea and I wanted to run it by you to get some feedback. Please look the following over and let me know what you think, whether it's positive or negative.
I've always wished that there was a way to embed certain pieces of data in Java code without having to follow Java's rules all the time. I've heard a lot of talk about Domain Specific Languages lately (DSLs) and how it would be great if we could utilize them more on a daily basis. I think I have an idea of how to do this in a reasonably elegant way.
Here are some examples of things that I know of that are a pain to represent in Java code (and other C-like languages) that I want this to solve:
List of short strings as string array
String[] ar = { "Item1", "Item2", "Item3", "Item4" };
List of long strings as string array
String[] ar = { "The quick brown\n fox jumped over\n the lazy dog.",
"The quick brown\n fox jumped over\n the lazy dog.",
"The quick brown\n fox jumped over\n the lazy dog.",
"The quick brown\n fox jumped over\n the lazy dog.", };
Table of strings as multi-dimensional string array:
String[][] ar = { { "InvoiceID", "Date", "SubTotal", "Tax", "Total" },
{ "1", "1/2/2009", "300, "21", "321" },
{ "2", "1/4/2008", "100", "7", "107" },
{ "3", "1/6/2008", "200", "14", "214" } };
List of key-value pairs
Map states = new HashMap();
states.add("FL", "Florida");
states.add("OH", "Ohio");
states.add("GA", "Georgia");
states.add("NY", "New York");
states.add("SC", "South Carolina");
HTML code single string
String html = "<a href=\"www.somesite.com\">Some site</a>";
HTML text block with decent text formatting
String html = "Hi, John,\r\n<br>\r\n<br>Thank you for writing to us. We do not currently carry that specific product.\r\n<br>\r\n<br>Regards,\r\n<br>";
I've investigated the following described solution a bit and I believe it's possible to create a usable library that would allow you to achieve this elegantly. In Java 5 and 6 there is something called the Annotation Processor Tool (APT) (not the same as Debian APT). You create your own source code processor, which will be called as the code is being compiled to give you the opportunity to rewrite the source code. After rewriting the code it is compiled as usual.
The following must be done to make use of APT: 1. Put this library's jar on the ANT classpath. 2. Put this library's jar on the project classpath. 3. Call the apt task instead of javac and add the preprocessdir parameter to specify where the generated files must be placed.
The DSL code can be placed inside a comment right after the variable where the result of the code will be placed. When the processor runs it can look forward in the code for the next comment, extract the code, run it through the processor, generate the code and do the compile.
Here is the list again, this time with what it could look like:
List of short strings as string array
@DslTextArray
String[] ar = null; /* Item1, Item2, Item3, Item4 */
List of long strings as string array
@DslMultilineTextArray
String[] ar = null;
/*
The quick brown
fox jumped over
the lazy dog.
The quick brown
fox jumped over
the lazy dog.
The quick brown
fox jumped over
the lazy dog.
The quick brown
fox jumped over
the lazy dog.
*/
Table of strings as multi-dimensional string array or JTable:
@DslTextTable
String[][] ar = null;
/*
InvoiceID,Date,SubTotal,Tax,Total
1,1/2/2009,300,21,321
2,1/4/2008,100,7,107
3,1/6/2008,200,14,214
*/
List of key-value pairs
@DslMap
Map states = null; /* FL=Florida, OH=Ohio, GA=Georgia, NY=New York, SC=South Carolina */
// Could also put each pair on a new line
HTML code single string
@DslText
String html = null; /* <a href="www.somesite.com">Some site</a> */
HTML text block with decent text formatting
@DslText
String html = null;
/*
Hi, John,
Thank you for writing to us. We do not currently carry that specific product.
Regards,
Mike
*/
Some requirements/features I can think of for this solution:
You must declare the variable to hold the data that the script will generate in the Java source code. This allows the rest of the source code to know about the resulting data even though the compiler doesn't know where it's coming from.
- Must not violate the Java language so that the IDE and javac do not show errors.
- Work with all the existing Java code you have. No need to replace any existing code. Just add these snippets wherever you like.
- Must be easily extensible with additional types.
- Must be able to later make extensions to IDE's that allow for source-code highlighting and auto-completion.
- Translations occur at compile-time so valid Java code must be generated.
- Convert to String and String[] for things like lists, multi-line text blocks such as CSS, SQL
- Convert and encode XML, HTML
- When code is rewritten retain the same line numbers. Do not add any lines so that debugging and reading errors does not become a pain.
- Run code written in any BSF language at runtime. Allow it to pass any parameter to the script and return any Java class or primitive back to Java.
- Run code written in any BSF language at compile-time to generate Java source code. Similar to how M4 is used on Linux.
- Later: Allow you to chain together the String results from many calls to build a long string. Some if it may be compile-time, some of it run-time.
Again, I would really appreciate getting some feedback on this. Is this a stupid idea? Is there something like this out there already? Would you bother using something like this or should I just keep it to myself?