re base code
[sdc.git] / openecomp-be / lib / openecomp-healing-lib / openecomp-sdc-healing-impl / src / main / java / org / openecomp / sdc / healing / healers / NetworkPackageHealer.java
1 /*
2  * Copyright © 2018 European Support Limited
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
17 package org.openecomp.sdc.healing.healers;
18
19 import com.amdocs.zusammen.adaptor.inbound.api.types.item.Element;
20 import com.amdocs.zusammen.adaptor.inbound.api.types.item.ElementInfo;
21 import com.amdocs.zusammen.adaptor.inbound.api.types.item.ZusammenElement;
22 import com.amdocs.zusammen.datatypes.Id;
23 import com.amdocs.zusammen.datatypes.SessionContext;
24 import com.amdocs.zusammen.datatypes.item.Action;
25 import com.amdocs.zusammen.datatypes.item.ElementContext;
26 import com.amdocs.zusammen.utils.fileutils.FileUtils;
27 import org.apache.commons.io.IOUtils;
28 import org.apache.commons.lang.ArrayUtils;
29 import org.apache.commons.lang.StringUtils;
30 import org.openecomp.core.utilities.file.FileContentHandler;
31 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
32 import org.openecomp.core.zusammen.api.ZusammenAdaptor;
33 import org.openecomp.core.zusammen.api.ZusammenAdaptorFactory;
34 import org.openecomp.sdc.common.errors.CoreException;
35 import org.openecomp.sdc.common.errors.ErrorCode;
36 import org.openecomp.sdc.common.utils.CommonUtil;
37 import org.openecomp.sdc.datatypes.error.ErrorLevel;
38 import org.openecomp.sdc.datatypes.model.ElementType;
39 import org.openecomp.sdc.healing.interfaces.Healer;
40 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
41 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDaoFactory;
42 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OnboardingMethod;
43 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
44 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateEntity;
45 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
46 import org.openecomp.sdc.vendorsoftwareproduct.factory.CandidateServiceFactory;
47 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
48 import org.openecomp.sdc.vendorsoftwareproduct.services.utils.CandidateEntityBuilder;
49 import org.openecomp.sdc.versioning.dao.types.Version;
50
51 import java.io.ByteArrayInputStream;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.nio.ByteBuffer;
55 import java.util.Collection;
56 import java.util.Objects;
57
58 import static org.openecomp.core.zusammen.api.ZusammenUtil.*;
59
60 public class NetworkPackageHealer implements Healer {
61
62   private static final byte[] EMPTY_DATA_BYTES = "{}".getBytes();
63   private static final String MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_ERROR =
64       "Vsp with invalid structure: does not contain element OrchestrationTemplateCandidate";
65   private static final String MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_CONTENT_ERROR =
66       "Vsp with invalid structure: does not contain element OrchestrationTemplateCandidateContent"
67           + " under OrchestrationTemplateCandidate";
68
69   private static final String MISSING_VSP_MODEL_ERROR =
70       "Vsp with invalid structure: does not contain element VspModel";
71   private static final String MISSING_ORCHESTRATION_TEMPLATE_ERROR =
72       "Vsp with invalid structure: does not contain element OrchestrationTemplate"
73           + " under VspModel element";
74   private static final String MISSING_ORCHESTRATION_TEMPLATE_VALIDATE_DATA_ERROR =
75       "Vsp with invalid structure: does not contain element OrchestrationTemplateValidationData"
76           + " under OrchestrationTemplate element";
77
78   private VendorSoftwareProductInfoDao vspInfoDao;
79   private ZusammenAdaptor zusammenAdaptor;
80   private CandidateService candidateService;
81
82   public NetworkPackageHealer() {
83     this.vspInfoDao = VendorSoftwareProductInfoDaoFactory.getInstance().createInterface();
84     this.zusammenAdaptor = ZusammenAdaptorFactory.getInstance().createInterface();
85     this.candidateService = CandidateServiceFactory.getInstance().createInterface();
86   }
87
88   @Override
89   public boolean isHealingNeeded(String itemId, Version version) {
90     return OnboardingMethod.NetworkPackage.name()
91         .equals(vspInfoDao.get(new VspDetails(itemId, version)).getOnboardingMethod()) &&
92         isVspMissingAddedElements(itemId, version);
93   }
94
95   @Override
96   public void heal(String itemId, Version version) throws Exception {
97     SessionContext context = createSessionContext();
98     ElementContext elementContext = new ElementContext(itemId, version.getId());
99
100     Element candidateElement =
101         getElement(context, elementContext, null, ElementType.OrchestrationTemplateCandidate,
102             MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_ERROR);
103
104     Collection<Element> candidateSubs =
105         zusammenAdaptor.listElementData(context, elementContext, candidateElement.getElementId());
106
107     Id candidateValidationElementId =
108         creatIfAbsentCandidateValidationElementId(candidateSubs, context,
109         elementContext, candidateElement);
110
111     Element orchestrationTemplateElement = getOrchestrationTemplateElement(context, elementContext);
112
113     Collection<Element> orchestrationTemplateSubs = zusammenAdaptor
114         .listElementData(context, elementContext, orchestrationTemplateElement.getElementId());
115
116     Id structureElementId = createIfAbsentStructureElementId(orchestrationTemplateSubs, context,
117         elementContext, orchestrationTemplateElement);
118
119     Element orchestrationTemplateValidationElement = getOrchestrationTemplateValidationElement
120         (orchestrationTemplateSubs);
121
122     OrchestrationTemplateEntity orchestrationTemplateEntity =
123         getOrchestrationTemplateEntity(orchestrationTemplateElement,
124             orchestrationTemplateValidationElement);
125
126     if (StringUtils.isEmpty(orchestrationTemplateEntity.getFileSuffix())) {
127       return;
128     }
129
130     Element candidateContentElement = getCandidateContentElement(candidateSubs);
131
132     VspDetails vspDetails = vspInfoDao.get(new VspDetails(itemId, version));
133     if (isEqual(orchestrationTemplateEntity,
134         getCandidateData(candidateElement, candidateContentElement))) {
135
136       if (isProcessedEntityValid(orchestrationTemplateEntity)) {
137         emptyStructureElementAndSub(context, elementContext, candidateElement.getElementId(),
138             ElementType.OrchestrationTemplateCandidate, candidateContentElement.getElementId(),
139             ElementType.OrchestrationTemplateCandidateContent);
140
141         populateOrchestrationTemplateStructure(orchestrationTemplateElement.getData(),
142             structureElementId, vspDetails, context, elementContext);
143       } else {
144         emptyStructureElementAndSub(context, elementContext,
145             orchestrationTemplateElement.getElementId(), ElementType.OrchestrationTemplate,
146             orchestrationTemplateValidationElement.getElementId(),
147             ElementType.OrchestrationTemplateValidationData);
148
149         populateCandidateValidationData(context, elementContext, candidateValidationElementId,
150             orchestrationTemplateEntity.getValidationData());
151       }
152     } else {
153       populateOrchestrationTemplateStructure(orchestrationTemplateElement.getData(),
154           structureElementId, vspDetails, context, elementContext);
155     }
156   }
157
158   private boolean isVspMissingAddedElements(String vspId, Version version) {
159     SessionContext context = createSessionContext();
160     ElementContext elementContext = new ElementContext(vspId, version.getId());
161
162     return zusammenAdaptor.listElementsByName(context, elementContext, null,
163         ElementType.OrchestrationTemplateCandidate.name()).stream()
164         .noneMatch(candidateSub -> ElementType.OrchestrationTemplateCandidateValidationData.name()
165             .equals(candidateSub.getInfo().getName()));
166   }
167
168   private boolean isEqual(OrchestrationTemplateEntity orchestrationTemplateEntity,
169                           OrchestrationTemplateCandidateData orchestrationTemplateCandidateData) {
170     return orchestrationTemplateEntity.getFileName()
171         .equals(orchestrationTemplateCandidateData.getFileName()) &&
172         orchestrationTemplateEntity.getFileSuffix()
173             .equals(orchestrationTemplateCandidateData.getFileSuffix());
174   }
175
176   private boolean isProcessedEntityValid(OrchestrationTemplateEntity orchestrationTemplateEntity) {
177     return !orchestrationTemplateEntity.getValidationData().contains(ErrorLevel.ERROR.name());
178   }
179
180   private void populateCandidateValidationData(SessionContext context,
181                                                ElementContext elementContext,
182                                                Id candidateValidationElementId,
183                                                String validationData) {
184     ZusammenElement candidateValidationElement =
185         buildStructuralElement(ElementType.OrchestrationTemplateCandidateValidationData,
186             Action.UPDATE);
187     candidateValidationElement.setElementId(candidateValidationElementId);
188     candidateValidationElement.setData(new ByteArrayInputStream(validationData.getBytes()));
189
190     zusammenAdaptor.saveElement(context, elementContext, candidateValidationElement,
191         "Healed Orchestration Template Candidate Validation data");
192   }
193
194   private void populateOrchestrationTemplateStructure(InputStream processedFile,
195                                                       Id structureElementId, VspDetails vspDetails,
196                                                       SessionContext context,
197                                                       ElementContext elementContext)
198       throws Exception {
199     byte[] byteData = FileUtils.toByteArray(processedFile);
200     FileContentHandler contentMap =
201         CommonUtil.validateAndUploadFileContent(OnboardingTypesEnum.ZIP, byteData);
202     OrchestrationTemplateCandidateData orchestrationTemplateEntityData =
203         new CandidateEntityBuilder(candidateService)
204             .buildCandidateEntityFromZip(vspDetails, byteData, contentMap, null);
205     String fileDataStructure = orchestrationTemplateEntityData.getFilesDataStructure();
206
207     ZusammenElement orchestrationTemplateStructure =
208         buildStructuralElement(ElementType.OrchestrationTemplateStructure, Action.UPDATE);
209     orchestrationTemplateStructure.setElementId(structureElementId);
210     orchestrationTemplateStructure.setData(new ByteArrayInputStream(fileDataStructure.getBytes()));
211
212     zusammenAdaptor.saveElement(context, elementContext, orchestrationTemplateStructure,
213         "Healed Orchestration Template Structure");
214   }
215
216   private Element getOrchestrationTemplateElement(SessionContext context,
217                                                   ElementContext elementContext) {
218     ElementInfo vspModelElement = zusammenAdaptor
219         .getElementInfoByName(context, elementContext, null, ElementType.VspModel.name())
220         .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder()
221             .withMessage(MISSING_VSP_MODEL_ERROR).build()));
222
223     return getElement(context, elementContext, vspModelElement.getId(),
224         ElementType.OrchestrationTemplate, MISSING_ORCHESTRATION_TEMPLATE_ERROR);
225   }
226
227   private Element getOrchestrationTemplateValidationElement(
228       Collection<Element> orchestrationTemplateSubs) {
229     return orchestrationTemplateSubs.stream()
230         .filter(orchestrationTemplateSub -> ElementType.OrchestrationTemplateValidationData.name()
231             .equals(orchestrationTemplateSub.getInfo().getName()))
232         .findFirst()
233         .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder()
234             .withMessage(MISSING_ORCHESTRATION_TEMPLATE_VALIDATE_DATA_ERROR).build()));
235
236   }
237
238   private Element getCandidateContentElement(Collection<Element> candidateSubs) {
239     return candidateSubs.stream()
240         .filter(candidateSub -> ElementType.OrchestrationTemplateCandidateContent.name()
241             .equals(candidateSub.getInfo().getName()))
242         .findFirst()
243         .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder()
244             .withMessage(MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_CONTENT_ERROR).build()));
245   }
246
247   private Id createIfAbsentStructureElementId(Collection<Element> orchestrationTemplateSubs,
248                                               SessionContext context, ElementContext elementContext,
249                                               Element orchestrationTemplateElement) {
250     return orchestrationTemplateSubs.stream()
251         .filter(orchestrationTemplateSub -> ElementType.OrchestrationTemplateStructure.name()
252             .equals(orchestrationTemplateSub.getInfo().getName()))
253         .findFirst().map(Element::getElementId)
254         .orElse(addStructureSubElement(context, elementContext,
255             ElementType.OrchestrationTemplateStructure,
256             orchestrationTemplateElement.getElementId()));
257   }
258
259   private Id creatIfAbsentCandidateValidationElementId(Collection<Element> candidateSubs,
260                                                        SessionContext context, ElementContext
261                                                  elementContext, Element candidateElement) {
262     return candidateSubs.stream()
263         .filter(candidateSub -> ElementType.OrchestrationTemplateCandidateValidationData.name()
264             .equals(candidateSub.getInfo().getName()))
265         .findFirst().map(Element::getElementId)
266         .orElse(addStructureSubElement(context, elementContext,
267             ElementType.OrchestrationTemplateCandidateValidationData,
268             candidateElement.getElementId()));
269   }
270
271   private Element getElement(SessionContext context, ElementContext elementContext,
272                              Id parentElementId, ElementType elementType, String errorMessage) {
273     return zusammenAdaptor
274         .getElementByName(context, elementContext, parentElementId, elementType.name())
275         .orElseThrow(() -> new CoreException(
276             new ErrorCode.ErrorCodeBuilder().withMessage(errorMessage).build()));
277   }
278
279   private OrchestrationTemplateEntity getOrchestrationTemplateEntity(
280       Element orchestrationTemplateElement, Element validationDataElement) {
281     OrchestrationTemplateEntity orchestrationTemplateEntity = new OrchestrationTemplateEntity();
282
283     if (isNotEmpty(orchestrationTemplateElement.getData())) {
284       orchestrationTemplateEntity.setContentData(
285           ByteBuffer.wrap(FileUtils.toByteArray(orchestrationTemplateElement.getData())));
286     }
287     orchestrationTemplateEntity.setFileSuffix(
288         validationDataElement.getInfo().getProperty(InfoPropertyName.FILE_SUFFIX.getVal()));
289     orchestrationTemplateEntity.setFileName(
290         validationDataElement.getInfo().getProperty(InfoPropertyName.FILE_NAME.getVal()));
291     if (isNotEmpty(validationDataElement.getData())) {
292       orchestrationTemplateEntity
293           .setValidationData(new String(FileUtils.toByteArray(validationDataElement.getData())));
294     }
295     return orchestrationTemplateEntity;
296   }
297
298   private OrchestrationTemplateCandidateData getCandidateData(Element candidateElement,
299                                                               Element candidateContentElement) {
300     OrchestrationTemplateCandidateData candidateData = new OrchestrationTemplateCandidateData();
301     candidateData
302         .setFilesDataStructure(new String(FileUtils.toByteArray(candidateElement.getData())));
303     candidateData
304         .setContentData(ByteBuffer.wrap(FileUtils.toByteArray(candidateContentElement.getData())));
305     candidateData.setFileSuffix(
306         candidateContentElement.getInfo().getProperty(InfoPropertyName.FILE_SUFFIX.getVal()));
307     candidateData.setFileName(
308         candidateContentElement.getInfo().getProperty(InfoPropertyName.FILE_NAME.getVal()));
309     return candidateData;
310   }
311
312   private Id addStructureSubElement(SessionContext context, ElementContext elementContext,
313                                     ElementType elementType, Id parentElementId) {
314     ZusammenElement newElement = buildStructuralElement(elementType, Action.CREATE);
315
316     ZusammenElement parentElement = buildElement(parentElementId, Action.IGNORE);
317     parentElement.addSubElement(newElement);
318
319     return zusammenAdaptor.saveElement(context, elementContext, parentElement,
320         String.format("Add element %s under element id %s", elementType.name(), parentElementId))
321         .getSubElements().iterator().next().getElementId();
322   }
323
324   private void emptyStructureElementAndSub(SessionContext context, ElementContext elementContext,
325                                            Id elementId, ElementType elementType, Id subElementId,
326                                            ElementType subElementType) {
327     ZusammenElement subElement = buildStructuralElement(subElementType, Action.UPDATE);
328     subElement.setElementId(subElementId);
329     subElement.setData(new ByteArrayInputStream(EMPTY_DATA_BYTES));
330
331     ZusammenElement element = buildStructuralElement(elementType, Action.UPDATE);
332     element.setElementId(elementId);
333     element.setData(new ByteArrayInputStream(EMPTY_DATA_BYTES));
334     element.addSubElement(subElement);
335
336     zusammenAdaptor.saveElement(context, elementContext, element,
337         String.format("Empty element %s and its sub element %s", elementType.name(),
338             subElementType.name()));
339   }
340
341   public enum InfoPropertyName {
342     FILE_SUFFIX("fileSuffix"),
343     FILE_NAME("fileName");
344
345     private String val;
346
347     InfoPropertyName(String val) {
348       this.val = val;
349     }
350
351     private String getVal() {
352       return val;
353     }
354   }
355
356   private boolean isNotEmpty(InputStream elementData) {
357     byte[] byteElementData;
358     if (Objects.isNull(elementData)) {
359       return false;
360     }
361     try {
362       byteElementData = IOUtils.toByteArray(elementData);
363     } catch (IOException e) {
364       return true;
365     }
366     return !ArrayUtils.isEmpty(byteElementData);
367   }
368 }