想法:将数据/ DSL嵌入Java作为注释并使用APT生成Java代码

时间:2009-03-17 04:33:16

标签: java dsl

我有一个想法,我想通过你运行它来获得一些反馈。请仔细阅读以下内容,让我知道您的想法,无论是积极的还是消极的。

我一直希望有一种方法可以在Java代码中嵌入某些数据,而不必始终遵循Java的规则。我最近听过很多关于领域特定语言的讨论(DSL)以及如果我们能够每天更多地使用它们会如何变得更好。我想我已经知道如何以一种相当优雅的方式做到这一点。

以下是我所知道的一些例子,这些例子很难用Java代码(以及其他类C语言)来表示,我希望它能解决这个问题:

字符串数组的短字符串列表

String[] ar = { "Item1", "Item2", "Item3", "Item4" };

长字符串列表为字符串数组

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.",  };

字符串表作为多维字符串数组:

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" } };

键值对列表

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文本块

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>";

我已经研究了以下描述的解决方案,我相信可以创建一个可用的库,让您可以优雅地实现这一目标。在Java 5和6中,有一种称为注释处理器工具(APT)(与Debian APT不同)。您可以创建自己的源代码处理器,在编译代码时将调用该代码处理器,以便您有机会重写源代码。重写代码后,它会照常编译。

必须采取以下措施才能使用APT: 1.将此库的jar放在ANT类路径上。 2.将此库的jar放在项目类路径上。 3.调用apt任务而不是javac,并添加preprocessdir参数以指定生成的文件必须放置的位置。

DSL代码可以放在注释结果后面的注释中,并放置代码的结果。当处理器运行时,它可以在代码中期待下一个注释,提取代码,通过处理器运行代码,生成代码并进行编译。

这是再次列表,这次是它的样子:

字符串数组的短字符串列表

@DslTextArray
String[] ar = null; /* Item1, Item2, Item3, Item4 */

长字符串列表为字符串数组

@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.
*/

作为多维字符串数组或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
*/

键值对列表

@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文本块

@DslText
String html = null;
/*
Hi, John,

Thank you for writing to us. We do not currently carry that specific product.

Regards,
Mike
*/

我可以为此解决方案考虑一些要求/功能:

您必须声明变量以保存脚本将在Java源代码中生成的数据。这允许其余的源代码知道结果数据,即使编译器不知道它来自何处。

  • 不得违反Java语言,以免IDE和javac显示错误。
  • 使用您拥有的所有现有Java代码。无需替换任何现有代码。只需在任何您喜欢的地方添加这些代码段即可。
  • 必须可以使用其他类型轻松扩展。
  • 以后必须能够对允许源代码突出显示和自动完成的IDE进行扩展。
  • 翻译在编译时发生,因此必须生成有效的Java代码。
  • 转换为String和String [],用于列表,多行文本块(如CSS,SQL
  • 转换和编码XML,HTML
  • 重写代码时,保留相同的行号。不要添加任何行,以免调试和读取错误。
  • 运行时以任何BSF语言编写的代码。允许它将任何参数传递给脚本,并将任何Java类或原语返回给Java。
  • 在编译时运行以任何BSF语言编写的代码以生成Java源代码。类似于在Linux上使用M4的方式。
  • 稍后:允许您将来自多个调用的String结果链接在一起以构建一个长字符串。有些可能是编译时,有些是运行时。

同样,我真的很感激收到一些反馈。这是一个愚蠢的想法吗?那里有类似的东西吗?你会费心使用这样的东西,还是应该把它留给自己?

2 个答案:

答案 0 :(得分:2)

我会使用google collections api现在是番石榴库http://code.google.com/p/guava-libraries/的一部分,它有很棒的列表和地图支持。它支持你试图实现的那种结构

public static final ImmutableList<Color> GOOGLE_COLORS
   = new ImmutableList.Builder<Color>()
       .addAll(WEBSAFE_COLORS)
       .add(new Color(0, 191, 255))
       .build();

答案 1 :(得分:1)

这是可行的,但我必须说我不喜欢它。

它使数据结构的初始化更容易一些,

BUT

  • 我的extremley很少需要使用编译时常量初始化这样的数据结构。所以一个单独的文件nexht到类/ java文件将更有用

  • 这对开发人员来说完全不透明。没有人希望评论转化为数据。实际上如果遇到这样的评论,我可能会认为它评论了旧代码并立即将其删除

  • ATP是一个功能强大且有趣的工具,但缺乏IDE集成。因此,您必须始终使用ANT构建和运行应用程序,这不像F11或者IDE为此目的提供的任何快捷方式那么好和快速

因此,基本上,您在开发基础架构复杂性方面受到了极大的打击,以最大限度地提高打字速度。

这个想法仍然很有意思。我实际上会更改一个变体,其中可以定义“DSL”类型的注释,允许将代码放入由注释声明定义的任意语言的注释中。当然,这将是一个重大的语言变化,不会很快发生,也可能根本不会发生。