02278acf3f5498d4c23b344b6c9db872ff4addae
[sdc.git] / openecomp-be / lib / openecomp-heat-lib / src / main / java / org / openecomp / sdc / heat / services / tree / HeatTreeManager.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  */
20
21 package org.openecomp.sdc.heat.services.tree;
22
23 import org.openecomp.core.utilities.file.FileContentHandler;
24 import org.openecomp.core.utilities.file.FileUtils;
25 import org.openecomp.core.utilities.json.JsonUtil;
26 import org.openecomp.core.utilities.yaml.YamlUtil;
27 import org.openecomp.core.validation.types.GlobalValidationContext;
28 import org.openecomp.sdc.common.utils.SdcCommon;
29 import org.openecomp.sdc.datatypes.error.ErrorMessage;
30 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
31 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
32 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
33 import org.openecomp.sdc.heat.datatypes.structure.Artifact;
34 import org.openecomp.sdc.heat.datatypes.structure.HeatStructureTree;
35 import org.openecomp.sdc.logging.api.Logger;
36 import org.openecomp.sdc.logging.api.LoggerFactory;
37
38 import java.io.InputStream;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Objects;
44 import java.util.Set;
45
46
47 public class HeatTreeManager {
48
49   private static Logger logger = (Logger) LoggerFactory.getLogger(HeatTreeManager.class);
50
51
52   private FileContentHandler heatContentMap = new FileContentHandler();
53   private byte[] manifest;
54   private HeatStructureTree tree = new HeatStructureTree();
55   private Map<String, HeatStructureTree> fileTreeRef = new HashMap<>();
56   private Map<String, Artifact> artifactRef = new HashMap<>();
57   private Map<String, Artifact> candidateOrphanArtifacts = new HashMap<>();
58   private Map<String, HeatStructureTree> nestedFiles = new HashMap<>();
59   private Map<HeatStructureTree, HeatStructureTree> volumeFileToParent = new HashMap<>();
60   private Map<HeatStructureTree, HeatStructureTree> networkFileToParent = new HashMap<>();
61   private Set<String> manifestFiles = new HashSet<>();
62
63   /**
64    * Add file.
65    *
66    * @param fileName the file name
67    * @param content  the content
68    */
69   public void addFile(String fileName, InputStream content) {
70     if (fileName.equals(SdcCommon.MANIFEST_NAME)) {
71       manifest = FileUtils.toByteArray(content);
72
73     } else {
74       heatContentMap.addFile(fileName, content);
75     }
76   }
77
78   /**
79    * Create tree.
80    */
81   public void createTree() {
82     if (manifest == null) {
83       logger.error("Missing manifest file in the zip.");
84       return;
85     }
86     ManifestContent manifestData =
87         JsonUtil.json2Object(new String(manifest), ManifestContent.class);
88     scanTree(null, manifestData.getData());
89     addNonNestedVolumeNetworkToTree(volumeFileToParent, nestedFiles.keySet(), true);
90     addNonNestedVolumeNetworkToTree(networkFileToParent, nestedFiles.keySet(), false);
91     handleOrphans();
92
93     tree = fileTreeRef.get(SdcCommon.PARENT);
94   }
95
96   private void handleOrphans() {
97     tree = fileTreeRef.get(SdcCommon.PARENT);
98     candidateOrphanArtifacts.entrySet().stream()
99         .forEach(entry -> tree.addArtifactToArtifactList(entry.getValue()));
100     nestedFiles
101         .values().stream().filter(heatStructureTree -> tree.getHeat().contains(heatStructureTree))
102         .forEach(heatStructureTree -> tree.getHeat().remove(heatStructureTree));
103
104     heatContentMap.getFileList().stream().filter(fileName -> !manifestFiles.contains(fileName))
105         .forEach(fileName -> addTreeOther(fileName));
106   }
107
108   private void addTreeOther(String fileName) {
109     if (tree.getOther() == null) {
110       tree.setOther(new HashSet<>());
111     }
112     HeatStructureTree other = new HeatStructureTree(fileName, false);
113     fileTreeRef.put(fileName, other);
114     tree.getOther().add(other);
115   }
116
117
118   private void handleHeatContentReference(String filename, HeatStructureTree fileHeatStructureTree,
119                                           GlobalValidationContext globalContext) {
120
121     String fileName = fileHeatStructureTree.getFileName();
122     InputStream fileContent = this.heatContentMap.getFileContent(fileName);
123     if (fileContent == null) {
124       return; // file exist in manifest but does not exist in zip
125     }
126     try {
127       HeatOrchestrationTemplate hot =
128           new YamlUtil().yamlToObject(fileContent, HeatOrchestrationTemplate.class);
129
130       Set<String> nestedSet = HeatTreeManagerUtil.getNestedFiles(filename, hot, globalContext);
131       addHeatNestedFiles(fileHeatStructureTree, nestedSet);
132
133       Set<String> artifactSet = HeatTreeManagerUtil.getArtifactFiles(filename, hot, globalContext);
134       addHeatArtifactFiles(fileHeatStructureTree, artifactSet);
135     } catch (Exception ignore) { /* invalid yaml no need to process reference */ }
136   }
137
138
139   private void addHeatArtifactFiles(HeatStructureTree fileHeatStructureTree,
140                                     Set<String> artifactSet) {
141     Artifact artifact;
142     for (String artifactName : artifactSet) {
143       FileData.Type type =
144           candidateOrphanArtifacts.get(artifactName) != null ? candidateOrphanArtifacts
145               .get(artifactName).getType() : null;
146       artifact = new Artifact(artifactName, type);
147       artifactRef.put(artifactName, artifact);
148       candidateOrphanArtifacts.remove(artifactName);
149       fileHeatStructureTree.addArtifactToArtifactList(artifact);
150     }
151   }
152
153
154   private void addHeatNestedFiles(HeatStructureTree fileHeatStructureTree, Set<String> nestedSet) {
155     HeatStructureTree childHeatStructureTree;
156     for (String nestedName : nestedSet) {
157       childHeatStructureTree = fileTreeRef.get(nestedName);
158       if (childHeatStructureTree == null) {
159         childHeatStructureTree = new HeatStructureTree();
160         childHeatStructureTree.setFileName(nestedName);
161         fileTreeRef.put(nestedName, childHeatStructureTree);
162       }
163       fileHeatStructureTree.addHeatStructureTreeToNestedHeatList(childHeatStructureTree);
164       nestedFiles.put(childHeatStructureTree.getFileName(), childHeatStructureTree);
165     }
166   }
167
168
169   /**
170    * Add errors.
171    *
172    * @param validationErrors the validation errors
173    */
174   public void addErrors(Map<String, List<ErrorMessage>> validationErrors) {
175
176     validationErrors.entrySet().stream().filter(entry -> {
177       return fileTreeRef.get(entry.getKey()) != null;
178     }).forEach(entry -> entry.getValue().stream().forEach(error ->
179         fileTreeRef.get(entry.getKey()).addErrorToErrorsList(error)));
180
181     validationErrors.entrySet().stream().filter(entry -> {
182       return artifactRef.get(entry.getKey()) != null;
183     }).forEach(entry -> artifactRef.get(entry.getKey()).setErrors(entry.getValue()));
184
185   }
186
187   /**
188    * Scan tree.
189    *
190    * @param parent the parent
191    * @param data   the data
192    */
193   public void scanTree(String parent, List<FileData> data) {
194     String fileName;
195     FileData.Type type;
196     HeatStructureTree parentHeatStructureTree;
197     HeatStructureTree fileHeatStructureTree;
198     HeatStructureTree childHeatStructureTree;
199     Artifact artifact;
200     if (parent == null) {
201       parentHeatStructureTree = new HeatStructureTree();
202       fileTreeRef.put(SdcCommon.PARENT, parentHeatStructureTree);
203     } else {
204       parentHeatStructureTree = fileTreeRef.get(parent);
205     }
206
207     for (FileData fileData : data) {
208       fileName = fileData.getFile();
209       manifestFiles.add(fileName);
210       type = fileData.getType();
211
212       if (Objects.nonNull(type) && FileData.Type.HEAT.equals(type)) {
213         fileHeatStructureTree = fileTreeRef.get(fileName);
214         if (fileHeatStructureTree == null) {
215           fileHeatStructureTree = new HeatStructureTree();
216           fileTreeRef.put(fileName, fileHeatStructureTree);
217         }
218         fileHeatStructureTree.setFileName(fileName);
219         fileHeatStructureTree.setBase(fileData.getBase());
220         fileHeatStructureTree.setType(type);
221         handleHeatContentReference(null, fileHeatStructureTree, null);
222         parentHeatStructureTree.addHeatToHeatList(fileHeatStructureTree);
223         if (fileData.getData() != null) {
224           scanTree(fileName, fileData.getData());
225         }
226       } else {
227         childHeatStructureTree = new HeatStructureTree();
228         childHeatStructureTree.setFileName(fileName);
229         childHeatStructureTree.setBase(fileData.getBase());
230         childHeatStructureTree.setType(type);
231         fileTreeRef.put(childHeatStructureTree.getFileName(), childHeatStructureTree);
232
233         if (type == null) {
234           parentHeatStructureTree.addOtherToOtherList(childHeatStructureTree);
235         } else if (FileData.Type.HEAT_NET.equals(type)) {
236           //parentHeatStructureTree.addNetworkToNetworkList(childHeatStructureTree);
237           networkFileToParent.put(childHeatStructureTree, parentHeatStructureTree);
238           if (fileData.getData() != null) {
239             scanTree(fileName, fileData.getData());
240           }
241
242         } else if (FileData.Type.HEAT_VOL.equals(type)) {
243           //parentHeatStructureTree.addVolumeFileToVolumeList(childHeatStructureTree);
244           volumeFileToParent.put(childHeatStructureTree, parentHeatStructureTree);
245           if (fileData.getData() != null) {
246             scanTree(fileName, fileData.getData());
247           }
248         } else if (FileData.Type.HEAT_ENV.equals(type)) {
249           if (parentHeatStructureTree != null && parentHeatStructureTree.getFileName() != null) {
250             parentHeatStructureTree.setEnv(childHeatStructureTree);
251           } else {
252             if (parentHeatStructureTree.getOther() == null) {
253               parentHeatStructureTree.setOther(new HashSet<>());
254             }
255             parentHeatStructureTree.getOther().add(childHeatStructureTree);
256           }
257         } else {
258           artifact = new Artifact(fileName, type);
259           if (!artifactRef.keySet().contains(fileName)) {
260             artifactRef.put(fileName, artifact);
261             candidateOrphanArtifacts.put(fileName, artifact);
262           }
263         }
264       }
265     }
266   }
267
268
269   private void addNonNestedVolumeNetworkToTree(
270       Map<HeatStructureTree, HeatStructureTree> netVolToParent, Set<String> nestedFileNames,
271       boolean isVolume) {
272     for (Map.Entry<HeatStructureTree, HeatStructureTree> entry : netVolToParent.entrySet()) {
273       HeatStructureTree netOrVolNode = entry.getKey();
274       HeatStructureTree parent = entry.getValue();
275       if (!nestedFileNames.contains(netOrVolNode.getFileName())) {
276         if (isVolume) {
277           parent.addVolumeFileToVolumeList(netOrVolNode);
278         } else {
279           parent.addNetworkToNetworkList(netOrVolNode);
280         }
281       }
282     }
283   }
284
285
286   public HeatStructureTree getTree() {
287     return tree;
288   }
289 }