From 504014bd83b7522fb107ca4daf36c7879272b6b1 Mon Sep 17 00:00:00 2001 From: Carter Cundiff Date: Fri, 13 Dec 2024 09:30:21 -0500 Subject: [PATCH] #78 Added functionality for accessing the current ModelInstanceRepository implementation outside of the GenerationContext --- .../ModelInstanceRepositoryManager.java | 32 +++++++++++++-- .../MetadataRepositoryManagerTest.java | 39 +++++++++++++++++++ 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/fermenter-mda/src/main/java/org/technologybrewery/fermenter/mda/metamodel/ModelInstanceRepositoryManager.java b/fermenter-mda/src/main/java/org/technologybrewery/fermenter/mda/metamodel/ModelInstanceRepositoryManager.java index 5d2addba..db9d11a1 100644 --- a/fermenter-mda/src/main/java/org/technologybrewery/fermenter/mda/metamodel/ModelInstanceRepositoryManager.java +++ b/fermenter-mda/src/main/java/org/technologybrewery/fermenter/mda/metamodel/ModelInstanceRepositoryManager.java @@ -10,19 +10,43 @@ public final class ModelInstanceRepositoryManager { private static ThreadLocal> threadBoundInstance = ThreadLocal.withInitial(HashMap::new); + private static final String ABSTRACT_MODEL_INSTANCE_REPOSITORY_CLASS_NAME = + "org.technologybrewery.fermenter.mda.metamodel.AbstractModelInstanceRepository"; + private ModelInstanceRepositoryManager() { // prevent private instantiation of all static class } /** - * Adds a repository. Only one repository of each type will be kept. + * Sets a repository as the repository implementation for its own class and any super + * classes if present. This enables downstream projects to safely extend upstream + * {@link ModelInstanceRepository}'s without breaking existing calls to getRepository(). + * + * For example, given the classes: + * MIR_A implements AbstractModelInstanceRepository + * MIR_B extends MIR_A + * MIR_C extends MIR_B + * + * When the repository is set using setRepository(MIR_C). Then following calls to + * getRepository would all return the MIR_C instance: + * getMetamodelRepository(MIR_A.class) -> MIR_C + * getMetamodelRepository(MIR_B.class) -> MIR_C + * getMetamodelRepository(MIR_C.class) -> MIR_C * - * @param respository + * @param repository * repository to add */ - public static void setRepository(ModelInstanceRepository respository) { + public static void setRepository(ModelInstanceRepository repository) { Map instanceMap = threadBoundInstance.get(); - instanceMap.put(respository.getClass().toString(), respository); + + instanceMap.put(repository.getClass().toString(), repository); + Class repositorySuperClass = repository.getClass().getSuperclass(); + + // Add an entry for all superclasses of the repository + while (!repositorySuperClass.getName().equals(ABSTRACT_MODEL_INSTANCE_REPOSITORY_CLASS_NAME)) { + instanceMap.put(repositorySuperClass.toString(), repository); + repositorySuperClass = repositorySuperClass.getSuperclass(); + } } /** diff --git a/fermenter-mda/src/test/java/org/technologybrewery/fermenter/mda/metamodel/MetadataRepositoryManagerTest.java b/fermenter-mda/src/test/java/org/technologybrewery/fermenter/mda/metamodel/MetadataRepositoryManagerTest.java index 509d0c9e..81939f5d 100644 --- a/fermenter-mda/src/test/java/org/technologybrewery/fermenter/mda/metamodel/MetadataRepositoryManagerTest.java +++ b/fermenter-mda/src/test/java/org/technologybrewery/fermenter/mda/metamodel/MetadataRepositoryManagerTest.java @@ -61,6 +61,27 @@ public void testOverwriteMetadataReposistory() { } + @Test + public void testMetadataRepositoryExtension() { + // Set the repository to the lowest subclass + TestMetadataRepository testRepositoryExtensionB = new TestMetadataRepositoryExtensionB(null); + ModelInstanceRepositoryManager.setRepository(testRepositoryExtensionB); + + // Get the repository extension with its superclass references + TestMetadataRepository managedTestRespository = ModelInstanceRepositoryManager + .getMetamodelRepository(TestMetadataRepository.class); + assertEquals(testRepositoryExtensionB, managedTestRespository); + + managedTestRespository = ModelInstanceRepositoryManager + .getMetamodelRepository(TestMetadataRepositoryExtensionA.class); + assertEquals(testRepositoryExtensionB, managedTestRespository); + + // Get the repository extension with its current class reference + managedTestRespository = ModelInstanceRepositoryManager + .getMetamodelRepository(TestMetadataRepositoryExtensionB.class); + assertEquals(testRepositoryExtensionB, managedTestRespository); + } + @Test public void testClearMetadataReposistoryManager() { setNewDefaultMetadataRepository(); @@ -106,3 +127,21 @@ public void validate() { } } + +/** + * Used for testing only. + */ +class TestMetadataRepositoryExtensionA extends TestMetadataRepository { + public TestMetadataRepositoryExtensionA(ModelRepositoryConfiguration config) { + super(config); + } +} + +/** + * Used for testing only. + */ +class TestMetadataRepositoryExtensionB extends TestMetadataRepositoryExtensionA { + public TestMetadataRepositoryExtensionB(ModelRepositoryConfiguration config) { + super(config); + } +}