diff --git a/ph-diver-repo/src/main/java/com/helger/diver/repo/IRepoStorageWithToc.java b/ph-diver-repo/src/main/java/com/helger/diver/repo/IRepoStorageWithToc.java deleted file mode 100644 index b236f07..0000000 --- a/ph-diver-repo/src/main/java/com/helger/diver/repo/IRepoStorageWithToc.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.helger.diver.repo; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import com.helger.commons.annotation.Nonempty; - -/** - * Extended {@link IRepoStorage} with support for table of contents. - * - * @author Philip Helger - * @since 1.0.1 - */ -public interface IRepoStorageWithToc extends IRepoStorage -{ - /** - * Read the ToC for a single artifact - * - * @param sGroupID - * Group ID. May neither be null nor empty. - * @param sArtifactID - * Artifact ID. May neither be null nor empty. - * @return null if either group or artifact do not exist, or if - * no ToC is present. - */ - @Nullable - RepoStorageItem readToc (@Nonnull @Nonempty String sGroupID, @Nonnull @Nonempty String sArtifactID); -} diff --git a/ph-diver-repo/src/main/java/com/helger/diver/repo/RepoStorageKey.java b/ph-diver-repo/src/main/java/com/helger/diver/repo/RepoStorageKey.java index f6a8b64..12e62d0 100644 --- a/ph-diver-repo/src/main/java/com/helger/diver/repo/RepoStorageKey.java +++ b/ph-diver-repo/src/main/java/com/helger/diver/repo/RepoStorageKey.java @@ -190,6 +190,9 @@ public static RepoStorageKey of (@Nonnull final VESID aVESID, @Nonnull @Nonempty public static RepoStorageKey ofToc (@Nonnull @Nonempty final String sGroupID, @Nonnull @Nonempty final String sArtifactID) { + ValueEnforcer.notEmpty (sGroupID, "GroupID"); + ValueEnforcer.notEmpty (sArtifactID, "ArtifactID"); + // ToC per group and artifact return new RepoStorageKey (new VESID (sGroupID, sArtifactID, TOC_VERSION), getPathOfGroupIDAndArtifactID (sGroupID, sArtifactID) + FILENAME_TOC_DIVER_XML); diff --git a/ph-diver-repo/src/main/java/com/helger/diver/repo/impl/AbstractRepoStorage.java b/ph-diver-repo/src/main/java/com/helger/diver/repo/impl/AbstractRepoStorage.java index 085a006..7c4c9e6 100644 --- a/ph-diver-repo/src/main/java/com/helger/diver/repo/impl/AbstractRepoStorage.java +++ b/ph-diver-repo/src/main/java/com/helger/diver/repo/impl/AbstractRepoStorage.java @@ -37,13 +37,14 @@ import com.helger.commons.state.ESuccess; import com.helger.commons.string.ToStringGenerator; import com.helger.commons.traits.IGenericImplTrait; +import com.helger.diver.api.version.VESID; import com.helger.diver.repo.ERepoDeletable; import com.helger.diver.repo.ERepoHashState; import com.helger.diver.repo.ERepoWritable; -import com.helger.diver.repo.IRepoStorageWithToc; import com.helger.diver.repo.RepoStorageItem; import com.helger.diver.repo.RepoStorageKey; import com.helger.diver.repo.RepoStorageType; +import com.helger.diver.repo.toc.IRepoStorageWithToc; import com.helger.diver.repo.toc.RepoToc; import com.helger.diver.repo.toc.RepoToc1Marshaller; import com.helger.diver.repo.toc.jaxb.v10.RepoTocType; @@ -145,16 +146,6 @@ public final IMPLTYPE setEnableTocUpdates (final boolean b) @Nullable protected abstract InputStream getInputStream (@Nonnull final RepoStorageKey aKey); - @Nullable - public final RepoStorageItem readToc (@Nonnull @Nonempty final String sGroupID, - @Nonnull @Nonempty final String sArtifactID) - { - ValueEnforcer.notEmpty (sGroupID, "GroupID"); - ValueEnforcer.notEmpty (sArtifactID, "ArtifactID"); - - return read (RepoStorageKey.ofToc (sGroupID, sArtifactID)); - } - @Nullable public final RepoStorageItem read (@Nonnull final RepoStorageKey aKey) { @@ -341,20 +332,21 @@ public final ESuccess write (@Nonnull final RepoStorageKey aKey, { // Update ToC if (updateToc (aKey.getKeyToc (), toc -> { + final VESID aVESID = aKey.getVESID (); // Make sure a publication DT is present and always UTC final OffsetDateTime aRealPubDT = aPublicationDT != null ? aPublicationDT : PDTFactory .getCurrentOffsetDateTimeUTC (); // Add new version - if (toc.addVersion (aKey.getVESID ().getVersionObj (), aRealPubDT).isUnchanged ()) + if (toc.addVersion (aVESID.getVersionObj (), aRealPubDT).isUnchanged ()) { LOGGER.warn ("Failed to add version '" + - aKey.getVESID ().getVersionString () + - "' to ToC because it is already contained"); + aVESID.getAsSingleID () + + "' to ToC of because it is already contained"); } else { - LOGGER.info ("Successfully added version '" + aKey.getVESID ().getVersionString () + "' to ToC"); + LOGGER.info ("Successfully added version '" + aVESID.getAsSingleID () + "' to ToC"); } }).isFailure ()) return ESuccess.FAILURE; @@ -405,16 +397,17 @@ public final ESuccess delete (@Nonnull final RepoStorageKey aKey) { // Update ToC if (updateToc (aKey.getKeyToc (), toc -> { + final VESID aVESID = aKey.getVESID (); // Remove deleted version - if (toc.removeVersion (aKey.getVESID ().getVersionObj ()).isUnchanged ()) + if (toc.removeVersion (aVESID.getVersionObj ()).isUnchanged ()) { LOGGER.warn ("Failed to delete version '" + - aKey.getVESID ().getVersionString () + + aVESID.getAsSingleID () + "' from ToC because it is not contained"); } else { - LOGGER.info ("Successfully deleted version '" + aKey.getVESID ().getVersionString () + "' from ToC"); + LOGGER.info ("Successfully deleted version '" + aVESID.getAsSingleID () + "' from ToC"); } }).isFailure ()) return ESuccess.FAILURE; diff --git a/ph-diver-repo/src/main/java/com/helger/diver/repo/toc/IRepoStorageWithToc.java b/ph-diver-repo/src/main/java/com/helger/diver/repo/toc/IRepoStorageWithToc.java new file mode 100644 index 0000000..e8879c7 --- /dev/null +++ b/ph-diver-repo/src/main/java/com/helger/diver/repo/toc/IRepoStorageWithToc.java @@ -0,0 +1,97 @@ +package com.helger.diver.repo.toc; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.helger.commons.annotation.Nonempty; +import com.helger.diver.api.version.VESID; +import com.helger.diver.repo.IRepoStorage; +import com.helger.diver.repo.RepoStorageItem; +import com.helger.diver.repo.RepoStorageKey; +import com.helger.diver.repo.toc.jaxb.v10.RepoTocType; + +/** + * Extended {@link IRepoStorage} with support for table of contents. + * + * @author Philip Helger + * @since 1.0.1 + */ +public interface IRepoStorageWithToc extends IRepoStorage +{ + /** + * Test if the table of contents for the provided Group ID and Artefact ID is + * present or not. + * + * @param sGroupID + * Group ID. May neither be null nor empty. + * @param sArtifactID + * Artifact ID. May neither be null nor empty. + * @return true if it exists, false if not. + */ + default boolean existsToc (@Nonnull @Nonempty final String sGroupID, @Nonnull @Nonempty final String sArtifactID) + { + return exists (RepoStorageKey.ofToc (sGroupID, sArtifactID)); + } + + /** + * Read the ToC bytes for the provided Group ID and Artefact ID + * + * @param sGroupID + * Group ID. May neither be null nor empty. + * @param sArtifactID + * Artifact ID. May neither be null nor empty. + * @return null if either group or artifact do not exist, or if + * no ToC is present. + */ + @Nullable + default RepoStorageItem readToc (@Nonnull @Nonempty final String sGroupID, + @Nonnull @Nonempty final String sArtifactID) + { + return read (RepoStorageKey.ofToc (sGroupID, sArtifactID)); + } + + /** + * Read the ToC for the provided Group ID and Artefact ID and return the + * parsed data. + * + * @param aVESID + * VESID to take Group ID and Artifact ID from. May not be + * null. + * @return null if either group or artifact do not exist, or if + * no ToC is present. + */ + @Nullable + default RepoToc readTocModel (@Nonnull final VESID aVESID) + { + return readTocModel (aVESID.getGroupID (), aVESID.getArtifactID ()); + } + + /** + * Read the ToC for the provided Group ID and Artefact ID and return the + * parsed data. + * + * @param sGroupID + * Group ID. May neither be null nor empty. + * @param sArtifactID + * Artifact ID. May neither be null nor empty. + * @return null if either group or artifact do not exist, or if + * no ToC is present. + */ + @Nullable + default RepoToc readTocModel (@Nonnull @Nonempty final String sGroupID, @Nonnull @Nonempty final String sArtifactID) + { + // Read bytes + final RepoStorageItem aItem = readToc (sGroupID, sArtifactID); + if (aItem != null) + { + // Parse to XML + final RepoTocType aJaxbObject = new RepoToc1Marshaller ().read (aItem.data ().bytes ()); + if (aJaxbObject != null) + { + // Convert to domain model + return RepoToc.createFromJaxbObject (aJaxbObject); + } + } + return null; + } +} diff --git a/ph-diver-repo/src/test/java/com/helger/diver/repo/impl/RepoStorageInMemoryTest.java b/ph-diver-repo/src/test/java/com/helger/diver/repo/impl/RepoStorageInMemoryTest.java index ccb06f0..1301df2 100644 --- a/ph-diver-repo/src/test/java/com/helger/diver/repo/impl/RepoStorageInMemoryTest.java +++ b/ph-diver-repo/src/test/java/com/helger/diver/repo/impl/RepoStorageInMemoryTest.java @@ -35,6 +35,7 @@ import com.helger.diver.repo.ERepoWritable; import com.helger.diver.repo.RepoStorageItem; import com.helger.diver.repo.RepoStorageKey; +import com.helger.diver.repo.toc.RepoToc; /** * Test class for class {@link RepoStorageInMemory}. @@ -51,6 +52,7 @@ public void testReadWriteReadDelete () ERepoDeletable.WITH_DELETE); assertTrue (aRepo.canWrite ()); assertTrue (aRepo.canDelete ()); + assertTrue (aRepo.isEnableTocUpdates ()); final RepoStorageKey aKey = RepoStorageKey.of (new VESID ("com.ecosio", "local", "1"), ".txt"); // Ensure not existing @@ -64,6 +66,12 @@ public void testReadWriteReadDelete () ESuccess eSuccess = aRepo.write (aKey, RepoStorageItem.ofUtf8 (sUploadedPayload)); assertTrue (eSuccess.isSuccess ()); + { + final RepoToc aToc = aRepo.readTocModel (aKey.getVESID ()); + assertNotNull (aToc); + assertEquals (1, aToc.getVersionCount ()); + } + // Read again RepoStorageItem aItem = aRepo.read (aKey); assertNotNull (aItem); @@ -74,6 +82,12 @@ public void testReadWriteReadDelete () eSuccess = aRepo.delete (aKey); assertTrue (eSuccess.isSuccess ()); + { + final RepoToc aToc = aRepo.readTocModel (aKey.getVESID ()); + assertNotNull (aToc); + assertEquals (0, aToc.getVersionCount ()); + } + // Read again aItem = aRepo.read (aKey); assertNull (aItem);