Skip to content

Commit 742cd8a

Browse files
authored
Adding support for the package attribute on the types element. (#904)
* Adding support for the package attribute on the types element. * checkstyle. * Revert accidental delete. * Change parameter order for Token. Add Javadoc. * Code style fixes. * Make QualifiedYieldTest use the new constructor. * Revert changes to test files (using custom version of StringWriterOutputManager). Should be replaced with a new version of Agrona. * Use agrone 1.17.1 * Remove @OverRide * make checkstyle happy. * Correct inherit directive.
1 parent d088c5b commit 742cd8a

File tree

13 files changed

+469
-14
lines changed

13 files changed

+469
-14
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 a 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-rc2. Defaults to false.
125+
*/
126+
public static final String TYPE_PACKAGE_OVERRIDE = "sbe.type.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(TYPE_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: 75 additions & 8 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;
@@ -30,7 +30,9 @@
3030
import java.io.Writer;
3131
import java.util.ArrayList;
3232
import java.util.Formatter;
33+
import java.util.HashSet;
3334
import java.util.List;
35+
import java.util.Set;
3436
import java.util.function.Function;
3537

3638
import static uk.co.real_logic.sbe.SbeTool.JAVA_INTERFACE_PACKAGE;
@@ -60,14 +62,40 @@ enum CodecType
6062
private static final String INDENT = " ";
6163

6264
private final Ir ir;
63-
private final OutputManager outputManager;
65+
private final DynamicPackageOutputManager outputManager;
6466
private final String fqMutableBuffer;
6567
private final String mutableBuffer;
6668
private final String fqReadOnlyBuffer;
6769
private final String readOnlyBuffer;
6870
private final boolean shouldGenerateGroupOrderAnnotation;
6971
private final boolean shouldGenerateInterfaces;
7072
private final boolean shouldDecodeUnknownEnumValues;
73+
private final boolean shouldSupportTypePackages;
74+
private final Set<String> typePackages = new HashSet<>();
75+
76+
/**
77+
* Create a new Java language {@link CodeGenerator}. Generator support for types in their own package is disabled.
78+
*
79+
* @param ir for the messages and types.
80+
* @param mutableBuffer implementation used for mutating underlying buffers.
81+
* @param readOnlyBuffer implementation used for reading underlying buffers.
82+
* @param shouldGenerateGroupOrderAnnotation in the codecs.
83+
* @param shouldGenerateInterfaces for common methods.
84+
* @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding.
85+
* @param outputManager for generating the codecs to.
86+
*/
87+
public JavaGenerator(
88+
final Ir ir,
89+
final String mutableBuffer,
90+
final String readOnlyBuffer,
91+
final boolean shouldGenerateGroupOrderAnnotation,
92+
final boolean shouldGenerateInterfaces,
93+
final boolean shouldDecodeUnknownEnumValues,
94+
final DynamicPackageOutputManager outputManager)
95+
{
96+
this(ir, mutableBuffer, readOnlyBuffer, shouldGenerateGroupOrderAnnotation, shouldGenerateInterfaces,
97+
shouldDecodeUnknownEnumValues, false, outputManager);
98+
}
7199

72100
/**
73101
* Create a new Java language {@link CodeGenerator}.
@@ -78,6 +106,7 @@ enum CodecType
78106
* @param shouldGenerateGroupOrderAnnotation in the codecs.
79107
* @param shouldGenerateInterfaces for common methods.
80108
* @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding.
109+
* @param shouldSupportTypePackages generator support for types in their own package
81110
* @param outputManager for generating the codecs to.
82111
*/
83112
public JavaGenerator(
@@ -87,12 +116,14 @@ public JavaGenerator(
87116
final boolean shouldGenerateGroupOrderAnnotation,
88117
final boolean shouldGenerateInterfaces,
89118
final boolean shouldDecodeUnknownEnumValues,
90-
final OutputManager outputManager)
119+
final boolean shouldSupportTypePackages,
120+
final DynamicPackageOutputManager outputManager)
91121
{
92122
Verify.notNull(ir, "ir");
93123
Verify.notNull(outputManager, "outputManager");
94124

95125
this.ir = ir;
126+
this.shouldSupportTypePackages = shouldSupportTypePackages;
96127
this.outputManager = outputManager;
97128

98129
this.mutableBuffer = validateBufferImplementation(mutableBuffer, MutableDirectBuffer.class);
@@ -144,11 +175,30 @@ public void generateTypeStubs() throws IOException
144175
}
145176
}
146177

178+
/**
179+
* Register the the type's explicit package - if it's set and should be supported.
180+
*
181+
* @param token the 0-th token of the type
182+
* @param ir the intermediate representation
183+
* @return the overriden package name of the type if set and supported, or {@link Ir#applicableNamespace() }
184+
*/
185+
private String registerTypePackage(final Token token, final Ir ir)
186+
{
187+
if (shouldSupportTypePackages && token.packageName() != null)
188+
{
189+
typePackages.add(token.packageName());
190+
outputManager.setPackageName(token.packageName());
191+
return token.packageName();
192+
}
193+
return ir.applicableNamespace();
194+
}
195+
147196
/**
148197
* {@inheritDoc}
149198
*/
150199
public void generate() throws IOException
151200
{
201+
typePackages.clear();
152202
generatePackageInfo();
153203
generateTypeStubs();
154204
generateMessageHeaderStub();
@@ -1188,6 +1238,7 @@ private void generateBitSet(final List<Token> tokens) throws IOException
11881238
final List<Token> choiceList = tokens.subList(1, tokens.size() - 1);
11891239
final String implementsString = implementsInterface(Flyweight.class.getSimpleName());
11901240

1241+
registerTypePackage(token, ir);
11911242
try (Writer out = outputManager.createOutput(decoderName))
11921243
{
11931244
final Encoding encoding = token.encoding();
@@ -1208,6 +1259,7 @@ private void generateBitSet(final List<Token> tokens) throws IOException
12081259
out.append("}\n");
12091260
}
12101261

1262+
registerTypePackage(token, ir);
12111263
try (Writer out = outputManager.createOutput(encoderName))
12121264
{
12131265
generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer);
@@ -1225,7 +1277,8 @@ private void generateFixedFlyweightHeader(
12251277
final String buffer,
12261278
final String fqBuffer) throws IOException
12271279
{
1228-
out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer));
1280+
final String packageName = registerTypePackage(token, ir);
1281+
out.append(generateFileHeader(packageName, fqBuffer));
12291282
out.append(generateDeclaration(typeName, implementsString, token));
12301283
out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer));
12311284
}
@@ -1238,7 +1291,8 @@ private void generateCompositeFlyweightHeader(
12381291
final String fqBuffer,
12391292
final String implementsString) throws IOException
12401293
{
1241-
out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer));
1294+
final String packageName = registerTypePackage(token, ir);
1295+
out.append(generateFileHeader(packageName, fqBuffer));
12421296
out.append(generateDeclaration(typeName, implementsString, token));
12431297
out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer));
12441298
}
@@ -1250,9 +1304,10 @@ private void generateEnum(final List<Token> tokens) throws IOException
12501304
final Encoding encoding = enumToken.encoding();
12511305
final String nullVal = encoding.applicableNullValue().toString();
12521306

1307+
final String packageName = registerTypePackage(enumToken, ir);
12531308
try (Writer out = outputManager.createOutput(enumName))
12541309
{
1255-
out.append(generateEnumFileHeader(ir.applicableNamespace()));
1310+
out.append(generateEnumFileHeader(packageName));
12561311
out.append(generateEnumDeclaration(enumName, enumToken));
12571312

12581313
final List<Token> valuesList = tokens.subList(1, tokens.size() - 1);
@@ -1272,6 +1327,7 @@ private void generateComposite(final List<Token> tokens) throws IOException
12721327
final String decoderName = decoderName(compositeName);
12731328
final String encoderName = encoderName(compositeName);
12741329

1330+
registerTypePackage(token, ir);
12751331
try (Writer out = outputManager.createOutput(decoderName))
12761332
{
12771333
final String implementsString = implementsInterface(CompositeDecoderFlyweight.class.getSimpleName());
@@ -1320,6 +1376,7 @@ private void generateComposite(final List<Token> tokens) throws IOException
13201376
out.append("}\n");
13211377
}
13221378

1379+
registerTypePackage(token, ir);
13231380
try (Writer out = outputManager.createOutput(encoderName))
13241381
{
13251382
final String implementsString = implementsInterface(CompositeEncoderFlyweight.class.getSimpleName());
@@ -1572,13 +1629,22 @@ private CharSequence generateFileHeader(final String packageName, final String f
15721629
private CharSequence generateMainHeader(
15731630
final String packageName, final CodecType codecType, final boolean hasVarData)
15741631
{
1632+
final StringBuffer packageImports = new StringBuffer();
1633+
for (final String typePackage : typePackages)
1634+
{
1635+
packageImports.append("import ");
1636+
packageImports.append(typePackage);
1637+
packageImports.append(".*;\n");
1638+
}
1639+
15751640
if (fqMutableBuffer.equals(fqReadOnlyBuffer))
15761641
{
15771642
return
15781643
"/* Generated SBE (Simple Binary Encoding) message codec. */\n" +
15791644
"package " + packageName + ";\n\n" +
15801645
"import " + fqMutableBuffer + ";\n" +
1581-
interfaceImportLine();
1646+
interfaceImportLine() +
1647+
packageImports.toString();
15821648
}
15831649
else
15841650
{
@@ -1590,7 +1656,8 @@ private CharSequence generateMainHeader(
15901656
"package " + packageName + ";\n\n" +
15911657
(hasMutableBuffer ? "import " + fqMutableBuffer + ";\n" : "") +
15921658
(hasReadOnlyBuffer ? "import " + fqReadOnlyBuffer + ";\n" : "") +
1593-
interfaceImportLine();
1659+
interfaceImportLine() +
1660+
packageImports.toString();
15941661
}
15951662
}
15961663

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2013-2022 Real Logic Limited.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package uk.co.real_logic.sbe.generation.java;
17+
18+
import java.io.FilterWriter;
19+
import java.io.IOException;
20+
import java.io.Writer;
21+
import org.agrona.collections.Object2NullableObjectHashMap;
22+
import org.agrona.collections.Object2ObjectHashMap;
23+
import org.agrona.generation.DynamicPackageOutputManager;
24+
import org.agrona.generation.PackageOutputManager;
25+
26+
/**
27+
* Implementation of {@link DynamicPackageOutputManager} for Java.
28+
*/
29+
public class JavaOutputManager implements DynamicPackageOutputManager
30+
{
31+
private final String baseDirName;
32+
private final PackageOutputManager basePackageOutputManager;
33+
private PackageOutputManager actingPackageOutputManager;
34+
private final Object2ObjectHashMap<String, PackageOutputManager> outputManagerCache
35+
= new Object2NullableObjectHashMap<>();
36+
37+
/**
38+
* Constructor.
39+
* @param baseDirName the target directory
40+
* @param packageName the initial package name
41+
*/
42+
public JavaOutputManager(final String baseDirName, final String packageName)
43+
{
44+
basePackageOutputManager = new PackageOutputManager(baseDirName, packageName);
45+
actingPackageOutputManager = basePackageOutputManager;
46+
this.baseDirName = baseDirName;
47+
}
48+
49+
/**
50+
* {@inheritDoc}
51+
*/
52+
public void setPackageName(final String packageName)
53+
{
54+
actingPackageOutputManager = outputManagerCache.get(packageName);
55+
if (actingPackageOutputManager == null)
56+
{
57+
actingPackageOutputManager = new PackageOutputManager(baseDirName, packageName);
58+
outputManagerCache.put(packageName, actingPackageOutputManager);
59+
}
60+
}
61+
62+
private void resetPackage()
63+
{
64+
actingPackageOutputManager = basePackageOutputManager;
65+
}
66+
67+
/**
68+
* {@inheritDoc}
69+
*/
70+
public Writer createOutput(final String name) throws IOException
71+
{
72+
return new FilterWriter(actingPackageOutputManager.createOutput(name))
73+
{
74+
public void close() throws IOException
75+
{
76+
super.close();
77+
resetPackage();
78+
}
79+
};
80+
}
81+
}

0 commit comments

Comments
 (0)