df46ef048dd2a999fa98c5f1ff217029b61941dc
[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.validation.types.GlobalValidationContext;
27 import org.openecomp.sdc.common.utils.SdcCommon;
28 import org.openecomp.sdc.datatypes.error.ErrorMessage;
29 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
30 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
31 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
32 import org.openecomp.sdc.heat.datatypes.structure.Artifact;
33 import org.openecomp.sdc.heat.datatypes.structure.HeatStructureTree;
34 import org.openecomp.sdc.logging.api.Logger;
35 import org.openecomp.sdc.logging.api.LoggerFactory;
36 import org.openecomp.sdc.tosca.services.YamlUtil;
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 -> isNotInManifestFiles(fileName))
105         .forEach(fileName -> addTreeOther(fileName));
106   }
107
108   private boolean isNotInManifestFiles(String fileName) {
109     return !manifestFiles.contains(fileName);
110   }
111
112   private void addTreeOther(String fileName) {
113     if (tree.getOther() == null) {
114       tree.setOther(new HashSet<>());
115     }
116     HeatStructureTree other = new HeatStructureTree(fileName, false);
117     fileTreeRef.put(fileName, other);
118     tree.getOther().add(other);
119   }
120
121
122   private void handleHeatContentReference(HeatStructureTree fileHeatStructureTree,
123                                           GlobalValidationContext globalContext) {
124
125     String fileName = fileHeatStructureTree.getFileName();
126
127     try (InputStream fileContent = this.heatContentMap.getFileContent(fileName)) {
128       HeatOrchestrationTemplate hot =
129           new YamlUtil().yamlToObject(fileContent, HeatOrchestrationTemplate.class);
130
131       Set<String> nestedSet = HeatTreeManagerUtil.getNestedFiles(fileName, hot, globalContext);
132       addHeatNestedFiles(fileHeatStructureTree, nestedSet);
133
134       Set<String> artifactSet = HeatTreeManagerUtil.getArtifactFiles(fileName, hot, globalContext);
135       addHeatArtifactFiles(fileHeatStructureTree, artifactSet);
136     } catch (Exception ignore) { /* invalid yaml no need to process reference */
137       logger.debug("",ignore);
138     }
139   }
140
141
142   private void addHeatArtifactFiles(HeatStructureTree fileHeatStructureTree,
143                                     Set<String> artifactSet) {
144     Artifact artifact;
145     for (String artifactName : artifactSet) {
146       FileData.Type type =
147           candidateOrphanArtifacts.get(artifactName) != null ? candidateOrphanArtifacts
148               .get(artifactName).getType() : null;
149       artifact = new Artifact(artifactName, type);
150       artifactRef.put(artifactName, artifact);
151       candidateOrphanArtifacts.remove(artifactName);
152       fileHeatStructureTree.addArtifactToArtifactList(artifact);
153     }
154   }
155
156
157   private void addHeatNestedFiles(HeatStructureTree fileHeatStructureTree, Set<String> nestedSet) {
158     HeatStructureTree childHeatStructureTree;
159     for (String nestedName : nestedSet) {
160       childHeatStructureTree = fileTreeRef.get(nestedName);
161       if (childHeatStructureTree == null) {
162         childHeatStructureTree = new HeatStructureTree();
163         childHeatStructureTree.setFileName(nestedName);
164         fileTreeRef.put(nestedName, childHeatStructureTree);
165       }
166       fileHeatStructureTree.addHeatStructureTreeToNestedHeatList(childHeatStructureTree);
167       nestedFiles.put(childHeatStructureTree.getFileName(), childHeatStructureTree);
168     }
169   }
170
171
172   /**
173    * Add errors.
174    *
175    * @param validationErrors the validation errors
176    */
177   public void addErrors(Map<String, List<ErrorMessage>> validationErrors) {
178
179     validationErrors.entrySet().stream().filter(entry -> {
180       return fileTreeRef.get(entry.getKey()) != null;
181     }).forEach(entry -> entry.getValue().stream().forEach(error ->
182         fileTreeRef.get(entry.getKey()).addErrorToErrorsList(error)));
183
184     validationErrors.entrySet().stream().filter(entry -> {
185       return artifactRef.get(entry.getKey()) != null;
186     }).forEach(entry -> artifactRef.get(entry.getKey()).setErrors(entry.getValue()));
187
188   }
189
190   /**
191    * Scan tree.
192    *
193    * @param parent the parent
194    * @param data   the data
195    */
196   public void scanTree(String parent, List<FileData> data) {
197     String fileName;
198     FileData.Type type;
199     HeatStructureTree parentHeatStructureTree;
200     HeatStructureTree fileHeatStructureTree;
201     HeatStructureTree childHeatStructureTree;
202     Artifact artifact;
203     if (parent == null) {
204       parentHeatStructureTree = new HeatStructureTree();
205       fileTreeRef.put(SdcCommon.PARENT, parentHeatStructureTree);
206     } else {
207       parentHeatStructureTree = fileTreeRef.get(parent);
208     }
209
210     for (FileData fileData : data) {
211       fileName = fileData.getFile();
212       manifestFiles.add(fileName);
213       type = fileData.getType();
214
215       if (Objects.nonNull(type) && FileData.Type.HEAT.equals(type)) {
216         fileHeatStructureTree = fileTreeRef.get(fileName);
217         if (fileHeatStructureTree == null) {
218           fileHeatStructureTree = new HeatStructureTree();
219           fileTreeRef.put(fileName, fileHeatStructureTree);
220         }
221         fileHeatStructureTree.setFileName(fileName);
222         fileHeatStructureTree.setBase(fileData.getBase());
223         fileHeatStructureTree.setType(type);
224         handleHeatContentReference(fileHeatStructureTree, null);
225         parentHeatStructureTree.addHeatToHeatList(fileHeatStructureTree);
226         if (fileData.getData() != null) {
227           scanTree(fileName, fileData.getData());
228         }
229       } else {
230         childHeatStructureTree = new HeatStructureTree();
231         childHeatStructureTree.setFileName(fileName);
232         childHeatStructureTree.setBase(fileData.getBase());
233         childHeatStructureTree.setType(type);
234         fileTreeRef.put(childHeatStructureTree.getFileName(), childHeatStructureTree);
235
236         if (type == null) {
237           parentHeatStructureTree.addOtherToOtherList(childHeatStructureTree);
238         } else if (FileData.Type.HEAT_NET.equals(type)) {
239           //parentHeatStructureTree.addNetworkToNetworkList(childHeatStructureTree);
240           networkFileToParent.put(childHeatStructureTree, parentHeatStructureTree);
241           if (fileData.getData() != null) {
242             scanTree(fileName, fileData.getData());
243           }
244           handleHeatContentReference(childHeatStructureTree, null);
245
246         } else if (FileData.Type.HEAT_VOL.equals(type)) {
247           //parentHeatStructureTree.addVolumeFileToVolumeList(childHeatStructureTree);
248           volumeFileToParent.put(childHeatStructureTree, parentHeatStructureTree);
249           if (fileData.getData() != null) {
250             scanTree(fileName, fileData.getData());
251           }
252           handleHeatContentReference(childHeatStructureTree, null);
253         } else if (FileData.Type.HEAT_ENV.equals(type)) {
254           if (parentHeatStructureTree != null && parentHeatStructureTree.getFileName() != null) {
255             parentHeatStructureTree.setEnv(childHeatStructureTree);
256           } else {
257             if (parentHeatStructureTree.getOther() == null) {
258               parentHeatStructureTree.setOther(new HashSet<>());
259             }
260             parentHeatStructureTree.getOther().add(childHeatStructureTree);
261           }
262         } else {
263           artifact = new Artifact(fileName, type);
264           if (!artifactRef.keySet().contains(fileName)) {
265             artifactRef.put(fileName, artifact);
266             candidateOrphanArtifacts.put(fileName, artifact);
267           }
268         }
269       }
270     }
271   }
272
273
274   private void addNonNestedVolumeNetworkToTree(
275       Map<HeatStructureTree, HeatStructureTree> netVolToParent, Set<String> nestedFileNames,
276       boolean isVolume) {
277     for (Map.Entry<HeatStructureTree, HeatStructureTree> entry : netVolToParent.entrySet()) {
278       HeatStructureTree netOrVolNode = entry.getKey();
279       HeatStructureTree parent = entry.getValue();
280       if (!nestedFileNames.contains(netOrVolNode.getFileName())) {
281         if (isVolume) {
282           parent.addVolumeFileToVolumeList(netOrVolNode);
283         } else {
284           parent.addNetworkToNetworkList(netOrVolNode);
285         }
286       }
287     }
288   }
289
290
291   public HeatStructureTree getTree() {
292     return tree;
293   }
294 }