Package org.eclipse.php.internal.ui.explorer

Source Code of org.eclipse.php.internal.ui.explorer.PHPExplorerContentProvider

/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.ui.explorer;

import java.util.*;
import java.util.Map.Entry;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.dltk.ast.Modifiers;
import org.eclipse.dltk.core.*;
import org.eclipse.dltk.core.IOpenable;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.index2.search.ISearchEngine.MatchRule;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchEngine;
import org.eclipse.dltk.internal.core.*;
import org.eclipse.dltk.internal.ui.StandardModelElementContentProvider;
import org.eclipse.dltk.internal.ui.navigator.ScriptExplorerContentProvider;
import org.eclipse.dltk.internal.ui.scriptview.BuildPathContainer;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.php.internal.core.PHPVersion;
import org.eclipse.php.internal.core.includepath.IIncludepathListener;
import org.eclipse.php.internal.core.includepath.IncludePath;
import org.eclipse.php.internal.core.includepath.IncludePathManager;
import org.eclipse.php.internal.core.language.LanguageModelInitializer;
import org.eclipse.php.internal.core.model.PhpModelAccess;
import org.eclipse.php.internal.core.project.ProjectOptions;
import org.eclipse.php.internal.core.typeinference.GlobalNamespace;
import org.eclipse.php.internal.ui.Logger;
import org.eclipse.php.internal.ui.PHPUIMessages;
import org.eclipse.php.internal.ui.PHPUiPlugin;
import org.eclipse.php.internal.ui.preferences.PreferenceConstants;
import org.eclipse.php.internal.ui.util.NamespaceNode;
import org.eclipse.wst.jsdt.core.*;
import org.eclipse.wst.jsdt.core.ElementChangedEvent;
import org.eclipse.wst.jsdt.core.IElementChangedListener;
import org.eclipse.wst.jsdt.internal.ui.packageview.PackageFragmentRootContainer;
import org.eclipse.wst.jsdt.ui.ProjectLibraryRoot;
import org.eclipse.wst.jsdt.ui.StandardJavaScriptElementContentProvider;
import org.eclipse.wst.jsdt.ui.project.JsNature;

/**
*
* @author apeled, ncohen
*
*/
public class PHPExplorerContentProvider extends ScriptExplorerContentProvider
    implements IIncludepathListener /* , IResourceChangeListener */,
    IElementChangedListener {
  public final static ArrayList<Object> EMPTY_LIST = new ArrayList<Object>();
  StandardJavaScriptElementContentProvider jsContentProvider;

  public PHPExplorerContentProvider(boolean provideMembers) {
    super(provideMembers);
    IncludePathManager.getInstance().registerIncludepathListener(this);
    setIsFlatLayout(false);
    jsContentProvider = new StandardJavaScriptElementContentProvider(true);
  }

  public void setIsFlatLayout(final boolean state) {
    super.setIsFlatLayout(false);
  }

  @Override
  public void dispose() {
    super.dispose();
    IncludePathManager.getInstance().unregisterIncludepathListener(this);
    JavaScriptCore.removeElementChangedListener(this);
  }

  private Object[] getNonPhpProjects(final IScriptModel model)
      throws ModelException {
    return model.getForeignResources();
  }

  public Object[] getChildren(Object parentElement) {
    if (parentElement instanceof IPath) {
      IPath path = (IPath) parentElement;
      IWorkspace workspace = ResourcesPlugin.getWorkspace();
      IResource iesource = workspace.getRoot().findMember(path);
      if (iesource instanceof IProject) {
        IProject project = (IProject) iesource;
        IScriptProject sp = DLTKCore.create(project);
        if (sp instanceof ScriptProject) {
          ScriptProject scriptProject = (ScriptProject) sp;
          try {
            return scriptProject.getAllProjectFragments();
          } catch (ModelException e) {
            Logger.logException(e);
          }
        }
      }
    }
    // include path node
    if (parentElement instanceof IncludePath) {
      final Object entry = ((IncludePath) parentElement).getEntry();
      if (entry instanceof IBuildpathEntry) {
        int entryKind = ((IBuildpathEntry) entry).getEntryKind();
        if (entryKind == IBuildpathEntry.BPE_CONTAINER
            || entryKind == IBuildpathEntry.BPE_LIBRARY) {
          return getBuildPathEntryChildren(parentElement, entry);
        }
      }
    }

    // JavaScript nodes
    if (parentElement instanceof ProjectLibraryRoot) {
      return ((ProjectLibraryRoot) parentElement).getChildren();
    }
    if (parentElement instanceof PackageFragmentRootContainer) {
      return getContainerPackageFragmentRoots(
          (PackageFragmentRootContainer) parentElement, true);
    }

    if (parentElement instanceof org.eclipse.wst.jsdt.core.IJavaScriptElement) {
      return jsContentProvider.getChildren(parentElement);
    }

    try {
      // don't show local method variables:
      if (parentElement instanceof IMethod) {
        return NO_CHILDREN;
      }

      // aggregate php projects and non php projects (includes closed
      // ones)
      if (parentElement instanceof IScriptModel) {
        return StandardModelElementContentProvider.concatenate(
            getScriptProjects((IScriptModel) parentElement),
            getNonPhpProjects((IScriptModel) parentElement));
      }

      // Handles SourceModule and downwards as well as
      // ExternalProjectFragments (i.e language model)
      if (parentElement instanceof ISourceModule
          || !(parentElement instanceof IOpenable)
          || parentElement instanceof ExternalProjectFragment) {
        if (parentElement instanceof IFolder) {
          IResource[] members = ((IFolder) parentElement).members();
          ArrayList<Object> returnChlidren = new ArrayList<Object>();
          for (IResource resource2 : members) {
            IModelElement modelElement = DLTKCore.create(resource2);
            if (modelElement != null
                && isSourceFolder(modelElement)) {
              returnChlidren.add(modelElement);
            } else {
              returnChlidren.add(resource2);
            }
          }
          return (Object[]) returnChlidren
              .toArray(new Object[returnChlidren.size()]);
        }

        for (ITreeContentProvider provider : TreeContentProviderRegistry
            .getInstance().getTreeProviders()) {

          Object[] providerChildren = provider
              .getChildren(parentElement);
          if (providerChildren != null) {
            return providerChildren;
          }
        }

        return super.getChildren(parentElement);
      }

      if (parentElement instanceof IOpenable) {
        if (parentElement instanceof ExternalScriptFolder) {
          return super.getChildren(parentElement);
        }

        IResource resource = ((IOpenable) parentElement).getResource();
        if (resource instanceof IContainer) {

          // contributed by Toshihiro Izumi
          if (!resource.isAccessible()) {
            return NO_CHILDREN;
          }

          ArrayList<Object> returnChildren = new ArrayList<Object>();

          boolean groupByNamespace = PHPUiPlugin
              .getDefault()
              .getPreferenceStore()
              .getBoolean(
                  PreferenceConstants.EXPLORER_GROUP_BY_NAMESPACES);
          if (groupByNamespace
              && parentElement instanceof IModelElement
              && isSourceFolder(DLTKCore.create(resource))
              && supportsNamespaces(((IOpenable) parentElement)
                  .getScriptProject())) {
            returnChildren.add(new GlobalNamespace(
                (IModelElement) parentElement));

            returnChildren.addAll(collectNamespaces(DLTKCore
                .create(resource)));

            IResource[] resChildren = ((IContainer) resource)
                .members();
            for (IResource resource2 : resChildren) {
              IModelElement modelElement = DLTKCore
                  .create(resource2);
              if (modelElement == null
                  || !isInSourceFolder(modelElement)) {
                returnChildren.add(resource2);
              }
            }
          } else {
            IResource[] resChildren = ((IContainer) resource)
                .members();
            for (IResource resource2 : resChildren) {
              IModelElement modelElement = DLTKCore
                  .create(resource2);
              if (modelElement != null
                  && isInSourceFolder(modelElement)) {
                returnChildren.add(modelElement);
              } else {
                returnChildren.add(resource2);
              }
            }
          }

          // Adding External libraries to the treeview :
          if (parentElement instanceof IScriptProject) {
            IScriptProject scriptProject = (IScriptProject) parentElement;
            IProject project = scriptProject.getProject();

            // Add include path node
            IncludePath[] includePaths = IncludePathManager
                .getInstance().getIncludePaths(project);
            IncludePathContainer incPathContainer = new IncludePathContainer(
                scriptProject, includePaths);
            returnChildren.add(incPathContainer);

            // Add the language library
            Object[] projectChildren = getProjectFragments(scriptProject);
            for (Object modelElement : projectChildren) {
              if (modelElement instanceof BuildPathContainer
                  && ((BuildPathContainer) modelElement)
                      .getBuildpathEntry()
                      .getPath()
                      .equals(LanguageModelInitializer.LANGUAGE_CONTAINER_PATH)) {
                returnChildren.add(modelElement);
              }
            }

            boolean hasJsNature = JsNature.hasNature(project);
            if (hasJsNature) {
              ProjectLibraryRoot projectLibs = new ProjectLibraryRoot(
                  JavaScriptCore.create(project));
              returnChildren.add(projectLibs);
            }

            // let extensions contribute explorer root elements
            for (ITreeContentProvider provider : TreeContentProviderRegistry
                .getInstance().getTreeProviders()) {

              Object[] providerChildren = provider
                  .getChildren(parentElement);
              if (providerChildren != null) {
                returnChildren.addAll(new ArrayList<Object>(
                    Arrays.asList(providerChildren)));
              }
            }
          }
          return returnChildren.toArray();
        }
      }
    } catch (CoreException e) {
      Logger.logException(e);
    }

    if (parentElement instanceof ArchiveProjectFragment
        || parentElement instanceof ArchiveFolder) {
      return super.getChildren(parentElement);
    }

    return NO_CHILDREN;
  }

  private boolean isSourceFolder(IModelElement modelElement) {
    ScriptProject project = (ScriptProject) modelElement.getScriptProject();
    IBuildpathEntry[] buildpath = null;
    try {
      buildpath = project.getResolvedBuildpath();
    } catch (ModelException e) {

    }
    if (buildpath == null) {
      return false;
    }
    for (int j = 0, buildpathLength = buildpath.length; j < buildpathLength; j++) {
      IBuildpathEntry entry = buildpath[j];
      // root path
      IPath path = entry.getPath();
      if (path != null
          && path.equals(modelElement.getResource().getFullPath())) {
        return true;
      }
    }

    return false;
  }

  private boolean isInSourceFolder(IModelElement modelElement) {
    return modelElement.getScriptProject().isOnBuildpath(modelElement);
  }

  /*
   * Finds the root info this path is included in. Returns null if not found.
   */
  private boolean isInPath(IPath parentPath, IResource resouce) {
    IPath path = resouce.getFullPath();
    while (path != null && path.segmentCount() > 0) {
      if (path.equals(parentPath)) {
        return true;
      }
      path = path.removeLastSegments(1);
    }
    return false;
  }

  protected boolean supportsNamespaces(IScriptProject project) {
    PHPVersion version = ProjectOptions.getPhpVersion(project.getProject());
    return version.isGreaterThan(PHPVersion.PHP5);
  }

  protected Object[] getAllNamespaces(final IScriptProject project)
      throws ModelException {
    IDLTKSearchScope scope = SearchEngine.createSearchScope(project,
        IDLTKSearchScope.SOURCES);
    IType[] namespaces = PhpModelAccess.getDefault().findTypes(null,
        MatchRule.PREFIX, Modifiers.AccNameSpace, 0, scope, null);
    Map<String, List<IType>> aggregated = new HashMap<String, List<IType>>();
    for (IType ns : namespaces) {
      String elementName = ns.getElementName();
      List<IType> l = aggregated.get(elementName);
      if (l == null) {
        l = new LinkedList<IType>();
        aggregated.put(elementName, l);
      }
      l.add(ns);
    }
    List<IType> result = new LinkedList<IType>();
    for (Entry<String, List<IType>> entry : aggregated.entrySet()) {
      result.add(new NamespaceNode(project, entry.getKey(), entry
          .getValue().toArray(new IType[entry.getValue().size()])));
    }
    return result.toArray();
  }

  protected List<IType> collectNamespaces(IModelElement create)
      throws ModelException {

    IDLTKSearchScope scope = SearchEngine.createSearchScope(create,
        IDLTKSearchScope.SOURCES);
    IType[] namespaces = PhpModelAccess.getDefault().findTypes(null,
        MatchRule.PREFIX, Modifiers.AccNameSpace, 0, scope, null);
    Map<String, List<IType>> aggregated = new HashMap<String, List<IType>>();
    for (IType ns : namespaces) {
      String elementName = ns.getElementName();
      List<IType> l = aggregated.get(elementName);
      if (l == null) {
        l = new LinkedList<IType>();
        aggregated.put(elementName, l);
      }
      l.add(ns);
    }
    List<IType> result = new LinkedList<IType>();
    for (Entry<String, List<IType>> entry : aggregated.entrySet()) {
      result.add(new NamespaceNode(create, entry.getKey(), entry
          .getValue().toArray(new IType[entry.getValue().size()])));
    }

    return result;
  }

  private Object[] getContainerPackageFragmentRoots(
      PackageFragmentRootContainer container, boolean createFolder) {

    Object[] children = container.getChildren();
    if (children == null)
      return new Object[0];

    ArrayList<IJavaScriptElement> allChildren = new ArrayList<IJavaScriptElement>();
    ArrayList<Object> expanded = new ArrayList<Object>();
    expanded.addAll(Arrays.asList(children));

    if (expanded == null || expanded.size() < 1)
      return new Object[0];

    Object next = expanded.remove(0);

    while (next != null) {
      try {
        if (next instanceof IPackageFragment) {
          expanded.addAll(Arrays.asList(((IPackageFragment) next)
              .getChildren()));
        } else if (next instanceof IPackageFragmentRoot) {
          expanded.addAll(Arrays.asList(((IPackageFragmentRoot) next)
              .getChildren()));
        } else if (next instanceof IClassFile) {
          List<IJavaScriptElement> newChildren = Arrays
              .asList(((IClassFile) next).getChildren());
          allChildren.removeAll(newChildren);
          allChildren.addAll(newChildren);
        } else if (next instanceof IJavaScriptUnit) {
          List<IJavaScriptElement> newChildren = Arrays
              .asList(((IJavaScriptUnit) next).getChildren());
          allChildren.removeAll(newChildren);
          allChildren.addAll(newChildren);

        }
      } catch (JavaScriptModelException ex) {
        Logger.logException(ex);
      }

      if (expanded.size() > 0)
        next = expanded.remove(0);
      else
        next = null;
    }

    return allChildren.toArray();
  }

  /**
   * @param parentElement
   * @param entry
   * @return
   */
  private Object[] getBuildPathEntryChildren(Object parentElement,
      Object entry) {
    IScriptProject scriptProject = DLTKCore
        .create(((IncludePath) parentElement).getProject());
    IProjectFragment[] findProjectFragments = scriptProject
        .findProjectFragments((IBuildpathEntry) entry);
    List<Object> children = new LinkedList<Object>();
    for (IProjectFragment projectFragment : findProjectFragments) {
      Object[] fragmentChildren = getChildren(projectFragment);
      children.addAll(Arrays.asList(fragmentChildren));
    }
    if (!children.isEmpty()) {
      return children.toArray(new Object[children.size()]);
    }
    return getChildren(((BuildpathEntry) entry).getPath());
  }

  private static IBuildpathEntry getBuildpathEntry(IScriptProject parent) {
    IBuildpathEntry[] entries;
    try {
      entries = parent.getRawBuildpath();
      if (entries != null && entries.length > 0) {
        return entries[0];
      }
    } catch (ModelException e) {
    }
    return DLTKCore.newContainerEntry(parent.getPath());
  }

  public class IncludePathContainer extends BuildPathContainer {
    private IncludePath[] fIncludePath;

    public IncludePathContainer(IScriptProject parent, IncludePath[] entries) {
      super(parent, PHPExplorerContentProvider.getBuildpathEntry(parent));
      fIncludePath = entries;
    }

    public String getLabel() {
      return PHPUIMessages.IncludePathExplorerNode_label;
    }

    public IAdaptable[] getChildren() {
      return fIncludePath;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + getOuterType().hashCode();
      result = prime * result + Arrays.hashCode(fIncludePath);
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (!super.equals(obj))
        return false;
      if (getClass() != obj.getClass())
        return false;
      IncludePathContainer other = (IncludePathContainer) obj;
      if (!getOuterType().equals(other.getOuterType()))
        return false;
      if (!Arrays.equals(fIncludePath, other.fIncludePath))
        return false;
      return true;
    }

    private PHPExplorerContentProvider getOuterType() {
      return PHPExplorerContentProvider.this;
    }
  }

  /**
   * This method overrides the
   */
  public void refresh(IProject project) {
    Collection<Runnable> runnables = new ArrayList<Runnable>();
    final ArrayList<IScriptProject> resources = new ArrayList<IScriptProject>(
        1);
    resources.add(DLTKCore.create(project));

    postRefresh(resources, true, runnables);
    this.executeRunnables(runnables);
  }

  @Override
  public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
    super.inputChanged(viewer, oldInput, newInput);
    if (oldInput == null && newInput != null) {
      JavaScriptCore.addElementChangedListener(this);
    } else if (oldInput != null && newInput == null) {
      JavaScriptCore.removeElementChangedListener(this);
    }
  }

  public void elementChanged(ElementChangedEvent event) {
    IJavaScriptElementDelta[] affectedChildren = event.getDelta()
        .getAffectedChildren();
    final ArrayList<Runnable> runnables = new ArrayList<Runnable>();
    for (int i = 0; i < affectedChildren.length; i++) {
      if (processDelta(affectedChildren[i], runnables)) {
        return; // early return, element got refreshed
      }
    }

  }

  private boolean processDelta(IJavaScriptElementDelta delta,
      ArrayList<Runnable> runnables) {
    int flags = delta.getFlags();
    IJavaScriptElement element = delta.getElement();
    int elementType = element.getElementType();

    if (elementType != IJavaScriptElement.JAVASCRIPT_MODEL
        && elementType != IJavaScriptElement.JAVASCRIPT_PROJECT) {
      IJavaScriptProject proj = element.getJavaScriptProject();
      if (proj == null || !proj.getProject().isOpen())
        return false;
    }

    if (elementType == IJavaScriptElement.JAVASCRIPT_PROJECT) {
      // if the raw class path has changed we refresh the entire project
      if ((flags & IJavaScriptElementDelta.F_INCLUDEPATH_CHANGED) != 0) {

        final ArrayList<IScriptProject> resources = new ArrayList<IScriptProject>(
            1);
        IProject project = ((IJavaScriptProject) element).getProject();
        resources.add(DLTKCore.create(project));
        postRefresh(resources, true, runnables);
        this.executeRunnables(runnables);
        return true;
      }
    }
    return false;
  }
}
TOP

Related Classes of org.eclipse.php.internal.ui.explorer.PHPExplorerContentProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.