Skip to content

Commit ee2c319

Browse files
authored
Merge pull request #55
refactor(normalize-class): centralize common refactor utilities into `JaxbClassRefactorUtil`
2 parents c5a67ca + 06e0c49 commit ee2c319

3 files changed

Lines changed: 417 additions & 248 deletions

File tree

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

Lines changed: 4 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@
2121
import com.sun.tools.xjc.model.CClassInfo;
2222
import com.sun.tools.xjc.outline.ClassOutline;
2323
import com.sun.tools.xjc.outline.Outline;
24-
import jakarta.xml.bind.JAXBContext;
2524
import jakarta.xml.bind.JAXBElement;
26-
import jakarta.xml.bind.JAXBException;
2725
import jakarta.xml.bind.annotation.*;
2826
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
2927
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
@@ -105,7 +103,7 @@ public boolean run(Outline outline, Options opt, ErrorHandler errorHandler) thro
105103
}
106104

107105
if (opt.debugMode) {
108-
fixJAXBDebugClass(outline);
106+
JaxbClassRefactorUtil.fixJAXBDebugClass(outline);
109107
}
110108

111109
return true;
@@ -322,135 +320,22 @@ private boolean removeWrapperClass(JDefinedClass wrapperClass, Set<JDefinedClass
322320
allClasses.removeIf(definedClass -> definedClass.equals(wrapperClass));
323321
var wrapperClassName = wrapperClass.fullName();
324322
var existsReference = allClasses.stream()
325-
.anyMatch(definedClass -> hasReference(definedClass, wrapperClassName));
323+
.anyMatch(definedClass -> JaxbClassRefactorUtil.hasReference(definedClass, wrapperClassName));
326324
if (!existsReference) {
327325
return removeWrapperClass(wrapperClass);
328326
}
329327

330328
return false;
331329
}
332330

333-
/**
334-
* Returns true if the definedClass references the classFullName.
335-
*
336-
* @param definedClass the class to check for references
337-
* @param classFullName the full name of the class to check for references
338-
* @return true if the definedClass references the classFullName
339-
*/
340-
private boolean hasReference(JDefinedClass definedClass, String classFullName) {
341-
var superClass = definedClass.superClass();
342-
var isRefBySuperClass = superClass != null && ClassNameDetector.detect(superClass.fullName(), classFullName);
343-
344-
return isRefBySuperClass
345-
|| isRefByAnnotation(definedClass, classFullName)
346-
|| definedClass.fields().values().stream()
347-
.anyMatch(field -> isRefInField(field, classFullName))
348-
349-
|| definedClass.methods().stream()
350-
.anyMatch(method -> isRefInMethod(method, classFullName));
351-
}
352-
353-
/**
354-
* Returns true if the field type or annotation references the classFullName.
355-
*/
356-
private boolean isRefInField(JFieldVar fieldVar, String classFullName) {
357-
var typeName = fieldVar.type().fullName();
358-
var isRefByType = ClassNameDetector.detect(typeName, classFullName);
359-
360-
return isRefByType || isRefByAnnotation(fieldVar, classFullName);
361-
}
362-
363-
/**
364-
* Returns true if the method return type or annotation references the classFullName.
365-
*/
366-
private boolean isRefInMethod(JMethod method, String classFullName) {
367-
var returnTypeName = method.type().fullName();
368-
var isRefByReturn = ClassNameDetector.detect(returnTypeName, classFullName);
369-
370-
return isRefByReturn || isRefByAnnotation(method, classFullName)
371-
|| method.params().stream()
372-
.anyMatch(param -> isRefInMethodParam(param, classFullName));
373-
}
374-
375-
/**
376-
* Returns true if the method parameter type or annotation references the classFullName.
377-
*/
378-
private boolean isRefInMethodParam(JVar param, String classFullName) {
379-
var typeName = param.type().fullName();
380-
var isRefByType = ClassNameDetector.detect(typeName, classFullName);
381-
382-
return isRefByType || isRefByAnnotation(param, classFullName);
383-
}
384-
385-
/**
386-
* Returns true if the annotatable contains a reference to the classFullName.
387-
*/
388-
private boolean isRefByAnnotation(JAnnotatable annotatable, String classFullName) {
389-
if (annotatable == null) {
390-
return false;
391-
}
392-
return annotatable.annotations().stream()
393-
.anyMatch(annotation -> isRefInAnnotation(annotation, classFullName));
394-
}
395-
396-
/**
397-
* Returns true if the annotation contains a reference to the classFullName.
398-
*/
399-
private boolean isRefInAnnotation(JAnnotationUse annotation, String classFullName) {
400-
if (annotation == null) {
401-
return false;
402-
}
403-
return annotation.getAnnotationMembers().values().stream().anyMatch(value -> switch (value) {
404-
case JAnnotationClassValue classValue ->
405-
ClassNameDetector.detect(classValue.type().fullName(), classFullName);
406-
case JAnnotationArrayMember arrayMember -> isRefInAnnotationArrayMember(arrayMember, classFullName);
407-
case JAnnotationUse annotationUse -> isRefInAnnotation(annotationUse, classFullName);
408-
default -> false;
409-
});
410-
}
411-
412-
/**
413-
* Returns true if the annotation array member contains a reference to the classFullName.
414-
*/
415-
private boolean isRefInAnnotationArrayMember(JAnnotationArrayMember arrayMember, String classFullName) {
416-
if (arrayMember == null) {
417-
return false;
418-
}
419-
return arrayMember.annotations2().stream().anyMatch(value -> switch (value) {
420-
case JAnnotationClassValue classValue ->
421-
ClassNameDetector.detect(classValue.type().fullName(), classFullName);
422-
case JAnnotationArrayMember subArrayMember -> isRefInAnnotationArrayMember(subArrayMember, classFullName);
423-
case JAnnotationUse annotationUse -> isRefInAnnotation(annotationUse, classFullName);
424-
default -> false;
425-
});
426-
}
427-
428331
/**
429332
* Removes the wrapper class from the parent container and ObjectFactory.
430333
*
431334
* @param wrapperClass The wrapper class to remove.
432335
*/
433336
private boolean removeWrapperClass(JDefinedClass wrapperClass) {
434-
// Remove the wrapper class from the parent container
435-
var parentContainer = wrapperClass.parentContainer();
436-
var classes = switch (parentContainer) {
437-
case JDefinedClass clazz -> clazz.classes();
438-
case JPackage jPackage -> jPackage.classes();
439-
default -> throw new IllegalArgumentException("Unknown parent container type: " + parentContainer);
440-
};
441-
while (classes.hasNext()) {
442-
if (wrapperClass.equals(classes.next())) {
443-
classes.remove();
444-
break;
445-
}
446-
}
447-
448-
// Remove the wrapper class from the ObjectFactory
449-
var jPackage = wrapperClass._package();
450-
var objectFactoryClass = jPackage._getClass("ObjectFactory");
451-
452-
objectFactoryClass.methods().removeIf(method ->
453-
ClassNameDetector.detect(method.type().fullName(), wrapperClass.fullName()));
337+
JaxbClassRefactorUtil.removeFromParentContainer(wrapperClass);
338+
JaxbClassRefactorUtil.removeFromObjectFactory(wrapperClass);
454339

455340
return true;
456341
}
@@ -565,46 +450,6 @@ private boolean isConflictingJaxbAnnotation(String className) {
565450
|| className.equals(XmlTransient.class.getName());
566451
}
567452

568-
/**
569-
* Fixes the JAXBDebug class in the JAXB outline.
570-
*
571-
* @param outline The JAXB outline to fix.
572-
*/
573-
private void fixJAXBDebugClass(Outline outline) {
574-
var model = outline.getModel();
575-
var codeModel = outline.getCodeModel();
576-
var rootPackage = codeModel.rootPackage();
577-
var jaxbDebugClass = rootPackage._getClass("JAXBDebug");
578-
if (jaxbDebugClass == null) return;
579-
580-
jaxbDebugClass.methods().removeIf(method -> method.name().equals("createContext"));
581-
582-
var createContextMethod = jaxbDebugClass.method(JMod.PUBLIC | JMod.STATIC, JAXBContext.class, "createContext");
583-
var classLoader = createContextMethod.param(ClassLoader.class, "classLoader");
584-
createContextMethod._throws(JAXBException.class);
585-
var invoke = codeModel.ref(JAXBContext.class).staticInvoke("newInstance");
586-
createContextMethod.body()._return(invoke);
587-
588-
var packageContexts = outline.getAllPackageContexts();
589-
switch (model.strategy) {
590-
case INTF_AND_IMPL -> {
591-
var joiner = new StringJoiner(":");
592-
for (var packageOutline : packageContexts) {
593-
joiner.add(packageOutline._package().name());
594-
}
595-
invoke.arg(joiner.toString()).arg(classLoader);
596-
}
597-
case BEAN_ONLY -> {
598-
for (var packageContext : packageContexts) {
599-
var jPackage = packageContext._package();
600-
jPackage.classes().forEachRemaining(classInfo -> {
601-
invoke.arg(JExpr.dotclass(classInfo));
602-
});
603-
}
604-
}
605-
default -> throw new IllegalStateException();
606-
}
607-
}
608453

609454
/**
610455
* Gets the annotation of the specified type for the given annotatable element.

0 commit comments

Comments
 (0)