/// <summary>
        /// Set up the pipeline and flow data with an element which contains
        /// properties which can used to test the GetWhere method.
        /// </summary>
        private void ConfigureGetWhere()
        {
            // Mock the element
            var element1 = new Mock <IFlowElement>();

            element1.SetupGet(e => e.ElementDataKey).Returns("element1");
            // Set up the properties
            element1.SetupGet(e => e.Properties).Returns(
                new List <IElementPropertyMetaData>()
            {
                new ElementPropertyMetaData(element1.Object, "available", typeof(string), true, "category"),
                new ElementPropertyMetaData(element1.Object, "anotheravailable", typeof(string), true, "category"),
                new ElementPropertyMetaData(element1.Object, "unavailable", typeof(string), false, "category"),
                new ElementPropertyMetaData(element1.Object, "differentcategory", typeof(string), true, "another category"),
                new ElementPropertyMetaData(element1.Object, "nocategory", typeof(string), true)
            });
            // Set up the values for the available properties
            DictionaryElementData elementData1 = new DictionaryElementData(new TestLogger <DictionaryElementData>(), _pipeline.Object);

            elementData1["available"]         = "a value";
            elementData1["anotheravailable"]  = "a value";
            elementData1["differentcategory"] = "a value";
            elementData1["nocategory"]        = "a value";
            // Set up the process method to add the values to the flow data
            _pipeline.Setup(p => p.Process(It.IsAny <IFlowData>()))
            .Callback((IFlowData data) =>
            {
                data.GetOrAdd("element1", (p) => elementData1);
            });
            // Set up the element in the pipeline
            _pipeline.SetupGet(i => i.FlowElements).Returns(new List <IFlowElement>()
            {
                element1.Object
            });
        }
        /// <summary>
        /// Set up the pipeline and flow data with an element which contains
        /// properties which can used to test the GetWhere method.
        /// </summary>
        private void ConfigureGetWhere(bool includePropertyWithException = false)
        {
            // Mock the element
            var element1 = new Mock <IFlowElement>();

            element1.SetupGet(e => e.ElementDataKey).Returns("element1");
            // Set up the properties
            var propertyMetaData =
                new List <IElementPropertyMetaData>()
            {
                new ElementPropertyMetaData(element1.Object, "available", typeof(string), true, "category"),
                new ElementPropertyMetaData(element1.Object, "anotheravailable", typeof(string), true, "category"),
                new ElementPropertyMetaData(element1.Object, "unavailable", typeof(string), false, "category"),
                new ElementPropertyMetaData(element1.Object, "differentcategory", typeof(string), true, "another category"),
                new ElementPropertyMetaData(element1.Object, "nocategory", typeof(string), true)
            };

            if (includePropertyWithException)
            {
                propertyMetaData.Add(new ElementPropertyMetaData(element1.Object, "throws", typeof(string), true));
            }
            element1.SetupGet(e => e.Properties).Returns(propertyMetaData);

            IElementData elementData1 = null;

            // Use a different element data instance based on whether
            // we want it to be able to throw an exception or not.
            if (includePropertyWithException == false)
            {
                elementData1 = new DictionaryElementData(new TestLogger <DictionaryElementData>(), _pipeline.Object);
            }
            else
            {
                var data = new PropertyExceptionElementData(new TestLogger <DictionaryElementData>(), _pipeline.Object);
                data.ConfigureExceptionForProperty("throws", new Exception("This property is broken!"));
                elementData1 = data;
            }
            // Set up the values for the available properties
            elementData1["available"]         = "a value";
            elementData1["anotheravailable"]  = "a value";
            elementData1["differentcategory"] = "a value";
            elementData1["nocategory"]        = "a value";

            // Set up the process method to add the values to the flow data
            _pipeline.Setup(p => p.Process(It.IsAny <IFlowData>()))
            .Callback((IFlowData data) =>
            {
                data.GetOrAdd("element1", (p) => elementData1);
            });
            // Set up the element in the pipeline
            _pipeline.SetupGet(i => i.FlowElements).Returns(new List <IFlowElement>()
            {
                element1.Object
            });
        }
        private void ConfigureMultiElementValues()
        {
            Mock <IFlowElement> element1 = new Mock <IFlowElement>();

            element1.Setup(e => e.ElementDataKey).Returns("element1");
            List <IElementPropertyMetaData> metaData1 = new List <IElementPropertyMetaData>()
            {
                new ElementPropertyMetaData(element1.Object, INT_PROPERTY, INT_PROPERTY_VALUE.GetType(), true),
                new ElementPropertyMetaData(element1.Object, NULL_STRING_PROPERTY, typeof(string), true),
                new ElementPropertyMetaData(element1.Object, LIST_PROPERTY, LIST_PROPERTY_VALUE.GetType(), true),
                new ElementPropertyMetaData(element1.Object, DUPLICATE_PROPERTY, typeof(string), true),
            };

            element1.Setup(e => e.Properties).Returns(metaData1);

            Mock <IFlowElement> element2 = new Mock <IFlowElement>();

            element2.Setup(e => e.ElementDataKey).Returns("element2");
            List <IElementPropertyMetaData> metaData2 = new List <IElementPropertyMetaData>()
            {
                new ElementPropertyMetaData(element2.Object, STRING_PROPERTY, STRING_PROPERTY_VALUE.GetType(), true),
                new ElementPropertyMetaData(element2.Object, DUPLICATE_PROPERTY, typeof(string), true),
            };

            element2.Setup(e => e.Properties).Returns(metaData2);

            DictionaryElementData elementData1 = new DictionaryElementData(
                new TestLogger <DictionaryElementData>(), _pipeline.Object);

            elementData1[INT_PROPERTY]         = INT_PROPERTY_VALUE;
            elementData1[NULL_STRING_PROPERTY] = null;
            elementData1[LIST_PROPERTY]        = LIST_PROPERTY_VALUE;
            DictionaryElementData elementData2 = new DictionaryElementData(
                new TestLogger <DictionaryElementData>(), _pipeline.Object);

            elementData2[STRING_PROPERTY] = STRING_PROPERTY_VALUE;

            List <IFlowElement> elements = new List <IFlowElement>()
            {
                element1.Object,
                element2.Object,
            };

            _pipeline.Setup(p => p.FlowElements).Returns(elements);
            _pipeline.Setup(p => p.Process(It.IsAny <IFlowData>()))
            .Callback((IFlowData data) =>
            {
                data.GetOrAdd("element1", (p) => elementData1);
                data.GetOrAdd("element2", (p) => elementData2);
            });
            _pipeline.Setup(p => p.GetMetaDataForProperty(It.IsAny <string>())).Returns((string propertyName) =>
            {
                var matches = metaData1.Union(metaData2)
                              .Where(d => d.Name == propertyName);
                if (matches.Count() == 0 || matches.Count() > 1)
                {
                    throw new PipelineDataException("");
                }
                return(matches.Single());
            });
        }