19
19
import org .agrona .MutableDirectBuffer ;
20
20
import org .agrona .Strings ;
21
21
import org .agrona .Verify ;
22
- import org .agrona .generation .OutputManager ;
22
+ import org .agrona .generation .DynamicPackageOutputManager ;
23
23
import org .agrona .sbe .*;
24
24
import uk .co .real_logic .sbe .PrimitiveType ;
25
25
import uk .co .real_logic .sbe .generation .CodeGenerator ;
29
29
import java .io .IOException ;
30
30
import java .io .Writer ;
31
31
import java .util .ArrayList ;
32
+ import java .util .Collections ;
32
33
import java .util .Formatter ;
34
+ import java .util .HashSet ;
33
35
import java .util .List ;
36
+ import java .util .Set ;
34
37
import java .util .function .Function ;
35
38
36
39
import static uk .co .real_logic .sbe .SbeTool .JAVA_INTERFACE_PACKAGE ;
@@ -58,16 +61,43 @@ enum CodecType
58
61
private static final String PACKAGE_INFO = "package-info" ;
59
62
private static final String BASE_INDENT = "" ;
60
63
private static final String INDENT = " " ;
64
+ private static final Set <String > PACKAGES_EMPTY_SET = Collections .emptySet ();
61
65
62
66
private final Ir ir ;
63
- private final OutputManager outputManager ;
67
+ private final DynamicPackageOutputManager outputManager ;
64
68
private final String fqMutableBuffer ;
65
69
private final String mutableBuffer ;
66
70
private final String fqReadOnlyBuffer ;
67
71
private final String readOnlyBuffer ;
68
72
private final boolean shouldGenerateGroupOrderAnnotation ;
69
73
private final boolean shouldGenerateInterfaces ;
70
74
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
+ }
71
101
72
102
/**
73
103
* Create a new Java language {@link CodeGenerator}.
@@ -78,6 +108,7 @@ enum CodecType
78
108
* @param shouldGenerateGroupOrderAnnotation in the codecs.
79
109
* @param shouldGenerateInterfaces for common methods.
80
110
* @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding.
111
+ * @param shouldSupportTypesPackageNames generator support for types in their own package.
81
112
* @param outputManager for generating the codecs to.
82
113
*/
83
114
public JavaGenerator (
@@ -87,12 +118,14 @@ public JavaGenerator(
87
118
final boolean shouldGenerateGroupOrderAnnotation ,
88
119
final boolean shouldGenerateInterfaces ,
89
120
final boolean shouldDecodeUnknownEnumValues ,
90
- final OutputManager outputManager )
121
+ final boolean shouldSupportTypesPackageNames ,
122
+ final DynamicPackageOutputManager outputManager )
91
123
{
92
124
Verify .notNull (ir , "ir" );
93
125
Verify .notNull (outputManager , "outputManager" );
94
126
95
127
this .ir = ir ;
128
+ this .shouldSupportTypesPackageNames = shouldSupportTypesPackageNames ;
96
129
this .outputManager = outputManager ;
97
130
98
131
this .mutableBuffer = validateBufferImplementation (mutableBuffer , MutableDirectBuffer .class );
@@ -144,11 +177,36 @@ public void generateTypeStubs() throws IOException
144
177
}
145
178
}
146
179
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
+
147
204
/**
148
205
* {@inheritDoc}
149
206
*/
150
207
public void generate () throws IOException
151
208
{
209
+ packageNameByTypes .clear ();
152
210
generatePackageInfo ();
153
211
generateTypeStubs ();
154
212
generateMessageHeaderStub ();
@@ -1188,10 +1246,12 @@ private void generateBitSet(final List<Token> tokens) throws IOException
1188
1246
final List <Token > choiceList = tokens .subList (1 , tokens .size () - 1 );
1189
1247
final String implementsString = implementsInterface (Flyweight .class .getSimpleName ());
1190
1248
1249
+ registerTypesPackageName (token , ir );
1191
1250
try (Writer out = outputManager .createOutput (decoderName ))
1192
1251
{
1193
1252
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 );
1195
1255
out .append (generateChoiceIsEmpty (encoding .primitiveType ()));
1196
1256
1197
1257
new Formatter (out ).format (
@@ -1208,9 +1268,11 @@ private void generateBitSet(final List<Token> tokens) throws IOException
1208
1268
out .append ("}\n " );
1209
1269
}
1210
1270
1271
+ registerTypesPackageName (token , ir );
1211
1272
try (Writer out = outputManager .createOutput (encoderName ))
1212
1273
{
1213
- generateFixedFlyweightHeader (out , token , encoderName , implementsString , mutableBuffer , fqMutableBuffer );
1274
+ generateFixedFlyweightHeader (
1275
+ out , token , encoderName , implementsString , mutableBuffer , fqMutableBuffer , PACKAGES_EMPTY_SET );
1214
1276
generateChoiceClear (out , encoderName , token );
1215
1277
generateChoiceEncoders (out , encoderName , choiceList );
1216
1278
out .append ("}\n " );
@@ -1223,9 +1285,10 @@ private void generateFixedFlyweightHeader(
1223
1285
final String typeName ,
1224
1286
final String implementsString ,
1225
1287
final String buffer ,
1226
- final String fqBuffer ) throws IOException
1288
+ final String fqBuffer ,
1289
+ final Set <String > importedTypesPackages ) throws IOException
1227
1290
{
1228
- out .append (generateFileHeader (ir . applicableNamespace () , fqBuffer ));
1291
+ out .append (generateFileHeader (registerTypesPackageName ( token , ir ), importedTypesPackages , fqBuffer ));
1229
1292
out .append (generateDeclaration (typeName , implementsString , token ));
1230
1293
out .append (generateFixedFlyweightCode (typeName , token .encodedLength (), buffer ));
1231
1294
}
@@ -1236,9 +1299,10 @@ private void generateCompositeFlyweightHeader(
1236
1299
final Writer out ,
1237
1300
final String buffer ,
1238
1301
final String fqBuffer ,
1239
- final String implementsString ) throws IOException
1302
+ final String implementsString ,
1303
+ final Set <String > importedTypesPackages ) throws IOException
1240
1304
{
1241
- out .append (generateFileHeader (ir . applicableNamespace () , fqBuffer ));
1305
+ out .append (generateFileHeader (registerTypesPackageName ( token , ir ), importedTypesPackages , fqBuffer ));
1242
1306
out .append (generateDeclaration (typeName , implementsString , token ));
1243
1307
out .append (generateFixedFlyweightCode (typeName , token .encodedLength (), buffer ));
1244
1308
}
@@ -1249,10 +1313,11 @@ private void generateEnum(final List<Token> tokens) throws IOException
1249
1313
final String enumName = formatClassName (enumToken .applicableTypeName ());
1250
1314
final Encoding encoding = enumToken .encoding ();
1251
1315
final String nullVal = encoding .applicableNullValue ().toString ();
1316
+ final String packageName = registerTypesPackageName (enumToken , ir );
1252
1317
1253
1318
try (Writer out = outputManager .createOutput (enumName ))
1254
1319
{
1255
- out .append (generateEnumFileHeader (ir . applicableNamespace () ));
1320
+ out .append (generateEnumFileHeader (packageName ));
1256
1321
out .append (generateEnumDeclaration (enumName , enumToken ));
1257
1322
1258
1323
final List <Token > valuesList = tokens .subList (1 , tokens .size () - 1 );
@@ -1272,11 +1337,14 @@ private void generateComposite(final List<Token> tokens) throws IOException
1272
1337
final String decoderName = decoderName (compositeName );
1273
1338
final String encoderName = encoderName (compositeName );
1274
1339
1340
+ registerTypesPackageName (token , ir );
1341
+ final Set <String > importedTypesPackages = scanPackagesToImport (tokens );
1342
+
1275
1343
try (Writer out = outputManager .createOutput (decoderName ))
1276
1344
{
1277
1345
final String implementsString = implementsInterface (CompositeDecoderFlyweight .class .getSimpleName ());
1278
1346
generateCompositeFlyweightHeader (
1279
- token , decoderName , out , readOnlyBuffer , fqReadOnlyBuffer , implementsString );
1347
+ token , decoderName , out , readOnlyBuffer , fqReadOnlyBuffer , implementsString , importedTypesPackages );
1280
1348
1281
1349
for (int i = 1 , end = tokens .size () - 1 ; i < end ;)
1282
1350
{
@@ -1320,10 +1388,12 @@ private void generateComposite(final List<Token> tokens) throws IOException
1320
1388
out .append ("}\n " );
1321
1389
}
1322
1390
1391
+ registerTypesPackageName (token , ir );
1323
1392
try (Writer out = outputManager .createOutput (encoderName ))
1324
1393
{
1325
1394
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 );
1327
1397
1328
1398
for (int i = 1 , end = tokens .size () - 1 ; i < end ;)
1329
1399
{
@@ -1365,6 +1435,32 @@ private void generateComposite(final List<Token> tokens) throws IOException
1365
1435
}
1366
1436
}
1367
1437
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
+
1368
1464
private void generateChoiceClear (final Appendable out , final String bitSetClassName , final Token token )
1369
1465
throws IOException
1370
1466
{
@@ -1550,6 +1646,26 @@ private CharSequence generateEnumLookupMethod(final List<Token> tokens, final St
1550
1646
return sb ;
1551
1647
}
1552
1648
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
+
1553
1669
private String interfaceImportLine ()
1554
1670
{
1555
1671
if (!shouldGenerateInterfaces )
@@ -1560,25 +1676,32 @@ private String interfaceImportLine()
1560
1676
return "import " + JAVA_INTERFACE_PACKAGE + ".*;\n \n " ;
1561
1677
}
1562
1678
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 )
1564
1682
{
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 " +
1567
1686
"package " + packageName + ";\n \n " +
1568
1687
"import " + fqBuffer + ";\n " +
1569
- interfaceImportLine ();
1688
+ interfaceImportLine () +
1689
+ importStatements ;
1570
1690
}
1571
1691
1572
1692
private CharSequence generateMainHeader (
1573
1693
final String packageName , final CodecType codecType , final boolean hasVarData )
1574
1694
{
1695
+ final StringBuilder importStatements = generateImportStatements (packageNameByTypes , packageName );
1696
+
1575
1697
if (fqMutableBuffer .equals (fqReadOnlyBuffer ))
1576
1698
{
1577
1699
return
1578
1700
"/* Generated SBE (Simple Binary Encoding) message codec. */\n " +
1579
1701
"package " + packageName + ";\n \n " +
1580
1702
"import " + fqMutableBuffer + ";\n " +
1581
- interfaceImportLine ();
1703
+ interfaceImportLine () +
1704
+ importStatements ;
1582
1705
}
1583
1706
else
1584
1707
{
@@ -1590,7 +1713,8 @@ private CharSequence generateMainHeader(
1590
1713
"package " + packageName + ";\n \n " +
1591
1714
(hasMutableBuffer ? "import " + fqMutableBuffer + ";\n " : "" ) +
1592
1715
(hasReadOnlyBuffer ? "import " + fqReadOnlyBuffer + ";\n " : "" ) +
1593
- interfaceImportLine ();
1716
+ interfaceImportLine () +
1717
+ importStatements ;
1594
1718
}
1595
1719
}
1596
1720
@@ -3759,13 +3883,6 @@ private String decoderName(final String className)
3759
3883
3760
3884
private String implementsInterface (final String interfaceName )
3761
3885
{
3762
- if (!shouldGenerateInterfaces )
3763
- {
3764
- return "" ;
3765
- }
3766
- else
3767
- {
3768
- return " implements " + interfaceName ;
3769
- }
3886
+ return shouldGenerateInterfaces ? " implements " + interfaceName : "" ;
3770
3887
}
3771
3888
}
0 commit comments