/***************************************************/ private static bool RemoveSubRequest(this IRequest requestTree, IRequest toRemove) { if (requestTree is LogicalNotRequest) { LogicalNotRequest logical = (LogicalNotRequest)requestTree; if (logical.Request == toRemove) { logical.Request = null; return(true); } else { return(logical.Request.RemoveSubRequest(toRemove)); } } else if (requestTree is ILogicalRequest) { ILogicalRequest logical = (ILogicalRequest)requestTree; List <IRequest> subRequests = logical.IRequests(); if (subRequests.Contains(toRemove)) { subRequests.Remove(toRemove); return(true); } else { foreach (IRequest subRequest in subRequests) { bool removed = subRequest.RemoveSubRequest(toRemove); if (removed) { return(true); } } } } return(false); }
/***************************************************/ /**** Private methods ****/ /***************************************************/ private static void Flatten(this IRequest request) { if (request is ILogicalRequest) { List <IRequest> subRequests = ((ILogicalRequest)request).IRequests(); Type type = request.GetType(); bool flattened = false; for (int i = subRequests.Count - 1; i >= 0; i--) { if (subRequests[i]?.GetType() == type && type != typeof(LogicalNotRequest)) { ILogicalRequest toRemove = (ILogicalRequest)subRequests[i]; subRequests.RemoveAt(i); subRequests.InsertRange(i, toRemove.IRequests()); flattened = true; } } if (flattened) { request.Flatten(); } else { for (int i = subRequests.Count - 1; i >= 0; i--) { IRequest subRequest = subRequests[i]; subRequest.Flatten(); ILogicalRequest logical = subRequest as ILogicalRequest; if (logical != null) { List <IRequest> subSub = logical.IRequests(); if (subSub.Count == 0) { subRequests.RemoveAt(i); } else if (subSub.Count == 1 && !(logical is LogicalNotRequest)) { if (request is LogicalNotRequest) { ((LogicalNotRequest)request).Request = subSub[0]; } else { subRequests.RemoveAt(i); if (subSub[0].GetType() == request.GetType()) { subRequests.InsertRange(i, ((ILogicalRequest)subSub[0]).IRequests()); } else { subRequests.Insert(i, subSub[0]); } } } } } } } }
/***************************************************/ /**** Private methods ****/ /***************************************************/ private static void ExtractTrees(this IRequest request, Type typeToExtract, List <IRequest> extracted, List <IRequest> history) { List <IRequest> newHistory = new List <IRequest>(history); Type type = request.GetType(); if (type == typeToExtract) { extracted.Add(request.Extract(newHistory)); IRequest last = request; for (int i = history.Count - 1; i >= 0; i--) { ILogicalRequest current = (ILogicalRequest)history[i]; if (current is LogicalNotRequest) { if (i == 0) { ((LogicalNotRequest)current).Request = null; return; } else { last = current; continue; } } else { current.IRequests().Remove(last); return; } } } newHistory.Add(request); if (request is LogicalAndRequest) { List <IRequest> subRequests = ((LogicalAndRequest)request).Requests; IRequest found = subRequests.FirstOrDefault(x => x.GetType() == typeToExtract); if (found != null) { extracted.Add(found.Extract(newHistory)); IRequest last = request; for (int i = history.Count - 1; i >= 0; i--) { ILogicalRequest current = (ILogicalRequest)history[i]; if (current is LogicalNotRequest) { if (i == 0) { ((LogicalNotRequest)current).Request = null; } else { last = current; continue; } } else { current.IRequests().Remove(last); break; } } } else { for (int i = subRequests.Count - 1; i >= 0; i--) { subRequests[i].ExtractTrees(typeToExtract, extracted, newHistory); } } } else if (request is LogicalOrRequest) { List <IRequest> subRequests = ((LogicalOrRequest)request).Requests; for (int i = subRequests.Count - 1; i >= 0; i--) { subRequests[i].ExtractTrees(typeToExtract, extracted, newHistory); } } else if (request is LogicalNotRequest) { ((LogicalNotRequest)request).Request.ExtractTrees(typeToExtract, extracted, newHistory); } }