/** * Iterate over the resource type of the given resource set, * derived resource types base resource types and complex types * used in these resource types and cache them. * * @param ResourceSetWrapper $resourceSetWrapper The resource set to inspect * * @return void * * @throws InvalidOperationException Throws exception in floowing cases: * (1) If IDSMP::getDerivedTypes returns any type other than null or array * (2) If Named streams are found on derived types */ private function _populateResourceTypeForSet(ResourceSetWrapper $resourceSetWrapper) { $derivedTypes = $this->metadataQueryproviderWrapper->getDerivedTypes($resourceSetWrapper->getResourceType()); if (!is_null($derivedTypes)) { if (!is_array($derivedTypes)) { throw new InvalidOperationException(Messages::metadataAssociationTypeSetInvalidGetDerivedTypesReturnType($resourceSetWrapper->getName())); } //Populate Resource type for derived types and //complex types in derived types foreach ($derivedTypes as $derivedType) { if ($derivedType->hasNamedStream()) { throw new InvalidOperationException(Messages::metadataResourceTypeSetNamedStreamsOnDerivedEntityTypesNotSupported($resourceSetWrapper->getName(), $derivedType->getFullName())); } $this->_populateResourceTypes($derivedType); $this->_populateComplexTypes($derivedType); } } //Populate Resource type for for this type and //base types and complex types in this type and base types $resourceType = $resourceSetWrapper->getResourceType(); while ($resourceType != null) { $this->_populateResourceTypes($resourceType); $this->_populateComplexTypes($resourceType); $resourceType = $resourceType->getBaseType(); } }
/** * Gets the visible resource properties for the given resource type from * the given resource set wrapper. * * @param ResourceSetWrapper &$resourceSetWrapper Resource set wrapper in * question. * @param ResourceType &$resourceType Resource type in question. * * @return array(string, ResourceProperty) Collection of visible resource * properties from the given resource set wrapper and resource type. */ public function getResourceProperties(ResourceSetWrapper &$resourceSetWrapper, ResourceType &$resourceType) { if ($resourceType->getResourceTypeKind() == ResourceTypeKind::ENTITY) { $cacheKey = $resourceSetWrapper->getName() . '_' . $resourceType->getFullName(); if (array_key_exists($cacheKey, $this->_resourcePropertyCache)) { return $this->_resourcePropertyCache[$cacheKey]; } $this->_resourcePropertyCache[$cacheKey] = array(); foreach ($resourceType->getAllProperties() as $resourceProperty) { //Check whether this is a visible navigation property if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY && !is_null($this->getResourceSetWrapperForNavigationProperty($resourceSetWrapper, $resourceType, $resourceProperty))) { $this->_resourcePropertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty; } else { //primitive, bag or complex property $this->_resourcePropertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty; } } return $this->_resourcePropertyCache[$cacheKey]; } else { //Complex resource type return $resourceType->getAllProperties(); } }
/** * Gets and validate the ResourceAssociationSet instance for the * given source resource association end * This function first searches the ResourceAssociationSet cache, * if found return it otherwise * get the association set from metadata wrapper, * validate, cache and return it. * * @param ResourceSetWrapper $resourceSet Resource set of the * source association end * @param ResourceType $resourceType Resource type of the * source association end * @param ResourceProperty $navigationProperty Resource property of the * source association end * * @return ResourceAssociationSet/NULL The association set instance for the * given association set end, * NULL if the metadata wrapper * returns NULL * (either IDSMP implementation * returns null or * target resource set is invisible) * * @throws InvalidOperationException If validation of AssociationSet fails * @throws ODataException If validation fails at * MetadataQueryProviderWrapper::getResourceAssociationSet */ private function _getResourceAssociationSet(ResourceSetWrapper $resourceSet, ResourceType $resourceType, ResourceProperty $navigationProperty) { $associationSetLookupKey = $resourceSet->getName() . '_' . $resourceType->getFullName() . '_' . $navigationProperty->getName(); if (array_key_exists($associationSetLookupKey, $this->_resourceAssociationSets)) { return $this->_resourceAssociationSets[$associationSetLookupKey]; } $resourceAssociationSet = $this->metadataQueryproviderWrapper->getResourceAssociationSet($resourceSet, $resourceType, $navigationProperty); if (is_null($resourceAssociationSet)) { //Either the related ResourceSet is invisible or IDSMP implementation returns null return null; } /** * @var ResourceAssociationSetEnd */ $relatedEnd = $resourceAssociationSet->getRelatedResourceAssociationSetEnd($resourceSet->getResourceSet(), $resourceType, $navigationProperty); //For bidirectional relationship IDSMP::getResourceAssociationSet should //return same association set when called from either end if (!is_null($relatedEnd->getResourceProperty())) { //No need to check whether the following call returns NULL, //because the above call //MetadataQueryproviderWrapper::getResourceAssociationSet //causes the metadata wrapper to check the visibility of //related resource set and cache the corrosponding wrapper. //If found invisible it would have return NULL, //which we are any way handling above. $relatedResourceSetWrapper = $this->metadataQueryproviderWrapper->validateResourceSetAndGetWrapper($relatedEnd->getResourceSet()); $reverseResourceAssociationSet = $this->metadataQueryproviderWrapper->getResourceAssociationSet($relatedResourceSetWrapper, $relatedEnd->getResourceType(), $relatedEnd->getResourceProperty()); if (is_null($reverseResourceAssociationSet) || !is_null($reverseResourceAssociationSet) && $resourceAssociationSet->getName() != $reverseResourceAssociationSet->getName()) { throw new InvalidOperationException(Messages::metadataAssociationTypeSetBidirectionalAssociationMustReturnSameResourceAssociationSetFromBothEnd()); } } $reverseAssociationSetLookupKey = null; if (!is_null($relatedEnd->getResourceProperty())) { $reverseAssociationSetLookupKey = $relatedEnd->getResourceSet()->getName() . '_' . $relatedEnd->getResourceProperty()->getResourceType()->getFullName() . '_' . $relatedEnd->getResourceProperty()->getName(); } else { $reverseAssociationSetLookupKey = $relatedEnd->getResourceSet()->getName() . '_Null_' . $resourceType->getFullName() . '_' . $navigationProperty->getName(); } if (array_key_exists($reverseAssociationSetLookupKey, $this->_resourceAssociationSets)) { throw new InvalidOperationException(Messages::metadataAssociationTypeSetMultipleAssociationSetsForTheSameAssociationTypeMustNotReferToSameEndSets($this->_resourceAssociationSets[$reverseAssociationSetLookupKey]->getName(), $resourceAssociationSet->getName(), $relatedEnd->getResourceSet()->getName())); } $this->_resourceAssociationSets[$associationSetLookupKey] = $resourceAssociationSet; $this->_resourceAssociationSets[$reverseAssociationSetLookupKey] = $resourceAssociationSet; return $resourceAssociationSet; }