public ShapeAlterationBuilder Placement(Func<ShapePlacementContext, bool> predicate, PlacementInfo location) {
     return Configure(descriptor => {
         var next = descriptor.Placement;
         descriptor.Placement = ctx => predicate(ctx) ? location : next(ctx);
     });
 }
 public ShapeAlterationBuilder Placement(Func <ShapePlacementContext, bool> predicate, PlacementInfo location)
 {
     return(Configure(descriptor =>
     {
         var next = descriptor.Placement;
         descriptor.Placement = ctx => predicate(ctx) ? location : next(ctx);
     }));
 }
        public IDictionary<string, IEnumerable<IPlacementDeclaration>> Process(string placementDeclaration)
        {
            var placements = new Dictionary<string, IEnumerable<IPlacementDeclaration>>();

            if (string.IsNullOrEmpty(placementDeclaration)) return placements;

            placementDeclaration = placementDeclaration.Trim();

            if (!placementDeclaration.StartsWith("<Placement>"))
            {
                placementDeclaration = "<Placement>" + placementDeclaration;
            }
            if (!placementDeclaration.EndsWith("</Placement>"))
            {
                placementDeclaration += "</Placement>";
            }

            var placementFile = new PlacementParser().Parse(placementDeclaration);
            if (placementFile != null)
            {
                // Invert the tree into a list of leaves and the stack
                var entries = DrillDownShapeLocations(placementFile.Nodes, Enumerable.Empty<PlacementMatch>());
                foreach (var entry in entries)
                {
                    var shapeLocation = entry.Item1;
                    var matches = entry.Item2;

                    string shapeType;
                    string differentiator;
                    GetShapeType(shapeLocation, out shapeType, out differentiator);

                    Func<ShapePlacementContext, bool> predicate = ctx => true;
                    if (differentiator != "")
                    {
                        predicate = ctx => (ctx.Differentiator ?? "") == differentiator;
                    }

                    if (matches.Any())
                    {
                        predicate = matches.SelectMany(match => match.Terms).Aggregate(predicate, BuildPredicate);
                    }

                    var placement = new PlacementInfo();

                    var segments = shapeLocation.Location.Split(';').Select(s => s.Trim());
                    foreach (var segment in segments)
                    {
                        if (!segment.Contains('='))
                        {
                            placement.Location = segment;
                        }
                        else
                        {
                            var index = segment.IndexOf('=');
                            var property = segment.Substring(0, index).ToLower();
                            var value = segment.Substring(index + 1);
                            switch (property)
                            {
                                case "shape":
                                    placement.ShapeType = value;
                                    break;
                                case "alternate":
                                    placement.Alternates = new[] { value };
                                    break;
                                case "wrapper":
                                    placement.Wrappers = new[] { value };
                                    break;
                            }
                        }
                    }

                    if (!placements.ContainsKey(shapeType))
                    {
                        placements[shapeType] = Enumerable.Empty<IPlacementDeclaration>();
                    }

                    placements[shapeType] = placements[shapeType].Concat(new[]
                    {
                        new PlacementDeclaration
                        {
                            Predicate = predicate,
                            Placement = placement
                        }
                    });
                }
            }

            return placements;
        }