/**
  * Retrieve the JSDT Project from the delta, if delta is about "Includes Path" changes.
  *
  * @param delta the JSDT delta.
  * @return
  */
 private IJavaScriptProject getJavaScriptProjectIfClassPathChanged(IJavaScriptElementDelta delta) {
   if (delta.getKind() != IJavaScriptElementDelta.CHANGED) {
     return null;
   }
   IJavaScriptElement element = delta.getElement();
   switch (element.getElementType()) {
     case IJavaScriptElement.JAVASCRIPT_MODEL:
       IJavaScriptElementDelta[] children = delta.getAffectedChildren();
       for (int i = 0, length = children.length; i < length; i++) {
         IJavaScriptElementDelta child = children[i];
         IJavaScriptProject project = getJavaScriptProjectIfClassPathChanged(child);
         if (project != null) {
           return project;
         }
       }
       return null;
     case IJavaScriptElement.JAVASCRIPT_PROJECT:
       int kind = delta.getKind();
       switch (kind) {
         case IJavaScriptElementDelta.ADDED:
         case IJavaScriptElementDelta.REMOVED:
           return null;
         case IJavaScriptElementDelta.CHANGED:
           int flags = delta.getFlags();
           if ((flags & IJavaScriptElementDelta.F_CLOSED) != 0
               || (flags & IJavaScriptElementDelta.F_OPENED) != 0) {
             return null;
           } else {
             children = delta.getAffectedChildren();
             for (int i = 0, length = children.length; i < length; i++) {
               IJavaScriptElementDelta child = children[i];
               IJavaScriptProject project = getJavaScriptProjectIfClassPathChanged(child);
               if (project != null) {
                 return project;
               }
             }
           }
           return null;
       }
       return null;
     case IJavaScriptElement.PACKAGE_FRAGMENT_ROOT:
       kind = delta.getKind();
       switch (kind) {
         case IJavaScriptElementDelta.ADDED:
         case IJavaScriptElementDelta.REMOVED:
           return null;
         case IJavaScriptElementDelta.CHANGED:
           int flags = delta.getFlags();
           if ((flags & IJavaScriptElementDelta.F_ADDED_TO_CLASSPATH) > 0
               || (flags & IJavaScriptElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
             // "Include Path" has changed, returns the JSDT project.
             return element.getJavaScriptProject();
           }
           return null;
       }
       break;
   }
   return null;
 }
  /**
   * Returns all of the openables defined in the region of this type hierarchy. Returns a map from
   * IJavaScriptProject to ArrayList of Openable
   */
  private HashMap determineOpenablesInRegion(IProgressMonitor monitor) {

    try {
      HashMap allOpenables = new HashMap();
      IJavaScriptElement[] roots = ((RegionBasedTypeHierarchy) this.hierarchy).region.getElements();
      int length = roots.length;
      if (monitor != null) monitor.beginTask("", length); // $NON-NLS-1$
      for (int i = 0; i < length; i++) {
        IJavaScriptElement root = roots[i];
        IJavaScriptProject javaProject = root.getJavaScriptProject();
        ArrayList openables = (ArrayList) allOpenables.get(javaProject);
        if (openables == null) {
          openables = new ArrayList();
          allOpenables.put(javaProject, openables);
        }
        switch (root.getElementType()) {
          case IJavaScriptElement.JAVASCRIPT_PROJECT:
            injectAllOpenablesForJavaProject((IJavaScriptProject) root, openables);
            break;
          case IJavaScriptElement.PACKAGE_FRAGMENT_ROOT:
            injectAllOpenablesForPackageFragmentRoot((IPackageFragmentRoot) root, openables);
            break;
          case IJavaScriptElement.PACKAGE_FRAGMENT:
            injectAllOpenablesForPackageFragment((IPackageFragment) root, openables);
            break;
          case IJavaScriptElement.CLASS_FILE:
          case IJavaScriptElement.JAVASCRIPT_UNIT:
            openables.add(root);
            break;
          case IJavaScriptElement.TYPE:
            IType type = (IType) root;
            if (type.isBinary()) {
              openables.add(type.getClassFile());
            } else {
              openables.add(type.getJavaScriptUnit());
            }
            break;
          default:
            break;
        }
        worked(monitor, 1);
      }
      return allOpenables;
    } finally {
      if (monitor != null) monitor.done();
    }
  }
 /* (non-Javadoc)
  * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object)
  */
 public boolean test(Object receiver, String method, Object[] args, Object expectedValue) {
   if (!(receiver instanceof IJavaScriptElement)) {
     return false;
   }
   IJavaScriptElement res = (IJavaScriptElement) receiver;
   if (method.equals(NAME)) {
     return Pattern.matches(toString(expectedValue), res.getElementName());
   } else if (method.equals(IS_IN_JAVA_PROJECT)) {
     IJavaScriptProject javaProject = res.getJavaScriptProject();
     return javaProject != null && javaProject.exists() && javaProject.getProject().isOpen();
   } else if (method.equals(IS_IN_JAVA_PROJECT_WITH_NATURE)) {
     IJavaScriptProject javaProject = res.getJavaScriptProject();
     if (javaProject != null && javaProject.exists() && javaProject.getProject().isOpen()) {
       if (expectedValue != null) {
         try {
           return javaProject.getProject().hasNature(toString(expectedValue));
         } catch (CoreException e) {
           return false;
         }
       }
     }
     return false;
   } else if (method.equals(IS_ON_CLASSPATH)) {
     IJavaScriptProject javaProject = res.getJavaScriptProject();
     if (javaProject != null && javaProject.exists()) {
       return javaProject.isOnIncludepath(res);
     }
     return false;
   } else if (method.equals(IN_SOURCE_FOLDER)) {
     IJavaScriptElement root = res.getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT_ROOT);
     if (root != null) {
       try {
         return ((IPackageFragmentRoot) root).getKind() == IPackageFragmentRoot.K_SOURCE;
       } catch (JavaScriptModelException e) {
         // ignore
       }
     }
     return false;
   } else if (method.equals(IN_ARCHIVE)) {
     IJavaScriptElement root = res.getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT_ROOT);
     if (root != null) {
       return ((IPackageFragmentRoot) root).isArchive();
     }
     return false;
   } else if (method.equals(IN_EXTERNAL_ARCHIVE)) {
     IJavaScriptElement root = res.getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT_ROOT);
     if (root != null) {
       return ((IPackageFragmentRoot) root).isExternal();
     }
     return false;
   } else if (method.equals(PROJECT_OPTION)) {
     IJavaScriptProject project = res.getJavaScriptProject();
     if (project != null) {
       if (args.length == 2) {
         String current = project.getOption(toString(args[0]), true);
         return current != null && current.equals(args[1]);
       } else if (args.length == 1) {
         return project.getOption(toString(args[0]), false) != null;
       }
     }
     return false;
   } else if (method.equals(HAS_TYPE_ON_CLASSPATH)) {
     IJavaScriptProject javaProject = res.getJavaScriptProject();
     if (javaProject != null && javaProject.exists()) {
       try {
         return javaProject.findType(toString(expectedValue)) != null;
       } catch (JavaScriptModelException e) {
         return false;
       }
     }
   }
   return false;
 }