internal static void AssertIsUnbounded(PageNumberAndSize unboundedPage)
        {
            Assert.IsTrue(unboundedPage.IsUnbounded);
            Assert.AreEqual(byte.MinValue, unboundedPage.Size);

            AssertIsFirstPage(unboundedPage);
        }
示例#2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PagingInfo"/> struct
 /// upon deserialization of another <see cref="PagingInfo"/> which
 /// this one replaces, used for lazy initialization by the internal
 /// <see cref="Calculator"/> property.
 /// </summary>
 /// <param name="calculator">
 /// A <see cref="PagingInfoCalculator"/> value initialized from
 /// the <see cref="CurrentPage"/> and <see cref="TotalItems"/>
 /// values of a <see cref="PagingInfo"/> value to be replaced
 /// by this new instance. To understand how this works,
 /// refer to the <see cref="Calculator"/> property.
 /// </param>
 private PagingInfo(PagingInfoCalculator calculator)
 {
     this.CurrentPage = calculator.CurrentPage;
     this.TotalItems  = calculator.TotalItems;
     this.calculator  = calculator;
     this.calculateAllPagesAndItemNumbers = calculator.IncludeAllPagesAndItemNumbers;
 }
 internal static void AssertIsFirstPage(PageNumberAndSize firstPage)
 {
     Assert.IsTrue(firstPage.HasValue);
     Assert.GreaterOrEqual(firstPage.Size, byte.MinValue);
     Assert.AreEqual(PageNumberAndSize.FirstPageNumber, firstPage.Number);
     Assert.AreEqual(0, firstPage.Index);
 }
 internal static void AssertIsEmpty(PageNumberAndSize emptyPage)
 {
     Assert.IsFalse(emptyPage.HasValue);
     Assert.IsFalse(emptyPage.IsUnbounded);
     Assert.AreEqual(byte.MinValue, emptyPage.Size);
     Assert.AreEqual(0, emptyPage.Number);
     Assert.AreEqual(-1, emptyPage.Index);
 }
示例#5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PagingInfo"/> struct
 /// based on a given <see cref="PageNumberAndSize"/> value.
 /// </summary>
 /// <param name="requestedPage">
 /// The requested page <see cref="PageNumberAndSize.Number"/>
 /// and <see cref="PageNumberAndSize.Size"/>.
 /// If <see cref="PageNumberAndSize.Unbounded"/> is sent,
 /// all of the items are returned on a single page as large
 /// as the number of <paramref name="totalItems"/>.
 /// </param>
 /// <param name="totalItems">
 /// The total number of items in the collection to be paged,
 /// initial value for the immutable <see cref="TotalItems"/> field.
 /// </param>
 /// <param name="calculateAllPagesAndItemNumbers">
 /// Indicates whether to include a representation of every
 /// page and its item numbers in the serialized version of
 /// this <see cref="PagingInfo"/>, as a list of
 /// <see cref="PageNumberAndItemNumbers"/>,
 /// for a paging widget which may want to use them.
 /// </param>
 public PagingInfo(
     PageNumberAndSize requestedPage, int totalItems, bool calculateAllPagesAndItemNumbers = DefaultCalculateAllPagesAndItemNumbers)
     : this(new PagingInfoCalculator(requestedPage, totalItems, calculateAllPagesAndItemNumbers))
 {
     Contract.Requires <ArgumentException>(
         requestedPage.HasValue, "The current page must have a value. \"Unbounded\" is an acceptable value.");
     Contract.Requires <ArgumentOutOfRangeException>(
         totalItems >= 0, "The number of items in the list must not be negative!");
 }
            public void Deserializes_As_Invalid_From_Negative_Page_Number()
            {
                PageNumberAndSize deserializedPage
                    = JsonConvert.DeserializeObject <PageNumberAndSize>(
                          "{\"Number\":-7,\"Size\":10}");

                Assert.IsFalse(deserializedPage.HasValue);
                Assert.IsFalse(deserializedPage.IsUnbounded);
            }
            public void Deserializes_And_Ignores_Inconsistency_From_Excessive_Specification()
            {
                PageNumberAndSize page = new PageNumberAndSize(7, 20);
                PageNumberAndSize deserializedPage
                    = JsonConvert.DeserializeObject <PageNumberAndSize>(
                          "{\"Number\":7,\"Size\":20,\"Index\":1111111,\"IsUnbounded\":true}");                       // ,\"HasValue\":false

                AssertEquality(page, deserializedPage);
            }
            public void Deserializes_From_Minimal_Specification()
            {
                PageNumberAndSize page = new PageNumberAndSize(7);
                PageNumberAndSize deserializedPage
                    = JsonConvert.DeserializeObject <PageNumberAndSize>(
                          "{\"Number\":7,\"Size\":10}");

                AssertEquality(page, deserializedPage);
            }
            public void Serializes_All_Properties()
            {
                PageNumberAndSize page           = new PageNumberAndSize(7, 20);
                string            serializedPage = JsonConvert.SerializeObject(page);

                Assert.AreEqual(
                    "{\"Number\":7,\"Size\":20,\"Index\":6,\"IsUnbounded\":false}",                     // ,\"HasValue\":true
                    serializedPage);
            }
示例#10
0
            public void ReturnsUnboundedFromUnbounded()
            {
                PagingInfo        unboundedPagingInfo = new PagingInfo(PageNumberAndSize.Unbounded, 57);
                PageNumberAndSize newPage             = unboundedPagingInfo.TurnToPage(8);

                Assert.AreEqual(1, newPage.Number);
                Assert.AreEqual(0, newPage.Size);
                Assert.IsTrue(newPage.IsUnbounded);
            }
示例#11
0
            public void AllowsTurningPastLastPage()
            {
                PagingInfo        validPagingInfo = new PagingInfo(3, 10, 57);
                PageNumberAndSize newPage         = validPagingInfo.TurnToPage(8);

                Assert.AreEqual(8, newPage.Number);
                Assert.AreEqual(10, newPage.Size);
                Assert.IsFalse(newPage.IsUnbounded);
            }
示例#12
0
            public void DefaultCaseReusesSize()
            {
                PagingInfo        validPagingInfo = new PagingInfo(3, 10, 57);
                PageNumberAndSize newPage         = validPagingInfo.TurnToPage(2);

                Assert.AreEqual(2, newPage.Number);
                Assert.AreEqual(10, newPage.Size);
                Assert.IsFalse(newPage.IsUnbounded);
            }
        internal static void AssertEquality(
            PageNumberAndSize expected, PageNumberAndSize actual)
        {
            Assert.IsTrue(expected == actual);
            Assert.IsFalse(expected != actual);
            Assert.IsTrue(expected.Equals(actual));
            Assert.AreEqual(expected, actual);

            Assert.IsTrue(actual == expected);
            Assert.IsFalse(actual != expected);
            Assert.IsTrue(actual.Equals(expected));
            Assert.AreEqual(actual, expected);

            Assert.AreEqual(expected.Number, actual.Number);
            Assert.AreEqual(expected.Size, actual.Size);
            Assert.AreEqual(expected.Index, actual.Index);
            Assert.AreEqual(expected.IsUnbounded, actual.IsUnbounded);
            Assert.AreEqual(expected.HasValue, actual.HasValue);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="PagingInfoCalculator"/> struct.
        /// Invoked by the private <see cref="PagingInfo.Calculator"/>
        /// property of an owner <see cref="PagingInfo"/> value,
        /// calculates metadata for paging UI, optionally including
        /// a list of all pages and item numbers. For effective lazy
        /// initialization following deserialization from bare essentials.
        /// </summary>
        /// <param name="currentPage">
        /// The page <see cref="PageNumberAndSize.Number"/>
        /// and <see cref="PageNumberAndSize.Size"/>.
        /// If <see cref="PageNumberAndSize.Unbounded"/> is sent,
        /// all of the items are returned on a single page as large
        /// as the number of <paramref name="totalItems"/>.
        /// </param>
        /// <param name="totalItems">
        /// The total number of items in the collection to be paged,
        /// initial value for the immutable <see cref="TotalItems"/> field.
        /// </param>
        /// <param name="includeAllPagesAndItemNumbers">
        /// Whether to fill the set of <see cref="AllPages"/>
        /// including the item numbers on each page,
        /// which may be useful for some paging UI.
        /// Relayed back to the <see cref="PagingInfo"/> via the
        /// <see cref="IncludeAllPagesAndItemNumbers"/> field,
        /// adds the private <see cref="PagingInfo.AllPages"/>
        /// property to the serialization output for JSON.
        /// </param>
        internal PagingInfoCalculator(
            PageNumberAndSize currentPage, int totalItems, bool includeAllPagesAndItemNumbers)
        {
            Contract.Requires <ArgumentException>(
                currentPage.HasValue, "The current page must have a value. \"Unbounded\" is an acceptable value.");
            Contract.Requires <ArgumentOutOfRangeException>(
                totalItems >= 0, "The number of items in the list must not be negative!");

            this.IncludeAllPagesAndItemNumbers = includeAllPagesAndItemNumbers;
            this.CurrentPage = currentPage;
            this.TotalItems  = totalItems;

            if (currentPage.IsUnbounded)
            {
                // This is the case where all of the items are returned on
                // the list, and there is just one unbounded page of items.
                // The total number of items may exceed the maximum allowed
                // value of a byte, so the "page size" value remains as zero.
                // Beware of division by zero!
                // There are no calculations here based on the page size!
                this.TotalPages      = 1;
                this.CurrentPage     = PageNumberAndSize.Unbounded;
                this.FirstItemNumber = this.TotalItems > 0 ? 1 : 0;
                this.LastItemNumber  = this.TotalItems;
                this.ItemCount       = this.TotalItems;
                this.IsFirstPage     = true;
                this.IsLastPage      = true;
                this.PreviousPage    = PageNumberAndSize.Empty;
                this.NextPage        = PageNumberAndSize.Empty;
                this.FirstPage       = this.CurrentPage;
                this.LastPage        = this.CurrentPage;
            }
            else
            {
                this.CurrentPage = currentPage;

                if ((this.TotalItems > 0) && (this.CurrentPage.Size > 0))
                {
                    // Calculate the total pages for a fixed page size and at least one result.
                    this.TotalPages = CalculateTotalPages(this.CurrentPage.Size, this.TotalItems);

                    // Handle the situation if someone turns past the last page.
                    if (this.CurrentPage.Number > this.TotalPages)
                    {
                        // Reset the current page to be the number of the last possible page.
                        this.CurrentPage = new PageNumberAndSize(this.TotalPages, this.CurrentPage.Size);
                    }

                    this.LastItemNumber  = this.CurrentPage.Number * this.CurrentPage.Size;
                    this.FirstItemNumber = this.LastItemNumber - this.CurrentPage.Size + 1;
                    this.ItemCount       = this.LastItemNumber - this.FirstItemNumber + 1;
                    this.IsFirstPage     = this.CurrentPage.Number == PageNumberAndSize.FirstPageNumber;
                    this.IsLastPage      = this.CurrentPage.Number == this.TotalPages;

                    if (this.IsFirstPage)
                    {
                        this.FirstPage    = this.CurrentPage;
                        this.PreviousPage = PageNumberAndSize.Empty;
                    }
                    else
                    {
                        this.FirstPage = new PageNumberAndSize(
                            PageNumberAndSize.FirstPageNumber, this.CurrentPage.Size);

                        this.PreviousPage = new PageNumberAndSize(
                            this.CurrentPage.Number - 1, this.CurrentPage.Size);
                    }

                    if (this.IsLastPage)
                    {
                        this.LastPage = this.CurrentPage;
                        this.NextPage = PageNumberAndSize.Empty;

                        // The number of items shown on the last page
                        // may be smaller than the number of items per page.
                        this.LastItemNumber = this.TotalItems;
                    }
                    else
                    {
                        this.LastPage = new PageNumberAndSize(
                            this.TotalPages, this.CurrentPage.Size);

                        this.NextPage = new PageNumberAndSize(
                            this.CurrentPage.Number + 1, this.CurrentPage.Size);
                    }
                }
                else
                {
                    // This is the case where the count of TotalItems is zero,
                    // so reset the page number back to the first page.
                    this.CurrentPage = new PageNumberAndSize(
                        PageNumberAndSize.FirstPageNumber, this.CurrentPage.Size);

                    // There is just one page of results, with no items.
                    this.TotalPages      = 1;
                    this.FirstItemNumber = 0;
                    this.LastItemNumber  = 0;
                    this.ItemCount       = 0;
                    this.IsFirstPage     = true;
                    this.IsLastPage      = true;
                    this.PreviousPage    = PageNumberAndSize.Empty;
                    this.NextPage        = PageNumberAndSize.Empty;
                    this.FirstPage       = this.CurrentPage;
                    this.LastPage        = this.CurrentPage;
                }
            }

            this.AllPages = this.IncludeAllPagesAndItemNumbers
                                ? AllPagesAndItemNumbers(this.CurrentPage.Size, this.TotalItems, this.TotalPages)
                                : null;
        }
示例#15
0
            public void ReturnsEmptyFromEmpty()
            {
                PageNumberAndSize newPage = PagingInfo.Empty.TurnToPage(6);

                PageNumberAndSizeTests.AssertIsEmpty(newPage);
            }