2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
8 * =============================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.openecomp.sdnc.config.params.transformer.tosca;
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.fasterxml.jackson.core.JsonProcessingException;
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
32 import org.apache.commons.lang.StringUtils;
34 import org.openecomp.sdc.tosca.datatypes.model.*;
35 import org.openecomp.sdc.tosca.services.YamlUtil;
36 import org.openecomp.sdnc.config.params.data.Parameter;
37 import org.openecomp.sdnc.config.params.data.PropertyDefinition;
38 import org.openecomp.sdnc.config.params.data.RequestKey;
39 import org.openecomp.sdnc.config.params.data.ResponseKey;
40 import org.openecomp.sdnc.config.params.transformer.tosca.exceptions.ArtifactProcessorException;
43 import java.io.IOException;
44 import java.io.OutputStream;
45 import java.io.OutputStreamWriter;
47 import java.util.regex.Matcher;
48 import java.util.regex.Pattern;
50 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
52 public class ArtifactProcessorImpl implements ArtifactProcessor
54 private static final String DERIVEDFROM = "org.openecomp.genericvnf";
55 private static final EELFLogger Log = EELFManager.getInstance().getLogger(ArtifactProcessorImpl.class);
56 private static final String EQUALSENCODING = "=";
57 private static final String COLONENCODING = ":";
58 private static final String COMMAENCODING = ",";
59 private static final String GREATERTHANENCODING = ">";
60 private static final String LESSTHANENCODING = "<";
63 public void generateArtifact(PropertyDefinition artifact, OutputStream stream) throws ArtifactProcessorException
66 MDC.put(MDC_SERVICE_NAME,"ArtifactGenerator");
67 Log.info("Entered into generateArtifact");
68 if(!StringUtils.isBlank(artifact.getKind())) {
69 logArtifact(artifact);
70 ServiceTemplate serviceTemplate = new ServiceTemplate();
72 addNodeType(artifact, serviceTemplate);
74 TopologyTemplate topologyTemplate = new TopologyTemplate();
75 serviceTemplate.setTopology_template(topologyTemplate);
76 addNodeTemplate(artifact, serviceTemplate);
78 String tosca = new YamlUtil().objectToYaml(serviceTemplate);
79 OutputStreamWriter writer = new OutputStreamWriter(stream);
83 } catch (IOException e) {
84 Log.error("Error writing to outputstream", e);
85 throw new ArtifactProcessorException(e);
89 } catch (IOException e) {
90 Log.error("Error while closing outputstream writer", e);
97 Log.error("Kind in PropertyDefinition is blank or null");
98 throw new ArtifactProcessorException("Kind in PropertyDefinition is blank or null");
103 public void generateArtifact(String artifact, OutputStream stream) throws ArtifactProcessorException
105 ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
107 PropertyDefinition pd = mapper.readValue(artifact, PropertyDefinition.class);
108 generateArtifact(pd, stream);
110 catch (IOException e)
112 Log.error("Error parsing property definition content = "+ artifact,e);
113 throw new ArtifactProcessorException(e);
118 public PropertyDefinition readArtifact(String toscaArtifact) throws ArtifactProcessorException{
119 Log.info("Entered into readArtifact.");
120 Log.info("Received ToscaArtifact:\n" + toscaArtifact);
122 PropertyDefinition propertyDefinitionObj = new PropertyDefinition();
123 ServiceTemplate serviceTemplate = new YamlUtil().yamlToObject(toscaArtifact, ServiceTemplate.class);
126 Map<String, NodeType> nodeTypeMap = serviceTemplate.getNode_types();
127 Map<String, NodeTemplate> nodeTemplateMap = serviceTemplate.getTopology_template().getNode_templates();
129 String nodeTemplateName = nodeTemplateMap.keySet().toArray(new String[0])[0];
130 NodeTemplate nodeTemplate = nodeTemplateMap.get(nodeTemplateName);
131 Map<String, Object> nodeTemplateProperties = nodeTemplate.getProperties();
133 String kind = nodeTypeMap.keySet().toArray(new String[0])[0];
134 NodeType nodeType = nodeTypeMap.get(kind);
135 String version = nodeType.getVersion();
136 Log.info("ReadArtifact for "+ kind + " with version "+version);
137 propertyDefinitionObj.setKind(kind);
138 propertyDefinitionObj.setVersion(version);
140 List<Parameter> parameterList = new LinkedList<>();
142 Map<String, org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition> propertyDefinitionFromTOSCA = nodeType.getProperties();
143 if(null != propertyDefinitionFromTOSCA){
144 for (String propertyName : propertyDefinitionFromTOSCA.keySet()) {
145 org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition propertyDefinition = propertyDefinitionFromTOSCA.get(propertyName);
147 Parameter parameter = new Parameter();
148 parameter.setName(propertyName);
150 if (propertyDefinition.get_default() != null) {
151 parameter.setDefaultValue(propertyDefinition.get_default().toString());
153 parameter.setDescription(propertyDefinition.getDescription());
154 if (null != propertyDefinition.getRequired()) {
155 parameter.setRequired(propertyDefinition.getRequired());
157 parameter.setRequired(false);
160 if (StringUtils.isNotEmpty(propertyDefinition.getType())) {
161 parameter.setType(propertyDefinition.getType());
164 String propertValueExpr = (String) nodeTemplateProperties.get(propertyName);
165 String[] stringTokens = parsePropertyValueExpression(propertValueExpr);
166 String ruleType = stringTokens[0].substring(stringTokens[0].indexOf('=')+1,stringTokens[0].length()).replaceAll(">","").trim();
167 String responseExpression = stringTokens[1].substring(stringTokens[1].indexOf('=')+1,stringTokens[1].length());
168 String source = stringTokens[2].substring(stringTokens[2].indexOf('=')+1,stringTokens[2].length()).replaceAll(">","").trim();
169 String requestExpression = stringTokens[3].substring(stringTokens[3].indexOf('=')+1,stringTokens[3].length());
171 List<RequestKey> requestKeys = readRequestKeys(requestExpression);
172 List<ResponseKey> responseKeys = readResponseKeys(responseExpression);
174 parameter.setRuleType(ruleType);
175 parameter.setSource(source);
176 parameter.setRequestKeys(requestKeys);
177 parameter.setResponseKeys(responseKeys);
179 parameterList.add(parameter);
183 propertyDefinitionObj.setParameters(parameterList);
184 Log.info("Exiting from readArtifact. ");
185 return propertyDefinitionObj;
188 private List<ResponseKey> readResponseKeys(String responseExpression) throws ArtifactProcessorException {
189 Log.info("Entered into readResponseKeys.");
190 List<ResponseKey> responseKeyList = null;
192 expression = responseExpression.replaceAll("<", "").replaceAll(">", "").trim();
193 if (StringUtils.isNotEmpty(expression)) {
194 responseKeyList = new ArrayList<>();
196 String[] responseKeys = expression.split(",");
197 for (String responseKeyStr : responseKeys) {
198 ResponseKey responseKey = new ResponseKey();
200 responseKey.setUniqueKeyName(responseKeyStr.split(":")[0].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",").replaceAll(EQUALSENCODING,"=").trim());
201 responseKey.setUniqueKeyValue(responseKeyStr.split(":")[1].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",").replaceAll(EQUALSENCODING,"=").trim());
202 responseKey.setFieldKeyName(responseKeyStr.split(":")[2].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",").replaceAll(EQUALSENCODING,"=").trim());
203 } catch (ArrayIndexOutOfBoundsException e) {
204 Log.error("Invalid response attribute found :" + responseKeyStr + "due to "+e);
205 throw new ArtifactProcessorException("Invalid response attribute found :" + responseKeyStr);
207 responseKeyList.add(responseKey);
210 Log.info("Exiting from readResponseKeys.");
211 return responseKeyList;
214 private List<RequestKey> readRequestKeys(String requestExpression) {
215 Log.info("Entered into readRequestKeys.");
216 List<RequestKey> requestKeyList = null;
218 expression = requestExpression.replaceAll("<","").replaceAll(">","").trim();
219 if(StringUtils.isNotEmpty(expression)){
220 requestKeyList = new ArrayList<>();
221 String[] requestKeys = expression.split(",");
222 for(String responseKeyStr :requestKeys){
223 RequestKey requestKey = new RequestKey();
224 requestKey.setKeyName(responseKeyStr.split(":")[0].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING,":").replaceAll(COMMAENCODING,",").replaceAll(EQUALSENCODING,"=").trim());
225 requestKey.setKeyValue(responseKeyStr.split(":")[1].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING,":").replaceAll(COMMAENCODING,",").replaceAll(EQUALSENCODING,"=").trim());
226 requestKeyList.add(requestKey);
229 Log.info("Exiting from readRequestKeys.");
230 return requestKeyList;
233 private String[] parsePropertyValueExpression(String propertValueExpr) throws ArtifactProcessorException{
234 Log.info("Entered into parsePropertyValueExpression.");
235 String nodeRegex = "<(.*?)>";
236 Pattern pattern = Pattern.compile(nodeRegex, Pattern.CASE_INSENSITIVE);
237 Matcher matcher = pattern.matcher(propertValueExpr);
238 List<String> stringTokens = new ArrayList<>();
239 while(matcher.find()){
240 stringTokens.add(matcher.group(0));
242 String[] propertiesArr = new String[stringTokens.size()];
243 propertiesArr = stringTokens.toArray(propertiesArr);
244 if(propertiesArr.length!=4){
245 throw new ArtifactProcessorException("Invalid input found " + propertValueExpr);
247 Log.info("Exiting from parsePropertyValueExpression.");
248 return propertiesArr;
251 private void addNodeType(PropertyDefinition artifact, ServiceTemplate toscaTemplate) throws ArtifactProcessorException {
252 //Add basic fields for the node
253 NodeType toscaNodeType = new NodeType();
254 toscaNodeType.setDerived_from(DERIVEDFROM);
255 toscaNodeType.setVersion(artifact.getVersion());
256 toscaNodeType.setDescription("");
257 if(artifact.getParameters()!=null) {
258 Map<String, org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition> toscaPropertyMap = new HashMap<>();
259 toscaNodeType.setProperties(toscaPropertyMap);
261 //Add properties from parameters of PD
262 for (Parameter pdParameter : artifact.getParameters()) {
263 addProperty(toscaNodeType, pdParameter);
267 // This is where it adds node in node Map and adds the map in tosca template
268 Map<String,NodeType> toscaNodeMap = new HashMap<>();
269 toscaNodeMap.put(artifact.getKind(),toscaNodeType);
270 toscaTemplate.setNode_types(toscaNodeMap);
273 private void addProperty(NodeType toscaNodeType, Parameter pdParameter) throws ArtifactProcessorException {
274 if(!StringUtils.isBlank(pdParameter.getName())&& !pdParameter.getName().matches(".*\\s+.*")) {
275 Log.info("Adding parameter " + pdParameter.getName() + " in node type");
276 org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition toscaProperty = new org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition();
278 toscaProperty.setType(StringUtils.isBlank(pdParameter.getType()) ? "string" : pdParameter.getType());
279 toscaProperty.set_default(pdParameter.getDefaultValue());
281 toscaProperty.setDescription(pdParameter.getDescription());
282 toscaProperty.setRequired(pdParameter.isRequired());
284 toscaNodeType.getProperties().put(pdParameter.getName(), toscaProperty);
288 String message ="Parameter name is empty,null or contains whitespace";
290 throw new ArtifactProcessorException(message);
294 private void addNodeTemplate(PropertyDefinition artifact, ServiceTemplate toscaTemplate)
296 NodeTemplate nodeTemplate = new NodeTemplate();
297 nodeTemplate.setType(artifact.getKind());
298 Map<String,Object> templateProperties = new HashMap<>();
299 //Add properties from parameters of PD
300 if(artifact.getParameters()!=null) {
301 for (Parameter pdParameter : artifact.getParameters()) {
302 addTemplateProperty(templateProperties, pdParameter);
304 nodeTemplate.setProperties(templateProperties);
306 Map<String,NodeTemplate> nodeTemplateMap = new HashMap<>();
307 nodeTemplateMap.put(artifact.getKind()+"_Template",nodeTemplate);
308 toscaTemplate.getTopology_template().setNode_templates(nodeTemplateMap);
311 private void addTemplateProperty(Map<String,Object> templateProperties, Parameter pdParameter)
313 Log.info("Adding parameter "+ pdParameter.getName() + " in node templates");
314 String responseKeys = buildResponseKeyExpression(pdParameter.getResponseKeys());
315 String requestKeys = buildRequestKeyExpression(pdParameter.getRequestKeys());
316 String ruleType = buildRuleType(pdParameter.getRuleType());
317 String source = buildSourceSystem(pdParameter.getSource());
318 String properties = ruleType + " " + responseKeys + " " + source + " " + requestKeys;
319 templateProperties.put(pdParameter.getName(),properties);
322 protected String buildResponseKeyExpression(List<ResponseKey> responseKeys)
324 StringBuilder propertyBuilder = new StringBuilder();
325 propertyBuilder.append("<response-keys = ");
326 if(responseKeys!=null) {
327 Iterator<ResponseKey> itr = responseKeys.iterator();
328 while (itr.hasNext()) {
329 ResponseKey res = itr.next();
331 propertyBuilder.append(encode(res.getUniqueKeyName()) + ":" + encode(res.getUniqueKeyValue()) + ":" + encode(res.getFieldKeyName()));
333 propertyBuilder.append(" , ");
336 propertyBuilder.append(">");
337 return propertyBuilder.toString();
340 protected String buildRequestKeyExpression(List<RequestKey> requestKeys)
342 StringBuilder propertyBuilder = new StringBuilder();
343 propertyBuilder.append("<request-keys = ");
344 if(requestKeys!=null) {
345 Iterator<RequestKey> itr = requestKeys.iterator();
346 while (itr.hasNext()) {
347 RequestKey res = itr.next();
349 propertyBuilder.append(encode(res.getKeyName()) + ":" + encode(res.getKeyValue()));
351 propertyBuilder.append(" , ");
354 propertyBuilder.append(">");
355 return propertyBuilder.toString();
358 protected String buildRuleType(String classType)
360 StringBuilder propertyBuilder = new StringBuilder();
361 String encodedClassType = StringUtils.isBlank(encode(classType))?"":encode(classType);
362 propertyBuilder.append("<");
363 propertyBuilder.append("rule-type = "+encodedClassType);
364 propertyBuilder.append(">");
365 return propertyBuilder.toString();
368 protected String buildSourceSystem(String source)
370 StringBuilder sourceBuilder = new StringBuilder();
371 sourceBuilder.append("<source-system = ");
372 sourceBuilder.append(StringUtils.isBlank(encode(source))?"":encode(source));
373 sourceBuilder.append(">");
374 return sourceBuilder.toString();
377 protected String encode(String string)
379 String encodedString = null;
381 encodedString = string.trim().replaceAll("<", "<").replaceAll(">", ">").replaceAll(":",":").replaceAll(",",",").replaceAll("=","=");
383 return encodedString;
386 private void logArtifact(PropertyDefinition artifact)
388 ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
389 String stringArtifact=null;
392 stringArtifact = mapper.writeValueAsString(artifact);
393 Log.info("Received PropertyDefinition:\n" + stringArtifact);
395 catch (JsonProcessingException e)
397 Log.error("Exception while logging artifact:",e);