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