85040221a5d314dffebaeae6d9ca32f1b8180a2b
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2021 Bell Canada. All rights reserved.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.model.policymodel.handling;
23
24 import java.util.Map;
25 import java.util.UUID;
26 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
27 import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInfo;
28 import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInformation;
29 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
30 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
31 import org.onap.policy.apex.model.basicmodel.test.TestApexModelCreator;
32 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
33 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbums;
34 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
35 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
36 import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
37 import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
38 import org.onap.policy.apex.model.eventmodel.concepts.AxField;
39 import org.onap.policy.apex.model.policymodel.concepts.AxPolicies;
40 import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
41 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
42 import org.onap.policy.apex.model.policymodel.concepts.AxState;
43 import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
44 import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput;
45 import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskOutputType;
46 import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskReference;
47 import org.onap.policy.apex.model.policymodel.concepts.AxTask;
48 import org.onap.policy.apex.model.policymodel.concepts.AxTaskLogic;
49 import org.onap.policy.apex.model.policymodel.concepts.AxTaskParameter;
50 import org.onap.policy.apex.model.policymodel.concepts.AxTaskSelectionLogic;
51 import org.onap.policy.apex.model.policymodel.concepts.AxTasks;
52
53 /**
54  * Model creator for model tests.
55  *
56  * @author Liam Fallon (liam.fallon@ericsson.com)
57  */
58 public class SupportApexPolicyModelCreator implements TestApexModelCreator<AxPolicyModel> {
59
60     @Override
61     public AxPolicyModel getModel() {
62         final AxContextSchema schema0 = new AxContextSchema(new AxArtifactKey("eventContextItem0", "0.0.1"), "Java",
63                         "java.lang.String");
64         final AxContextSchema schema1 = new AxContextSchema(new AxArtifactKey("eventContextItem1", "0.0.1"), "Java",
65                         "java.lang.Long");
66         final AxContextSchema schema2 = new AxContextSchema(new AxArtifactKey("StringType", "0.0.1"), "Java",
67                         "org.onap.policy.apex.model.policymodel.concepts.TestContextItem000");
68         final AxContextSchema schema3 = new AxContextSchema(new AxArtifactKey("MapType", "0.0.1"), "Java",
69                         "org.onap.policy.apex.model.policymodel.concepts.TestContextItem00A");
70
71         final AxContextSchemas schemas = new AxContextSchemas(new AxArtifactKey("ContextSchemas", "0.0.1"));
72         schemas.getSchemasMap().put(schema0.getKey(), schema0);
73         schemas.getSchemasMap().put(schema1.getKey(), schema1);
74         schemas.getSchemasMap().put(schema2.getKey(), schema2);
75         schemas.getSchemasMap().put(schema3.getKey(), schema3);
76
77         final AxContextAlbum album0 = new AxContextAlbum(new AxArtifactKey("contextAlbum0", "0.0.1"), "APPLICATION",
78                         true, schema3.getKey());
79         final AxContextAlbum album1 = new AxContextAlbum(new AxArtifactKey("contextAlbum1", "0.0.1"), "GLOBAL", false,
80                         schema2.getKey());
81
82         final AxContextAlbums albums = new AxContextAlbums(new AxArtifactKey("context", "0.0.1"));
83         albums.getAlbumsMap().put(album0.getKey(), album0);
84         albums.getAlbumsMap().put(album1.getKey(), album1);
85
86         final AxEvent inEvent = new AxEvent(new AxArtifactKey("inEvent", "0.0.1"),
87                         "org.onap.policy.apex.model.policymodel.events", "Source", "Target");
88         inEvent.getParameterMap().put("IEPAR0",
89                         new AxField(new AxReferenceKey(inEvent.getKey(), "IEPAR0"), schema0.getKey()));
90         inEvent.getParameterMap().put("IEPAR1",
91                         new AxField(new AxReferenceKey(inEvent.getKey(), "IEPAR1"), schema1.getKey()));
92
93         final AxEvent outEvent0 = new AxEvent(new AxArtifactKey("outEvent0", "0.0.1"),
94                         "org.onap.policy.apex.model.policymodel.events", "Source", "Target");
95         outEvent0.getParameterMap().put("OE0PAR0",
96                         new AxField(new AxReferenceKey(outEvent0.getKey(), "OE0PAR0"), schema0.getKey()));
97         outEvent0.getParameterMap().put("OE0PAR1",
98                         new AxField(new AxReferenceKey(outEvent0.getKey(), "OE0PAR1"), schema1.getKey()));
99         outEvent0.getParameterMap().put("OE1PAR0",
100                         new AxField(new AxReferenceKey(outEvent0.getKey(), "OE1PAR0"), schema0.getKey()));
101         outEvent0.getParameterMap().put("OE1PAR1",
102                         new AxField(new AxReferenceKey(outEvent0.getKey(), "OE1PAR1"), schema1.getKey()));
103
104         final AxEvent outEvent1 = new AxEvent(new AxArtifactKey("outEvent1", "0.0.1"),
105                         "org.onap.policy.apex.model.policymodel.events", "Source", "Target");
106         outEvent1.getParameterMap().put("OE1PAR0",
107                         new AxField(new AxReferenceKey(outEvent1.getKey(), "OE1PAR0"), schema0.getKey()));
108         outEvent1.getParameterMap().put("OE1PAR1",
109                         new AxField(new AxReferenceKey(outEvent1.getKey(), "OE1PAR1"), schema1.getKey()));
110
111         final AxEvents events = new AxEvents(new AxArtifactKey("events", "0.0.1"));
112         events.getEventMap().put(inEvent.getKey(), inEvent);
113         events.getEventMap().put(outEvent0.getKey(), outEvent0);
114         events.getEventMap().put(outEvent1.getKey(), outEvent1);
115
116         final AxTask task = new AxTask(new AxArtifactKey("task", "0.0.1"));
117
118         task.setInputEvent(inEvent);
119         task.setOutputEvents(Map.of(outEvent0.getId(), outEvent0, outEvent1.getId(), outEvent1));
120
121         final AxTaskParameter taskPar0 = new AxTaskParameter(new AxReferenceKey(task.getKey(), "taskParameter0"),
122                         "Task parameter 0 value");
123         final AxTaskParameter taskPar1 = new AxTaskParameter(new AxReferenceKey(task.getKey(), "taskParameter1"),
124                         "Task parameter 1 value");
125
126         task.getTaskParameters().put(taskPar0.getKey().getLocalName(), taskPar0);
127         task.getTaskParameters().put(taskPar1.getKey().getLocalName(), taskPar1);
128         task.getContextAlbumReferences().add(album0.getKey());
129         task.getContextAlbumReferences().add(album1.getKey());
130
131         final AxTaskLogic taskLogic = new AxTaskLogic(new AxReferenceKey(task.getKey(), "taskLogic"), "MVEL",
132                         "Some task logic");
133         task.setTaskLogic(taskLogic);
134
135         final AxTasks tasks = new AxTasks(new AxArtifactKey("tasks", "0.0.1"));
136         tasks.getTaskMap().put(task.getKey(), task);
137
138         final AxPolicy policy = new AxPolicy(new AxArtifactKey("policy", "0.0.1"));
139         policy.setTemplate("FREEFORM");
140
141         final AxState state = new AxState(new AxReferenceKey(policy.getKey(), "state"));
142         final AxTaskSelectionLogic taskSelectionLogic = new AxTaskSelectionLogic(
143                         new AxReferenceKey(state.getKey(), "taskSelectionLogic"), "MVEL", "Some TS logic ");
144
145         state.setTrigger(inEvent.getKey());
146         state.getContextAlbumReferences().add(album0.getKey());
147         state.getContextAlbumReferences().add(album1.getKey());
148         state.setTaskSelectionLogic(taskSelectionLogic);
149         state.setDefaultTask(task.getKey());
150
151         final AxStateOutput stateOutput0 = new AxStateOutput(new AxReferenceKey(state.getKey(), "stateOutput0"),
152                         outEvent0.getKey(), AxReferenceKey.getNullKey());
153         state.getStateOutputs().put(stateOutput0.getKey().getLocalName(), stateOutput0);
154
155         final AxStateTaskReference stateTaskReference = new AxStateTaskReference(
156                         new AxReferenceKey(state.getKey(), task.getKey().getName()), AxStateTaskOutputType.DIRECT,
157                         stateOutput0.getKey());
158
159         state.getTaskReferences().put(task.getKey(), stateTaskReference);
160
161         policy.getStateMap().put(state.getKey().getLocalName(), state);
162         policy.setFirstState(state.getKey().getLocalName());
163
164         final AxPolicies policies = new AxPolicies(new AxArtifactKey("policies", "0.0.1"));
165         policies.getPolicyMap().put(policy.getKey(), policy);
166
167         final AxKeyInformation keyInformation = new AxKeyInformation(new AxArtifactKey("KeyInfoMapKey", "0.0.1"));
168         final AxPolicyModel policyModel = new AxPolicyModel(new AxArtifactKey("PolicyModel", "0.0.1"));
169         policyModel.setKeyInformation(keyInformation);
170         policyModel.setSchemas(schemas);
171         policyModel.setAlbums(albums);
172         policyModel.setEvents(events);
173         policyModel.setTasks(tasks);
174         policyModel.setPolicies(policies);
175         policyModel.getKeyInformation().generateKeyInfo(policyModel);
176
177         int uuidIncrementer = 0;
178         for (final AxKeyInfo keyInfo : policyModel.getKeyInformation().getKeyInfoMap().values()) {
179             final String uuidString = String.format("ce9168c-e6df-414f-9646-6da464b6e%03d", uuidIncrementer++);
180             keyInfo.setUuid(UUID.fromString(uuidString));
181         }
182
183         final AxValidationResult result = new AxValidationResult();
184         policyModel.validate(result);
185
186         return policyModel;
187     }
188
189     /**
190      * Gets another policy model.
191      *
192      * @return the model
193      */
194     public AxPolicyModel getAnotherModel() {
195         final AxContextSchema schema0 = new AxContextSchema(new AxArtifactKey("eventContextItemA0", "0.0.1"), "Java",
196                         "java.lang.String");
197         final AxContextSchema schema1 = new AxContextSchema(new AxArtifactKey("eventContextItemA1", "0.0.1"), "Java",
198                         "java.lang.Long");
199         final AxContextSchema schema2 = new AxContextSchema(new AxArtifactKey("StringTypeA", "0.0.1"), "Java",
200                         "org.onap.policy.apex.model.policymodel.concepts.TestContextItem000");
201         final AxContextSchema schema3 = new AxContextSchema(new AxArtifactKey("MapTypeA", "0.0.1"), "Java",
202                         "org.onap.policy.apex.model.policymodel.concepts.TestContextItem00A");
203
204         final AxContextSchemas schemas = new AxContextSchemas(new AxArtifactKey("ContextSchemasA", "0.0.1"));
205         schemas.getSchemasMap().put(schema0.getKey(), schema0);
206         schemas.getSchemasMap().put(schema1.getKey(), schema1);
207         schemas.getSchemasMap().put(schema2.getKey(), schema2);
208         schemas.getSchemasMap().put(schema3.getKey(), schema3);
209
210         final AxContextAlbum album0 = new AxContextAlbum(new AxArtifactKey("contextAlbumA0", "0.0.1"), "APPLICATION",
211                         true, schema3.getKey());
212         final AxContextAlbum album1 = new AxContextAlbum(new AxArtifactKey("contextAlbumA1", "0.0.1"), "GLOBAL", false,
213                         schema2.getKey());
214
215         final AxContextAlbums albums = new AxContextAlbums(new AxArtifactKey("contextA", "0.0.1"));
216         albums.getAlbumsMap().put(album0.getKey(), album0);
217         albums.getAlbumsMap().put(album1.getKey(), album1);
218
219         final AxEvent inEvent = new AxEvent(new AxArtifactKey("inEventA", "0.0.1"),
220                         "org.onap.policy.apex.model.policymodel.events", "Source", "Target");
221         inEvent.getParameterMap().put("IEPARA0",
222                         new AxField(new AxReferenceKey(inEvent.getKey(), "IEPARA0"), schema0.getKey()));
223         inEvent.getParameterMap().put("IEPARA1",
224                         new AxField(new AxReferenceKey(inEvent.getKey(), "IEPARA1"), schema1.getKey()));
225
226         final AxEvent outEvent0 = new AxEvent(new AxArtifactKey("outEventA0", "0.0.1"),
227                         "org.onap.policy.apex.model.policymodel.events", "Source", "Target");
228         outEvent0.getParameterMap().put("OE0PARA0",
229                         new AxField(new AxReferenceKey(outEvent0.getKey(), "OE0PARA0"), schema0.getKey()));
230         outEvent0.getParameterMap().put("OE0PARA1",
231                         new AxField(new AxReferenceKey(outEvent0.getKey(), "OE0PARA1"), schema1.getKey()));
232         outEvent0.getParameterMap().put("OE1PARA0",
233                         new AxField(new AxReferenceKey(outEvent0.getKey(), "OE1PARA0"), schema0.getKey()));
234         outEvent0.getParameterMap().put("OE1PARA1",
235                         new AxField(new AxReferenceKey(outEvent0.getKey(), "OE1PARA1"), schema1.getKey()));
236
237         final AxEvent outEvent1 = new AxEvent(new AxArtifactKey("outEventA1", "0.0.1"),
238                         "org.onap.policy.apex.model.policymodel.events", "Source", "Target");
239         outEvent1.getParameterMap().put("OE1PARA0",
240                         new AxField(new AxReferenceKey(outEvent1.getKey(), "OE1PARA0"), schema0.getKey()));
241         outEvent1.getParameterMap().put("OE1PARA1",
242                         new AxField(new AxReferenceKey(outEvent1.getKey(), "OE1PARA1"), schema1.getKey()));
243
244         final AxEvents events = new AxEvents(new AxArtifactKey("eventsA", "0.0.1"));
245         events.getEventMap().put(inEvent.getKey(), inEvent);
246         events.getEventMap().put(outEvent0.getKey(), outEvent0);
247         events.getEventMap().put(outEvent1.getKey(), outEvent1);
248
249         final AxTask task = new AxTask(new AxArtifactKey("taskA", "0.0.1"));
250
251         task.setInputEvent(inEvent);
252         task.setOutputEvents(Map.of(outEvent0.getId(), outEvent0, outEvent1.getId(), outEvent1));
253
254         final AxTaskParameter taskPar0 = new AxTaskParameter(new AxReferenceKey(task.getKey(), "taskParameterA0"),
255                         "Task parameter 0 value");
256         final AxTaskParameter taskPar1 = new AxTaskParameter(new AxReferenceKey(task.getKey(), "taskParameterA1"),
257                         "Task parameter 1 value");
258
259         task.getTaskParameters().put(taskPar0.getKey().getLocalName(), taskPar0);
260         task.getTaskParameters().put(taskPar1.getKey().getLocalName(), taskPar1);
261         task.getContextAlbumReferences().add(album0.getKey());
262         task.getContextAlbumReferences().add(album1.getKey());
263
264         final AxTaskLogic taskLogic = new AxTaskLogic(new AxReferenceKey(task.getKey(), "taskLogicA"), "MVEL",
265                         "Some task logic");
266         task.setTaskLogic(taskLogic);
267
268         final AxTasks tasks = new AxTasks(new AxArtifactKey("tasksA", "0.0.1"));
269         tasks.getTaskMap().put(task.getKey(), task);
270
271         final AxPolicy policy = new AxPolicy(new AxArtifactKey("policyA", "0.0.1"));
272         policy.setTemplate("FREEFORM");
273
274         final AxState state = new AxState(new AxReferenceKey(policy.getKey(), "stateA"));
275         final AxTaskSelectionLogic taskSelectionLogic = new AxTaskSelectionLogic(
276                         new AxReferenceKey(state.getKey(), "taskSelectionLogicA"), "MVEL", "Some TS logic ");
277
278         state.setTrigger(inEvent.getKey());
279         state.getContextAlbumReferences().add(album0.getKey());
280         state.getContextAlbumReferences().add(album1.getKey());
281         state.setTaskSelectionLogic(taskSelectionLogic);
282         state.setDefaultTask(task.getKey());
283
284         final AxStateOutput stateOutput0 = new AxStateOutput(new AxReferenceKey(state.getKey(), "stateOutputA0"),
285                         outEvent0.getKey(), AxReferenceKey.getNullKey());
286         state.getStateOutputs().put(stateOutput0.getKey().getLocalName(), stateOutput0);
287
288         final AxStateTaskReference stateTaskReference = new AxStateTaskReference(
289                         new AxReferenceKey(state.getKey(), task.getKey().getName()), AxStateTaskOutputType.DIRECT,
290                         stateOutput0.getKey());
291
292         state.getTaskReferences().put(task.getKey(), stateTaskReference);
293
294         policy.getStateMap().put(state.getKey().getLocalName(), state);
295         policy.setFirstState(state.getKey().getLocalName());
296
297         final AxPolicies policies = new AxPolicies(new AxArtifactKey("policiesA", "0.0.1"));
298         policies.getPolicyMap().put(policy.getKey(), policy);
299
300         final AxKeyInformation keyInformation = new AxKeyInformation(new AxArtifactKey("KeyInfoMapKeyA", "0.0.1"));
301         final AxPolicyModel policyModel = new AxPolicyModel(new AxArtifactKey("PolicyModelA", "0.0.1"));
302         policyModel.setKeyInformation(keyInformation);
303         policyModel.setSchemas(schemas);
304         policyModel.setAlbums(albums);
305         policyModel.setEvents(events);
306         policyModel.setTasks(tasks);
307         policyModel.setPolicies(policies);
308         policyModel.getKeyInformation().generateKeyInfo(policyModel);
309
310         int uuidIncrementer = 0;
311         for (final AxKeyInfo keyInfo : policyModel.getKeyInformation().getKeyInfoMap().values()) {
312             final String uuidString = String.format("ce9168c-e6df-414f-9646-6da464b6e%03d", uuidIncrementer++);
313             keyInfo.setUuid(UUID.fromString(uuidString));
314         }
315
316         final AxValidationResult result = new AxValidationResult();
317         policyModel.validate(result);
318
319         return policyModel;
320     }
321
322     @Override
323     public AxPolicyModel getMalstructuredModel() {
324         final AxPolicyModel policyModel = new AxPolicyModel(new AxArtifactKey("policyModel", "0.0.1"));
325         return policyModel;
326     }
327
328     @Override
329     public AxPolicyModel getObservationModel() {
330         final AxPolicyModel policyModel = getModel();
331
332         final AxState state = policyModel.getPolicies().get("policy").getStateMap().get("state");
333         final AxTask task = policyModel.getTasks().get("task");
334
335         final AxStateFinalizerLogic stateFinalizerLogic = new AxStateFinalizerLogic(
336                         new AxReferenceKey(state.getKey(), "SFL"), "MVEL", "Some SF logic ");
337         state.getStateFinalizerLogicMap().put(stateFinalizerLogic.getKey().getLocalName(), stateFinalizerLogic);
338         final AxStateTaskReference stateTaskReference = new AxStateTaskReference(
339                         new AxReferenceKey(state.getKey(), task.getKey().getName()), AxStateTaskOutputType.LOGIC,
340                         stateFinalizerLogic.getKey());
341
342         state.getTaskReferences().put(task.getKey(), stateTaskReference);
343
344         return policyModel;
345     }
346
347     @Override
348     public AxPolicyModel getWarningModel() {
349         final AxPolicyModel policyModel = getModel();
350
351         final AxState anotherState = new AxState(
352                         new AxReferenceKey(new AxArtifactKey("policy", "0.0.1"), "anotherState"));
353
354         final AxEvent inEvent = policyModel.getEvents().getEventMap().get(new AxArtifactKey("inEvent", "0.0.1"));
355         final AxEvent outEvent0 = policyModel.getEvents().getEventMap().get(new AxArtifactKey("outEvent0", "0.0.1"));
356
357         final AxTask anotherTask = new AxTask(new AxArtifactKey("anotherTask", "0.0.1"));
358
359         anotherTask.setInputEvent(inEvent);
360         anotherTask.setOutputEvents(Map.of(outEvent0.getId(), outEvent0));
361         final AxTaskParameter taskPar0 = new AxTaskParameter(new AxReferenceKey(anotherTask.getKey(), "taskParameter0"),
362                         "Task parameter 0 value");
363         final AxTaskParameter taskPar1 = new AxTaskParameter(new AxReferenceKey(anotherTask.getKey(), "taskParameter1"),
364                         "Task parameter 1 value");
365
366         anotherTask.getTaskParameters().put(taskPar0.getKey().getLocalName(), taskPar0);
367         anotherTask.getTaskParameters().put(taskPar1.getKey().getLocalName(), taskPar1);
368
369         final AxTaskLogic taskLogic = new AxTaskLogic(new AxReferenceKey(anotherTask.getKey(), "taskLogic"), "MVEL",
370                         "Some task logic");
371         anotherTask.setTaskLogic(taskLogic);
372         policyModel.getTasks().getTaskMap().put(anotherTask.getKey(), anotherTask);
373
374         final AxStateOutput anotherStateOutput0 = new AxStateOutput(
375                         new AxReferenceKey(anotherState.getKey(), "stateOutput0"), outEvent0.getKey(),
376                         AxReferenceKey.getNullKey());
377         anotherState.setTrigger(inEvent.getKey());
378         anotherState.getStateOutputs().put(anotherStateOutput0.getKey().getLocalName(), anotherStateOutput0);
379         anotherState.setDefaultTask(anotherTask.getKey());
380         final AxStateTaskReference anotherStateTaskReference = new AxStateTaskReference(
381                         new AxReferenceKey(anotherState.getKey(), anotherTask.getKey().getName()),
382                         AxStateTaskOutputType.DIRECT, anotherStateOutput0.getKey());
383         anotherState.getTaskReferences().put(anotherTask.getKey(), anotherStateTaskReference);
384
385         policyModel.getPolicies().getPolicyMap().get(new AxArtifactKey("policy", "0.0.1")).getStateMap()
386                         .put(anotherState.getKey().getLocalName(), anotherState);
387
388         policyModel.getKeyInformation().generateKeyInfo(policyModel);
389
390         return policyModel;
391     }
392
393     @Override
394     public AxPolicyModel getInvalidModel() {
395         final AxPolicyModel policyModel = getModel();
396
397         policyModel.getAlbums().get(new AxArtifactKey("contextAlbum0", "0.0.1")).setScope("UNDEFINED");
398         policyModel.getAlbums().get(new AxArtifactKey("contextAlbum1", "0.0.1")).setScope("UNDEFINED");
399
400         final AxEvent outEvent0 = policyModel.getEvents().get("outEvent0");
401         outEvent0.getParameterMap().remove("OE1PAR0");
402         outEvent0.getParameterMap().remove("OE1PAR1");
403
404         return policyModel;
405     }
406 }