/// <summary> /// Get the list of child streams that have \e stream as their immediate parent (basis) stream. /// </summary> /// <param name="stream">Stream to query for child streams.</param> /// <param name="includeWSpaces">\e true to include workspaces in the list that have \e stream as their backing stream.</param> /// <returns>\e true if children found and the list of child streams, \e false if no children found, or \e null on error.</returns> /*! \pre Using \e includeWSpaces to include workspaces in the list requires that all stream types be specified at AcDepot * object creation as per the \e dynamicOnly=false (default) constructor parameter. */ /*! \code * AcDepot depot = new AcDepot("MARS"); // includes workspace streams * if (!(await depot.initAsync())) return false; // operation failed, check log file * * AcStream stage = depot.getStream("MARS_STAGE"); * var children = await depot.getChildrenAsync(stage, includeWSpaces: true); * bool? res = children.Item1; * if (res == null) return false; // operation failed, check log file * * if (res == false) * Console.WriteLine("No children!"); * else * { * IList<AcStream> list = children.Item2; * foreach (AcStream child in list) * Console.WriteLine(child); * } * \endcode */ /*! \sa [AcDepot.forStreamAndAllChildrenAsync](@ref AcUtils#AcDepot#forStreamAndAllChildrenAsync) */ /*! \attention To use \e getChildrenAsync you must deploy * <a href="https://www.nuget.org/packages/Microsoft.Experimental.Collections">Microsoft.Experimental.Collections.dll</a> with your application. */ public async Task <Tuple <bool?, IList <AcStream> > > getChildrenAsync(AcStream stream, bool includeWSpaces = false) { IList <AcStream> children = null; if (stream.Type == StreamType.workspace) { return(Tuple.Create((bool?)false, children)); // workspaces don't have children } bool?ret = null; // thread safe one-time stream hierarchy initialization // see "C# Lazy Initialization && Race-to-initialize" http://stackoverflow.com/questions/11555755/c-sharp-lazy-initialization-race-to-initialize await LazyInitializer.EnsureInitialized(ref _hierarchy, ref _hierInit, ref _hierSync, async() => await getHierarchyAsync(includeWSpaces).ConfigureAwait(false)).ConfigureAwait(false); if (_hierarchy == null) { return(Tuple.Create(ret, children)); // initialization failed, check log file } IReadOnlyCollection <int> list = null; ret = _hierarchy.Result.TryGetValue(stream.ID, out list); if (ret == true) { children = new List <AcStream>(list.Count); foreach (int id in list) { AcStream child = getStream(id); children.Add(child); } } return(Tuple.Create(ret, children)); }
/// <summary> /// Get the AcStream object for stream \e name. /// </summary> /// <param name="name">Stream name to query.</param> /// <returns>AcStream object for stream \e name, otherwise \e null if not found.</returns> public AcStream getStream(string name) { AcStream stream = (from d in this from s in d.Streams.Where(n => n.Name == name) select s).SingleOrDefault(); return(stream); }
/// <summary> /// Populate this container with AcProperty objects for all streams in \e depot or just \e stream in \e depot. /// Optionally include hidden (removed) streams. /// </summary> /// <param name="depot">The depot to query for properties.</param> /// <param name="stream">The stream for a specific stream only, otherwise \e null for all streams in \e depot.</param> /// <param name="includeHidden">\e true to include properties for hidden (removed) streams, \e false otherwise.</param> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) in /// <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c getproperty command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa [AcProperties constructor](@ref AcUtils#AcProperties#AcProperties), initAsync(string, bool) */ /*! \getproperty_ <tt>getproperty \<-fx | -fix\> \<-s \<stream\> | -ks -p \<depot\>\></tt> */ public async Task <bool> initAsync(AcDepot depot, AcStream stream = null, bool includeHidden = false) { bool ret = false; // assume failure try { string cmd = null; if (stream != null && includeHidden) { cmd = $@"getproperty -fix -s ""{stream}"""; } else if (stream != null && !includeHidden) { cmd = $@"getproperty -fx -s ""{stream}"""; } else if (includeHidden) // request is for all streams in depot including those that are hidden { cmd = $@"getproperty -fix -ks -p ""{depot}"""; } else // request is for all streams except those that are hidden { cmd = $@"getproperty -fx -ks -p ""{depot}"""; } AcResult r = await AcCommand.runAsync(cmd).ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("property")) { AcProperty property = new AcProperty(); string kind = (string)e.Attribute("kind"); property.Kind = (PropKind)Enum.Parse(typeof(PropKind), kind); property.Depot = depot; property.ID = (int)e.Attribute("streamNumber"); property.Name = (string)e.Attribute("streamName"); property.PropName = (string)e.Attribute("propertyName"); property.PropValue = (string)e; lock (_locker) { Add(property); } } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcProperties.initAsync(AcDepot, AcStream, bool){Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcProperties.initAsync(AcDepot, AcStream, bool){Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Get the basis (parent) stream for stream \e ID number. /// </summary> /// <param name="ID">Stream ID number to query.</param> /// <returns>Basis AcStream object for stream \e ID number, otherwise \e null if not found.</returns> public AcStream getBasis(int ID) { AcStream basis = null; // ignore root stream (1) since it has no parent AcStream stream = _streams.Where(s => s.ID > 1).SingleOrDefault(s => s.ID == ID); if (stream != null) { basis = getStream(stream.BasisID); } return(basis); }
/// <summary> /// Populate this container with AcRule objects for \e stream as per /// [constructor parameter](@ref AcUtils#AcRules#AcRules) \e explicitOnly. /// </summary> /// <param name="stream">The stream to query for rules.</param> /// <returns>\e true if no failure occurred and list was initialized successfully, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) in /// <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c lsrules command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \lsrules_ <tt>lsrules -s \<stream\> [-d] -fx</tt> */ /*! \code * <!-- accurev lsrules -s "PG_DEV1" -fx --> * <AcResponse * Command="lscomp" * TaskId="54394"> * <element * kind="incl" * elemType="dir" * dir="yes" // Not used as its redundant. We use ElementType.Dir instead. * location="\.\Iconic" * setInStream="PG_DEV1" * xlinkToStream="IC_DEV1" * options="1"/> // Obsolete. Was used for compatibility of rules in version 4.5.3 and earlier. Will always be a value of 1. * <element * kind="incl" * elemType="dir" * dir="yes" * location="\.\" * setInStream="PlayGround" * options="1"/> * </AcResponse> * \endcode */ public async Task <bool> initAsync(AcStream stream) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync($@"lsrules -s ""{stream}"" {(_explicitOnly ? "-d" : String.Empty)} -fx") .ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("element")) { AcRule rule = new AcRule(); string kind = (string)e.Attribute("kind"); rule.Kind = (RuleKind)Enum.Parse(typeof(RuleKind), kind); string type = (string)e.Attribute("elemType"); rule.Type = (ElementType)Enum.Parse(typeof(ElementType), type); rule.Location = (string)e.Attribute("location"); rule.SetInStream = (string)e.Attribute("setInStream"); rule.XlinkToStream = (string)e.Attribute("xlinkToStream") ?? String.Empty; lock (_locker) { Add(rule); } } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcRules.initAsync(AcStream){Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcRules.initAsync(AcStream){Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Run the specified action \e cb for \e stream and all child streams in its hierarchy. /// </summary> /// <param name="stream">Top-level stream to begin the operation with.</param> /// <param name="cb">Delegate to invoke for each stream.</param> /// <param name="includeWSpaces">\e true to include workspaces in the list.</param> /// <returns>\e true if operation succeeded with no errors, \e false on error.</returns> /*! \pre Using \e includeWSpaces to include workspaces requires that all stream types be specified at AcDepot * object creation as per the \e dynamicOnly=false (default) constructor parameter. */ /*! \code * AcDepot depot = new AcDepot("NEPTUNE", dynamicOnly: true); * if (!(await depot.initAsync())) return false; // error occurred, check log file * * // list streams beginning with NEPTUNE_DEV2 and its hierarchy * AcStream stream = depot.getStream("NEPTUNE_DEV2"); * if (!(await depot.forStreamAndAllChildrenAsync(stream, n => Console.WriteLine(n)))) * return false; // .. * \endcode */ /*! \sa [AcDepot.getChildrenAsync](@ref AcUtils#AcDepot#getChildrenAsync) */ /*! \attention To use \e forStreamAndAllChildrenAsync you must deploy * <a href="https://www.nuget.org/packages/Microsoft.Experimental.Collections">Microsoft.Experimental.Collections.dll</a> with your application. */ public async Task <bool> forStreamAndAllChildrenAsync(AcStream stream, Action <AcStream> cb, bool includeWSpaces = false) { cb(stream); var children = await getChildrenAsync(stream, includeWSpaces).ConfigureAwait(false); if (children == null) { return(false); // operation failed, check log file } if (children.Item1 == null) { return(false); // .. } if (children.Item1 == true) // if children exist { foreach (AcStream child in children.Item2) { await forStreamAndAllChildrenAsync(child, cb, includeWSpaces).ConfigureAwait(false); } } return(true); }
/// <summary> /// Get the basis (parent) stream for this workspace. /// </summary> /// <returns>Basis AcStream object for this workspace or \e null if not found.</returns> public AcStream getBasis() { AcStream basis = _depot.getBasis(_id); return(basis); }
/// <summary> /// Get the AcStream object with stream \e ID number. /// </summary> /// <param name="ID">Stream ID number to query.</param> /// <returns>AcStream object for stream \e ID number or \e null if not found.</returns> public AcStream getStream(int ID) { AcStream stream = _streams.SingleOrDefault(s => s.ID == ID); return(stream); }
/// <summary> /// Get the AcStream object for stream \e name. /// </summary> /// <param name="name">Stream name to query.</param> /// <returns>AcStream object for stream \e name or \e null if not found.</returns> public AcStream getStream(string name) { AcStream stream = _streams.SingleOrDefault(s => s.Name == name); return(stream); }