docs: private void updateChannelNode(
              String nodeId,
              IUserLayoutChannelDescription newChanDesc,
              IUserLayoutChannelDescription oldChanDesc)
              throws PortalException {
          Element ilfNode = (Element) getUserLayoutDOM().getElementById(nodeId);
          List<ILayoutProcessingAction> pendingActions = new ArrayList<ILayoutProcessingAction>();
          boolean isIncorporated = nodeId.startsWith(Constants.FRAGMENT_ID_USER_PREFIX);
  
          /*
           * see what structure attributes changed if any and see if allowed.
           *
           * CHANNEL ATTRIBUTES that currently can be EDITED in DLM are:
           * dlm:moveAllowed - only on fragments
           * dlm:editAllowed - only on fragments
           * dlm:deleteAllowed - only on fragments
           */
  
          // ATT: DLM Restrictions
          if (isFragmentOwner
                  && (newChanDesc.isDeleteAllowed() != oldChanDesc.isDeleteAllowed()
                          || newChanDesc.isEditAllowed() != oldChanDesc.isEditAllowed()
                          || newChanDesc.isMoveAllowed() != oldChanDesc.isMoveAllowed())) {
              pendingActions.add(
                      new LPAEditRestriction(
                              owner,
                              ilfNode,
                              newChanDesc.isMoveAllowed(),
                              newChanDesc.isDeleteAllowed(),
                              newChanDesc.isEditAllowed(),
                              newChanDesc.isAddChildAllowed()));
          }
  
          // ATT: other? if other attributes should be editable in DLM on channels
          // we can add calls like this to enable such support.
          //  updateNodeAttribute(ilfNode, nodeId, "hidden",
          //     newChanDesc.getName(), oldChanDesc.getName(), pendingActions);
  
          /*
           * now we loop through all parameters in the new channel description and
           * see if there is a corresponding parameter in the old channel
           * description and see if the change is allowed. For each allowed change
           * we add an object that will make such a change once all changes have
           * been approved. As we find matches in the old channel description we
           * remove those parameters. Then any left there after processing those
           * of the new channel description indicate parameters that were removed.
           */
          FragmentChannelInfo fragChanInf = null;
          Map pubParms = getPublishedChannelParametersMap(newChanDesc.getChannelPublishId());
  
          if (isIncorporated)
              fragChanInf = this.distributedLayoutStore.getFragmentChannelInfo(nodeId);
          Map oldParms = new HashMap(oldChanDesc.getParameterMap());
          for (Iterator itr = newChanDesc.getParameterMap().entrySet().iterator(); itr.hasNext(); ) {
              Map.Entry e = (Entry) itr.next();
              String name = (String) e.getKey();
              String newVal = (String) e.getValue();
              String oldVal = (String) oldParms.remove(name);
  
              if (oldVal == null) {
                  /*
                   * not in old description so this is a new ad-hoc parameter
                   */
                  pendingActions.add(new LPAAddParameter(nodeId, name, newVal, owner, ilfNode));
              } else if (!oldVal.equals(newVal)) {
                  if (isIncorporated) {
                      /*
                       * if the fragment does not have a value for this parm then
                       * this is an ad-hoc value and we need a directive to
                       * persist the user's desired value. if the frament does
                       * have a value and it is the same as the new value then we
                       * can remove the override since it won't accomplish
                       * anything. if the fragment does have a value and it is
                       * different then we need the directive to persist the
                       * user's desired value.
                       */
                      String fragValue = fragChanInf.getParameterValue(name);
  
                      if (fragValue == null) {
                          /*
                           * so fragment doesn't override. See if the value
                           * specified matches that of the channel definition
                           */
                          IPortletDefinitionParameter cp =
                                  (IPortletDefinitionParameter) pubParms.get(name);
  
                          if (cp != null && cp.getValue().equals(newVal))
                              /*
                               * new value matches that of published channel to
                               * remove any user parameter spec since not needed
                               */
                              pendingActions.add(
                                      new LPARemoveParameter(nodeId, name, owner, ilfNode));
                          else
                              /*
                               * value doesn't match that of published chanel so
                               * we need change any existing parameter spec or add
                               * a new one if it doesn't exist.
                               */
                              pendingActions.add(
                                      new LPAChangeParameter(nodeId, name, newVal, owner, ilfNode));
                      } else if (!fragValue.equals(newVal)) {
                          /*
                           * so fragment does specify and user value is different
                           * so change any existing parameter spec or add a new
                           * one if it doesn't exist.
                           */
                          pendingActions.add(
                                  new LPAChangeParameter(nodeId, name, newVal, owner, ilfNode));
                      } else {
                          /*
                           * new val same as fragment value so don't persist.
                           * remove any parameter spec if it exists.
                           */
                          pendingActions.add(
                                  new LPAResetParameter(nodeId, name, fragValue, owner, ilfNode));
                      }
                  } else // not incorporated from a fragment
                  {
                      /*
                       * see if the value specified matches that of the channel
                       * definition.
                       */
                      IPortletDefinitionParameter cp =
                              (IPortletDefinitionParameter) pubParms.get(name);
  
                      if (cp != null && cp.getValue().equals(newVal))
                          pendingActions.add(new LPARemoveParameter(nodeId, name, owner, ilfNode));
                      else
                          pendingActions.add(
                                  new LPAChangeParameter(nodeId, name, newVal, owner, ilfNode));
                  }
              }
          }
          /*
           * So any parameters remaining in the oldParms map at this point didn't
           * match those in the new channel description which means that they were
           * removed. So remove any parameter spec if it exists.
           */
          for (Iterator itr = oldParms.entrySet().iterator(); itr.hasNext(); ) {
              Map.Entry e = (Entry) itr.next();
              String name = (String) e.getKey();
              pendingActions.add(new LPARemoveParameter(nodeId, name, owner, ilfNode));
          }
          /*
           * if we make it to this point then all edits made are allowed so
           * process the actions to push the edits into the layout
           */
          for (Iterator itr = pendingActions.iterator(); itr.hasNext(); ) {
              ILayoutProcessingAction action = (ILayoutProcessingAction) itr.next();
              action.perform();
          }
      }