/**
  * 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 
  * ProvidersWrapper::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->providersWrapper->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
         //providersWrapper::getResourceAssociationSet
         //causes the metadata wrapper to check the visibility of
         //related resource set and cache the corresponding wrapper.
         //If found invisible it would have return NULL,
         //which we are any way handling above.
         $relatedResourceSetWrapper = $this->providersWrapper->validateResourceSetAndGetWrapper($relatedEnd->getResourceSet());
         $reverseResourceAssociationSet = $this->providersWrapper->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;
 }
예제 #2
0
 /**
  * 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 following 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->providersWrapper->getDerivedTypes($resourceSetWrapper->getResourceType());
     //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();
     }
 }
예제 #3
0
 /**
  * Gets the visible resource properties for the given resource type from the given resource set wrapper.
  *
  * @param ResourceSetWrapper $setWrapper Resource set wrapper in question.
  * @param ResourceType       $resourceType       Resource type in question.
  * @return ResourceProperty[] Collection of visible resource properties from the given resource set wrapper and resource type.
  */
 public function getResourceProperties(ResourceSetWrapper $setWrapper, ResourceType $resourceType)
 {
     if ($resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
         //Complex resource type
         return $resourceType->getAllProperties();
     }
     //TODO: move this to doctrine annotations
     $cacheKey = $setWrapper->getName() . '_' . $resourceType->getFullName();
     if (!array_key_exists($cacheKey, $this->propertyCache)) {
         //Fill the cache
         $this->propertyCache[$cacheKey] = array();
         foreach ($resourceType->getAllProperties() as $resourceProperty) {
             //Check whether this is a visible navigation property
             //TODO: is this broken?? see #87
             if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY && !is_null($this->getResourceSetWrapperForNavigationProperty($setWrapper, $resourceType, $resourceProperty))) {
                 $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
             } else {
                 //primitive, bag or complex property
                 $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
             }
         }
     }
     return $this->propertyCache[$cacheKey];
 }