@Override
  protected List<Object> getKeys() {

    List<Object> keys = new ArrayList<Object>();

    List<IConfigurationElement> proxyElements =
        ToolchainExtensions.getInstance().findExplorerProxyNodes(element);

    List<IConfigurationElement> children = new ArrayList<IConfigurationElement>();
    Collections.addAll(children, element.getChildren());

    for (IConfigurationElement proxy : proxyElements) {
      Collections.addAll(children, proxy.getChildren());
    }

    for (IConfigurationElement el : children) {

      if (ToolchainExtensions.NODE_EXTENSION_NAME.equals(el.getName())) {
        keys.add(new Key(el, null));
      }

      if (ToolchainExtensions.NODE_RESOURCE_EXTENSION_NAME.equals(el.getName())) {
        keys.add(new Key(el, null));
      }

      if (ToolchainExtensions.NODE_DYNAMIC_EXTENSION_NAME.equals(el.getName())) {
        try {
          IExplorerContentRetriever contentRetriever = contentRetrievers.get(el);
          if (contentRetriever == null) {
            contentRetriever = (IExplorerContentRetriever) el.createExecutableExtension("class");
            contentRetriever.initialize(el.getAttribute("id"), getNode().getContext());
            contentRetriever.addPropertyChangeListener(contentRetrieverListener);
            contentRetrievers.put(el, contentRetriever);
          }

          if (contentRetriever != null) {

            List<Object> contentList = contentRetriever.getChildren();
            if (contentList.isEmpty()) {

              String emptyNodeID = el.getAttribute("empty");
              if (emptyNodeID != null && !emptyNodeID.isEmpty()) {
                keys.add(new Key(el, null));
              }

            } else {
              for (Object content : contentList) {
                keys.add(new Key(el, content));
              }
            }
          }

        } catch (CoreException e) {
          e.printStackTrace();
        }
      }
    }

    return keys;
  }
  @Override
  public IExplorerNode getChild(Object key) {

    IConfigurationElement el = ((Key) key).element;
    Object value = ((Key) key).value;

    IExplorerNode node = null;

    if (ToolchainExtensions.NODE_EXTENSION_NAME.equals(el.getName())) {

      IExplorerNodeChildren children = new ConfigurationElementNodeChildren(el);
      node = new ConfigurationElementNode(getNode().getContext(), el, children);
    }

    if (ToolchainExtensions.NODE_RESOURCE_EXTENSION_NAME.equals(el.getName())) {

      IExplorerNodeChildren children = new ConfigurationElementNodeChildren(el);
      node = new ConfigurationElementEditorNode(getNode().getContext(), el, children);
    }

    if (ToolchainExtensions.NODE_DYNAMIC_EXTENSION_NAME.equals(el.getName())) {

      if (value == null) {
        String empty = el.getAttribute("empty");
        IConfigurationElement emptyElement =
            ToolchainExtensions.getInstance().findNodeElement(empty);
        if (emptyElement != null) {
          ExplorerNodeChildren children = new ConfigurationElementNodeChildren(emptyElement);
          node = getChild(new Key(emptyElement, children));
        }
      }

      ExplorerNodeChildren children = new ConfigurationElementNodeChildren(el);

      if (value instanceof IEditorInputResource) {
        node =
            new AlternativeNode(
                getNode().getContext(),
                el.getAttribute("editor"),
                (IEditorInputResource) value,
                children);
      }
      if (value instanceof IFile) {
        node = new AlternativeResourceNode(getNode().getContext(), (IFile) value);
      }
      if (value instanceof IProject) {
        node =
            new ConfigurationElementResourceNode(
                getNode().getContext(), el, (IResource) value, children);
        node.setName(((IProject) value).getName());
      }
    }

    return node;
  }