Skip to content

Commit ab54955

Browse files
committed
feat(normalize-class): remove empty derived classes and update superclass references
1 parent 420ce14 commit ab54955

1 file changed

Lines changed: 54 additions & 0 deletions

File tree

plugins/src/main/java/io/github/rawvoid/jaxb/plugin/NormalizeClassPlugin.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,23 @@
3636
@Option(name = "Xnormalize-class", description = "Normalize generated classes")
3737
public class NormalizeClassPlugin extends AbstractPlugin {
3838

39+
private static final String FIELD_MODS = "mods";
40+
41+
private static final java.lang.reflect.Field JMODS_MODS_FIELD = getField(JMods.class, FIELD_MODS);
42+
43+
private static java.lang.reflect.Field getField(Class<?> type, String name) {
44+
try {
45+
var field = type.getDeclaredField(name);
46+
field.setAccessible(true);
47+
return field;
48+
} catch (NoSuchFieldException ex) {
49+
throw new IllegalStateException("Failed to access field '" + name + "' on " + type.getName(), ex);
50+
}
51+
}
52+
3953
@Override
4054
public boolean run(Outline outline, Options opt, ErrorHandler errorHandler) throws SAXException {
55+
removeEmptyDerivedClasses(outline);
4156
outline.getAllPackageContexts().forEach(packageOutline -> {
4257
removeDuplicateClasses(packageOutline);
4358
});
@@ -47,6 +62,45 @@ public boolean run(Outline outline, Options opt, ErrorHandler errorHandler) thro
4762
return true;
4863
}
4964

65+
private void removeEmptyDerivedClasses(Outline outline) {
66+
var classOutlines = new ArrayList<>(outline.getClasses());
67+
classOutlines.forEach(classOutline -> {
68+
var implClass = classOutline.implClass;
69+
var superClass = implClass.superClass();
70+
if (!(superClass instanceof JDefinedClass definedSuperClass)) {
71+
return;
72+
}
73+
if (!isEmptyClass(implClass)) {
74+
return;
75+
}
76+
77+
JaxbClassRefactorUtil.removeFromParentContainer(implClass);
78+
JaxbClassRefactorUtil.removeFromObjectFactory(implClass);
79+
80+
outline.getClasses().forEach(c ->
81+
JaxbClassRefactorUtil.replaceClassReferences(c.implClass, implClass, definedSuperClass));
82+
83+
if (definedSuperClass.isAbstract()) {
84+
clearAbstractModifier(definedSuperClass.mods());
85+
}
86+
});
87+
}
88+
89+
private boolean isEmptyClass(JDefinedClass definedClass) {
90+
return definedClass.fields().isEmpty()
91+
&& definedClass.methods().isEmpty()
92+
&& !definedClass.classes().hasNext();
93+
}
94+
95+
private void clearAbstractModifier(JMods mods) {
96+
try {
97+
var flags = (int) JMODS_MODS_FIELD.get(mods);
98+
JMODS_MODS_FIELD.set(mods, flags & ~JMod.ABSTRACT);
99+
} catch (IllegalAccessException ex) {
100+
throw new IllegalStateException("Failed to clear abstract modifier", ex);
101+
}
102+
}
103+
50104
private void removeDuplicateClasses(PackageOutline packageOutline) {
51105
var classOutlines = packageOutline.getClasses();
52106
var classOutlinesGroup = classOutlines.stream()

0 commit comments

Comments
 (0)