Support for defining attributes on a node_type
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ResourceImportManager.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22
23 package org.openecomp.sdc.be.components.impl;
24
25 import static org.openecomp.sdc.be.components.impl.ImportUtils.Constants.QUOTE;
26 import static org.openecomp.sdc.be.utils.TypeUtils.setField;
27
28 import fj.data.Either;
29 import java.util.LinkedHashMap;
30 import org.apache.commons.codec.binary.Base64;
31 import org.apache.commons.lang3.StringUtils;
32 import org.apache.commons.lang3.tuple.ImmutablePair;
33 import org.openecomp.sdc.be.auditing.api.AuditEventFactory;
34 import org.openecomp.sdc.be.auditing.impl.AuditingManager;
35 import org.openecomp.sdc.be.auditing.impl.resourceadmin.AuditImportResourceAdminEventFactory;
36 import org.openecomp.sdc.be.components.csar.CsarInfo;
37 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum;
38 import org.openecomp.sdc.be.components.impl.ImportUtils.Constants;
39 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
40 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
41 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
42 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
43 import org.openecomp.sdc.be.config.BeEcompErrorManager;
44 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
45 import org.openecomp.sdc.be.dao.api.ActionStatus;
46 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
47 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
48 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
49 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
50 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
51 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
52 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
53 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
54 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
55 import org.openecomp.sdc.be.impl.ComponentsUtils;
56 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
57 import org.openecomp.sdc.be.model.ArtifactDefinition;
58 import org.openecomp.sdc.be.model.AttributeDefinition;
59 import org.openecomp.sdc.be.model.CapabilityDefinition;
60 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
61 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
62 import org.openecomp.sdc.be.model.InterfaceDefinition;
63 import org.openecomp.sdc.be.model.LifecycleStateEnum;
64 import org.openecomp.sdc.be.model.PropertyDefinition;
65 import org.openecomp.sdc.be.model.RequirementDefinition;
66 import org.openecomp.sdc.be.model.Resource;
67 import org.openecomp.sdc.be.model.UploadResourceInfo;
68 import org.openecomp.sdc.be.model.User;
69 import org.openecomp.sdc.be.model.category.CategoryDefinition;
70 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
71 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
72 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
73 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
74 import org.openecomp.sdc.be.model.operations.impl.CapabilityTypeOperation;
75 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
76 import org.openecomp.sdc.be.resources.data.auditing.model.CommonAuditData;
77 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
78 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo;
79 import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
80 import org.openecomp.sdc.be.utils.TypeUtils;
81 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
82 import org.openecomp.sdc.common.log.wrappers.Logger;
83 import org.openecomp.sdc.common.util.ThreadLocalsHolder;
84 import org.openecomp.sdc.common.util.ValidationUtils;
85 import org.openecomp.sdc.exception.ResponseFormat;
86 import org.springframework.beans.factory.annotation.Autowired;
87 import org.springframework.stereotype.Component;
88 import org.springframework.web.context.WebApplicationContext;
89 import org.yaml.snakeyaml.Yaml;
90
91 import javax.servlet.ServletContext;
92 import java.util.ArrayList;
93 import java.util.Arrays;
94 import java.util.HashMap;
95 import java.util.HashSet;
96 import java.util.Iterator;
97 import java.util.List;
98 import java.util.Map;
99 import java.util.Map.Entry;
100 import java.util.Set;
101 import java.util.function.Function;
102 import java.util.regex.Pattern;
103 import java.util.stream.Collectors;
104
105 @Component("resourceImportManager")
106 public class ResourceImportManager {
107
108     private static final Logger log = Logger.getLogger(ResourceImportManager.class);
109
110     static final Pattern PROPERTY_NAME_PATTERN_IGNORE_LENGTH = Pattern.compile("[\\w\\-\\_\\d\\:]+");
111     private static final String IMPLEMENTATION = "implementation";
112     private static final String INPUTS = "inputs";
113     private static final String TYPE = "type";
114     private static final String DESCRIPTION = "description";
115     private static final String REQUIRED = "required";
116     private static final String DEFAULT = "default";
117     private static final String STATUS = "status";
118
119     private ServletContext servletContext;
120
121     private AuditingManager auditingManager;
122     private ResourceBusinessLogic resourceBusinessLogic;
123     private InterfaceOperationBusinessLogic interfaceOperationBusinessLogic;
124
125     private IGraphLockOperation graphLockOperation;
126     private ToscaOperationFacade toscaOperationFacade;
127
128     private final ComponentsUtils componentsUtils;
129     private final CapabilityTypeOperation capabilityTypeOperation;
130
131     private ResponseFormatManager responseFormatManager;
132
133     @Autowired
134     public ResourceImportManager(ComponentsUtils componentsUtils, CapabilityTypeOperation capabilityTypeOperation) {
135         this.componentsUtils = componentsUtils;
136         this.capabilityTypeOperation = capabilityTypeOperation;
137     }
138
139     @Autowired
140     public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) {
141         this.toscaOperationFacade = toscaOperationFacade;
142     }
143
144     public ImmutablePair<Resource, ActionStatus> importNormativeResource(String resourceYml,
145                                                                          UploadResourceInfo resourceMetaData,
146                                                                          User creator, boolean createNewVersion,
147                                                                          boolean needLock) {
148
149         LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction();
150         lifecycleChangeInfo.setUserRemarks("certification on import");
151         Function<Resource, Boolean> validator = resource -> resourceBusinessLogic
152             .validatePropertiesDefaultValues(resource);
153
154         return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false,
155             createNewVersion, needLock, null, null, false, null, null, false);
156     }
157
158     public ImmutablePair<Resource, ActionStatus> importNormativeResourceFromCsar(String resourceYml,
159                                                                                  UploadResourceInfo resourceMetaData,
160                                                                                  User creator, boolean createNewVersion,
161                                                                                  boolean needLock) {
162
163         LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction();
164         lifecycleChangeInfo.setUserRemarks("certification on import");
165         Function<Resource, Boolean> validator = resource -> resourceBusinessLogic
166             .validatePropertiesDefaultValues(resource);
167
168         return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false,
169             createNewVersion, needLock, null, null, false, null, null, false);
170     }
171
172     public ImmutablePair<Resource, ActionStatus> importCertifiedResource(String resourceYml,
173                                                                          UploadResourceInfo resourceMetaData,
174                                                                          User creator,
175                                                                          Function<Resource, Boolean> validationFunction,
176                                                                          LifecycleChangeInfoWithAction lifecycleChangeInfo,
177                                                                          boolean isInTransaction,
178                                                                          boolean createNewVersion, boolean needLock,
179                                                                          Map<ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle,
180                                                                          List<ArtifactDefinition> nodeTypesNewCreatedArtifacts,
181                                                                          boolean forceCertificationAllowed,
182                                                                          CsarInfo csarInfo, String nodeName,
183                                                                          boolean isNested) {
184         Resource resource = new Resource();
185         ImmutablePair<Resource, ActionStatus> responsePair = new ImmutablePair<>(resource, ActionStatus.CREATED);
186         Either<ImmutablePair<Resource, ActionStatus>, ResponseFormat> response = Either.left(responsePair);
187
188         String latestCertifiedResourceId = null;
189         try {
190             boolean shouldBeCertified = nodeTypeArtifactsToHandle == null || nodeTypeArtifactsToHandle.isEmpty();
191             setConstantMetaData(resource, shouldBeCertified);
192             setMetaDataFromJson(resourceMetaData, resource);
193
194             populateResourceFromYaml(resourceYml, resource);
195
196             Boolean isValidResource = validationFunction.apply(resource);
197             if (!createNewVersion) {
198                 Either<Resource, StorageOperationStatus> latestByName = toscaOperationFacade
199                     .getLatestByName(resource.getName());
200                 if (latestByName.isLeft()) {
201                     throw new ByActionStatusComponentException(ActionStatus.COMPONENT_NAME_ALREADY_EXIST,
202                         resource.getName());
203                 }
204             }
205             resource = resourceBusinessLogic
206                 .createOrUpdateResourceByImport(resource, creator, true, isInTransaction, needLock, csarInfo, nodeName,
207                     isNested).left;
208             Resource changeStateResponse;
209
210             if (nodeTypeArtifactsToHandle != null && !nodeTypeArtifactsToHandle.isEmpty()) {
211                 Either<List<ArtifactDefinition>, ResponseFormat> handleNodeTypeArtifactsRes =
212                     resourceBusinessLogic
213                         .handleNodeTypeArtifacts(resource, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts,
214                             creator, isInTransaction, false);
215                 if (handleNodeTypeArtifactsRes.isRight()) {
216                     //TODO: should be used more correct action
217                     throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
218                 }
219             }
220             latestCertifiedResourceId = getLatestCertifiedResourceId(resource);
221             changeStateResponse = resourceBusinessLogic
222                 .propagateStateToCertified(creator, resource, lifecycleChangeInfo, isInTransaction, needLock,
223                     forceCertificationAllowed);
224             responsePair = new ImmutablePair<>(changeStateResponse, response.left()
225                 .value().right);
226         } catch (RuntimeException e) {
227             handleImportResourceException(resourceMetaData, creator, true, e);
228         } finally {
229             if (latestCertifiedResourceId != null && needLock) {
230                 log.debug("unlock resource {}", latestCertifiedResourceId);
231                 graphLockOperation.unlockComponent(latestCertifiedResourceId, NodeTypeEnum.Resource);
232             }
233         }
234
235         return responsePair;
236     }
237
238     private ResponseFormat getResponseFormatFromComponentException(RuntimeException e) {
239         if (e instanceof ComponentException) {
240             return ((ComponentException) e).getResponseFormat() == null ?
241                 componentsUtils
242                     .getResponseFormat(((ComponentException) e).getActionStatus(), ((ComponentException) e).getParams())
243                 :
244                     ((ComponentException) e).getResponseFormat();
245         }
246         return null;
247     }
248
249     private String getLatestCertifiedResourceId(Resource resource) {
250         Map<String, String> allVersions = resource.getAllVersions();
251         Double latestCertifiedVersion = 0.0;
252         if (allVersions != null) {
253             for (String version : allVersions.keySet()) {
254                 Double dVersion = Double.valueOf(version);
255                 if ((dVersion > latestCertifiedVersion) && (version.endsWith(".0"))) {
256                     latestCertifiedVersion = dVersion;
257                 }
258             }
259             return allVersions.get(String.valueOf(latestCertifiedVersion));
260         } else {
261             return null;
262         }
263     }
264
265     public void populateResourceMetadata(UploadResourceInfo resourceMetaData, Resource resource) {
266         if (resource != null && resourceMetaData != null) {
267             resource.setDescription(resourceMetaData.getDescription());
268             resource.setTags(resourceMetaData.getTags());
269             resource.setCategories(resourceMetaData.getCategories());
270             resource.setContactId(resourceMetaData.getContactId());
271             resource.setName(resourceMetaData.getName());
272             resource.setIcon(resourceMetaData.getResourceIconPath());
273             resource.setResourceVendorModelNumber(resourceMetaData.getResourceVendorModelNumber());
274             resource.setResourceType(ResourceTypeEnum.valueOf(resourceMetaData.getResourceType()));
275             if (resourceMetaData.getVendorName() != null) {
276                 resource.setVendorName(resourceMetaData.getVendorName());
277             }
278             if (resourceMetaData.getVendorRelease() != null) {
279                 resource.setVendorRelease(resourceMetaData.getVendorRelease());
280             }
281         }
282     }
283
284     public ImmutablePair<Resource, ActionStatus> importUserDefinedResource(String resourceYml,
285                                                                            UploadResourceInfo resourceMetaData,
286                                                                            User creator, boolean isInTransaction) {
287
288         Resource resource = new Resource();
289         ImmutablePair<Resource, ActionStatus> responsePair = new ImmutablePair<>(resource, ActionStatus.CREATED);
290
291         try {
292             setMetaDataFromJson(resourceMetaData, resource);
293
294             populateResourceFromYaml(resourceYml, resource);
295
296             // currently import VF isn't supported. In future will be supported
297             // import VF only with CSAR file!!
298             if (ResourceTypeEnum.VF == resource.getResourceType()) {
299                 log.debug("Now import VF isn't supported. It will be supported in future with CSAR file only");
300                 throw new ByActionStatusComponentException(ActionStatus.RESTRICTED_OPERATION);
301             }
302
303             resourceBusinessLogic.validateDerivedFromNotEmpty(creator, resource, AuditingActionEnum.CREATE_RESOURCE);
304             Boolean validatePropertiesTypes = resourceBusinessLogic.validatePropertiesDefaultValues(resource);
305
306             responsePair = resourceBusinessLogic.createOrUpdateResourceByImport(resource, creator,
307                 false, isInTransaction, true, null, null, false);
308
309         } catch (RuntimeException e) {
310             handleImportResourceException(resourceMetaData, creator, false, e);
311         }
312         return responsePair;
313
314     }
315
316     private void populateResourceFromYaml(String resourceYml, Resource resource) {
317         @SuppressWarnings("unchecked")
318         Object ymlObj = new Yaml().load(resourceYml);
319         if (ymlObj instanceof Map) {
320             Map<String, Object> toscaJsonAll = (Map<String, Object>) ymlObj;
321             Map<String, Object> toscaJson = toscaJsonAll;
322
323             // Checks if exist and builds the node_types map
324             if (toscaJsonAll.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName())
325                 && resource.getResourceType() != ResourceTypeEnum.CVFC) {
326                 toscaJson = new HashMap<>();
327                 toscaJson.put(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName(),
328                     toscaJsonAll.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName()));
329             }
330             // Derived From
331             Resource parentResource = setDerivedFrom(toscaJson, resource);
332             if (StringUtils.isEmpty(resource.getToscaResourceName())) {
333                 setToscaResourceName(toscaJson, resource);
334             }
335             setAttributes(toscaJson, resource);
336             setCapabilities(toscaJson, resource, parentResource);
337             setProperties(toscaJson, resource);
338             setRequirements(toscaJson, resource, parentResource);
339             setInterfaceLifecycle(toscaJson, resource);
340         } else {
341             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
342         }
343
344     }
345
346     private void setToscaResourceName(Map<String, Object> toscaJson, Resource resource) {
347         Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils
348             .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
349         if (toscaElement.isLeft() || toscaElement.left().value().size() == 1) {
350             String toscaResourceName = toscaElement.left().value().keySet().iterator().next();
351             resource.setToscaResourceName(toscaResourceName);
352         }
353     }
354
355     private void setInterfaceLifecycle(Map<String, Object> toscaJson, Resource resource) {
356         Either<Map<String, Object>, ResultStatusEnum> toscaInterfaces = ImportUtils
357             .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.INTERFACES);
358         if (toscaInterfaces.isLeft()) {
359             Map<String, Object> jsonInterfaces = toscaInterfaces.left().value();
360             Map<String, InterfaceDefinition> moduleInterfaces = new HashMap<>();
361             Iterator<Entry<String, Object>> interfacesNameValue = jsonInterfaces.entrySet().iterator();
362             while (interfacesNameValue.hasNext()) {
363                 Entry<String, Object> interfaceNameValue = interfacesNameValue.next();
364                 Either<InterfaceDefinition, ResultStatusEnum> eitherInterface = createModuleInterface(interfaceNameValue
365                     .getValue(), resource);
366                 if (eitherInterface.isRight()) {
367                     log.info("error when creating interface:{}, for resource:{}", interfaceNameValue.getKey(),
368                         resource.getName());
369                 } else {
370                     moduleInterfaces.put(interfaceNameValue.getKey(), eitherInterface.left().value());
371                 }
372
373             }
374             if (moduleInterfaces.size() > 0) {
375                 resource.setInterfaces(moduleInterfaces);
376             }
377         }
378     }
379
380     private Either<InterfaceDefinition, ResultStatusEnum> createModuleInterface(Object interfaceJson,
381                                                                                 Resource resource) {
382         final InterfaceDefinition interf = new InterfaceDefinition();
383         Either<InterfaceDefinition, ResultStatusEnum> result = Either.left(interf);
384
385         try {
386             if (interfaceJson instanceof String) {
387                 final String requirementJsonString = (String) interfaceJson;
388                 interf.setType(requirementJsonString);
389             } else if (interfaceJson instanceof Map && ResourceTypeEnum.VFC.equals(resource.getResourceType())) {
390                 final Map<String, Object> requirementJsonMap = (Map<String, Object>) interfaceJson;
391                 final Map<String, OperationDataDefinition> operations = new HashMap<>();
392
393                 for (final Entry<String, Object> entry : requirementJsonMap.entrySet()) {
394                     if (entryIsInterfaceType(entry)) {
395                         final String type = (String) requirementJsonMap
396                             .get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName());
397                         interf.setType(type);
398                         interf.setUniqueId(type.toLowerCase());
399                     } else if (entryContainsImplementationForAKnownOperation(entry, interf.getType())) {
400
401                         final OperationDataDefinition operation = new OperationDataDefinition();
402                         operation.setName(entry.getKey());
403
404                         final Map<?, ?> entryValue = (Map<?, ?>) entry.getValue();
405                         if (entryValue.containsKey(IMPLEMENTATION)) {
406                             operation.setImplementation(handleOperationImplementation(entry));
407                         }
408                         if (entryValue.containsKey(INPUTS)) {
409                             final Map<String, Object> interfaceInputs = (Map<String, Object>) entryValue
410                                 .get(ToscaTagNamesEnum.INPUTS.getElementName());
411                             operation.setInputs(handleInterfaceInput(interfaceInputs));
412                         }
413                         operations.put(entry.getKey(), operation);
414                     }
415                 }
416                 if (!operations.isEmpty()) {
417                     interf.setOperations(operations);
418                 }
419             } else {
420                 result = Either.right(ResultStatusEnum.GENERAL_ERROR);
421             }
422
423         } catch (Exception e) {
424             BeEcompErrorManager.getInstance().logBeSystemError("Import Resource- create interface");
425             log.debug("error when creating interface, message:{}", e.getMessage(), e);
426             result = Either.right(ResultStatusEnum.GENERAL_ERROR);
427         }
428
429         return result;
430     }
431
432     private ArtifactDataDefinition handleOperationImplementation(final Entry<String, Object> entry) {
433         final ArtifactDataDefinition implementation = new ArtifactDataDefinition();
434         final String artifactName = ((Map<String, String>) entry.getValue()).get(IMPLEMENTATION);
435         if (OperationArtifactUtil.artifactNameIsALiteralValue(artifactName)) {
436             implementation.setArtifactName(artifactName);
437         } else {
438             implementation.setArtifactName(QUOTE + artifactName + QUOTE);
439         }
440         return implementation;
441     }
442
443     private ListDataDefinition<OperationInputDefinition> handleInterfaceInput(
444         final Map<String, Object> interfaceInputs) {
445         final ListDataDefinition<OperationInputDefinition> inputs = new ListDataDefinition<>();
446         for (final Entry<String, Object> interfaceInput : interfaceInputs.entrySet()) {
447             final OperationInputDefinition operationInput = new OperationInputDefinition();
448             operationInput.setName(interfaceInput.getKey());
449             if (interfaceInput.getValue() instanceof Map) {
450                 final LinkedHashMap<String, Object> inputPropertyValue =
451                     (LinkedHashMap<String, Object>) interfaceInput.getValue();
452                 log.info("createModuleInterface: i interfaceInput.getKey() {}, {} , {}  ",
453                     interfaceInput.getKey(), inputPropertyValue.keySet(),
454                     inputPropertyValue.values());
455                 if (inputPropertyValue.get(TYPE) != null) {
456                     operationInput.setType(inputPropertyValue.get(TYPE).toString());
457                 }
458                 if (inputPropertyValue.get(DESCRIPTION) != null) {
459                     operationInput.setDescription(inputPropertyValue.get(DESCRIPTION).toString());
460                 }
461                 if (inputPropertyValue.get(REQUIRED) != null) {
462                     operationInput.setRequired(
463                         Boolean.getBoolean(inputPropertyValue.get(REQUIRED).toString()));
464                 }
465                 if (inputPropertyValue.get(DEFAULT) != null) {
466                     operationInput.setToscaDefaultValue(inputPropertyValue.get(DEFAULT).toString());
467                 }
468                 if (inputPropertyValue.get(STATUS) != null) {
469                     operationInput.setStatus(inputPropertyValue.get(STATUS).toString());
470                 }
471
472             } else if (interfaceInput.getValue() instanceof String) {
473                 final String value = (String) interfaceInput.getValue();
474                 operationInput.setDefaultValue(value);
475                 operationInput.setToscaDefaultValue(value);
476                 operationInput.setValue(value);
477             }
478             inputs.getListToscaDataDefinition().add(operationInput);
479             inputs.add(operationInput);
480         }
481         return inputs;
482     }
483
484     private boolean entryIsInterfaceType(final Entry<String, Object> entry) {
485         if (entry.getKey().equals(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
486             if (entry.getValue() instanceof String) {
487                 return true;
488             }
489             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML);
490         }
491         return false;
492     }
493
494     private boolean entryContainsImplementationForAKnownOperation(final Entry<String, Object> entry,
495                                                                   final String interfaceType) {
496         if (entry.getValue() instanceof Map && ((Map<?, ?>) entry.getValue()).containsKey(IMPLEMENTATION)) {
497             if (isAKnownOperation(interfaceType, entry.getKey())) {
498                 return true;
499             }
500             throw new ByActionStatusComponentException(ActionStatus.INTERFACE_OPERATION_NOT_FOUND);
501         }
502         return false;
503     }
504
505     private boolean isAKnownOperation(String interfaceType, String operation) {
506         Either<Map<String, InterfaceDefinition>, ResponseFormat> interfaceLifecycleTypes = interfaceOperationBusinessLogic
507             .getAllInterfaceLifecycleTypes();
508         if (interfaceLifecycleTypes.isRight() || interfaceLifecycleTypes.left().value() == null) {
509             return false;
510         }
511
512         for (Entry<String, InterfaceDefinition> interfaceLifecycleType : interfaceLifecycleTypes.left().value()
513             .entrySet()) {
514             if (interfaceTypeAndOperationMatches(interfaceLifecycleType, interfaceType, operation)) {
515                 return true;
516             }
517         }
518         return false;
519     }
520
521     private boolean interfaceTypeAndOperationMatches(Entry<String, InterfaceDefinition> interfaceLifecycleType,
522                                                      String interfaceType, String operation) {
523         if (interfaceLifecycleType.getKey().equalsIgnoreCase(interfaceType)
524             && interfaceLifecycleType.getValue().getOperations() != null) {
525             for (String interfaceLifecycleTypeOperation : interfaceLifecycleType.getValue().getOperations().keySet()) {
526                 if (interfaceLifecycleTypeOperation != null && interfaceLifecycleTypeOperation
527                     .equalsIgnoreCase(operation)) {
528                     return true;
529                 }
530             }
531         }
532         return false;
533     }
534
535     private void setRequirements(Map<String, Object> toscaJson, Resource resource,
536                                  Resource parentResource) {// Note that parentResource can be null
537         Either<List<Object>, ResultStatusEnum> toscaRequirements = ImportUtils
538             .findFirstToscaListElement(toscaJson, TypeUtils.ToscaTagNamesEnum.REQUIREMENTS);
539         if (toscaRequirements.isLeft()) {
540             List<Object> jsonRequirements = toscaRequirements.left().value();
541             Map<String, List<RequirementDefinition>> moduleRequirements = new HashMap<>();
542             // Checking for name duplication
543             Set<String> reqNames = new HashSet<>();
544             // Getting flattened list of capabilities of parent node - cap name
545             // to cap type
546             Map<String, String> reqName2TypeMap = getReqName2Type(parentResource);
547             for (Object jsonRequirementObj : jsonRequirements) {
548                 // Requirement
549                 Map<String, Object> requirementJsonWrapper = (Map<String, Object>) jsonRequirementObj;
550                 String requirementName = requirementJsonWrapper.keySet().iterator().next();
551                 String reqNameLowerCase = requirementName.toLowerCase();
552                 if (reqNames.contains(reqNameLowerCase)) {
553                     log.debug(
554                         "More than one requirement with same name {} (case-insensitive) in imported TOSCA file is invalid",
555                         reqNameLowerCase);
556                     throw new ByActionStatusComponentException(ActionStatus.IMPORT_DUPLICATE_REQ_CAP_NAME,
557                         "requirement", reqNameLowerCase);
558                 }
559                 reqNames.add(reqNameLowerCase);
560                 RequirementDefinition requirementDef = createRequirementFromImportFile(requirementJsonWrapper
561                     .get(requirementName));
562                 requirementDef.setName(requirementName);
563                 if (moduleRequirements.containsKey(requirementDef.getCapability())) {
564                     moduleRequirements.get(requirementDef.getCapability()).add(requirementDef);
565                 } else {
566                     List<RequirementDefinition> list = new ArrayList<>();
567                     list.add(requirementDef);
568                     moduleRequirements.put(requirementDef.getCapability(), list);
569                 }
570
571                 // Validating against req/cap of "derived from" node
572                 Boolean validateVsParentCap = validateCapNameVsDerived(reqName2TypeMap, requirementDef
573                     .getCapability(), requirementDef.getName());
574                 if (!validateVsParentCap) {
575                     String parentResourceName = parentResource != null ? parentResource.getName() : "";
576                     log.debug("Requirement with name {} already exists in parent {}", requirementDef.getName(),
577                         parentResourceName);
578                     throw new ByActionStatusComponentException(ActionStatus.IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED,
579                         "requirement", requirementDef
580                         .getName()
581                         .toLowerCase(), parentResourceName);
582                 }
583             }
584             if (moduleRequirements.size() > 0) {
585                 resource.setRequirements(moduleRequirements);
586             }
587
588         }
589     }
590
591     private RequirementDefinition createRequirementFromImportFile(Object requirementJson) {
592         RequirementDefinition requirement = new RequirementDefinition();
593
594         if (requirementJson instanceof String) {
595             String requirementJsonString = (String) requirementJson;
596             requirement.setCapability(requirementJsonString);
597         } else if (requirementJson instanceof Map) {
598             Map<String, Object> requirementJsonMap = (Map<String, Object>) requirementJson;
599             if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.CAPABILITY.getElementName())) {
600                 requirement.setCapability(
601                     (String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.CAPABILITY.getElementName()));
602             }
603
604             if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.NODE.getElementName())) {
605                 requirement.setNode((String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.NODE.getElementName()));
606             }
607
608             if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.RELATIONSHIP.getElementName())) {
609                 requirement.setRelationship(
610                     (String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.RELATIONSHIP.getElementName()));
611             }
612             if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName())) {
613                 List<Object> occurrencesList = (List) requirementJsonMap
614                     .get(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName());
615                 validateOccurrences(occurrencesList);
616                 requirement.setMinOccurrences(occurrencesList.get(0).toString());
617                 requirement.setMaxOccurrences(occurrencesList.get(1).toString());
618             }
619         } else {
620             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML);
621         }
622         return requirement;
623     }
624
625     private void setProperties(Map<String, Object> toscaJson, Resource resource) {
626         Map<String, Object> reducedToscaJson = new HashMap<>(toscaJson);
627         ImportUtils.removeElementFromJsonMap(reducedToscaJson, "capabilities");
628         Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = ImportUtils
629             .getProperties(reducedToscaJson);
630         if (properties.isLeft()) {
631             List<PropertyDefinition> propertiesList = new ArrayList<>();
632             Map<String, PropertyDefinition> value = properties.left().value();
633             if (value != null) {
634                 for (Entry<String, PropertyDefinition> entry : value.entrySet()) {
635                     String name = entry.getKey();
636                     if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) {
637                         log.debug("The property with invalid name {} occured upon import resource {}. ", name,
638                             resource.getName());
639                         throw new ByActionStatusComponentException(componentsUtils
640                             .convertFromResultStatusEnum(ResultStatusEnum.INVALID_PROPERTY_NAME,
641                                 JsonPresentationFields.PROPERTY));
642                     }
643                     PropertyDefinition propertyDefinition = entry.getValue();
644                     propertyDefinition.setName(name);
645                     propertiesList.add(propertyDefinition);
646                 }
647             }
648             resource.setProperties(propertiesList);
649         } else if (properties.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND) {
650             throw new ByActionStatusComponentException(componentsUtils.convertFromResultStatusEnum(properties
651                 .right()
652                 .value(), JsonPresentationFields.PROPERTY));
653         }
654     }
655
656     private ResultStatusEnum setAttributes(Map<String, Object> toscaJson, Resource resource) {
657         ResultStatusEnum result = ResultStatusEnum.OK;
658         Either<Map<String, AttributeDataDefinition>, ResultStatusEnum> attributes = ImportUtils
659             .getAttributes(toscaJson);
660         if (attributes.isLeft()) {
661             List<AttributeDataDefinition> attributeList = new ArrayList<>();
662             Map<String, AttributeDataDefinition> value = attributes.left().value();
663             if (value != null) {
664                 for (Entry<String, AttributeDataDefinition> entry : value.entrySet()) {
665                     String name = entry.getKey();
666                     AttributeDataDefinition attributeDef = entry.getValue();
667                     attributeDef.setName(name);
668                     attributeList.add(attributeDef);
669                 }
670             }
671             resource.setAttributes(attributeList);
672         } else {
673             result = attributes.right().value();
674         }
675         return result;
676     }
677
678     private Resource setDerivedFrom(Map<String, Object> toscaJson, Resource resource) {
679         Either<String, ResultStatusEnum> toscaDerivedFromElement = ImportUtils
680             .findFirstToscaStringElement(toscaJson, TypeUtils.ToscaTagNamesEnum.DERIVED_FROM);
681         Resource derivedFromResource = null;
682         if (toscaDerivedFromElement.isLeft()) {
683             String derivedFrom = toscaDerivedFromElement.left().value();
684             log.debug("Derived from TOSCA name is {}", derivedFrom);
685             resource.setDerivedFrom(Arrays.asList(new String[]{derivedFrom}));
686             Either<Resource, StorageOperationStatus> latestByToscaResourceName = toscaOperationFacade
687                 .getLatestByToscaResourceName(derivedFrom);
688
689             if (latestByToscaResourceName.isRight()) {
690                 StorageOperationStatus operationStatus = latestByToscaResourceName.right().value();
691                 if (operationStatus == StorageOperationStatus.NOT_FOUND) {
692                     operationStatus = StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND;
693                 }
694                 log.debug("Error when fetching parent resource {}, error: {}", derivedFrom, operationStatus);
695                 ActionStatus convertFromStorageResponse = componentsUtils.convertFromStorageResponse(operationStatus);
696                 BeEcompErrorManager.getInstance()
697                     .logBeComponentMissingError("Import TOSCA YAML", "resource", derivedFrom);
698                 throw new ByActionStatusComponentException(convertFromStorageResponse, derivedFrom);
699             }
700             derivedFromResource = latestByToscaResourceName.left().value();
701         }
702         return derivedFromResource;
703     }
704
705     private void setCapabilities(Map<String, Object> toscaJson, Resource resource,
706                                  Resource parentResource) {// Note that parentResource can be null
707         Either<Map<String, Object>, ResultStatusEnum> toscaCapabilities = ImportUtils
708             .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.CAPABILITIES);
709         if (toscaCapabilities.isLeft()) {
710             Map<String, Object> jsonCapabilities = toscaCapabilities.left().value();
711             Map<String, List<CapabilityDefinition>> moduleCapabilities = new HashMap<>();
712             Iterator<Entry<String, Object>> capabilitiesNameValue = jsonCapabilities.entrySet().iterator();
713             Set<String> capNames = new HashSet<>();
714             // Getting flattened list of capabilities of parent node - cap name
715             // to cap type
716             Map<String, String> capName2TypeMap = getCapName2Type(parentResource);
717             while (capabilitiesNameValue.hasNext()) {
718                 Entry<String, Object> capabilityNameValue = capabilitiesNameValue.next();
719
720                 // Validating that no req/cap duplicates exist in imported YAML
721                 String capNameLowerCase = capabilityNameValue.getKey().toLowerCase();
722                 if (capNames.contains(capNameLowerCase)) {
723                     log.debug(
724                         "More than one capability with same name {} (case-insensitive) in imported TOSCA file is invalid",
725                         capNameLowerCase);
726                     throw new ByActionStatusComponentException(ActionStatus.IMPORT_DUPLICATE_REQ_CAP_NAME, "capability",
727                         capNameLowerCase);
728                 }
729                 capNames.add(capNameLowerCase);
730
731                 CapabilityDefinition capabilityDef = createCapabilityFromImportFile(capabilityNameValue
732                     .getValue());
733                 capabilityDef.setName(capabilityNameValue.getKey());
734                 if (moduleCapabilities.containsKey(capabilityDef.getType())) {
735                     moduleCapabilities.get(capabilityDef.getType()).add(capabilityDef);
736                 } else {
737                     List<CapabilityDefinition> list = new ArrayList<>();
738                     list.add(capabilityDef);
739                     moduleCapabilities.put(capabilityDef.getType(), list);
740                 }
741
742                 // Validating against req/cap of "derived from" node
743                 Boolean validateVsParentCap = validateCapNameVsDerived(capName2TypeMap, capabilityDef
744                     .getType(), capabilityDef.getName());
745
746                 if (!validateVsParentCap) {
747                     // Here parentResource is for sure not null, so it's
748                     // null-safe
749                     // Check added to avoid sonar warning
750                     String parentResourceName = parentResource != null ? parentResource.getName() : "";
751                     log.debug("Capability with name {} already exists in parent {}", capabilityDef.getName(),
752                         parentResourceName);
753                     throw new ByActionStatusComponentException(ActionStatus.IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED,
754                         "capability", capabilityDef
755                         .getName()
756                         .toLowerCase(), parentResourceName);
757                 }
758             }
759             if (moduleCapabilities.size() > 0) {
760                 resource.setCapabilities(moduleCapabilities);
761             }
762         }
763     }
764
765     private Map<String, String> getCapName2Type(Resource parentResource) {
766         Map<String, String> capName2type = new HashMap<>();
767         if (parentResource != null) {
768             Map<String, List<CapabilityDefinition>> capabilities = parentResource.getCapabilities();
769             if (capabilities != null) {
770                 for (List<CapabilityDefinition> capDefinitions : capabilities.values()) {
771                     for (CapabilityDefinition capDefinition : capDefinitions) {
772                         String nameLowerCase = capDefinition.getName().toLowerCase();
773                         if (capName2type.get(nameLowerCase) != null) {
774                             String parentResourceName = parentResource.getName();
775                             log.debug("Resource with name {} has more than one capability with name {}, ignoring case",
776                                 parentResourceName, nameLowerCase);
777                             BeEcompErrorManager.getInstance()
778                                 .logInternalDataError("Import resource", "Parent resource " + parentResourceName
779                                         + " of imported resource has one or more capabilities with name " + nameLowerCase,
780                                     ErrorSeverity.ERROR);
781                             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
782                         }
783                         capName2type.put(nameLowerCase, capDefinition.getType());
784                     }
785                 }
786             }
787         }
788         return capName2type;
789     }
790
791     private Map<String, String> getReqName2Type(Resource parentResource) {
792         Map<String, String> reqName2type = new HashMap<>();
793         if (parentResource != null) {
794             Map<String, List<RequirementDefinition>> requirements = parentResource.getRequirements();
795             if (requirements != null) {
796                 for (List<RequirementDefinition> reqDefinitions : requirements.values()) {
797                     for (RequirementDefinition reqDefinition : reqDefinitions) {
798                         String nameLowerCase = reqDefinition.getName().toLowerCase();
799                         if (reqName2type.get(nameLowerCase) != null) {
800                             String parentResourceName = parentResource.getName();
801                             log.debug("Resource with name {} has more than one requirement with name {}, ignoring case",
802                                 parentResourceName, nameLowerCase);
803                             BeEcompErrorManager.getInstance()
804                                 .logInternalDataError("Import resource", "Parent resource " + parentResourceName
805                                         + " of imported resource has one or more requirements with name " + nameLowerCase,
806                                     ErrorSeverity.ERROR);
807                             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
808                         }
809                         reqName2type.put(nameLowerCase, reqDefinition.getCapability());
810                     }
811                 }
812             }
813         }
814         return reqName2type;
815     }
816
817     private Boolean validateCapNameVsDerived(Map<String, String> parentCapName2Type, String childCapabilityType,
818                                              String reqCapName) {
819         String capNameLowerCase = reqCapName.toLowerCase();
820         log.trace("Validating capability {} vs parent resource", capNameLowerCase);
821         String parentCapType = parentCapName2Type.get(capNameLowerCase);
822         if (parentCapType != null) {
823             if (childCapabilityType.equals(parentCapType)) {
824                 log.debug(
825                     "Capability with name {} is of same type {} for imported resource and its parent - this is OK",
826                     capNameLowerCase, childCapabilityType);
827                 return true;
828             }
829             Either<Boolean, StorageOperationStatus> capabilityTypeDerivedFrom = capabilityTypeOperation
830                 .isCapabilityTypeDerivedFrom(childCapabilityType, parentCapType);
831             if (capabilityTypeDerivedFrom.isRight()) {
832                 log.debug("Couldn't check whether imported resource capability derives from its parent's capability");
833                 throw new ByActionStatusComponentException(
834                     componentsUtils.convertFromStorageResponse(capabilityTypeDerivedFrom
835                         .right()
836                         .value()));
837             }
838             return capabilityTypeDerivedFrom.left().value();
839         }
840         return true;
841     }
842
843     private CapabilityDefinition createCapabilityFromImportFile(Object capabilityJson) {
844
845         CapabilityDefinition capabilityDefinition = new CapabilityDefinition();
846
847         if (capabilityJson instanceof String) {
848             String capabilityJsonString = (String) capabilityJson;
849             capabilityDefinition.setType(capabilityJsonString);
850         } else if (capabilityJson instanceof Map) {
851             Map<String, Object> capabilityJsonMap = (Map<String, Object>) capabilityJson;
852             // Type
853             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
854                 capabilityDefinition
855                     .setType((String) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName()));
856             }
857             // ValidSourceTypes
858             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName())) {
859                 capabilityDefinition.setValidSourceTypes(
860                     (List<String>) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.VALID_SOURCE_TYPES
861                         .getElementName()));
862             }
863             // ValidSourceTypes
864             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName())) {
865                 capabilityDefinition.setDescription(
866                     (String) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName()));
867             }
868             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName())) {
869                 List<Object> occurrencesList = (List) capabilityJsonMap
870                     .get(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName());
871                 validateOccurrences(occurrencesList);
872                 capabilityDefinition.setMinOccurrences(occurrencesList.get(0).toString());
873                 capabilityDefinition.setMaxOccurrences(occurrencesList.get(1).toString());
874             }
875             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.PROPERTIES.getElementName())) {
876
877                 Either<Map<String, PropertyDefinition>, ResultStatusEnum> propertiesRes = ImportUtils
878                     .getProperties(capabilityJsonMap);
879                 if (propertiesRes.isRight()) {
880                     throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND);
881                 } else {
882                     propertiesRes.left()
883                         .value()
884                         .entrySet()
885                         .stream()
886                         .forEach(e -> e.getValue().setName(e.getKey().toLowerCase()));
887                     List<ComponentInstanceProperty> capabilityProperties = propertiesRes.left()
888                         .value()
889                         .values()
890                         .stream()
891                         .map(p -> new ComponentInstanceProperty(p, p
892                             .getDefaultValue(), null))
893                         .collect(Collectors.toList());
894                     capabilityDefinition.setProperties(capabilityProperties);
895                 }
896             }
897
898         } else if (!(capabilityJson instanceof List)) {
899             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML);
900         }
901         return capabilityDefinition;
902     }
903
904     private void handleImportResourceException(UploadResourceInfo resourceMetaData, User user, boolean isNormative,
905                                                RuntimeException e) {
906         ResponseFormat responseFormat;
907         ComponentException newException;
908         if (e instanceof ComponentException) {
909             ComponentException componentException = (ComponentException) e;
910             responseFormat = componentException.getResponseFormat();
911             if (responseFormat == null) {
912                 responseFormat = getResponseFormatManager()
913                     .getResponseFormat(componentException.getActionStatus(), componentException.getParams());
914             }
915             newException = componentException;
916         } else {
917             responseFormat = getResponseFormatManager().getResponseFormat(ActionStatus.GENERAL_ERROR);
918             newException = new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
919         }
920         String payloadName = (resourceMetaData != null) ? resourceMetaData.getPayloadName() : "";
921         BeEcompErrorManager.getInstance().logBeSystemError("Import Resource " + payloadName);
922         log.debug("Error when importing resource from payload:{} Exception text: {}", payloadName, e.getMessage(), e);
923         auditErrorImport(resourceMetaData, user, responseFormat, isNormative);
924         throw newException;
925     }
926
927     private void auditErrorImport(UploadResourceInfo resourceMetaData, User user, ResponseFormat errorResponseWrapper,
928                                   boolean isNormative) {
929         String version, lifeCycleState;
930         if (isNormative) {
931             version = TypeUtils.getFirstCertifiedVersionVersion();
932             lifeCycleState = LifecycleStateEnum.CERTIFIED.name();
933         } else {
934             version = "";
935             lifeCycleState = LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name();
936
937         }
938
939         String message = "";
940         if (errorResponseWrapper.getMessageId() != null) {
941             message = errorResponseWrapper.getMessageId() + ": ";
942         }
943         message += errorResponseWrapper.getFormattedMessage();
944
945         AuditEventFactory factory = new AuditImportResourceAdminEventFactory(
946             CommonAuditData.newBuilder()
947                 .status(errorResponseWrapper.getStatus())
948                 .description(message)
949                 .requestId(ThreadLocalsHolder.getUuid())
950                 .build(),
951             new ResourceCommonInfo(resourceMetaData.getName(), ComponentTypeEnum.RESOURCE.getValue()),
952             ResourceVersionInfo.newBuilder()
953                 .state(lifeCycleState)
954                 .version(version)
955                 .build(),
956             ResourceVersionInfo.newBuilder()
957                 .state("")
958                 .version("")
959                 .build(),
960             "", user, "");
961         getAuditingManager().auditEvent(factory);
962
963     }
964
965     private void setMetaDataFromJson(final UploadResourceInfo resourceMetaData, final Resource resource) {
966         this.populateResourceMetadata(resourceMetaData, resource);
967         resource.setCreatorUserId(resourceMetaData.getContactId());
968
969         final String payloadData = resourceMetaData.getPayloadData();
970         if (payloadData != null) {
971             resource.setToscaVersion(getToscaVersion(payloadData));
972             resource.setAttributes(getAttributes(payloadData));
973         }
974
975         final List<CategoryDefinition> categories = resourceMetaData.getCategories();
976         calculateResourceIsAbstract(resource, categories);
977     }
978
979     private List<AttributeDataDefinition> getAttributes(final String payloadData) {
980         final Map<String, Object> mappedToscaTemplate = decodePayload(payloadData);
981
982         final List<AttributeDataDefinition> attributeDataDefinitionList = new ArrayList<>();
983
984         final Either<Map<String, Object>, ResultStatusEnum> firstToscaMapElement = ImportUtils
985             .findFirstToscaMapElement(mappedToscaTemplate, ToscaTagNamesEnum.ATTRIBUTES);
986         if (firstToscaMapElement.isRight()) {
987             return attributeDataDefinitionList;
988         }
989         final Map<String, Object> attributes = firstToscaMapElement.left().value();
990
991         final Iterator<Entry<String, Object>> propertiesNameValue = attributes.entrySet().iterator();
992         while (propertiesNameValue.hasNext()) {
993             final Entry<String, Object> attributeNameValue = propertiesNameValue.next();
994             final Object value = attributeNameValue.getValue();
995             final String key = attributeNameValue.getKey();
996             if (value instanceof Map) {
997
998                 final Map<String, Object> attributeMap = (Map<String, Object>) value;
999
1000                 final AttributeDefinition attributeDefinition = new AttributeDefinition();
1001                 attributeDefinition.setName(key);
1002
1003                 setField(attributeMap, ToscaTagNamesEnum.DESCRIPTION, attributeDefinition::setDescription);
1004                 setField(attributeMap, ToscaTagNamesEnum.TYPE, attributeDefinition::setType);
1005                 setField(attributeMap, ToscaTagNamesEnum.STATUS, attributeDefinition::setStatus);
1006                 setField(attributeMap, ToscaTagNamesEnum.ENTRY_SCHEMA, attributeDefinition::setEntry_schema);
1007                 attributeDataDefinitionList.add(attributeDefinition);
1008             } else {
1009                 final AttributeDefinition attributeDefinition = new AttributeDefinition();
1010                 attributeDefinition.setName(key);
1011                 attributeDataDefinitionList.add(attributeDefinition);
1012             }
1013         }
1014         return attributeDataDefinitionList;
1015     }
1016
1017     private Map<String, Object> decodePayload(final String payloadData) {
1018         final String decodedPayload = new String(Base64.decodeBase64(payloadData));
1019         return (Map<String, Object>) new Yaml().load(decodedPayload);
1020     }
1021
1022     private String getToscaVersion(final String payloadData) {
1023         final Map<String, Object> mappedToscaTemplate = decodePayload(payloadData);
1024         final Either<String, ResultStatusEnum> findFirstToscaStringElement =
1025             ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
1026         return findFirstToscaStringElement.left().value();
1027     }
1028
1029     private void calculateResourceIsAbstract(Resource resource, List<CategoryDefinition> categories) {
1030         if (categories != null && !categories.isEmpty()) {
1031             CategoryDefinition categoryDef = categories.get(0);
1032             resource.setAbstract(false);
1033             if (categoryDef != null && categoryDef.getName() != null && categoryDef.getName()
1034                 .equals(Constants.ABSTRACT_CATEGORY_NAME)) {
1035                 SubCategoryDefinition subCategoryDef = categoryDef.getSubcategories().get(0);
1036                 if (subCategoryDef != null && subCategoryDef.getName().equals(Constants.ABSTRACT_SUBCATEGORY)) {
1037                     resource.setAbstract(true);
1038                 }
1039             }
1040         }
1041     }
1042
1043     private void setConstantMetaData(Resource resource, boolean shouldBeCertified) {
1044         String version;
1045         LifecycleStateEnum state;
1046         if (shouldBeCertified) {
1047             version = TypeUtils.getFirstCertifiedVersionVersion();
1048             state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE;
1049         } else {
1050             version = ImportUtils.Constants.FIRST_NON_CERTIFIED_VERSION;
1051             state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT;
1052         }
1053         resource.setVersion(version);
1054         resource.setLifecycleState(state);
1055         resource.setHighestVersion(ImportUtils.Constants.NORMATIVE_TYPE_HIGHEST_VERSION);
1056         resource.setVendorName(ImportUtils.Constants.VENDOR_NAME);
1057         resource.setVendorRelease(ImportUtils.Constants.VENDOR_RELEASE);
1058
1059     }
1060
1061     private void validateOccurrences(List<Object> occurrensesList) {
1062
1063         if (!ValidationUtils.validateListNotEmpty(occurrensesList)) {
1064             log.debug("Occurrenses list empty");
1065             throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
1066         }
1067
1068         if (occurrensesList.size() < 2) {
1069             log.debug("Occurrenses list size not 2");
1070             throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
1071         }
1072         Object minObj = occurrensesList.get(0);
1073         Object maxObj = occurrensesList.get(1);
1074         Integer minOccurrences;
1075         Integer maxOccurrences;
1076         if (minObj instanceof Integer) {
1077             minOccurrences = (Integer) minObj;
1078         } else {
1079             log.debug("Invalid occurrenses format. low_bound occurrense must be Integer {}", minObj);
1080             throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
1081         }
1082         if (minOccurrences < 0) {
1083             log.debug("Invalid occurrenses format.low_bound occurrense negative {}", minOccurrences);
1084             throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
1085         }
1086
1087         if (maxObj instanceof String) {
1088             if (!"UNBOUNDED".equals(maxObj)) {
1089                 log.debug("Invalid occurrenses format. Max occurrence is {}", maxObj);
1090                 throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
1091             }
1092         } else {
1093             if (maxObj instanceof Integer) {
1094                 maxOccurrences = (Integer) maxObj;
1095             } else {
1096                 log.debug("Invalid occurrenses format.  Max occurrence is {}", maxObj);
1097                 throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
1098             }
1099
1100             if (maxOccurrences <= 0 || maxOccurrences < minOccurrences) {
1101                 log.debug("Invalid occurrenses format.  min occurrence is {}, Max occurrence is {}", minOccurrences,
1102                     maxOccurrences);
1103                 throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
1104             }
1105         }
1106     }
1107
1108     public synchronized void init(ServletContext servletContext) {
1109         if (this.servletContext == null) {
1110             this.servletContext = servletContext;
1111             responseFormatManager = ResponseFormatManager.getInstance();
1112             resourceBusinessLogic = getResourceBL(servletContext);
1113         }
1114     }
1115
1116     public boolean isResourceExist(String resourceName) {
1117         return resourceBusinessLogic.isResourceExist(resourceName);
1118     }
1119
1120     private ResourceBusinessLogic getResourceBL(ServletContext context) {
1121         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context
1122             .getAttribute(org.openecomp.sdc.common.api.Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
1123         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
1124         return webApplicationContext.getBean(ResourceBusinessLogic.class);
1125     }
1126
1127     public ServletContext getServletContext() {
1128         return servletContext;
1129     }
1130
1131     public AuditingManager getAuditingManager() {
1132         return auditingManager;
1133     }
1134
1135     public ResponseFormatManager getResponseFormatManager() {
1136         return responseFormatManager;
1137     }
1138
1139     public void setResponseFormatManager(ResponseFormatManager responseFormatManager) {
1140         this.responseFormatManager = responseFormatManager;
1141     }
1142
1143     public ResourceBusinessLogic getResourceBusinessLogic() {
1144         return resourceBusinessLogic;
1145     }
1146
1147     @Autowired
1148     public void setResourceBusinessLogic(ResourceBusinessLogic resourceBusinessLogic) {
1149         this.resourceBusinessLogic = resourceBusinessLogic;
1150     }
1151
1152     @Autowired
1153     public void setInterfaceOperationBusinessLogic(InterfaceOperationBusinessLogic interfaceOperationBusinessLogic) {
1154         this.interfaceOperationBusinessLogic = interfaceOperationBusinessLogic;
1155     }
1156
1157     public IGraphLockOperation getGraphLockOperation() {
1158         return graphLockOperation;
1159     }
1160
1161     @Autowired
1162     public void setGraphLockOperation(IGraphLockOperation graphLockOperation) {
1163         this.graphLockOperation = graphLockOperation;
1164     }
1165
1166     public void setServletContext(ServletContext servletContext) {
1167         this.servletContext = servletContext;
1168     }
1169
1170     @Autowired
1171     public void setAuditingManager(AuditingManager auditingManager) {
1172         this.auditingManager = auditingManager;
1173     }
1174
1175 }