diff --git a/src/main/java/emissary/core/IBaseDataObjectHelper.java b/src/main/java/emissary/core/IBaseDataObjectHelper.java index 5479aad5dd..ac8edd52ce 100644 --- a/src/main/java/emissary/core/IBaseDataObjectHelper.java +++ b/src/main/java/emissary/core/IBaseDataObjectHelper.java @@ -10,7 +10,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; -import java.lang.reflect.Field; import java.security.NoSuchAlgorithmException; import java.util.Collections; import java.util.Date; @@ -18,6 +17,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.UUID; import java.util.regex.Pattern; import javax.annotation.Nullable; @@ -30,6 +30,12 @@ public final class IBaseDataObjectHelper { */ private static final Logger LOGGER = LoggerFactory.getLogger(IBaseDataObjectHelper.class); + private static class InternalIdBaseDataObject extends BaseDataObject { + private InternalIdBaseDataObject(final UUID internalId) { + this.internalId = internalId; + } + } + private IBaseDataObjectHelper() {} /** @@ -44,14 +50,13 @@ private IBaseDataObjectHelper() {} public static IBaseDataObject clone(final IBaseDataObject iBaseDataObject, final boolean fullClone) { Validate.notNull(iBaseDataObject, "Required: iBaseDataObject not null"); - final BaseDataObject bdo = new BaseDataObject(); + final BaseDataObject bdo = fullClone ? new InternalIdBaseDataObject(iBaseDataObject.getInternalId()) : new BaseDataObject(); final SeekableByteChannelFactory sbcf = iBaseDataObject.getChannelFactory(); if (sbcf != null) { bdo.setChannelFactory(sbcf); } - bdo.replaceCurrentForm(null); final List allCurrentForms = iBaseDataObject.getAllCurrentForms(); for (int i = 0; i < allCurrentForms.size(); i++) { bdo.enqueueCurrentForm(allCurrentForms.get(i)); @@ -71,11 +76,6 @@ public static IBaseDataObject clone(final IBaseDataObject iBaseDataObject, final } if (fullClone) { - try { - setPrivateFieldValue(bdo, "internalId", iBaseDataObject.getInternalId()); - } catch (IllegalAccessException | NoSuchFieldException e) { - // Ignore any problems setting the internal id. - } final String processingError = iBaseDataObject.getProcessingError(); if (processingError != null) { bdo.addProcessingError(processingError.substring(0, processingError.length() - 1)); @@ -98,29 +98,6 @@ public static IBaseDataObject clone(final IBaseDataObject iBaseDataObject, final return bdo; } - /** - * This method reflectively sets a private method that is not normally accessible. This method should only be used when - * the field must be set and there is no other way to do it. Ideally the class would be modified so that this method - * call would not be necessary. - * - * @param bdo the BaseDataObject to set the field on. - * @param fieldName the name of the field to be set. - * @param object the object that the field is to be set to. - * @throws IllegalAccessException if this {@code Field} object is enforcing Java language access control and the - * underlying field is either inaccessible or final. - * @throws NoSuchFieldException if a field with the specified name is not found. - */ - public static void setPrivateFieldValue(final BaseDataObject bdo, final String fieldName, final Object object) - throws IllegalAccessException, NoSuchFieldException { - Validate.notNull(bdo, "Required: bdo not null"); - Validate.notNull(fieldName, "Required: fieldName not null"); - - final Field field = bdo.getClass().getDeclaredField(fieldName); - - field.setAccessible(true); // NOSONAR intentional visibility change - field.set(bdo, object); // NOSONAR intentional visibility change - } - /** * Used to propagate needed parent information to a sprouted child. NOTE: This is taken from * emissary.place.MultiFileServerPlace. diff --git a/src/main/java/emissary/core/IBaseDataObjectXmlHelper.java b/src/main/java/emissary/core/IBaseDataObjectXmlHelper.java index ba615c5138..446e3ab0ae 100644 --- a/src/main/java/emissary/core/IBaseDataObjectXmlHelper.java +++ b/src/main/java/emissary/core/IBaseDataObjectXmlHelper.java @@ -61,9 +61,8 @@ private IBaseDataObjectXmlHelper() {} * @param kff an existing Kff handler * @return a typical BDO with the specified data */ - public static IBaseDataObject createStandardInitialIbdo(final SeekableByteChannelFactory sbcf, + public static IBaseDataObject createStandardInitialIbdo(final IBaseDataObject ibdo, final SeekableByteChannelFactory sbcf, final String classification, final String formAndFileType, final KffDataObjectHandler kff) { - final IBaseDataObject ibdo = new BaseDataObject(); final IBaseDataObject tempIbdo = new BaseDataObject(); // We want to return the ibdo with the data field equal to null. This can only diff --git a/src/test/java/emissary/core/IBaseDataObjectHelperTest.java b/src/test/java/emissary/core/IBaseDataObjectHelperTest.java index f45e02768e..6846ce21d3 100644 --- a/src/test/java/emissary/core/IBaseDataObjectHelperTest.java +++ b/src/test/java/emissary/core/IBaseDataObjectHelperTest.java @@ -8,7 +8,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; -import org.mockito.MockedStatic; import org.mockito.Mockito; import java.io.IOException; @@ -37,7 +36,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import static org.mockito.ArgumentMatchers.any; class IBaseDataObjectHelperTest extends UnitTest { @@ -184,15 +182,6 @@ void testCloneFilename() { @Test void testCloneInternalId() { verifyClone("getInternalId", ibdo1, IS_NOT_SAME, IS_NOT_EQUALS, EQUAL_AFTER_FULL_CLONE); - // Now assert that if an exception occurs, the IDs will differ - try (MockedStatic helper = Mockito.mockStatic(IBaseDataObjectHelper.class, Mockito.CALLS_REAL_METHODS)) { - helper.when(() -> IBaseDataObjectHelper.setPrivateFieldValue(any(), any(), any())) - .thenThrow(IllegalAccessException.class); - - final IBaseDataObject cloneExceptionIbdo = IBaseDataObjectHelper.clone(ibdo1, EQUAL_AFTER_FULL_CLONE); - assertNotEquals(ibdo1.getInternalId(), cloneExceptionIbdo.getInternalId()); - // IDs will differ if an exception occurs during setPrivateField - } } @Test diff --git a/src/test/java/emissary/core/IBaseDataObjectXmlHelperTest.java b/src/test/java/emissary/core/IBaseDataObjectXmlHelperTest.java index 72b09bd923..5131b27b93 100644 --- a/src/test/java/emissary/core/IBaseDataObjectXmlHelperTest.java +++ b/src/test/java/emissary/core/IBaseDataObjectXmlHelperTest.java @@ -265,7 +265,7 @@ void testCreateStandardInitialIbdo() { expectedIbdo.setFileType(formAndFileType); expectedIbdo.setClassification(classification); - final IBaseDataObject actualIbdo = IBaseDataObjectXmlHelper.createStandardInitialIbdo(sbcf, classification, + final IBaseDataObject actualIbdo = IBaseDataObjectXmlHelper.createStandardInitialIbdo(new BaseDataObject(), sbcf, classification, formAndFileType, kff); IBaseDataObjectDiffHelper.diff(expectedIbdo, actualIbdo, differences, DiffCheckConfiguration.onlyCheckData()); diff --git a/src/test/java/emissary/test/core/junit5/RegressionTest.java b/src/test/java/emissary/test/core/junit5/RegressionTest.java index c359d9eb02..86820356d0 100644 --- a/src/test/java/emissary/test/core/junit5/RegressionTest.java +++ b/src/test/java/emissary/test/core/junit5/RegressionTest.java @@ -1,5 +1,6 @@ package emissary.test.core.junit5; +import emissary.core.BaseDataObject; import emissary.core.IBaseDataObject; import emissary.core.IBaseDataObjectHelper; import emissary.core.IBaseDataObjectXmlCodecs; @@ -71,7 +72,7 @@ protected boolean generateAnswers() { */ @ForOverride protected IBaseDataObject getInitialIbdo(final String resource) { - return RegressionTestUtil.getInitialIbdoWithFormInFilename(resource, kff); + return RegressionTestUtil.getInitialIbdoWithFormInFilename(new ClearDataBaseDataObject(), resource, kff); } /** @@ -85,7 +86,11 @@ protected IBaseDataObject getInitialIbdo(final String resource) { */ @ForOverride protected void tweakInitialIbdoBeforeSerialisation(final String resource, final IBaseDataObject initialIbdo) { - RegressionTestUtil.setDataToNull(initialIbdo); + if (initialIbdo instanceof ClearDataBaseDataObject) { + ((ClearDataBaseDataObject) initialIbdo).clearData(); + } else { + fail("Didn't get an expected type of IBaseDataObject"); + } } /** @@ -236,6 +241,13 @@ private Optional hashBytesIfNonPrintable(byte[] bytes) { // Everything above can be overridden by extending classes to modify behaviour as they see fit. // Below this point, methods should not be able to be overridden as they are inherently part of RegressionTest. + protected class ClearDataBaseDataObject extends BaseDataObject { + protected void clearData() { + theData = null; + seekableByteChannelFactory = null; + } + } + @ParameterizedTest @MethodSource("data") @Override diff --git a/src/test/java/emissary/test/core/junit5/RegressionTestUtil.java b/src/test/java/emissary/test/core/junit5/RegressionTestUtil.java index 5c4d3c498e..0f087e71f8 100644 --- a/src/test/java/emissary/test/core/junit5/RegressionTestUtil.java +++ b/src/test/java/emissary/test/core/junit5/RegressionTestUtil.java @@ -1,9 +1,7 @@ package emissary.test.core.junit5; -import emissary.core.BaseDataObject; import emissary.core.DiffCheckConfiguration; import emissary.core.IBaseDataObject; -import emissary.core.IBaseDataObjectHelper; import emissary.core.IBaseDataObjectXmlCodecs; import emissary.core.IBaseDataObjectXmlCodecs.ElementDecoders; import emissary.core.IBaseDataObjectXmlCodecs.ElementEncoders; @@ -303,24 +301,6 @@ public static String getInitialFormFromFilename(final String resource) { } } - /** - * Allow setting the internal data fields to null to avoid being included during serialisation. - * - * @param initialIbdo to null out - */ - public static void setDataToNull(final IBaseDataObject initialIbdo) { - try { - if (initialIbdo instanceof BaseDataObject) { - IBaseDataObjectHelper.setPrivateFieldValue((BaseDataObject) initialIbdo, "theData", null); - IBaseDataObjectHelper.setPrivateFieldValue((BaseDataObject) initialIbdo, "seekableByteChannelFactory", null); - } else { - fail("Didn't get an expected type of IBaseDataObject"); - } - } catch (final IllegalAccessException | NoSuchFieldException e) { - fail("Couldn't null out data for BDO", e); - } - } - /** * Simple/default way to provide the initial IBDO * @@ -329,13 +309,14 @@ public static void setDataToNull(final IBaseDataObject initialIbdo) { * @param resource path to the dat file * @return the initial IBDO */ - public static IBaseDataObject getInitialIbdoWithFormInFilename(final String resource, final KffDataObjectHandler kff) { + public static IBaseDataObject getInitialIbdoWithFormInFilename(final IBaseDataObject ibdo, final String resource, + final KffDataObjectHandler kff) { try { final Path datFileUrl = Paths.get(new ResourceReader().getResource(resource).toURI()); final InitialFinalFormFormat datFile = new InitialFinalFormFormat(datFileUrl); final SeekableByteChannelFactory sbcf = FileChannelFactory.create(datFile.getPath()); // Create a BDO for the data, and set the filename correctly - final IBaseDataObject initialIbdo = IBaseDataObjectXmlHelper.createStandardInitialIbdo(sbcf, "Classification", + final IBaseDataObject initialIbdo = IBaseDataObjectXmlHelper.createStandardInitialIbdo(ibdo, sbcf, "Classification", datFile.getInitialForm(), kff); initialIbdo.setChannelFactory(sbcf); initialIbdo.setFilename(datFile.getOriginalFileName());