using System; using System.Collections.Generic; using System.IO; #if NET452_OR_GREATER || NETCOREAPP using System.IO.Compression; using System.Linq; #endif namespace MPF.Processors { /// /// Represents attributes about an /// [Flags] public enum OutputFileFlags : ushort { /// /// Default state /// None = 0x0000, /// /// File is required to exist /// Required = 0x0001, /// /// File is included as an artifact /// Artifact = 0x0002, /// /// File is included as a binary artifact /// Binary = 0x0004, /// /// File can be deleted after processing /// Deleteable = 0x0008, /// /// File can be zipped after processing /// Zippable = 0x0010, } /// /// 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; #else return _flags.HasFlag(OutputFileFlags.Zippable); #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 NET452_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 == null) return false; foreach (string filename in Filenames) { // Check for invalid filenames if (string.IsNullOrEmpty(filename)) continue; try { // Check all entries on filename alone if (archive.Entries.Any(e => e.Name == filename)) return true; } catch { } } return false; } #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; } } }