Fix OSGi wiring issues
[ccsdk/features.git] / blueprints-processor / plugin / assignment-provider / src / main / java / org / onap / ccsdk / features / assignment / processor / MdsalResourceProcessor.java
1 /*\r
2  * Copyright © 2017-2018 AT&T Intellectual Property.\r
3  * Modifications Copyright © 2018 IBM.\r
4  * \r
5  * Licensed under the Apache License, Version 2.0 (the "License");\r
6  * you may not use this file except in compliance with the License.\r
7  * You may obtain a copy of the License at\r
8  * \r
9  * http://www.apache.org/licenses/LICENSE-2.0\r
10  * \r
11  * Unless required by applicable law or agreed to in writing, software\r
12  * distributed under the License is distributed on an "AS IS" BASIS,\r
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
14  * See the License for the specific language governing permissions and\r
15  * limitations under the License.\r
16  */\r
17 \r
18 package org.onap.ccsdk.features.assignment.processor;\r
19 \r
20 import java.util.HashMap;\r
21 import java.util.List;\r
22 import java.util.Map;\r
23 import org.apache.commons.collections.CollectionUtils;\r
24 import org.apache.commons.collections.MapUtils;\r
25 import org.apache.commons.lang3.StringUtils;\r
26 import org.onap.ccsdk.features.assignment.service.ConfigAssignmentUtils;\r
27 import org.onap.ccsdk.features.model.ConfigModelConstant;\r
28 import org.onap.ccsdk.features.model.ConfigModelException;\r
29 import org.onap.ccsdk.features.model.data.ResourceAssignment;\r
30 import org.onap.ccsdk.features.model.data.dict.ResourceDefinition;\r
31 import org.onap.ccsdk.features.model.data.dict.SourcesDefinition;\r
32 import org.onap.ccsdk.features.model.service.ComponentNode;\r
33 import org.onap.ccsdk.features.model.utils.ResourceAssignmentUtils;\r
34 import org.onap.ccsdk.features.model.utils.TransformationUtils;\r
35 import org.onap.ccsdk.features.rest.adaptor.ConfigRestAdaptorConstants;\r
36 import org.onap.ccsdk.features.rest.adaptor.service.ConfigRestAdaptorService;\r
37 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;\r
38 import org.onap.ccsdk.sli.core.sli.SvcLogicException;\r
39 import com.att.eelf.configuration.EELFLogger;\r
40 import com.att.eelf.configuration.EELFManager;\r
41 import com.fasterxml.jackson.databind.JsonNode;\r
42 \r
43 public class MdsalResourceProcessor implements ComponentNode {\r
44 \r
45     private static EELFLogger logger = EELFManager.getInstance().getLogger(MdsalResourceProcessor.class);\r
46     private ConfigRestAdaptorService configRestAdaptorService;\r
47     private Map<String, ResourceDefinition> dictionaries;\r
48 \r
49     public MdsalResourceProcessor(ConfigRestAdaptorService configRestAdaptorService) {\r
50         this.configRestAdaptorService = configRestAdaptorService;\r
51     }\r
52 \r
53     @Override\r
54     public Boolean preCondition(Map<String, String> inParams, SvcLogicContext ctx, Map<String, Object> componentContext)\r
55             throws SvcLogicException {\r
56         return Boolean.TRUE;\r
57     }\r
58 \r
59     @Override\r
60     public void preProcess(Map<String, String> inParams, SvcLogicContext ctx, Map<String, Object> componentContext)\r
61             throws SvcLogicException {\r
62         // Auto-generated method stub\r
63     }\r
64 \r
65     @Override\r
66     public void process(Map<String, String> inParams, SvcLogicContext ctx) throws SvcLogicException {\r
67         // Auto-generated method stub\r
68     }\r
69 \r
70     @SuppressWarnings("unchecked")\r
71     @Override\r
72     public void process(Map<String, String> inParams, SvcLogicContext ctx, Map<String, Object> componentContext)\r
73             throws SvcLogicException {\r
74         try {\r
75             List<ResourceAssignment> batchResourceAssignment =\r
76                     (List<ResourceAssignment>) componentContext.get(ConfigModelConstant.PROPERTY_RESOURCE_ASSIGNMENTS);\r
77             dictionaries =\r
78                     (Map<String, ResourceDefinition>) componentContext.get(ConfigModelConstant.PROPERTY_DICTIONARIES);\r
79 \r
80             if (CollectionUtils.isNotEmpty(batchResourceAssignment)) {\r
81                 for (ResourceAssignment resourceAssignment : batchResourceAssignment) {\r
82                     processResourceAssignmnet(ctx, componentContext, resourceAssignment);\r
83                 }\r
84             }\r
85         } catch (Exception e) {\r
86             throw new SvcLogicException(String.format("MdsalResourceProcessor Exception : (%s) ", e), e);\r
87         }\r
88     }\r
89 \r
90     private void processResourceAssignmnet(SvcLogicContext ctx, Map<String, Object> componentContext,\r
91             ResourceAssignment resourceAssignment) throws ConfigModelException, SvcLogicException {\r
92 \r
93         try {\r
94             // Validating Resource Assignment and Dictionary Definition data\r
95             validate(resourceAssignment);\r
96 \r
97             // Check if It has Input\r
98             Object value = ConfigAssignmentUtils.getContextKeyValue(ctx, resourceAssignment.getName());\r
99             if (value != null) {\r
100                 logger.info("mdsal source template key ({}) found from input and value is ({})",\r
101                         resourceAssignment.getName(), value);\r
102                 ResourceAssignmentUtils.setResourceDataValue(componentContext, resourceAssignment, value);\r
103                 return;\r
104             }\r
105 \r
106             ResourceDefinition resourceDefinition = dictionaries.get(resourceAssignment.getDictionaryName());\r
107             SourcesDefinition sourceMdsal = resourceDefinition.getSources().get("mdsal");\r
108             String urlPath = sourceMdsal.getProperties().getUrlPath();\r
109             String path = sourceMdsal.getProperties().getPath();\r
110             Map<String, String> inputKeyMapping = sourceMdsal.getProperties().getInputKeyMapping();\r
111             Map<String, String> outputKeyMapping = sourceMdsal.getProperties().getOutputKeyMapping();\r
112 \r
113             logger.info(\r
114                     "mdsal dictionary information : urlpath ({}), path({}), inputKeyMapping ({}), outputKeyMapping ({})",\r
115                     urlPath, path, inputKeyMapping, outputKeyMapping);\r
116 \r
117             // Resolving url Variables\r
118             Map<String, Object> urlVariables = populateUrlVariables(inputKeyMapping, componentContext);\r
119             for (Map.Entry<String, Object> entry : urlVariables.entrySet()) {\r
120                 urlPath = urlPath.replaceAll("\\$" + entry.getKey(), entry.getValue().toString());\r
121             }\r
122 \r
123             String restResponse = fetchResourceFromMDSAL(urlPath);\r
124             // if restResponse is null don't call processMdsalResults to populate the value\r
125             if (StringUtils.isNotBlank(restResponse)) {\r
126                 // Processing MDSAL Response\r
127                 processMdsalResults(ctx, componentContext, resourceAssignment, sourceMdsal, restResponse);\r
128             } else {\r
129                 logger.warn("Coudn't get proper mdsal Response content ({}) for Resource Name ({}) for URI ({})",\r
130                         restResponse, resourceAssignment.getDictionaryName(), urlPath);\r
131             }\r
132 \r
133             // Check the value has populated for mandatory case\r
134             ResourceAssignmentUtils.assertTemplateKeyValueNotNull(componentContext, resourceAssignment);\r
135         } catch (Exception e) {\r
136             ResourceAssignmentUtils.setFailedResourceDataValue(componentContext, resourceAssignment, e.getMessage());\r
137             throw new SvcLogicException(\r
138                     String.format("Failed in assignments for (%s) with (%s)", resourceAssignment, e), e);\r
139         }\r
140     }\r
141 \r
142     private String fetchResourceFromMDSAL(String urlPath) {\r
143         String response = null;\r
144         try {\r
145             response = configRestAdaptorService.getResource(ConfigRestAdaptorConstants.SELECTOR_RESTCONF, urlPath,\r
146                     String.class);\r
147         } catch (Exception e) {\r
148             logger.warn("Fetching MDSAL data for URL ({}) failed with Error ({})", urlPath, e);\r
149         }\r
150         return response;\r
151     }\r
152 \r
153     private void validate(ResourceAssignment resourceAssignment) throws SvcLogicException {\r
154         if (resourceAssignment == null) {\r
155             throw new SvcLogicException("resource assignment is not defined");\r
156         }\r
157 \r
158         if (StringUtils.isBlank(resourceAssignment.getName())) {\r
159             throw new SvcLogicException("resource assignment template key is not defined");\r
160         }\r
161 \r
162         if (StringUtils.isBlank(resourceAssignment.getDictionaryName())) {\r
163             throw new SvcLogicException(\r
164                     String.format("resource assignment dictionary name is not defined for template key (%s)",\r
165                             resourceAssignment.getName()));\r
166         }\r
167 \r
168         if (!ConfigModelConstant.SOURCE_MDSAL.equalsIgnoreCase(resourceAssignment.getDictionarySource())) {\r
169             throw new SvcLogicException(String.format("resource assignment source is not mdsal, it is (%s)",\r
170                     resourceAssignment.getDictionarySource()));\r
171         }\r
172 \r
173         ResourceDefinition resourceDefinition = dictionaries.get(resourceAssignment.getDictionaryName());\r
174         if (resourceDefinition == null) {\r
175             throw new SvcLogicException(String.format("missing resource dictionary definition for name (%s)  ",\r
176                     resourceAssignment.getDictionaryName()));\r
177         }\r
178 \r
179         if (StringUtils.isBlank(resourceDefinition.getProperty().getType())) {\r
180             throw new SvcLogicException(String.format(String.format("Failed to get dictionary (%s) data type info.",\r
181                     resourceAssignment.getDictionaryName())));\r
182         }\r
183 \r
184         if (resourceDefinition.getSources() == null || resourceDefinition.getSources().get("mdsal") == null) {\r
185             throw new SvcLogicException(\r
186                     String.format("missing resource dictionary mdsal source definition for name (%s)  ",\r
187                             resourceAssignment.getDictionaryName()));\r
188         }\r
189 \r
190         SourcesDefinition sourceMdsal = resourceDefinition.getSources().get("mdsal");\r
191         if (StringUtils.isBlank(sourceMdsal.getProperties().getUrlPath())) {\r
192             throw new SvcLogicException(String.format("Failed to get request URL Path for dictionary (%s)",\r
193                     resourceAssignment.getDictionaryName()));\r
194         }\r
195 \r
196         if (StringUtils.isBlank(sourceMdsal.getProperties().getPath())) {\r
197             throw new SvcLogicException(String.format("Failed to get request Path for dictionary (%s)",\r
198                     resourceAssignment.getDictionaryName()));\r
199         }\r
200     }\r
201 \r
202     private Map<String, Object> populateUrlVariables(Map<String, String> inputKeyMapping,\r
203             Map<String, Object> componentContext) {\r
204         Map<String, Object> urlVariables = new HashMap<>();\r
205         if (MapUtils.isNotEmpty(inputKeyMapping)) {\r
206 \r
207             for (Map.Entry<String, String> mapping : inputKeyMapping.entrySet()) {\r
208                 ResourceDefinition referenceDictionaryDefinition = dictionaries.get(mapping.getValue());\r
209                 Object expressionValue =\r
210                         ResourceAssignmentUtils.getDictionaryKeyValue(componentContext, referenceDictionaryDefinition);\r
211                 logger.trace("Reference dictionary key ({}), value ({})", mapping.getKey(), expressionValue);\r
212                 urlVariables.put(mapping.getKey(), expressionValue);\r
213             }\r
214         }\r
215         return urlVariables;\r
216     }\r
217 \r
218     private void processMdsalResults(SvcLogicContext ctx, Map<String, Object> componentContext,\r
219             ResourceAssignment resourceAssignment, SourcesDefinition sourceMdsal, String restResponse)\r
220             throws SvcLogicException, ConfigModelException {\r
221 \r
222         Map<String, String> outputKeyMapping = sourceMdsal.getProperties().getOutputKeyMapping();\r
223         JsonNode responseNode = TransformationUtils.getJsonNodeForString(restResponse);\r
224         if (StringUtils.isNotBlank(sourceMdsal.getProperties().getPath())) {\r
225             responseNode = responseNode.at(sourceMdsal.getProperties().getPath());\r
226         }\r
227         if (responseNode != null) {\r
228             ConfigAssignmentUtils.populateValueForOutputMapping(ctx, componentContext, resourceAssignment,\r
229                     outputKeyMapping, responseNode);\r
230         }\r
231     }\r
232 \r
233     @Override\r
234     public void postProcess(Map<String, String> inParams, SvcLogicContext ctx, Map<String, Object> componentContext)\r
235             throws SvcLogicException {\r
236         // Do Nothing\r
237     }\r
238 \r
239 }\r