Completed
Push — master ( f1c3b7...bffd1d )
by Bálint
10:19
created
src/POData/Providers/ProvidersWrapper.php 3 patches
Doc Comments   +6 added lines, -1 removed lines patch added patch discarded remove patch
@@ -605,6 +605,10 @@  discard block
 block discarded – undo
605 605
 	}
606 606
 
607 607
 
608
+	/**
609
+	 * @param QueryResult $queryResult
610
+	 * @param string $methodName
611
+	 */
608 612
 	private function ValidateQueryResult($queryResult, QueryType $queryType, $methodName){
609 613
 		if (!$queryResult instanceof QueryResult) {
610 614
 			throw ODataException::createInternalServerError(
@@ -644,6 +648,8 @@  discard block
 block discarded – undo
644 648
 	 * @param InternalOrderByInfo $orderBy The orderBy information
645 649
 	 * @param int $top The top count
646 650
 	 * @param int $skip The skip count
651
+	 * @param \POData\UriProcessor\QueryProcessor\SkipTokenParser\SkipTokenInfo $skiptoken
652
+	 * @param \POData\UriProcessor\QueryProcessor\ExpandProjectionParser\ExpandedProjectionNode[] $expansion
647 653
 	 *
648 654
 	 * @return QueryResult
649 655
 	 */
@@ -714,7 +720,6 @@  discard block
 block discarded – undo
714 720
 	 * Posts an entity instance to entity set identified by a key
715 721
 	 *
716 722
 	 * @param ResourceSet $resourceSet The entity set containing the entity to update
717
-	 * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
718 723
 	 *
719 724
 	 * @return bool|null Returns result of executiong query
720 725
 	 */
Please login to merge, or discard this patch.
Indentation   +931 added lines, -931 removed lines patch added patch discarded remove patch
@@ -32,935 +32,935 @@
 block discarded – undo
32 32
  */
33 33
 class ProvidersWrapper
34 34
 {
35
-	/**
36
-	 * Holds reference to IMetadataProvider implementation
37
-	 *
38
-	 * @var IMetadataProvider
39
-	 */
40
-	private $metaProvider;
41
-
42
-	/**
43
-	 * Holds reference to IQueryProvider implementation
44
-	 *
45
-	 * @var IQueryProvider
46
-	 *
47
-	 */
48
-	private $queryProvider;
49
-
50
-	/**
51
-	 * Holds reference to IServiceConfiguration implementation
52
-	 *
53
-	 * @var ServiceConfiguration
54
-	 */
55
-	private $config;
56
-
57
-
58
-	/**
59
-	 * Cache for ResourceProperties of a resource type that belongs to a
60
-	 * resource set. An entry (ResourceProperty collection) in this cache
61
-	 * contains only the visible properties of ResourceType.
62
-	 *
63
-	 * @var array(string, array(string, ResourceProperty))
64
-	 */
65
-	private $propertyCache;
66
-
67
-	/**
68
-	 * Cache for ResourceSetWrappers. If ResourceSet is invisible value will
69
-	 * be null.
70
-	 *
71
-	 * @var ResourceSetWrapper[] indexed by resource set name
72
-	 */
73
-	private $setWrapperCache;
74
-
75
-	/**
76
-	 * Cache for ResourceTypes
77
-	 *
78
-	 * @var ResourceType[] indexed by resource type name
79
-	 */
80
-	private $typeCache;
81
-
82
-	/**
83
-	 * Cache for ResourceAssociationSet. If ResourceAssociationSet is invisible
84
-	 * value will be null.
85
-	 *
86
-	 * @var ResourceAssociationSet[] indexed by name
87
-	 */
88
-	private $associationSetCache;
89
-
90
-	/**
91
-	 * Creates a new instance of ProvidersWrapper
92
-	 *
93
-	 * @param IMetadataProvider $metadataProvider Reference to IMetadataProvider implementation
94
-	 * @param IQueryProvider    $queryProvider    Reference to IQueryProvider implementation
95
-	 * @param ServiceConfiguration    $configuration    Reference to IServiceConfiguration implementation
96
-	 */
97
-	public function __construct(IMetadataProvider $metadataProvider, IQueryProvider $queryProvider, ServiceConfiguration $configuration)
98
-	{
99
-		$this->metaProvider = $metadataProvider;
100
-		$this->queryProvider = $queryProvider;
101
-		$this->config = $configuration;
102
-		$this->setWrapperCache = array();
103
-		$this->typeCache = array();
104
-		$this->associationSetCache = array();
105
-		$this->propertyCache = array();
106
-	}
107
-
108
-	//Wrappers for IMetadataProvider methods
109
-
110
-	/**
111
-	 * To get the Container name for the data source,
112
-	 * Note: Wrapper for IMetadataProvider::getContainerName method
113
-	 * implementation
114
-	 *
115
-	 * @return string that contains the name of the container
116
-	 *
117
-	 * @throws ODataException Exception if implementation returns empty container name
118
-	 *
119
-	 */
120
-	public function getContainerName()
121
-	{
122
-		$containerName = $this->metaProvider->getContainerName();
123
-		if (empty($containerName)) {
124
-			throw new ODataException(
125
-				Messages::providersWrapperContainerNameMustNotBeNullOrEmpty(),
126
-				500
127
-			);
128
-		}
129
-
130
-		return $containerName;
131
-	}
132
-
133
-	/**
134
-	 * To get Namespace name for the data source,
135
-	 * Note: Wrapper for IMetadataProvider::getContainerNamespace method implementation
136
-	 *
137
-	 * @return string that contains the namespace name.
138
-	 *
139
-	 * @throws ODataException Exception if implementation returns empty container namespace
140
-	 *
141
-	 */
142
-	public function getContainerNamespace()
143
-	{
144
-		$containerNamespace = $this->metaProvider->getContainerNamespace();
145
-		if (empty($containerNamespace)) {
146
-			throw new ODataException(
147
-				Messages::providersWrapperContainerNamespaceMustNotBeNullOrEmpty(),
148
-				500
149
-			);
150
-		}
151
-
152
-		return $containerNamespace;
153
-	}
154
-
155
-	/**
156
-	 * To get the data service configuration
157
-	 *
158
-	 * @return ServiceConfiguration
159
-	 */
160
-	public function getConfiguration()
161
-	{
162
-		return $this->config;
163
-	}
164
-
165
-	/**
166
-	 *  To get all entity set information,
167
-	 *  Note: Wrapper for IMetadataProvider::getResourceSets method implementation,
168
-	 *  This method returns array of ResourceSetWrapper instances but the corresponding IDSMP method returns array of ResourceSet instances
169
-	 *
170
-	 *  @return ResourceSetWrapper[] The ResourceSetWrappers for the visible ResourceSets
171
-	 *  @throws ODataException when two resource sets with the same name are encountered
172
-	 *
173
-	 */
174
-	public function getResourceSets()
175
-	{
176
-		$resourceSets = $this->metaProvider->getResourceSets();
177
-		$resourceSetWrappers = array();
178
-		$resourceSetNames = array();
179
-		foreach ($resourceSets as $resourceSet) {
180
-			$name = $resourceSet->getName();
181
-			if (in_array($name, $resourceSetNames)) {
182
-				throw new ODataException(Messages::providersWrapperEntitySetNameShouldBeUnique($name), 500 );
183
-			}
184
-
185
-			$resourceSetNames[] = $name;
186
-			$resourceSetWrapper = $this->_validateResourceSetAndGetWrapper($resourceSet);
187
-			if (!is_null($resourceSetWrapper)) {
188
-				$resourceSetWrappers[] = $resourceSetWrapper;
189
-			}
190
-		}
191
-
192
-		return $resourceSetWrappers;
193
-	}
194
-
195
-	/**
196
-	 * To get all resource types in the data source,
197
-	 * Note: Wrapper for IMetadataProvider::getTypes method implementation
198
-	 *
199
-	 * @return ResourceType[]
200
-	 */
201
-	public function getTypes()
202
-	{
203
-		$resourceTypes = $this->metaProvider->getTypes();
204
-		$resourceTypeNames = array();
205
-		foreach ($resourceTypes as $resourceType) {
206
-			if (in_array($resourceType->getName(), $resourceTypeNames)) {
207
-				throw new ODataException(
208
-					Messages::providersWrapperEntityTypeNameShouldBeUnique($resourceType->getName()),
209
-					500
210
-				);
211
-			}
212
-
213
-			$resourceTypeNames[] = $resourceType->getName();
214
-			$this->_validateResourceType($resourceType);
215
-		}
216
-
217
-		return $resourceTypes;
218
-	}
219
-
220
-	/**
221
-	 * To get a resource set based on the specified resource set name which is
222
-	 * visible,
223
-	 * Note: Wrapper for IMetadataProvider::resolveResourceSet method
224
-	 * implementation
225
-	 *
226
-	 * @param string $name Name of the resource set
227
-	 *
228
-	 * @return ResourceSetWrapper|null Returns resource set with the given name if found, NULL if resource set is set to invisible or not found
229
-	 *
230
-	 */
231
-	public function resolveResourceSet($name)
232
-	{
233
-		if (array_key_exists($name, $this->setWrapperCache)) {
234
-			return $this->setWrapperCache[$name];
235
-		}
236
-
237
-		$resourceSet = $this->metaProvider->resolveResourceSet($name);
238
-		if (is_null($resourceSet)) {
239
-			return null;
240
-		}
241
-
242
-		return $this->_validateResourceSetAndGetWrapper($resourceSet);
243
-	}
244
-
245
-	/**
246
-	 * To get a resource type based on the resource set name,
247
-	 * Note: Wrapper for IMetadataProvider::resolveResourceType
248
-	 * method implementation
249
-	 *
250
-	 * @param string $name Name of the resource set
251
-	 *
252
-	 * @return ResourceType|null resource type with the given resource set name if found else NULL
253
-	 *
254
-	 *
255
-	 * @throws ODataException If the ResourceType is invalid
256
-	 */
257
-	public function resolveResourceType($name)
258
-	{
259
-		$resourceType = $this->metaProvider->resolveResourceType($name);
260
-		if (is_null($resourceType)) {
261
-			return null;
262
-		}
263
-
264
-		return $this->_validateResourceType($resourceType);
265
-	}
266
-
267
-	/**
268
-	 * The method must return a collection of all the types derived from
269
-	 * $resourceType The collection returned should NOT include the type
270
-	 * passed in as a parameter
271
-	 * Note: Wrapper for IMetadataProvider::getDerivedTypes
272
-	 * method implementation
273
-	 *
274
-	 * @param ResourceType $resourceType Resource to get derived resource types from
275
-	 *
276
-	 * @return ResourceType[]
277
-	 *
278
-	 * @throws InvalidOperationException when the meat provider doesn't return an array
279
-	 */
280
-	public function getDerivedTypes(ResourceType $resourceType)
281
-	{
282
-		$derivedTypes = $this->metaProvider->getDerivedTypes($resourceType);
283
-		if (!is_array($derivedTypes)) {
284
-			throw new InvalidOperationException(Messages::metadataAssociationTypeSetInvalidGetDerivedTypesReturnType($resourceType->getName()));
285
-		}
286
-
287
-		foreach ($derivedTypes as $derivedType) {
288
-			$this->_validateResourceType($derivedType);
289
-		}
290
-
291
-		return $derivedTypes;
292
-	}
293
-
294
-	/**
295
-	 * Returns true if $resourceType represents an Entity Type which has derived
296
-	 * Entity Types, else false.
297
-	 * Note: Wrapper for IMetadataProvider::hasDerivedTypes method
298
-	 * implementation
299
-	 *
300
-	 * @param ResourceType $resourceType Resource to check for derived resource
301
-	 *                                   types.
302
-	 *
303
-	 * @return boolean
304
-	 *
305
-	 * @throws ODataException If the ResourceType is invalid
306
-	 */
307
-	public function hasDerivedTypes(ResourceType $resourceType)
308
-	{
309
-		$this->_validateResourceType($resourceType);
310
-		return $this->metaProvider->hasDerivedTypes($resourceType);
311
-	}
312
-
313
-	/**
314
-	 * Gets the ResourceAssociationSet instance for the given source association end,
315
-	 * Note: Wrapper for IMetadataProvider::getResourceAssociationSet
316
-	 * method implementation
317
-	 *
318
-	 * @param ResourceSet $set Resource set of the source association end
319
-	 * @param ResourceType       $type       Resource type of the source association end
320
-	 * @param ResourceProperty   $property   Resource property of the source association end
321
-	 *
322
-	 *
323
-	 * @return ResourceAssociationSet|null Returns ResourceAssociationSet for the source
324
-	 *                                             association end, NULL if no such
325
-	 *                                             association end or resource set in the
326
-	 *                                             other end of the association is invisible
327
-	 */
328
-	public function getResourceAssociationSet(
329
-		ResourceSet $set,
330
-		ResourceType $type,
331
-		ResourceProperty $property
332
-	) {
333
-		$type = $this->_getResourceTypeWherePropertyIsDeclared($type, $property);
334
-		$cacheKey = $set->getName() . '_' . $type->getName() . '_' . $property->getName();
335
-
336
-		if (array_key_exists($cacheKey,  $this->associationSetCache)) {
337
-			return $this->associationSetCache[$cacheKey];
338
-		}
339
-
340
-		$associationSet = $this->metaProvider->getResourceAssociationSet(
341
-			$set,
342
-			$type,
343
-			$property
344
-		);
345
-
346
-		if (!is_null($associationSet)) {
347
-			$thisAssociationSetEnd = $associationSet->getResourceAssociationSetEnd(
348
-				$set,
349
-				$type,
350
-				$property
351
-			);
352
-
353
-			$relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
354
-				$set,
355
-				$type,
356
-				$property
357
-			);
358
-
359
-			//If $thisAssociationSetEnd or $relatedAssociationSetEnd
360
-			//is null means the associationset
361
-			//we got from the IDSMP::getResourceAssociationSet is invalid.
362
-			//AssociationSet::getResourceAssociationSetEnd
363
-			//return null, if AssociationSet's End1 or End2's resourceset name
364
-			//is not matching with the name of
365
-			//resource set wrapper (param1) and resource type is not assignable
366
-			//from given resource type (param2)
367
-			if (is_null($thisAssociationSetEnd) || is_null($relatedAssociationSetEnd)) {
368
-				throw new ODataException(
369
-					Messages::providersWrapperIDSMPGetResourceSetReturnsInvalidResourceSet(
370
-						$set->getName(),
371
-						$type->getFullName(),
372
-						$property->getName()
373
-					),
374
-					500
375
-				);
376
-			}
377
-
378
-			$relatedResourceSetWrapper = $this->_validateResourceSetAndGetWrapper(
379
-				$relatedAssociationSetEnd->getResourceSet()
380
-			);
381
-			if ($relatedResourceSetWrapper === null) {
382
-				$associationSet = null;
383
-			} else {
384
-				$this->_validateResourceType($thisAssociationSetEnd->getResourceType());
385
-				$this->_validateResourceType($relatedAssociationSetEnd->getResourceType());
386
-			}
387
-		}
388
-
389
-		$this->associationSetCache[$cacheKey] = $associationSet;
390
-		return $associationSet;
391
-	}
392
-
393
-	/**
394
-	 * Gets the target resource set wrapper for the given navigation property,
395
-	 * source resource set wrapper and the source resource type
396
-	 *
397
-	 * @param ResourceSetWrapper $resourceSetWrapper         Source resource set.
398
-	 * @param ResourceType       $resourceType               Source resource type.
399
-	 * @param ResourceProperty   $navigationResourceProperty Navigation property.
400
-	 *
401
-	 * @return ResourceSetWrapper|null Returns instance of ResourceSetWrapper
402
-	 *     (describes the entity set and associated configuration) for the
403
-	 *     given navigation property. returns NULL if resourceset for the
404
-	 *     navigation property is invisible or if metadata provider returns
405
-	 *     null resource association set
406
-	 */
407
-	public function getResourceSetWrapperForNavigationProperty(
408
-		ResourceSetWrapper $resourceSetWrapper,
409
-		ResourceType $resourceType,
410
-		ResourceProperty $navigationResourceProperty
411
-	) {
412
-		$associationSet = $this->getResourceAssociationSet(
413
-			$resourceSetWrapper,
414
-			$resourceType,
415
-			$navigationResourceProperty
416
-		);
417
-
418
-		if (!is_null($associationSet)) {
419
-			$relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
420
-				$resourceSetWrapper->getResourceSet(),
421
-				$resourceType,
422
-				$navigationResourceProperty
423
-			);
424
-			return $this->_validateResourceSetAndGetWrapper(
425
-				$relatedAssociationSetEnd->getResourceSet()
426
-			);
427
-		}
428
-
429
-		return null;
430
-	}
431
-
432
-	/**
433
-	 * Gets the visible resource properties for the given resource type from the given resource set wrapper.
434
-	 *
435
-	 * @param ResourceSetWrapper $setWrapper Resource set wrapper in question.
436
-	 * @param ResourceType       $resourceType       Resource type in question.
437
-	 * @return ResourceProperty[] Collection of visible resource properties from the given resource set wrapper and resource type.
438
-	 */
439
-	public function getResourceProperties(ResourceSetWrapper $setWrapper, ResourceType $resourceType) {
440
-		if ($resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
441
-			//Complex resource type
442
-			return $resourceType->getAllProperties();
443
-		}
444
-		//TODO: move this to doctrine annotations
445
-		$cacheKey = $setWrapper->getName() . '_' . $resourceType->getFullName();
446
-		if (!array_key_exists($cacheKey,  $this->propertyCache)) {
447
-			//Fill the cache
448
-			$this->propertyCache[$cacheKey] = array();
449
-			foreach ($resourceType->getAllProperties() as $resourceProperty) {
450
-				//Check whether this is a visible navigation property
451
-				//TODO: is this broken?? see #87
452
-				if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY
453
-					&& !is_null($this->getResourceSetWrapperForNavigationProperty($setWrapper, $resourceType, $resourceProperty))
454
-				) {
455
-					$this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
456
-				} else {
457
-					//primitive, bag or complex property
458
-					$this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
459
-				}
460
-			}
461
-		}
462
-		return $this->propertyCache[$cacheKey];
463
-
464
-	}
465
-
466
-	/**
467
-	 * Wrapper function over _validateResourceSetAndGetWrapper function
468
-	 *
469
-	 * @param ResourceSet $resourceSet see the comments of _validateResourceSetAndGetWrapper
470
-	 *
471
-	 * @return ResourceSetWrapper|null see the comments of _validateResourceSetAndGetWrapper
472
-	 */
473
-	public function validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
474
-	{
475
-		return $this->_validateResourceSetAndGetWrapper($resourceSet);
476
-	}
477
-
478
-	/**
479
-	 * Gets the Edm Schema version compliance to the metadata
480
-	 *
481
-	 * @return EdmSchemaVersion
482
-	 */
483
-	public function getEdmSchemaVersion()
484
-	{
485
-		//The minimal schema version for custom provider is 1.1
486
-		return EdmSchemaVersion::VERSION_1_DOT_1;
487
-	}
488
-
489
-	/**
490
-	 * This function perform the following operations
491
-	 *  (1) If the cache contain an entry [key, value] for the resourceset then
492
-	 *      return the entry-value
493
-	 *  (2) If the cache not contain an entry for the resourceset then validate
494
-	 *      the resourceset
495
-	 *            (a) If valid add entry as [resouceset_name, resourceSetWrapper]
496
-	 *            (b) if not valid add entry as [resouceset_name, null]
497
-	 *  Note: validating a resourceset means checking the resourceset is visible
498
-	 *  or not using configuration
499
-	 *
500
-	 * @param ResourceSet $resourceSet The resourceset to validate and get the
501
-	 *                                 wrapper for
502
-	 *
503
-	 * @return ResourceSetWrapper|null Returns an instance if a resource set with the given name is visible
504
-	 */
505
-	private function _validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
506
-	{
507
-		$cacheKey = $resourceSet->getName();
508
-		if (array_key_exists($cacheKey, $this->setWrapperCache)) {
509
-			return $this->setWrapperCache[$cacheKey];
510
-		}
511
-
512
-		$this->_validateResourceType($resourceSet->getResourceType());
513
-		$wrapper = new ResourceSetWrapper($resourceSet, $this->config);
514
-		if ($wrapper->isVisible()) {
515
-			$this->setWrapperCache[$cacheKey] = $wrapper;
516
-		} else {
517
-			$this->setWrapperCache[$cacheKey] = null;
518
-		}
519
-
520
-		return $this->setWrapperCache[$cacheKey];
521
-	}
522
-
523
-	/**
524
-	 * Validates the given instance of ResourceType
525
-	 *
526
-	 * @param ResourceType $resourceType The ResourceType to validate
527
-	 *
528
-	 * @return ResourceType
529
-	 *
530
-	 * @throws ODataException Exception if $resourceType is invalid
531
-	 */
532
-	private function _validateResourceType(ResourceType $resourceType)
533
-	{
534
-		$cacheKey = $resourceType->getName();
535
-		if (array_key_exists($cacheKey, $this->typeCache)) {
536
-			return $this->typeCache[$cacheKey];
537
-		}
538
-
539
-		//TODO: Do validation if any for the ResourceType
540
-		$this->typeCache[$cacheKey] = $resourceType;
541
-		return $resourceType;
542
-	}
543
-
544
-	/**
545
-	 * Gets the resource type on which the resource property is declared on,
546
-	 * If property is not declared in the given resource type, then this
547
-	 * function drill down to the inheritance hierarchy of the given resource
548
-	 * type to find out the base class in which the property is declared
549
-	 *
550
-	 * @param ResourceType     $resourceType     The resource type to start looking
551
-	 * @param ResourceProperty $resourceProperty The resource property in question
552
-	 *
553
-	 * @return ResourceType|null Returns reference to the ResourceType on which
554
-	 *                                   the $resourceProperty is declared, NULL if
555
-	 *                                   $resourceProperty is not declared anywhere
556
-	 *                                   in the inheritance hierarchy
557
-	 */
558
-	private function _getResourceTypeWherePropertyIsDeclared(ResourceType $resourceType,
559
-		ResourceProperty $resourceProperty
560
-	) {
561
-		$type = $resourceType;
562
-		while ($type !== null) {
563
-			if ($type->resolvePropertyDeclaredOnThisType($resourceProperty->getName()) !== null) {
564
-				break;
565
-			}
566
-
567
-			$type = $type->getBaseType();
568
-		}
569
-
570
-		return $type;
571
-	}
572
-
573
-	/**
574
-	 * Gets the underlying custom expression provider, the end developer is
575
-	 * responsible for implementing IExpressionProvider if he choose for
576
-	 *
577
-	 * @return IExpressionProvider Instance of IExpressionProvider implementation.
578
-	 *
579
-	 */
580
-	public function getExpressionProvider()
581
-	{
582
-		$expressionProvider = $this->queryProvider->getExpressionProvider();
583
-		if (is_null($expressionProvider)) {
584
-			throw ODataException::createInternalServerError(Messages::providersWrapperExpressionProviderMustNotBeNullOrEmpty());
585
-		}
586
-
587
-		if (!$expressionProvider instanceof IExpressionProvider)
588
-		{
589
-			throw ODataException::createInternalServerError( Messages::providersWrapperInvalidExpressionProviderInstance() );
590
-		}
591
-
592
-		return $expressionProvider;
593
-	}
594
-
595
-	/**
596
-	 * Indicates if the QueryProvider can handle ordered paging, this means respecting order, skip, and top parameters
597
-	 * If the query provider can not handle ordered paging, it must return the entire result set and POData will
598
-	 * perform the ordering and paging
599
-	 *
600
-	 * @return Boolean True if the query provider can handle ordered paging, false if POData should perform the paging
601
-	 */
602
-	public function handlesOrderedPaging()
603
-	{
604
-		return $this->queryProvider->handlesOrderedPaging();
605
-	}
606
-
607
-
608
-	private function ValidateQueryResult($queryResult, QueryType $queryType, $methodName){
609
-		if (!$queryResult instanceof QueryResult) {
610
-			throw ODataException::createInternalServerError(
611
-				Messages::queryProviderReturnsNonQueryResult($methodName)
612
-			);
613
-		}
614
-
615
-		if($queryType == QueryType::COUNT() || $queryType == QueryType::ENTITIES_WITH_COUNT()){
616
-			//and the provider is supposed to handle the ordered paging they must return a count!
617
-			if($this->queryProvider->handlesOrderedPaging() && !is_numeric($queryResult->count)){
618
-				throw ODataException::createInternalServerError(
619
-					Messages::queryProviderResultCountMissing($methodName, $queryType)
620
-				);
621
-			}
622
-
623
-			//If POData is supposed to handle the ordered aging they must return results! (possibly empty)
624
-			if(!$this->queryProvider->handlesOrderedPaging() && !is_array($queryResult->results)){
625
-				throw ODataException::createInternalServerError(
626
-					Messages::queryProviderResultsMissing($methodName, $queryType)
627
-				);
628
-			}
629
-		}
630
-
631
-		if(($queryType == QueryType::ENTITIES() || $queryType == QueryType::ENTITIES_WITH_COUNT()) && !is_array($queryResult->results)){
632
-			throw ODataException::createInternalServerError(
633
-				Messages::queryProviderResultsMissing($methodName, $queryType)
634
-			);
635
-		}
636
-	}
637
-
638
-	/**
639
-	 * Gets collection of entities belongs to an entity set
640
-	 *
641
-	 * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
642
-	 * @param ResourceSet $resourceSet The entity set containing the entities that need to be fetched
643
-	 * @param FilterInfo $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
644
-	 * @param InternalOrderByInfo $orderBy The orderBy information
645
-	 * @param int $top The top count
646
-	 * @param int $skip The skip count
647
-	 *
648
-	 * @return QueryResult
649
-	 */
650
-	public function getResourceSet(QueryType $queryType, ResourceSet $resourceSet, $filterInfo, $orderBy, $top, $skip, $skiptoken = null, $expansion=null)
651
-	{
652
-
653
-		$queryResult = $this->queryProvider->getResourceSet(
654
-			$queryType,
655
-			$resourceSet,
656
-			$filterInfo,
657
-			$orderBy,
658
-			$top,
659
-			$skip,
660
-			$skiptoken,
661
-			$expansion
662
-		);
663
-
664
-		$this->validateQueryResult($queryResult, $queryType, 'IQueryProvider::getResourceSet');
665
-
666
-		return $queryResult;
667
-	}
668
-
669
-
670
-
671
-	/**
672
-	 * Gets an entity instance from an entity set identified by a key
673
-	 *
674
-	 * @param ResourceSet $resourceSet The entity set containing the entity to fetch
675
-	 * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
676
-	 *
677
-	 * @return object|null Returns entity instance if found else null
678
-	 */
679
-	public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
680
-	{
681
-		$entityInstance = $this->queryProvider->getResourceFromResourceSet( $resourceSet, $keyDescriptor );
682
-		$this->_validateEntityInstance(
683
-			$entityInstance,
684
-			$resourceSet,
685
-			$keyDescriptor,
686
-			'IQueryProvider::getResourceFromResourceSet'
687
-		);
688
-		return $entityInstance;
689
-	}
690
-
691
-	/**
692
-	 * Puts an entity instance to entity set identified by a key
693
-	 *
694
-	 * @param ResourceSet $resourceSet The entity set containing the entity to update
695
-	 * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
696
-	 *
697
-	 * @return bool|null Returns result of executiong query
698
-	 */
699
-	public function putResource(
700
-		ResourceSet $resourceSet,
701
-		KeyDescriptor $keyDescriptor,
702
-		$data
703
-	) {
704
-		$queryResult = $this->queryProvider->putResource(
705
-			$resourceSet,
706
-			$keyDescriptor,
707
-			$data
708
-		);
709
-
710
-		return $queryResult;
711
-	}
712
-
713
-	/**
714
-	 * Posts an entity instance to entity set identified by a key
715
-	 *
716
-	 * @param ResourceSet $resourceSet The entity set containing the entity to update
717
-	 * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
718
-	 *
719
-	 * @return bool|null Returns result of executiong query
720
-	 */
721
-	public function postResource(
722
-		ResourceSet $resourceSet,
723
-		$data
724
-	) {
725
-		$queryResult = $this->queryProvider->postResource(
726
-			$resourceSet,
727
-			$data
728
-		);
729
-
730
-		return $queryResult;
731
-	}
732
-
733
-	/**
734
-	 * Get related resource set for a resource
735
-	 *
736
-	 * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
737
-	 * @param ResourceSet $sourceResourceSet The entity set containing the source entity
738
-	 * @param object $sourceEntity The source entity instance.
739
-	 * @param ResourceSet      $targetResourceSet    The resource set of containing the target of the navigation property
740
-	 * @param ResourceProperty $targetProperty       The navigation property to retrieve
741
-	 * @param FilterInfo  $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
742
-	 * @param mixed $orderBy sorted order if we want to get the data in some specific order
743
-	 * @param int $top number of records which  need to be skip
744
-	 * @param String $skip value indicating what records to skip
745
-	 *
746
-	 * @return QueryResult
747
-	 *
748
-	 * @throws ODataException
749
-	 */
750
-	public function getRelatedResourceSet(
751
-		QueryType $queryType,
752
-		ResourceSet $sourceResourceSet,
753
-		$sourceEntity,
754
-		ResourceSet $targetResourceSet,
755
-		ResourceProperty $targetProperty,
756
-		$filterInfo,
757
-		$orderBy,
758
-		$top,
759
-		$skip
760
-	) {
761
-
762
-		$queryResult = $this->queryProvider->getRelatedResourceSet(
763
-			$queryType,
764
-			$sourceResourceSet,
765
-			$sourceEntity,
766
-			$targetResourceSet,
767
-			$targetProperty,
768
-			$filterInfo,
769
-			$orderBy,
770
-			$top,
771
-			$skip
772
-		);
773
-
774
-
775
-		$this->validateQueryResult($queryResult, $queryType, 'IQueryProvider::getRelatedResourceSet');
776
-
777
-
778
-		return $queryResult;
779
-	}
780
-
781
-	/**
782
-	 * Gets a related entity instance from an entity set identified by a key
783
-	 *
784
-	 * @param ResourceSet      $sourceResourceSet The entity set related to the entity to be fetched.
785
-	 * @param object           $sourceEntity      The related entity instance.
786
-	 * @param ResourceSet      $targetResourceSet The entity set from which entity needs to be fetched.
787
-	 * @param ResourceProperty $targetProperty    The metadata of the target property.
788
-	 * @param KeyDescriptor    $keyDescriptor     The key to identify the entity to be fetched.
789
-	 *
790
-	 *
791
-	 * @return object|null Returns entity instance if found else null
792
-	 */
793
-	public function getResourceFromRelatedResourceSet(ResourceSet $sourceResourceSet,
794
-		$sourceEntity, ResourceSet $targetResourceSet, ResourceProperty $targetProperty,
795
-		KeyDescriptor $keyDescriptor
796
-	) {
797
-		$entityInstance = $this->queryProvider->getResourceFromRelatedResourceSet(
798
-			$sourceResourceSet,
799
-			$sourceEntity,
800
-			$targetResourceSet,
801
-			$targetProperty,
802
-			$keyDescriptor
803
-		);
804
-
805
-		$this->_validateEntityInstance(
806
-			$entityInstance, $targetResourceSet,
807
-			$keyDescriptor,
808
-			'IQueryProvider::getResourceFromRelatedResourceSet'
809
-		);
810
-		return $entityInstance;
811
-	}
812
-
813
-	/**
814
-	 * Get related resource for a resource
815
-	 *
816
-	 * @param ResourceSet      $sourceResourceSet The source resource set
817
-	 * @param object           $sourceEntity      The source resource
818
-	 * @param ResourceSet      $targetResourceSet The resource set of the navigation
819
-	 *                                            property
820
-	 * @param ResourceProperty $targetProperty    The navigation property to be
821
-	 *                                            retrieved
822
-	 *
823
-	 * @return object|null The related resource if exists else null
824
-	 */
825
-	public function getRelatedResourceReference(ResourceSet $sourceResourceSet,
826
-		$sourceEntity, ResourceSet $targetResourceSet,
827
-		ResourceProperty $targetProperty
828
-	) {
829
-		$entityInstance = $this->queryProvider->getRelatedResourceReference(
830
-			$sourceResourceSet,
831
-			$sourceEntity,
832
-			$targetResourceSet,
833
-			$targetProperty
834
-		);
835
-
836
-		// we will not throw error if the resource reference is null
837
-		// e.g. Orders(1234)/Customer => Customer can be null, this is
838
-		// allowed if Customer is last segment. consider the following:
839
-		// Orders(1234)/Customer/Orders => here if Customer is null then
840
-		// the UriProcessor will throw error.
841
-		if (!is_null($entityInstance)) {
842
-			$entityName
843
-				= $targetResourceSet
844
-					->getResourceType()
845
-					->getInstanceType()
846
-					->getName();
847
-			if (!is_object($entityInstance)
848
-				|| !($entityInstance instanceof $entityName)
849
-			) {
850
-				throw ODataException::createInternalServerError(
851
-					Messages::providersWrapperIDSQPMethodReturnsUnExpectedType(
852
-						$entityName,
853
-						'IQueryProvider::getRelatedResourceReference'
854
-					)
855
-				);
856
-			}
857
-
858
-			foreach ($targetProperty->getResourceType()->getKeyProperties()
859
-			as $keyName => $resourceProperty) {
860
-				try {
861
-					$keyProperty = new \ReflectionProperty(
862
-						$entityInstance,
863
-						$keyName
864
-					);
865
-					$keyProperty->setAccessible(true);
866
-					$keyValue = $keyProperty->getValue($entityInstance);
867
-					if (is_null($keyValue)) {
868
-						throw ODataException::createInternalServerError(
869
-							Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties('IDSQP::getRelatedResourceReference')
870
-						);
871
-					}
872
-				} catch (\ReflectionException $reflectionException) {
873
-					//throw ODataException::createInternalServerError(
874
-					//    Messages::orderByParserFailedToAccessOrInitializeProperty(
875
-					//        $resourceProperty->getName(), $resourceType->getName()
876
-					//    )
877
-					//);
878
-				}
879
-			}
880
-		}
881
-
882
-		return $entityInstance;
883
-	}
884
-
885
-	/**
886
-	 * Validate the given entity instance.
887
-	 *
888
-	 * @param object        $entityInstance Entity instance to validate
889
-	 * @param ResourceSet   &$resourceSet   Resource set to which the entity
890
-	 *                                      instance belongs to.
891
-	 * @param KeyDescriptor &$keyDescriptor The key descriptor.
892
-	 * @param string        $methodName     Method from which this function
893
-	 *                                      invoked.
894
-	 *
895
-	 * @return void
896
-	 *
897
-	 * @throws ODataException
898
-	 */
899
-	private function _validateEntityInstance($entityInstance,
900
-		ResourceSet &$resourceSet,
901
-		KeyDescriptor &$keyDescriptor,
902
-		$methodName
903
-	) {
904
-		if (is_null($entityInstance)) {
905
-			throw ODataException::createResourceNotFoundError($resourceSet->getName());
906
-		}
907
-
908
-		$entityName = $resourceSet->getResourceType()->getInstanceType()->getName();
909
-		if (!is_object($entityInstance)
910
-			|| !($entityInstance instanceof $entityName)
911
-		) {
912
-			throw ODataException::createInternalServerError(
913
-				Messages::providersWrapperIDSQPMethodReturnsUnExpectedType(
914
-					$entityName,
915
-					$methodName
916
-				)
917
-			);
918
-		}
919
-
920
-		foreach ($keyDescriptor->getValidatedNamedValues()
921
-			as $keyName => $valueDescription) {
922
-			try {
923
-				$keyProperty = new \ReflectionProperty($entityInstance, $keyName);
924
-				$keyProperty->setAccessible(true);
925
-				$keyValue = $keyProperty->getValue($entityInstance);
926
-				if (is_null($keyValue)) {
927
-					throw ODataException::createInternalServerError(
928
-						Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties($methodName)
929
-					);
930
-				}
931
-
932
-				$convertedValue
933
-					= $valueDescription[1]->convert($valueDescription[0]);
934
-				if ($keyValue != $convertedValue) {
935
-					throw ODataException::createInternalServerError(
936
-						Messages::providersWrapperIDSQPMethodReturnsInstanceWithNonMatchingKeys($methodName)
937
-					);
938
-				}
939
-			} catch (\ReflectionException $reflectionException) {
940
-				//throw ODataException::createInternalServerError(
941
-				//  Messages::orderByParserFailedToAccessOrInitializeProperty(
942
-				//      $resourceProperty->getName(), $resourceType->getName()
943
-				//  )
944
-				//);
945
-			}
946
-		}
947
-	}
948
-
949
-	/**
950
-	 * Assert that the given condition is true.
951
-	 *
952
-	 * @param boolean $condition         Condition to be asserted.
953
-	 * @param string  $conditionAsString String containing message incase
954
-	 *                                   if assertion fails.
955
-	 *
956
-	 * @throws InvalidOperationException Incase if assertion fails.
957
-	 *
958
-	 * @return void
959
-	 */
960
-	protected function assert($condition, $conditionAsString)
961
-	{
962
-		if (!$condition) {
963
-			throw new InvalidOperationException("Unexpected state, expecting $conditionAsString");
964
-		}
965
-	}
35
+    /**
36
+     * Holds reference to IMetadataProvider implementation
37
+     *
38
+     * @var IMetadataProvider
39
+     */
40
+    private $metaProvider;
41
+
42
+    /**
43
+     * Holds reference to IQueryProvider implementation
44
+     *
45
+     * @var IQueryProvider
46
+     *
47
+     */
48
+    private $queryProvider;
49
+
50
+    /**
51
+     * Holds reference to IServiceConfiguration implementation
52
+     *
53
+     * @var ServiceConfiguration
54
+     */
55
+    private $config;
56
+
57
+
58
+    /**
59
+     * Cache for ResourceProperties of a resource type that belongs to a
60
+     * resource set. An entry (ResourceProperty collection) in this cache
61
+     * contains only the visible properties of ResourceType.
62
+     *
63
+     * @var array(string, array(string, ResourceProperty))
64
+     */
65
+    private $propertyCache;
66
+
67
+    /**
68
+     * Cache for ResourceSetWrappers. If ResourceSet is invisible value will
69
+     * be null.
70
+     *
71
+     * @var ResourceSetWrapper[] indexed by resource set name
72
+     */
73
+    private $setWrapperCache;
74
+
75
+    /**
76
+     * Cache for ResourceTypes
77
+     *
78
+     * @var ResourceType[] indexed by resource type name
79
+     */
80
+    private $typeCache;
81
+
82
+    /**
83
+     * Cache for ResourceAssociationSet. If ResourceAssociationSet is invisible
84
+     * value will be null.
85
+     *
86
+     * @var ResourceAssociationSet[] indexed by name
87
+     */
88
+    private $associationSetCache;
89
+
90
+    /**
91
+     * Creates a new instance of ProvidersWrapper
92
+     *
93
+     * @param IMetadataProvider $metadataProvider Reference to IMetadataProvider implementation
94
+     * @param IQueryProvider    $queryProvider    Reference to IQueryProvider implementation
95
+     * @param ServiceConfiguration    $configuration    Reference to IServiceConfiguration implementation
96
+     */
97
+    public function __construct(IMetadataProvider $metadataProvider, IQueryProvider $queryProvider, ServiceConfiguration $configuration)
98
+    {
99
+        $this->metaProvider = $metadataProvider;
100
+        $this->queryProvider = $queryProvider;
101
+        $this->config = $configuration;
102
+        $this->setWrapperCache = array();
103
+        $this->typeCache = array();
104
+        $this->associationSetCache = array();
105
+        $this->propertyCache = array();
106
+    }
107
+
108
+    //Wrappers for IMetadataProvider methods
109
+
110
+    /**
111
+     * To get the Container name for the data source,
112
+     * Note: Wrapper for IMetadataProvider::getContainerName method
113
+     * implementation
114
+     *
115
+     * @return string that contains the name of the container
116
+     *
117
+     * @throws ODataException Exception if implementation returns empty container name
118
+     *
119
+     */
120
+    public function getContainerName()
121
+    {
122
+        $containerName = $this->metaProvider->getContainerName();
123
+        if (empty($containerName)) {
124
+            throw new ODataException(
125
+                Messages::providersWrapperContainerNameMustNotBeNullOrEmpty(),
126
+                500
127
+            );
128
+        }
129
+
130
+        return $containerName;
131
+    }
132
+
133
+    /**
134
+     * To get Namespace name for the data source,
135
+     * Note: Wrapper for IMetadataProvider::getContainerNamespace method implementation
136
+     *
137
+     * @return string that contains the namespace name.
138
+     *
139
+     * @throws ODataException Exception if implementation returns empty container namespace
140
+     *
141
+     */
142
+    public function getContainerNamespace()
143
+    {
144
+        $containerNamespace = $this->metaProvider->getContainerNamespace();
145
+        if (empty($containerNamespace)) {
146
+            throw new ODataException(
147
+                Messages::providersWrapperContainerNamespaceMustNotBeNullOrEmpty(),
148
+                500
149
+            );
150
+        }
151
+
152
+        return $containerNamespace;
153
+    }
154
+
155
+    /**
156
+     * To get the data service configuration
157
+     *
158
+     * @return ServiceConfiguration
159
+     */
160
+    public function getConfiguration()
161
+    {
162
+        return $this->config;
163
+    }
164
+
165
+    /**
166
+     *  To get all entity set information,
167
+     *  Note: Wrapper for IMetadataProvider::getResourceSets method implementation,
168
+     *  This method returns array of ResourceSetWrapper instances but the corresponding IDSMP method returns array of ResourceSet instances
169
+     *
170
+     *  @return ResourceSetWrapper[] The ResourceSetWrappers for the visible ResourceSets
171
+     *  @throws ODataException when two resource sets with the same name are encountered
172
+     *
173
+     */
174
+    public function getResourceSets()
175
+    {
176
+        $resourceSets = $this->metaProvider->getResourceSets();
177
+        $resourceSetWrappers = array();
178
+        $resourceSetNames = array();
179
+        foreach ($resourceSets as $resourceSet) {
180
+            $name = $resourceSet->getName();
181
+            if (in_array($name, $resourceSetNames)) {
182
+                throw new ODataException(Messages::providersWrapperEntitySetNameShouldBeUnique($name), 500 );
183
+            }
184
+
185
+            $resourceSetNames[] = $name;
186
+            $resourceSetWrapper = $this->_validateResourceSetAndGetWrapper($resourceSet);
187
+            if (!is_null($resourceSetWrapper)) {
188
+                $resourceSetWrappers[] = $resourceSetWrapper;
189
+            }
190
+        }
191
+
192
+        return $resourceSetWrappers;
193
+    }
194
+
195
+    /**
196
+     * To get all resource types in the data source,
197
+     * Note: Wrapper for IMetadataProvider::getTypes method implementation
198
+     *
199
+     * @return ResourceType[]
200
+     */
201
+    public function getTypes()
202
+    {
203
+        $resourceTypes = $this->metaProvider->getTypes();
204
+        $resourceTypeNames = array();
205
+        foreach ($resourceTypes as $resourceType) {
206
+            if (in_array($resourceType->getName(), $resourceTypeNames)) {
207
+                throw new ODataException(
208
+                    Messages::providersWrapperEntityTypeNameShouldBeUnique($resourceType->getName()),
209
+                    500
210
+                );
211
+            }
212
+
213
+            $resourceTypeNames[] = $resourceType->getName();
214
+            $this->_validateResourceType($resourceType);
215
+        }
216
+
217
+        return $resourceTypes;
218
+    }
219
+
220
+    /**
221
+     * To get a resource set based on the specified resource set name which is
222
+     * visible,
223
+     * Note: Wrapper for IMetadataProvider::resolveResourceSet method
224
+     * implementation
225
+     *
226
+     * @param string $name Name of the resource set
227
+     *
228
+     * @return ResourceSetWrapper|null Returns resource set with the given name if found, NULL if resource set is set to invisible or not found
229
+     *
230
+     */
231
+    public function resolveResourceSet($name)
232
+    {
233
+        if (array_key_exists($name, $this->setWrapperCache)) {
234
+            return $this->setWrapperCache[$name];
235
+        }
236
+
237
+        $resourceSet = $this->metaProvider->resolveResourceSet($name);
238
+        if (is_null($resourceSet)) {
239
+            return null;
240
+        }
241
+
242
+        return $this->_validateResourceSetAndGetWrapper($resourceSet);
243
+    }
244
+
245
+    /**
246
+     * To get a resource type based on the resource set name,
247
+     * Note: Wrapper for IMetadataProvider::resolveResourceType
248
+     * method implementation
249
+     *
250
+     * @param string $name Name of the resource set
251
+     *
252
+     * @return ResourceType|null resource type with the given resource set name if found else NULL
253
+     *
254
+     *
255
+     * @throws ODataException If the ResourceType is invalid
256
+     */
257
+    public function resolveResourceType($name)
258
+    {
259
+        $resourceType = $this->metaProvider->resolveResourceType($name);
260
+        if (is_null($resourceType)) {
261
+            return null;
262
+        }
263
+
264
+        return $this->_validateResourceType($resourceType);
265
+    }
266
+
267
+    /**
268
+     * The method must return a collection of all the types derived from
269
+     * $resourceType The collection returned should NOT include the type
270
+     * passed in as a parameter
271
+     * Note: Wrapper for IMetadataProvider::getDerivedTypes
272
+     * method implementation
273
+     *
274
+     * @param ResourceType $resourceType Resource to get derived resource types from
275
+     *
276
+     * @return ResourceType[]
277
+     *
278
+     * @throws InvalidOperationException when the meat provider doesn't return an array
279
+     */
280
+    public function getDerivedTypes(ResourceType $resourceType)
281
+    {
282
+        $derivedTypes = $this->metaProvider->getDerivedTypes($resourceType);
283
+        if (!is_array($derivedTypes)) {
284
+            throw new InvalidOperationException(Messages::metadataAssociationTypeSetInvalidGetDerivedTypesReturnType($resourceType->getName()));
285
+        }
286
+
287
+        foreach ($derivedTypes as $derivedType) {
288
+            $this->_validateResourceType($derivedType);
289
+        }
290
+
291
+        return $derivedTypes;
292
+    }
293
+
294
+    /**
295
+     * Returns true if $resourceType represents an Entity Type which has derived
296
+     * Entity Types, else false.
297
+     * Note: Wrapper for IMetadataProvider::hasDerivedTypes method
298
+     * implementation
299
+     *
300
+     * @param ResourceType $resourceType Resource to check for derived resource
301
+     *                                   types.
302
+     *
303
+     * @return boolean
304
+     *
305
+     * @throws ODataException If the ResourceType is invalid
306
+     */
307
+    public function hasDerivedTypes(ResourceType $resourceType)
308
+    {
309
+        $this->_validateResourceType($resourceType);
310
+        return $this->metaProvider->hasDerivedTypes($resourceType);
311
+    }
312
+
313
+    /**
314
+     * Gets the ResourceAssociationSet instance for the given source association end,
315
+     * Note: Wrapper for IMetadataProvider::getResourceAssociationSet
316
+     * method implementation
317
+     *
318
+     * @param ResourceSet $set Resource set of the source association end
319
+     * @param ResourceType       $type       Resource type of the source association end
320
+     * @param ResourceProperty   $property   Resource property of the source association end
321
+     *
322
+     *
323
+     * @return ResourceAssociationSet|null Returns ResourceAssociationSet for the source
324
+     *                                             association end, NULL if no such
325
+     *                                             association end or resource set in the
326
+     *                                             other end of the association is invisible
327
+     */
328
+    public function getResourceAssociationSet(
329
+        ResourceSet $set,
330
+        ResourceType $type,
331
+        ResourceProperty $property
332
+    ) {
333
+        $type = $this->_getResourceTypeWherePropertyIsDeclared($type, $property);
334
+        $cacheKey = $set->getName() . '_' . $type->getName() . '_' . $property->getName();
335
+
336
+        if (array_key_exists($cacheKey,  $this->associationSetCache)) {
337
+            return $this->associationSetCache[$cacheKey];
338
+        }
339
+
340
+        $associationSet = $this->metaProvider->getResourceAssociationSet(
341
+            $set,
342
+            $type,
343
+            $property
344
+        );
345
+
346
+        if (!is_null($associationSet)) {
347
+            $thisAssociationSetEnd = $associationSet->getResourceAssociationSetEnd(
348
+                $set,
349
+                $type,
350
+                $property
351
+            );
352
+
353
+            $relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
354
+                $set,
355
+                $type,
356
+                $property
357
+            );
358
+
359
+            //If $thisAssociationSetEnd or $relatedAssociationSetEnd
360
+            //is null means the associationset
361
+            //we got from the IDSMP::getResourceAssociationSet is invalid.
362
+            //AssociationSet::getResourceAssociationSetEnd
363
+            //return null, if AssociationSet's End1 or End2's resourceset name
364
+            //is not matching with the name of
365
+            //resource set wrapper (param1) and resource type is not assignable
366
+            //from given resource type (param2)
367
+            if (is_null($thisAssociationSetEnd) || is_null($relatedAssociationSetEnd)) {
368
+                throw new ODataException(
369
+                    Messages::providersWrapperIDSMPGetResourceSetReturnsInvalidResourceSet(
370
+                        $set->getName(),
371
+                        $type->getFullName(),
372
+                        $property->getName()
373
+                    ),
374
+                    500
375
+                );
376
+            }
377
+
378
+            $relatedResourceSetWrapper = $this->_validateResourceSetAndGetWrapper(
379
+                $relatedAssociationSetEnd->getResourceSet()
380
+            );
381
+            if ($relatedResourceSetWrapper === null) {
382
+                $associationSet = null;
383
+            } else {
384
+                $this->_validateResourceType($thisAssociationSetEnd->getResourceType());
385
+                $this->_validateResourceType($relatedAssociationSetEnd->getResourceType());
386
+            }
387
+        }
388
+
389
+        $this->associationSetCache[$cacheKey] = $associationSet;
390
+        return $associationSet;
391
+    }
392
+
393
+    /**
394
+     * Gets the target resource set wrapper for the given navigation property,
395
+     * source resource set wrapper and the source resource type
396
+     *
397
+     * @param ResourceSetWrapper $resourceSetWrapper         Source resource set.
398
+     * @param ResourceType       $resourceType               Source resource type.
399
+     * @param ResourceProperty   $navigationResourceProperty Navigation property.
400
+     *
401
+     * @return ResourceSetWrapper|null Returns instance of ResourceSetWrapper
402
+     *     (describes the entity set and associated configuration) for the
403
+     *     given navigation property. returns NULL if resourceset for the
404
+     *     navigation property is invisible or if metadata provider returns
405
+     *     null resource association set
406
+     */
407
+    public function getResourceSetWrapperForNavigationProperty(
408
+        ResourceSetWrapper $resourceSetWrapper,
409
+        ResourceType $resourceType,
410
+        ResourceProperty $navigationResourceProperty
411
+    ) {
412
+        $associationSet = $this->getResourceAssociationSet(
413
+            $resourceSetWrapper,
414
+            $resourceType,
415
+            $navigationResourceProperty
416
+        );
417
+
418
+        if (!is_null($associationSet)) {
419
+            $relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
420
+                $resourceSetWrapper->getResourceSet(),
421
+                $resourceType,
422
+                $navigationResourceProperty
423
+            );
424
+            return $this->_validateResourceSetAndGetWrapper(
425
+                $relatedAssociationSetEnd->getResourceSet()
426
+            );
427
+        }
428
+
429
+        return null;
430
+    }
431
+
432
+    /**
433
+     * Gets the visible resource properties for the given resource type from the given resource set wrapper.
434
+     *
435
+     * @param ResourceSetWrapper $setWrapper Resource set wrapper in question.
436
+     * @param ResourceType       $resourceType       Resource type in question.
437
+     * @return ResourceProperty[] Collection of visible resource properties from the given resource set wrapper and resource type.
438
+     */
439
+    public function getResourceProperties(ResourceSetWrapper $setWrapper, ResourceType $resourceType) {
440
+        if ($resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
441
+            //Complex resource type
442
+            return $resourceType->getAllProperties();
443
+        }
444
+        //TODO: move this to doctrine annotations
445
+        $cacheKey = $setWrapper->getName() . '_' . $resourceType->getFullName();
446
+        if (!array_key_exists($cacheKey,  $this->propertyCache)) {
447
+            //Fill the cache
448
+            $this->propertyCache[$cacheKey] = array();
449
+            foreach ($resourceType->getAllProperties() as $resourceProperty) {
450
+                //Check whether this is a visible navigation property
451
+                //TODO: is this broken?? see #87
452
+                if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY
453
+                    && !is_null($this->getResourceSetWrapperForNavigationProperty($setWrapper, $resourceType, $resourceProperty))
454
+                ) {
455
+                    $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
456
+                } else {
457
+                    //primitive, bag or complex property
458
+                    $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
459
+                }
460
+            }
461
+        }
462
+        return $this->propertyCache[$cacheKey];
463
+
464
+    }
465
+
466
+    /**
467
+     * Wrapper function over _validateResourceSetAndGetWrapper function
468
+     *
469
+     * @param ResourceSet $resourceSet see the comments of _validateResourceSetAndGetWrapper
470
+     *
471
+     * @return ResourceSetWrapper|null see the comments of _validateResourceSetAndGetWrapper
472
+     */
473
+    public function validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
474
+    {
475
+        return $this->_validateResourceSetAndGetWrapper($resourceSet);
476
+    }
477
+
478
+    /**
479
+     * Gets the Edm Schema version compliance to the metadata
480
+     *
481
+     * @return EdmSchemaVersion
482
+     */
483
+    public function getEdmSchemaVersion()
484
+    {
485
+        //The minimal schema version for custom provider is 1.1
486
+        return EdmSchemaVersion::VERSION_1_DOT_1;
487
+    }
488
+
489
+    /**
490
+     * This function perform the following operations
491
+     *  (1) If the cache contain an entry [key, value] for the resourceset then
492
+     *      return the entry-value
493
+     *  (2) If the cache not contain an entry for the resourceset then validate
494
+     *      the resourceset
495
+     *            (a) If valid add entry as [resouceset_name, resourceSetWrapper]
496
+     *            (b) if not valid add entry as [resouceset_name, null]
497
+     *  Note: validating a resourceset means checking the resourceset is visible
498
+     *  or not using configuration
499
+     *
500
+     * @param ResourceSet $resourceSet The resourceset to validate and get the
501
+     *                                 wrapper for
502
+     *
503
+     * @return ResourceSetWrapper|null Returns an instance if a resource set with the given name is visible
504
+     */
505
+    private function _validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
506
+    {
507
+        $cacheKey = $resourceSet->getName();
508
+        if (array_key_exists($cacheKey, $this->setWrapperCache)) {
509
+            return $this->setWrapperCache[$cacheKey];
510
+        }
511
+
512
+        $this->_validateResourceType($resourceSet->getResourceType());
513
+        $wrapper = new ResourceSetWrapper($resourceSet, $this->config);
514
+        if ($wrapper->isVisible()) {
515
+            $this->setWrapperCache[$cacheKey] = $wrapper;
516
+        } else {
517
+            $this->setWrapperCache[$cacheKey] = null;
518
+        }
519
+
520
+        return $this->setWrapperCache[$cacheKey];
521
+    }
522
+
523
+    /**
524
+     * Validates the given instance of ResourceType
525
+     *
526
+     * @param ResourceType $resourceType The ResourceType to validate
527
+     *
528
+     * @return ResourceType
529
+     *
530
+     * @throws ODataException Exception if $resourceType is invalid
531
+     */
532
+    private function _validateResourceType(ResourceType $resourceType)
533
+    {
534
+        $cacheKey = $resourceType->getName();
535
+        if (array_key_exists($cacheKey, $this->typeCache)) {
536
+            return $this->typeCache[$cacheKey];
537
+        }
538
+
539
+        //TODO: Do validation if any for the ResourceType
540
+        $this->typeCache[$cacheKey] = $resourceType;
541
+        return $resourceType;
542
+    }
543
+
544
+    /**
545
+     * Gets the resource type on which the resource property is declared on,
546
+     * If property is not declared in the given resource type, then this
547
+     * function drill down to the inheritance hierarchy of the given resource
548
+     * type to find out the base class in which the property is declared
549
+     *
550
+     * @param ResourceType     $resourceType     The resource type to start looking
551
+     * @param ResourceProperty $resourceProperty The resource property in question
552
+     *
553
+     * @return ResourceType|null Returns reference to the ResourceType on which
554
+     *                                   the $resourceProperty is declared, NULL if
555
+     *                                   $resourceProperty is not declared anywhere
556
+     *                                   in the inheritance hierarchy
557
+     */
558
+    private function _getResourceTypeWherePropertyIsDeclared(ResourceType $resourceType,
559
+        ResourceProperty $resourceProperty
560
+    ) {
561
+        $type = $resourceType;
562
+        while ($type !== null) {
563
+            if ($type->resolvePropertyDeclaredOnThisType($resourceProperty->getName()) !== null) {
564
+                break;
565
+            }
566
+
567
+            $type = $type->getBaseType();
568
+        }
569
+
570
+        return $type;
571
+    }
572
+
573
+    /**
574
+     * Gets the underlying custom expression provider, the end developer is
575
+     * responsible for implementing IExpressionProvider if he choose for
576
+     *
577
+     * @return IExpressionProvider Instance of IExpressionProvider implementation.
578
+     *
579
+     */
580
+    public function getExpressionProvider()
581
+    {
582
+        $expressionProvider = $this->queryProvider->getExpressionProvider();
583
+        if (is_null($expressionProvider)) {
584
+            throw ODataException::createInternalServerError(Messages::providersWrapperExpressionProviderMustNotBeNullOrEmpty());
585
+        }
586
+
587
+        if (!$expressionProvider instanceof IExpressionProvider)
588
+        {
589
+            throw ODataException::createInternalServerError( Messages::providersWrapperInvalidExpressionProviderInstance() );
590
+        }
591
+
592
+        return $expressionProvider;
593
+    }
594
+
595
+    /**
596
+     * Indicates if the QueryProvider can handle ordered paging, this means respecting order, skip, and top parameters
597
+     * If the query provider can not handle ordered paging, it must return the entire result set and POData will
598
+     * perform the ordering and paging
599
+     *
600
+     * @return Boolean True if the query provider can handle ordered paging, false if POData should perform the paging
601
+     */
602
+    public function handlesOrderedPaging()
603
+    {
604
+        return $this->queryProvider->handlesOrderedPaging();
605
+    }
606
+
607
+
608
+    private function ValidateQueryResult($queryResult, QueryType $queryType, $methodName){
609
+        if (!$queryResult instanceof QueryResult) {
610
+            throw ODataException::createInternalServerError(
611
+                Messages::queryProviderReturnsNonQueryResult($methodName)
612
+            );
613
+        }
614
+
615
+        if($queryType == QueryType::COUNT() || $queryType == QueryType::ENTITIES_WITH_COUNT()){
616
+            //and the provider is supposed to handle the ordered paging they must return a count!
617
+            if($this->queryProvider->handlesOrderedPaging() && !is_numeric($queryResult->count)){
618
+                throw ODataException::createInternalServerError(
619
+                    Messages::queryProviderResultCountMissing($methodName, $queryType)
620
+                );
621
+            }
622
+
623
+            //If POData is supposed to handle the ordered aging they must return results! (possibly empty)
624
+            if(!$this->queryProvider->handlesOrderedPaging() && !is_array($queryResult->results)){
625
+                throw ODataException::createInternalServerError(
626
+                    Messages::queryProviderResultsMissing($methodName, $queryType)
627
+                );
628
+            }
629
+        }
630
+
631
+        if(($queryType == QueryType::ENTITIES() || $queryType == QueryType::ENTITIES_WITH_COUNT()) && !is_array($queryResult->results)){
632
+            throw ODataException::createInternalServerError(
633
+                Messages::queryProviderResultsMissing($methodName, $queryType)
634
+            );
635
+        }
636
+    }
637
+
638
+    /**
639
+     * Gets collection of entities belongs to an entity set
640
+     *
641
+     * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
642
+     * @param ResourceSet $resourceSet The entity set containing the entities that need to be fetched
643
+     * @param FilterInfo $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
644
+     * @param InternalOrderByInfo $orderBy The orderBy information
645
+     * @param int $top The top count
646
+     * @param int $skip The skip count
647
+     *
648
+     * @return QueryResult
649
+     */
650
+    public function getResourceSet(QueryType $queryType, ResourceSet $resourceSet, $filterInfo, $orderBy, $top, $skip, $skiptoken = null, $expansion=null)
651
+    {
652
+
653
+        $queryResult = $this->queryProvider->getResourceSet(
654
+            $queryType,
655
+            $resourceSet,
656
+            $filterInfo,
657
+            $orderBy,
658
+            $top,
659
+            $skip,
660
+            $skiptoken,
661
+            $expansion
662
+        );
663
+
664
+        $this->validateQueryResult($queryResult, $queryType, 'IQueryProvider::getResourceSet');
665
+
666
+        return $queryResult;
667
+    }
668
+
669
+
670
+
671
+    /**
672
+     * Gets an entity instance from an entity set identified by a key
673
+     *
674
+     * @param ResourceSet $resourceSet The entity set containing the entity to fetch
675
+     * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
676
+     *
677
+     * @return object|null Returns entity instance if found else null
678
+     */
679
+    public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
680
+    {
681
+        $entityInstance = $this->queryProvider->getResourceFromResourceSet( $resourceSet, $keyDescriptor );
682
+        $this->_validateEntityInstance(
683
+            $entityInstance,
684
+            $resourceSet,
685
+            $keyDescriptor,
686
+            'IQueryProvider::getResourceFromResourceSet'
687
+        );
688
+        return $entityInstance;
689
+    }
690
+
691
+    /**
692
+     * Puts an entity instance to entity set identified by a key
693
+     *
694
+     * @param ResourceSet $resourceSet The entity set containing the entity to update
695
+     * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
696
+     *
697
+     * @return bool|null Returns result of executiong query
698
+     */
699
+    public function putResource(
700
+        ResourceSet $resourceSet,
701
+        KeyDescriptor $keyDescriptor,
702
+        $data
703
+    ) {
704
+        $queryResult = $this->queryProvider->putResource(
705
+            $resourceSet,
706
+            $keyDescriptor,
707
+            $data
708
+        );
709
+
710
+        return $queryResult;
711
+    }
712
+
713
+    /**
714
+     * Posts an entity instance to entity set identified by a key
715
+     *
716
+     * @param ResourceSet $resourceSet The entity set containing the entity to update
717
+     * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
718
+     *
719
+     * @return bool|null Returns result of executiong query
720
+     */
721
+    public function postResource(
722
+        ResourceSet $resourceSet,
723
+        $data
724
+    ) {
725
+        $queryResult = $this->queryProvider->postResource(
726
+            $resourceSet,
727
+            $data
728
+        );
729
+
730
+        return $queryResult;
731
+    }
732
+
733
+    /**
734
+     * Get related resource set for a resource
735
+     *
736
+     * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
737
+     * @param ResourceSet $sourceResourceSet The entity set containing the source entity
738
+     * @param object $sourceEntity The source entity instance.
739
+     * @param ResourceSet      $targetResourceSet    The resource set of containing the target of the navigation property
740
+     * @param ResourceProperty $targetProperty       The navigation property to retrieve
741
+     * @param FilterInfo  $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
742
+     * @param mixed $orderBy sorted order if we want to get the data in some specific order
743
+     * @param int $top number of records which  need to be skip
744
+     * @param String $skip value indicating what records to skip
745
+     *
746
+     * @return QueryResult
747
+     *
748
+     * @throws ODataException
749
+     */
750
+    public function getRelatedResourceSet(
751
+        QueryType $queryType,
752
+        ResourceSet $sourceResourceSet,
753
+        $sourceEntity,
754
+        ResourceSet $targetResourceSet,
755
+        ResourceProperty $targetProperty,
756
+        $filterInfo,
757
+        $orderBy,
758
+        $top,
759
+        $skip
760
+    ) {
761
+
762
+        $queryResult = $this->queryProvider->getRelatedResourceSet(
763
+            $queryType,
764
+            $sourceResourceSet,
765
+            $sourceEntity,
766
+            $targetResourceSet,
767
+            $targetProperty,
768
+            $filterInfo,
769
+            $orderBy,
770
+            $top,
771
+            $skip
772
+        );
773
+
774
+
775
+        $this->validateQueryResult($queryResult, $queryType, 'IQueryProvider::getRelatedResourceSet');
776
+
777
+
778
+        return $queryResult;
779
+    }
780
+
781
+    /**
782
+     * Gets a related entity instance from an entity set identified by a key
783
+     *
784
+     * @param ResourceSet      $sourceResourceSet The entity set related to the entity to be fetched.
785
+     * @param object           $sourceEntity      The related entity instance.
786
+     * @param ResourceSet      $targetResourceSet The entity set from which entity needs to be fetched.
787
+     * @param ResourceProperty $targetProperty    The metadata of the target property.
788
+     * @param KeyDescriptor    $keyDescriptor     The key to identify the entity to be fetched.
789
+     *
790
+     *
791
+     * @return object|null Returns entity instance if found else null
792
+     */
793
+    public function getResourceFromRelatedResourceSet(ResourceSet $sourceResourceSet,
794
+        $sourceEntity, ResourceSet $targetResourceSet, ResourceProperty $targetProperty,
795
+        KeyDescriptor $keyDescriptor
796
+    ) {
797
+        $entityInstance = $this->queryProvider->getResourceFromRelatedResourceSet(
798
+            $sourceResourceSet,
799
+            $sourceEntity,
800
+            $targetResourceSet,
801
+            $targetProperty,
802
+            $keyDescriptor
803
+        );
804
+
805
+        $this->_validateEntityInstance(
806
+            $entityInstance, $targetResourceSet,
807
+            $keyDescriptor,
808
+            'IQueryProvider::getResourceFromRelatedResourceSet'
809
+        );
810
+        return $entityInstance;
811
+    }
812
+
813
+    /**
814
+     * Get related resource for a resource
815
+     *
816
+     * @param ResourceSet      $sourceResourceSet The source resource set
817
+     * @param object           $sourceEntity      The source resource
818
+     * @param ResourceSet      $targetResourceSet The resource set of the navigation
819
+     *                                            property
820
+     * @param ResourceProperty $targetProperty    The navigation property to be
821
+     *                                            retrieved
822
+     *
823
+     * @return object|null The related resource if exists else null
824
+     */
825
+    public function getRelatedResourceReference(ResourceSet $sourceResourceSet,
826
+        $sourceEntity, ResourceSet $targetResourceSet,
827
+        ResourceProperty $targetProperty
828
+    ) {
829
+        $entityInstance = $this->queryProvider->getRelatedResourceReference(
830
+            $sourceResourceSet,
831
+            $sourceEntity,
832
+            $targetResourceSet,
833
+            $targetProperty
834
+        );
835
+
836
+        // we will not throw error if the resource reference is null
837
+        // e.g. Orders(1234)/Customer => Customer can be null, this is
838
+        // allowed if Customer is last segment. consider the following:
839
+        // Orders(1234)/Customer/Orders => here if Customer is null then
840
+        // the UriProcessor will throw error.
841
+        if (!is_null($entityInstance)) {
842
+            $entityName
843
+                = $targetResourceSet
844
+                    ->getResourceType()
845
+                    ->getInstanceType()
846
+                    ->getName();
847
+            if (!is_object($entityInstance)
848
+                || !($entityInstance instanceof $entityName)
849
+            ) {
850
+                throw ODataException::createInternalServerError(
851
+                    Messages::providersWrapperIDSQPMethodReturnsUnExpectedType(
852
+                        $entityName,
853
+                        'IQueryProvider::getRelatedResourceReference'
854
+                    )
855
+                );
856
+            }
857
+
858
+            foreach ($targetProperty->getResourceType()->getKeyProperties()
859
+            as $keyName => $resourceProperty) {
860
+                try {
861
+                    $keyProperty = new \ReflectionProperty(
862
+                        $entityInstance,
863
+                        $keyName
864
+                    );
865
+                    $keyProperty->setAccessible(true);
866
+                    $keyValue = $keyProperty->getValue($entityInstance);
867
+                    if (is_null($keyValue)) {
868
+                        throw ODataException::createInternalServerError(
869
+                            Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties('IDSQP::getRelatedResourceReference')
870
+                        );
871
+                    }
872
+                } catch (\ReflectionException $reflectionException) {
873
+                    //throw ODataException::createInternalServerError(
874
+                    //    Messages::orderByParserFailedToAccessOrInitializeProperty(
875
+                    //        $resourceProperty->getName(), $resourceType->getName()
876
+                    //    )
877
+                    //);
878
+                }
879
+            }
880
+        }
881
+
882
+        return $entityInstance;
883
+    }
884
+
885
+    /**
886
+     * Validate the given entity instance.
887
+     *
888
+     * @param object        $entityInstance Entity instance to validate
889
+     * @param ResourceSet   &$resourceSet   Resource set to which the entity
890
+     *                                      instance belongs to.
891
+     * @param KeyDescriptor &$keyDescriptor The key descriptor.
892
+     * @param string        $methodName     Method from which this function
893
+     *                                      invoked.
894
+     *
895
+     * @return void
896
+     *
897
+     * @throws ODataException
898
+     */
899
+    private function _validateEntityInstance($entityInstance,
900
+        ResourceSet &$resourceSet,
901
+        KeyDescriptor &$keyDescriptor,
902
+        $methodName
903
+    ) {
904
+        if (is_null($entityInstance)) {
905
+            throw ODataException::createResourceNotFoundError($resourceSet->getName());
906
+        }
907
+
908
+        $entityName = $resourceSet->getResourceType()->getInstanceType()->getName();
909
+        if (!is_object($entityInstance)
910
+            || !($entityInstance instanceof $entityName)
911
+        ) {
912
+            throw ODataException::createInternalServerError(
913
+                Messages::providersWrapperIDSQPMethodReturnsUnExpectedType(
914
+                    $entityName,
915
+                    $methodName
916
+                )
917
+            );
918
+        }
919
+
920
+        foreach ($keyDescriptor->getValidatedNamedValues()
921
+            as $keyName => $valueDescription) {
922
+            try {
923
+                $keyProperty = new \ReflectionProperty($entityInstance, $keyName);
924
+                $keyProperty->setAccessible(true);
925
+                $keyValue = $keyProperty->getValue($entityInstance);
926
+                if (is_null($keyValue)) {
927
+                    throw ODataException::createInternalServerError(
928
+                        Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties($methodName)
929
+                    );
930
+                }
931
+
932
+                $convertedValue
933
+                    = $valueDescription[1]->convert($valueDescription[0]);
934
+                if ($keyValue != $convertedValue) {
935
+                    throw ODataException::createInternalServerError(
936
+                        Messages::providersWrapperIDSQPMethodReturnsInstanceWithNonMatchingKeys($methodName)
937
+                    );
938
+                }
939
+            } catch (\ReflectionException $reflectionException) {
940
+                //throw ODataException::createInternalServerError(
941
+                //  Messages::orderByParserFailedToAccessOrInitializeProperty(
942
+                //      $resourceProperty->getName(), $resourceType->getName()
943
+                //  )
944
+                //);
945
+            }
946
+        }
947
+    }
948
+
949
+    /**
950
+     * Assert that the given condition is true.
951
+     *
952
+     * @param boolean $condition         Condition to be asserted.
953
+     * @param string  $conditionAsString String containing message incase
954
+     *                                   if assertion fails.
955
+     *
956
+     * @throws InvalidOperationException Incase if assertion fails.
957
+     *
958
+     * @return void
959
+     */
960
+    protected function assert($condition, $conditionAsString)
961
+    {
962
+        if (!$condition) {
963
+            throw new InvalidOperationException("Unexpected state, expecting $conditionAsString");
964
+        }
965
+    }
966 966
 }
967 967
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 		foreach ($resourceSets as $resourceSet) {
180 180
 			$name = $resourceSet->getName();
181 181
 			if (in_array($name, $resourceSetNames)) {
182
-				throw new ODataException(Messages::providersWrapperEntitySetNameShouldBeUnique($name), 500 );
182
+				throw new ODataException(Messages::providersWrapperEntitySetNameShouldBeUnique($name), 500);
183 183
 			}
184 184
 
185 185
 			$resourceSetNames[] = $name;
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
 		$type = $this->_getResourceTypeWherePropertyIsDeclared($type, $property);
334 334
 		$cacheKey = $set->getName() . '_' . $type->getName() . '_' . $property->getName();
335 335
 
336
-		if (array_key_exists($cacheKey,  $this->associationSetCache)) {
336
+		if (array_key_exists($cacheKey, $this->associationSetCache)) {
337 337
 			return $this->associationSetCache[$cacheKey];
338 338
 		}
339 339
 
@@ -443,7 +443,7 @@  discard block
 block discarded – undo
443 443
 		}
444 444
 		//TODO: move this to doctrine annotations
445 445
 		$cacheKey = $setWrapper->getName() . '_' . $resourceType->getFullName();
446
-		if (!array_key_exists($cacheKey,  $this->propertyCache)) {
446
+		if (!array_key_exists($cacheKey, $this->propertyCache)) {
447 447
 			//Fill the cache
448 448
 			$this->propertyCache[$cacheKey] = array();
449 449
 			foreach ($resourceType->getAllProperties() as $resourceProperty) {
@@ -586,7 +586,7 @@  discard block
 block discarded – undo
586 586
 
587 587
 		if (!$expressionProvider instanceof IExpressionProvider)
588 588
 		{
589
-			throw ODataException::createInternalServerError( Messages::providersWrapperInvalidExpressionProviderInstance() );
589
+			throw ODataException::createInternalServerError(Messages::providersWrapperInvalidExpressionProviderInstance());
590 590
 		}
591 591
 
592 592
 		return $expressionProvider;
@@ -605,30 +605,30 @@  discard block
 block discarded – undo
605 605
 	}
606 606
 
607 607
 
608
-	private function ValidateQueryResult($queryResult, QueryType $queryType, $methodName){
608
+	private function ValidateQueryResult($queryResult, QueryType $queryType, $methodName) {
609 609
 		if (!$queryResult instanceof QueryResult) {
610 610
 			throw ODataException::createInternalServerError(
611 611
 				Messages::queryProviderReturnsNonQueryResult($methodName)
612 612
 			);
613 613
 		}
614 614
 
615
-		if($queryType == QueryType::COUNT() || $queryType == QueryType::ENTITIES_WITH_COUNT()){
615
+		if ($queryType == QueryType::COUNT() || $queryType == QueryType::ENTITIES_WITH_COUNT()) {
616 616
 			//and the provider is supposed to handle the ordered paging they must return a count!
617
-			if($this->queryProvider->handlesOrderedPaging() && !is_numeric($queryResult->count)){
617
+			if ($this->queryProvider->handlesOrderedPaging() && !is_numeric($queryResult->count)) {
618 618
 				throw ODataException::createInternalServerError(
619 619
 					Messages::queryProviderResultCountMissing($methodName, $queryType)
620 620
 				);
621 621
 			}
622 622
 
623 623
 			//If POData is supposed to handle the ordered aging they must return results! (possibly empty)
624
-			if(!$this->queryProvider->handlesOrderedPaging() && !is_array($queryResult->results)){
624
+			if (!$this->queryProvider->handlesOrderedPaging() && !is_array($queryResult->results)) {
625 625
 				throw ODataException::createInternalServerError(
626 626
 					Messages::queryProviderResultsMissing($methodName, $queryType)
627 627
 				);
628 628
 			}
629 629
 		}
630 630
 
631
-		if(($queryType == QueryType::ENTITIES() || $queryType == QueryType::ENTITIES_WITH_COUNT()) && !is_array($queryResult->results)){
631
+		if (($queryType == QueryType::ENTITIES() || $queryType == QueryType::ENTITIES_WITH_COUNT()) && !is_array($queryResult->results)) {
632 632
 			throw ODataException::createInternalServerError(
633 633
 				Messages::queryProviderResultsMissing($methodName, $queryType)
634 634
 			);
@@ -647,7 +647,7 @@  discard block
 block discarded – undo
647 647
 	 *
648 648
 	 * @return QueryResult
649 649
 	 */
650
-	public function getResourceSet(QueryType $queryType, ResourceSet $resourceSet, $filterInfo, $orderBy, $top, $skip, $skiptoken = null, $expansion=null)
650
+	public function getResourceSet(QueryType $queryType, ResourceSet $resourceSet, $filterInfo, $orderBy, $top, $skip, $skiptoken = null, $expansion = null)
651 651
 	{
652 652
 
653 653
 		$queryResult = $this->queryProvider->getResourceSet(
@@ -678,7 +678,7 @@  discard block
 block discarded – undo
678 678
 	 */
679 679
 	public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
680 680
 	{
681
-		$entityInstance = $this->queryProvider->getResourceFromResourceSet( $resourceSet, $keyDescriptor );
681
+		$entityInstance = $this->queryProvider->getResourceFromResourceSet($resourceSet, $keyDescriptor);
682 682
 		$this->_validateEntityInstance(
683 683
 			$entityInstance,
684 684
 			$resourceSet,
@@ -897,8 +897,8 @@  discard block
 block discarded – undo
897 897
 	 * @throws ODataException
898 898
 	 */
899 899
 	private function _validateEntityInstance($entityInstance,
900
-		ResourceSet &$resourceSet,
901
-		KeyDescriptor &$keyDescriptor,
900
+		ResourceSet & $resourceSet,
901
+		KeyDescriptor & $keyDescriptor,
902 902
 		$methodName
903 903
 	) {
904 904
 		if (is_null($entityInstance)) {
Please login to merge, or discard this patch.
src/POData/UriProcessor/UriProcessor.php 3 patches
Indentation   +72 added lines, -72 removed lines patch added patch discarded remove patch
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
         $absoluteServiceUri = $service->getHost()->getAbsoluteServiceUri();
100 100
 
101 101
         if (!$absoluteServiceUri->isBaseOf($absoluteRequestUri)) {
102
-			throw ODataException::createInternalServerError(
102
+            throw ODataException::createInternalServerError(
103 103
                 Messages::uriProcessorRequestUriDoesNotHaveTheRightBaseUri(
104 104
                     $absoluteRequestUri->getUrlAsString(),
105 105
                     $absoluteServiceUri->getUrlAsString()
@@ -109,9 +109,9 @@  discard block
 block discarded – undo
109 109
 
110 110
         $uriProcessor = new UriProcessor($service);
111 111
         //Parse the resource path part of the request Uri.
112
-		$uriProcessor->request = ResourcePathProcessor::process($service);
112
+        $uriProcessor->request = ResourcePathProcessor::process($service);
113 113
 
114
-	    $uriProcessor->request->setUriProcessor($uriProcessor);
114
+        $uriProcessor->request->setUriProcessor($uriProcessor);
115 115
 
116 116
         //Parse the query string options of the request Uri.
117 117
         QueryProcessor::process( $uriProcessor->request, $service );
@@ -224,11 +224,11 @@  discard block
 block discarded – undo
224 224
 
225 225
             $requestTargetKind = $segment->getTargetKind();
226 226
 
227
-	        if ($segment->getTargetSource() == TargetSource::ENTITY_SET) {
227
+            if ($segment->getTargetSource() == TargetSource::ENTITY_SET) {
228 228
                 $this->handleSegmentTargetsToResourceSet($segment);
229 229
             } else if ($requestTargetKind == TargetKind::RESOURCE()) {
230 230
                 if (is_null($segment->getPrevious()->getResult())) {
231
-					throw ODataException::createResourceNotFoundError(
231
+                    throw ODataException::createResourceNotFoundError(
232 232
                         $segment->getPrevious()->getIdentifier()
233 233
                     );
234 234
                 }
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
             } else {
244 244
                 if ($requestTargetKind == TargetKind::MEDIA_RESOURCE()) {
245 245
                     if (is_null($segment->getPrevious()->getResult())) {
246
-						throw ODataException::createResourceNotFoundError(
246
+                        throw ODataException::createResourceNotFoundError(
247 247
                             $segment->getPrevious()->getIdentifier()
248 248
                         );
249 249
                     }
@@ -256,14 +256,14 @@  discard block
 block discarded – undo
256 256
                     break;
257 257
                 }
258 258
 
259
-	            $value = $segment->getPrevious()->getResult();
259
+                $value = $segment->getPrevious()->getResult();
260 260
                 while (!is_null($segment)) {
261
-	                //TODO: what exactly is this doing here?  Once a null's found it seems everything will be null
261
+                    //TODO: what exactly is this doing here?  Once a null's found it seems everything will be null
262 262
                     if (!is_null($value)) {
263 263
                         $value = null;
264 264
                     } else {
265 265
                         try {
266
-	                        //see #88
266
+                            //see #88
267 267
                             $property = new \ReflectionProperty($value, $segment->getIdentifier());
268 268
                             $value = $property->getValue($value);
269 269
                         } catch (\ReflectionException $reflectionException) {
@@ -288,9 +288,9 @@  discard block
 block discarded – undo
288 288
             }
289 289
         }
290 290
 
291
-         // Apply $select and $expand options to result set, this function will be always applied
292
-         // irrespective of return value of IDSQP2::canApplyQueryOptions which means library will
293
-         // not delegate $expand/$select operation to IDSQP2 implementation
291
+            // Apply $select and $expand options to result set, this function will be always applied
292
+            // irrespective of return value of IDSQP2::canApplyQueryOptions which means library will
293
+            // not delegate $expand/$select operation to IDSQP2 implementation
294 294
         $this->handleExpansion();
295 295
     }
296 296
 
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
             $internalskiptokentinfo = $this->request->getInternalSkipTokenInfo();
316 316
 
317 317
             $queryResult = $this->providers->getResourceSet(
318
-	            $this->request->queryType,
318
+                $this->request->queryType,
319 319
                 $segment->getTargetResourceSetWrapper(),
320 320
                 $this->request->getFilterInfo(),
321 321
                 $this->request->getInternalOrderByInfo(),
@@ -354,13 +354,13 @@  discard block
 block discarded – undo
354 354
                 $segment->setResult($entityInstance);
355 355
             } else {
356 356
                 $queryResult = $this->providers->getRelatedResourceSet(
357
-	                $this->request->queryType,
357
+                    $this->request->queryType,
358 358
                     $segment->getPrevious()->getTargetResourceSetWrapper(),
359 359
                     $segment->getPrevious()->getResult(),
360 360
                     $segment->getTargetResourceSetWrapper(),
361 361
                     $segment->getProjectedProperty(),
362 362
                     $this->request->getFilterInfo(),
363
-	                //TODO: why are these null?  see #98
363
+                    //TODO: why are these null?  see #98
364 364
                     null, // $orderby
365 365
                     null, // $top
366 366
                     null  // $skip
@@ -397,19 +397,19 @@  discard block
 block discarded – undo
397 397
             return;
398 398
         }
399 399
 
400
-	    //TODO: I'm not really happy with this..i think i'd rather keep the result the QueryResult
401
-	    //not even bother with the setCountValue stuff (shouldn't counts be on segments?)
402
-	    //and just work with the QueryResult in the object model serializer
403
-	    $result = $segment->getResult();
400
+        //TODO: I'm not really happy with this..i think i'd rather keep the result the QueryResult
401
+        //not even bother with the setCountValue stuff (shouldn't counts be on segments?)
402
+        //and just work with the QueryResult in the object model serializer
403
+        $result = $segment->getResult();
404 404
 
405
-	    if(!$result instanceof QueryResult){
406
-		    //If the segment isn't a query result, then there's no paging or counting to be done
407
-		    return;
405
+        if(!$result instanceof QueryResult){
406
+            //If the segment isn't a query result, then there's no paging or counting to be done
407
+            return;
408 408
         }
409 409
 
410 410
 
411 411
         // Note $inlinecount=allpages means include the total count regardless of paging..so we set the counts first
412
-	    // regardless if POData does the paging or not.
412
+        // regardless if POData does the paging or not.
413 413
         if ($this->request->queryType == QueryType::ENTITIES_WITH_COUNT()) {
414 414
             if ($this->providers->handlesOrderedPaging()) {
415 415
                 $this->request->setCountValue($result->count);
@@ -418,57 +418,57 @@  discard block
 block discarded – undo
418 418
             }
419 419
         }
420 420
 
421
-	    //Have POData perform paging if necessary
422
-	    if(!$this->providers->handlesOrderedPaging() && !empty($result->results)){
423
-			$result->results = $this->performPaging($result->results);
424
-	    }
425
-
426
-	    //a bit surprising, but $skip and $top affects $count so update it here, not above
427
-	    //IE  data.svc/Collection/$count?$top=10 returns 10 even if Collection has 11+ entries
428
-	    if ($this->request->queryType == QueryType::COUNT()) {
429
-		    if ($this->providers->handlesOrderedPaging()) {
430
-			    $this->request->setCountValue($result->count);
431
-		    } else {
432
-			    $this->request->setCountValue(count($result->results));
433
-		    }
434
-	    }
421
+        //Have POData perform paging if necessary
422
+        if(!$this->providers->handlesOrderedPaging() && !empty($result->results)){
423
+            $result->results = $this->performPaging($result->results);
424
+        }
425
+
426
+        //a bit surprising, but $skip and $top affects $count so update it here, not above
427
+        //IE  data.svc/Collection/$count?$top=10 returns 10 even if Collection has 11+ entries
428
+        if ($this->request->queryType == QueryType::COUNT()) {
429
+            if ($this->providers->handlesOrderedPaging()) {
430
+                $this->request->setCountValue($result->count);
431
+            } else {
432
+                $this->request->setCountValue(count($result->results));
433
+            }
434
+        }
435 435
 
436 436
         $segment->setResult($result->results);
437 437
     }
438 438
 
439
-	/**
440
-	 * If the provider does not perform the paging (ordering, top, skip) then this method does it
441
-	 *
442
-	 * @param array $result
443
-	 * @return array
444
-	 */
445
-	private function performPaging(array $result)
446
-	{
447
-		//Apply (implicit and explicit) $orderby option
448
-		$internalOrderByInfo = $this->request->getInternalOrderByInfo();
449
-		if (!is_null($internalOrderByInfo)) {
450
-			$orderByFunction = $internalOrderByInfo->getSorterFunction()->getReference();
451
-			usort($result, $orderByFunction);
452
-		}
453
-
454
-		//Apply $skiptoken option
455
-		$internalSkipTokenInfo = $this->request->getInternalSkipTokenInfo();
456
-		if (!is_null($internalSkipTokenInfo)) {
457
-			$matchingIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($result);
458
-			$result = array_slice($result, $matchingIndex);
459
-		}
460
-
461
-		//Apply $top and $skip option
462
-		if (!empty($result)) {
463
-			$top  = $this->request->getTopCount();
464
-			$skip = $this->request->getSkipCount();
465
-			if(is_null($skip)) $skip = 0;
466
-
467
-			$result = array_slice($result, $skip, $top);
468
-		}
469
-
470
-		return $result;
471
-	}
439
+    /**
440
+     * If the provider does not perform the paging (ordering, top, skip) then this method does it
441
+     *
442
+     * @param array $result
443
+     * @return array
444
+     */
445
+    private function performPaging(array $result)
446
+    {
447
+        //Apply (implicit and explicit) $orderby option
448
+        $internalOrderByInfo = $this->request->getInternalOrderByInfo();
449
+        if (!is_null($internalOrderByInfo)) {
450
+            $orderByFunction = $internalOrderByInfo->getSorterFunction()->getReference();
451
+            usort($result, $orderByFunction);
452
+        }
453
+
454
+        //Apply $skiptoken option
455
+        $internalSkipTokenInfo = $this->request->getInternalSkipTokenInfo();
456
+        if (!is_null($internalSkipTokenInfo)) {
457
+            $matchingIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($result);
458
+            $result = array_slice($result, $matchingIndex);
459
+        }
460
+
461
+        //Apply $top and $skip option
462
+        if (!empty($result)) {
463
+            $top  = $this->request->getTopCount();
464
+            $skip = $this->request->getSkipCount();
465
+            if(is_null($skip)) $skip = 0;
466
+
467
+            $result = array_slice($result, $skip, $top);
468
+        }
469
+
470
+        return $result;
471
+    }
472 472
 
473 473
 
474 474
     /**
@@ -511,7 +511,7 @@  discard block
 block discarded – undo
511 511
                         $resourceSetOfProjectedProperty = $expandedProjectionNode->getResourceSetWrapper()->getResourceSet();
512 512
                         $projectedProperty1 = $expandedProjectionNode->getResourceProperty();
513 513
                         $result1 = $this->providers->getRelatedResourceSet(
514
-	                        QueryType::ENTITIES(), //it's always entities for an expansion
514
+                            QueryType::ENTITIES(), //it's always entities for an expansion
515 515
                             $currentResourceSet,
516 516
                             $entry,
517 517
                             $resourceSetOfProjectedProperty,
@@ -570,7 +570,7 @@  discard block
 block discarded – undo
570 570
                     $resourceSetOfProjectedProperty2 = $expandedProjectionNode->getResourceSetWrapper()->getResourceSet();
571 571
                     $projectedProperty4 = $expandedProjectionNode->getResourceProperty();
572 572
                     $result1 = $this->providers->getRelatedResourceSet(
573
-	                    QueryType::ENTITIES(), //it's always entities for an expansion
573
+                        QueryType::ENTITIES(), //it's always entities for an expansion
574 574
                         $currentResourceSet2,
575 575
                         $result,
576 576
                         $resourceSetOfProjectedProperty2,
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
 	    $uriProcessor->request->setUriProcessor($uriProcessor);
115 115
 
116 116
         //Parse the query string options of the request Uri.
117
-        QueryProcessor::process( $uriProcessor->request, $service );
117
+        QueryProcessor::process($uriProcessor->request, $service);
118 118
 
119 119
         return $uriProcessor;
120 120
     }
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
      */
169 169
     protected function executePut()
170 170
     {
171
-        return $this->executeBase(function ($uriProcessor, $segment) {
171
+        return $this->executeBase(function($uriProcessor, $segment) {
172 172
             $requestMethod = $uriProcessor->service->getOperationContext()->incomingRequest()->getMethod();
173 173
             $resourceSet = $segment->getTargetResourceSetWrapper();
174 174
             $keyDescriptor = $segment->getKeyDescriptor();
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
      */
193 193
     protected function executePost()
194 194
     {
195
-        return $this->executeBase(function ($uriProcessor, $segment) {
195
+        return $this->executeBase(function($uriProcessor, $segment) {
196 196
             $requestMethod = $uriProcessor->service->getOperationContext()->incomingRequest()->getMethod();
197 197
             $resourceSet = $segment->getTargetResourceSetWrapper();
198 198
             $keyDescriptor = $segment->getKeyDescriptor();
@@ -301,7 +301,7 @@  discard block
 block discarded – undo
301 301
      * @return void
302 302
      *
303 303
      */
304
-    private function handleSegmentTargetsToResourceSet( SegmentDescriptor $segment ) {
304
+    private function handleSegmentTargetsToResourceSet(SegmentDescriptor $segment) {
305 305
         if ($segment->isSingleResult()) {
306 306
             $entityInstance = $this->providers->getResourceFromResourceSet(
307 307
                 $segment->getTargetResourceSetWrapper(),
@@ -402,7 +402,7 @@  discard block
 block discarded – undo
402 402
 	    //and just work with the QueryResult in the object model serializer
403 403
 	    $result = $segment->getResult();
404 404
 
405
-	    if(!$result instanceof QueryResult){
405
+	    if (!$result instanceof QueryResult) {
406 406
 		    //If the segment isn't a query result, then there's no paging or counting to be done
407 407
 		    return;
408 408
         }
@@ -419,7 +419,7 @@  discard block
 block discarded – undo
419 419
         }
420 420
 
421 421
 	    //Have POData perform paging if necessary
422
-	    if(!$this->providers->handlesOrderedPaging() && !empty($result->results)){
422
+	    if (!$this->providers->handlesOrderedPaging() && !empty($result->results)) {
423 423
 			$result->results = $this->performPaging($result->results);
424 424
 	    }
425 425
 
@@ -462,7 +462,7 @@  discard block
 block discarded – undo
462 462
 		if (!empty($result)) {
463 463
 			$top  = $this->request->getTopCount();
464 464
 			$skip = $this->request->getSkipCount();
465
-			if(is_null($skip)) $skip = 0;
465
+			if (is_null($skip)) $skip = 0;
466 466
 
467 467
 			$result = array_slice($result, $skip, $top);
468 468
 		}
@@ -669,7 +669,7 @@  discard block
 block discarded – undo
669 669
      * @throws InvalidOperationException If this function invoked with non-navigation
670 670
      *                                   property instance.
671 671
      */
672
-    private function _pushSegmentForNavigationProperty(ResourceProperty &$resourceProperty)
672
+    private function _pushSegmentForNavigationProperty(ResourceProperty & $resourceProperty)
673 673
     {
674 674
         if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) {
675 675
             $this->assert(
@@ -764,7 +764,7 @@  discard block
 block discarded – undo
764 764
      *
765 765
      * @return bool true if the segment was push, false otherwise
766 766
      */
767
-    private function _pushSegment($segmentName, ResourceSetWrapper &$resourceSetWrapper)
767
+    private function _pushSegment($segmentName, ResourceSetWrapper & $resourceSetWrapper)
768 768
     {
769 769
         $rootProjectionNode = $this->request->getRootProjectionNode();
770 770
         if (!is_null($rootProjectionNode)
Please login to merge, or discard this patch.
Braces   +6 added lines, -7 removed lines patch added patch discarded remove patch
@@ -143,14 +143,11 @@  discard block
 block discarded – undo
143 143
         $requestMethod = $operationContext->incomingRequest()->getMethod();
144 144
         if ($requestMethod == HTTPRequestMethod::GET()) {
145 145
             $this->executeGet();
146
-        }
147
-        elseif ($requestMethod == HTTPRequestMethod::PUT()) {
146
+        } elseif ($requestMethod == HTTPRequestMethod::PUT()) {
148 147
             $this->executePut();
149
-        }
150
-        elseif ($requestMethod == HTTPRequestMethod::POST()) {
148
+        } elseif ($requestMethod == HTTPRequestMethod::POST()) {
151 149
             $this->executePost();
152
-        }
153
-        else {
150
+        } else {
154 151
             throw ODataException::createNotImplementedError(Messages::unsupportedMethod($requestMethod));
155 152
         }
156 153
     }
@@ -462,7 +459,9 @@  discard block
 block discarded – undo
462 459
 		if (!empty($result)) {
463 460
 			$top  = $this->request->getTopCount();
464 461
 			$skip = $this->request->getSkipCount();
465
-			if(is_null($skip)) $skip = 0;
462
+			if(is_null($skip)) {
463
+			    $skip = 0;
464
+			}
466 465
 
467 466
 			$result = array_slice($result, $skip, $top);
468 467
 		}
Please login to merge, or discard this patch.
src/POData/Common/Messages.php 1 patch
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
      */
172 172
     public static function expressionParser2NonPrimitivePropertyNotAllowed()
173 173
     {
174
-    	return 'This data service does not support non-primitive types in the expression';
174
+        return 'This data service does not support non-primitive types in the expression';
175 175
     }
176 176
 
177 177
     /**
@@ -604,7 +604,7 @@  discard block
 block discarded – undo
604 604
      */
605 605
     public static function providersWrapperInvalidExpressionProviderInstance()
606 606
     {
607
-    	return 'The value returned by IQueryProvider::getExpressionProvider method must be an implementation of IExpressionProvider';
607
+        return 'The value returned by IQueryProvider::getExpressionProvider method must be an implementation of IExpressionProvider';
608 608
     }
609 609
 
610 610
     /**
Please login to merge, or discard this patch.