Development of NETCONF RPCs for tr-069 adapter to
[oam/tr069-adapter.git] / acs / requestprocessor / src / main / java / org / commscope / tr069adapter / acs / requestprocessor / custom / ConfigureMultipleObject.java
1 /*
2  * ============LICENSE_START========================================================================
3  * ONAP : tr-069-adapter
4  * =================================================================================================
5  * Copyright (C) 2020 CommScope Inc Intellectual Property.
6  * =================================================================================================
7  * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You
9  * may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
14  * either express or implied. See the License for the specific language governing permissions and
15  * limitations under the License.
16  * ===============LICENSE_END=======================================================================
17  */
18
19 package org.commscope.tr069adapter.acs.requestprocessor.custom;
20
21 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.NUMBER_REGEX;
22 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.SUCCESS;
23
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29 import org.commscope.tr069adapter.acs.common.DeviceRPCRequest;
30 import org.commscope.tr069adapter.acs.common.DeviceRPCResponse;
31 import org.commscope.tr069adapter.acs.common.OperationDetails;
32 import org.commscope.tr069adapter.acs.common.OperationResponse;
33 import org.commscope.tr069adapter.acs.common.ParameterDTO;
34 import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails;
35 import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode;
36 import org.commscope.tr069adapter.acs.common.dto.TR069OperationDetails;
37 import org.commscope.tr069adapter.acs.common.exception.TR069EventProcessingException;
38 import org.commscope.tr069adapter.acs.common.response.AddObjectResponse;
39 import org.commscope.tr069adapter.acs.common.response.DeleteObjectResponse;
40 import org.commscope.tr069adapter.acs.common.response.GetParameterValueResponse;
41 import org.commscope.tr069adapter.acs.common.response.SetParameterValueResponse;
42 import org.commscope.tr069adapter.acs.requestprocessor.dao.DeviceRPCRequestRepositoryHelper;
43 import org.commscope.tr069adapter.acs.requestprocessor.dto.CustomOperationData;
44 import org.commscope.tr069adapter.acs.requestprocessor.entity.TR069DeviceRPCRequestEntity;
45 import org.commscope.tr069adapter.acs.requestprocessor.impl.TR069RequestProcessEngine;
46 import org.commscope.tr069adapter.acs.requestprocessor.util.TR069RequestProcessorUtility;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.springframework.beans.factory.annotation.Autowired;
50 import org.springframework.stereotype.Component;
51
52 @Component("ConfigureMultipleObject")
53 public class ConfigureMultipleObject implements CustomOperation {
54
55   private static final Logger logger = LoggerFactory.getLogger(ConfigureMultipleObject.class);
56
57   @Autowired
58   TR069RequestProcessEngine tr069ProcessEngine;
59
60   @Autowired
61   protected DeviceRPCRequestRepositoryHelper deviceRPCRequestRepositoryHelper;
62
63   public CustomOperationData executeCustomLogic(CustomOperationData customOperationData)
64       throws TR069EventProcessingException {
65
66     TR069DeviceDetails deviceDetails = customOperationData.getDeviceDetails();
67     DeviceRPCResponse deviceRPCResponse = customOperationData.getDeviceRPCResponse();
68     DeviceRPCRequest nbiDeviceOperationRequest = customOperationData.getDeviceRPCRequest();
69
70     logger.debug("Started processing Configure multiple object");
71     DeviceRPCRequest operRequest = null;
72     Long responseOperationId = null;
73     if (deviceRPCResponse != null && deviceRPCResponse.getOperationId() != null) {
74       responseOperationId = deviceRPCResponse.getOperationId();
75       if (deviceRPCResponse.getFaultKey() != null && responseOperationId != null
76           && responseOperationId.equals(nbiDeviceOperationRequest.getOperationId())) {
77         logger.error("The Configure Multiple Object operation has failed, Reason: {}",
78             deviceRPCResponse.getFaultString());
79
80         logger.debug(
81             "Deleting the NBI operation request for custom operation configureMultipleObjects with operation ID: {}",
82             responseOperationId);
83         List<TR069DeviceRPCRequestEntity> tr069DeviceRPCRequestEntityList =
84             deviceRPCRequestRepositoryHelper
85                 .findByDeviceIdAndOperationId(deviceDetails.getDeviceId(), responseOperationId);
86         for (TR069DeviceRPCRequestEntity tr069DeviceRPCRequestEntity : tr069DeviceRPCRequestEntityList) {
87           tr069DeviceRPCRequestEntity.setIsProcessed(Integer.valueOf(1));
88         }
89         deviceRPCRequestRepositoryHelper.saveAll(tr069DeviceRPCRequestEntityList);
90
91         OperationResponse operationResponse = new GetParameterValueResponse();
92         operationResponse.setParameterDTOs(new ArrayList<>());
93         operationResponse.setStatus(1);
94         deviceRPCResponse.setOperationResponse(operationResponse);
95
96         customOperationData.setDeviceRPCResponse(deviceRPCResponse);
97         customOperationData.setDeviceRPCRequest(null);
98         logger.debug("Finished processing Configure multiple object");
99         return customOperationData;
100       }
101     }
102
103     TR069OperationDetails tr069OperationDetails =
104         (TR069OperationDetails) nbiDeviceOperationRequest.getOpDetails();
105     List<ParameterDTO> tr069deleteParamList = tr069OperationDetails.getDeleteParamList();
106     List<ParameterDTO> tr069modifyParamList = tr069OperationDetails.getModifyParamList();
107     List<ParameterDTO> tr069setParamList = tr069OperationDetails.getSetParamList();
108
109     OperationOrder nextOperation = null;
110     boolean isPendingOperationExists = true;
111     final String NXT_OPERATION = "Next operation to be executed is : ";
112
113     if ((responseOperationId == null) || (responseOperationId != null
114         && !responseOperationId.equals(nbiDeviceOperationRequest.getOperationId()))) {
115       // Must be called from Empty HTTP request, First operation to be called
116
117       // Must be called from a different user operation, First operation to be called
118       // if response operation id is different from current
119       // nbiDevOperRequest operation id then first step is deleteObject
120
121       nextOperation = OperationOrder.DELETE_OBJECT;
122       logger.debug(NXT_OPERATION, nextOperation);
123     } else {
124       // Since the responseOperation is not null and equivalent, find the
125       // response type and the take next action
126       OperationResponse opResponse = deviceRPCResponse.getOperationResponse();
127       if (opResponse instanceof DeleteObjectResponse) {
128         logger.debug("Received delete object response");
129         if (null != tr069deleteParamList && !tr069deleteParamList.isEmpty()) {
130           int i = 0;
131           for (ParameterDTO deleteParam : tr069deleteParamList) {
132             i++;
133             if (!deleteParam.isProcessed()) {
134               deleteParam.setProcessed(true);
135             } else {
136               continue;
137             }
138             logger.debug("Persisting the NBI request for deleteObject");
139             // Update the existing NBI request
140             List<TR069DeviceRPCRequestEntity> entityList =
141                 deviceRPCRequestRepositoryHelper.findByDeviceIdAndOperationId(
142                     deviceDetails.getDeviceId(), nbiDeviceOperationRequest.getOperationId());
143             List<TR069DeviceRPCRequestEntity> tr069DeviceRPCRequestEntityList =
144                 TR069RequestProcessorUtility.convertToEntity(nbiDeviceOperationRequest);
145             for (int j = 0; j < entityList.size(); j++) {
146               tr069DeviceRPCRequestEntityList.get(j).setId(entityList.get(j).getId());
147             }
148             deviceRPCRequestRepositoryHelper.saveAll(tr069DeviceRPCRequestEntityList);
149
150             if (tr069deleteParamList.size() > i) {
151               nextOperation = OperationOrder.DELETE_OBJECT;
152               logger.debug(NXT_OPERATION, nextOperation);
153               break;
154             } else {
155               nextOperation = OperationOrder.ADD_OBJECT;
156               logger.debug(NXT_OPERATION, nextOperation);
157             }
158           }
159         } else {
160           nextOperation = OperationOrder.ADD_OBJECT;
161           logger.debug(NXT_OPERATION, nextOperation);
162         }
163       } else if (opResponse instanceof AddObjectResponse) {
164         logger.debug("Received Add object response");
165         if (null != tr069setParamList && !tr069setParamList.isEmpty()) {
166           long instanceNumber;
167           boolean addParamExist = false;
168           AddObjectResponse addObjResponse =
169               (AddObjectResponse) deviceRPCResponse.getOperationResponse();
170           List<ParameterDTO> modifyParamList = new ArrayList<>();
171           List<ParameterDTO> removeParamList = new ArrayList<>();
172           ParameterDTO addParam = null;
173
174           if (null != addObjResponse) {
175             instanceNumber = addObjResponse.getInstanceNumber();
176             String replaceIndex = null;
177             String replaceParam = null;
178
179             for (ParameterDTO setParam : tr069setParamList) {
180               if (!setParam.isProcessed()) {
181                 String paramName = setParam.getParamName();
182                 final Matcher matcher = Pattern.compile(NUMBER_REGEX).matcher(paramName);
183                 String index = null;
184                 String modifyParamName = null;
185                 String subString = null;
186                 while (matcher.find()) {
187                   index = matcher.group().substring(1, matcher.group().length() - 1);
188                   StringBuilder sb = new StringBuilder(paramName);
189                   int lastIndex = paramName.lastIndexOf(matcher.group());
190                   modifyParamName = (sb.replace(lastIndex, lastIndex + matcher.group().length(),
191                       "." + instanceNumber + ".")).toString();
192                   subString = paramName.substring(0, matcher.start()) + ".";
193                 }
194                 if (null == replaceIndex)
195                   replaceIndex = index;
196                 if (null == replaceParam)
197                   replaceParam = subString;
198                 if (null != replaceIndex && null != index && replaceIndex.equals(index)
199                     && replaceParam.equalsIgnoreCase(subString)) {
200                   setParam.setProcessed(true);
201                   modifyParamList.add(prepareParamDTO(modifyParamName, null, setParam));
202                   removeParamList.add(prepareParamDTO(null, null, setParam));
203                 } else {
204                   addParamExist = true;
205                 }
206                 if (null == addParam) {
207                   logger.debug(
208                       "The device index chosen is {} for adding the NBI tab parameter with index {}",
209                       instanceNumber, replaceIndex);
210                   addParam = prepareParamDTO(subString + replaceIndex,
211                       String.valueOf(instanceNumber), setParam);
212                 }
213               }
214             }
215           }
216           // Replace index with instance number and add in modify param list
217           if (!modifyParamList.isEmpty()) {
218             tr069modifyParamList.addAll(modifyParamList);
219           }
220           // Prepare add object param and add in set param list
221           if (null != addParam) {
222             addParam.setDataType("1");
223             tr069setParamList.add(addParam);
224           }
225           // Remove all processed set params from set param list
226           if (!removeParamList.isEmpty()) {
227             tr069setParamList.removeAll(removeParamList);
228           }
229
230           logger.debug("Persisting the NBI request for addObject");
231           List<TR069DeviceRPCRequestEntity> entityList =
232               deviceRPCRequestRepositoryHelper.findByDeviceIdAndOperationId(
233                   deviceDetails.getDeviceId(), nbiDeviceOperationRequest.getOperationId());
234           List<TR069DeviceRPCRequestEntity> tr069DeviceRPCRequestEntityList =
235               TR069RequestProcessorUtility.convertToEntity(nbiDeviceOperationRequest);
236           for (int i = 0; i < entityList.size(); i++) {
237             tr069DeviceRPCRequestEntityList.get(i).setId(entityList.get(i).getId());
238           }
239           deviceRPCRequestRepositoryHelper.saveAll(tr069DeviceRPCRequestEntityList);
240
241           if (addParamExist) {
242             nextOperation = OperationOrder.ADD_OBJECT;
243             logger.debug(NXT_OPERATION, nextOperation);
244           } else {
245             nextOperation = OperationOrder.SET_PARAMETER_VALUE;
246             logger.debug(NXT_OPERATION, nextOperation);
247           }
248         } else {
249           nextOperation = OperationOrder.SET_PARAMETER_VALUE;
250           logger.debug(NXT_OPERATION, nextOperation);
251         }
252       } else if (opResponse instanceof SetParameterValueResponse) {
253         logger.debug("Received Set parameter value response");
254         isPendingOperationExists = false;
255         for (ParameterDTO setParam : tr069modifyParamList) {
256           if (Boolean.TRUE.equals(setParam.isInitiated())
257               && Boolean.FALSE.equals(setParam.isProcessed())) {
258             setParam.setInitiated(Boolean.FALSE);
259             setParam.setProcessed(Boolean.TRUE);
260           } else if (Boolean.FALSE.equals(setParam.isInitiated())
261               && Boolean.FALSE.equals(setParam.isProcessed())) {
262             isPendingOperationExists = true;
263             nextOperation = OperationOrder.SET_PARAMETER_VALUE;
264           }
265         }
266
267         updateParamChangedFlagInDb(deviceDetails.getDeviceId(), nbiDeviceOperationRequest);
268         logger.debug("Next operation to be executed is : {}", nextOperation);
269       }
270     }
271
272     if (isPendingOperationExists) {
273       boolean checkForNextoperation = true;
274       while (checkForNextoperation) {
275         switch (nextOperation) {
276           case DELETE_OBJECT:
277             if (null != tr069deleteParamList && !tr069deleteParamList.isEmpty()) {
278               logger.debug("Started executing delete object request");
279               checkForNextoperation = false;
280               DeviceRPCRequest clonedOpRequest = cloneNBIRequest(nbiDeviceOperationRequest);
281               List<ParameterDTO> deleteParamList = new ArrayList<>();
282               // Just take the first not processed delete object from the list
283               for (ParameterDTO deleteParam : tr069deleteParamList) {
284                 if (!deleteParam.isProcessed()) {
285                   deleteParamList.add(deleteParam);
286                   break;
287                 }
288               }
289               clonedOpRequest.setOpDetails(null);
290               OperationDetails opDetails = new OperationDetails();
291               opDetails.setOpCode(TR069OperationCode.DELETE_OBJECT);
292               opDetails.setParmeters(deleteParamList);
293               clonedOpRequest.setOpDetails(opDetails);
294               operRequest = clonedOpRequest;
295             } else {
296               nextOperation = OperationOrder.ADD_OBJECT;
297               logger.debug(NXT_OPERATION, nextOperation);
298             }
299             break;
300           case ADD_OBJECT:
301             if (null != tr069setParamList && !tr069setParamList.isEmpty()) {
302               logger.debug("Started executing Add object request");
303               checkForNextoperation = false;
304               DeviceRPCRequest clonedOpRequest = cloneNBIRequest(nbiDeviceOperationRequest);
305               List<ParameterDTO> addParamList = new ArrayList<>();
306               // Just take the first not processed delete object from the list
307               for (ParameterDTO addParam : tr069setParamList) {
308                 if (!addParam.isProcessed()) {
309                   String addParamMO = null;
310                   final Matcher matcher =
311                       Pattern.compile(NUMBER_REGEX).matcher(addParam.getParamName());
312                   while (matcher.find()) {
313                     addParamMO = addParam.getParamName().substring(0, matcher.start()) + ".";
314                   }
315                   if (null != addParamMO) {
316                     addParamList.add(prepareParamDTO(addParamMO, null, addParam));
317                   }
318                   break;
319                 }
320               }
321               clonedOpRequest.setOpDetails(null);
322               OperationDetails opDetails = new OperationDetails();
323               opDetails.setOpCode(TR069OperationCode.ADD_OBJECT);
324               opDetails.setParmeters(addParamList);
325               clonedOpRequest.setOpDetails(opDetails);
326               operRequest = clonedOpRequest;
327             } else {
328               nextOperation = OperationOrder.SET_PARAMETER_VALUE;
329               logger.debug(NXT_OPERATION, nextOperation);
330             }
331             break;
332           case SET_PARAMETER_VALUE:
333             checkForNextoperation = false;
334             if (null != tr069modifyParamList && !tr069modifyParamList.isEmpty()) {
335               logger.debug("Started executing SPV request");
336               DeviceRPCRequest clonedOpRequest = cloneNBIRequest(nbiDeviceOperationRequest);
337               clonedOpRequest.setOpDetails(null);
338               OperationDetails opDetails = new OperationDetails();
339               opDetails.setOpCode(TR069OperationCode.SET_PARAMETER_VALUES);
340               List<ParameterDTO> unprocessedParamList = new ArrayList<>();
341               ParameterDTO adminStateParam = null;
342               for (ParameterDTO paramDTO : tr069modifyParamList) {
343                 if (!paramDTO.isProcessed()) {
344                   if (isAdminStateExists(paramDTO)) {
345                     adminStateParam = paramDTO;
346                   } else {
347                     unprocessedParamList.add(paramDTO);
348                   }
349                 }
350               }
351
352               if (null != adminStateParam && isAdminStateFalse(adminStateParam.getParamValue())) {
353                 List<ParameterDTO> adminStateParamList = new ArrayList<>();
354                 adminStateParam.setInitiated(Boolean.TRUE);
355                 adminStateParamList.add(adminStateParam);
356                 opDetails.setParmeters(adminStateParamList);
357                 updateParamChangedFlagInDb(deviceDetails.getDeviceId(), nbiDeviceOperationRequest);
358               } else if (!unprocessedParamList.isEmpty()) {
359                 setInititedFlagTrue(unprocessedParamList);
360                 opDetails.setParmeters(unprocessedParamList);
361                 updateParamChangedFlagInDb(deviceDetails.getDeviceId(), nbiDeviceOperationRequest);
362               } else if (null != adminStateParam
363                   && isAdminStateTrue(adminStateParam.getParamValue())) {
364                 List<ParameterDTO> paramList = new ArrayList<>();
365                 adminStateParam.setInitiated(Boolean.TRUE);
366                 paramList.add(adminStateParam);
367                 opDetails.setParmeters(paramList);
368                 updateParamChangedFlagInDb(deviceDetails.getDeviceId(), nbiDeviceOperationRequest);
369               } else {
370                 isPendingOperationExists = false;
371               }
372
373               clonedOpRequest.setOpDetails(opDetails);
374               operRequest = clonedOpRequest;
375             } else {
376               isPendingOperationExists = false;
377               operRequest = null;
378             }
379             break;
380           default:
381             isPendingOperationExists = false;
382             operRequest = null;
383         }
384       }
385     }
386
387     if (!isPendingOperationExists) {
388       logger.debug(
389           "No pending operation exists, hence marking the operation as processed with id {} "
390               + "and sending GetParameterValueResponse for ConfigureMultipleObjects",
391           responseOperationId);
392       List<ParameterDTO> responseParamList = new ArrayList<>();
393
394       if (tr069deleteParamList != null) {
395         for (ParameterDTO delete : tr069deleteParamList) {
396           delete.setParamValue(SUCCESS);
397           delete.setDataType("2");
398           responseParamList.add(delete);
399         }
400       }
401
402       if (tr069modifyParamList != null) {
403         for (ParameterDTO modify : tr069modifyParamList) {
404           modify.setParamValue(SUCCESS);
405           modify.setDataType("4");
406           responseParamList.add(modify);
407         }
408       }
409
410       responseParamList.addAll(tr069setParamList);
411
412       OperationResponse operationResponse = new GetParameterValueResponse();
413       operationResponse.setParameterDTOs(responseParamList);
414       if (deviceRPCResponse != null) {
415         deviceRPCResponse.setDeviceDetails(deviceDetails);
416         deviceRPCResponse.setOperationResponse(operationResponse);
417         deviceRPCResponse.setOperationId(responseOperationId);
418       }
419
420       logger.debug(
421           "Prepared operation result for custom operation Configure Multiple Objects, hence marking as processed the corresponding NBI Operation request record");
422       deviceRPCRequestRepositoryHelper.markDeviceRPCRequestAsProcessed(deviceDetails.getDeviceId(),
423           responseOperationId);
424     }
425
426     customOperationData.setDeviceRPCResponse(deviceRPCResponse);
427     customOperationData.setDeviceRPCRequest(operRequest);
428     logger.debug("Finished processing Configure multiple object");
429     return customOperationData;
430   }
431
432
433   enum OperationOrder {
434
435     SET_PARAMETER_VALUE(null), ADD_OBJECT(SET_PARAMETER_VALUE), DELETE_OBJECT(ADD_OBJECT);
436
437     OperationOrder nextOperation;
438
439     OperationOrder(OperationOrder nextOperation) {
440       this.nextOperation = nextOperation;
441     }
442
443     public OperationOrder getNextOperation() {
444       return nextOperation;
445     }
446
447   }
448
449   private DeviceRPCRequest cloneNBIRequest(DeviceRPCRequest nbiDeviceOperationRequest) {
450     return new DeviceRPCRequest(nbiDeviceOperationRequest);
451   }
452
453   private ParameterDTO prepareParamDTO(String name, String value, ParameterDTO paramDTO) {
454     ParameterDTO parameterDTO = new ParameterDTO();
455     if (null != name) {
456       parameterDTO.setParamName(name);
457     } else {
458       parameterDTO.setParamName(paramDTO.getParamName());
459     }
460     if (null != value) {
461       parameterDTO.setParamValue(value);
462     } else {
463       parameterDTO.setParamValue(paramDTO.getParamValue());
464     }
465     parameterDTO.setDataType(paramDTO.getDataType());
466     parameterDTO.setProcessed(paramDTO.isProcessed());
467
468     return parameterDTO;
469   }
470
471   private boolean isAdminStateExists(ParameterDTO paramDTO) {
472     return (paramDTO.getParamName().contains(TR069RequestProcessorUtility.ADMIN_STATE)
473         || paramDTO.getParamName().contains(TR069RequestProcessorUtility.ADMIN_STATUS));
474   }
475
476   private void updateParamChangedFlagInDb(String deviceId,
477       DeviceRPCRequest nbiDeviceOperationRequest) throws TR069EventProcessingException {
478     List<TR069DeviceRPCRequestEntity> entityList = deviceRPCRequestRepositoryHelper
479         .findByDeviceIdAndOperationId(deviceId, nbiDeviceOperationRequest.getOperationId());
480     List<TR069DeviceRPCRequestEntity> tr069DeviceRPCRequestEntityList =
481         TR069RequestProcessorUtility.convertToEntity(nbiDeviceOperationRequest);
482     for (int i = 0; i < entityList.size(); i++) {
483       tr069DeviceRPCRequestEntityList.get(i).setId(entityList.get(i).getId());
484     }
485     deviceRPCRequestRepositoryHelper.saveAll(tr069DeviceRPCRequestEntityList);
486   }
487
488   private void setInititedFlagTrue(List<ParameterDTO> unprocessedParamList) {
489     for (ParameterDTO paramDTO : unprocessedParamList) {
490       paramDTO.setInitiated(Boolean.TRUE);
491     }
492   }
493
494   private boolean isAdminStateFalse(String adminState) {
495     return (null != adminState && (adminState.equalsIgnoreCase(Boolean.FALSE.toString())
496         || adminState.equalsIgnoreCase("0")));
497   }
498
499   private boolean isAdminStateTrue(String adminState) {
500     return (null != adminState && (adminState.equalsIgnoreCase(Boolean.TRUE.toString())
501         || adminState.equalsIgnoreCase("1")));
502   }
503
504 }