internal static void DeliverSelection(IInternalActorRef anchor, IActorRef sender, ActorSelectionMessage sel)
{
if (sel.Elements.IsNullOrEmpty())
{
anchor.Tell(sel.Message, sender);
}
else
{
var iter = sel.Elements.Iterator();
Action<IInternalActorRef> rec = null;
rec = @ref => @ref.Match()
.With<ActorRefWithCell>(refWithCell =>
{
var emptyRef = new EmptyLocalActorRef(refWithCell.Provider, anchor.Path/sel.Elements.Select(el => el.ToString()), refWithCell.Underlying.System.EventStream);
iter.Next()
.Match()
.With<SelectParent>(_ =>
{
var parent = @ref.Parent;
if (iter.IsEmpty())
parent.Tell(sel.Message, sender);
else
rec(parent);
})
.With<SelectChildName>(name =>
{
var child = refWithCell.GetSingleChild(name.Name);
if (child is Nobody)
{
if (!sel.WildCardFanOut)
emptyRef.Tell(sel, sender);
}
else if (iter.IsEmpty())
{
child.Tell(sel.Message, sender);
}
else
{
rec(child);
}
})
.With<SelectChildPattern>(p =>
{
var children = refWithCell.Children;
var matchingChildren = children
.Where(c => c.Path.Name.Like(p.PatternStr))
.ToList();
if (iter.IsEmpty())
{
if(matchingChildren.Count ==0 && !sel.WildCardFanOut)
emptyRef.Tell(sel, sender);
else
matchingChildren.ForEach(child => child.Tell(sel.Message, sender));
}
else
{
if (matchingChildren.Count == 0 && !sel.WildCardFanOut)
emptyRef.Tell(sel, sender);
else
{
var m = new ActorSelectionMessage(sel.Message, iter.ToVector().ToArray(),
sel.WildCardFanOut || matchingChildren.Count > 1);
matchingChildren.ForEach(child => DeliverSelection(child as IInternalActorRef, sender, m));
}
}
});
})
.Default(_ => @ref.Tell(new ActorSelectionMessage(sel.Message, iter.ToVector().ToArray()), sender));
rec(anchor);
}
}