Improve import and export VFC TOSCA attributes
[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             setAttributes(toscaJson, resource);
357             setRequirements(toscaJson, resource, parentResource);
358             setInterfaceLifecycle(toscaJson, resource);
359         } else {
360             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
361         }
362
363     }
364
365     private void setToscaResourceName(Map<String, Object> toscaJson, Resource resource) {
366         Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils
367             .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
368         if (toscaElement.isLeft() || toscaElement.left().value().size() == 1) {
369             String toscaResourceName = toscaElement.left().value().keySet().iterator().next();
370             resource.setToscaResourceName(toscaResourceName);
371         }
372     }
373
374     private void setInterfaceLifecycle(Map<String, Object> toscaJson, Resource resource) {
375         Either<Map<String, Object>, ResultStatusEnum> toscaInterfaces = ImportUtils
376             .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.INTERFACES);
377         if (toscaInterfaces.isLeft()) {
378             Map<String, Object> jsonInterfaces = toscaInterfaces.left().value();
379             Map<String, InterfaceDefinition> moduleInterfaces = new HashMap<>();
380             for (final Entry<String, Object> interfaceNameValue : jsonInterfaces.entrySet()) {
381                 final Either<InterfaceDefinition, ResultStatusEnum> eitherInterface =
382                     createModuleInterface(interfaceNameValue.getValue());
383                 if (eitherInterface.isRight()) {
384                     log.info("error when creating interface:{}, for resource:{}", interfaceNameValue.getKey(),
385                         resource.getName());
386                 } else {
387                     final InterfaceDefinition interfaceDefinition = eitherInterface.left().value();
388                     moduleInterfaces.put(interfaceNameValue.getKey(), interfaceDefinition);
389                 }
390
391             }
392             if (!moduleInterfaces.isEmpty()) {
393                 resource.setInterfaces(moduleInterfaces);
394             }
395         }
396     }
397
398     private Either<InterfaceDefinition, ResultStatusEnum> createModuleInterface(final Object interfaceJson) {
399         try {
400             if (interfaceJson instanceof String) {
401                 final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
402                 interfaceDefinition.setType((String) interfaceJson);
403                 return Either.left(interfaceDefinition);
404             }
405
406             if (interfaceJson instanceof Map) {
407                 final Map<String, Object> interfaceJsonMap = (Map<String, Object>) interfaceJson;
408                 final InterfaceDefinition interfaceDefinition = interfaceDefinitionHandler.create(interfaceJsonMap);
409                 return Either.left(interfaceDefinition);
410             }
411
412             return Either.right(ResultStatusEnum.GENERAL_ERROR);
413         } catch (final Exception e) {
414             BeEcompErrorManager.getInstance().logBeSystemError("Import Resource- create interface");
415             log.debug("error when creating interface, message:{}", e.getMessage(), e);
416             return Either.right(ResultStatusEnum.GENERAL_ERROR);
417         }
418     }
419
420     private void setRequirements(Map<String, Object> toscaJson, Resource resource,
421                                  Resource parentResource) {// Note that parentResource can be null
422         Either<List<Object>, ResultStatusEnum> toscaRequirements = ImportUtils
423             .findFirstToscaListElement(toscaJson, TypeUtils.ToscaTagNamesEnum.REQUIREMENTS);
424         if (toscaRequirements.isLeft()) {
425             List<Object> jsonRequirements = toscaRequirements.left().value();
426             Map<String, List<RequirementDefinition>> moduleRequirements = new HashMap<>();
427             // Checking for name duplication
428             Set<String> reqNames = new HashSet<>();
429             // Getting flattened list of capabilities of parent node - cap name
430             // to cap type
431             Map<String, String> reqName2TypeMap = getReqName2Type(parentResource);
432             for (Object jsonRequirementObj : jsonRequirements) {
433                 // Requirement
434                 Map<String, Object> requirementJsonWrapper = (Map<String, Object>) jsonRequirementObj;
435                 String requirementName = requirementJsonWrapper.keySet().iterator().next();
436                 String reqNameLowerCase = requirementName.toLowerCase();
437                 if (reqNames.contains(reqNameLowerCase)) {
438                     log.debug(
439                         "More than one requirement with same name {} (case-insensitive) in imported TOSCA file is invalid",
440                         reqNameLowerCase);
441                     throw new ByActionStatusComponentException(ActionStatus.IMPORT_DUPLICATE_REQ_CAP_NAME,
442                         "requirement", reqNameLowerCase);
443                 }
444                 reqNames.add(reqNameLowerCase);
445                 RequirementDefinition requirementDef = createRequirementFromImportFile(requirementJsonWrapper
446                     .get(requirementName));
447                 requirementDef.setName(requirementName);
448                 if (moduleRequirements.containsKey(requirementDef.getCapability())) {
449                     moduleRequirements.get(requirementDef.getCapability()).add(requirementDef);
450                 } else {
451                     List<RequirementDefinition> list = new ArrayList<>();
452                     list.add(requirementDef);
453                     moduleRequirements.put(requirementDef.getCapability(), list);
454                 }
455
456                 // Validating against req/cap of "derived from" node
457                 Boolean validateVsParentCap = validateCapNameVsDerived(reqName2TypeMap, requirementDef
458                     .getCapability(), requirementDef.getName());
459                 if (!validateVsParentCap) {
460                     String parentResourceName = parentResource != null ? parentResource.getName() : "";
461                     log.debug("Requirement with name {} already exists in parent {}", requirementDef.getName(),
462                         parentResourceName);
463                     throw new ByActionStatusComponentException(ActionStatus.IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED,
464                         "requirement", requirementDef
465                         .getName()
466                         .toLowerCase(), parentResourceName);
467                 }
468             }
469             if (moduleRequirements.size() > 0) {
470                 resource.setRequirements(moduleRequirements);
471             }
472
473         }
474     }
475
476     private RequirementDefinition createRequirementFromImportFile(Object requirementJson) {
477         RequirementDefinition requirement = new RequirementDefinition();
478
479         if (requirementJson instanceof String) {
480             String requirementJsonString = (String) requirementJson;
481             requirement.setCapability(requirementJsonString);
482         } else if (requirementJson instanceof Map) {
483             Map<String, Object> requirementJsonMap = (Map<String, Object>) requirementJson;
484             if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.CAPABILITY.getElementName())) {
485                 requirement.setCapability(
486                     (String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.CAPABILITY.getElementName()));
487             }
488
489             if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.NODE.getElementName())) {
490                 requirement.setNode((String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.NODE.getElementName()));
491             }
492
493             if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.RELATIONSHIP.getElementName())) {
494                 requirement.setRelationship(
495                     (String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.RELATIONSHIP.getElementName()));
496             }
497             if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName())) {
498                 List<Object> occurrencesList = (List) requirementJsonMap
499                     .get(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName());
500                 validateOccurrences(occurrencesList);
501                 requirement.setMinOccurrences(occurrencesList.get(0).toString());
502                 requirement.setMaxOccurrences(occurrencesList.get(1).toString());
503             }
504         } else {
505             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML);
506         }
507         return requirement;
508     }
509
510     private void setProperties(Map<String, Object> toscaJson, Resource resource) {
511         Map<String, Object> reducedToscaJson = new HashMap<>(toscaJson);
512         ImportUtils.removeElementFromJsonMap(reducedToscaJson, "capabilities");
513         Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = ImportUtils
514             .getProperties(reducedToscaJson);
515         if (properties.isLeft()) {
516             List<PropertyDefinition> propertiesList = new ArrayList<>();
517             Map<String, PropertyDefinition> value = properties.left().value();
518             if (value != null) {
519                 for (Entry<String, PropertyDefinition> entry : value.entrySet()) {
520                     String name = entry.getKey();
521                     if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) {
522                         log.debug("The property with invalid name {} occured upon import resource {}. ", name,
523                             resource.getName());
524                         throw new ByActionStatusComponentException(componentsUtils
525                             .convertFromResultStatusEnum(ResultStatusEnum.INVALID_PROPERTY_NAME,
526                                 JsonPresentationFields.PROPERTY));
527                     }
528                     PropertyDefinition propertyDefinition = entry.getValue();
529                     propertyDefinition.setName(name);
530                     propertiesList.add(propertyDefinition);
531                 }
532             }
533             resource.setProperties(propertiesList);
534         } else if (properties.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND) {
535             throw new ByActionStatusComponentException(componentsUtils.convertFromResultStatusEnum(properties
536                 .right()
537                 .value(), JsonPresentationFields.PROPERTY));
538         }
539     }
540
541     private void setAttributes(final Map<String, Object> originalToscaJsonMap, final Resource resource) {
542         final Map<String, Object> toscaJsonMap = new HashMap<>(originalToscaJsonMap);
543         ImportUtils.removeElementFromJsonMap(toscaJsonMap, "capabilities");
544         final Either<Map<String, AttributeDefinition>, ResultStatusEnum> getAttributeEither = ImportUtils
545             .getAttributes(toscaJsonMap);
546
547         if (getAttributeEither.isRight()) {
548             final ResultStatusEnum resultStatus = getAttributeEither.right().value();
549             if (resultStatus == ResultStatusEnum.ELEMENT_NOT_FOUND) {
550                 return;
551             }
552             throw new ByActionStatusComponentException(
553                 componentsUtils.convertFromResultStatusEnum(resultStatus, JsonPresentationFields.ATTRIBUTES));
554         }
555
556         final List<AttributeDefinition> attributeDefinitionList = new ArrayList<>();
557         final Map<String, AttributeDefinition> attributeMap = getAttributeEither.left().value();
558         if (MapUtils.isEmpty(attributeMap)) {
559             return;
560         }
561         for (final Entry<String, AttributeDefinition> entry : attributeMap.entrySet()) {
562             final String name = entry.getKey();
563             if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) {
564                 log.debug("Detected attribute with invalid name '{}' during resource '{}' import. ",
565                     name, resource.getName());
566                 throw new ByActionStatusComponentException(componentsUtils
567                     .convertFromResultStatusEnum(ResultStatusEnum.INVALID_ATTRIBUTE_NAME,
568                         JsonPresentationFields.ATTRIBUTES));
569             }
570             final AttributeDefinition attributeDefinition = entry.getValue();
571             attributeDefinition.setName(name);
572             attributeDefinitionList.add(attributeDefinition);
573         }
574         resource.setAttributes(attributeDefinitionList);
575     }
576
577     private Resource setDerivedFrom(Map<String, Object> toscaJson, Resource resource) {
578         Either<String, ResultStatusEnum> toscaDerivedFromElement = ImportUtils
579             .findFirstToscaStringElement(toscaJson, TypeUtils.ToscaTagNamesEnum.DERIVED_FROM);
580         Resource derivedFromResource = null;
581         if (toscaDerivedFromElement.isLeft()) {
582             String derivedFrom = toscaDerivedFromElement.left().value();
583             log.debug("Derived from TOSCA name is {}", derivedFrom);
584             resource.setDerivedFrom(Arrays.asList(new String[]{derivedFrom}));
585             Either<Resource, StorageOperationStatus> latestByToscaResourceName = toscaOperationFacade
586                 .getLatestByToscaResourceName(derivedFrom);
587
588             if (latestByToscaResourceName.isRight()) {
589                 StorageOperationStatus operationStatus = latestByToscaResourceName.right().value();
590                 if (operationStatus == StorageOperationStatus.NOT_FOUND) {
591                     operationStatus = StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND;
592                 }
593                 log.debug("Error when fetching parent resource {}, error: {}", derivedFrom, operationStatus);
594                 ActionStatus convertFromStorageResponse = componentsUtils.convertFromStorageResponse(operationStatus);
595                 BeEcompErrorManager.getInstance()
596                     .logBeComponentMissingError("Import TOSCA YAML", "resource", derivedFrom);
597                 throw new ByActionStatusComponentException(convertFromStorageResponse, derivedFrom);
598             }
599             derivedFromResource = latestByToscaResourceName.left().value();
600         }
601         return derivedFromResource;
602     }
603
604     private void setCapabilities(Map<String, Object> toscaJson, Resource resource,
605                                  Resource parentResource) {// Note that parentResource can be null
606         Either<Map<String, Object>, ResultStatusEnum> toscaCapabilities = ImportUtils
607             .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.CAPABILITIES);
608         if (toscaCapabilities.isLeft()) {
609             Map<String, Object> jsonCapabilities = toscaCapabilities.left().value();
610             Map<String, List<CapabilityDefinition>> moduleCapabilities = new HashMap<>();
611             Iterator<Entry<String, Object>> capabilitiesNameValue = jsonCapabilities.entrySet().iterator();
612             Set<String> capNames = new HashSet<>();
613             // Getting flattened list of capabilities of parent node - cap name
614             // to cap type
615             Map<String, String> capName2TypeMap = getCapName2Type(parentResource);
616             while (capabilitiesNameValue.hasNext()) {
617                 Entry<String, Object> capabilityNameValue = capabilitiesNameValue.next();
618
619                 // Validating that no req/cap duplicates exist in imported YAML
620                 String capNameLowerCase = capabilityNameValue.getKey().toLowerCase();
621                 if (capNames.contains(capNameLowerCase)) {
622                     log.debug(
623                         "More than one capability with same name {} (case-insensitive) in imported TOSCA file is invalid",
624                         capNameLowerCase);
625                     throw new ByActionStatusComponentException(ActionStatus.IMPORT_DUPLICATE_REQ_CAP_NAME, "capability",
626                         capNameLowerCase);
627                 }
628                 capNames.add(capNameLowerCase);
629
630                 CapabilityDefinition capabilityDef = createCapabilityFromImportFile(capabilityNameValue
631                     .getValue());
632                 capabilityDef.setName(capabilityNameValue.getKey());
633                 if (moduleCapabilities.containsKey(capabilityDef.getType())) {
634                     moduleCapabilities.get(capabilityDef.getType()).add(capabilityDef);
635                 } else {
636                     List<CapabilityDefinition> list = new ArrayList<>();
637                     list.add(capabilityDef);
638                     moduleCapabilities.put(capabilityDef.getType(), list);
639                 }
640
641                 // Validating against req/cap of "derived from" node
642                 Boolean validateVsParentCap = validateCapNameVsDerived(capName2TypeMap, capabilityDef
643                     .getType(), capabilityDef.getName());
644
645                 if (!validateVsParentCap) {
646                     // Here parentResource is for sure not null, so it's
647                     // null-safe
648                     // Check added to avoid sonar warning
649                     String parentResourceName = parentResource != null ? parentResource.getName() : "";
650                     log.debug("Capability with name {} already exists in parent {}", capabilityDef.getName(),
651                         parentResourceName);
652                     throw new ByActionStatusComponentException(ActionStatus.IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED,
653                         "capability", capabilityDef
654                         .getName()
655                         .toLowerCase(), parentResourceName);
656                 }
657             }
658             if (moduleCapabilities.size() > 0) {
659                 resource.setCapabilities(moduleCapabilities);
660             }
661         }
662     }
663
664     private Map<String, String> getCapName2Type(Resource parentResource) {
665         Map<String, String> capName2type = new HashMap<>();
666         if (parentResource != null) {
667             Map<String, List<CapabilityDefinition>> capabilities = parentResource.getCapabilities();
668             if (capabilities != null) {
669                 for (List<CapabilityDefinition> capDefinitions : capabilities.values()) {
670                     for (CapabilityDefinition capDefinition : capDefinitions) {
671                         String nameLowerCase = capDefinition.getName().toLowerCase();
672                         if (capName2type.get(nameLowerCase) != null) {
673                             String parentResourceName = parentResource.getName();
674                             log.debug("Resource with name {} has more than one capability with name {}, ignoring case",
675                                 parentResourceName, nameLowerCase);
676                             BeEcompErrorManager.getInstance()
677                                 .logInternalDataError("Import resource", "Parent resource " + parentResourceName
678                                         + " of imported resource has one or more capabilities with name " + nameLowerCase,
679                                     ErrorSeverity.ERROR);
680                             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
681                         }
682                         capName2type.put(nameLowerCase, capDefinition.getType());
683                     }
684                 }
685             }
686         }
687         return capName2type;
688     }
689
690     private Map<String, String> getReqName2Type(Resource parentResource) {
691         Map<String, String> reqName2type = new HashMap<>();
692         if (parentResource != null) {
693             Map<String, List<RequirementDefinition>> requirements = parentResource.getRequirements();
694             if (requirements != null) {
695                 for (List<RequirementDefinition> reqDefinitions : requirements.values()) {
696                     for (RequirementDefinition reqDefinition : reqDefinitions) {
697                         String nameLowerCase = reqDefinition.getName().toLowerCase();
698                         if (reqName2type.get(nameLowerCase) != null) {
699                             String parentResourceName = parentResource.getName();
700                             log.debug("Resource with name {} has more than one requirement with name {}, ignoring case",
701                                 parentResourceName, nameLowerCase);
702                             BeEcompErrorManager.getInstance()
703                                 .logInternalDataError("Import resource", "Parent resource " + parentResourceName
704                                         + " of imported resource has one or more requirements with name " + nameLowerCase,
705                                     ErrorSeverity.ERROR);
706                             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
707                         }
708                         reqName2type.put(nameLowerCase, reqDefinition.getCapability());
709                     }
710                 }
711             }
712         }
713         return reqName2type;
714     }
715
716     private Boolean validateCapNameVsDerived(Map<String, String> parentCapName2Type, String childCapabilityType,
717                                              String reqCapName) {
718         String capNameLowerCase = reqCapName.toLowerCase();
719         log.trace("Validating capability {} vs parent resource", capNameLowerCase);
720         String parentCapType = parentCapName2Type.get(capNameLowerCase);
721         if (parentCapType != null) {
722             if (childCapabilityType.equals(parentCapType)) {
723                 log.debug(
724                     "Capability with name {} is of same type {} for imported resource and its parent - this is OK",
725                     capNameLowerCase, childCapabilityType);
726                 return true;
727             }
728             Either<Boolean, StorageOperationStatus> capabilityTypeDerivedFrom = capabilityTypeOperation
729                 .isCapabilityTypeDerivedFrom(childCapabilityType, parentCapType);
730             if (capabilityTypeDerivedFrom.isRight()) {
731                 log.debug("Couldn't check whether imported resource capability derives from its parent's capability");
732                 throw new ByActionStatusComponentException(
733                     componentsUtils.convertFromStorageResponse(capabilityTypeDerivedFrom
734                         .right()
735                         .value()));
736             }
737             return capabilityTypeDerivedFrom.left().value();
738         }
739         return true;
740     }
741
742     private CapabilityDefinition createCapabilityFromImportFile(Object capabilityJson) {
743
744         CapabilityDefinition capabilityDefinition = new CapabilityDefinition();
745
746         if (capabilityJson instanceof String) {
747             String capabilityJsonString = (String) capabilityJson;
748             capabilityDefinition.setType(capabilityJsonString);
749         } else if (capabilityJson instanceof Map) {
750             Map<String, Object> capabilityJsonMap = (Map<String, Object>) capabilityJson;
751             // Type
752             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
753                 capabilityDefinition
754                     .setType((String) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName()));
755             }
756             // ValidSourceTypes
757             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName())) {
758                 capabilityDefinition.setValidSourceTypes(
759                     (List<String>) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.VALID_SOURCE_TYPES
760                         .getElementName()));
761             }
762             // ValidSourceTypes
763             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName())) {
764                 capabilityDefinition.setDescription(
765                     (String) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName()));
766             }
767             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName())) {
768                 List<Object> occurrencesList = (List) capabilityJsonMap
769                     .get(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName());
770                 validateOccurrences(occurrencesList);
771                 capabilityDefinition.setMinOccurrences(occurrencesList.get(0).toString());
772                 capabilityDefinition.setMaxOccurrences(occurrencesList.get(1).toString());
773             }
774             if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.PROPERTIES.getElementName())) {
775
776                 Either<Map<String, PropertyDefinition>, ResultStatusEnum> propertiesRes = ImportUtils
777                     .getProperties(capabilityJsonMap);
778                 if (propertiesRes.isRight()) {
779                     throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND);
780                 } else {
781                     propertiesRes.left()
782                         .value()
783                         .entrySet()
784                         .stream()
785                         .forEach(e -> e.getValue().setName(e.getKey().toLowerCase()));
786                     List<ComponentInstanceProperty> capabilityProperties = propertiesRes.left()
787                         .value()
788                         .values()
789                         .stream()
790                         .map(p -> new ComponentInstanceProperty(p, p
791                             .getDefaultValue(), null))
792                         .collect(Collectors.toList());
793                     capabilityDefinition.setProperties(capabilityProperties);
794                 }
795             }
796
797         } else if (!(capabilityJson instanceof List)) {
798             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML);
799         }
800         return capabilityDefinition;
801     }
802
803     private void handleImportResourceException(UploadResourceInfo resourceMetaData, User user, boolean isNormative,
804                                                RuntimeException e) {
805         ResponseFormat responseFormat;
806         ComponentException newException;
807         if (e instanceof ComponentException) {
808             ComponentException componentException = (ComponentException) e;
809             responseFormat = componentException.getResponseFormat();
810             if (responseFormat == null) {
811                 responseFormat = getResponseFormatManager()
812                     .getResponseFormat(componentException.getActionStatus(), componentException.getParams());
813             }
814             newException = componentException;
815         } else {
816             responseFormat = getResponseFormatManager().getResponseFormat(ActionStatus.GENERAL_ERROR);
817             newException = new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
818         }
819         String payloadName = (resourceMetaData != null) ? resourceMetaData.getPayloadName() : "";
820         BeEcompErrorManager.getInstance().logBeSystemError("Import Resource " + payloadName);
821         log.debug("Error when importing resource from payload:{} Exception text: {}", payloadName, e.getMessage(), e);
822         auditErrorImport(resourceMetaData, user, responseFormat, isNormative);
823         throw newException;
824     }
825
826     private void auditErrorImport(UploadResourceInfo resourceMetaData, User user, ResponseFormat errorResponseWrapper,
827                                   boolean isNormative) {
828         String version, lifeCycleState;
829         if (isNormative) {
830             version = TypeUtils.getFirstCertifiedVersionVersion();
831             lifeCycleState = LifecycleStateEnum.CERTIFIED.name();
832         } else {
833             version = "";
834             lifeCycleState = LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name();
835
836         }
837
838         String message = "";
839         if (errorResponseWrapper.getMessageId() != null) {
840             message = errorResponseWrapper.getMessageId() + ": ";
841         }
842         message += errorResponseWrapper.getFormattedMessage();
843
844         AuditEventFactory factory = new AuditImportResourceAdminEventFactory(
845             CommonAuditData.newBuilder()
846                 .status(errorResponseWrapper.getStatus())
847                 .description(message)
848                 .requestId(ThreadLocalsHolder.getUuid())
849                 .build(),
850             new ResourceCommonInfo(resourceMetaData.getName(), ComponentTypeEnum.RESOURCE.getValue()),
851             ResourceVersionInfo.newBuilder()
852                 .state(lifeCycleState)
853                 .version(version)
854                 .build(),
855             ResourceVersionInfo.newBuilder()
856                 .state("")
857                 .version("")
858                 .build(),
859             "", user, "");
860         getAuditingManager().auditEvent(factory);
861
862     }
863
864     private void setMetaDataFromJson(final UploadResourceInfo resourceMetaData, final Resource resource) {
865         this.populateResourceMetadata(resourceMetaData, resource);
866         resource.setCreatorUserId(resourceMetaData.getContactId());
867
868         final String payloadData = resourceMetaData.getPayloadData();
869         if (payloadData != null) {
870             resource.setToscaVersion(getToscaVersion(payloadData));
871         }
872
873         final List<CategoryDefinition> categories = resourceMetaData.getCategories();
874         calculateResourceIsAbstract(resource, categories);
875     }
876
877     private Map<String, Object> decodePayload(final String payloadData) {
878         final String decodedPayload = new String(Base64.decodeBase64(payloadData));
879         return (Map<String, Object>) new Yaml().load(decodedPayload);
880     }
881
882     private String getToscaVersion(final String payloadData) {
883         final Map<String, Object> mappedToscaTemplate = decodePayload(payloadData);
884         final Either<String, ResultStatusEnum> findFirstToscaStringElement =
885             ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
886         if (findFirstToscaStringElement.isLeft()) {
887             return findFirstToscaStringElement.left().value();
888         } else {
889             return null;
890         }
891     }
892
893     private Map<String, Object> getDataTypes(final String payloadData) {
894         final Map<String, Object> mappedToscaTemplate = decodePayload(payloadData);
895         final Either<Map<String, Object>, ResultStatusEnum> findFirstToscaStringElement =
896             ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, ToscaTagNamesEnum.DATA_TYPES);
897         if (findFirstToscaStringElement.isLeft()) {
898             return findFirstToscaStringElement.left().value();
899         } else {
900             return Collections.EMPTY_MAP;
901         }
902     }
903
904     private void calculateResourceIsAbstract(Resource resource, List<CategoryDefinition> categories) {
905         if (categories != null && !categories.isEmpty()) {
906             CategoryDefinition categoryDef = categories.get(0);
907             resource.setAbstract(false);
908             if (categoryDef != null && categoryDef.getName() != null && categoryDef.getName()
909                 .equals(Constants.ABSTRACT_CATEGORY_NAME)) {
910                 SubCategoryDefinition subCategoryDef = categoryDef.getSubcategories().get(0);
911                 if (subCategoryDef != null && subCategoryDef.getName().equals(Constants.ABSTRACT_SUBCATEGORY)) {
912                     resource.setAbstract(true);
913                 }
914             }
915         }
916     }
917
918     private void setConstantMetaData(Resource resource, boolean shouldBeCertified) {
919         String version;
920         LifecycleStateEnum state;
921         if (shouldBeCertified) {
922             version = TypeUtils.getFirstCertifiedVersionVersion();
923             state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE;
924         } else {
925             version = ImportUtils.Constants.FIRST_NON_CERTIFIED_VERSION;
926             state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT;
927         }
928         resource.setVersion(version);
929         resource.setLifecycleState(state);
930         resource.setHighestVersion(ImportUtils.Constants.NORMATIVE_TYPE_HIGHEST_VERSION);
931         resource.setVendorName(ImportUtils.Constants.VENDOR_NAME);
932         resource.setVendorRelease(ImportUtils.Constants.VENDOR_RELEASE);
933
934     }
935
936     private void validateOccurrences(List<Object> occurrensesList) {
937
938         if (!ValidationUtils.validateListNotEmpty(occurrensesList)) {
939             log.debug("Occurrenses list empty");
940             throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
941         }
942
943         if (occurrensesList.size() < 2) {
944             log.debug("Occurrenses list size not 2");
945             throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
946         }
947         Object minObj = occurrensesList.get(0);
948         Object maxObj = occurrensesList.get(1);
949         Integer minOccurrences;
950         Integer maxOccurrences;
951         if (minObj instanceof Integer) {
952             minOccurrences = (Integer) minObj;
953         } else {
954             log.debug("Invalid occurrenses format. low_bound occurrense must be Integer {}", minObj);
955             throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
956         }
957         if (minOccurrences < 0) {
958             log.debug("Invalid occurrenses format.low_bound occurrense negative {}", minOccurrences);
959             throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
960         }
961
962         if (maxObj instanceof String) {
963             if (!"UNBOUNDED".equals(maxObj)) {
964                 log.debug("Invalid occurrenses format. Max occurrence is {}", maxObj);
965                 throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
966             }
967         } else {
968             if (maxObj instanceof Integer) {
969                 maxOccurrences = (Integer) maxObj;
970             } else {
971                 log.debug("Invalid occurrenses format.  Max occurrence is {}", maxObj);
972                 throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
973             }
974
975             if (maxOccurrences <= 0 || maxOccurrences < minOccurrences) {
976                 log.debug("Invalid occurrenses format.  min occurrence is {}, Max occurrence is {}", minOccurrences,
977                     maxOccurrences);
978                 throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES);
979             }
980         }
981     }
982
983     public synchronized void init(ServletContext servletContext) {
984         if (this.servletContext == null) {
985             this.servletContext = servletContext;
986             responseFormatManager = ResponseFormatManager.getInstance();
987             resourceBusinessLogic = getResourceBL(servletContext);
988         }
989     }
990
991     public boolean isResourceExist(String resourceName) {
992         return resourceBusinessLogic.isResourceExist(resourceName);
993     }
994
995     private ResourceBusinessLogic getResourceBL(ServletContext context) {
996         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context
997             .getAttribute(org.openecomp.sdc.common.api.Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
998         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
999         return webApplicationContext.getBean(ResourceBusinessLogic.class);
1000     }
1001
1002     public ServletContext getServletContext() {
1003         return servletContext;
1004     }
1005
1006     public AuditingManager getAuditingManager() {
1007         return auditingManager;
1008     }
1009
1010     public ResponseFormatManager getResponseFormatManager() {
1011         return responseFormatManager;
1012     }
1013
1014     public void setResponseFormatManager(ResponseFormatManager responseFormatManager) {
1015         this.responseFormatManager = responseFormatManager;
1016     }
1017
1018     public ResourceBusinessLogic getResourceBusinessLogic() {
1019         return resourceBusinessLogic;
1020     }
1021
1022     @Autowired
1023     public void setResourceBusinessLogic(ResourceBusinessLogic resourceBusinessLogic) {
1024         this.resourceBusinessLogic = resourceBusinessLogic;
1025     }
1026
1027     public IGraphLockOperation getGraphLockOperation() {
1028         return graphLockOperation;
1029     }
1030
1031     @Autowired
1032     public void setGraphLockOperation(IGraphLockOperation graphLockOperation) {
1033         this.graphLockOperation = graphLockOperation;
1034     }
1035
1036     public void setServletContext(ServletContext servletContext) {
1037         this.servletContext = servletContext;
1038     }
1039
1040     @Autowired
1041     public void setAuditingManager(AuditingManager auditingManager) {
1042         this.auditingManager = auditingManager;
1043     }
1044
1045     private List<DataTypeDefinition> extractDataTypeFromJson(final ResourceBusinessLogic resourceBusinessLogic,
1046                                                              final Map<String, Object> foundElements) {
1047         final List<DataTypeDefinition> dataTypeDefinitionList = new ArrayList<>();
1048         if (MapUtils.isNotEmpty(foundElements)) {
1049             final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypeCacheAll =
1050                 resourceBusinessLogic.dataTypeCache.getAll();
1051             if (dataTypeCacheAll.isLeft()) {
1052                 for (final Entry<String, Object> attributeNameValue : foundElements.entrySet()) {
1053                     final Object value = attributeNameValue.getValue();
1054                     if (value instanceof Map) {
1055                         final DataTypeDefinition dataTypeDefinition =
1056                             createDataTypeDefinitionWithName(attributeNameValue);
1057                         final DataTypeDefinition dataTypeDefinitionParent =
1058                             dataTypeCacheAll.left().value().get(dataTypeDefinition.getDerivedFromName());
1059                         dataTypeDefinition.setDerivedFrom(dataTypeDefinitionParent);
1060
1061                         dataTypeDefinitionList.add(dataTypeDefinition);
1062                     } else {
1063                         dataTypeDefinitionList.add(createDataType(String.valueOf(value)));
1064                     }
1065                 }
1066             }
1067         }
1068         return dataTypeDefinitionList;
1069     }
1070 }