public static LandListing LandListing(bool isClearAllIsModified = true)
        {
            var listing = new LandListing
            {
                CategoryType = LandListingCategoryType.Residential,
                AuctionOn = new DateTime(2015, 5, 23),
                CouncilRates = "some council rates",
                Estate = new LandEstate
                {
                    Name = "some land estate",
                    Stage = "1st stage"
                },
                Pricing = new SalePricing
                {
                    IsUnderOffer = true,
                    SalePrice = 12345.66m,
                    SalePriceText = "house for sale",
                    SoldOn = new DateTime(2015, 6, 1),
                    SoldPrice = 45432.99m,
                    SoldPriceText = "just sold woot!"
                }
            };

            if (isClearAllIsModified)
            {
                listing.ClearAllIsModified();
            }

            return listing;
        }
        public void Copy(LandListing newLandListing)
        {
            if (newLandListing == null)
            {
                throw new ArgumentNullException("newLandListing");
            }

            if (!newLandListing.IsModified)
            {
                return;
            }

            base.Copy(newLandListing);

            if (newLandListing.IsCategoryTypeModified)
            {
                CategoryType = newLandListing.CategoryType;
            }

            if (newLandListing.IsPricingModified)
            {
                if (newLandListing.Pricing == null)
                {
                    Pricing = null;
                }
                else
                {
                    if (Pricing == null)
                    {
                        Pricing = new SalePricing();
                    }

                    if (newLandListing.IsPricingModified)
                    {
                        Pricing.Copy(newLandListing.Pricing);
                    }

                    IsPricingModified = true;
                }
            }

            if (newLandListing.IsAuctionOnModified)
            {
                AuctionOn = newLandListing.AuctionOn;
            }

            if (newLandListing.IsEstateModified)
            {
                if (newLandListing.Estate == null)
                {
                    Estate = null;
                }
                else
                {
                    if (Estate == null)
                    {
                        Estate = new LandEstate();
                    }
                    Estate.Copy(newLandListing.Estate);
                    IsEstateModified = true;
                }
            }

            if (newLandListing.IsCouncilRatesModified)
            {
                CouncilRates = newLandListing.CouncilRates;
            }
        }
            private static void AssertLandSoldListing(LandListing listing,
                bool isSoldPriceVisibile = true)
            {
                listing.AgencyId.ShouldBe("XNWXNW");
                listing.Id.ShouldBe("Land-Sold-ABCD1234");
                listing.StatusType.ShouldBe(StatusType.Sold);

                decimal? soldPrice = 85000m;
                listing.Pricing.SoldPrice.ShouldBe(soldPrice);
                listing.Pricing.SoldPriceText.ShouldBe(isSoldPriceVisibile
                    ? soldPrice.Value.ToString("C0")
                    : null);
                listing.Pricing.SoldOn.ShouldBe(new DateTime(2009, 01, 10, 12, 30, 00));
            }
            private static void AssertLandCurrentListing(LandListing listing,
                LandCategoryType landCategoryType = LandCategoryType.Residential,
                IList<string> tags = null,
                string streetNumber = "LOT 12/39",
                CarParking carParking = null,
                bool isModified = true)
            {
                listing.AgencyId.ShouldBe("XNWXNW");
                listing.Id.ShouldBe("Land-Current-ABCD1234");
                listing.StatusType.ShouldBe(StatusType.Current);
                listing.CategoryType.ShouldBe(landCategoryType);

                listing.Agents.Count.ShouldBe(1);
                listing.Agents[0].Name.ShouldBe("Mr. John Doe");
                listing.Agents[0].Communications.Count.ShouldBe(3);

                listing.Address.StreetNumber.ShouldBe(streetNumber);
                listing.Address.Street.ShouldBe("Main Road");
                listing.Address.Suburb.ShouldBe("RICHMOND");
                listing.Address.IsStreetDisplayed.ShouldBe(true);

                listing.Pricing.IsUnderOffer.ShouldBe(false);
                listing.Pricing.SalePrice.ShouldBe(80000);
                listing.Pricing.SalePriceText.ShouldBe("To suit buyers 60K+");

                listing.Estate.Name.ShouldBe("Panorama");
                listing.Estate.Stage.ShouldBe("5");

                listing.LandDetails.Area.Type.ShouldBe("square");
                listing.LandDetails.Area.Value.ShouldBe(60m);
                listing.LandDetails.Frontage.Type.ShouldBe("meter");
                listing.LandDetails.Frontage.Value.ShouldBe(20m);
                listing.LandDetails.Depths[0].Type.ShouldBe("meter");
                listing.LandDetails.Depths[0].Value.ShouldBe(30m);
                listing.LandDetails.Depths[0].Side.ShouldBe("rear");
                listing.LandDetails.CrossOver.ShouldBe("left");

                listing.Images.Count.ShouldBe(2);
                listing.Images[0].Order.ShouldBe(1);
                listing.Images[0].Url.ShouldBe("http://www.realestate.com.au/tmp/imageM.jpg");

                listing.FloorPlans.Count.ShouldBe(2);
                listing.FloorPlans[0].Order.ShouldBe(1);
                listing.FloorPlans[0].Url.ShouldBe("http://www.realestate.com.au/tmp/floorplan1.gif");

                listing.AuctionOn.ShouldBe(new DateTime(2009, 1, 24, 12, 30, 00));

                AssertFeatures(listing.Features, 
                    tags, 
                    carParking:carParking,
                    isModified: isModified);
            }
        public void Copy(LandListing newLandListing)
        {
            if (newLandListing == null)
            {
                throw new ArgumentNullException("newLandListing");
            }

            if (!newLandListing.IsModified)
            {
                return;
            }

            base.Copy(newLandListing);

            if (newLandListing.IsCategoryTypeModified)
            {
                CategoryType = newLandListing.CategoryType;
            }

            if (newLandListing.IsPricingModified)
            {
                if (newLandListing.Pricing == null)
                {
                    Pricing = null;
                }
                else
                {
                    if (Pricing == null)
                    {
                        Pricing = new SalePricing();
                    }

                    if (newLandListing.IsPricingModified)
                    {
                        Pricing.Copy(newLandListing.Pricing);
                    }

                    IsPricingModified = true;
                }
            }

            if (newLandListing.IsAuctionOnModified)
            {
                AuctionOn = newLandListing.AuctionOn;
            }

            if (newLandListing.IsEstateModified)
            {
                if (newLandListing.Estate == null)
                {
                    Estate = null;
                }
                else
                {
                    if (Estate == null)
                    {
                        Estate = new LandEstate();
                    }
                    Estate.Copy(newLandListing.Estate);
                    IsEstateModified = true;
                }
            }

            if (newLandListing.IsCouncilRatesModified)
            {
                CouncilRates = newLandListing.CouncilRates;
            }
        }
        private static Listing CreateListing(CategoryType categoryType)
        {
            Listing listing;

            switch (categoryType)
            {
                case CategoryType.Sale:
                    listing = new ResidentialListing();
                    break;
                case CategoryType.Rent:
                    listing = new RentalListing();
                    break;
                case CategoryType.Land:
                    listing = new LandListing();
                    break;
                case CategoryType.Rural:
                    listing = new RuralListing();
                    break;
                default:
                    // Not sure if we should do some logging here?
                    listing = null;
                    break;
            }

            return listing;
        }
        private static void ExtractLandData(LandListing landListing, XElement document, CultureInfo cultureInfo)
        {
            landListing.ShouldNotBe(null);
            document.ShouldNotBe(null);

            landListing.CategoryType = ExtractLandCategoryType(document);
            landListing.Pricing = ExtractSalePricing(document, cultureInfo);
            landListing.AuctionOn = ExtractAuction(document);
            landListing.Estate = ExtractLandEstate(document);
            landListing.AuctionOn = ExtractAuction(document);
            landListing.CouncilRates = document.ValueOrDefault("councilRates");
        }