/**
  * Build nextpage link from the given object which will be the last object
  * in the page.
  * 
  * @param mixed $lastObject Entity instance to build next page link from.
  * 
  * @return string
  * 
  * @throws ODataException If reflection exception occurs while accessing 
  *                        property.
  */
 public function buildNextPageLink($lastObject)
 {
     $nextPageLink = null;
     foreach ($this->_internalOrderByInfo->getOrderByPathSegments() as $orderByPathSegment) {
         $index = 0;
         $currentObject = $lastObject;
         $subPathSegments = $orderByPathSegment->getSubPathSegments();
         $subPathCount = count($subPathSegments);
         foreach ($subPathSegments as &$subPathSegment) {
             $isLastSegment = $index == $subPathCount - 1;
             try {
                 $dummyProperty = new \ReflectionProperty($currentObject, $subPathSegment->getName());
                 $currentObject = $dummyProperty->getValue($currentObject);
                 if (is_null($currentObject)) {
                     $nextPageLink .= 'null, ';
                     break;
                 } else {
                     if ($isLastSegment) {
                         $type = $subPathSegment->getInstanceType();
                         $value = $type->convertToOData($currentObject);
                         $nextPageLink .= $value . ', ';
                     }
                 }
             } catch (\ReflectionException $reflectionException) {
                 throw ODataException::createInternalServerError(Messages::internalSkipTokenInfoFailedToAccessOrInitializeProperty($subPathSegment->getName()));
             }
             $index++;
         }
     }
     return rtrim($nextPageLink, ", ");
 }
 /**
  * Parse the given skiptoken, validate it using the given InternalOrderByInfo 
  * and generates instance of InternalSkipTokenInfo.
  * 
  * @param ResourceType        &$resourceType        The resource type of the
  *                                                  resource targetted by the
  *                                                  resource path.
  * @param InternalOrderByInfo &$internalOrderByInfo The $orderby details.
  * @param string              $skipToken            The $skiptoken value.
  * 
  * @return InternalSkipTokenInfo
  * 
  * @throws ODataException
  */
 public static function parseSkipTokenClause(ResourceType &$resourceType, InternalOrderByInfo &$internalOrderByInfo, $skipToken)
 {
     $tokenValueDescriptor = null;
     if (!KeyDescriptor::tryParseValuesFromSkipToken($skipToken, $tokenValueDescriptor)) {
         ODataException::createSyntaxError(Messages::skipTokenParserSyntaxError($skipToken));
     }
     $orderByPathSegments = null;
     //$positionalValues are of type array(int, array(string, IType))
     $positionalValues =& $tokenValueDescriptor->getPositionalValuesByRef();
     $count = count($positionalValues);
     $orderByPathSegments = $internalOrderByInfo->getOrderByPathSegments();
     $orderByPathCount = count($orderByPathSegments);
     if ($count != $orderByPathCount) {
         ODataException::createBadRequestError(Messages::skipTokenParserSkipTokenNotMatchingOrdering($count, $skipToken, $orderByPathCount));
     }
     $i = 0;
     foreach ($orderByPathSegments as $orderByPathSegment) {
         $typeProvidedInSkipToken = $positionalValues[$i][1];
         if (!$typeProvidedInSkipToken instanceof Null1) {
             $orderBySubPathSegments = $orderByPathSegment->getSubPathSegments();
             $j = count($orderBySubPathSegments) - 1;
             $expectedType = $orderBySubPathSegments[$j]->getInstanceType();
             if (!$expectedType->isCompatibleWith($typeProvidedInSkipToken)) {
                 ODataException::createSyntaxError(Messages::skipTokenParserInCompatibleTypeAtPosition($skipToken, $expectedType->getFullTypeName(), $i, $typeProvidedInSkipToken->getFullTypeName()));
             }
         }
         $i++;
     }
     return new InternalSkipTokenInfo($internalOrderByInfo, $positionalValues, $resourceType);
 }