Skip to content

Commit

Permalink
Improved InterfaceCodeGenerator
Browse files Browse the repository at this point in the history
- Remember all created Struct class names to prevent generating code
  using same struct class name multiple times for different structs
- Improved naming of structs by adding the parameter/argument name to
  the generated struct class (e.g. MyMethod(something) => MyMethodSomethingStruct)
  • Loading branch information
hypfvieh committed Mar 25, 2024
1 parent 0e8a16d commit 903460f
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ The library will remain open source and MIT licensed and can still be used, fork
- More Java 17 syntactic sugar, thanks to [spannm](https://github.com/spannm) ([PR#249](https://github.com/hypfvieh/dbus-java/issues/249))
- Added support for custom ClassLoader/ModuleLayer when configuring Transport (allows usage of third party transports when e.g. using JPMS) ([#251](https://github.com/hypfvieh/dbus-java/issues/251))
- Improved handling of `@DBusBoundProperty` annotation ([#253](https://github.com/hypfvieh/dbus-java/issues/253)), ([PR#252](https://github.com/hypfvieh/dbus-java/issues/252))
- Improved InterfaceCodeGenerator to handle generated struct class names properly ([#254](https://github.com/hypfvieh/dbus-java/issues/254))
- Improved InterfaceCodeGenerator to add parameter/argument name to created struct class name (e.g. MyMethod(something) => MyMethodSomethingStruct)

##### Changes in 5.0.0 (2024-01-25):
- **Updated minimum required Java version to 17**
Expand Down
12 changes: 12 additions & 0 deletions dbus-java-core/src/main/java/org/freedesktop/dbus/utils/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -693,4 +693,16 @@ public static Object[] toObjectArray(Object _obj) {
}
return ret;
}

/**
* Return a default String if input is null.
*
* @param _input input string
* @param _default default to use if input is null
*
* @return input string or default
*/
public static String defaultString(String _input, String _default) {
return _input == null ? _default : _input;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,17 @@ public class InterfaceCodeGenerator {
private final String forcePackageName;
private final boolean propertyMethods;

private final Set<String> generatedStructClassNames;

public InterfaceCodeGenerator(boolean _disableFilter, String _introspectionData, String _objectPath, String _busName, String _packageName, boolean _propertyMethods) {
disableFilter = _disableFilter;
introspectionData = _introspectionData;
nodeName = _objectPath;
busName = Util.isBlank(_busName) ? "*" : _busName;
forcePackageName = _packageName;
propertyMethods = _propertyMethods;
System.out.println(forcePackageName + "/" + propertyMethods);
generatedStructClassNames = new LinkedHashSet<>();
logger.debug("ForcePackageName: {} / PropertyMethods: {}", forcePackageName, propertyMethods);
}

/**
Expand Down Expand Up @@ -284,7 +287,8 @@ private List<ClassBuilderInfo> extractMethods(Element _methodElement, ClassBuild

if (argElm.getAttribute("type").contains("(")) { // this argument requires some sort of struct
String structPart = argElm.getAttribute("type").replaceAll("(\\(.+\\))", "$1");
String parentType = buildStructClass(structPart, methodElementName + "Struct", _clzBldr, additionalClasses);
String paramName = Util.defaultString(Util.upperCaseFirstChar(Util.snakeToCamelCase(argName)), "");
String parentType = buildStructClass(structPart, methodElementName + paramName + "Struct", _clzBldr, additionalClasses);
if (parentType != null) {
argType = parentType;
} else {
Expand Down Expand Up @@ -486,7 +490,17 @@ private String createTuple(List<MemberOrArgument> _outputArgs, String _className
* @throws DBusException on Error
*/
private String buildStructClass(String _dbusTypeStr, String _structName, ClassBuilderInfo _packageName, List<ClassBuilderInfo> _structClasses) throws DBusException {
return new StructTreeBuilder().buildStructClasses(_dbusTypeStr, _structName, _packageName, _structClasses);
String structFqcn = _packageName.getPackageName() + "." + _structName;
String structName = _structName;
if (generatedStructClassNames.contains(structFqcn)) {
while (generatedStructClassNames.contains(structFqcn)) {
structFqcn += "Struct";
structName += "Struct";
}
}
String structClassName = new StructTreeBuilder().buildStructClasses(_dbusTypeStr, structName, _packageName, _structClasses);
generatedStructClassNames.add(structFqcn);
return structClassName;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,37 @@ void testCreateSampleStructArgs() throws Exception {

assertEquals(2, analyze.size()); // class with method and struct class expected

String clzContent = analyze.get(new File("org", "ExampleMethodStruct.java"));
String clzContent = analyze.get(new File("org", "ExampleMethodExampleArgStruct.java"));

assertTrue(clzContent.contains("@Position(0)"), "Position annotation expected");
assertTrue(clzContent.contains("private final List<Integer> member0;"), "Final List<Integer> member expected");
assertTrue(clzContent.contains("public ExampleMethodStruct(List<Integer> member0)"), "Constructor using List<Integer> expected");
assertTrue(clzContent.contains("public ExampleMethodExampleArgStruct(List<Integer> member0)"), "Constructor using List<Integer> expected");
assertTrue(clzContent.contains("public List<Integer> getMember0()"), "Getter for Member of type List<Integer> expected");
}

@Test
void testCreateStructNames() throws Exception {
InterfaceCodeGenerator ci2 = loadDBusXmlFile(
new File("src/test/resources/CreateInterface/systemd/org.freedesktop.systemd1.Manager.xml"),
"/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
Map<File, String> analyze = ci2.analyze(true);

assertEquals(4, analyze.size());

String managerFileContent = analyze.get(new File("org/freedesktop/systemd1/Manager.java"));
assertTrue(managerFileContent.contains("public void StartTransientUnit(List<StartTransientUnitPropertiesStruct> properties, List<StartTransientUnitAuxStruct> aux);"));

String auxStructFileContent = analyze.get(new File("org/freedesktop/systemd1/StartTransientUnitAuxStruct.java"));
assertTrue(auxStructFileContent.contains("private final String member0;"));
assertTrue(auxStructFileContent.contains("private final List<StartTransientUnitAuxStructStruct> member1;"));

String auxStructStructFileContent = analyze.get(new File("org/freedesktop/systemd1/StartTransientUnitAuxStructStruct.java"));
assertTrue(auxStructStructFileContent.contains("private final String member0;"));
assertTrue(auxStructStructFileContent.contains("private final Variant<?> member1;"));

String propertiesStructFileContent = analyze.get(new File("org/freedesktop/systemd1/StartTransientUnitPropertiesStruct.java"));
assertTrue(propertiesStructFileContent.contains("private final String member0;"));
assertTrue(propertiesStructFileContent.contains("private final Variant<?> member1;"));

}
}

0 comments on commit 903460f

Please sign in to comment.