Skip to content

Commit 3eaf972

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents 4fc4462 + e46a5e7 commit 3eaf972

File tree

14 files changed

+596
-59
lines changed

14 files changed

+596
-59
lines changed

sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
* <li><b>sbe.keyword.append.token</b>: Token to be appended to keywords.</li>
6969
* <li><b>sbe.decode.unknown.enum.values</b>: Support unknown decoded enum values. Defaults to false.</li>
7070
* <li><b>sbe.xinclude.aware</b>: Is XInclude supported for the schema. Defaults to false.</li>
71+
* <li><b>sbe.type.package.override</b>: Is package attribute for types element supported (only for JAVA). Defaults to
72+
* false.</li>
7173
* </ul>
7274
*/
7375
public class SbeTool
@@ -117,6 +119,12 @@ public class SbeTool
117119
*/
118120
public static final String XINCLUDE_AWARE = "sbe.xinclude.aware";
119121

122+
/**
123+
* Boolean system property to control the support of package names in {@code <types>} elements.
124+
* Part of SBE v2-rc3. Defaults to false.
125+
*/
126+
public static final String TYPES_PACKAGE_OVERRIDE = "sbe.types.package.override";
127+
120128
/**
121129
* Target language for generated code.
122130
*/

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package uk.co.real_logic.sbe.generation;
1717

18-
import org.agrona.generation.PackageOutputManager;
18+
import uk.co.real_logic.sbe.generation.java.JavaOutputManager;
1919
import uk.co.real_logic.sbe.generation.c.CGenerator;
2020
import uk.co.real_logic.sbe.generation.c.COutputManager;
2121
import uk.co.real_logic.sbe.generation.cpp.CppGenerator;
@@ -52,7 +52,8 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir)
5252
"true".equals(System.getProperty(JAVA_GROUP_ORDER_ANNOTATION)),
5353
"true".equals(System.getProperty(JAVA_GENERATE_INTERFACES)),
5454
"true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)),
55-
new PackageOutputManager(outputDir, ir.applicableNamespace()));
55+
"true".equals(System.getProperty(TYPES_PACKAGE_OVERRIDE)),
56+
new JavaOutputManager(outputDir, ir.applicableNamespace()));
5657
}
5758
},
5859

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java

Lines changed: 143 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import org.agrona.MutableDirectBuffer;
2020
import org.agrona.Strings;
2121
import org.agrona.Verify;
22-
import org.agrona.generation.OutputManager;
22+
import org.agrona.generation.DynamicPackageOutputManager;
2323
import org.agrona.sbe.*;
2424
import uk.co.real_logic.sbe.PrimitiveType;
2525
import uk.co.real_logic.sbe.generation.CodeGenerator;
@@ -29,8 +29,11 @@
2929
import java.io.IOException;
3030
import java.io.Writer;
3131
import java.util.ArrayList;
32+
import java.util.Collections;
3233
import java.util.Formatter;
34+
import java.util.HashSet;
3335
import java.util.List;
36+
import java.util.Set;
3437
import java.util.function.Function;
3538

3639
import static uk.co.real_logic.sbe.SbeTool.JAVA_INTERFACE_PACKAGE;
@@ -58,16 +61,43 @@ enum CodecType
5861
private static final String PACKAGE_INFO = "package-info";
5962
private static final String BASE_INDENT = "";
6063
private static final String INDENT = " ";
64+
private static final Set<String> PACKAGES_EMPTY_SET = Collections.emptySet();
6165

6266
private final Ir ir;
63-
private final OutputManager outputManager;
67+
private final DynamicPackageOutputManager outputManager;
6468
private final String fqMutableBuffer;
6569
private final String mutableBuffer;
6670
private final String fqReadOnlyBuffer;
6771
private final String readOnlyBuffer;
6872
private final boolean shouldGenerateGroupOrderAnnotation;
6973
private final boolean shouldGenerateInterfaces;
7074
private final boolean shouldDecodeUnknownEnumValues;
75+
private final boolean shouldSupportTypesPackageNames;
76+
private final Set<String> packageNameByTypes = new HashSet<>();
77+
78+
/**
79+
* Create a new Java language {@link CodeGenerator}. Generator support for types in their own package is disabled.
80+
*
81+
* @param ir for the messages and types.
82+
* @param mutableBuffer implementation used for mutating underlying buffers.
83+
* @param readOnlyBuffer implementation used for reading underlying buffers.
84+
* @param shouldGenerateGroupOrderAnnotation in the codecs.
85+
* @param shouldGenerateInterfaces for common methods.
86+
* @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding.
87+
* @param outputManager for generating the codecs to.
88+
*/
89+
public JavaGenerator(
90+
final Ir ir,
91+
final String mutableBuffer,
92+
final String readOnlyBuffer,
93+
final boolean shouldGenerateGroupOrderAnnotation,
94+
final boolean shouldGenerateInterfaces,
95+
final boolean shouldDecodeUnknownEnumValues,
96+
final DynamicPackageOutputManager outputManager)
97+
{
98+
this(ir, mutableBuffer, readOnlyBuffer, shouldGenerateGroupOrderAnnotation, shouldGenerateInterfaces,
99+
shouldDecodeUnknownEnumValues, false, outputManager);
100+
}
71101

72102
/**
73103
* Create a new Java language {@link CodeGenerator}.
@@ -78,6 +108,7 @@ enum CodecType
78108
* @param shouldGenerateGroupOrderAnnotation in the codecs.
79109
* @param shouldGenerateInterfaces for common methods.
80110
* @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding.
111+
* @param shouldSupportTypesPackageNames generator support for types in their own package.
81112
* @param outputManager for generating the codecs to.
82113
*/
83114
public JavaGenerator(
@@ -87,12 +118,14 @@ public JavaGenerator(
87118
final boolean shouldGenerateGroupOrderAnnotation,
88119
final boolean shouldGenerateInterfaces,
89120
final boolean shouldDecodeUnknownEnumValues,
90-
final OutputManager outputManager)
121+
final boolean shouldSupportTypesPackageNames,
122+
final DynamicPackageOutputManager outputManager)
91123
{
92124
Verify.notNull(ir, "ir");
93125
Verify.notNull(outputManager, "outputManager");
94126

95127
this.ir = ir;
128+
this.shouldSupportTypesPackageNames = shouldSupportTypesPackageNames;
96129
this.outputManager = outputManager;
97130

98131
this.mutableBuffer = validateBufferImplementation(mutableBuffer, MutableDirectBuffer.class);
@@ -144,11 +177,36 @@ public void generateTypeStubs() throws IOException
144177
}
145178
}
146179

180+
/**
181+
* Register the types explicit package - if set and should be supported.
182+
*
183+
* @param token the 0-th token of the type.
184+
* @param ir the intermediate representation.
185+
* @return the overridden package name of the type if set and supported, or {@link Ir#applicableNamespace()}.
186+
*/
187+
private String registerTypesPackageName(final Token token, final Ir ir)
188+
{
189+
if (!shouldSupportTypesPackageNames)
190+
{
191+
return ir.applicableNamespace();
192+
}
193+
194+
if (token.packageName() != null)
195+
{
196+
packageNameByTypes.add(token.packageName());
197+
outputManager.setPackageName(token.packageName());
198+
return token.packageName();
199+
}
200+
201+
return ir.applicableNamespace();
202+
}
203+
147204
/**
148205
* {@inheritDoc}
149206
*/
150207
public void generate() throws IOException
151208
{
209+
packageNameByTypes.clear();
152210
generatePackageInfo();
153211
generateTypeStubs();
154212
generateMessageHeaderStub();
@@ -1188,10 +1246,12 @@ private void generateBitSet(final List<Token> tokens) throws IOException
11881246
final List<Token> choiceList = tokens.subList(1, tokens.size() - 1);
11891247
final String implementsString = implementsInterface(Flyweight.class.getSimpleName());
11901248

1249+
registerTypesPackageName(token, ir);
11911250
try (Writer out = outputManager.createOutput(decoderName))
11921251
{
11931252
final Encoding encoding = token.encoding();
1194-
generateFixedFlyweightHeader(out, token, decoderName, implementsString, readOnlyBuffer, fqReadOnlyBuffer);
1253+
generateFixedFlyweightHeader(
1254+
out, token, decoderName, implementsString, readOnlyBuffer, fqReadOnlyBuffer, PACKAGES_EMPTY_SET);
11951255
out.append(generateChoiceIsEmpty(encoding.primitiveType()));
11961256

11971257
new Formatter(out).format(
@@ -1208,9 +1268,11 @@ private void generateBitSet(final List<Token> tokens) throws IOException
12081268
out.append("}\n");
12091269
}
12101270

1271+
registerTypesPackageName(token, ir);
12111272
try (Writer out = outputManager.createOutput(encoderName))
12121273
{
1213-
generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer);
1274+
generateFixedFlyweightHeader(
1275+
out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer, PACKAGES_EMPTY_SET);
12141276
generateChoiceClear(out, encoderName, token);
12151277
generateChoiceEncoders(out, encoderName, choiceList);
12161278
out.append("}\n");
@@ -1223,9 +1285,10 @@ private void generateFixedFlyweightHeader(
12231285
final String typeName,
12241286
final String implementsString,
12251287
final String buffer,
1226-
final String fqBuffer) throws IOException
1288+
final String fqBuffer,
1289+
final Set<String> importedTypesPackages) throws IOException
12271290
{
1228-
out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer));
1291+
out.append(generateFileHeader(registerTypesPackageName(token, ir), importedTypesPackages, fqBuffer));
12291292
out.append(generateDeclaration(typeName, implementsString, token));
12301293
out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer));
12311294
}
@@ -1236,9 +1299,10 @@ private void generateCompositeFlyweightHeader(
12361299
final Writer out,
12371300
final String buffer,
12381301
final String fqBuffer,
1239-
final String implementsString) throws IOException
1302+
final String implementsString,
1303+
final Set<String> importedTypesPackages) throws IOException
12401304
{
1241-
out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer));
1305+
out.append(generateFileHeader(registerTypesPackageName(token, ir), importedTypesPackages, fqBuffer));
12421306
out.append(generateDeclaration(typeName, implementsString, token));
12431307
out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer));
12441308
}
@@ -1249,10 +1313,11 @@ private void generateEnum(final List<Token> tokens) throws IOException
12491313
final String enumName = formatClassName(enumToken.applicableTypeName());
12501314
final Encoding encoding = enumToken.encoding();
12511315
final String nullVal = encoding.applicableNullValue().toString();
1316+
final String packageName = registerTypesPackageName(enumToken, ir);
12521317

12531318
try (Writer out = outputManager.createOutput(enumName))
12541319
{
1255-
out.append(generateEnumFileHeader(ir.applicableNamespace()));
1320+
out.append(generateEnumFileHeader(packageName));
12561321
out.append(generateEnumDeclaration(enumName, enumToken));
12571322

12581323
final List<Token> valuesList = tokens.subList(1, tokens.size() - 1);
@@ -1272,11 +1337,14 @@ private void generateComposite(final List<Token> tokens) throws IOException
12721337
final String decoderName = decoderName(compositeName);
12731338
final String encoderName = encoderName(compositeName);
12741339

1340+
registerTypesPackageName(token, ir);
1341+
final Set<String> importedTypesPackages = scanPackagesToImport(tokens);
1342+
12751343
try (Writer out = outputManager.createOutput(decoderName))
12761344
{
12771345
final String implementsString = implementsInterface(CompositeDecoderFlyweight.class.getSimpleName());
12781346
generateCompositeFlyweightHeader(
1279-
token, decoderName, out, readOnlyBuffer, fqReadOnlyBuffer, implementsString);
1347+
token, decoderName, out, readOnlyBuffer, fqReadOnlyBuffer, implementsString, importedTypesPackages);
12801348

12811349
for (int i = 1, end = tokens.size() - 1; i < end;)
12821350
{
@@ -1320,10 +1388,12 @@ private void generateComposite(final List<Token> tokens) throws IOException
13201388
out.append("}\n");
13211389
}
13221390

1391+
registerTypesPackageName(token, ir);
13231392
try (Writer out = outputManager.createOutput(encoderName))
13241393
{
13251394
final String implementsString = implementsInterface(CompositeEncoderFlyweight.class.getSimpleName());
1326-
generateCompositeFlyweightHeader(token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString);
1395+
generateCompositeFlyweightHeader(
1396+
token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString, importedTypesPackages);
13271397

13281398
for (int i = 1, end = tokens.size() - 1; i < end;)
13291399
{
@@ -1365,6 +1435,32 @@ private void generateComposite(final List<Token> tokens) throws IOException
13651435
}
13661436
}
13671437

1438+
private Set<String> scanPackagesToImport(final List<Token> tokens)
1439+
{
1440+
if (!shouldSupportTypesPackageNames)
1441+
{
1442+
return PACKAGES_EMPTY_SET;
1443+
}
1444+
1445+
final Set<String> packagesToImport = new HashSet<>();
1446+
1447+
for (int i = 1, limit = tokens.size() - 1; i < limit; i++)
1448+
{
1449+
final Token typeToken = tokens.get(i);
1450+
if (typeToken.signal() == Signal.BEGIN_ENUM ||
1451+
typeToken.signal() == Signal.BEGIN_SET ||
1452+
typeToken.signal() == Signal.BEGIN_COMPOSITE)
1453+
{
1454+
if (typeToken.packageName() != null)
1455+
{
1456+
packagesToImport.add(typeToken.packageName());
1457+
}
1458+
}
1459+
}
1460+
1461+
return packagesToImport;
1462+
}
1463+
13681464
private void generateChoiceClear(final Appendable out, final String bitSetClassName, final Token token)
13691465
throws IOException
13701466
{
@@ -1550,6 +1646,26 @@ private CharSequence generateEnumLookupMethod(final List<Token> tokens, final St
15501646
return sb;
15511647
}
15521648

1649+
private StringBuilder generateImportStatements(final Set<String> packages, final String currentPackage)
1650+
{
1651+
final StringBuilder importStatements = new StringBuilder();
1652+
1653+
for (final String candidatePackage : packages)
1654+
{
1655+
if (!candidatePackage.equals(currentPackage))
1656+
{
1657+
importStatements.append("import ").append(candidatePackage).append(".*;\n");
1658+
}
1659+
}
1660+
1661+
if (importStatements.length() > 0)
1662+
{
1663+
importStatements.append("\n\n");
1664+
}
1665+
1666+
return importStatements;
1667+
}
1668+
15531669
private String interfaceImportLine()
15541670
{
15551671
if (!shouldGenerateInterfaces)
@@ -1560,25 +1676,32 @@ private String interfaceImportLine()
15601676
return "import " + JAVA_INTERFACE_PACKAGE + ".*;\n\n";
15611677
}
15621678

1563-
private CharSequence generateFileHeader(final String packageName, final String fqBuffer)
1679+
1680+
private CharSequence generateFileHeader(final String packageName, final Set<String> importedTypesPackages,
1681+
final String fqBuffer)
15641682
{
1565-
return
1566-
"/* Generated SBE (Simple Binary Encoding) message codec. */\n" +
1683+
final StringBuilder importStatements = generateImportStatements(importedTypesPackages, packageName);
1684+
1685+
return "/* Generated SBE (Simple Binary Encoding) message codec. */\n" +
15671686
"package " + packageName + ";\n\n" +
15681687
"import " + fqBuffer + ";\n" +
1569-
interfaceImportLine();
1688+
interfaceImportLine() +
1689+
importStatements;
15701690
}
15711691

15721692
private CharSequence generateMainHeader(
15731693
final String packageName, final CodecType codecType, final boolean hasVarData)
15741694
{
1695+
final StringBuilder importStatements = generateImportStatements(packageNameByTypes, packageName);
1696+
15751697
if (fqMutableBuffer.equals(fqReadOnlyBuffer))
15761698
{
15771699
return
15781700
"/* Generated SBE (Simple Binary Encoding) message codec. */\n" +
15791701
"package " + packageName + ";\n\n" +
15801702
"import " + fqMutableBuffer + ";\n" +
1581-
interfaceImportLine();
1703+
interfaceImportLine() +
1704+
importStatements;
15821705
}
15831706
else
15841707
{
@@ -1590,7 +1713,8 @@ private CharSequence generateMainHeader(
15901713
"package " + packageName + ";\n\n" +
15911714
(hasMutableBuffer ? "import " + fqMutableBuffer + ";\n" : "") +
15921715
(hasReadOnlyBuffer ? "import " + fqReadOnlyBuffer + ";\n" : "") +
1593-
interfaceImportLine();
1716+
interfaceImportLine() +
1717+
importStatements;
15941718
}
15951719
}
15961720

@@ -3759,13 +3883,6 @@ private String decoderName(final String className)
37593883

37603884
private String implementsInterface(final String interfaceName)
37613885
{
3762-
if (!shouldGenerateInterfaces)
3763-
{
3764-
return "";
3765-
}
3766-
else
3767-
{
3768-
return " implements " + interfaceName;
3769-
}
3886+
return shouldGenerateInterfaces ? " implements " + interfaceName : "";
37703887
}
37713888
}

0 commit comments

Comments
 (0)