This is an automated email from the ASF dual-hosted git repository.
kezhuw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/master by this push:
new d1d57c4af ZOOKEEPER-4880: Generate comments from zookeeper.jute into
code
d1d57c4af is described below
commit d1d57c4af37cebb9a2dd10d372e30c90f85bf000
Author: luozongle01 <[email protected]>
AuthorDate: Sat Dec 7 13:54:43 2024 +0800
ZOOKEEPER-4880: Generate comments from zookeeper.jute into code
Reviewers: kezhuw, tisonkun
Author: luozongle01
Closes #2206 from luozongle01/ZOOKEEPER-4880
---
.../main/java/org/apache/jute/compiler/JField.java | 42 +++
.../java/org/apache/jute/compiler/JRecord.java | 146 ++++++++-
.../java/org/apache/jute/compiler/generated/rcc.jj | 45 +--
.../java/org/apache/jute/compiler/JRecordTest.java | 344 +++++++++++++++++++++
4 files changed, 547 insertions(+), 30 deletions(-)
diff --git a/zookeeper-jute/src/main/java/org/apache/jute/compiler/JField.java
b/zookeeper-jute/src/main/java/org/apache/jute/compiler/JField.java
index 395c0b6a9..0d8f35bd0 100644
--- a/zookeeper-jute/src/main/java/org/apache/jute/compiler/JField.java
+++ b/zookeeper-jute/src/main/java/org/apache/jute/compiler/JField.java
@@ -18,6 +18,9 @@
package org.apache.jute.compiler;
+import org.apache.jute.compiler.generated.RccConstants;
+import org.apache.jute.compiler.generated.Token;
+
/**
*
*/
@@ -25,6 +28,21 @@ public class JField {
private JType mType;
private String mName;
+ /**
+ * {@link #mType} of token.
+ */
+ private Token mTypeToken;
+
+ private Token previousToken;
+
+ /**
+ * Since we can only get the comments before the token through the {@link
Token#specialToken},
+ * we need to save the next token to get the end-of-line comment.
+ *
+ * <p>It may be the type of the next field, or it may be {@link
RccConstants#RBRACE_TKN} of the class.
+ */
+ private Token nextToken;
+
/**
* Creates a new instance of JField.
*/
@@ -33,6 +51,30 @@ public class JField {
mName = name;
}
+ public Token getTypeToken() {
+ return mTypeToken;
+ }
+
+ public void setTypeToken(Token typeToken) {
+ this.mTypeToken = typeToken;
+ }
+
+ public Token getNextToken() {
+ return nextToken;
+ }
+
+ public void setNextToken(Token nextToken) {
+ this.nextToken = nextToken;
+ }
+
+ public Token getPreviousToken() {
+ return previousToken;
+ }
+
+ public void setPreviousToken(Token previousToken) {
+ this.previousToken = previousToken;
+ }
+
public String getSignature() {
return mType.getSignature();
}
diff --git a/zookeeper-jute/src/main/java/org/apache/jute/compiler/JRecord.java
b/zookeeper-jute/src/main/java/org/apache/jute/compiler/JRecord.java
index 618b4c50b..76ebc1731 100644
--- a/zookeeper-jute/src/main/java/org/apache/jute/compiler/JRecord.java
+++ b/zookeeper-jute/src/main/java/org/apache/jute/compiler/JRecord.java
@@ -22,10 +22,13 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import org.apache.jute.compiler.generated.RccConstants;
+import org.apache.jute.compiler.generated.Token;
/**
*
@@ -36,11 +39,12 @@ public class JRecord extends JCompType {
private String mName;
private String mModule;
private List<JField> mFields;
+ private Token mRecordToken;
/**
* Creates a new instance of JRecord.
*/
- public JRecord(String name, ArrayList<JField> flist) {
+ public JRecord(String name, ArrayList<JField> flist, Token recordToken) {
super("struct " + name.substring(name.lastIndexOf('.') + 1),
name.replaceAll("\\.", "::"), getCsharpFQName(name), name,
"Record", name, getCsharpFQName("IRecord"));
mFQName = name;
@@ -48,12 +52,17 @@ public class JRecord extends JCompType {
mName = name.substring(idx + 1);
mModule = name.substring(0, idx);
mFields = flist;
+ mRecordToken = recordToken;
}
public String getName() {
return mName;
}
+ public Token getRecordToken() {
+ return mRecordToken;
+ }
+
public String getCsharpName() {
return "Id".equals(mName) ? "ZKId" : mName;
}
@@ -208,8 +217,17 @@ public class JRecord extends JCompType {
}
}
String recName = getName();
+
+ String recordComments = getRecordComments();
+ if (recordComments != null && !recordComments.isEmpty()) {
+ h.write(recordComments);
+ }
h.write("struct " + recName + " {\n");
for (JField f : mFields) {
+ String fieldComments = getCFieldComments(f);
+ if (fieldComments != null && !fieldComments.isEmpty()) {
+ h.write(fieldComments);
+ }
h.write(f.genCDecl());
}
h.write("};\n");
@@ -436,10 +454,18 @@ public class JRecord extends JCompType {
jj.write("import org.apache.jute.*;\n");
jj.write("import org.apache.jute.Record; // JDK14 needs explicit
import due to clash with java.lang.Record\n");
jj.write("import org.apache.yetus.audience.InterfaceAudience;\n");
+ String recordComments = getRecordComments();
+ if (recordComments != null && !recordComments.isEmpty()) {
+ jj.write(recordComments);
+ }
jj.write("@InterfaceAudience.Public\n");
jj.write("public class " + getName() + " implements Record {\n");
for (Iterator<JField> i = mFields.iterator(); i.hasNext(); ) {
JField jf = i.next();
+ String fieldComments = getJavaFieldComments(jf);
+ if (fieldComments != null && !fieldComments.isEmpty()) {
+ jj.write(fieldComments);
+ }
jj.write(jf.genJavaDecl());
}
jj.write(" public " + getName() + "() {\n");
@@ -767,4 +793,122 @@ public class JRecord extends JCompType {
}
return fQName.toString();
}
+
+ public String getJavaFieldComments(JField jField) {
+ return getFieldComments(jField, " ");
+ }
+
+ public String getCFieldComments(JField jField) {
+ return getFieldComments(jField, " ");
+ }
+
+ private String getFieldComments(JField jField, String indent) {
+ if (jField == null || jField.getTypeToken() == null ||
jField.getNextToken() == null) {
+ return "";
+ }
+
+ // get the comment before the line
+ Token beforeTheLineCommentToken =
getCommentToken(jField.getTypeToken(), jField.getPreviousToken());
+ List<String> comments = extractComments(beforeTheLineCommentToken,
Integer.MAX_VALUE);
+
+ Token endOfLineCommentToken = getCommentToken(jField.getNextToken(),
null);
+ if (endOfLineCommentToken != null && jField.getTypeToken().beginLine
== endOfLineCommentToken.beginLine) {
+
+ comments.addAll(extractComments(endOfLineCommentToken,
endOfLineCommentToken.beginLine));
+ }
+
+ return formatComments(indent, comments);
+ }
+
+ private Token getCommentToken(Token token, Token previousToken) {
+ if (token == null || token.specialToken == null) {
+ return null;
+ }
+
+ Token commentToken = token.specialToken;
+ while (commentToken.specialToken != null) {
+ commentToken = commentToken.specialToken;
+ }
+ // Skip end of line comment belong to previous token.
+ while (previousToken != null && commentToken != null &&
commentToken.beginLine == previousToken.endLine) {
+ commentToken = commentToken.next;
+ }
+ return commentToken;
+ }
+
+ public String getRecordComments() {
+ if (getRecordToken() == null || getRecordToken().specialToken == null)
{
+ return "";
+ }
+
+ // get the comments before the class
+ Token commentToken = getCommentToken(getRecordToken(), null);
+ return formatComments("", extractComments(commentToken,
Integer.MAX_VALUE));
+ }
+
+ private static String formatComments(String indent, List<String>
commentLines) {
+ if (commentLines == null || commentLines.isEmpty()) {
+ return "";
+ }
+
+ StringBuilder builder = new StringBuilder();
+ for (String line : commentLines) {
+ if (!line.isEmpty()) {
+ builder.append(indent).append(line);
+ }
+ builder.append(System.lineSeparator());
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * Extracts comments with indentation and line separator trimmed.
+ *
+ * <p>Empty line is represented as empty string.
+ */
+ private static List<String> extractComments(Token token, int endLine) {
+ List<String> comments = new ArrayList<>();
+
+ if (token == null) {
+ return comments;
+ }
+
+ int nextLine = token.beginLine;
+ while (token != null && token.beginLine <= endLine) {
+ while (nextLine < token.beginLine) {
+ comments.add("");
+ nextLine++;
+ }
+ nextLine = token.endLine + 1;
+ switch (token.kind) {
+ case RccConstants.ONE_LINE_COMMENT:
+ comments.add(token.image);
+ break;
+ case RccConstants.MULTI_LINE_COMMENT: {
+ List<String> lines =
Arrays.asList(token.image.split("\r|\n|\r\n"));
+ // First line captures no indentation.
+ comments.add(lines.get(0));
+ int indentSpaces = token.beginColumn - 1;
+ for (int i = 1; i < lines.size(); i++) {
+ String line = lines.get(i);
+ int j = 0;
+ while (j < indentSpaces && j < line.length()) {
+ if (line.charAt(j) != ' ') {
+ break;
+ }
+ j++;
+ }
+ comments.add(line.substring(j));
+ }
+ }
+ break;
+ default:
+ throw new IllegalStateException("expect comment token, but
get token kind " + token.kind);
+ }
+ token = token.next;
+ }
+
+ return comments;
+ }
}
diff --git
a/zookeeper-jute/src/main/java/org/apache/jute/compiler/generated/rcc.jj
b/zookeeper-jute/src/main/java/org/apache/jute/compiler/generated/rcc.jj
index 94d4f42f6..f97ebc3c6 100644
--- a/zookeeper-jute/src/main/java/org/apache/jute/compiler/generated/rcc.jj
+++ b/zookeeper-jute/src/main/java/org/apache/jute/compiler/generated/rcc.jj
@@ -111,32 +111,8 @@ SKIP :
SPECIAL_TOKEN :
{
- "//" : WithinOneLineComment
-}
-
-<WithinOneLineComment> SPECIAL_TOKEN :
-{
- <("\n" | "\r" | "\r\n" )> : DEFAULT
-}
-
-<WithinOneLineComment> MORE :
-{
- <~[]>
-}
-
-SPECIAL_TOKEN :
-{
- "/*" : WithinMultiLineComment
-}
-
-<WithinMultiLineComment> SPECIAL_TOKEN :
-{
- "*/" : DEFAULT
-}
-
-<WithinMultiLineComment> MORE :
-{
- <~[]>
+ <ONE_LINE_COMMENT: "//" (~["\n","\r"])*>
+| <MULTI_LINE_COMMENT: "/*" (~["*"])* "*" (~["*","/"] (~["*"])* "*" | "*")*
"/">
}
TOKEN :
@@ -274,21 +250,32 @@ JRecord Record() :
ArrayList<JField> flist = new ArrayList<JField>();
Token t;
JField f;
+ // Get the comments on the class token
+ Token recordTkn;
+ Token typeTkn;
+ Token previousToken = null;
}
{
- <RECORD_TKN>
+ recordTkn = <RECORD_TKN>
t = <IDENT_TKN>
{ rname = t.image; }
- <LBRACE_TKN>
+ previousToken = <LBRACE_TKN>
(
+ {typeTkn = getToken(1);}
f = Field()
{ flist.add(f); }
<SEMICOLON_TKN>
+ {
+ f.setTypeToken(typeTkn);
+ f.setPreviousToken(previousToken);
+ f.setNextToken(getToken(1));
+ previousToken = typeTkn;
+ }
)+
<RBRACE_TKN>
{
String fqn = curModuleName + "." + rname;
- JRecord r = new JRecord(fqn, flist);
+ JRecord r = new JRecord(fqn, flist, recordTkn);
recTab.put(fqn, r);
return r;
}
diff --git
a/zookeeper-jute/src/test/java/org/apache/jute/compiler/JRecordTest.java
b/zookeeper-jute/src/test/java/org/apache/jute/compiler/JRecordTest.java
new file mode 100644
index 000000000..91eece84e
--- /dev/null
+++ b/zookeeper-jute/src/test/java/org/apache/jute/compiler/JRecordTest.java
@@ -0,0 +1,344 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jute.compiler;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.StringReader;
+import java.lang.reflect.Field;
+import java.util.List;
+import org.apache.jute.compiler.generated.ParseException;
+import org.apache.jute.compiler.generated.Rcc;
+import org.junit.jupiter.api.Test;
+
+@SuppressWarnings({"unchecked", "SameParameterValue"})
+public class JRecordTest {
+
+ @Test
+ public void testEndOfLineComments() throws ParseException,
NoSuchFieldException, IllegalAccessException {
+ String juteStr = "module org.apache.zookeeper.data {\n"
+ + " // information explicitly stored by the server
persistently\n"
+ + " class StatPersisted {\n"
+ + " long czxid; // created zxid\n"
+ + " long mzxid; // last modified zxid\n"
+ + " long ctime; /* created */\n"
+ + " long mtime; /** last modified */\n"
+ + " int version; /* version */ /* testComment1 */\n"
+ + " int cversion; /* child version */ /* child
versionComment2 */ /* child versionComment3 */\n"
+ + " int aversion; /** acl version */ /** acl
versionComment2 */ /** acl version */\n"
+ + " long ephemeralOwner; /* A multi-line end of line
comment. */ /* Another multi-line end of line comment. */ /* Yet another\n"
+ + "end of line comment. */ /* Comment belong to new field */\n"
+ + " long pzxid; /* A multi-line end of line
comment. */ /* Another multi-line end of line comment. */ /* Yet another\n"
+ + "end of line comment. */ /* Comment belong to new field */\n"
+ + " }\n"
+ + "}";
+
+ try (StringReader stringReader = new StringReader(juteStr)) {
+ Rcc parser = new Rcc(stringReader);
+ JFile jFile = parser.Input();
+ List<JRecord> mRecords = getField(jFile, "mRecords", List.class);
+ assertEquals(1, mRecords.size());
+
+ JRecord jRecord = mRecords.get(0);
+ assertEquals("StatPersisted", jRecord.getName());
+ List<JField> fields = jRecord.getFields();
+ assertFiled(fields);
+
+ assertEquals("// information explicitly stored by the server
persistently\n", jRecord.getRecordComments());
+ assertEquals(" // created zxid\n",
jRecord.getJavaFieldComments(fields.get(0)));
+ assertEquals(" // last modified zxid\n",
jRecord.getJavaFieldComments(fields.get(1)));
+ assertEquals(" /* created */\n",
jRecord.getJavaFieldComments(fields.get(2)));
+ assertEquals(" /** last modified */\n",
jRecord.getJavaFieldComments(fields.get(3)));
+ assertEquals(" /* version */\n /* testComment1 */\n",
jRecord.getJavaFieldComments(fields.get(4)));
+ assertEquals(" /* child version */\n /* child versionComment2
*/\n /* child versionComment3 */\n",
jRecord.getJavaFieldComments(fields.get(5)));
+ assertEquals(" /** acl version */\n /** acl versionComment2 */\n
/** acl version */\n", jRecord.getJavaFieldComments(fields.get(6)));
+ assertEquals(
+ " /* A multi-line end of line comment. */\n"
+ + " /* Another multi-line end of line comment.
*/\n"
+ + " /* Yet another\n"
+ + " end of line comment. */\n",
jRecord.getJavaFieldComments(fields.get(7)));
+ assertEquals(
+ " /* Comment belong to new field */\n"
+ + " /* A multi-line end of line comment. */\n"
+ + " /* Another multi-line end of line comment.
*/\n"
+ + " /* Yet another\n"
+ + " end of line comment. */\n",
jRecord.getJavaFieldComments(fields.get(8)));
+ }
+ }
+
+ @Test
+ public void testCommentBeforeLineAndEndOfLine() throws ParseException,
NoSuchFieldException, IllegalAccessException {
+ String juteStr = "module org.apache.zookeeper.data {\n"
+ + " /**\n"
+ + " * information explicitly stored by the server
persistently\n"
+ + " */ \n"
+ + " class StatPersisted {\n"
+ + " // created zxid\n"
+ + " long czxid; // created zxid comment2\n"
+ + " /* last modified zxid */\n"
+ + " long mzxid; // last modified zxid comment2\n"
+ + " /* created */\n"
+ + " long ctime; // created comment2\n"
+ + " /* last modified */\n"
+ + " /* last modified */\n"
+ + " long mtime; // last modified comment2\n"
+ + " // version comment\n "
+ + " int version; /* version comment1 */ /*
version\n comment2 */\n"
+ + " /** child version */\n"
+ + " /** child version */\n"
+ + " int cversion; /** child version */ // child
version\n"
+ + " // acl version\n"
+ + " // acl version\n"
+ + " // acl version\n"
+ + " int aversion; // acl version\n"
+ + " // ephemeralOwner comment\n"
+ + " long ephemeralOwner; /* A multi-line end of line
comment. */ /* Another multi-line end of line comment. */ /* Yet another\n"
+ + "end of line comment. */ /* Comment belong to new field */\n"
+ + " // pzxid comment\n"
+ + " long pzxid; /* A multi-line end of line
comment. */ /* Another multi-line end of line comment. */ /* Yet another\n"
+ + "end of line comment. */ /* Comment belong to new field */\n"
+ + " }\n"
+ + "}";
+ try (StringReader stringReader = new StringReader(juteStr)) {
+ Rcc parser = new Rcc(stringReader);
+ JFile jFile = parser.Input();
+ List<JRecord> mRecords = getField(jFile, "mRecords", List.class);
+ assertEquals(1, mRecords.size());
+
+ JRecord jRecord = mRecords.get(0);
+ assertEquals("StatPersisted", jRecord.getName());
+ List<JField> fields = jRecord.getFields();
+ assertFiled(fields);
+
+ assertEquals("/**\n * information explicitly stored by the server
persistently\n */\n", jRecord.getRecordComments());
+ assertEquals(" // created zxid\n // created zxid comment2\n",
jRecord.getJavaFieldComments(fields.get(0)));
+ assertEquals(" /* last modified zxid */\n // last modified zxid
comment2\n", jRecord.getJavaFieldComments(fields.get(1)));
+ assertEquals(" /* created */\n // created comment2\n",
jRecord.getJavaFieldComments(fields.get(2)));
+ assertEquals(" /* last modified */\n /* last modified */\n //
last modified comment2\n", jRecord.getJavaFieldComments(fields.get(3)));
+
+ assertEquals(" // version comment\n /* version comment1 */\n /*
version\n comment2 */\n", jRecord.getJavaFieldComments(fields.get(4)));
+ assertEquals(" /** child version */\n /** child version */\n
/** child version */\n // child version\n",
jRecord.getJavaFieldComments(fields.get(5)));
+ assertEquals(" // acl version\n // acl version\n // acl
version\n // acl version\n", jRecord.getJavaFieldComments(fields.get(6)));
+ assertEquals(
+ " // ephemeralOwner comment\n"
+ + " /* A multi-line end of line comment. */\n"
+ + " /* Another multi-line end of line comment.
*/\n"
+ + " /* Yet another\n"
+ + " end of line comment. */\n",
jRecord.getJavaFieldComments(fields.get(7)));
+ assertEquals(
+ " /* Comment belong to new field */\n"
+ + " // pzxid comment\n"
+ + " /* A multi-line end of line comment. */\n"
+ + " /* Another multi-line end of line comment.
*/\n"
+ + " /* Yet another\n"
+ + " end of line comment. */\n",
jRecord.getJavaFieldComments(fields.get(8)));
+ }
+ }
+
+ @Test
+ public void testCommentBeforeLine() throws ParseException,
NoSuchFieldException, IllegalAccessException {
+ String juteStr = "module org.apache.zookeeper.data {\n"
+ + " // information explicitly stored by the server
persistently\n"
+ + " // StatPersisted Comment1\n"
+ + " // StatPersisted Comment2\n"
+ + " class StatPersisted {\n"
+ + " // created zxid comment1\n"
+ + " // created zxid comment2\n"
+ + " // created zxid comment3\n"
+ + " long czxid;\n"
+ + " // last modified zxid\n"
+ + " // last modified zxid\n"
+ + " // last modified zxid\n"
+ + " long mzxid;\n"
+ + " /* created */\n"
+ + " /* created */\n"
+ + " /* created */\n"
+ + " long ctime;\n"
+ + " /** last modified */\n"
+ + " /** last modified */\n"
+ + " long mtime;\n"
+ + " /** version */\n"
+ + " /** version */\n"
+ + " int version;\n"
+ + " // child version\n"
+ + " /** child version */\n"
+ + " /** child version */\n"
+ + " int cversion;\n"
+ + " /* acl version */\n"
+ + " // acl version\n"
+ + " /* acl version */\n"
+ + " int aversion;\n"
+ + " // owner id if ephemeral, 0 otw\n"
+ + " long ephemeralOwner;\n"
+ + " // last modified children\n"
+ + " long pzxid;\n"
+ + " }\n"
+ + "}";
+ try (StringReader stringReader = new StringReader(juteStr)) {
+ Rcc parser = new Rcc(stringReader);
+ JFile jFile = parser.Input();
+ List<JRecord> mRecords = getField(jFile, "mRecords", List.class);
+ assertEquals(1, mRecords.size());
+
+ JRecord jRecord = mRecords.get(0);
+ assertEquals("StatPersisted", jRecord.getName());
+ List<JField> fields = jRecord.getFields();
+ assertFiled(fields);
+
+ assertEquals("// information explicitly stored by the server
persistently\n// StatPersisted Comment1\n// StatPersisted Comment2\n",
jRecord.getRecordComments());
+ assertEquals(" // created zxid comment1\n // created zxid
comment2\n // created zxid comment3\n",
jRecord.getJavaFieldComments(fields.get(0)));
+ assertEquals(" // last modified zxid\n // last modified zxid\n
// last modified zxid\n", jRecord.getJavaFieldComments(fields.get(1)));
+ assertEquals(" /* created */\n /* created */\n /* created
*/\n", jRecord.getJavaFieldComments(fields.get(2)));
+ assertEquals(" /** last modified */\n /** last modified */\n",
jRecord.getJavaFieldComments(fields.get(3)));
+ assertEquals(" /** version */\n /** version */\n",
jRecord.getJavaFieldComments(fields.get(4)));
+ assertEquals(" // child version\n /** child version */\n /**
child version */\n", jRecord.getJavaFieldComments(fields.get(5)));
+ assertEquals(" /* acl version */\n // acl version\n /* acl
version */\n", jRecord.getJavaFieldComments(fields.get(6)));
+ assertEquals(" // owner id if ephemeral, 0 otw\n",
jRecord.getJavaFieldComments(fields.get(7)));
+ assertEquals(" // last modified children\n",
jRecord.getJavaFieldComments(fields.get(8)));
+ }
+ }
+
+ @Test
+ public void testMultiLineComments() throws ParseException,
NoSuchFieldException, IllegalAccessException {
+ String juteStr = "module org.apache.zookeeper.data {\n"
+ + " /**\n"
+ + " * information explicitly stored by the server
persistently\n"
+ + " */\n"
+ + " // StatPersisted Comment\n"
+ + " /* StatPersisted Comment */\n"
+ + " class StatPersisted {\n"
+ + " /**\n"
+ + " * created zxid\n"
+ + " */\n"
+ + " long czxid;\n"
+ + " /**\n"
+ + " * last modified zxid comment1\n"
+ + " */\n"
+ + " /**\n"
+ + " * last modified zxid comment2\n"
+ + " */\n"
+ + " long mzxid;\n"
+ + " /*\n"
+ + " * created\n"
+ + " */\n"
+ + " long ctime; /* multi-line\n"
+ + "end of line */\n"
+ + " /*\n"
+ + " last modified\n"
+ + " */"
+ + " long mtime; /* A multi-line end of line comment. */
/* Another multi-line end of line comment. */ /* Yet another\n"
+ + "end of line comment. */ /* Comment belong to new field */\n"
+ + " /* version comment */\n"
+ + " int version; // version\n"
+ + " /**\n"
+ + " * child version\n"
+ + " */\n"
+ + " /**\n"
+ + " * child version comment2\n"
+ + " */\n"
+ + " int cversion; // child version\n"
+ + " /* acl version */\n"
+ + " int aversion; /* acl version */ /* acl version */
// acl version\n"
+ + " /*\n"
+ + " ephemeralOwner comment\n"
+ + " */\n"
+ + " // ephemeralOwner comment\n"
+ + " /*\n"
+ + " ephemeralOwner comment\n"
+ + " */\n"
+ + " long ephemeralOwner; // owner id if ephemeral, 0
otw\n"
+ + " /*\n"
+ + " pzxid comment\n"
+ + " */\n"
+ + " long pzxid; // last modified children\n"
+ + " }\n"
+ + "}";
+ try (StringReader stringReader = new StringReader(juteStr)) {
+ Rcc parser = new Rcc(stringReader);
+ JFile jFile = parser.Input();
+ List<JRecord> mRecords = getField(jFile, "mRecords", List.class);
+ assertEquals(1, mRecords.size());
+
+ JRecord jRecord = mRecords.get(0);
+ assertEquals("StatPersisted", jRecord.getName());
+ List<JField> fields = jRecord.getFields();
+ assertFiled(fields);
+
+ assertEquals(
+ "/**\n"
+ + " * information explicitly stored by the server
persistently\n"
+ + " */\n"
+ + "// StatPersisted Comment\n"
+ + "/* StatPersisted Comment */\n",
jRecord.getRecordComments());
+ assertEquals(" /**\n * created zxid\n */\n",
jRecord.getJavaFieldComments(fields.get(0)));
+ assertEquals(" /**\n * last modified zxid comment1\n */\n
/**\n * last modified zxid comment2\n */\n",
+ jRecord.getJavaFieldComments(fields.get(1)));
+ assertEquals(" /*\n * created\n */\n /* multi-line\n end of
line */\n", jRecord.getJavaFieldComments(fields.get(2)));
+ assertEquals(" /*\n last modified\n */\n"
+ + " /* A multi-line end of line comment. */\n"
+ + " /* Another multi-line end of line comment.
*/\n"
+ + " /* Yet another\n"
+ + " end of line comment. */\n",
jRecord.getJavaFieldComments(fields.get(3)));
+ assertEquals(" /* Comment belong to new field */\n /* version
comment */\n // version\n",
+ jRecord.getJavaFieldComments(fields.get(4)));
+ assertEquals(" /**\n * child version\n */\n /**\n * child
version comment2\n */\n // child version\n",
+ jRecord.getJavaFieldComments(fields.get(5)));
+ assertEquals(" /* acl version */\n /* acl version */\n /* acl
version */\n // acl version\n", jRecord.getJavaFieldComments(fields.get(6)));
+ assertEquals(" /*\n"
+ + " ephemeralOwner comment\n"
+ + " */\n"
+ + " // ephemeralOwner comment\n"
+ + " /*\n"
+ + " ephemeralOwner comment\n"
+ + " */\n"
+ + " // owner id if ephemeral, 0 otw\n",
jRecord.getJavaFieldComments(fields.get(7)));
+ assertEquals(" /*\n pzxid comment\n */\n // last modified
children\n", jRecord.getJavaFieldComments(fields.get(8)));
+ }
+ }
+
+ private void assertFiled(List<JField> fields) {
+ assertEquals(9, fields.size());
+ assertEquals("long", fields.get(0).getType().getJavaType());
+ assertEquals("czxid", fields.get(0).getName());
+ assertEquals("long", fields.get(1).getType().getJavaType());
+ assertEquals("mzxid", fields.get(1).getName());
+ assertEquals("long", fields.get(2).getType().getJavaType());
+ assertEquals("ctime", fields.get(2).getName());
+ assertEquals("long", fields.get(3).getType().getJavaType());
+ assertEquals("mtime", fields.get(3).getName());
+ assertEquals("int", fields.get(4).getType().getJavaType());
+ assertEquals("version", fields.get(4).getName());
+ assertEquals("int", fields.get(5).getType().getJavaType());
+ assertEquals("cversion", fields.get(5).getName());
+ assertEquals("int", fields.get(6).getType().getJavaType());
+ assertEquals("aversion", fields.get(6).getName());
+ assertEquals("long", fields.get(7).getType().getJavaType());
+ assertEquals("ephemeralOwner", fields.get(7).getName());
+ assertEquals("long", fields.get(8).getType().getJavaType());
+ assertEquals("pzxid", fields.get(8).getName());
+ }
+
+ private <T> T getField(final Object target,
+ final String fieldName,
+ final Class<T> fieldClassType) throws
NoSuchFieldException, IllegalAccessException {
+ Class<?> targetClazz = target.getClass();
+ Field field = targetClazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return fieldClassType.cast(field.get(target));
+ }
+}