Passed
Push — master ( 4ab488...bcfbc7 )
by Bálint
03:58
created

MetadataWriter::_getSchemaNamespaceUri()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 20
c 0
b 0
f 0
rs 9.2222
cc 6
nc 6
nop 1
1
<?php
2
3
namespace POData\Writers\Metadata;
4
5
use POData\Providers\Metadata\ResourceAssociationSet;
6
use POData\Providers\Metadata\ResourceAssociationTypeEnd;
7
use POData\Providers\Metadata\ResourcePropertyKind;
8
use POData\Providers\Metadata\ResourceProperty;
9
use POData\Providers\Metadata\ResourceType;
10
use POData\Providers\Metadata\ResourceTypeKind;
11
use POData\Providers\ProvidersWrapper;
12
use POData\Common\Version;
13
use POData\Common\ODataConstants;
14
use POData\Common\Messages;
15
use POData\Common\ODataException;
16
use POData\Common\InvalidOperationException;
17
use POData\Providers\Metadata\ResourceAssociationType;
18
use POData\Providers\Metadata\EdmSchemaVersion;
19
use XMLWriter;
20
21
/**
22
 * Class MetadataWriter
23
 * @package POData\Writers\Metadata
24
 */
25
class MetadataWriter
26
{
27
    /**
28
     * Writer to which output (CSDL Document) is sent
29
     *
30
     * @var \XMLWriter
31
     */
32
    private $_xmlWriter;
33
34
    /**                                     `
35
     * Hold reference to the MetadataManager instance,
36
     * which can be used for retrieving details about all ResourceType,
37
     * ResourceSet, AssociationType and AssociationSet defined in the service.
38
     *
39
     * @var MetadataManager
40
     */
41
    private $_metadataManager;
42
43
    /**
44
     * Holds reference to the wrapper over service metadata and query provider implementations
45
     * In this context this provider will be used for gathering metadata information only.
46
     *
47
     * @var ProvidersWrapper
48
     */
49
    private $providersWrapper;
50
51
    /**
52
     * Data service base uri from which resources should be resolved
53
     *
54
     * @var string
55
     */
56
    private $_baseUri;
0 ignored issues
show
introduced by
The private property $_baseUri is not used, and could be removed.
Loading history...
57
58
    /**
59
     * Encoding used for the output (CSDL document)
60
     *
61
     * @var string
62
     */
63
    private $_encoding;
0 ignored issues
show
introduced by
The private property $_encoding is not used, and could be removed.
Loading history...
64
65
    /**
66
     * The DataServiceVersion for this metadata.
67
     *
68
     * @var Version
69
     */
70
    private $_dataServiceVersion;
71
72
    /**
73
     * Creates new instance of MetadataWriter
74
     *
75
     * @param ProvidersWrapper $provider Reference to the
76
     * service metadata and query provider wrapper
77
     */
78
    public function __construct(ProvidersWrapper $provider)
79
    {
80
        $this->providersWrapper = $provider;
81
    }
82
83
    /**
84
     * Write the metadata in CSDL format.
85
     *
86
     * @return string
87
     */
88
    public function writeMetadata()
89
    {
90
        $this->_metadataManager = MetadataManager::create($this->providersWrapper);
91
92
        $this->_dataServiceVersion = new Version(3, 0);
93
        $edmSchemaVersion = $this->providersWrapper->getEdmSchemaVersion();
94
        $this->_metadataManager->getDataServiceAndEdmSchemaVersions($this->_dataServiceVersion, $edmSchemaVersion);
95
        $this->_xmlWriter = new XMLWriter();
96
        $this->_xmlWriter->openMemory();
97
        $this->_xmlWriter->setIndent(true);
98
        $this->_xmlWriter->startDocument('1.0', 'utf-8');
99
        $this->_writeTopLevelElements($this->_dataServiceVersion->toString());
100
        $resourceTypesInContainerNamespace = array();
101
        $containerNamespace = $this->providersWrapper->getContainerNamespace();
102
        foreach ($this->_metadataManager->getResourceTypesAlongWithNamespace() as $resourceTypeNamespace => $resourceTypesWithName) {
103
            if ($resourceTypeNamespace == $containerNamespace) {
104
                foreach ($resourceTypesWithName as $resourceTypeName => $resourceType) {
105
                    $resourceTypesInContainerNamespace[] = $resourceType;
106
                }
107
            } else {
108
                $associationsInThisNamespace = $this->_metadataManager->getResourceAssociationTypesForNamespace($resourceTypeNamespace);
109
                $this->_writeSchemaElement($resourceTypeNamespace, $edmSchemaVersion);
110
                $uniqueAssociationsInThisNamespace = $this->_metadataManager->getUniqueResourceAssociationTypesForNamespace($resourceTypeNamespace);
111
                $this->_writeResourceTypes(array_values($resourceTypesWithName), $associationsInThisNamespace);
112
                $this->_writeAssociationTypes($uniqueAssociationsInThisNamespace);
113
            }
114
        }
115
116
        //write Container schema node and define required nmaespaces
117
        $this->_writeSchemaElement($resourceTypeNamespace, $edmSchemaVersion);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $resourceTypeNamespace seems to be defined by a foreach iteration on line 102. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
118
        if (!empty($resourceTypesInContainerNamespace)) {
119
            //Get assocation types in container namespace as array of
120
            //key-value pairs (with key as association type
121
            //lookup key i.e. ResourceType::Name_NavigationProperty::Name.
122
            //Same association will appear twice for di-directional relationship
123
            //(duplicate value will be there in this case)
124
            $associationsInThisNamespace = $this->_metadataManager->getResourceAssociationTypesForNamespace($containerNamespace);
125
            //Get association type in container namespace as array of unique values
126
            $uniqueAssociationsInThisNamespace = $this->_metadataManager->getUniqueResourceAssociationTypesForNamespace($containerNamespace);
127
            $this->_writeResourceTypes($resourceTypesInContainerNamespace, $associationsInThisNamespace);
128
            $this->_writeAssociationTypes($uniqueAssociationsInThisNamespace);
129
        }
130
131
        $this->_writeEntityContainer();
132
        //End container Schema node
133
        $this->_xmlWriter->endElement();
134
135
        //End edmx:Edmx and edmx:DataServices nodes
136
        $this->_xmlWriter->endElement();
137
        $this->_xmlWriter->endElement();
138
        $metadataInCsdl = $this->_xmlWriter->outputMemory(true);
139
        return $metadataInCsdl;
140
    }
141
142
    /**
143
     * Gets data service version for this metadata.
144
     *
145
     * @return Version
146
     */
147
    public function getDataServiceVersion()
148
    {
149
        return $this->_dataServiceVersion;
150
    }
151
152
    /**
153
     * Write top level 'Edmx' and 'DataServices' nodes with associated attributes
154
     *
155
     * @param Version $dataServiceVersion version of the data service
156
     *
157
     * @return void
158
     */
159
    private function _writeTopLevelElements($dataServiceVersion)
160
    {
161
        $this->_xmlWriter->startElementNs(ODataConstants::EDMX_NAMESPACE_PREFIX, ODataConstants::EDMX_ELEMENT, ODataConstants::EDMX_NAMESPACE_1_0);
162
        $this->_xmlWriter->writeAttribute(ODataConstants::EDMX_VERSION, ODataConstants::EDMX_VERSION_VALUE);
163
        // ==
164
        $this->_xmlWriter->startElementNs(ODataConstants::EDMX_NAMESPACE_PREFIX, ODataConstants::EDMX_DATASERVICES_ELEMENT, null);
165
        $this->_xmlWriter->writeAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, null, ODataConstants::ODATA_METADATA_NAMESPACE);
166
        $this->_xmlWriter->writeAttributeNs(ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, ODataConstants::ODATAVERSIONHEADER, null, $dataServiceVersion);
0 ignored issues
show
Bug introduced by
$dataServiceVersion of type POData\Common\Version is incompatible with the type string expected by parameter $content of XMLWriter::writeAttributeNs(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

166
        $this->_xmlWriter->writeAttributeNs(ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, ODataConstants::ODATAVERSIONHEADER, null, /** @scrutinizer ignore-type */ $dataServiceVersion);
Loading history...
167
        $this->_xmlWriter->writeAttributeNs(ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, ODataConstants::ODATAMAXVERSIONHEADER, null, $dataServiceVersion);
168
    }
169
170
    /**
171
     * Write 'Schema' node with associated attributes
172
     *
173
     * @param string                   $schemaNamespace  schema namespace
174
     * @param EdmSchemaVersion $edmSchemaVersion edm schema version
175
     *
176
     * @return void
177
     */
178
    private function _writeSchemaElement($schemaNamespace, $edmSchemaVersion)
179
    {
180
        $this->_xmlWriter->startElementNs(null, ODataConstants::SCHEMA, $this->_getSchemaNamespaceUri($edmSchemaVersion));
181
        $this->_xmlWriter->writeAttribute(ODataConstants::NAMESPACE1, $schemaNamespace);
182
        // $this->_xmlWriter->writeAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, ODataConstants::ODATA_NAMESPACE_PREFIX, null, ODataConstants::ODATA_NAMESPACE);
183
        // $this->_xmlWriter->writeAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, null, ODataConstants::ODATA_METADATA_NAMESPACE);
184
    }
185
186
    /**
187
     * Write all resource types (entity and complex types)
188
     *
189
     * @param ResourceType[] $resourceTypes resource types array
190
     * @param ResourceAssociationType[] $associationTypesInResourceTypesNamespace collection of
191
     * association types for the given resource types
192
     * array(string, AssociationType)
193
     *
194
     * @return void
195
     */
196
    private function _writeResourceTypes($resourceTypes, $associationTypesInResourceTypesNamespace)
197
    {
198
        foreach ($resourceTypes as $resourceType) {
199
            if ($resourceType->getResourceTypeKind() == ResourceTypeKind::ENTITY) {
200
                $this->_writeEntityType($resourceType, $associationTypesInResourceTypesNamespace);
201
            } else if ($resourceType->getResourceTypeKind() == ResourceTypeKind::COMPLEX) {
202
                $this->_writeComplexType($resourceType);
203
            } else {
204
                throw ODataException::createInternalServerError(Messages::metadataWriterExpectingEntityOrComplexResourceType());
205
            }
206
        }
207
    }
208
209
    /**
210
     * Write an entity type and associated attributes.
211
     *
212
     * @param ResourceType $resourceType                            Resource type
213
     * @param ResourceAssociationType[]        $associationTypesInResourceTypeNamespace Collection of
214
     * association types for the given resource types
215
     * array(string, AssociationType)
216
     *
217
     * @return void
218
     */
219
    private function _writeEntityType(ResourceType $resourceType, $associationTypesInResourceTypeNamespace)
220
    {
221
        $this->_xmlWriter->startElement(ODataConstants::ENTITY_TYPE);
222
        $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $resourceType->getName());
223
        if ($resourceType->isAbstract()) {
224
            $this->_xmlWriter->writeAttribute(ODataConstants::ABSTRACT1, "true");
225
        }
226
227
        if ($resourceType->isMediaLinkEntry() && (!$resourceType->hasBaseType() || ($resourceType->hasBaseType() && $resourceType->getBaseType()->isMediaLinkEntry()))) {
228
            $this->_xmlWriter->writeAttributeNs(ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, ODataConstants::DATAWEB_ACCESS_HASSTREAM_ATTRIBUTE, null, "true");
229
        }
230
231
        if ($resourceType->hasBaseType()) {
232
            $this->_xmlWriter->writeAttribute(ODataConstants::BASE_TYPE, $resourceType->getBaseType()->getFullName());
233
        } else {
234
            $this->_xmlWriter->startElement(ODataConstants::KEY);
235
            foreach ($resourceType->getKeyProperties() as $resourceProperty) {
236
                $this->_xmlWriter->startElement(ODataConstants::PROPERTY_REF);
237
                $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $resourceProperty->getName());
238
                $this->_xmlWriter->endElement();
239
            }
240
241
            $this->_xmlWriter->endElement();
242
        }
243
244
        $this->_writeProperties($resourceType, $associationTypesInResourceTypeNamespace);
245
        $this->_writeNamedStreams($resourceType);
246
        $this->_xmlWriter->endElement();
247
    }
248
249
    /**
250
     * Write a complex type and associated attributes
251
     *
252
     * @param ResourceType $complexType resource type
253
     *
254
     * @return void
255
     */
256
    private function _writeComplexType(ResourceType $complexType)
257
    {
258
        $this->_xmlWriter->startElement(ODataConstants::COMPLEX_TYPE);
259
        $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $complexType->getName());
260
        $this->_writeProperties($complexType, null);
261
        $this->_xmlWriter->endElement();
262
    }
263
264
    /**
265
     * Write properties of a resource type (entity or complex type)
266
     *
267
     * @param ResourceType $resourceType                            The Entity
268
     * or Complex resource type.
269
     * @param array        $associationTypesInResourceTypeNamespace When the
270
     * resource type represents an entity, This will be an array of AssociationType
271
     * in the namespace same as resource type namespace, array will be
272
     * key-value pair with key as association type lookup name and value as
273
     * association type, this parameter will be null if the resource type
274
     * represents a complex type
275
     * array(string, AssociationType)
276
     *
277
     * @return void
278
     */
279
    private function _writeProperties(ResourceType $resourceType, $associationTypesInResourceTypeNamespace)
280
    {
281
        foreach ($this->_metadataManager->getAllVisiblePropertiesDeclaredOnThisType($resourceType) as $resourceProperty) {
282
            if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) {
0 ignored issues
show
Bug introduced by
POData\Providers\Metadat...sourcePropertyKind::BAG of type integer is incompatible with the type POData\Providers\Metadata\ResourcePropertyKind expected by parameter $kind of POData\Providers\Metadat...rceProperty::isKindOf(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

282
            if ($resourceProperty->isKindOf(/** @scrutinizer ignore-type */ ResourcePropertyKind::BAG)) {
Loading history...
283
                $this->_writeBagProperty($resourceProperty);
284
            } else if ($resourceProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) {
285
                $this->_writePrimitiveProperty($resourceProperty);
286
            } else if ($resourceProperty->isKindOf(ResourcePropertyKind::COMPLEX_TYPE)) {
287
                $this->_writeComplexProperty($resourceProperty);
288
            } else if ($resourceProperty->isKindOf(ResourcePropertyKind::RESOURCE_REFERENCE)
289
                || $resourceProperty->isKindOf(ResourcePropertyKind::RESOURCESET_REFERENCE)
290
            ) {
291
                    $this->_writeNavigationProperty($resourceType, $associationTypesInResourceTypeNamespace, $resourceProperty);
292
            } else {
293
                    //Unexpected ResourceProperty, expected
294
                    //Bag/Primitive/Complex/Navigation Property
295
            }
296
        }
297
    }
298
299
    /**
300
     * Write a bag property and associated attributes
301
     *
302
     * @param ResourceProperty $bagProperty bag property
303
     *
304
     * @return void
305
     */
306
    private function _writeBagProperty(ResourceProperty $bagProperty)
307
    {
308
        $this->_xmlWriter->startElement(ODataConstants::PROPERTY);
309
        $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $bagProperty->getName());
310
        $this->_xmlWriter->writeAttribute(ODataConstants::TYPE1, ODataConstants::EDM_BAG_TYPE);
311
        $this->_xmlWriter->writeAttribute(ODataConstants::NULLABLE, "false");
312
        $this->_xmlWriter->startElement(ODataConstants::TYPE_REF);
313
        $this->_xmlWriter->writeAttribute(ODataConstants::TYPE1, $bagProperty->getResourceType()->getFullName());
314
        $this->_xmlWriter->writeAttribute(ODataConstants::NULLABLE, "false");
315
        $this->_xmlWriter->endElement();
316
        $this->_xmlWriter->endElement();
317
    }
318
319
    /**
320
     * Write a primitive property and associated attributes
321
     *
322
     * @param ResourceProperty $primitiveProperty primitive resource property
323
     *
324
     * @return void
325
     */
326
    private function _writePrimitiveProperty(ResourceProperty $primitiveProperty)
327
    {
328
        $this->_xmlWriter->startElement(ODataConstants::PROPERTY);
329
        $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $primitiveProperty->getName());
330
        $this->_xmlWriter->writeAttribute(ODataConstants::TYPE1, $primitiveProperty->getResourceType()->getFullName());
331
        $this->_writePrimitivePropertyFacets($primitiveProperty);
332
        if (!is_null($primitiveProperty->getMIMEType())) {
0 ignored issues
show
introduced by
The condition is_null($primitiveProperty->getMIMEType()) is always false.
Loading history...
333
            $this->_xmlWriter->writeAttributeNs(ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, ODataConstants::DATAWEB_MIMETYPE_ATTRIBUTE_NAME, null, $primitiveProperty->getMIMEType());
334
        }
335
336
        if ($primitiveProperty->isKindOf(ResourcePropertyKind::ETAG)) {
0 ignored issues
show
Bug introduced by
POData\Providers\Metadat...ourcePropertyKind::ETAG of type integer is incompatible with the type POData\Providers\Metadata\ResourcePropertyKind expected by parameter $kind of POData\Providers\Metadat...rceProperty::isKindOf(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

336
        if ($primitiveProperty->isKindOf(/** @scrutinizer ignore-type */ ResourcePropertyKind::ETAG)) {
Loading history...
337
            $this->_xmlWriter->writeAttribute(ODataConstants::CONCURRENCY_ATTRIBUTE, ODataConstants::CONCURRENCY_FIXEDVALUE);
338
        }
339
340
        $this->_xmlWriter->endElement();
341
    }
342
343
    /**
344
     * Write a complex property and associated attributes.
345
     *
346
     * @param ResourceProperty $complexProperty complex property
347
     *
348
     * @return void
349
     */
350
    private function _writeComplexProperty(ResourceProperty $complexProperty)
351
    {
352
        $this->_xmlWriter->startElement(ODataConstants::PROPERTY);
353
        $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $complexProperty->getName());
354
        $this->_xmlWriter->writeAttribute(ODataConstants::TYPE1, $complexProperty->getResourceType()->getFullName());
355
        $this->_xmlWriter->writeAttribute(ODataConstants::NULLABLE, "false");
356
        $this->_xmlWriter->endElement();
357
    }
358
359
    /**
360
     * Write a navigation property
361
     *
362
     * @param ResourceType     $resourceType                            Resource type
363
     * @param ResourceAssociationType[] $associationTypesInResourceTypeNamespace Collection of association types for the given resource types
364
     * @param ResourceProperty $navigationProperty Navigation property
365
     *
366
     * @throws InvalidOperationException
367
     * @return void
368
     */
369
    private function _writeNavigationProperty(ResourceType $resourceType, $associationTypesInResourceTypeNamespace, ResourceProperty $navigationProperty)
370
    {
371
        $associationTypeLookupName = $resourceType->getName() . '_' . $navigationProperty->getName();
372
        if (!array_key_exists($associationTypeLookupName, $associationTypesInResourceTypeNamespace)) {
373
            throw new InvalidOperationException(Messages::metadataWriterNoResourceAssociationSetForNavigationProperty($navigationProperty->getName(), $resourceType->getName()));
374
        }
375
376
        $associationType = $associationTypesInResourceTypeNamespace[$associationTypeLookupName];
377
        $thisEnd = $associationType->getResourceAssociationTypeEnd($resourceType, $navigationProperty);
378
        $relatedEnd = $associationType->getRelatedResourceAssociationSetEnd($resourceType, $navigationProperty);
379
380
        $this->_xmlWriter->startElement(ODataConstants::NAVIGATION_PROPERTY);
381
        $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $navigationProperty->getName());
382
        $this->_xmlWriter->writeAttribute(ODataConstants::RELATIONSHIP, $associationType->getFullName());
383
        $this->_xmlWriter->writeAttribute(ODataConstants::FROM_ROLE, $thisEnd->getName());
384
        $this->_xmlWriter->writeAttribute(ODataConstants::TO_ROLE, $relatedEnd->getName());
385
        $this->_xmlWriter->endElement();
386
    }
387
388
    /**
389
     * Write primitive property facets.
390
     *
391
     * @param ResourceProperty $primitveProperty primitive property
392
     *
393
     * @return void
394
     */
395
    private function _writePrimitivePropertyFacets(ResourceProperty $primitveProperty)
396
    {
397
        $nullable = true;
398
        if ($primitveProperty->isKindOf(ResourcePropertyKind::KEY)) {
0 ignored issues
show
Bug introduced by
POData\Providers\Metadat...sourcePropertyKind::KEY of type integer is incompatible with the type POData\Providers\Metadata\ResourcePropertyKind expected by parameter $kind of POData\Providers\Metadat...rceProperty::isKindOf(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

398
        if ($primitveProperty->isKindOf(/** @scrutinizer ignore-type */ ResourcePropertyKind::KEY)) {
Loading history...
399
            $nullable = false;
400
        }
401
402
        $this->_xmlWriter->writeAttribute(ODataConstants::NULLABLE, $nullable ? "true" : "false");
403
    }
404
405
    /**
406
     * Write all named streams in the given entity type
407
     *
408
     * @param ResourceType $resourceType resource type
409
     *
410
     * @return void
411
     */
412
    private function _writeNamedStreams(ResourceType $resourceType)
413
    {
414
        $namedStreams = $resourceType->getNamedStreamsDeclaredOnThisType();
415
        if (!empty($namedStreams)) {
416
            $this->_xmlWriter->startElementNs(null, ODataConstants::DATAWEB_NAMEDSTREAMS_ELEMENT, ODataConstants::ODATA_METADATA_NAMESPACE);
417
            foreach ($namedStreams as $namedStreamName => $resourceStreamInfo) {
418
                $this->_xmlWriter->startElementNs(null, ODataConstants::DATAWEB_NAMEDSTREAM_ELEMENT, ODataConstants::ODATA_METADATA_NAMESPACE);
419
                $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $resourceStreamInfo->getName());
420
                $this->_xmlWriter->endElement();
421
            }
422
423
            $this->_xmlWriter->endElement();
424
        }
425
    }
426
427
    /**
428
     * Write all association type
429
     *
430
     * @param ResourceAssociationType[] $resourceAssociationTypes collection of resource association types
431
     *
432
     * @return void
433
     */
434
    private function _writeAssociationTypes($resourceAssociationTypes)
435
    {
436
        foreach ($resourceAssociationTypes as $resourceAssociationType) {
437
            $this->_xmlWriter->startElement(ODataConstants::ASSOCIATION);
438
            $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $resourceAssociationType->getName());
439
            $this->_writeAssociationTypeEnd($resourceAssociationType->getEnd1());
440
            $this->_writeAssociationTypeEnd($resourceAssociationType->getEnd2());
441
            $this->_xmlWriter->endElement();
442
        }
443
    }
444
445
    /**
446
     * Write an association type end.
447
     *
448
     * @param ResourceAssociationTypeEnd $resourceAssociationTypeEnd Resource
449
     * association type end
450
     *
451
     * @return void
452
     */
453
    private function _writeAssociationTypeEnd(ResourceAssociationTypeEnd $resourceAssociationTypeEnd)
454
    {
455
        $this->_xmlWriter->startElement(ODataConstants::END);
456
        $this->_xmlWriter->writeAttribute(ODataConstants::ROLE, $resourceAssociationTypeEnd->getName());
457
        $this->_xmlWriter->writeAttribute(ODataConstants::TYPE1, $resourceAssociationTypeEnd->getResourceType()->getFullName());
458
        $this->_xmlWriter->writeAttribute(ODataConstants::MULTIPLICITY, $resourceAssociationTypeEnd->getMultiplicity());
459
        $this->_xmlWriter->endElement();
460
    }
461
462
    /**
463
     * Write entity container
464
     *
465
     * @return void
466
     */
467
    private function _writeEntityContainer()
468
    {
469
        $this->_xmlWriter->startElement(ODataConstants::ENTITY_CONTAINER);
470
        $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $this->providersWrapper->getContainerName());
471
        $this->_xmlWriter->writeAttributeNs(ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, ODataConstants::ISDEFAULT_ENTITY_CONTAINER_ATTRIBUTE, null, "true");
472
        foreach ($this->_metadataManager->getResourceSets() as $resourceSet) {
473
            $this->_xmlWriter->startElement(ODataConstants::ENTITY_SET);
474
            $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $resourceSet->getName());
475
            $this->_xmlWriter->writeAttribute(ODataConstants::ENTITY_TYPE, $resourceSet->getResourceType()->getFullName());
476
            $this->_xmlWriter->endElement();
477
        }
478
479
        $this->_writeAssociationSets();
480
        $this->_xmlWriter->endElement();
481
    }
482
483
    /**
484
     * Write all association sets.
485
     *
486
     * @return void
487
     */
488
    private function _writeAssociationSets()
489
    {
490
        foreach ($this->_metadataManager->getAssociationSets() as $associationSetName => $associationSet) {
491
            $this->_xmlWriter->startElement(ODataConstants::ASSOCIATION_SET);
492
            $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $associationSetName);
493
            $this->_xmlWriter->writeAttribute(ODataConstants::ASSOCIATION, $associationSet->resourceAssociationType->getFullName());
494
            $this->_writeAssocationSetEnds($associationSet);
495
            $this->_xmlWriter->endElement();
496
        }
497
    }
498
499
    /**
500
     * Write both ends of the given association set.
501
     *
502
     * @param ResourceAssociationSet $associationSet resource association set
503
     *
504
     * @return void
505
     */
506
    private function _writeAssocationSetEnds(ResourceAssociationSet $associationSet)
507
    {
508
        $associationTypeEnd1 = $associationSet->resourceAssociationType->getResourceAssociationTypeEnd($associationSet->getEnd1()->getResourceType(), $associationSet->getEnd1()->getResourceProperty());
509
        $associationTypeEnd2 = $associationSet->resourceAssociationType->getResourceAssociationTypeEnd($associationSet->getEnd2()->getResourceType(), $associationSet->getEnd2()->getResourceProperty());
510
        $this->_xmlWriter->startElement(ODataConstants::END);
511
        $this->_xmlWriter->writeAttribute(ODataConstants::ROLE, $associationTypeEnd1->getName());
512
        $this->_xmlWriter->writeAttribute(ODataConstants::ENTITY_SET, $associationSet->getEnd1()->getResourceSet()->getName());
513
        $this->_xmlWriter->endElement();
514
        $this->_xmlWriter->startElement(ODataConstants::END);
515
        $this->_xmlWriter->writeAttribute(ODataConstants::ROLE, $associationTypeEnd2->getName());
516
        $this->_xmlWriter->writeAttribute(ODataConstants::ENTITY_SET, $associationSet->getEnd2()->getResourceSet()->getName());
517
        $this->_xmlWriter->endElement();
518
    }
519
520
    /**
521
     * Gets the edmx schema namespace uri for the given schema version
522
     *
523
     * @param EdmSchemaVersion $edmSchemaVersion metadata edm
524
     * schema version
525
     *
526
     * @return string The schema namespace uri
527
     */
528
    private function _getSchemaNamespaceUri($edmSchemaVersion)
529
    {
530
        switch ($edmSchemaVersion) {
531
            case EdmSchemaVersion::VERSION_1_DOT_0:
532
                return ODataConstants::CSDL_VERSION_1_0;
533
534
            case EdmSchemaVersion::VERSION_1_DOT_1:
535
                return ODataConstants::CSDL_VERSION_1_1;
536
537
            case EdmSchemaVersion::VERSION_1_DOT_2:
538
                return ODataConstants::CSDL_VERSION_1_2;
539
540
            case EdmSchemaVersion::VERSION_2_DOT_0:
541
                return ODataConstants::CSDL_VERSION_2_0;
542
543
            case EdmSchemaVersion::VERSION_2_DOT_2:
544
                return ODataConstants::CSDL_VERSION_2_2;
545
546
            default:
547
                return ODataConstants::CSDL_VERSION_2_2;
548
        }
549
    }
550
}
551