From 0e49b5f94c05bae0417b1272002531ea8deea4b7 Mon Sep 17 00:00:00 2001 From: luozongle01 Date: Thu, 28 Nov 2024 23:32:37 +0800 Subject: [PATCH] ZOOKEEPER-4880: Generate comments from zookeeper.jute into code. --- .../java/org/apache/jute/compiler/JField.java | 42 +++ .../org/apache/jute/compiler/JRecord.java | 146 +++++++- .../org/apache/jute/compiler/generated/rcc.jj | 45 +-- .../org/apache/jute/compiler/JRecordTest.java | 344 ++++++++++++++++++ 4 files changed, 547 insertions(+), 30 deletions(-) create mode 100644 zookeeper-jute/src/test/java/org/apache/jute/compiler/JRecordTest.java 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 395c0b6a966..0d8f35bd0e5 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. + * + *

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 JField(JType type, String name) { 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 618b4c50bb0..76ebc1731e4 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.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 mFields; + private Token mRecordToken; /** * Creates a new instance of JRecord. */ - public JRecord(String name, ArrayList flist) { + public JRecord(String name, ArrayList 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 JRecord(String name, ArrayList flist) { 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 void genCCode(FileWriter h, FileWriter c) throws IOException { } } 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 void genJavaCode(File outputDirectory) throws IOException { 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 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 static String getCsharpFQName(String name) { } 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 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 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. + * + *

Empty line is represented as empty string. + */ + private static List extractComments(Token token, int endLine) { + List 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 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 94d4f42f6b3..f97ebc3c6c4 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 -} - - SPECIAL_TOKEN : -{ - <("\n" | "\r" | "\r\n" )> : DEFAULT -} - - MORE : -{ - <~[]> -} - -SPECIAL_TOKEN : -{ - "/*" : WithinMultiLineComment -} - - SPECIAL_TOKEN : -{ - "*/" : DEFAULT -} - - MORE : -{ - <~[]> + +| } TOKEN : @@ -274,21 +250,32 @@ JRecord Record() : ArrayList flist = new ArrayList(); Token t; JField f; + // Get the comments on the class token + Token recordTkn; + Token typeTkn; + Token previousToken = null; } { - + recordTkn = t = { rname = t.image; } - + previousToken = ( + {typeTkn = getToken(1);} f = Field() { flist.add(f); } + { + f.setTypeToken(typeTkn); + f.setPreviousToken(previousToken); + f.setNextToken(getToken(1)); + previousToken = typeTkn; + } )+ { 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 00000000000..91eece84e17 --- /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 mRecords = getField(jFile, "mRecords", List.class); + assertEquals(1, mRecords.size()); + + JRecord jRecord = mRecords.get(0); + assertEquals("StatPersisted", jRecord.getName()); + List 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 mRecords = getField(jFile, "mRecords", List.class); + assertEquals(1, mRecords.size()); + + JRecord jRecord = mRecords.get(0); + assertEquals("StatPersisted", jRecord.getName()); + List 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 mRecords = getField(jFile, "mRecords", List.class); + assertEquals(1, mRecords.size()); + + JRecord jRecord = mRecords.get(0); + assertEquals("StatPersisted", jRecord.getName()); + List 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 mRecords = getField(jFile, "mRecords", List.class); + assertEquals(1, mRecords.size()); + + JRecord jRecord = mRecords.get(0); + assertEquals("StatPersisted", jRecord.getName()); + List 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 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 getField(final Object target, + final String fieldName, + final Class fieldClassType) throws NoSuchFieldException, IllegalAccessException { + Class targetClazz = target.getClass(); + Field field = targetClazz.getDeclaredField(fieldName); + field.setAccessible(true); + return fieldClassType.cast(field.get(target)); + } +}