da101a2e6db0106bf3eefa247847cf1e16d40faf
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7  * ================================================================================
8  * Modifications Copyright (c) 2019 Samsung
9  * ================================================================================
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  * 
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  * 
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.so.apihandlerinfra;
25
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Optional;
32 import javax.transaction.Transactional;
33 import javax.ws.rs.Consumes;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.POST;
36 import javax.ws.rs.PUT;
37 import javax.ws.rs.Path;
38 import javax.ws.rs.PathParam;
39 import javax.ws.rs.Produces;
40 import javax.ws.rs.container.ContainerRequestContext;
41 import javax.ws.rs.core.Context;
42 import javax.ws.rs.core.MediaType;
43 import javax.ws.rs.core.Response;
44 import org.apache.commons.lang.StringUtils;
45 import org.apache.http.HttpStatus;
46 import org.onap.so.apihandler.common.CommonConstants;
47 import org.onap.so.apihandler.common.ErrorNumbers;
48 import org.onap.so.apihandler.common.RequestClientParameter;
49 import org.onap.so.apihandlerinfra.exceptions.ApiException;
50 import org.onap.so.apihandlerinfra.exceptions.RecipeNotFoundException;
51 import org.onap.so.apihandlerinfra.exceptions.RequestDbFailureException;
52 import org.onap.so.apihandlerinfra.exceptions.ValidateException;
53 import org.onap.so.apihandlerinfra.infra.rest.handler.AbstractRestHandler;
54 import org.onap.so.apihandlerinfra.infra.rest.validators.RequestValidatorListenerRunner;
55 import org.onap.so.apihandlerinfra.logging.ErrorLoggerInfo;
56 import org.onap.so.constants.Status;
57 import org.onap.so.db.catalog.beans.NetworkResource;
58 import org.onap.so.db.catalog.beans.NetworkResourceCustomization;
59 import org.onap.so.db.catalog.beans.Recipe;
60 import org.onap.so.db.catalog.beans.ServiceRecipe;
61 import org.onap.so.db.catalog.beans.VfModule;
62 import org.onap.so.db.catalog.beans.VfModuleCustomization;
63 import org.onap.so.db.catalog.beans.VnfRecipe;
64 import org.onap.so.db.catalog.beans.VnfResource;
65 import org.onap.so.db.catalog.beans.VnfResourceCustomization;
66 import org.onap.so.db.catalog.client.CatalogDbClient;
67 import org.onap.so.db.request.beans.InfraActiveRequests;
68 import org.onap.so.db.request.client.RequestsDbClient;
69 import org.onap.so.exceptions.ValidationException;
70 import org.onap.so.logger.ErrorCode;
71 import org.onap.so.logger.MessageEnum;
72 import org.onap.so.serviceinstancebeans.CloudConfiguration;
73 import org.onap.so.serviceinstancebeans.ModelInfo;
74 import org.onap.so.serviceinstancebeans.ModelType;
75 import org.onap.so.serviceinstancebeans.Networks;
76 import org.onap.so.serviceinstancebeans.RelatedInstance;
77 import org.onap.so.serviceinstancebeans.RelatedInstanceList;
78 import org.onap.so.serviceinstancebeans.RequestDetails;
79 import org.onap.so.serviceinstancebeans.RequestParameters;
80 import org.onap.so.serviceinstancebeans.RequestReferences;
81 import org.onap.so.serviceinstancebeans.Service;
82 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
83 import org.onap.so.serviceinstancebeans.ServiceInstancesResponse;
84 import org.onap.so.serviceinstancebeans.VfModules;
85 import org.onap.so.serviceinstancebeans.Vnfs;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
88 import org.springframework.beans.factory.annotation.Autowired;
89 import org.springframework.core.env.Environment;
90 import org.springframework.stereotype.Component;
91 import org.springframework.web.client.RestTemplate;
92 import com.fasterxml.jackson.databind.ObjectMapper;
93 import io.swagger.v3.oas.annotations.OpenAPIDefinition;
94 import io.swagger.v3.oas.annotations.Operation;
95 import io.swagger.v3.oas.annotations.info.Info;
96 import io.swagger.v3.oas.annotations.media.ArraySchema;
97 import io.swagger.v3.oas.annotations.media.Content;
98 import io.swagger.v3.oas.annotations.media.Schema;
99 import io.swagger.v3.oas.annotations.responses.ApiResponse;
100
101 @Component
102 @Path("/onap/so/infra/serviceInstantiation")
103 @OpenAPIDefinition(info = @Info(title = "/onap/so/infra/serviceInstantiation",
104         description = "Infrastructure API Requests for Service Instances"))
105 public class ServiceInstances extends AbstractRestHandler {
106
107     private static Logger logger = LoggerFactory.getLogger(MsoRequest.class);
108     private static String NAME = "name";
109     private static String VALUE = "value";
110     private static String uriPrefix = "/serviceInstantiation/";
111     private static final String SAVE_TO_DB = "save instance to db";
112
113     @Autowired
114     private Environment env;
115
116     @Autowired
117     private RestTemplate restTemplate;
118
119     @Autowired
120     private CatalogDbClient catalogDbClient;
121
122     @Autowired
123     private RequestsDbClient infraActiveRequestsClient;
124
125     @Autowired
126     private MsoRequest msoRequest;
127
128     @Autowired
129     private RequestHandlerUtils requestHandlerUtils;
130
131     @Autowired
132     private RequestValidatorListenerRunner requestValidatorListenerRunner;
133
134     @POST
135     @Path("/{version:[vV][5-7]}/serviceInstances")
136     @Consumes(MediaType.APPLICATION_JSON)
137     @Produces(MediaType.APPLICATION_JSON)
138     @Operation(description = "Create a Service Instance on a version provided", responses = @ApiResponse(
139             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
140     @Transactional
141     public Response createServiceInstance(String request, @PathParam("version") String version,
142             @Context ContainerRequestContext requestContext) throws ApiException {
143         String requestId = requestHandlerUtils.getRequestId(requestContext);
144         return serviceInstances(request, Action.createInstance, null, version, requestId,
145                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
146     }
147
148     @POST
149     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/activate")
150     @Consumes(MediaType.APPLICATION_JSON)
151     @Produces(MediaType.APPLICATION_JSON)
152     @Operation(description = "Activate provided Service Instance", responses = @ApiResponse(
153             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
154     @Transactional
155     public Response activateServiceInstance(String request, @PathParam("version") String version,
156             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
157             throws ApiException {
158         String requestId = requestHandlerUtils.getRequestId(requestContext);
159         HashMap<String, String> instanceIdMap = new HashMap<>();
160         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
161         return serviceInstances(request, Action.activateInstance, instanceIdMap, version, requestId,
162                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
163     }
164
165     @POST
166     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/deactivate")
167     @Consumes(MediaType.APPLICATION_JSON)
168     @Produces(MediaType.APPLICATION_JSON)
169     @Operation(description = "Deactivate provided Service Instance", responses = @ApiResponse(
170             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
171     @Transactional
172     public Response deactivateServiceInstance(String request, @PathParam("version") String version,
173             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
174             throws ApiException {
175         String requestId = requestHandlerUtils.getRequestId(requestContext);
176         HashMap<String, String> instanceIdMap = new HashMap<>();
177         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
178         return serviceInstances(request, Action.deactivateInstance, instanceIdMap, version, requestId,
179                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
180     }
181
182     @DELETE
183     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}")
184     @Consumes(MediaType.APPLICATION_JSON)
185     @Produces(MediaType.APPLICATION_JSON)
186     @Operation(description = "Delete provided Service Instance", responses = @ApiResponse(
187             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
188     @Transactional
189     public Response deleteServiceInstance(String request, @PathParam("version") String version,
190             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
191             throws ApiException {
192         String requestId = requestHandlerUtils.getRequestId(requestContext);
193         HashMap<String, String> instanceIdMap = new HashMap<>();
194         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
195         return serviceInstances(request, Action.deleteInstance, instanceIdMap, version, requestId,
196                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
197     }
198
199     @POST
200     @Path("/{version:[vV][7]}/serviceInstances/assign")
201     @Consumes(MediaType.APPLICATION_JSON)
202     @Produces(MediaType.APPLICATION_JSON)
203     @Operation(description = "Assign Service Instance", responses = @ApiResponse(
204             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
205     @Transactional
206     public Response assignServiceInstance(String request, @PathParam("version") String version,
207             @Context ContainerRequestContext requestContext) throws ApiException {
208         String requestId = requestHandlerUtils.getRequestId(requestContext);
209         return serviceInstances(request, Action.assignInstance, null, version, requestId,
210                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
211     }
212
213     @POST
214     @Path("/{version:[vV][7]}/serviceInstances/{serviceInstanceId}/unassign")
215     @Consumes(MediaType.APPLICATION_JSON)
216     @Produces(MediaType.APPLICATION_JSON)
217     @Operation(description = "Unassign Service Instance", responses = @ApiResponse(
218             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
219     @Transactional
220     public Response unassignServiceInstance(String request, @PathParam("version") String version,
221             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
222             throws ApiException {
223         String requestId = requestHandlerUtils.getRequestId(requestContext);
224         HashMap<String, String> instanceIdMap = new HashMap<>();
225         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
226         return serviceInstances(request, Action.unassignInstance, instanceIdMap, version, requestId,
227                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
228     }
229
230     @POST
231     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/configurations")
232     @Consumes(MediaType.APPLICATION_JSON)
233     @Produces(MediaType.APPLICATION_JSON)
234     @Operation(description = "Create Port Mirroring Configuration", responses = @ApiResponse(
235             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
236     @Transactional
237     public Response createPortConfiguration(String request, @PathParam("version") String version,
238             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
239             throws ApiException {
240         String requestId = requestHandlerUtils.getRequestId(requestContext);
241         HashMap<String, String> instanceIdMap = new HashMap<>();
242         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
243         return configurationRecipeLookup(request, Action.createInstance, instanceIdMap, version, requestId,
244                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
245     }
246
247     @DELETE
248     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/configurations/{configurationInstanceId}")
249     @Consumes(MediaType.APPLICATION_JSON)
250     @Produces(MediaType.APPLICATION_JSON)
251     @Operation(description = "Delete provided Port", responses = @ApiResponse(
252             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
253     @Transactional
254     public Response deletePortConfiguration(String request, @PathParam("version") String version,
255             @PathParam("serviceInstanceId") String serviceInstanceId,
256             @PathParam("configurationInstanceId") String configurationInstanceId,
257             @Context ContainerRequestContext requestContext) throws ApiException {
258         String requestId = requestHandlerUtils.getRequestId(requestContext);
259         HashMap<String, String> instanceIdMap = new HashMap<>();
260         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
261         instanceIdMap.put("configurationInstanceId", configurationInstanceId);
262         return configurationRecipeLookup(request, Action.deleteInstance, instanceIdMap, version, requestId,
263                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
264     }
265
266     @POST
267     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/configurations/{configurationInstanceId}/enablePort")
268     @Consumes(MediaType.APPLICATION_JSON)
269     @Produces(MediaType.APPLICATION_JSON)
270     @Operation(description = "Enable Port Mirroring", responses = @ApiResponse(
271             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
272     @Transactional
273     public Response enablePort(String request, @PathParam("version") String version,
274             @PathParam("serviceInstanceId") String serviceInstanceId,
275             @PathParam("configurationInstanceId") String configurationInstanceId,
276             @Context ContainerRequestContext requestContext) throws ApiException {
277         String requestId = requestHandlerUtils.getRequestId(requestContext);
278         HashMap<String, String> instanceIdMap = new HashMap<>();
279         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
280         instanceIdMap.put("configurationInstanceId", configurationInstanceId);
281         return configurationRecipeLookup(request, Action.enablePort, instanceIdMap, version, requestId,
282                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
283     }
284
285     @POST
286     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/configurations/{configurationInstanceId}/disablePort")
287     @Consumes(MediaType.APPLICATION_JSON)
288     @Produces(MediaType.APPLICATION_JSON)
289     @Operation(description = "Disable Port Mirroring", responses = @ApiResponse(
290             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
291     @Transactional
292     public Response disablePort(String request, @PathParam("version") String version,
293             @PathParam("serviceInstanceId") String serviceInstanceId,
294             @PathParam("configurationInstanceId") String configurationInstanceId,
295             @Context ContainerRequestContext requestContext) throws ApiException {
296         String requestId = requestHandlerUtils.getRequestId(requestContext);
297         HashMap<String, String> instanceIdMap = new HashMap<>();
298         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
299         instanceIdMap.put("configurationInstanceId", configurationInstanceId);
300         return configurationRecipeLookup(request, Action.disablePort, instanceIdMap, version, requestId,
301                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
302     }
303
304     @POST
305     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/configurations/{configurationInstanceId}/activate")
306     @Consumes(MediaType.APPLICATION_JSON)
307     @Produces(MediaType.APPLICATION_JSON)
308     @Operation(description = "Activate Port Mirroring", responses = @ApiResponse(
309             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
310     @Transactional
311     public Response activatePort(String request, @PathParam("version") String version,
312             @PathParam("serviceInstanceId") String serviceInstanceId,
313             @PathParam("configurationInstanceId") String configurationInstanceId,
314             @Context ContainerRequestContext requestContext) throws ApiException {
315         String requestId = requestHandlerUtils.getRequestId(requestContext);
316         HashMap<String, String> instanceIdMap = new HashMap<>();
317         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
318         instanceIdMap.put("configurationInstanceId", configurationInstanceId);
319         return configurationRecipeLookup(request, Action.activateInstance, instanceIdMap, version, requestId,
320                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
321     }
322
323     @POST
324     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/configurations/{configurationInstanceId}/deactivate")
325     @Consumes(MediaType.APPLICATION_JSON)
326     @Produces(MediaType.APPLICATION_JSON)
327     @Operation(description = "Deactivate Port Mirroring", responses = @ApiResponse(
328             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
329     @Transactional
330     public Response deactivatePort(String request, @PathParam("version") String version,
331             @PathParam("serviceInstanceId") String serviceInstanceId,
332             @PathParam("configurationInstanceId") String configurationInstanceId,
333             @Context ContainerRequestContext requestContext) throws ApiException {
334         String requestId = requestHandlerUtils.getRequestId(requestContext);
335         HashMap<String, String> instanceIdMap = new HashMap<>();
336         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
337         instanceIdMap.put("configurationInstanceId", configurationInstanceId);
338         return configurationRecipeLookup(request, Action.deactivateInstance, instanceIdMap, version, requestId,
339                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
340     }
341
342     @POST
343     @Path("/{version:[vV][6-7]}/serviceInstances/{serviceInstanceId}/addRelationships")
344     @Consumes(MediaType.APPLICATION_JSON)
345     @Produces(MediaType.APPLICATION_JSON)
346     @Operation(description = "Add Relationships to a Service Instance", responses = @ApiResponse(
347             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
348     @Transactional
349     public Response addRelationships(String request, @PathParam("version") String version,
350             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
351             throws ApiException {
352         String requestId = requestHandlerUtils.getRequestId(requestContext);
353         HashMap<String, String> instanceIdMap = new HashMap<>();
354         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
355         return configurationRecipeLookup(request, Action.addRelationships, instanceIdMap, version, requestId,
356                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
357     }
358
359     @POST
360     @Path("/{version:[vV][6-7]}/serviceInstances/{serviceInstanceId}/removeRelationships")
361     @Consumes(MediaType.APPLICATION_JSON)
362     @Produces(MediaType.APPLICATION_JSON)
363     @Operation(description = "Remove Relationships from Service Instance", responses = @ApiResponse(
364             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
365     @Transactional
366     public Response removeRelationships(String request, @PathParam("version") String version,
367             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
368             throws ApiException {
369         String requestId = requestHandlerUtils.getRequestId(requestContext);
370         HashMap<String, String> instanceIdMap = new HashMap<>();
371         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
372         return configurationRecipeLookup(request, Action.removeRelationships, instanceIdMap, version, requestId,
373                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
374     }
375
376     @POST
377     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs")
378     @Consumes(MediaType.APPLICATION_JSON)
379     @Produces(MediaType.APPLICATION_JSON)
380     @Operation(description = "Create VNF on a specified version and serviceInstance", responses = @ApiResponse(
381             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
382     @Transactional
383     public Response createVnfInstance(String request, @PathParam("version") String version,
384             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
385             throws ApiException {
386         String requestId = requestHandlerUtils.getRequestId(requestContext);
387         HashMap<String, String> instanceIdMap = new HashMap<>();
388         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
389         try {
390             return serviceInstances(request, Action.createInstance, instanceIdMap, version, requestId,
391                     requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
392         } catch (Exception e) {
393             logger.error("Error in vnf", e);
394             throw e;
395         }
396     }
397
398     @POST
399     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/replace")
400     @Consumes(MediaType.APPLICATION_JSON)
401     @Produces(MediaType.APPLICATION_JSON)
402     @Operation(description = "Replace provided VNF instance", responses = @ApiResponse(
403             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
404     @Transactional
405     public Response replaceVnfInstance(String request, @PathParam("version") String version,
406             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
407             @Context ContainerRequestContext requestContext) throws ApiException {
408         String requestId = requestHandlerUtils.getRequestId(requestContext);
409         HashMap<String, String> instanceIdMap = new HashMap<>();
410         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
411         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
412         return serviceInstances(request, Action.replaceInstance, instanceIdMap, version, requestId,
413                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
414     }
415
416     @PUT
417     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}")
418     @Consumes(MediaType.APPLICATION_JSON)
419     @Produces(MediaType.APPLICATION_JSON)
420     @Operation(description = "Update VNF on a specified version, serviceInstance and vnfInstance",
421             responses = @ApiResponse(
422                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
423     @Transactional
424     public Response updateVnfInstance(String request, @PathParam("version") String version,
425             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
426             @Context ContainerRequestContext requestContext) throws ApiException {
427         String requestId = requestHandlerUtils.getRequestId(requestContext);
428         HashMap<String, String> instanceIdMap = new HashMap<>();
429         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
430         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
431         return serviceInstances(request, Action.updateInstance, instanceIdMap, version, requestId,
432                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
433     }
434
435     @POST
436     @Path("/{version:[vV][6-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/applyUpdatedConfig")
437     @Consumes(MediaType.APPLICATION_JSON)
438     @Produces(MediaType.APPLICATION_JSON)
439     @Operation(description = "Apply updated configuration", responses = @ApiResponse(
440             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
441     public Response applyUpdatedConfig(String request, @PathParam("version") String version,
442             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
443             @Context ContainerRequestContext requestContext) throws ApiException {
444         String requestId = requestHandlerUtils.getRequestId(requestContext);
445         HashMap<String, String> instanceIdMap = new HashMap<>();
446         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
447         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
448         return serviceInstances(request, Action.applyUpdatedConfig, instanceIdMap, version, requestId,
449                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
450     }
451
452     @POST
453     @Path("/{version:[vV][7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/recreate")
454     @Consumes(MediaType.APPLICATION_JSON)
455     @Produces(MediaType.APPLICATION_JSON)
456     @Operation(description = "Recreate VNF Instance", responses = @ApiResponse(
457             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
458     public Response recreateVnfInstance(String request, @PathParam("version") String version,
459             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
460             @Context ContainerRequestContext requestContext) throws ApiException {
461         String requestId = requestHandlerUtils.getRequestId(requestContext);
462         HashMap<String, String> instanceIdMap = new HashMap<>();
463         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
464         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
465         return serviceInstances(request, Action.recreateInstance, instanceIdMap, version, requestId,
466                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
467     }
468
469     @DELETE
470     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}")
471     @Consumes(MediaType.APPLICATION_JSON)
472     @Produces(MediaType.APPLICATION_JSON)
473     @Operation(description = "Delete provided VNF instance", responses = @ApiResponse(
474             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
475     @Transactional
476     public Response deleteVnfInstance(String request, @PathParam("version") String version,
477             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
478             @Context ContainerRequestContext requestContext) throws ApiException {
479         String requestId = requestHandlerUtils.getRequestId(requestContext);
480         HashMap<String, String> instanceIdMap = new HashMap<>();
481         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
482         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
483         return serviceInstances(request, Action.deleteInstance, instanceIdMap, version, requestId,
484                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
485     }
486
487     @POST
488     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/vfModules")
489     @Consumes(MediaType.APPLICATION_JSON)
490     @Produces(MediaType.APPLICATION_JSON)
491     @Operation(description = "Create VfModule on a specified version, serviceInstance and vnfInstance",
492             responses = @ApiResponse(
493                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
494     @Transactional
495     public Response createVfModuleInstance(String request, @PathParam("version") String version,
496             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
497             @Context ContainerRequestContext requestContext) throws ApiException {
498         String requestId = requestHandlerUtils.getRequestId(requestContext);
499         HashMap<String, String> instanceIdMap = new HashMap<>();
500         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
501         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
502         return serviceInstances(request, Action.createInstance, instanceIdMap, version, requestId,
503                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
504     }
505
506     @POST
507     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/vfModules/{vfmoduleInstanceId}/replace")
508     @Consumes(MediaType.APPLICATION_JSON)
509     @Produces(MediaType.APPLICATION_JSON)
510     @Operation(description = "Create VfModule on a specified version, serviceInstance and vnfInstance",
511             responses = @ApiResponse(
512                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
513     @Transactional
514     public Response replaceVfModuleInstance(String request, @PathParam("version") String version,
515             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
516             @PathParam("vfmoduleInstanceId") String vfmoduleInstanceId, @Context ContainerRequestContext requestContext)
517             throws ApiException {
518         String requestId = requestHandlerUtils.getRequestId(requestContext);
519         HashMap<String, String> instanceIdMap = new HashMap<>();
520         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
521         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
522         instanceIdMap.put("vfModuleInstanceId", vfmoduleInstanceId);
523         return serviceInstances(request, Action.replaceInstance, instanceIdMap, version, requestId,
524                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
525     }
526
527     @PUT
528     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/vfModules/{vfmoduleInstanceId}")
529     @Consumes(MediaType.APPLICATION_JSON)
530     @Produces(MediaType.APPLICATION_JSON)
531     @Operation(description = "Update VfModule on a specified version, serviceInstance, vnfInstance and vfModule",
532             responses = @ApiResponse(
533                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
534     @Transactional
535     public Response updateVfModuleInstance(String request, @PathParam("version") String version,
536             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
537             @PathParam("vfmoduleInstanceId") String vfmoduleInstanceId, @Context ContainerRequestContext requestContext)
538             throws ApiException {
539         String requestId = requestHandlerUtils.getRequestId(requestContext);
540         HashMap<String, String> instanceIdMap = new HashMap<>();
541         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
542         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
543         instanceIdMap.put("vfModuleInstanceId", vfmoduleInstanceId);
544         return serviceInstances(request, Action.updateInstance, instanceIdMap, version, requestId,
545                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
546     }
547
548     @POST
549     @Path("/{version:[vV][6-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/inPlaceSoftwareUpdate")
550     @Consumes(MediaType.APPLICATION_JSON)
551     @Produces(MediaType.APPLICATION_JSON)
552     @Operation(description = "Perform VNF software update", responses = @ApiResponse(
553             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
554     @Transactional
555     public Response inPlaceSoftwareUpdate(String request, @PathParam("version") String version,
556             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
557             @Context ContainerRequestContext requestContext) throws ApiException {
558         String requestId = requestHandlerUtils.getRequestId(requestContext);
559         HashMap<String, String> instanceIdMap = new HashMap<>();
560         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
561         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
562         return serviceInstances(request, Action.inPlaceSoftwareUpdate, instanceIdMap, version, requestId,
563                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
564     }
565
566     @DELETE
567     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/vfModules/{vfmoduleInstanceId}")
568     @Consumes(MediaType.APPLICATION_JSON)
569     @Produces(MediaType.APPLICATION_JSON)
570     @Operation(description = "Delete provided VfModule instance", responses = @ApiResponse(
571             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
572     @Transactional
573     public Response deleteVfModuleInstance(String request, @PathParam("version") String version,
574             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
575             @PathParam("vfmoduleInstanceId") String vfmoduleInstanceId, @Context ContainerRequestContext requestContext)
576             throws ApiException {
577         String requestId = requestHandlerUtils.getRequestId(requestContext);
578         HashMap<String, String> instanceIdMap = new HashMap<>();
579         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
580         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
581         instanceIdMap.put("vfModuleInstanceId", vfmoduleInstanceId);
582         return serviceInstances(request, Action.deleteInstance, instanceIdMap, version, requestId,
583                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
584     }
585
586     @POST
587     @Path("/{version:[vV][7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/vfModules/{vfmoduleInstanceId}/deactivateAndCloudDelete")
588     @Consumes(MediaType.APPLICATION_JSON)
589     @Produces(MediaType.APPLICATION_JSON)
590     @Operation(description = "Deactivate and Cloud Delete VfModule instance", responses = @ApiResponse(
591             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
592     @Transactional
593     public Response deactivateAndCloudDeleteVfModuleInstance(String request, @PathParam("version") String version,
594             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
595             @PathParam("vfmoduleInstanceId") String vfmoduleInstanceId, @Context ContainerRequestContext requestContext)
596             throws ApiException {
597         String requestId = requestHandlerUtils.getRequestId(requestContext);
598         HashMap<String, String> instanceIdMap = new HashMap<>();
599         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
600         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
601         instanceIdMap.put("vfModuleInstanceId", vfmoduleInstanceId);
602         Response response = serviceInstances(request, Action.deactivateAndCloudDelete, instanceIdMap, version,
603                 requestId, requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
604         return response;
605     }
606
607     @POST
608     @Path("/{version:[vV][7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/vfModules/scaleOut")
609     @Consumes(MediaType.APPLICATION_JSON)
610     @Produces(MediaType.APPLICATION_JSON)
611     @Operation(description = "VF Auto Scale Out", responses = @ApiResponse(
612             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
613     @Transactional
614     public Response scaleOutVfModule(String request, @PathParam("version") String version,
615             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
616             @Context ContainerRequestContext requestContext) throws ApiException {
617         String requestId = requestHandlerUtils.getRequestId(requestContext);
618         HashMap<String, String> instanceIdMap = new HashMap<>();
619         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
620         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
621         return serviceInstances(request, Action.scaleOut, instanceIdMap, version, requestId,
622                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
623     }
624
625     @POST
626     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/volumeGroups")
627     @Consumes(MediaType.APPLICATION_JSON)
628     @Produces(MediaType.APPLICATION_JSON)
629     @Operation(description = "Create VolumeGroup on a specified version, serviceInstance, vnfInstance",
630             responses = @ApiResponse(
631                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
632     @Transactional
633     public Response createVolumeGroupInstance(String request, @PathParam("version") String version,
634             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
635             @Context ContainerRequestContext requestContext) throws ApiException {
636         String requestId = requestHandlerUtils.getRequestId(requestContext);
637         HashMap<String, String> instanceIdMap = new HashMap<>();
638         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
639         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
640         return serviceInstances(request, Action.createInstance, instanceIdMap, version, requestId,
641                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
642     }
643
644     @PUT
645     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/volumeGroups/{volumeGroupInstanceId}")
646     @Consumes(MediaType.APPLICATION_JSON)
647     @Produces(MediaType.APPLICATION_JSON)
648     @Operation(description = "Update VolumeGroup on a specified version, serviceInstance, vnfInstance and volumeGroup",
649             responses = @ApiResponse(
650                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
651     @Transactional
652     public Response updateVolumeGroupInstance(String request, @PathParam("version") String version,
653             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
654             @PathParam("volumeGroupInstanceId") String volumeGroupInstanceId,
655             @Context ContainerRequestContext requestContext) throws ApiException {
656         String requestId = requestHandlerUtils.getRequestId(requestContext);
657         HashMap<String, String> instanceIdMap = new HashMap<>();
658         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
659         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
660         instanceIdMap.put("volumeGroupInstanceId", volumeGroupInstanceId);
661         return serviceInstances(request, Action.updateInstance, instanceIdMap, version, requestId,
662                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
663     }
664
665     @DELETE
666     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/vnfs/{vnfInstanceId}/volumeGroups/{volumeGroupInstanceId}")
667     @Consumes(MediaType.APPLICATION_JSON)
668     @Produces(MediaType.APPLICATION_JSON)
669     @Operation(description = "Delete provided VolumeGroup instance", responses = @ApiResponse(
670             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
671     @Transactional
672     public Response deleteVolumeGroupInstance(String request, @PathParam("version") String version,
673             @PathParam("serviceInstanceId") String serviceInstanceId, @PathParam("vnfInstanceId") String vnfInstanceId,
674             @PathParam("volumeGroupInstanceId") String volumeGroupInstanceId,
675             @Context ContainerRequestContext requestContext) throws ApiException {
676         String requestId = requestHandlerUtils.getRequestId(requestContext);
677         HashMap<String, String> instanceIdMap = new HashMap<>();
678         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
679         instanceIdMap.put("vnfInstanceId", vnfInstanceId);
680         instanceIdMap.put("volumeGroupInstanceId", volumeGroupInstanceId);
681         return serviceInstances(request, Action.deleteInstance, instanceIdMap, version, requestId,
682                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
683     }
684
685     @POST
686     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/networks")
687     @Consumes(MediaType.APPLICATION_JSON)
688     @Produces(MediaType.APPLICATION_JSON)
689     @Operation(description = "Create NetworkInstance on a specified version and serviceInstance ",
690             responses = @ApiResponse(
691                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
692     @Transactional
693     public Response createNetworkInstance(String request, @PathParam("version") String version,
694             @PathParam("serviceInstanceId") String serviceInstanceId, @Context ContainerRequestContext requestContext)
695             throws ApiException {
696         String requestId = requestHandlerUtils.getRequestId(requestContext);
697         HashMap<String, String> instanceIdMap = new HashMap<>();
698         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
699         return serviceInstances(request, Action.createInstance, instanceIdMap, version, requestId,
700                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
701     }
702
703     @PUT
704     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/networks/{networkInstanceId}")
705     @Consumes(MediaType.APPLICATION_JSON)
706     @Produces(MediaType.APPLICATION_JSON)
707     @Operation(description = "Update VolumeGroup on a specified version, serviceInstance, networkInstance",
708             responses = @ApiResponse(
709                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
710     @Transactional
711     public Response updateNetworkInstance(String request, @PathParam("version") String version,
712             @PathParam("serviceInstanceId") String serviceInstanceId,
713             @PathParam("networkInstanceId") String networkInstanceId, @Context ContainerRequestContext requestContext)
714             throws ApiException {
715         String requestId = requestHandlerUtils.getRequestId(requestContext);
716         HashMap<String, String> instanceIdMap = new HashMap<>();
717         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
718         instanceIdMap.put("networkInstanceId", networkInstanceId);
719         return serviceInstances(request, Action.updateInstance, instanceIdMap, version, requestId,
720                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
721     }
722
723     @DELETE
724     @Path("/{version:[vV][5-7]}/serviceInstances/{serviceInstanceId}/networks/{networkInstanceId}")
725     @Consumes(MediaType.APPLICATION_JSON)
726     @Produces(MediaType.APPLICATION_JSON)
727     @Operation(description = "Delete provided Network instance", responses = @ApiResponse(
728             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
729     @Transactional
730     public Response deleteNetworkInstance(String request, @PathParam("version") String version,
731             @PathParam("serviceInstanceId") String serviceInstanceId,
732             @PathParam("networkInstanceId") String networkInstanceId, @Context ContainerRequestContext requestContext)
733             throws ApiException {
734         String requestId = requestHandlerUtils.getRequestId(requestContext);
735         HashMap<String, String> instanceIdMap = new HashMap<>();
736         instanceIdMap.put("serviceInstanceId", serviceInstanceId);
737         instanceIdMap.put("networkInstanceId", networkInstanceId);
738         return serviceInstances(request, Action.deleteInstance, instanceIdMap, version, requestId,
739                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
740     }
741
742     @POST
743     @Path("/{version:[vV][7]}/instanceGroups")
744     @Consumes(MediaType.APPLICATION_JSON)
745     @Produces(MediaType.APPLICATION_JSON)
746     @Operation(description = "Create instanceGroups", responses = @ApiResponse(
747             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
748     @Transactional
749     public Response createInstanceGroups(String request, @PathParam("version") String version,
750             @Context ContainerRequestContext requestContext) throws ApiException {
751         String requestId = requestHandlerUtils.getRequestId(requestContext);
752         return serviceInstances(request, Action.createInstance, null, version, requestId,
753                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
754     }
755
756     @DELETE
757     @Path("/{version:[vV][7]}/instanceGroups/{instanceGroupId}")
758     @Consumes(MediaType.APPLICATION_JSON)
759     @Produces(MediaType.APPLICATION_JSON)
760     @Operation(description = "Delete instanceGroup", responses = @ApiResponse(
761             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
762     @Transactional
763     public Response deleteInstanceGroups(@PathParam("version") String version,
764             @PathParam("instanceGroupId") String instanceGroupId, @Context ContainerRequestContext requestContext)
765             throws ApiException {
766         String requestId = requestHandlerUtils.getRequestId(requestContext);
767         HashMap<String, String> instanceIdMap = new HashMap<>();
768         instanceIdMap.put(CommonConstants.INSTANCE_GROUP_INSTANCE_ID, instanceGroupId);
769         return deleteInstanceGroups(Action.deleteInstance, instanceIdMap, version, requestId,
770                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix), requestContext);
771     }
772
773     @POST
774     @Path("/{version:[vV][7]}/instanceGroups/{instanceGroupId}/addMembers")
775     @Consumes(MediaType.APPLICATION_JSON)
776     @Produces(MediaType.APPLICATION_JSON)
777     @Operation(description = "Add instanceGroup members", responses = @ApiResponse(
778             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
779     @Transactional
780     public Response addInstanceGroupMembers(String request, @PathParam("version") String version,
781             @PathParam("instanceGroupId") String instanceGroupId, @Context ContainerRequestContext requestContext)
782             throws ApiException {
783         String requestId = requestHandlerUtils.getRequestId(requestContext);
784         HashMap<String, String> instanceIdMap = new HashMap<>();
785         instanceIdMap.put(CommonConstants.INSTANCE_GROUP_INSTANCE_ID, instanceGroupId);
786         return serviceInstances(request, Action.addMembers, instanceIdMap, version, requestId,
787                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
788     }
789
790     @POST
791     @Path("/{version:[vV][7]}/instanceGroups/{instanceGroupId}/removeMembers")
792     @Consumes(MediaType.APPLICATION_JSON)
793     @Produces(MediaType.APPLICATION_JSON)
794     @Operation(description = "Remove instanceGroup members", responses = @ApiResponse(
795             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
796     @Transactional
797     public Response removeInstanceGroupMembers(String request, @PathParam("version") String version,
798             @PathParam("instanceGroupId") String instanceGroupId, @Context ContainerRequestContext requestContext)
799             throws ApiException {
800         String requestId = requestHandlerUtils.getRequestId(requestContext);
801         HashMap<String, String> instanceIdMap = new HashMap<>();
802         instanceIdMap.put(CommonConstants.INSTANCE_GROUP_INSTANCE_ID, instanceGroupId);
803         return serviceInstances(request, Action.removeMembers, instanceIdMap, version, requestId,
804                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
805     }
806
807     /**
808      * This method is used for POST a request to the BPEL client (BPMN).
809      *
810      * Convert the requestJson to ServiceInstanceRequest(sir), create the msoRequest object, check whether this request
811      * is already being processed in requestdb for duplicate check.
812      *
813      * Based on the alacarte flag, sir and msoRequest will do the recipe lookup from the service and servicerecipe table
814      * of catalogdb, and get the OrchestrationURI.
815      *
816      * If the present request is not the duplicate request then this request will be saved in the requestdb. and will
817      * POST a request to the BPMN engine at the OrchestrationURI fetched.
818      *
819      * @param requestJSON Json fetched as body in the API call
820      * @param action Type of action to be performed
821      * @param instanceIdMap Map of instance ids of service/vnf/vf/configuration etc..
822      * @param version Supported version of API
823      * @param requestId Unique id for the request
824      * @param requestUri
825      * @return response object
826      * @throws ApiException
827      */
828     public Response serviceInstances(String requestJSON, Actions action, HashMap<String, String> instanceIdMap,
829             String version, String requestId, String requestUri) throws ApiException {
830         return serviceInstances(requestJSON, action, instanceIdMap, version, requestId, requestUri, null);
831
832     }
833
834     public Response serviceInstances(String requestJSON, Actions action, HashMap<String, String> instanceIdMap,
835             String version, String requestId, String requestUri, HashMap<String, String> queryParams)
836             throws ApiException {
837         String serviceInstanceId;
838         Boolean aLaCarte = null;
839         ServiceInstancesRequest sir;
840         String apiVersion = version.substring(1);
841
842         sir = requestHandlerUtils.convertJsonToServiceInstanceRequest(requestJSON, action, requestId, requestUri);
843         action = handleReplaceInstance(action, sir);
844         requestValidatorListenerRunner.runValidations(requestUri, instanceIdMap, sir, queryParams);
845
846         String requestScope = requestHandlerUtils.deriveRequestScope(action, sir, requestUri);
847         InfraActiveRequests currentActiveReq =
848                 msoRequest.createRequestObject(sir, action, requestId, Status.IN_PROGRESS, requestJSON, requestScope);
849         if (sir.getRequestDetails().getRequestParameters() != null) {
850             aLaCarte = sir.getRequestDetails().getRequestParameters().getALaCarte();
851         }
852         requestHandlerUtils.parseRequest(sir, instanceIdMap, action, version, requestJSON, aLaCarte, requestId,
853                 currentActiveReq);
854         requestHandlerUtils.setInstanceId(currentActiveReq, requestScope, null, instanceIdMap);
855
856         int requestVersion = Integer.parseInt(version.substring(1));
857         String instanceName = null;
858         if (sir.getRequestDetails().getRequestInfo() != null) {
859             instanceName = sir.getRequestDetails().getRequestInfo().getInstanceName();
860         }
861         boolean alaCarteFlag = msoRequest.getAlacarteFlag(sir);
862         String vnfType = msoRequest.getVnfType(sir, requestScope, action, requestVersion);
863         String networkType = msoRequest.getNetworkType(sir, requestScope);
864         String sdcServiceModelVersion = msoRequest.getSDCServiceModelVersion(sir);
865         String vfModuleType = msoRequest.getVfModuleType(sir, requestScope, action, requestVersion);
866
867         if (requestScope.equalsIgnoreCase(ModelType.vnf.name()) && vnfType != null) {
868             currentActiveReq.setVnfType(vnfType);
869         } else if (requestScope.equalsIgnoreCase(ModelType.network.name()) && networkType != null) {
870             currentActiveReq.setNetworkType(networkType);
871         }
872
873         InfraActiveRequests dup = null;
874         boolean inProgress = false;
875
876         dup = requestHandlerUtils.duplicateCheck(action, instanceIdMap, instanceName, requestScope, currentActiveReq);
877
878         if (dup != null) {
879             inProgress = requestHandlerUtils.camundaHistoryCheck(dup, currentActiveReq);
880         }
881
882         if (dup != null && inProgress) {
883             requestHandlerUtils.buildErrorOnDuplicateRecord(currentActiveReq, action, instanceIdMap, instanceName,
884                     requestScope, dup);
885         }
886         ServiceInstancesResponse serviceResponse = new ServiceInstancesResponse();
887
888         RequestReferences referencesResponse = new RequestReferences();
889
890         referencesResponse.setRequestId(requestId);
891
892         serviceResponse.setRequestReferences(referencesResponse);
893         RecipeLookupResult recipeLookupResult =
894                 getServiceInstanceOrchestrationURI(sir, action, alaCarteFlag, currentActiveReq);
895         String serviceInstanceType = requestHandlerUtils.getServiceType(requestScope, sir, alaCarteFlag);
896
897         ModelInfo modelInfo = sir.getRequestDetails().getModelInfo();
898         ModelType modelType = requestHandlerUtils.getModelType(action, modelInfo);
899
900         Boolean isBaseVfModule = false;
901
902         if (modelType.equals(ModelType.vfModule)) {
903             isBaseVfModule = requestHandlerUtils.getIsBaseVfModule(modelInfo, action, vnfType, sdcServiceModelVersion,
904                     currentActiveReq);
905         }
906
907         serviceInstanceId = requestHandlerUtils.setServiceInstanceId(requestScope, sir);
908         String vnfId = "";
909         String vfModuleId = "";
910         String volumeGroupId = "";
911         String networkId = "";
912         String pnfCorrelationId = "";
913         String instanceGroupId = null;
914
915         if (sir.getVnfInstanceId() != null) {
916             vnfId = sir.getVnfInstanceId();
917         }
918
919         if (sir.getVfModuleInstanceId() != null) {
920             vfModuleId = sir.getVfModuleInstanceId();
921         }
922
923         if (sir.getVolumeGroupInstanceId() != null) {
924             volumeGroupId = sir.getVolumeGroupInstanceId();
925         }
926
927         if (sir.getNetworkInstanceId() != null) {
928             networkId = sir.getNetworkInstanceId();
929         }
930         if (sir.getInstanceGroupId() != null) {
931             instanceGroupId = sir.getInstanceGroupId();
932         }
933
934         pnfCorrelationId = getPnfCorrelationId(sir);
935
936         try {
937             infraActiveRequestsClient.save(currentActiveReq);
938         } catch (Exception e) {
939             logger.error("Exception occurred", e);
940             ErrorLoggerInfo errorLoggerInfo =
941                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
942                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
943             throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR,
944                     ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e).errorInfo(errorLoggerInfo).build();
945         }
946
947         if (!requestScope.equalsIgnoreCase(ModelType.service.name()) && action != Action.recreateInstance) {
948             aLaCarte = true;
949         } else if (aLaCarte == null) {
950             aLaCarte = false;
951         }
952
953
954         RequestClientParameter requestClientParameter = null;
955         try {
956             requestClientParameter = new RequestClientParameter.Builder().setRequestId(requestId)
957                     .setBaseVfModule(isBaseVfModule).setRecipeTimeout(recipeLookupResult.getRecipeTimeout())
958                     .setRequestAction(action.toString()).setServiceInstanceId(serviceInstanceId)
959                     .setPnfCorrelationId(pnfCorrelationId).setVnfId(vnfId).setVfModuleId(vfModuleId)
960                     .setVolumeGroupId(volumeGroupId).setNetworkId(networkId).setServiceType(serviceInstanceType)
961                     .setVnfType(vnfType).setVfModuleType(vfModuleType).setNetworkType(networkType)
962                     .setRequestDetails(requestHandlerUtils.mapJSONtoMSOStyle(requestJSON, sir, aLaCarte, action))
963                     .setApiVersion(apiVersion).setALaCarte(aLaCarte).setRequestUri(requestUri)
964                     .setInstanceGroupId(instanceGroupId).build();
965         } catch (IOException e) {
966             logger.error("Exception occurred", e);
967             ErrorLoggerInfo errorLoggerInfo =
968                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
969                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
970             throw new ValidateException.Builder("Unable to generate RequestClientParamter object" + e.getMessage(),
971                     HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).errorInfo(errorLoggerInfo)
972                             .build();
973         }
974         return requestHandlerUtils.postBPELRequest(currentActiveReq, requestClientParameter,
975                 recipeLookupResult.getOrchestrationURI(), requestScope);
976     }
977
978     /**
979      * @param action
980      * @param sir
981      * @return
982      */
983     protected Actions handleReplaceInstance(Actions action, ServiceInstancesRequest sir) {
984         if (action != null && action.equals(Action.replaceInstance)
985                 && sir.getRequestDetails().getRequestParameters().getRetainAssignments() != null
986                 && sir.getRequestDetails().getRequestParameters().getRetainAssignments()) {
987             action = Action.replaceInstanceRetainAssignments;
988         }
989         return action;
990     }
991
992     /**
993      * This method deletes the Instance Groups.
994      *
995      * This method will check whether the request is not duplicate in requestdb. if its not then will save as a new
996      * request. And will send a POST request to BEPL client to delete the Insatnce Groups.
997      *
998      * @param action
999      * @param instanceIdMap
1000      * @param version
1001      * @param requestId
1002      * @param requestUri
1003      * @param requestContext
1004      * @return
1005      * @throws ApiException
1006      */
1007     public Response deleteInstanceGroups(Actions action, HashMap<String, String> instanceIdMap, String version,
1008             String requestId, String requestUri, ContainerRequestContext requestContext) throws ApiException {
1009         String instanceGroupId = instanceIdMap.get(CommonConstants.INSTANCE_GROUP_INSTANCE_ID);
1010         Boolean aLaCarte = true;
1011         String apiVersion = version.substring(1);
1012         ServiceInstancesRequest sir = new ServiceInstancesRequest();
1013         sir.setInstanceGroupId(instanceGroupId);
1014
1015         String requestScope = ModelType.instanceGroup.toString();
1016         InfraActiveRequests currentActiveReq =
1017                 msoRequest.createRequestObject(sir, action, requestId, Status.IN_PROGRESS, null, requestScope);
1018         requestHandlerUtils.setInstanceId(currentActiveReq, requestScope, null, instanceIdMap);
1019         try {
1020             requestHandlerUtils.validateHeaders(requestContext);
1021         } catch (ValidationException e) {
1022             logger.error("Exception occurred", e);
1023             ErrorLoggerInfo errorLoggerInfo =
1024                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_VALIDATION_ERROR, ErrorCode.SchemaError)
1025                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1026             ValidateException validateException =
1027                     new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
1028                             ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
1029             requestHandlerUtils.updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
1030             throw validateException;
1031         }
1032
1033         InfraActiveRequests dup =
1034                 requestHandlerUtils.duplicateCheck(action, instanceIdMap, null, requestScope, currentActiveReq);
1035         boolean inProgress = false;
1036
1037         if (dup != null) {
1038             inProgress = requestHandlerUtils.camundaHistoryCheck(dup, currentActiveReq);
1039         }
1040
1041         if (dup != null && inProgress) {
1042             requestHandlerUtils.buildErrorOnDuplicateRecord(currentActiveReq, action, instanceIdMap, null, requestScope,
1043                     dup);
1044         }
1045
1046         ServiceInstancesResponse serviceResponse = new ServiceInstancesResponse();
1047
1048         RequestReferences referencesResponse = new RequestReferences();
1049
1050         referencesResponse.setRequestId(requestId);
1051
1052         serviceResponse.setRequestReferences(referencesResponse);
1053         Boolean isBaseVfModule = false;
1054
1055         RecipeLookupResult recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
1056
1057         try {
1058             infraActiveRequestsClient.save(currentActiveReq);
1059         } catch (Exception e) {
1060             logger.error("Exception occurred", e);
1061             ErrorLoggerInfo errorLoggerInfo =
1062                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
1063                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1064             throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR,
1065                     ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e).errorInfo(errorLoggerInfo).build();
1066         }
1067
1068         RequestClientParameter requestClientParameter = new RequestClientParameter.Builder().setRequestId(requestId)
1069                 .setBaseVfModule(isBaseVfModule).setRecipeTimeout(recipeLookupResult.getRecipeTimeout())
1070                 .setRequestAction(action.toString()).setApiVersion(apiVersion).setALaCarte(aLaCarte)
1071                 .setRequestUri(requestUri).setInstanceGroupId(instanceGroupId).build();
1072
1073
1074         return requestHandlerUtils.postBPELRequest(currentActiveReq, requestClientParameter,
1075                 recipeLookupResult.getOrchestrationURI(), requestScope);
1076     }
1077
1078     protected String getPnfCorrelationId(ServiceInstancesRequest sir) {
1079         return Optional.of(sir).map(ServiceInstancesRequest::getRequestDetails)
1080                 .map(RequestDetails::getRequestParameters).map(parameters -> parameters.getUserParamValue("pnfId"))
1081                 .orElse("");
1082     }
1083
1084     protected RecipeLookupResult getServiceInstanceOrchestrationURI(ServiceInstancesRequest sir, Actions action,
1085             boolean alaCarteFlag, InfraActiveRequests currentActiveReq) throws ApiException {
1086         RecipeLookupResult recipeLookupResult = null;
1087         // if the aLaCarte flag is set to TRUE, the API-H should choose the VID_DEFAULT
1088         // recipe for the requested action
1089         ModelInfo modelInfo = sir.getRequestDetails().getModelInfo();
1090         // Query MSO Catalog DB
1091
1092         if (action == Action.applyUpdatedConfig || action == Action.inPlaceSoftwareUpdate) {
1093             recipeLookupResult = getDefaultVnfUri(sir, action);
1094         } else if (action == Action.addMembers || action == Action.removeMembers) {
1095             recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
1096         } else if (modelInfo.getModelType().equals(ModelType.service)) {
1097             try {
1098                 recipeLookupResult = getServiceURI(sir, action, alaCarteFlag);
1099             } catch (IOException e) {
1100                 ErrorLoggerInfo errorLoggerInfo =
1101                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
1102                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1103
1104                 ValidateException validateException =
1105                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
1106                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
1107
1108                 requestHandlerUtils.updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
1109
1110                 throw validateException;
1111             }
1112         } else if (modelInfo.getModelType().equals(ModelType.vfModule)
1113                 || modelInfo.getModelType().equals(ModelType.volumeGroup)
1114                 || modelInfo.getModelType().equals(ModelType.vnf)) {
1115             try {
1116                 recipeLookupResult = getVnfOrVfModuleUri(sir, action);
1117             } catch (ValidationException e) {
1118                 ErrorLoggerInfo errorLoggerInfo =
1119                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
1120                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1121
1122                 ValidateException validateException =
1123                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
1124                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
1125
1126                 requestHandlerUtils.updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
1127
1128                 throw validateException;
1129             }
1130         } else if (modelInfo.getModelType().equals(ModelType.network)) {
1131             try {
1132                 recipeLookupResult = getNetworkUri(sir, action);
1133             } catch (ValidationException e) {
1134
1135                 ErrorLoggerInfo errorLoggerInfo =
1136                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
1137                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1138
1139                 ValidateException validateException =
1140                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
1141                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
1142                 requestHandlerUtils.updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
1143
1144                 throw validateException;
1145             }
1146         } else if (modelInfo.getModelType().equals(ModelType.instanceGroup)) {
1147             recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
1148         }
1149
1150         if (recipeLookupResult == null) {
1151             ErrorLoggerInfo errorLoggerInfo =
1152                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
1153                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1154
1155             RecipeNotFoundException recipeNotFoundExceptionException =
1156                     new RecipeNotFoundException.Builder("Recipe could not be retrieved from catalog DB.",
1157                             HttpStatus.SC_NOT_FOUND, ErrorNumbers.SVC_GENERAL_SERVICE_ERROR).errorInfo(errorLoggerInfo)
1158                                     .build();
1159
1160             requestHandlerUtils.updateStatus(currentActiveReq, Status.FAILED,
1161                     recipeNotFoundExceptionException.getMessage());
1162             throw recipeNotFoundExceptionException;
1163         }
1164         return recipeLookupResult;
1165     }
1166
1167     protected RecipeLookupResult getServiceURI(ServiceInstancesRequest servInstReq, Actions action,
1168             boolean alaCarteFlag) throws IOException {
1169         // SERVICE REQUEST
1170         // Construct the default service name
1171         // TODO need to make this a configurable property
1172         String defaultServiceModelName = requestHandlerUtils.getDefaultModel(servInstReq);
1173         RequestDetails requestDetails = servInstReq.getRequestDetails();
1174         ModelInfo modelInfo = requestDetails.getModelInfo();
1175         org.onap.so.db.catalog.beans.Service serviceRecord;
1176         List<org.onap.so.db.catalog.beans.Service> serviceRecordList;
1177         ServiceRecipe recipe = null;
1178
1179         if (alaCarteFlag) {
1180             serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
1181             if (serviceRecord != null) {
1182                 recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(serviceRecord.getModelUUID(),
1183                         action.toString());
1184             }
1185         } else {
1186             serviceRecord = catalogDbClient.getServiceByID(modelInfo.getModelVersionId());
1187             recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(modelInfo.getModelVersionId(),
1188                     action.toString());
1189             if (recipe == null) {
1190                 serviceRecordList = catalogDbClient
1191                         .getServiceByModelInvariantUUIDOrderByModelVersionDesc(modelInfo.getModelInvariantId());
1192                 if (!serviceRecordList.isEmpty()) {
1193                     for (org.onap.so.db.catalog.beans.Service record : serviceRecordList) {
1194                         recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(record.getModelUUID(),
1195                                 action.toString());
1196                         if (recipe != null) {
1197                             break;
1198                         }
1199                     }
1200                 }
1201             }
1202         }
1203
1204         // if an aLaCarte flag was sent in the request, throw an error if the recipe was
1205         // not found
1206         RequestParameters reqParam = requestDetails.getRequestParameters();
1207         if (reqParam != null && alaCarteFlag && recipe == null) {
1208             return null;
1209         } else if (!alaCarteFlag && recipe != null && Action.createInstance.equals(action)) {
1210             mapToLegacyRequest(requestDetails);
1211         } else if (recipe == null) { // aLaCarte wasn't sent, so we'll try the default
1212             serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
1213             recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(serviceRecord.getModelUUID(),
1214                     action.toString());
1215         }
1216         if (modelInfo.getModelVersionId() == null) {
1217             modelInfo.setModelVersionId(serviceRecord.getModelUUID());
1218         }
1219         if (recipe == null) {
1220             return null;
1221         }
1222         return new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout());
1223     }
1224
1225     protected void mapToLegacyRequest(RequestDetails requestDetails) throws IOException {
1226         RequestParameters reqParam;
1227         if (requestDetails.getRequestParameters() == null) {
1228             reqParam = new RequestParameters();
1229         } else {
1230             reqParam = requestDetails.getRequestParameters();
1231         }
1232         if (requestDetails.getCloudConfiguration() == null) {
1233             CloudConfiguration cloudConfig = configureCloudConfig(reqParam);
1234             if (cloudConfig != null) {
1235                 requestDetails.setCloudConfiguration(cloudConfig);
1236             }
1237         }
1238
1239         List<Map<String, Object>> userParams = configureUserParams(reqParam);
1240         if (!userParams.isEmpty()) {
1241             if (reqParam == null) {
1242                 requestDetails.setRequestParameters(new RequestParameters());
1243             }
1244             requestDetails.getRequestParameters().setUserParams(userParams);
1245         }
1246     }
1247
1248     protected CloudConfiguration configureCloudConfig(RequestParameters reqParams) throws IOException {
1249
1250         for (Map<String, Object> params : reqParams.getUserParams()) {
1251             if (params.containsKey("service")) {
1252                 Service service = serviceMapper(params);
1253
1254                 Optional<CloudConfiguration> targetConfiguration = addCloudConfig(service.getCloudConfiguration());
1255
1256                 if (targetConfiguration.isPresent()) {
1257                     return targetConfiguration.get();
1258                 } else {
1259                     for (Networks network : service.getResources().getNetworks()) {
1260                         targetConfiguration = addCloudConfig(network.getCloudConfiguration());
1261                         if (targetConfiguration.isPresent()) {
1262                             return targetConfiguration.get();
1263                         }
1264                     }
1265
1266                     for (Vnfs vnf : service.getResources().getVnfs()) {
1267                         targetConfiguration = addCloudConfig(vnf.getCloudConfiguration());
1268
1269                         if (targetConfiguration.isPresent()) {
1270                             return targetConfiguration.get();
1271                         }
1272
1273                         for (VfModules vfModule : vnf.getVfModules()) {
1274                             targetConfiguration = addCloudConfig(vfModule.getCloudConfiguration());
1275
1276                             if (targetConfiguration.isPresent()) {
1277                                 return targetConfiguration.get();
1278                             }
1279                         }
1280                     }
1281                 }
1282             }
1283         }
1284
1285         return null;
1286     }
1287
1288     private Optional<CloudConfiguration> addCloudConfig(CloudConfiguration sourceCloudConfiguration) {
1289         CloudConfiguration targetConfiguration = new CloudConfiguration();
1290         if (sourceCloudConfiguration != null) {
1291             targetConfiguration.setAicNodeClli(sourceCloudConfiguration.getAicNodeClli());
1292             targetConfiguration.setTenantId(sourceCloudConfiguration.getTenantId());
1293             targetConfiguration.setLcpCloudRegionId(sourceCloudConfiguration.getLcpCloudRegionId());
1294             targetConfiguration.setCloudOwner(sourceCloudConfiguration.getCloudOwner());
1295             return Optional.of(targetConfiguration);
1296         }
1297         return Optional.empty();
1298     }
1299
1300     protected List<Map<String, Object>> configureUserParams(RequestParameters reqParams) throws IOException {
1301         logger.debug("Configuring UserParams for Macro Request");
1302         Map<String, Object> userParams = new HashMap<>();
1303
1304         for (Map<String, Object> params : reqParams.getUserParams()) {
1305             if (params.containsKey("service")) {
1306                 Service service = serviceMapper(params);
1307
1308                 addUserParams(userParams, service.getInstanceParams());
1309
1310                 for (Networks network : service.getResources().getNetworks()) {
1311                     addUserParams(userParams, network.getInstanceParams());
1312                 }
1313
1314                 for (Vnfs vnf : service.getResources().getVnfs()) {
1315                     addUserParams(userParams, vnf.getInstanceParams());
1316
1317                     for (VfModules vfModule : vnf.getVfModules()) {
1318                         addUserParams(userParams, vfModule.getInstanceParams());
1319                     }
1320                 }
1321             }
1322         }
1323
1324         return mapFlatMapToNameValue(userParams);
1325     }
1326
1327     private Service serviceMapper(Map<String, Object> params) throws IOException {
1328         ObjectMapper obj = new ObjectMapper();
1329         String input = obj.writeValueAsString(params.get("service"));
1330         return obj.readValue(input, Service.class);
1331     }
1332
1333     private void addUserParams(Map<String, Object> targetUserParams, List<Map<String, String>> sourceUserParams) {
1334         for (Map<String, String> map : sourceUserParams) {
1335             for (Map.Entry<String, String> entry : map.entrySet()) {
1336                 targetUserParams.put(entry.getKey(), entry.getValue());
1337             }
1338         }
1339     }
1340
1341     protected List<Map<String, Object>> mapFlatMapToNameValue(Map<String, Object> flatMap) {
1342         List<Map<String, Object>> targetUserParams = new ArrayList<>();
1343
1344         for (Map.Entry<String, Object> map : flatMap.entrySet()) {
1345             Map<String, Object> targetMap = new HashMap<>();
1346             targetMap.put(NAME, map.getKey());
1347             targetMap.put(VALUE, map.getValue());
1348             targetUserParams.add(targetMap);
1349         }
1350         return targetUserParams;
1351     }
1352
1353     private RecipeLookupResult getVnfOrVfModuleUri(ServiceInstancesRequest servInstReq, Actions action)
1354             throws ValidationException {
1355
1356         ModelInfo modelInfo = servInstReq.getRequestDetails().getModelInfo();
1357         String vnfComponentType = modelInfo.getModelType().name();
1358
1359         RelatedInstanceList[] instanceList = null;
1360         if (servInstReq.getRequestDetails() != null) {
1361             instanceList = servInstReq.getRequestDetails().getRelatedInstanceList();
1362         }
1363
1364         Recipe recipe;
1365         String defaultSource = requestHandlerUtils.getDefaultModel(servInstReq);
1366         String modelCustomizationId = modelInfo.getModelCustomizationId();
1367         String modelCustomizationName = modelInfo.getModelCustomizationName();
1368         String relatedInstanceModelVersionId = null;
1369         String relatedInstanceModelInvariantId = null;
1370         String relatedInstanceVersion = null;
1371         String relatedInstanceModelCustomizationName = null;
1372
1373         if (instanceList != null) {
1374
1375             for (RelatedInstanceList relatedInstanceList : instanceList) {
1376
1377                 RelatedInstance relatedInstance = relatedInstanceList.getRelatedInstance();
1378                 ModelInfo relatedInstanceModelInfo = relatedInstance.getModelInfo();
1379                 if (relatedInstanceModelInfo.getModelType().equals(ModelType.service)) {
1380                     relatedInstanceModelVersionId = relatedInstanceModelInfo.getModelVersionId();
1381                     relatedInstanceVersion = relatedInstanceModelInfo.getModelVersion();
1382                 }
1383
1384                 if (relatedInstanceModelInfo.getModelType().equals(ModelType.vnf)) {
1385                     relatedInstanceModelVersionId = relatedInstanceModelInfo.getModelVersionId();
1386                     relatedInstanceModelInvariantId = relatedInstanceModelInfo.getModelInvariantId();
1387                     relatedInstanceVersion = relatedInstanceModelInfo.getModelVersion();
1388                     relatedInstanceModelCustomizationName = relatedInstanceModelInfo.getModelCustomizationName();
1389                 }
1390             }
1391
1392             if (modelInfo.getModelType().equals(ModelType.vnf)) {
1393                 // a. For a vnf request (only create, no update currently):
1394                 // i. (v3-v4) If modelInfo.modelCustomizationId is provided, use it to validate
1395                 // catalog DB has record in
1396                 // vnf_resource_customization.model_customization_uuid.
1397                 // ii. (v2-v4) If modelInfo.modelCustomizationId is NOT provided (because it is
1398                 // a pre-1702 ASDC model or
1399                 // pre-v3), then modelInfo.modelCustomizationName must have
1400                 // been provided (else create request should be rejected). APIH should use the
1401                 // relatedInstance.modelInfo[service].modelVersionId** +
1402                 // modelInfo[vnf].modelCustomizationName
1403                 // to Ã¢â‚¬Å“join�? service_to_resource_customizations with
1404                 // vnf_resource_customization to confirm a
1405                 // vnf_resource_customization.model_customization_uuid record exists.
1406                 // **If relatedInstance.modelInfo[service].modelVersionId was not provided, use
1407                 // relatedInstance.modelInfo[service].modelInvariantId + modelVersion instead to
1408                 // lookup modelVersionId
1409                 // (MODEL_UUID) in SERVICE table.
1410                 // iii. Regardless of how the value was provided/obtained above, APIH must
1411                 // always populate
1412                 // vnfModelCustomizationId in bpmnRequest. It would be assumed it was MSO
1413                 // generated
1414                 // during 1707 data migration if VID did not provide it originally on request.
1415                 // iv. Note: continue to construct the Ã¢â‚¬Å“vnf-type�? value and pass to BPMN
1416                 // (must still be populated
1417                 // in A&AI).
1418                 // 1. If modelCustomizationName is NOT provided on a vnf/vfModule request, use
1419                 // modelCustomizationId to
1420                 // look it up in our catalog to construct vnf-type value to pass to BPMN.
1421
1422                 VnfResource vnfResource = null;
1423                 VnfResourceCustomization vrc = null;
1424                 // Validation for vnfResource
1425
1426                 if (modelCustomizationId != null) {
1427                     vrc = catalogDbClient.getVnfResourceCustomizationByModelCustomizationUUID(modelCustomizationId);
1428                     if (vrc != null) {
1429                         vnfResource = vrc.getVnfResources();
1430                     }
1431                 } else {
1432                     org.onap.so.db.catalog.beans.Service service =
1433                             catalogDbClient.getServiceByID(relatedInstanceModelVersionId);
1434                     if (service == null) {
1435                         service = catalogDbClient.getServiceByModelVersionAndModelInvariantUUID(relatedInstanceVersion,
1436                                 relatedInstanceModelInvariantId);
1437                     }
1438
1439                     if (service == null) {
1440                         throw new ValidationException("service in relatedInstance");
1441                     }
1442                     for (VnfResourceCustomization vnfResourceCustom : service.getVnfCustomizations()) {
1443                         if (vnfResourceCustom.getModelInstanceName().equals(modelCustomizationName)) {
1444                             vrc = vnfResourceCustom;
1445                         }
1446                     }
1447
1448                     if (vrc != null) {
1449                         vnfResource = vrc.getVnfResources();
1450                         modelInfo.setModelCustomizationId(vrc.getModelCustomizationUUID());
1451                         modelInfo.setModelCustomizationUuid(vrc.getModelCustomizationUUID());
1452                     }
1453                 }
1454
1455                 if (vnfResource == null) {
1456                     throw new ValidationException("vnfResource");
1457                 } else {
1458                     if (modelInfo.getModelVersionId() == null) {
1459                         modelInfo.setModelVersionId(vnfResource.getModelUUID());
1460                     }
1461                 }
1462
1463                 VnfRecipe vnfRecipe = null;
1464
1465                 if (vrc != null) {
1466                     String nfRole = vrc.getNfRole();
1467                     if (nfRole != null) {
1468                         vnfRecipe =
1469                                 catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(vrc.getNfRole(), action.toString());
1470                     }
1471                 }
1472
1473                 if (vnfRecipe == null) {
1474                     vnfRecipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
1475                 }
1476
1477                 if (vnfRecipe == null) {
1478                     return null;
1479                 }
1480
1481                 return new RecipeLookupResult(vnfRecipe.getOrchestrationUri(), vnfRecipe.getRecipeTimeout());
1482             } else {
1483                 /*
1484                  * (v5-v7) If modelInfo.modelCustomizationId is NOT provided (because it is a pre-1702 ASDC model or
1485                  * pre-v3), then modelInfo.modelCustomizationName must have // been provided (else create request should
1486                  * be rejected). APIH should use the relatedInstance.modelInfo[vnf].modelVersionId +
1487                  * modelInfo[vnf].modelCustomizationName // to join vnf_to_resource_customizations with
1488                  * vf_resource_customization to confirm a vf_resource_customization.model_customization_uuid record
1489                  * exists. // Once the vnfs model_customization_uuid has been obtained, use it to find all vfModule
1490                  * customizations for that vnf customization in the vnf_res_custom_to_vf_module_custom join table. //
1491                  * For each vf_module_cust_model_customization_uuid value returned, use that UUID to query
1492                  * vf_module_customization table along with modelInfo[vfModule|volumeGroup].modelVersionId to // confirm
1493                  * record matches request data (and to identify the modelCustomizationId associated with the vfModule in
1494                  * the request). This means taking each record found // in vf_module_customization and looking up in
1495                  * vf_module (using vf_module_customization’s FK into vf_module) to find a match on
1496                  * MODEL_INVARIANT_UUID (modelInvariantId) // and MODEL_VERSION (modelVersion).
1497                  */
1498                 VfModuleCustomization vfmc = null;
1499                 VnfResource vnfr;
1500                 VnfResourceCustomization vnfrc;
1501                 VfModule vfModule = null;
1502
1503                 if (modelInfo.getModelCustomizationId() != null) {
1504                     vfmc = catalogDbClient
1505                             .getVfModuleCustomizationByModelCuztomizationUUID(modelInfo.getModelCustomizationId());
1506                 } else {
1507                     vnfr = catalogDbClient.getVnfResourceByModelUUID(relatedInstanceModelVersionId);
1508                     if (vnfr == null) {
1509                         vnfr = catalogDbClient.getFirstVnfResourceByModelInvariantUUIDAndModelVersion(
1510                                 relatedInstanceModelInvariantId, relatedInstanceVersion);
1511                     }
1512                     vnfrc = catalogDbClient.getFirstVnfResourceCustomizationByModelInstanceNameAndVnfResources(
1513                             relatedInstanceModelCustomizationName, vnfr);
1514
1515                     List<VfModuleCustomization> list = vnfrc.getVfModuleCustomizations();
1516
1517                     String vfModuleModelUUID = modelInfo.getModelVersionId();
1518                     for (VfModuleCustomization vf : list) {
1519                         VfModuleCustomization vfmCustom;
1520                         if (vfModuleModelUUID != null) {
1521                             vfmCustom = catalogDbClient
1522                                     .getVfModuleCustomizationByModelCustomizationUUIDAndVfModuleModelUUID(
1523                                             vf.getModelCustomizationUUID(), vfModuleModelUUID);
1524                             if (vfmCustom != null) {
1525                                 vfModule = vfmCustom.getVfModule();
1526                             }
1527                         } else {
1528                             vfmCustom = catalogDbClient
1529                                     .getVfModuleCustomizationByModelCuztomizationUUID(vf.getModelCustomizationUUID());
1530                             if (vfmCustom != null) {
1531                                 vfModule = vfmCustom.getVfModule();
1532                             } else {
1533                                 vfModule = catalogDbClient.getVfModuleByModelInvariantUUIDAndModelVersion(
1534                                         relatedInstanceModelInvariantId, relatedInstanceVersion);
1535                             }
1536                         }
1537
1538                         if (vfModule != null) {
1539                             modelInfo.setModelCustomizationId(vf.getModelCustomizationUUID());
1540                             modelInfo.setModelCustomizationUuid(vf.getModelCustomizationUUID());
1541                             break;
1542                         }
1543                     }
1544                 }
1545
1546                 if (vfmc == null && vfModule == null) {
1547                     throw new ValidationException("vfModuleCustomization");
1548                 } else if (vfModule == null && vfmc != null) {
1549                     vfModule = vfmc.getVfModule(); // can't be null as vfModuleModelUUID is not-null property in
1550                     // VfModuleCustomization table
1551                 }
1552
1553                 if (modelInfo.getModelVersionId() == null) {
1554                     modelInfo.setModelVersionId(vfModule.getModelUUID());
1555                 }
1556
1557                 recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1558                         vfModule.getModelUUID(), vnfComponentType, action.toString());
1559                 if (recipe == null) {
1560                     List<VfModule> vfModuleRecords = catalogDbClient
1561                             .getVfModuleByModelInvariantUUIDOrderByModelVersionDesc(vfModule.getModelInvariantUUID());
1562                     if (!vfModuleRecords.isEmpty()) {
1563                         for (VfModule record : vfModuleRecords) {
1564                             recipe = catalogDbClient
1565                                     .getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1566                                             record.getModelUUID(), vnfComponentType, action.toString());
1567                             if (recipe != null) {
1568                                 break;
1569                             }
1570                         }
1571                     }
1572                 }
1573                 if (recipe == null) {
1574                     recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1575                             defaultSource, vnfComponentType, action.toString());
1576                     if (recipe == null) {
1577                         recipe = catalogDbClient.getFirstVnfComponentsRecipeByVnfComponentTypeAndAction(
1578                                 vnfComponentType, action.toString());
1579                     }
1580
1581                     if (recipe == null) {
1582                         return null;
1583                     }
1584                 }
1585             }
1586         } else {
1587
1588             if (modelInfo.getModelType().equals(ModelType.vnf)) {
1589                 recipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
1590                 if (recipe == null) {
1591                     return null;
1592                 }
1593             } else {
1594                 recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1595                         defaultSource, vnfComponentType, action.toString());
1596
1597                 if (recipe == null) {
1598                     return null;
1599                 }
1600             }
1601         }
1602
1603         return new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout());
1604     }
1605
1606     private RecipeLookupResult getDefaultVnfUri(ServiceInstancesRequest sir, Actions action) {
1607
1608         String defaultSource = requestHandlerUtils.getDefaultModel(sir);
1609
1610         VnfRecipe vnfRecipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
1611
1612         if (vnfRecipe == null) {
1613             return null;
1614         }
1615
1616         return new RecipeLookupResult(vnfRecipe.getOrchestrationUri(), vnfRecipe.getRecipeTimeout());
1617     }
1618
1619     private RecipeLookupResult getNetworkUri(ServiceInstancesRequest sir, Actions action) throws ValidationException {
1620
1621         String defaultNetworkType = requestHandlerUtils.getDefaultModel(sir);
1622
1623         ModelInfo modelInfo = sir.getRequestDetails().getModelInfo();
1624         String modelName = modelInfo.getModelName();
1625         Recipe recipe = null;
1626
1627         if (modelInfo.getModelCustomizationId() != null) {
1628             NetworkResourceCustomization networkResourceCustomization = catalogDbClient
1629                     .getNetworkResourceCustomizationByModelCustomizationUUID(modelInfo.getModelCustomizationId());
1630             if (networkResourceCustomization != null) {
1631                 NetworkResource networkResource = networkResourceCustomization.getNetworkResource();
1632                 if (networkResource != null) {
1633                     if (modelInfo.getModelVersionId() == null) {
1634                         modelInfo.setModelVersionId(networkResource.getModelUUID());
1635                     }
1636                     recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(networkResource.getModelName(),
1637                             action.toString());
1638                 } else {
1639                     throw new ValidationException("no catalog entry found");
1640                 }
1641             } else if (action != Action.deleteInstance) {
1642                 throw new ValidationException("modelCustomizationId for networkResourceCustomization lookup", true);
1643             }
1644         } else {
1645             // ok for version < 3 and action delete
1646             if (modelName != null) {
1647                 recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(modelName, action.toString());
1648             }
1649         }
1650
1651         if (recipe == null) {
1652             recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(defaultNetworkType, action.toString());
1653         }
1654
1655         return recipe != null ? new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout()) : null;
1656     }
1657
1658     private Response configurationRecipeLookup(String requestJSON, Action action, HashMap<String, String> instanceIdMap,
1659             String version, String requestId, String requestUri) throws ApiException {
1660         String serviceInstanceId;
1661         Boolean aLaCarte = null;
1662         String apiVersion = version.substring(1);
1663         boolean inProgress = false;
1664         ServiceInstancesRequest sir;
1665
1666         sir = requestHandlerUtils.convertJsonToServiceInstanceRequest(requestJSON, action, requestId, requestUri);
1667         String requestScope = requestHandlerUtils.deriveRequestScope(action, sir, requestUri);
1668         InfraActiveRequests currentActiveReq =
1669                 msoRequest.createRequestObject(sir, action, requestId, Status.IN_PROGRESS, requestJSON, requestScope);
1670         if (sir.getRequestDetails().getRequestParameters() != null) {
1671             aLaCarte = sir.getRequestDetails().getRequestParameters().getALaCarte();
1672         }
1673         requestHandlerUtils.parseRequest(sir, instanceIdMap, action, version, requestJSON, aLaCarte, requestId,
1674                 currentActiveReq);
1675         requestHandlerUtils.setInstanceId(currentActiveReq, requestScope, null, instanceIdMap);
1676         String instanceName = sir.getRequestDetails().getRequestInfo().getInstanceName();
1677
1678         InfraActiveRequests dup = null;
1679
1680         dup = requestHandlerUtils.duplicateCheck(action, instanceIdMap, instanceName, requestScope, currentActiveReq);
1681
1682         if (dup != null) {
1683             inProgress = requestHandlerUtils.camundaHistoryCheck(dup, currentActiveReq);
1684         }
1685
1686         if (instanceIdMap != null && dup != null && inProgress) {
1687             requestHandlerUtils.buildErrorOnDuplicateRecord(currentActiveReq, action, instanceIdMap, instanceName,
1688                     requestScope, dup);
1689         }
1690
1691         ServiceInstancesResponse serviceResponse = new ServiceInstancesResponse();
1692         RequestReferences referencesResponse = new RequestReferences();
1693         referencesResponse.setRequestId(requestId);
1694         serviceResponse.setRequestReferences(referencesResponse);
1695
1696         String orchestrationUri = env.getProperty(CommonConstants.ALACARTE_ORCHESTRATION);
1697         String timeOut = env.getProperty(CommonConstants.ALACARTE_RECIPE_TIMEOUT);
1698
1699         if (StringUtils.isBlank(orchestrationUri) || StringUtils.isBlank(timeOut)) {
1700             String error = StringUtils.isBlank(orchestrationUri) ? "ALaCarte Orchestration URI not found in properties"
1701                     : "ALaCarte Recipe Timeout not found in properties";
1702
1703             ErrorLoggerInfo errorLoggerInfo =
1704                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND, ErrorCode.DataError)
1705                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1706
1707             ValidateException validateException = new ValidateException.Builder(error, HttpStatus.SC_NOT_FOUND,
1708                     ErrorNumbers.SVC_GENERAL_SERVICE_ERROR).errorInfo(errorLoggerInfo).build();
1709
1710             requestHandlerUtils.updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
1711
1712             throw validateException;
1713
1714         }
1715
1716         serviceInstanceId = "";
1717         String configurationId = "";
1718         String pnfCorrelationId = "";
1719
1720         if (sir.getServiceInstanceId() != null) {
1721             serviceInstanceId = sir.getServiceInstanceId();
1722         }
1723
1724         if (sir.getConfigurationId() != null) {
1725             configurationId = sir.getConfigurationId();
1726         }
1727
1728         pnfCorrelationId = getPnfCorrelationId(sir);
1729
1730         try {
1731             infraActiveRequestsClient.save(currentActiveReq);
1732         } catch (Exception e) {
1733             ErrorLoggerInfo errorLoggerInfo =
1734                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
1735                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1736             throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR,
1737                     ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e).errorInfo(errorLoggerInfo).build();
1738         }
1739
1740         if (!requestScope.equalsIgnoreCase(ModelType.service.name())) {
1741             aLaCarte = true;
1742         } else if (aLaCarte == null) {
1743             aLaCarte = false;
1744         }
1745         RequestClientParameter requestClientParameter = null;
1746         try {
1747             requestClientParameter = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
1748                     .setRecipeTimeout(Integer.parseInt(timeOut)).setRequestAction(action.toString())
1749                     .setServiceInstanceId(serviceInstanceId).setPnfCorrelationId(pnfCorrelationId)
1750                     .setConfigurationId(configurationId)
1751                     .setRequestDetails(requestHandlerUtils.mapJSONtoMSOStyle(requestJSON, sir, aLaCarte, action))
1752                     .setApiVersion(apiVersion).setALaCarte(aLaCarte).setRequestUri(requestUri).build();
1753         } catch (IOException e) {
1754             ErrorLoggerInfo errorLoggerInfo =
1755                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
1756                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
1757             throw new ValidateException.Builder("Unable to generate RequestClientParamter object" + e.getMessage(),
1758                     HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).errorInfo(errorLoggerInfo)
1759                             .build();
1760         }
1761
1762         return requestHandlerUtils.postBPELRequest(currentActiveReq, requestClientParameter, orchestrationUri,
1763                 requestScope);
1764     }
1765
1766 }