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; }
private static TimeSpan minChapterLength { get; } = TimeSpan.FromSeconds(3);
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 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)
{
Steps = new StepSequence
@ -26,6 +39,7 @@ namespace AaxDecrypter
["Step 2: Download Decrypted Audiobook"] = Step_DownloadAudiobookAsMultipleFilesPerChapter,
["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)
{
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);
FileUtility.SaferDelete(fileName);

View File

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

View File

@ -86,45 +86,39 @@ namespace FileUtilityTests
}
[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]
public void negative_partsPosition() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", -1, 2, "")
=> FileUtility.GetSequenceFormatted(-1, 2)
);
[TestMethod]
public void zero_partsPosition() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", 0, 2, "")
=> FileUtility.GetSequenceFormatted(0, 2)
);
[TestMethod]
public void negative_partsTotal() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", 2, -1, "")
=> FileUtility.GetSequenceFormatted(2, -1)
);
[TestMethod]
public void zero_partsTotal() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", 2, 0, "")
=> FileUtility.GetSequenceFormatted(2, 0)
);
[TestMethod]
public void partsPosition_greater_than_partsTotal() => Assert.ThrowsException<ArgumentException>(()
=> FileUtility.GetMultipartFileName("foo", 2, 1, "")
=> FileUtility.GetSequenceFormatted(2, 1)
);
[TestMethod]
// 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
[DataRow(@"C:\foo\bar\my file.txt", 2, 100, "title", @"C:\foo\bar\my file - 002 - title.txt")]
// no suffix
[DataRow(@"C:\foo\bar\my file.txt", 2, 100, "", @"C:\foo\bar\my file - 002 - .txt")]
public void Tests(string originalPath, int partsPosition, int partsTotal, string suffix, string expected)
=> FileUtility.GetMultipartFileName(originalPath, partsPosition, partsTotal, suffix).Should().Be(expected);
[DataRow(2, 900, "002")]
public void Tests(int partsPosition, int partsTotal, string expected)
=> FileUtility.GetSequenceFormatted(partsPosition, partsTotal).Should().Be(expected);
}
}

View File

@ -35,26 +35,22 @@ namespace FileManager
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(partsPosition, nameof(partsPosition), 0);
ArgumentValidator.EnsureGreaterThan(partsTotal, nameof(partsTotal), 0);
if (partsPosition > partsTotal)
throw new ArgumentException($"{partsPosition} may not be greater than {partsTotal}");
ArgumentValidator.EnsureGreaterThan(position, nameof(position), 0);
ArgumentValidator.EnsureGreaterThan(total, nameof(total), 0);
if (position > total)
throw new ArgumentException($"{position} may not be greater than {total}");
// 1-9 => 1-9
// 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();
return position.ToString().PadLeft(total.ToString().Length, '0');
}
private const int MAX_FILENAME_LENGTH = 255;