/**
  * Unlink all contribution items from the given model menu.
  *
  * @param renderer the renderer that is holding the links
  * @param menu the model menu whose children should have its items unlinked from their
  *     corresponding contribution items
  */
 private void unlink(MenuManagerRenderer renderer, MMenu menu) {
   for (MMenuElement menuElement : menu.getChildren()) {
     if (menuElement instanceof MOpaqueMenuItem) {
       MOpaqueMenuItem opaqueMenuItem = (MOpaqueMenuItem) menuElement;
       Object item = opaqueMenuItem.getOpaqueItem();
       if (item instanceof IContributionItem) {
         renderer.clearModelToContribution(opaqueMenuItem, (IContributionItem) item);
         opaqueMenuItem.setOpaqueItem(null);
       }
     } else if (menuElement instanceof MOpaqueMenuSeparator) {
       MOpaqueMenuSeparator opaqueMenuItem = (MOpaqueMenuSeparator) menuElement;
       Object item = opaqueMenuItem.getOpaqueItem();
       if (item instanceof IContributionItem) {
         renderer.clearModelToContribution(opaqueMenuItem, (IContributionItem) item);
         opaqueMenuItem.setOpaqueItem(null);
       }
     } else if (menuElement instanceof MMenu) {
       MMenu subMenu = (MMenu) menuElement;
       unlink(renderer, subMenu);
       MenuManager manager = renderer.getManager(subMenu);
       if (manager != null) {
         renderer.clearModelToManager(subMenu, manager);
       }
     } else {
       IContributionItem contribution = renderer.getContribution(menuElement);
       if (contribution != null) {
         renderer.clearModelToContribution(menuElement, contribution);
       }
     }
   }
 }
  /**
   * @param menuManager
   * @param menuModel
   */
  public void reconcileManagerToModel(MenuManager menuManager, MMenu menuModel) {
    List<MMenuElement> modelChildren = menuModel.getChildren();

    HashSet<MOpaqueMenuItem> oldModelItems = new HashSet<MOpaqueMenuItem>();
    HashSet<MOpaqueMenu> oldMenus = new HashSet<MOpaqueMenu>();
    HashSet<MOpaqueMenuSeparator> oldSeps = new HashSet<MOpaqueMenuSeparator>();
    for (MMenuElement itemModel : modelChildren) {
      if (itemModel instanceof MOpaqueMenuSeparator) {
        oldSeps.add((MOpaqueMenuSeparator) itemModel);
      } else if (itemModel instanceof MOpaqueMenuItem) {
        oldModelItems.add((MOpaqueMenuItem) itemModel);
      } else if (itemModel instanceof MOpaqueMenu) {
        oldMenus.add((MOpaqueMenu) itemModel);
      }
    }

    IContributionItem[] items = menuManager.getItems();
    for (int src = 0, dest = 0; src < items.length; src++, dest++) {
      IContributionItem item = items[src];
      if (item instanceof MenuManager) {
        MenuManager childManager = (MenuManager) item;
        MMenu childModel = getMenuModel(childManager);
        if (childModel == null) {
          MMenu legacyModel = MenuFactoryImpl.eINSTANCE.createOpaqueMenu();
          legacyModel.setElementId(childManager.getId());
          legacyModel.setVisible(childManager.isVisible());
          linkModelToManager(legacyModel, childManager);
          modelChildren.add(dest, legacyModel);
          reconcileManagerToModel(childManager, legacyModel);
        } else {
          if (childModel instanceof MOpaqueMenu) {
            oldMenus.remove(childModel);
          }
          if (modelChildren.size() > dest) {
            if (modelChildren.get(dest) != childModel) {
              modelChildren.remove(childModel);
              modelChildren.add(dest, childModel);
            }
          } else {
            modelChildren.add(childModel);
          }
        }
      } else if (item.isSeparator() || item.isGroupMarker()) {
        MMenuElement menuElement = getMenuElement(item);
        if (menuElement == null) {
          MOpaqueMenuSeparator legacySep = MenuFactoryImpl.eINSTANCE.createOpaqueMenuSeparator();
          legacySep.setElementId(item.getId());
          legacySep.setVisible(item.isVisible());
          legacySep.setOpaqueItem(item);
          linkModelToContribution(legacySep, item);
          modelChildren.add(dest, legacySep);
        } else if (menuElement instanceof MOpaqueMenuSeparator) {
          MOpaqueMenuSeparator legacySep = (MOpaqueMenuSeparator) menuElement;
          oldSeps.remove(legacySep);
          if (modelChildren.size() > dest) {
            if (modelChildren.get(dest) != legacySep) {
              modelChildren.remove(legacySep);
              modelChildren.add(dest, legacySep);
            }
          } else {
            modelChildren.add(legacySep);
          }
        }
      } else {
        MMenuElement menuElement = getMenuElement(item);
        if (menuElement == null) {
          MOpaqueMenuItem legacyItem = MenuFactoryImpl.eINSTANCE.createOpaqueMenuItem();
          legacyItem.setElementId(item.getId());
          legacyItem.setVisible(item.isVisible());
          legacyItem.setOpaqueItem(item);
          linkModelToContribution(legacyItem, item);
          modelChildren.add(dest, legacyItem);
        } else if (menuElement instanceof MOpaqueMenuItem) {
          MOpaqueMenuItem legacyItem = (MOpaqueMenuItem) menuElement;
          oldModelItems.remove(legacyItem);
          if (modelChildren.size() > dest) {
            if (modelChildren.get(dest) != legacyItem) {
              modelChildren.remove(legacyItem);
              modelChildren.add(dest, legacyItem);
            }
          } else {
            modelChildren.add(legacyItem);
          }
        }
      }
    }
    if (!oldModelItems.isEmpty()) {
      modelChildren.removeAll(oldModelItems);
      for (MOpaqueMenuItem model : oldModelItems) {
        clearModelToContribution(model, (IContributionItem) model.getOpaqueItem());
      }
    }
    if (!oldMenus.isEmpty()) {
      modelChildren.removeAll(oldMenus);
      for (MOpaqueMenu oldMenu : oldMenus) {
        MenuManager oldManager = getManager(oldMenu);
        clearModelToManager(oldMenu, oldManager);
      }
    }
    if (!oldSeps.isEmpty()) {
      modelChildren.removeAll(oldSeps);
      for (MOpaqueMenuSeparator model : oldSeps) {
        clearModelToContribution(model, (IContributionItem) model.getOpaqueItem());
      }
    }
  }