private static void ClearArray(JObject finalObject, IPath attributePath)
        {
            JToken        array      = (JArray)finalObject[attributePath.AttributePath];
            List <JToken> arrayItems = array.Children().ToList();

            foreach (JToken arItem in arrayItems)
            {
                if (ColumnsUtility.MatchArrayItem(arItem, attributePath))
                {
                    arItem.Remove();
                }
            }
        }
        private static void ClearObject(JToken finalObject, IPath attributePath)
        {
            //Assume that object allreay exists
            JToken token = finalObject[attributePath.AttributePath];
            IPath  nextLevelAttribute = attributePath.ValuePath;
            JToken internalProperty   = token[nextLevelAttribute.AttributePath];

            if (nextLevelAttribute.ValuePath != null)
            {
                internalProperty.Remove();
            }
            else
            {
                ColumnsUtility.ClearObject(token, nextLevelAttribute);
            }
        }
        private static void AddObject(JObject finalObject, IPath attributePath, JToken itemValue)
        {
            JObject jobject = (JObject)finalObject[attributePath.AttributePath];

            IPath nextlevelAttribe = attributePath.ValuePath;

            if (nextlevelAttribe == null)
            {
                finalObject.Add(attributePath.AttributePath, jobject);
            }
            else
            {
                JObject emptyObject = new JObject();
                finalObject.Add(attributePath.AttributePath, emptyObject);
                JToken item = itemValue[nextlevelAttribe.AttributePath];
                ColumnsUtility.AddObject(emptyObject, nextlevelAttribe, item);
            }
        }
        private static T BuildResouce <T>(IEnumerable <string> requestedAttributes, IEnumerable <string> excludedAttributes, string[] allwaysRetuned, T resource)
        {
            JObject result            = new JObject();
            Type    objectType        = resource.GetType();
            JObject projectedResrouce = JObject.FromObject(resource);

            if (!requestedAttributes.Any() && !excludedAttributes.Any())
            {
                return(resource);
            }
            foreach (string requestedAtt in requestedAttributes)
            {
                if (Path.TryParse(requestedAtt, out IPath attributePath))
                {
                    JToken itemValue = projectedResrouce[attributePath.AttributePath];
                    if (itemValue != null)
                    {
                        switch (itemValue.Type)
                        {
                        case JTokenType.Array:
                            if (!attributePath.SubAttributes.Any())
                            {
                                result.Add(attributePath.AttributePath, itemValue);
                            }
                            else
                            {
                                AddArray(result, attributePath, itemValue);
                            }
                            break;

                        case JTokenType.Object:
                            ColumnsUtility.AddObject(result, attributePath, itemValue);
                            break;

                        default:
                            result.Add(attributePath.AttributePath, itemValue);
                            break;
                        }
                    }
                }
            }

            foreach (string requestedAtt in allwaysRetuned)
            {
                if (Path.TryParse(requestedAtt, out IPath attributePath))
                {
                    JToken itemValue = projectedResrouce[attributePath.AttributePath];
                    if (itemValue != null)
                    {
                        switch (itemValue.Type)
                        {
                        case JTokenType.Array:
                            if (!attributePath.SubAttributes.Any())
                            {
                                result.Add(attributePath.AttributePath, itemValue);
                            }
                            else
                            {
                                ColumnsUtility.AddArray(result, attributePath, itemValue);
                            }
                            break;

                        case JTokenType.Object:
                            ColumnsUtility.AddObject(result, attributePath, itemValue);
                            break;

                        default:
                            result.Add(attributePath.AttributePath, itemValue);
                            break;
                        }
                    }
                }
            }

            if (!requestedAttributes.Any() && excludedAttributes.Any())
            {
                result = projectedResrouce;
            }

            foreach (string excluded in excludedAttributes)
            {
                if (Path.TryParse(excluded, out IPath attributePath))
                {
                    JToken itemValue = projectedResrouce[attributePath.AttributePath];
                    if (itemValue != null)
                    {
                        switch (itemValue.Type)
                        {
                        case JTokenType.Array:
                            if (!attributePath.SubAttributes.Any())
                            {
                                result[attributePath.AttributePath].Remove();
                            }
                            else
                            {
                                ColumnsUtility.ClearArray(result, attributePath);
                            }
                            break;

                        case JTokenType.Object:
                            if (attributePath.ValuePath == null)
                            {
                                result[attributePath.AttributePath].Remove();
                            }
                            else
                            {
                                ColumnsUtility.ClearObject(result, attributePath);
                            }
                            break;

                        default:
                            result[attributePath.AttributePath].Remove();
                            break;
                        }
                    }
                }
            }
            return((T)result.ToObject(objectType));
        }
 public static T FilterAttributes <T>(IEnumerable <string> requestedAttributes, IEnumerable <string> excludedAttributes, T projectedResouce, string[] allwaysRetuned) where T : Resource
 {
     return(ColumnsUtility.BuildResouce(requestedAttributes, excludedAttributes, allwaysRetuned, projectedResouce));
 }