Naming logic for all new files can now originate from domian logic

This commit is contained in:
Robert McRackan 2021-10-20 10:56:07 -04:00
parent 87e3075fb3
commit e4fc104afe
4 changed files with 47 additions and 40 deletions

View File

@ -12,10 +12,23 @@ namespace AaxDecrypter
{ {
protected override StepSequence Steps { get; } protected override StepSequence Steps { get; }
private Func<string, int, int, NewSplitCallback, string> multipartFileNameCallback { get; }
private static string DefaultMultipartFileName(string outputFileName, int partsPosition, int partsTotal, NewSplitCallback newSplitCallback)
{
var template = Path.ChangeExtension(outputFileName, null) + " - <chapter> - <title>" + Path.GetExtension(outputFileName);
var fileTemplate = new FileTemplate(template) { IllegalCharacterReplacements = " " };
fileTemplate.AddParameterReplacement("chapter", FileUtility.GetSequenceFormatted(partsPosition, partsTotal));
fileTemplate.AddParameterReplacement("title", newSplitCallback?.Chapter?.Title ?? "");
return fileTemplate.GetFilename();
}
private static TimeSpan minChapterLength { get; } = TimeSpan.FromSeconds(3); private static TimeSpan minChapterLength { get; } = TimeSpan.FromSeconds(3);
private List<string> multiPartFilePaths { get; } = new List<string>(); private List<string> multiPartFilePaths { get; } = new List<string>();
public AaxcDownloadMultiConverter(string outFileName, string cacheDirectory, DownloadLicense dlLic, OutputFormat outputFormat) public AaxcDownloadMultiConverter(string outFileName, string cacheDirectory, DownloadLicense dlLic, OutputFormat outputFormat,
Func<string, int, int, NewSplitCallback, string> multipartFileNameCallback = null)
: base(outFileName, cacheDirectory, dlLic, outputFormat) : base(outFileName, cacheDirectory, dlLic, outputFormat)
{ {
Steps = new StepSequence Steps = new StepSequence
@ -26,6 +39,7 @@ namespace AaxDecrypter
["Step 2: Download Decrypted Audiobook"] = Step_DownloadAudiobookAsMultipleFilesPerChapter, ["Step 2: Download Decrypted Audiobook"] = Step_DownloadAudiobookAsMultipleFilesPerChapter,
["Step 3: Cleanup"] = Step_Cleanup, ["Step 3: Cleanup"] = Step_Cleanup,
}; };
this.multipartFileNameCallback = multipartFileNameCallback ?? DefaultMultipartFileName;
} }
/* /*
@ -119,7 +133,9 @@ That naming may not be desirable for everyone, but it's an easy change to instea
private void createOutputFileStream(int currentChapter, ChapterInfo splitChapters, NewSplitCallback newSplitCallback) private void createOutputFileStream(int currentChapter, ChapterInfo splitChapters, NewSplitCallback newSplitCallback)
{ {
var fileName = FileUtility.GetMultipartFileName(OutputFileName, currentChapter, splitChapters.Count, newSplitCallback.Chapter.Title); var fileName = multipartFileNameCallback(OutputFileName, currentChapter, splitChapters.Count, newSplitCallback);
fileName = FileUtility.GetValidFilename(fileName);
multiPartFilePaths.Add(fileName); multiPartFilePaths.Add(fileName);
FileUtility.SaferDelete(fileName); FileUtility.SaferDelete(fileName);

View File

@ -46,9 +46,10 @@ namespace AaxDecrypter
throw new DirectoryNotFoundException($"Directory does not exist: {nameof(cacheDirectory)}"); throw new DirectoryNotFoundException($"Directory does not exist: {nameof(cacheDirectory)}");
cacheDir = cacheDirectory; cacheDir = cacheDirectory;
DownloadLicense = ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic));
// delete file after validation is complete // delete file after validation is complete
FileUtility.SaferDelete(OutputFileName); FileUtility.SaferDelete(OutputFileName);
DownloadLicense = ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic));
} }
public abstract void Cancel(); public abstract void Cancel();

View File

@ -86,45 +86,39 @@ namespace FileUtilityTests
} }
[TestClass] [TestClass]
public class GetMultipartFileName public class GetSequenceFormatted
{ {
[TestMethod]
public void null_path() => Assert.ThrowsException<ArgumentNullException>(() => FileUtility.GetMultipartFileName(null, 1, 1, ""));
[TestMethod]
public void null_suffix() => Tests(@"C:\foo\bar\my file.txt", 2, 100, null, @"C:\foo\bar\my file - 002 - .txt");
[TestMethod] [TestMethod]
public void negative_partsPosition() => Assert.ThrowsException<ArgumentException>(() public void negative_partsPosition() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", -1, 2, "") => FileUtility.GetSequenceFormatted(-1, 2)
); );
[TestMethod] [TestMethod]
public void zero_partsPosition() => Assert.ThrowsException<ArgumentException>(() public void zero_partsPosition() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", 0, 2, "") => FileUtility.GetSequenceFormatted(0, 2)
); );
[TestMethod] [TestMethod]
public void negative_partsTotal() => Assert.ThrowsException<ArgumentException>(() public void negative_partsTotal() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", 2, -1, "") => FileUtility.GetSequenceFormatted(2, -1)
); );
[TestMethod] [TestMethod]
public void zero_partsTotal() => Assert.ThrowsException<ArgumentException>(() public void zero_partsTotal() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", 2, 0, "") => FileUtility.GetSequenceFormatted(2, 0)
); );
[TestMethod] [TestMethod]
public void partsPosition_greater_than_partsTotal() => Assert.ThrowsException<ArgumentException>(() public void partsPosition_greater_than_partsTotal() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", 2, 1, "") => FileUtility.GetSequenceFormatted(2, 1)
); );
[TestMethod] [TestMethod]
// only part // only part
[DataRow(@"C:\foo\bar\my file.txt", 1, 1, "title", @"C:\foo\bar\my file - 1 - title.txt")] [DataRow(1, 1, "1")]
// 2 digits
[DataRow(2, 90, "02")]
// 3 digits // 3 digits
[DataRow(@"C:\foo\bar\my file.txt", 2, 100, "title", @"C:\foo\bar\my file - 002 - title.txt")] [DataRow(2, 900, "002")]
// no suffix public void Tests(int partsPosition, int partsTotal, string expected)
[DataRow(@"C:\foo\bar\my file.txt", 2, 100, "", @"C:\foo\bar\my file - 002 - .txt")] => FileUtility.GetSequenceFormatted(partsPosition, partsTotal).Should().Be(expected);
public void Tests(string originalPath, int partsPosition, int partsTotal, string suffix, string expected)
=> FileUtility.GetMultipartFileName(originalPath, partsPosition, partsTotal, suffix).Should().Be(expected);
} }
} }

View File

@ -35,26 +35,22 @@ namespace FileManager
return fileTemplate.GetFilename(); return fileTemplate.GetFilename();
} }
public static string GetMultipartFileName(string originalPath, int partsPosition, int partsTotal, string suffix) /// <summary>
/// Return position with correct number of leading zeros.
/// <br />- 2 of 9 => "2"
/// <br />- 2 of 90 => "02"
/// <br />- 2 of 900 => "002"
/// </summary>
/// <param name="position">position in sequence. The 'x' in 'x of y'</param>
/// <param name="total">total qty in sequence. The 'y' in 'x of y'</param>
public static string GetSequenceFormatted(int position, int total)
{ {
ArgumentValidator.EnsureNotNull(originalPath, nameof(originalPath)); ArgumentValidator.EnsureGreaterThan(position, nameof(position), 0);
ArgumentValidator.EnsureGreaterThan(partsPosition, nameof(partsPosition), 0); ArgumentValidator.EnsureGreaterThan(total, nameof(total), 0);
ArgumentValidator.EnsureGreaterThan(partsTotal, nameof(partsTotal), 0); if (position > total)
if (partsPosition > partsTotal) throw new ArgumentException($"{position} may not be greater than {total}");
throw new ArgumentException($"{partsPosition} may not be greater than {partsTotal}");
// 1-9 => 1-9 return position.ToString().PadLeft(total.ToString().Length, '0');
// 10-99 => 01-99
// 100-999 => 001-999
var chapterCountLeadingZeros = partsPosition.ToString().PadLeft(partsTotal.ToString().Length, '0');
var template = Path.ChangeExtension(originalPath, null) + " - <chapter> - <title>" + Path.GetExtension(originalPath);
var fileTemplate = new FileTemplate(template) { IllegalCharacterReplacements = " " };
fileTemplate.AddParameterReplacement("chapter", chapterCountLeadingZeros);
fileTemplate.AddParameterReplacement("title", suffix);
return fileTemplate.GetFilename();
} }
private const int MAX_FILENAME_LENGTH = 255; private const int MAX_FILENAME_LENGTH = 255;