using System; using System.Collections.Generic; using System.IO; #if NET462_OR_GREATER || NETCOREAPP using SharpCompress.Archives; using SharpCompress.Archives.Zip; #endif namespace MPF.Processors.OutputFiles { /// /// Represents a single output file /// internal class OutputFile { /// /// Set of all filename variants /// public string[] Filenames { get; private set; } /// /// Key used when creating an artifact /// public string? ArtifactKey { get; private set; } /// /// Indicates if the file is required /// public bool IsRequired { get { #if NET20 || NET35 return (_flags & OutputFileFlags.Required) != 0; #else return _flags.HasFlag(OutputFileFlags.Required); #endif } } /// /// Indicates if the file is an artifact /// public bool IsArtifact { get { #if NET20 || NET35 return (_flags & OutputFileFlags.Artifact) != 0 || (_flags & OutputFileFlags.Binary) != 0; #else return _flags.HasFlag(OutputFileFlags.Artifact) || _flags.HasFlag(OutputFileFlags.Binary); #endif } } /// /// Indicates if the file is a binary artifact /// public bool IsBinaryArtifact { get { #if NET20 || NET35 return (_flags & OutputFileFlags.Binary) != 0; #else return _flags.HasFlag(OutputFileFlags.Binary); #endif } } /// /// Indicates if the file is deleteable after processing /// public bool IsDeleteable { get { #if NET20 || NET35 return (_flags & OutputFileFlags.Deleteable) != 0; #else return _flags.HasFlag(OutputFileFlags.Deleteable); #endif } } /// /// Indicates if the file is zippable after processing /// public bool IsZippable { get { #if NET20 || NET35 return (_flags & OutputFileFlags.Zippable) != 0 || (_flags & OutputFileFlags.Preserve) != 0; #else return _flags.HasFlag(OutputFileFlags.Zippable) || _flags.HasFlag(OutputFileFlags.Preserve); #endif } } /// /// Indicates if the file is preserved after zipping /// public bool IsPreserved { get { #if NET20 || NET35 return (_flags & OutputFileFlags.Preserve) != 0; #else return _flags.HasFlag(OutputFileFlags.Preserve); #endif } } /// /// Represents attributes about the current file /// protected readonly OutputFileFlags _flags; /// /// Create an OutputFile with a single filename /// public OutputFile(string filename, OutputFileFlags flags) : this([filename], flags) { } /// /// Create an OutputFile with a single filename /// public OutputFile(string filename, OutputFileFlags flags, string artifactKey) : this([filename], flags, artifactKey) { } /// /// Create an OutputFile with set of filenames /// public OutputFile(string[] filenames, OutputFileFlags flags) { Filenames = filenames; ArtifactKey = null; _flags = flags; // Validate the inputs if (filenames.Length == 0) throw new ArgumentException($"{nameof(filenames)} must contain at least one value"); if (IsArtifact && string.IsNullOrEmpty(ArtifactKey)) throw new ArgumentException($"{nameof(flags)} should not contain the Artifact or Binary flag"); } /// /// Create an OutputFile with set of filenames /// public OutputFile(string[] filenames, OutputFileFlags flags, string artifactKey) { Filenames = filenames; ArtifactKey = artifactKey; _flags = flags; // Validate the inputs if (filenames.Length == 0) throw new ArgumentException($"{nameof(filenames)} must contain at least one value"); if (IsArtifact && string.IsNullOrEmpty(ArtifactKey)) throw new ArgumentException($"{nameof(flags)} should not contain the Artifact or Binary flag"); } /// /// Indicates if an output file exists in a base directory /// /// Base directory to check in public virtual bool Exists(string outputDirectory) { // Ensure the directory exists if (!Directory.Exists(outputDirectory)) return false; foreach (string filename in Filenames) { // Check for invalid filenames if (string.IsNullOrEmpty(filename)) continue; try { string possibleFile = Path.Combine(outputDirectory, filename); if (File.Exists(possibleFile)) return true; } catch { } } return false; } #if NET462_OR_GREATER || NETCOREAPP /// /// Indicates if an output file exists in an archive /// /// Zip archive to check in public virtual bool Exists(ZipArchive? archive) { // If the archive is invalid if (archive is null) return false; // Get list of all files in archive foreach (var entry in archive.Entries) { if (entry.Key is null) continue; if (Array.Exists(Filenames, filename => entry.Key == filename)) return true; } return false; } /// /// Extracts an output file from a zip archive /// /// Zip archive to check in /// Base directory to extract to /// True if file extracted, False otherwise public virtual bool Extract(ZipArchive? archive, string outputDirectory) { // If the archive is invalid if (archive is null) return false; // Get list of all files in archive foreach (var entry in archive.Entries) { if (entry.Key is null) continue; var matches = Array.FindAll(Filenames, filename => entry.Key == filename); foreach (string match in matches) { try { string outputPath = Path.Combine(outputDirectory, match); entry.WriteToFile(outputPath); } catch { } } } return true; } #endif /// /// Get all matching paths for the file /// /// Base directory to check in public virtual List GetPaths(string outputDirectory) { List paths = []; foreach (string filename in Filenames) { string possibleFile = Path.Combine(outputDirectory, filename); if (!File.Exists(possibleFile)) continue; paths.Add(possibleFile); } return paths; } } }