3636@ Option (name = "Xnormalize-class" , description = "Normalize generated classes" )
3737public 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