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