using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Text.RegularExpressions; using JD.Core.ProjectManaging; using Packager.BuildConfigurations; using Packager.Parameters; namespace Packager.Tasks { public enum IOCardinality { Single, Multi } public enum IOType { File, Directory, GUID, String, } [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] public sealed class OutputAttribute : Attribute { public readonly string Name; public readonly IOType Type; public OutputAttribute(string name, IOType type) { Name = name; Type = type; } public override string ToString() { return Name; } } [DataContract(Namespace = "")] public class IORef { private string _refName; [DataMember(EmitDefaultValue = false)] public string Task { get; set; } [DataMember] public string RefName { get { if (_refName != null && _refName.StartsWith("$(DataRoot)")) { return DataPath.GetAbsolutePath(_refName.Substring("$(DataRoot)".Length)); } return _refName; } set { string relative; if (!string.IsNullOrEmpty(value) && (DataPath.ExtractRelativePath(value, out relative) || // To keep only during the transition to relative paths. DataPath.ExtractRelativePath(ProjectManager.Instance.CurrentProject.DataPath, value, out relative))) { value = @"$(DataRoot)\" + relative; } _refName = value; } } [DataMember(EmitDefaultValue = false)] public bool Distributed { get; set; } // We need a default constructor for the serialization public IORef() { } public IORef(string refFileName, bool distributed = false) { Task = null; RefName = refFileName; Distributed = distributed; } public IORef(string refName, string taskName, bool distributed = false) { Task = taskName; RefName = refName; Distributed = distributed; } private string ResolveMacro(BuildConfiguration profile, string name) { if (string.IsNullOrEmpty(name)) return name; name = Regex.Replace(name, @"\$\(Platform\)", profile.PlatformList.First(), RegexOptions.IgnoreCase); name = Regex.Replace(name, @"\$\(DataRoot\)", DataPath.Value, RegexOptions.IgnoreCase); return name; } public string[] Resolve(BuildConfiguration profile, int step, out int total) { if (Task == null) { total = 1; return new[] { ResolveMacro(profile, RefName) }; } var refTask = profile.Tasks[Task]; var outputs = refTask.GetOutputs(RefName); total = outputs.Length; return Distributed && total > 1 ? new[] { outputs[step] } : outputs; } public bool IsValid(TaskList taskList, int maxIndex) { if (Task == null) { return !string.IsNullOrEmpty(RefName); } var refTask = taskList[Task]; if (refTask == null || refTask.OrderId >= maxIndex) { return false; } var outputs = refTask.GetOutputsDesc(); return outputs.Any(o => o.Name == RefName); } } [Flags] public enum InputFlags { None, Optional } [AttributeUsage(AttributeTargets.Property)] public sealed class InputAttribute : Attribute { public readonly string DisplayName; public readonly IOCardinality Cardinality; public readonly IOType Type; public InputFlags Flags { get; set; } public InputAttribute(string displayName, IOCardinality cardinality, IOType type) { DisplayName = displayName; Cardinality = cardinality; Type = type; Flags = InputFlags.None; } } public class InputDesc { public string DisplayName { get; private set; } public IOCardinality Cardinality { get; private set; } public IOType Type { get; private set; } public InputFlags Flags { get; private set; } public string Id { get; private set; } public Reference Input { get; private set; } public Task OwnerTask { get; private set; } public InputDesc(Task owner, string id, InputAttribute attr, Reference input) { DisplayName = attr.DisplayName; Cardinality = attr.Cardinality; Type = attr.Type; Flags = attr.Flags; OwnerTask = owner; Id = id; Input = input; } } public class TaskIO : Dictionary> { } }