Completed
Pull Request — master (#40)
by Robbert van den
02:31
created

Schema::getElement()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GoetasWebservices\XML\XSDReader\Schema;
6
7
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeDef;
8
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeItem;
9
use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group as AttributeGroup;
10
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef;
11
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementItem;
12
use GoetasWebservices\XML\XSDReader\Schema\Element\Group;
13
use GoetasWebservices\XML\XSDReader\Schema\Exception\SchemaException;
14
use GoetasWebservices\XML\XSDReader\Schema\Exception\TypeNotFoundException;
15
use GoetasWebservices\XML\XSDReader\Schema\Type\Type;
16
17
class Schema
18
{
19
    /**
20
     * @param bool[] $calling
21
     */
22 63
    protected function findSomethingNoThrow(
23
        string $getter,
24
        string $name,
25
        string $namespace = null,
26
        array &$calling = array()
27
    ): ? SchemaItem {
28 63
        $calling[spl_object_hash($this)] = true;
29 63
        $cid = "$getter, $name, $namespace";
30
31 63
        if (isset($this->typeCache[$cid])) {
32 63
            return $this->typeCache[$cid];
33
        } elseif (
34 63
            $this->getTargetNamespace() === $namespace
35
        ) {
36
            /**
37
             * @var SchemaItem|null
38
             */
39 63
            $item = $this->$getter($name);
40
41 63
            if ($item instanceof SchemaItem) {
42 63
                return $this->typeCache[$cid] = $item;
43
            }
44
        }
45
46 63
        return $this->findSomethingNoThrowSchemas(
47 63
            $this->getSchemas(),
48 63
            $cid,
49 63
            $getter,
50 63
            $name,
51 63
            $namespace,
52 63
            $calling
53
        );
54
    }
55
56
    /**
57
     * @param Schema[] $schemas
58
     * @param bool[]   $calling
59
     */
60 63
    protected function findSomethingNoThrowSchemas(
61
        array $schemas,
62
        string $cid,
63
        string $getter,
64
        string $name,
65
        string $namespace = null,
66
        array &$calling = array()
67
    ): ? SchemaItem {
68 63
        foreach ($schemas as $childSchema) {
69 63
            if (!isset($calling[spl_object_hash($childSchema)])) {
70
                /**
71
                 * @var SchemaItem|null
72
                 */
73 63
                $in = $childSchema->findSomethingNoThrow($getter, $name, $namespace, $calling);
74
75 63
                if ($in instanceof SchemaItem) {
76 63
                    return $this->typeCache[$cid] = $in;
77
                }
78
            }
79
        }
80
81 10
        return null;
82
    }
83
84
    /**
85
     * @throws TypeNotFoundException
86
     */
87 63
    protected function findSomething(string $getter, string $name, string $namespace = null, array &$calling = array()): SchemaItem
88
    {
89 63
        $in = $this->findSomethingNoThrow(
90 63
            $getter,
91 63
            $name,
92 63
            $namespace,
93 63
            $calling
94
        );
95
96 63
        if ($in instanceof SchemaItem) {
97 63
            return $in;
98
        }
99
100 5
        throw new TypeNotFoundException(
101 5
            sprintf(
102 5
                "Can't find the %s named {%s}#%s.",
103 5
                (string) substr($getter, 3),
104 5
                $namespace,
105 5
                $name
106
            )
107
        );
108
    }
109
110
    /**
111
     * @var bool
112
     */
113
    protected $elementsQualification = false;
114
115
    /**
116
     * @var bool
117
     */
118
    protected $attributesQualification = false;
119
120
    /**
121
     * @var string|null
122
     */
123
    protected $targetNamespace;
124
125
    /**
126
     * @var Schema[]
127
     */
128
    protected $schemas = array();
129
130
    /**
131
     * @var Type[]
132
     */
133
    protected $types = array();
134
135
    /**
136
     * @var ElementDef[]
137
     */
138
    protected $elements = array();
139
140
    /**
141
     * @var Group[]
142
     */
143
    protected $groups = array();
144
145
    /**
146
     * @var AttributeGroup[]
147
     */
148
    protected $attributeGroups = array();
149
150
    /**
151
     * @var AttributeDef[]
152
     */
153
    protected $attributes = array();
154
155
    /**
156
     * @var string|null
157
     */
158
    protected $doc;
159
160
    /**
161
     * @var \GoetasWebservices\XML\XSDReader\Schema\SchemaItem[]
162
     */
163
    protected $typeCache = array();
164
165 1
    public function getElementsQualification(): bool
166
    {
167 1
        return $this->elementsQualification;
168
    }
169
170 63
    public function setElementsQualification(bool $elementsQualification): void
171
    {
172 63
        $this->elementsQualification = $elementsQualification;
173 63
    }
174
175
    public function getAttributesQualification(): bool
176
    {
177
        return $this->attributesQualification;
178
    }
179
180 63
    public function setAttributesQualification(bool $attributesQualification): void
181
    {
182 63
        $this->attributesQualification = $attributesQualification;
183 63
    }
184
185 63
    public function getTargetNamespace(): ?string
186
    {
187 63
        return $this->targetNamespace;
188
    }
189
190 63
    public function setTargetNamespace(? string $targetNamespace): void
191
    {
192 63
        $this->targetNamespace = $targetNamespace;
193 63
    }
194
195
    /**
196
     * @return Type[]
197
     */
198 6
    public function getTypes(): array
199
    {
200 6
        return $this->types;
201
    }
202
203
    /**
204
     * @return ElementDef[]
205
     */
206 4
    public function getElements(): array
207
    {
208 4
        return $this->elements;
209
    }
210
211
    /**
212
     * @return Schema[]
213
     */
214 63
    public function getSchemas(): array
215
    {
216 63
        return $this->schemas;
217
    }
218
219
    /**
220
     * @return AttributeDef[]
221
     */
222 1
    public function getAttributes(): array
223
    {
224 1
        return $this->attributes;
225
    }
226
227
    /**
228
     * @return Group[]
229
     */
230 2
    public function getGroups(): array
231
    {
232 2
        return $this->groups;
233
    }
234
235
    public function getDoc(): ?string
236
    {
237
        return $this->doc;
238
    }
239
240 63
    public function setDoc(string $doc): void
241
    {
242 63
        $this->doc = $doc;
243 63
    }
244
245 63
    public function addType(Type $type): void
246
    {
247 63
        $this->types[(string) $type->getName()] = $type;
248 63
    }
249
250 63
    public function addElement(ElementDef $element): void
251
    {
252 63
        $this->elements[$element->getName()] = $element;
253 63
    }
254
255 63
    public function addSchema(self $schema, string $namespace = null): void
256
    {
257 63
        if ($namespace === null) {
258 63
            $this->schemas[] = $schema;
259 63
            return;
260
        }
261
262 63
        if ($schema->getTargetNamespace() !== $namespace) {
263
            throw new SchemaException(
264
                sprintf(
265
                    "The target namespace ('%s') for schema, does not match the declared namespace '%s'",
266
                    $schema->getTargetNamespace(),
267
                    $namespace
268
                )
269
            );
270
        }
271
272 63
        if (isset($this->schemas[$namespace])) {
273 1
            $this->schemas[$namespace]->addSchema($schema);
274 1
            return;
275
        }
276
277 63
        $this->schemas[$namespace] = $schema;
278 63
    }
279
280 63
    public function addAttribute(AttributeDef $attribute): void
281
    {
282 63
        $this->attributes[$attribute->getName()] = $attribute;
283 63
    }
284
285 63
    public function addGroup(Group $group): void
286
    {
287 63
        $this->groups[$group->getName()] = $group;
288 63
    }
289
290 63
    public function addAttributeGroup(AttributeGroup $group): void
291
    {
292 63
        $this->attributeGroups[$group->getName()] = $group;
293 63
    }
294
295
    /**
296
     * @return AttributeGroup[]
297
     */
298 1
    public function getAttributeGroups(): array
299
    {
300 1
        return $this->attributeGroups;
301
    }
302
303 63
    public function getGroup(string $name): ?Group
304
    {
305 63
        if (isset($this->groups[$name])) {
306 63
            return $this->groups[$name];
307
        }
308
309
        return null;
310
    }
311
312 63
    public function getElement(string $name): ?ElementItem
313
    {
314 63
        if (isset($this->elements[$name])) {
315 63
            return $this->elements[$name];
316
        }
317
318 1
        return null;
319
    }
320
321 63
    public function getType(string $name): ?Type
322
    {
323 63
        if (isset($this->types[$name])) {
324 63
            return $this->types[$name];
325
        }
326
327 1
        return null;
328
    }
329
330 63
    public function getAttribute(string $name): ? AttributeItem
331
    {
332 63
        if (isset($this->attributes[$name])) {
333 63
            return $this->attributes[$name];
334
        }
335
336
        return null;
337
    }
338
339 63
    public function getAttributeGroup(string $name): ?AttributeGroup
340
    {
341 63
        if (isset($this->attributeGroups[$name])) {
342 63
            return $this->attributeGroups[$name];
343
        }
344
345
        return null;
346
    }
347
348
    public function __toString(): string
349
    {
350
        return sprintf('Target namespace %s', $this->getTargetNamespace());
351
    }
352
353 63
    public function findType(string $name, string $namespace = null): Type
354
    {
355 63
        $out = $this->findSomething('getType', $name, $namespace);
356
357 63
        if (!($out instanceof Type)) {
358
            throw new TypeNotFoundException(sprintf("Can't find the %s named {%s}#%s.", 'Type', $namespace, $name));
359
        }
360
361 63
        return $out;
362
    }
363
364 63
    public function findGroup(string $name, string $namespace = null): Group
365
    {
366 63
        $out = $this->findSomething('getGroup', $name, $namespace);
367
368 63
        if (!($out instanceof Group)) {
369
            throw new TypeNotFoundException(sprintf("Can't find the %s named {%s}#%s.", 'Group', $namespace, $name));
370
        }
371
372 63
        return $out;
373
    }
374
375 63
    public function findElement(string $name, string $namespace = null): ElementDef
376
    {
377 63
        $out = $this->findSomething('getElement', $name, $namespace);
378
379 63
        if (!($out instanceof ElementDef)) {
380
            throw new TypeNotFoundException(sprintf("Can't find the %s named {%s}#%s.", 'Element', $namespace, $name));
381
        }
382
383 63
        return $out;
384
    }
385
386 63
    public function findAttribute(string $name, string $namespace = null): AttributeItem
387
    {
388 63
        $out = $this->findSomething('getAttribute', $name, $namespace);
389
390 63
        if (!($out instanceof AttributeItem)) {
391
            throw new TypeNotFoundException(sprintf("Can't find the %s named {%s}#%s.", 'Attribute', $namespace, $name));
392
        }
393
394 63
        return $out;
395
    }
396
397 63
    public function findAttributeGroup(string $name, string $namespace = null): AttributeGroup
398
    {
399 63
        $out = $this->findSomething('getAttributeGroup', $name, $namespace);
400
401 63
        if (!($out instanceof AttributeGroup)) {
402
            throw new TypeNotFoundException(sprintf("Can't find the %s named {%s}#%s.", 'AttributeGroup', $namespace, $name));
403
        }
404
405 63
        return $out;
406
    }
407
}
408