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