2 * Copyright © 2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * ================================================================================
16 * Modifications copyright (c) 2019 Nokia
17 * ================================================================================
20 package org.openecomp.sdc.healing.healers;
22 import com.amdocs.zusammen.adaptor.inbound.api.types.item.Element;
23 import com.amdocs.zusammen.adaptor.inbound.api.types.item.ElementInfo;
24 import com.amdocs.zusammen.adaptor.inbound.api.types.item.ZusammenElement;
25 import com.amdocs.zusammen.datatypes.Id;
26 import com.amdocs.zusammen.datatypes.SessionContext;
27 import com.amdocs.zusammen.datatypes.item.Action;
28 import com.amdocs.zusammen.datatypes.item.ElementContext;
29 import com.amdocs.zusammen.utils.fileutils.FileUtils;
30 import org.apache.commons.io.IOUtils;
31 import org.apache.commons.lang.ArrayUtils;
32 import org.apache.commons.lang.StringUtils;
33 import org.openecomp.core.utilities.file.FileContentHandler;
34 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
35 import org.openecomp.core.zusammen.api.ZusammenAdaptor;
36 import org.openecomp.core.zusammen.api.ZusammenAdaptorFactory;
37 import org.openecomp.sdc.common.errors.CoreException;
38 import org.openecomp.sdc.common.errors.ErrorCode;
39 import org.openecomp.sdc.common.utils.CommonUtil;
40 import org.openecomp.sdc.datatypes.error.ErrorLevel;
41 import org.openecomp.sdc.datatypes.model.ElementType;
42 import org.openecomp.sdc.healing.interfaces.Healer;
43 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
44 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDaoFactory;
45 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OnboardingMethod;
46 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
47 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateEntity;
48 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
49 import org.openecomp.sdc.vendorsoftwareproduct.factory.CandidateServiceFactory;
50 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
51 import org.openecomp.sdc.vendorsoftwareproduct.services.utils.CandidateEntityBuilder;
52 import org.openecomp.sdc.versioning.dao.types.Version;
54 import java.io.ByteArrayInputStream;
55 import java.io.IOException;
56 import java.io.InputStream;
57 import java.nio.ByteBuffer;
58 import java.util.Collection;
59 import java.util.Objects;
61 import static org.openecomp.core.zusammen.api.ZusammenUtil.*;
63 public class NetworkPackageHealer implements Healer {
65 private static final byte[] EMPTY_DATA_BYTES = "{}".getBytes();
66 private static final String MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_ERROR =
67 "Vsp with invalid structure: does not contain element OrchestrationTemplateCandidate";
68 private static final String MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_CONTENT_ERROR =
69 "Vsp with invalid structure: does not contain element OrchestrationTemplateCandidateContent"
70 + " under OrchestrationTemplateCandidate";
72 private static final String MISSING_VSP_MODEL_ERROR =
73 "Vsp with invalid structure: does not contain element VspModel";
74 private static final String MISSING_ORCHESTRATION_TEMPLATE_ERROR =
75 "Vsp with invalid structure: does not contain element OrchestrationTemplate" + " under VspModel element";
76 private static final String MISSING_ORCHESTRATION_TEMPLATE_VALIDATE_DATA_ERROR =
77 "Vsp with invalid structure: does not contain element OrchestrationTemplateValidationData"
78 + " under OrchestrationTemplate element";
80 private final VendorSoftwareProductInfoDao vspInfoDao;
81 private final ZusammenAdaptor zusammenAdaptor;
82 private final CandidateEntityBuilder candidateEntityBuilder;
84 public NetworkPackageHealer() {
85 this(VendorSoftwareProductInfoDaoFactory.getInstance().createInterface(),
86 ZusammenAdaptorFactory.getInstance().createInterface(),
87 CandidateServiceFactory.getInstance().createInterface());
90 private NetworkPackageHealer(VendorSoftwareProductInfoDao vspInfoDao, ZusammenAdaptor zusammenAdaptor,
91 CandidateService candidateService) {
92 this(vspInfoDao, zusammenAdaptor, new CandidateEntityBuilder(candidateService));
95 NetworkPackageHealer(VendorSoftwareProductInfoDao vspInfoDao, ZusammenAdaptor zusammenAdaptor,
96 CandidateEntityBuilder candidateEntityBuilder) {
97 this.vspInfoDao = vspInfoDao;
98 this.zusammenAdaptor = zusammenAdaptor;
99 this.candidateEntityBuilder = candidateEntityBuilder;
103 public boolean isHealingNeeded(String itemId, Version version) {
104 return OnboardingMethod.NetworkPackage.name()
105 .equals(vspInfoDao.get(new VspDetails(itemId, version)).getOnboardingMethod())
106 && isVspMissingAddedElements(itemId, version);
110 public void heal(String itemId, Version version) throws Exception {
111 SessionContext context = createSessionContext();
112 ElementContext elementContext = new ElementContext(itemId, version.getId());
114 Element candidateElement = getElement(context, elementContext, null, ElementType.OrchestrationTemplateCandidate,
115 MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_ERROR);
117 Collection<Element> candidateSubs =
118 zusammenAdaptor.listElementData(context, elementContext, candidateElement.getElementId());
120 Id candidateValidationElementId =
121 creatIfAbsentCandidateValidationElementId(candidateSubs, context, elementContext, candidateElement);
123 Element orchestrationTemplateElement = getOrchestrationTemplateElement(context, elementContext);
125 Collection<Element> orchestrationTemplateSubs =
126 zusammenAdaptor.listElementData(context, elementContext, orchestrationTemplateElement.getElementId());
128 Id structureElementId = createIfAbsentStructureElementId(orchestrationTemplateSubs, context, elementContext,
129 orchestrationTemplateElement);
131 Element orchestrationTemplateValidationElement =
132 getOrchestrationTemplateValidationElement(orchestrationTemplateSubs);
134 OrchestrationTemplateEntity orchestrationTemplateEntity =
135 getOrchestrationTemplateEntity(orchestrationTemplateElement, orchestrationTemplateValidationElement);
137 if (StringUtils.isEmpty(orchestrationTemplateEntity.getFileSuffix())) {
141 Element candidateContentElement = getCandidateContentElement(candidateSubs);
143 VspDetails vspDetails = vspInfoDao.get(new VspDetails(itemId, version));
144 if (isEqual(orchestrationTemplateEntity, getCandidateData(candidateElement, candidateContentElement))) {
146 if (isProcessedEntityValid(orchestrationTemplateEntity)) {
147 emptyStructureElementAndSub(context, elementContext, candidateElement.getElementId(),
148 ElementType.OrchestrationTemplateCandidate, candidateContentElement.getElementId(),
149 ElementType.OrchestrationTemplateCandidateContent);
151 populateOrchestrationTemplateStructure(orchestrationTemplateElement.getData(), structureElementId,
152 vspDetails, context, elementContext);
154 emptyStructureElementAndSub(context, elementContext, orchestrationTemplateElement.getElementId(),
155 ElementType.OrchestrationTemplate, orchestrationTemplateValidationElement.getElementId(),
156 ElementType.OrchestrationTemplateValidationData);
158 populateCandidateValidationData(context, elementContext, candidateValidationElementId,
159 orchestrationTemplateEntity.getValidationData());
162 populateOrchestrationTemplateStructure(orchestrationTemplateElement.getData(), structureElementId,
163 vspDetails, context, elementContext);
167 private boolean isVspMissingAddedElements(String vspId, Version version) {
168 SessionContext context = createSessionContext();
169 ElementContext elementContext = new ElementContext(vspId, version.getId());
171 return zusammenAdaptor.listElementsByName(context, elementContext, null,
172 ElementType.OrchestrationTemplateCandidate.name()).stream().noneMatch(
173 candidateSub -> ElementType.OrchestrationTemplateCandidateValidationData.name()
174 .equals(candidateSub.getInfo().getName()));
177 private boolean isEqual(OrchestrationTemplateEntity orchestrationTemplateEntity,
178 OrchestrationTemplateCandidateData orchestrationTemplateCandidateData) {
179 return orchestrationTemplateEntity.getFileName().equals(orchestrationTemplateCandidateData.getFileName())
180 && orchestrationTemplateEntity.getFileSuffix()
181 .equals(orchestrationTemplateCandidateData.getFileSuffix());
184 private boolean isProcessedEntityValid(OrchestrationTemplateEntity orchestrationTemplateEntity) {
185 return !orchestrationTemplateEntity.getValidationData().contains(ErrorLevel.ERROR.name());
188 private void populateCandidateValidationData(SessionContext context, ElementContext elementContext,
189 Id candidateValidationElementId, String validationData) {
190 ZusammenElement candidateValidationElement =
191 buildStructuralElement(ElementType.OrchestrationTemplateCandidateValidationData, Action.UPDATE);
192 candidateValidationElement.setElementId(candidateValidationElementId);
193 candidateValidationElement.setData(new ByteArrayInputStream(validationData.getBytes()));
195 zusammenAdaptor.saveElement(context, elementContext, candidateValidationElement,
196 "Healed Orchestration Template Candidate Validation data");
199 private void populateOrchestrationTemplateStructure(InputStream processedFile, Id structureElementId,
200 VspDetails vspDetails, SessionContext context, ElementContext elementContext) throws Exception {
201 byte[] byteData = FileUtils.toByteArray(processedFile);
202 FileContentHandler contentMap = CommonUtil.validateAndUploadFileContent(OnboardingTypesEnum.ZIP, byteData);
203 OrchestrationTemplateCandidateData orchestrationTemplateEntityData =
204 candidateEntityBuilder
205 .buildCandidateEntityFromZip(vspDetails, byteData, contentMap, null);
206 String fileDataStructure = orchestrationTemplateEntityData.getFilesDataStructure();
208 ZusammenElement orchestrationTemplateStructure =
209 buildStructuralElement(ElementType.OrchestrationTemplateStructure, Action.UPDATE);
210 orchestrationTemplateStructure.setElementId(structureElementId);
211 orchestrationTemplateStructure.setData(new ByteArrayInputStream(fileDataStructure.getBytes()));
213 zusammenAdaptor.saveElement(context, elementContext, orchestrationTemplateStructure,
214 "Healed Orchestration Template Structure");
217 private Element getOrchestrationTemplateElement(SessionContext context, ElementContext elementContext) {
218 ElementInfo vspModelElement =
219 zusammenAdaptor.getElementInfoByName(context, elementContext, null, ElementType.VspModel.name())
220 .orElseThrow(() -> new CoreException(
221 new ErrorCode.ErrorCodeBuilder().withMessage(MISSING_VSP_MODEL_ERROR).build()));
223 return getElement(context, elementContext, vspModelElement.getId(), ElementType.OrchestrationTemplate,
224 MISSING_ORCHESTRATION_TEMPLATE_ERROR);
227 private Element getOrchestrationTemplateValidationElement(Collection<Element> orchestrationTemplateSubs) {
228 return orchestrationTemplateSubs.stream()
229 .filter(orchestrationTemplateSub -> ElementType.OrchestrationTemplateValidationData.name()
230 .equals(orchestrationTemplateSub.getInfo()
231 .getName())).findFirst().orElseThrow(
232 () -> new CoreException(new ErrorCode.ErrorCodeBuilder()
233 .withMessage(MISSING_ORCHESTRATION_TEMPLATE_VALIDATE_DATA_ERROR)
238 private Element getCandidateContentElement(Collection<Element> candidateSubs) {
239 return candidateSubs.stream().filter(candidateSub -> ElementType.OrchestrationTemplateCandidateContent.name()
240 .equals(candidateSub.getInfo().getName()))
241 .findFirst().orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder().withMessage(
242 MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_CONTENT_ERROR).build()));
245 private Id createIfAbsentStructureElementId(Collection<Element> orchestrationTemplateSubs, SessionContext context,
246 ElementContext elementContext, Element orchestrationTemplateElement) {
247 return orchestrationTemplateSubs.stream()
248 .filter(orchestrationTemplateSub -> ElementType.OrchestrationTemplateStructure.name()
249 .equals(orchestrationTemplateSub.getInfo()
250 .getName())).findFirst()
251 .map(Element::getElementId).orElse(addStructureSubElement(context, elementContext,
252 ElementType.OrchestrationTemplateStructure, orchestrationTemplateElement.getElementId()));
255 private Id creatIfAbsentCandidateValidationElementId(Collection<Element> candidateSubs, SessionContext context,
256 ElementContext elementContext, Element candidateElement) {
257 return candidateSubs.stream()
258 .filter(candidateSub -> ElementType.OrchestrationTemplateCandidateValidationData.name()
259 .equals(candidateSub.getInfo().getName())).findFirst()
260 .map(Element::getElementId).orElse(addStructureSubElement(context, elementContext,
261 ElementType.OrchestrationTemplateCandidateValidationData, candidateElement.getElementId()));
264 private Element getElement(SessionContext context, ElementContext elementContext, Id parentElementId,
265 ElementType elementType, String errorMessage) {
266 return zusammenAdaptor.getElementByName(context, elementContext, parentElementId, elementType.name())
267 .orElseThrow(() -> new CoreException(
268 new ErrorCode.ErrorCodeBuilder().withMessage(errorMessage).build()));
271 private OrchestrationTemplateEntity getOrchestrationTemplateEntity(Element orchestrationTemplateElement,
272 Element validationDataElement) {
273 OrchestrationTemplateEntity orchestrationTemplateEntity = new OrchestrationTemplateEntity();
275 if (isNotEmpty(orchestrationTemplateElement.getData())) {
276 orchestrationTemplateEntity
277 .setContentData(ByteBuffer.wrap(FileUtils.toByteArray(orchestrationTemplateElement.getData())));
279 orchestrationTemplateEntity
280 .setFileSuffix(validationDataElement.getInfo().getProperty(InfoPropertyName.FILE_SUFFIX.getVal()));
281 orchestrationTemplateEntity
282 .setFileName(validationDataElement.getInfo().getProperty(InfoPropertyName.FILE_NAME.getVal()));
283 if (isNotEmpty(validationDataElement.getData())) {
284 orchestrationTemplateEntity
285 .setValidationData(new String(FileUtils.toByteArray(validationDataElement.getData())));
287 return orchestrationTemplateEntity;
290 private OrchestrationTemplateCandidateData getCandidateData(Element candidateElement,
291 Element candidateContentElement) {
292 OrchestrationTemplateCandidateData candidateData = new OrchestrationTemplateCandidateData();
293 candidateData.setFilesDataStructure(new String(FileUtils.toByteArray(candidateElement.getData())));
294 candidateData.setContentData(ByteBuffer.wrap(FileUtils.toByteArray(candidateContentElement.getData())));
296 .setFileSuffix(candidateContentElement.getInfo().getProperty(InfoPropertyName.FILE_SUFFIX.getVal()));
297 candidateData.setFileName(candidateContentElement.getInfo().getProperty(InfoPropertyName.FILE_NAME.getVal()));
298 return candidateData;
301 private Id addStructureSubElement(SessionContext context, ElementContext elementContext, ElementType elementType,
302 Id parentElementId) {
303 ZusammenElement newElement = buildStructuralElement(elementType, Action.CREATE);
305 ZusammenElement parentElement = buildElement(parentElementId, Action.IGNORE);
306 parentElement.addSubElement(newElement);
308 return zusammenAdaptor.saveElement(context, elementContext, parentElement,
309 String.format("Add element %s under element id %s", elementType.name(), parentElementId))
310 .getSubElements().iterator().next().getElementId();
313 private void emptyStructureElementAndSub(SessionContext context, ElementContext elementContext, Id elementId,
314 ElementType elementType, Id subElementId, ElementType subElementType) {
315 ZusammenElement subElement = buildStructuralElement(subElementType, Action.UPDATE);
316 subElement.setElementId(subElementId);
317 subElement.setData(new ByteArrayInputStream(EMPTY_DATA_BYTES));
319 ZusammenElement element = buildStructuralElement(elementType, Action.UPDATE);
320 element.setElementId(elementId);
321 element.setData(new ByteArrayInputStream(EMPTY_DATA_BYTES));
322 element.addSubElement(subElement);
324 zusammenAdaptor.saveElement(context, elementContext, element,
325 String.format("Empty element %s and its sub element %s", elementType.name(), subElementType.name()));
328 public enum InfoPropertyName {
329 FILE_SUFFIX("fileSuffix"), FILE_NAME("fileName");
333 InfoPropertyName(String val) {
337 private String getVal() {
342 private boolean isNotEmpty(InputStream elementData) {
343 byte[] byteElementData;
344 if (Objects.isNull(elementData)) {
348 byteElementData = IOUtils.toByteArray(elementData);
349 } catch (IOException e) {
352 return !ArrayUtils.isEmpty(byteElementData);