/// <returns>true if it has failures</returns>
        private bool ValidateZones(Facility requirement, Facility submitted, Facility retFacility)
        {
            if (requirement.Zones == null) 
                return false;
            var ret = false;
            // hack: create a fake modelFacility candidates from spaces.
            var fakeSubmittedFacility = new Facility();
            fakeSubmittedFacility.Floors = fakeSubmittedFacility.Clone(submitted.Floors as IEnumerable<Floor>).ToList();
            fakeSubmittedFacility.Zones = new List<Zone>();
            var lSpaces = submitted.Get<Space>().ToList();

            foreach (var zoneRequirement in requirement.Zones)
            {
                var v = new CobieObjectValidator<Zone, Space>(zoneRequirement)
                {
                    TerminationMode = TerminationMode
                };
                if (! v.HasRequirements)
                    continue;

                // hack: now create a fake Zone based on candidates from spaces.
                var fakeZone = fakeSubmittedFacility.Create<Zone>();
                fakeZone.Categories = zoneRequirement.Categories.Clone().ToList();
                fakeZone.Name = zoneRequirement.Name;
                fakeZone.ExternalEntity = zoneRequirement.ExternalEntity;
                fakeZone.ExternalSystem = zoneRequirement.ExternalSystem;
                fakeZone.ExternalId = zoneRequirement.ExternalId;
                fakeZone.Spaces = new List<SpaceKey>();

                var candidateSpaces = v.GetCandidates(lSpaces).ToList();

                if (candidateSpaces.Any())
                {
                    foreach (var spaceMatch in candidateSpaces)
                    {
                        var mSpace = spaceMatch.MatchedObject as Space;
                        if (mSpace == null)
                            continue;
                        var sk = new SpaceKey {Name = mSpace.Name};
                        fakeZone.Spaces.Add(sk);
                    }
                    if (retFacility.Zones == null)
                        retFacility.Zones = new List<Zone>();
                    var validatedZone = v.Validate(fakeZone, retFacility);
                    retFacility.Zones.Add(validatedZone);
                    var tmpFloor = retFacility.Get<Floor>(fl => fl.Name == TemporaryFloorName).FirstOrDefault();
                    if (tmpFloor == null)
                        continue;
                    // ensure that the floor and spaces are avalialale in the report facility
                    foreach (var spaceKey in validatedZone.Spaces)
                    {
                        // 1) on the floor
                        var submissionOwningFloor =
                            submitted.Get<Floor>(f => f.Spaces != null && f.Spaces.Any(sp => sp.Name == spaceKey.Name)).FirstOrDefault();
                        if (submissionOwningFloor == null)
                            continue;
                        var destFloor = retFacility.Get<Floor>(f => f.Name == submissionOwningFloor.Name).FirstOrDefault();
                        if (destFloor == null)
                        {
                            destFloor = retFacility.Create<Floor>();
                            destFloor.Name = submissionOwningFloor.Name;
                            destFloor.ExternalEntity = submissionOwningFloor.ExternalEntity;
                            destFloor.ExternalId = submissionOwningFloor.ExternalId;
                            destFloor.ExternalSystem = submissionOwningFloor.ExternalSystem;
                            destFloor.Elevation = submissionOwningFloor.Elevation;
                            destFloor.Spaces = new List<Space>();
                            retFacility.Floors.Add(destFloor); // finally add it in the facility tree
                        }
                        // 2) now on the space.

                        var sourceSpace = tmpFloor.Spaces.FirstOrDefault(sp => sp.Name == spaceKey.Name);
                        if (sourceSpace != null)
                        {
                            destFloor.Spaces.Add(sourceSpace);        
                        }
                    }
                    retFacility.Floors.Remove(tmpFloor);
                }
                else
                {
                    if (retFacility.Zones == null)
                        retFacility.Zones = new List<Zone>();
                    retFacility.Zones.Add(v.Validate((Zone) null, retFacility));
                }
                ret |= v.HasFailures;   
            }
            return ret;
        }
        public void DeepSearchTest()
        {
            #region Model

            var facility = new Facility
            {
                Contacts = new List<Contact>(new[]
                {
                    new Contact
                    {
                        Name = "*****@*****.**"
                    }
                }),
                Floors = new List<Floor>(new[]
                {
                    new Floor
                    {
                        Name = "Floor 0",
                        Spaces = new List<Space>(new[]
                        {
                            new Space
                            {
                                Name = "Space A",
                                Attributes = new List<Attribute>(new[]
                                {
                                    new Attribute {Name = "Space A attribute 1"},
                                    new Attribute {Name = "Space A attribute 2"},
                                })
                            },
                            new Space
                            {
                                Name = "Space B",
                                Attributes = new List<Attribute>(new[]
                                {
                                    new Attribute {Name = "Space B attribute 1"},
                                    new Attribute {Name = "Space B attribute 2"},
                                })
                            }
                        })
                    },
                    new Floor
                    {
                        Name = "Floor 1",
                        Spaces = new List<Space>(new[]
                        {
                            new Space
                            {
                                Name = "Space C",
                                Attributes = new List<Attribute>(new[]
                                {
                                    new Attribute {Name = "Space C attribute 1"},
                                    new Attribute {Name = "Space C attribute 2"},
                                })
                            },
                            new Space
                            {
                                Name = "Space D",
                                Attributes = new List<Attribute>(new[]
                                {
                                    new Attribute {Name = "Space D attribute 1"},
                                    new Attribute {Name = "Space D attribute 2"},
                                })
                            }
                        })
                    },
                    new Floor
                    {
                        Name = "Floor 2",
                        Spaces = new List<Space>(new[]
                        {
                            new Space
                            {
                                Name = "Space E",
                                Attributes = new List<Attribute>(new[]
                                {
                                    new Attribute {Name = "Space E attribute 1"},
                                    new Attribute {Name = "Space E attribute 2"},
                                })
                            },
                            new Space
                            {
                                Name = "Space F",
                                Attributes = new List<Attribute>(new[]
                                {
                                    new Attribute {Name = "Space F attribute 1"},
                                    new Attribute {Name = "Space F attribute 2"},
                                })
                            }
                        })
                    }
                })
            };

            #endregion

            var allAttributes = facility.Get<Attribute>();
            Assert.AreEqual(12, allAttributes.Count());

            var allSpaces = facility.Get<Space>();
            Assert.AreEqual(6, allSpaces.Count());

            var spaceA = facility.Get<Space>(s => s.Name == "Space A");
            Assert.AreEqual(1, spaceA.Count());

            var self = facility.Get<Facility>().FirstOrDefault();
            Assert.IsNotNull(self);

            var contact =
                facility.Get<CobieObject>(
                    c => c.GetType() == typeof (Contact) && c.Name == "*****@*****.**");
        }