2018-02-13 09:23:53 -08:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
|
// Licensed under the MIT License.
|
2016-03-30 14:20:52 -07:00
|
|
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.PowerShell.Commands.Internal.Format
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// INTERNAL IMPLEMENTATION CLASS
|
2017-01-16 13:31:14 -08:00
|
|
|
///
|
2016-03-30 14:20:52 -07:00
|
|
|
/// It manages the finite state machine for the sequence of formatting messages.
|
2016-08-26 16:46:03 -04:00
|
|
|
/// It achieves this by maintaining a stack of OutputContext-derived objects.
|
2016-03-30 14:20:52 -07:00
|
|
|
/// A predefined set of events allows the host of this class to process the information
|
|
|
|
|
/// as it comes trough the finite state machine (push model)
|
2017-01-16 13:31:14 -08:00
|
|
|
///
|
2016-08-26 16:46:03 -04:00
|
|
|
/// IMPORTANT: The code using this class will have to provide ALL the callbacks.
|
2016-03-30 14:20:52 -07:00
|
|
|
/// </summary>
|
|
|
|
|
internal class FormatMessagesContextManager
|
|
|
|
|
{
|
|
|
|
|
// callbacks declarations
|
2016-07-29 13:02:49 -07:00
|
|
|
internal delegate OutputContext FormatContextCreationCallback(OutputContext parentContext, FormatInfoData formatData);
|
|
|
|
|
internal delegate void FormatStartCallback(OutputContext c);
|
|
|
|
|
internal delegate void FormatEndCallback(FormatEndData fe, OutputContext c);
|
|
|
|
|
internal delegate void GroupStartCallback(OutputContext c);
|
|
|
|
|
internal delegate void GroupEndCallback(GroupEndData fe, OutputContext c);
|
|
|
|
|
internal delegate void PayloadCallback(FormatEntryData formatEntryData, OutputContext c);
|
2016-03-30 14:20:52 -07:00
|
|
|
|
|
|
|
|
// callback instances
|
|
|
|
|
internal FormatContextCreationCallback contextCreation = null;
|
|
|
|
|
internal FormatStartCallback fs = null;
|
|
|
|
|
internal FormatEndCallback fe = null;
|
|
|
|
|
internal GroupStartCallback gs = null;
|
|
|
|
|
internal GroupEndCallback ge = null;
|
|
|
|
|
internal PayloadCallback payload = null;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The current output context, as determined by the
|
|
|
|
|
/// sequence of formatting messages in the object stream
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal abstract class OutputContext
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="parentContextInStack">parent context in the stack, it can be null</param>
|
|
|
|
|
internal OutputContext(OutputContext parentContextInStack)
|
|
|
|
|
{
|
2016-08-02 13:29:09 -07:00
|
|
|
ParentContext = parentContextInStack;
|
2016-03-30 14:20:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// the outer context: the context object pushed onto the
|
|
|
|
|
/// stack before the current one. For the first object pushed onto
|
|
|
|
|
/// the stack it will be null
|
|
|
|
|
/// </summary>
|
2016-08-02 13:29:09 -07:00
|
|
|
internal OutputContext ParentContext { get; }
|
2016-03-30 14:20:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2017-01-16 13:31:14 -08:00
|
|
|
/// process an object from an input stream. It manages the context stack and
|
2016-03-30 14:20:52 -07:00
|
|
|
/// calls back on the specified event delegates
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="o">object to process</param>
|
2016-07-29 13:02:49 -07:00
|
|
|
internal void Process(object o)
|
2016-03-30 14:20:52 -07:00
|
|
|
{
|
|
|
|
|
PacketInfoData formatData = o as PacketInfoData;
|
|
|
|
|
FormatEntryData fed = formatData as FormatEntryData;
|
|
|
|
|
if (fed != null)
|
|
|
|
|
{
|
|
|
|
|
OutputContext ctx = null;
|
2016-07-29 13:02:49 -07:00
|
|
|
|
2016-03-30 14:20:52 -07:00
|
|
|
if (!fed.outOfBand)
|
|
|
|
|
{
|
2016-07-29 13:02:49 -07:00
|
|
|
ctx = _stack.Peek();
|
2016-03-30 14:20:52 -07:00
|
|
|
}
|
|
|
|
|
// notify for Payload
|
|
|
|
|
this.payload(fed, ctx);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bool formatDataIsFormatStartData = formatData is FormatStartData;
|
|
|
|
|
bool formatDataIsGroupStartData = formatData is GroupStartData;
|
|
|
|
|
// it's one of our formatting messages
|
|
|
|
|
// we assume for the moment that they are in the correct sequence
|
|
|
|
|
if (formatDataIsFormatStartData || formatDataIsGroupStartData)
|
|
|
|
|
{
|
2016-07-29 13:02:49 -07:00
|
|
|
OutputContext oc = this.contextCreation(this.ActiveOutputContext, formatData);
|
|
|
|
|
_stack.Push(oc);
|
2016-03-30 14:20:52 -07:00
|
|
|
|
2017-01-16 13:31:14 -08:00
|
|
|
// now we have the context properly set: need to notify the
|
2016-03-30 14:20:52 -07:00
|
|
|
// underlying algorithm to do the start document or group stuff
|
|
|
|
|
if (formatDataIsFormatStartData)
|
|
|
|
|
{
|
|
|
|
|
// notify for Fs
|
|
|
|
|
this.fs(oc);
|
|
|
|
|
}
|
|
|
|
|
else if (formatDataIsGroupStartData)
|
|
|
|
|
{
|
|
|
|
|
//GroupStartData gsd = (GroupStartData) formatData;
|
|
|
|
|
// notify for Gs
|
|
|
|
|
this.gs(oc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GroupEndData ged = formatData as GroupEndData;
|
|
|
|
|
FormatEndData fEndd = formatData as FormatEndData;
|
|
|
|
|
if (ged != null || fEndd != null)
|
|
|
|
|
{
|
2016-07-29 13:02:49 -07:00
|
|
|
OutputContext oc = _stack.Peek();
|
2016-03-30 14:20:52 -07:00
|
|
|
if (fEndd != null)
|
|
|
|
|
{
|
|
|
|
|
// notify for Fe, passing the Fe info, before a Pop()
|
|
|
|
|
this.fe(fEndd, oc);
|
|
|
|
|
}
|
|
|
|
|
else if (ged != null)
|
|
|
|
|
{
|
|
|
|
|
// notify for Fe, passing the Fe info, before a Pop()
|
|
|
|
|
this.ge(ged, oc);
|
|
|
|
|
}
|
2016-07-29 13:02:49 -07:00
|
|
|
_stack.Pop();
|
2016-03-30 14:20:52 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// access the active context (top of the stack). It can be null.
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal OutputContext ActiveOutputContext
|
2016-07-29 13:02:49 -07:00
|
|
|
{
|
|
|
|
|
get { return (_stack.Count > 0) ? _stack.Peek() : null; }
|
2016-03-30 14:20:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// internal stack to manage context
|
|
|
|
|
/// </summary>
|
2016-07-29 13:02:49 -07:00
|
|
|
private Stack<OutputContext> _stack = new Stack<OutputContext>();
|
2016-03-30 14:20:52 -07:00
|
|
|
}
|
|
|
|
|
}
|