docs: @Override
      public synchronized ChainData updateChain(String chainName, String[] newChannelList) throws ChannelException, ChainException {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "updateChain: " + chainName);
          }
          if (null == chainName) {
              throw new InvalidChainNameException("Null chain name");
          }
          if ((null == newChannelList) || (0 == newChannelList.length)) {
              throw new InvalidChannelNameException("Null or empty channel list");
          }
          // Verify chain config exists.
          ChainDataImpl oldChainData = chainDataMap.get(chainName);
          if (null == oldChainData) {
              InvalidChainNameException e = new InvalidChainNameException("Unable to update unknown chain, " + chainName);
              FFDCFilter.processException(e, getClass().getName() + ".updateChain", "1724", this, new Object[] { chainName });
              throw e;
          }
  
          // Verify the chain config is not currently in use by the runtime.
          Chain chain = chainRunningMap.get(chainName);
          if (chain != null) {
              ChainException e = new ChainException("Unable to update runtime chain " + chainName + ".  Destroy chain first.");
              FFDCFilter.processException(e, getClass().getName() + ".updateChain", "1733", this, new Object[] { chain });
              throw e;
          }
  
          // Verify all channel configs were found in the framework.
          ChannelData[] newChannelData = new ChannelData[newChannelList.length];
          for (int i = 0; i < newChannelList.length; i++) {
              // Build up list of new channel configs for the new chain.
              newChannelData[i] = channelDataMap.get(newChannelList[i]);
              if (null == newChannelData[i]) {
                  InvalidChannelNameException e = new InvalidChannelNameException("Unable to update chain config with unknown channel, " + newChannelList[i]);
                  FFDCFilter.processException(e, getClass().getName() + ".updateChain", "1752", this, new Object[] { newChannelList[i] });
                  throw e;
              }
          }
  
          // Ensure that new configuration is different from old one.
          ChannelData[] oldChannelDataArray = oldChainData.getChannelList();
          boolean configurationDifferent = true;
          if (oldChannelDataArray.length == newChannelData.length) {
              // Same number of channelRunningMap. Now look for exact same
              // channelRunningMap.
              String oldChannelName = null;
              String newChannelName = null;
              boolean foundOldChannel = false;
              configurationDifferent = false;
              for (int j = 0; j < oldChannelDataArray.length; j++) {
                  oldChannelName = oldChannelDataArray[j].getName();
                  foundOldChannel = false;
                  for (int k = 0; k < newChannelData.length; k++) {
                      newChannelName = newChannelData[k].getName();
                      if (oldChannelName.equals(newChannelName)) {
                          foundOldChannel = true;
                          break;
                      }
                  }
                  if (!foundOldChannel) {
                      // Never found the old channel in the new channel list.
                      configurationDifferent = true;
                      break;
                  }
              }
          }
          if (!configurationDifferent) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "Identical channel list, no update");
              }
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                  Tr.exit(tc, "updateChain");
              }
              return oldChainData;
          }
  
          // Create the new chain configuration object with the input chain name.
          ChainDataImpl newChainData = null;
          try {
              newChainData = (ChainDataImpl) createChainData(chainName, FlowType.INBOUND, newChannelData, oldChainData.getPropertyBag());
          } catch (IncoherentChainException e) {
              FFDCFilter.processException(e, getClass().getName() + ".updateChain", "1792", this, new Object[] { chainName, newChannelData });
              throw e;
          }
  
          // Ensure existing listeners in old chain config move to new chain config.
          newChainData.setChainEventListeners(oldChainData.removeAllChainEventListeners());
          // Create or swap in new chain config.
          this.chainDataMap.put(chainName, newChainData);
  
          // Update any chain groups including this chain.
          ChainGroupDataImpl groupData = null;
          Iterator<ChainGroupData> groupIter = chainGroups.values().iterator();
          while (groupIter.hasNext()) {
              groupData = (ChainGroupDataImpl) groupIter.next();
              if (groupData.containsChain(chainName)) {
                  groupData.updateChain(newChainData);
              }
          }
  
          // Alert the chain event listener.
          newChainData.chainUpdated();
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "updateChain");
          }
          return newChainData;
      }