/**
  * To check this relationship belongs to a specfic entity property
  *  
  * @param ResourceType          $resourceType     The type of the entity
  * @param ResourceProperty|null $resourceProperty The property in the entity
  * 
  * @return boolean
  */
 public function isBelongsTo(ResourceType $resourceType, $resourceProperty)
 {
     $flag1 = is_null($resourceProperty);
     $flag2 = is_null($this->_resourceProperty);
     if ($flag1 != $flag2) {
         return false;
     }
     if ($flag1 === true) {
         return strcmp($resourceType->getFullName(), $this->_resourceType->getFullName()) == 0;
     }
     return strcmp($resourceType->getFullName(), $this->_resourceType->getFullName()) == 0 && strcmp($resourceProperty->getName(), $this->_resourceProperty->getName()) == 0;
 }
 /**
  * Construct new instance of ResourceAssociationSetEnd
  * Note: The $resourceSet represents collection of an entity, The 
  * $resourceType can be this entity's type or type of any of the 
  * base resource of this entity, on which the navigation property 
  * represented by $resourceProperty is defined.
  *   
  * @param ResourceSet      $resourceSet      Resource set for the association end
  * @param ResourceType     $resourceType     Resource type for the association end
  * @param ResourceProperty $resourceProperty Resource property for the association end
  * 
  * @throws \InvalidArgumentException
  */
 public function __construct(ResourceSet $resourceSet, ResourceType $resourceType, $resourceProperty)
 {
     if (!is_null($resourceProperty) && !$resourceProperty instanceof ResourceProperty) {
         throw new \InvalidArgumentException(Messages::resourceAssociationSetPropertyMustBeNullOrInstanceofResourceProperty('$resourceProperty'));
     }
     if (!is_null($resourceProperty) && (is_null($resourceType->resolveProperty($resourceProperty->getName())) || $resourceProperty->getKind() != ResourcePropertyKind::RESOURCE_REFERENCE && $resourceProperty->getKind() != ResourcePropertyKind::RESOURCESET_REFERENCE)) {
         throw new \InvalidArgumentException(Messages::resourceAssociationSetEndPropertyMustBeNavigationProperty($resourceProperty->getName(), $resourceType->getFullName()));
     }
     if (!$resourceSet->getResourceType()->isAssignableFrom($resourceType) && !$resourceType->isAssignableFrom($resourceSet->getResourceType())) {
         throw new \InvalidArgumentException(Messages::resourceAssociationSetEndResourceTypeMustBeAssignableToResourceSet($resourceType->getFullName(), $resourceSet->getName()));
     }
     $this->_resourceSet = $resourceSet;
     $this->_resourceType = $resourceType;
     $this->_resourceProperty = $resourceProperty;
 }
 /**
  * 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;
 }
예제 #4
0
 /**
  * Write value of a bag instance.
  *
  * @param array/NULL           &$BagValue             Bag value to write.
  * @param string               $propertyName          Property name of the bag.
  * @param ResourceType         &$resourceType         Type describing the 
  *                                                    bag value.
  * @param string               $relativeUri           Relative Url to the bag.
  * @param ODataPropertyContent &$odataPropertyContent On return, this object 
  *                                                    will hold bag value which 
  *                                                    can be used by writers.
  * 
  * @return void
  */
 private function _writeBagValue(&$BagValue, $propertyName, ResourceType &$resourceType, $relativeUri, ODataPropertyContent &$odataPropertyContent)
 {
     $bagItemResourceTypeKind = $resourceType->getResourceTypeKind();
     $this->assert($bagItemResourceTypeKind == ResourceTypeKind::PRIMITIVE || $bagItemResourceTypeKind == ResourceTypeKind::COMPLEX, '$bagItemResourceTypeKind == ResourceTypeKind::PRIMITIVE
         || $bagItemResourceTypeKind == ResourceTypeKind::COMPLEX');
     $odataProperty = new ODataProperty();
     $odataProperty->name = $propertyName;
     $odataProperty->typeName = 'Collection(' . $resourceType->getFullName() . ')';
     if (is_null($BagValue) || is_array($BagValue) && empty($BagValue)) {
         $odataProperty->value = null;
     } else {
         $odataBagContent = new ODataBagContent();
         foreach ($BagValue as $itemValue) {
             if (!is_null($itemValue)) {
                 if ($bagItemResourceTypeKind == ResourceTypeKind::PRIMITIVE) {
                     $primitiveValueAsString = null;
                     $this->_primitiveToString($resourceType, $itemValue, $primitiveValueAsString);
                     $odataBagContent->propertyContents[] = $primitiveValueAsString;
                 } else {
                     if ($bagItemResourceTypeKind == ResourceTypeKind::COMPLEX) {
                         $complexContent = new ODataPropertyContent();
                         $actualType = $this->_complexObjectToContent($itemValue, $propertyName, $resourceType, $relativeUri, $complexContent);
                         //TODO add type in case of base type
                         $odataBagContent->propertyContents[] = $complexContent;
                     }
                 }
             }
         }
         $odataProperty->value = $odataBagContent;
     }
     $odataPropertyContent->properties[] = $odataProperty;
 }
예제 #5
0
 /**
  * test ResourceType class
  */
 public function testResourceType()
 {
     $exceptionThrown = false;
     try {
         ResourceType::getPrimitiveResourceType(TypeCode::VOID);
         $this->fail('An expected InvalidArgumentException for \'EdmPrimitiveType\' has not been raised');
     } catch (\InvalidArgumentException $exception) {
         $this->assertStringEndsWith('is not a valid EdmPrimitiveType Enum value', $exception->getMessage());
     }
     $int16ResType = new ResourceType(new Int16(), ResourceTypeKind::PRIMITIVE, 'Int16', 'Edm');
     try {
         $int32ResType = new ResourceType(new Int32(), ResourceTypeKind::PRIMITIVE, 'Int32', 'Edm', $int16ResType);
         $this->fail('An expected InvalidArgumentException for \'basetype\' has not been raised');
     } catch (\InvalidArgumentException $exception) {
         $this->AssertEquals('Primitive type cannot have base type', $exception->getMessage());
     }
     try {
         $int32ResType = new ResourceType(new Int32(), ResourceTypeKind::PRIMITIVE, 'Int32', 'Edm', null, true);
         $this->fail('An expected InvalidArgumentException for \'abstract\' has not been raised');
     } catch (\InvalidArgumentException $exception) {
         $this->AssertEquals('Primitive type cannot be abstract', $exception->getMessage());
     }
     try {
         $int32ResType = new ResourceType(null, ResourceTypeKind::PRIMITIVE, 'Int32', 'Edm');
         $this->fail('An expected InvalidArgumentException for \'IType\' has not been raised');
     } catch (\InvalidArgumentException $exception) {
         $this->assertStringEndsWith('should be an \'IType\' implementor instance', $exception->getMessage());
     }
     try {
         $customerResType = new ResourceType(null, ResourceTypeKind::ENTITY, 'Customer', 'Northwind');
         $this->fail('An expected InvalidArgumentException for \'ReflectionClass\' has not been raised');
     } catch (\InvalidArgumentException $exception) {
         $this->assertStringEndsWith('argument should be an \'ReflectionClass\' instance', $exception->getMessage());
     }
     $customerResType = new ResourceType(new \ReflectionClass('UnitTests\\POData\\Facets\\NorthWind1\\Customer2'), ResourceTypeKind::ENTITY, 'Customer', 'Northwind');
     $this->AssertEquals($customerResType->getName(), 'Customer');
     $this->AssertEquals($customerResType->getFullName(), 'Northwind.Customer');
     $this->assertTrue($customerResType->getInstanceType() instanceof \ReflectionClass);
     $this->AssertEquals($customerResType->getNamespace(), 'Northwind');
     $this->AssertEquals($customerResType->getResourceTypeKind(), ResourceTypeKind::ENTITY);
     $this->AssertEquals($customerResType->isMediaLinkEntry(), false);
     try {
         $customerResType->validateType();
         $this->fail('An expected InvalidOperationException for \'No key defined\' has not been raised');
     } catch (InvalidOperationException $exception) {
         $this->assertStringEndsWith('Please make sure the key properties are defined for this entity type', $exception->getMessage());
     }
     $int32ResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::INT32);
     $primitiveResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::STRING);
     $testProperty = new ResourceProperty('test', null, ResourcePropertyKind::PRIMITIVE, $primitiveResourceType);
     try {
         $int32ResourceType->addProperty($testProperty);
         $this->fail('An expected InvalidOperationException for \'property on primitive\' has not been raised');
     } catch (InvalidOperationException $exception) {
         $this->assertStringEndsWith('ResourceType instances with a ResourceTypeKind equal to \'Primitive\'', $exception->getMessage());
     }
     $stringResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::STRING);
     $customerIDPrimProperty = new ResourceProperty('CustomerID', null, ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY, $stringResourceType);
     $customerNamePrimProperty = new ResourceProperty('CustomerName', null, ResourcePropertyKind::PRIMITIVE, $stringResourceType);
     $intResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::INT32);
     $ratingPrimProperty = new ResourceProperty('Rating', null, ResourcePropertyKind::PRIMITIVE, $intResourceType);
     $addressResType = new ResourceType(new \ReflectionClass('UnitTests\\POData\\Facets\\NorthWind1\\Address2'), ResourceTypeKind::COMPLEX, 'Address', 'Northwind');
     $booleanResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::BOOLEAN);
     $isPrimaryPrimProperty = new ResourceProperty('IsPrimary', null, ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY, $booleanResourceType);
     try {
         $addressResType->addProperty($isPrimaryPrimProperty);
         $this->fail('An expected InvalidOperationException for \'Key on non-entity\' has not been raised');
     } catch (InvalidOperationException $exception) {
         $this->assertStringEndsWith('ResourceType instances with a ResourceTypeKind equal to \'EntityType\'', $exception->getMessage());
     }
     $booleanResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::BOOLEAN);
     $isPrimaryPrimProperty = new ResourceProperty('IsPrimary', null, ResourcePropertyKind::PRIMITIVE, $booleanResourceType);
     $addressResType->addProperty($isPrimaryPrimProperty);
     try {
         $addressResType->addProperty($isPrimaryPrimProperty);
         $this->fail('An expected InvalidArgumentException for \'Property duplication\' has not been raised');
     } catch (InvalidOperationException $exception) {
         $this->assertStringStartsWith('Property with same name \'IsPrimary\' already exists in type \'Address\'', $exception->getMessage());
     }
     try {
         $addressResType->setMediaLinkEntry(true);
         $this->fail('An expected InvalidOperationException for \'MLE on non-entity\' has not been raised');
     } catch (InvalidOperationException $exception) {
         $this->assertStringStartsWith('Cannot apply the HasStreamAttribute', $exception->getMessage());
     }
     $customerAdrComplexType = new ResourceProperty('Address', null, ResourcePropertyKind::COMPLEX_TYPE, $addressResType);
     $customerResType->addProperty($customerIDPrimProperty);
     $customerResType->addProperty($customerNamePrimProperty);
     $customerResType->addProperty($ratingPrimProperty);
     $customerResType->addProperty($customerAdrComplexType);
     $customerResType->validateType();
     $customerProperties = $customerResType->getPropertiesDeclaredOnThisType();
     $this->AssertEquals(count($customerProperties), 4);
     $customerAllProperties = $customerResType->getAllProperties();
     $this->AssertEquals(count($customerProperties), count($customerAllProperties));
     $keys = array('CustomerID', 'CustomerName', 'Rating', 'Address');
     $i = 0;
     foreach ($customerAllProperties as $key => $customerProperty) {
         $this->AssertEquals($key, $keys[$i++]);
     }
     $entityKeys = array('CustomerID');
     $customerKeyProperties = $customerResType->getKeyProperties();
     $i = 0;
     foreach ($customerKeyProperties as $key => $customerKeyProperty) {
         $this->AssertEquals($key, $entityKeys[$i++]);
     }
     $this->AssertEquals(count($customerResType->getETagProperties()), 0);
     $this->AssertEquals($customerResType->resolveProperty('PropNotExists'), null);
     $property = $customerResType->resolveProperty('CustomerName');
     $this->AssertNotEquals($property, null);
     $this->AssertEquals($property->getName(), 'CustomerName');
     $employeeResType = new ResourceType(new \ReflectionClass('UnitTests\\POData\\Facets\\NorthWind1\\Employee2'), ResourceTypeKind::ENTITY, 'Employee', 'Northwind');
     $stringResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::STRING);
     $employeeResType->addProperty(new ResourceProperty('EmployeeID', null, ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY, $stringResourceType));
     $employeeResType->addProperty(new ResourceProperty('Emails', null, ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::BAG, $stringResourceType));
     $employeeResType->setMediaLinkEntry(true);
     $employeeResType->addNamedStream(new ResourceStreamInfo('ThumNail_64X64'));
     try {
         $employeeResType->addNamedStream(new ResourceStreamInfo('ThumNail_64X64'));
         $this->fail('An expected InvalidOperationException for \'named stream duplication\' has not been raised');
     } catch (InvalidOperationException $exception) {
         $this->assertStringStartsWith('Named stream with the name \'ThumNail_64X64\' already exists in type \'Employee\'', $exception->getMessage());
     }
     $this->AssertEquals($employeeResType->hasNamedStream(), true);
     $b = array();
     $this->AssertEquals($employeeResType->hasBagProperty($b), true);
     $namedStreams = $employeeResType->getAllNamedStreams();
     $this->AssertEquals(count($namedStreams), 1);
     $this->AssertTrue(array_key_exists('ThumNail_64X64', $namedStreams));
     $name = $employeeResType->tryResolveNamedStreamByName('ThumNail_64X64')->getName();
     $this->AssertEquals($name, 'ThumNail_64X64');
 }
예제 #6
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];
 }
예제 #7
0
 /**
  * Gets full name of this type in EDM namespace
  * Note: implementation of IType::getFullTypeName
  * 
  * @return string
  */
 public function getFullTypeName()
 {
     return $this->_resourceType->getFullName();
 }