From 50c974e6b2db7394d3f00eae7a21867f04def56e Mon Sep 17 00:00:00 2001 From: Davide Cavarretta Date: Fri, 17 Oct 2025 11:25:42 +0200 Subject: [PATCH] HBX-3170: Adds access to reveng.xml elements from Custom RevengStrategy Backport of HBX-3168 to 6.6 --- .../api/reveng/RevengStrategyFactory.java | 66 ++++++++++++++----- ...ReverseEngineeringStrategyFactoryTest.java | 49 ++++++++++++++ orm/src/test/resources/test.reveng.xml | 28 ++++++++ 3 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 orm/src/test/resources/test.reveng.xml diff --git a/orm/src/main/java/org/hibernate/tool/api/reveng/RevengStrategyFactory.java b/orm/src/main/java/org/hibernate/tool/api/reveng/RevengStrategyFactory.java index 9616683b25..54ee16db56 100644 --- a/orm/src/main/java/org/hibernate/tool/api/reveng/RevengStrategyFactory.java +++ b/orm/src/main/java/org/hibernate/tool/api/reveng/RevengStrategyFactory.java @@ -3,8 +3,12 @@ import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; import org.hibernate.tool.internal.reveng.strategy.DefaultStrategy; +import org.hibernate.tool.internal.reveng.strategy.DelegatingStrategy; import org.hibernate.tool.internal.reveng.strategy.OverrideRepository; import org.hibernate.tool.util.ReflectionUtil; @@ -15,34 +19,65 @@ public class RevengStrategyFactory { public static RevengStrategy createReverseEngineeringStrategy( String reverseEngineeringClassName) { + return createReverseEngineeringStrategy(reverseEngineeringClassName, (OverrideRepository) null); + } + + public static RevengStrategy createReverseEngineeringStrategy( + String reverseEngineeringClassName, + File[] revengFiles) { RevengStrategy result = null; + Class revengClass = getRevengClass(reverseEngineeringClassName); + if (!DelegatingStrategy.class.isAssignableFrom(revengClass)) { + result = createReverseEngineeringStrategy(reverseEngineeringClassName); + } + if (revengFiles != null && revengFiles.length > 0) { + OverrideRepository overrideRepository = new OverrideRepository(); + for (File file : revengFiles) { + overrideRepository.addFile(file); + } + if (DelegatingStrategy.class.isAssignableFrom(revengClass)) { + return createReverseEngineeringStrategy(reverseEngineeringClassName, overrideRepository); + } + result = overrideRepository.getReverseEngineeringStrategy(result); + } + return result; + } + + private static Class getRevengClass(String reverseEngineeringClassName) { try { - Class reverseEngineeringClass = - ReflectionUtil.classForName( + return ReflectionUtil.classForName( reverseEngineeringClassName == null ? DEFAULT_REVERSE_ENGINEERING_STRATEGY_CLASS_NAME : reverseEngineeringClassName); - Constructor reverseEngineeringConstructor = reverseEngineeringClass.getConstructor(new Class[] {}); - result = (RevengStrategy)reverseEngineeringConstructor.newInstance(); - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException exception) { + } catch (ClassNotFoundException exception) { throw new RuntimeException("An exporter of class '" + reverseEngineeringClassName + "' could not be created", exception); } - return result; } public static RevengStrategy createReverseEngineeringStrategy( String reverseEngineeringClassName, - File[] revengFiles) { - RevengStrategy result = - createReverseEngineeringStrategy(reverseEngineeringClassName); - if (revengFiles != null && revengFiles.length > 0) { - OverrideRepository overrideRepository = new OverrideRepository(); - for (File file : revengFiles) { - overrideRepository.addFile(file); + OverrideRepository overrideRepository) { + try { + Class reverseEngineeringClass = getRevengClass(reverseEngineeringClassName); + if (DelegatingStrategy.class.isAssignableFrom(reverseEngineeringClass)) { + Constructor[] constructors = reverseEngineeringClass.getConstructors(); + Optional> doesHasDelegateParameter = Arrays.stream(constructors).filter(item -> item.getParameterCount() == 1 && + RevengStrategy.class.isAssignableFrom(item.getParameterTypes()[0])) + .findFirst(); + if (doesHasDelegateParameter.isPresent()) { + Constructor reverseEngineeringConstructor = reverseEngineeringClass.getConstructor(new Class[] {RevengStrategy.class}); + if (Objects.nonNull(overrideRepository)) + return (RevengStrategy) reverseEngineeringConstructor.newInstance(overrideRepository.getReverseEngineeringStrategy(new DefaultStrategy())); + else + return (RevengStrategy) reverseEngineeringConstructor.newInstance(new DefaultStrategy()); + } } - result = overrideRepository.getReverseEngineeringStrategy(result); + + Constructor reverseEngineeringConstructor = reverseEngineeringClass.getConstructor(new Class[] {}); + return (RevengStrategy)reverseEngineeringConstructor.newInstance(); + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException exception) { + throw new RuntimeException("An exporter of class '" + reverseEngineeringClassName + "' could not be created", exception); } - return result; } public static RevengStrategy createReverseEngineeringStrategy() { @@ -50,3 +85,4 @@ public static RevengStrategy createReverseEngineeringStrategy() { } } + diff --git a/orm/src/test/java/org/hibernate/tool/api/reveng/ReverseEngineeringStrategyFactoryTest.java b/orm/src/test/java/org/hibernate/tool/api/reveng/ReverseEngineeringStrategyFactoryTest.java index 6ce1fd3aea..13225c2dc3 100644 --- a/orm/src/test/java/org/hibernate/tool/api/reveng/ReverseEngineeringStrategyFactoryTest.java +++ b/orm/src/test/java/org/hibernate/tool/api/reveng/ReverseEngineeringStrategyFactoryTest.java @@ -21,8 +21,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.File; +import java.net.URISyntaxException; + +import javax.management.RuntimeErrorException; + +import org.hibernate.id.insert.GetGeneratedKeysDelegate; import org.hibernate.tool.internal.reveng.strategy.DefaultStrategy; +import org.hibernate.tool.internal.reveng.strategy.DelegatingStrategy; import org.junit.jupiter.api.Test; @@ -48,8 +57,48 @@ public void testCreateReverseEngineeringStrategy() { assertEquals( DefaultStrategy.class.getName(), reverseEngineeringStrategy.getClass().getName()); + + reverseEngineeringStrategy = + RevengStrategyFactory.createReverseEngineeringStrategy(TestDelegatingReverseEngineeringStrategyFactory.class.getName()); + assertEquals( + TestDelegatingReverseEngineeringStrategyFactory.class.getName(), + reverseEngineeringStrategy.getClass().getName()); + assertEquals(DefaultStrategy.class.getName(), ((TestDelegatingReverseEngineeringStrategyFactory) reverseEngineeringStrategy).getDelegateTest().getClass().getName()); + + + try { + File file = new File(this.getClass().getResource("/test.reveng.xml").toURI()); + reverseEngineeringStrategy = + RevengStrategyFactory.createReverseEngineeringStrategy(TestDelegatingReverseEngineeringStrategyFactory.class.getName(), new File[] {file}); + assertEquals( + TestDelegatingReverseEngineeringStrategyFactory.class.getName(), + reverseEngineeringStrategy.getClass().getName()); + assertTrue(DelegatingStrategy.class.isAssignableFrom(((TestDelegatingReverseEngineeringStrategyFactory) reverseEngineeringStrategy).getDelegateTest().getClass())); + // TODO this does not keep track of the eventually DefaultStrategy. + } catch (URISyntaxException exception) { + throw new RuntimeException("Unable to load /test.reveng.xml from test resources", exception); + } + } public static class TestReverseEngineeringStrategyFactory extends DefaultStrategy {} + public static class TestDelegatingReverseEngineeringStrategyFactory extends DelegatingStrategy { + + private RevengStrategy delegateTest; + + public TestDelegatingReverseEngineeringStrategyFactory(RevengStrategy delegate) { + super(delegate); + this.delegateTest = delegate; + } + + public RevengStrategy getDelegateTest() { + return delegateTest; + } + + public void setDelegateTest(RevengStrategy delegateTest) { + this.delegateTest = delegateTest; + } + + } } diff --git a/orm/src/test/resources/test.reveng.xml b/orm/src/test/resources/test.reveng.xml new file mode 100644 index 0000000000..622b826bd2 --- /dev/null +++ b/orm/src/test/resources/test.reveng.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file