/**
  * 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;
 }
 private static boolean hasParentInSet(IJavaScriptElement elem, Set set) {
   IJavaScriptElement parent = elem.getParent();
   while (parent != null) {
     if (set.contains(parent)) return true;
     parent = parent.getParent();
   }
   return false;
 }
 /**
  * Returns a collection of all the parents of this element up to (but not including) the root of
  * this tree in bottom-up order. If the given element is not a descendant of the root of this
  * tree, <code>null</code> is returned.
  */
 private ArrayList getAncestors(IJavaScriptElement element) {
   IJavaScriptElement parent = element.getParent();
   if (parent == null) {
     return null;
   }
   ArrayList parents = new ArrayList();
   while (!parent.equals(this.changedElement)) {
     parents.add(parent);
     parent = parent.getParent();
     if (parent == null) {
       return null;
     }
   }
   parents.trimToSize();
   return parents;
 }
  /**
   * 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();
    }
  }
  private static boolean hasReadOnlyResourcesAndSubResources(IJavaScriptElement javaElement)
      throws CoreException {
    switch (javaElement.getElementType()) {
      case IJavaScriptElement.CLASS_FILE:
        // if this assert fails, it means that a precondition is missing
        Assert.isTrue(((IClassFile) javaElement).getResource() instanceof IFile);
        // fall thru
      case IJavaScriptElement.JAVASCRIPT_UNIT:
        IResource resource = ReorgUtils.getResource(javaElement);
        return (resource != null && Resources.isReadOnly(resource));
      case IJavaScriptElement.PACKAGE_FRAGMENT:
        IResource packResource = ReorgUtils.getResource(javaElement);
        if (packResource == null) return false;
        IPackageFragment pack = (IPackageFragment) javaElement;
        if (Resources.isReadOnly(packResource)) return true;
        Object[] nonJava = pack.getNonJavaScriptResources();
        for (int i = 0; i < nonJava.length; i++) {
          Object object = nonJava[i];
          if (object instanceof IResource
              && hasReadOnlyResourcesAndSubResources((IResource) object)) return true;
        }
        return hasReadOnlyResourcesAndSubResources(pack.getChildren());
      case IJavaScriptElement.PACKAGE_FRAGMENT_ROOT:
        IPackageFragmentRoot root = (IPackageFragmentRoot) javaElement;
        if (root.isArchive()) return false;
        IResource pfrResource = ReorgUtils.getResource(javaElement);
        if (pfrResource == null) return false;
        if (Resources.isReadOnly(pfrResource)) return true;
        Object[] nonJava1 = root.getNonJavaScriptResources();
        for (int i = 0; i < nonJava1.length; i++) {
          Object object = nonJava1[i];
          if (object instanceof IResource
              && hasReadOnlyResourcesAndSubResources((IResource) object)) return true;
        }
        return hasReadOnlyResourcesAndSubResources(root.getChildren());

      case IJavaScriptElement.FIELD:
      case IJavaScriptElement.IMPORT_CONTAINER:
      case IJavaScriptElement.IMPORT_DECLARATION:
      case IJavaScriptElement.INITIALIZER:
      case IJavaScriptElement.METHOD:
      case IJavaScriptElement.TYPE:
        return false;
      default:
        Assert.isTrue(false); // not handled here
        return false;
    }
  }
  /**
   * Processes a delta recursively. When more than two children are affected the tree is fully
   * refreshed starting at this node. The delta is processed in the current thread but the viewer
   * updates are posted to the UI thread.
   */
  protected void processDelta(IJavaScriptElementDelta delta) throws JavaScriptModelException {
    int kind = delta.getKind();
    int flags = delta.getFlags();
    final IJavaScriptElement element = delta.getElement();
    final boolean isElementValidForView = fBrowsingPart.isValidElement(element);

    if (!getProvideWorkingCopy()
        && element instanceof IJavaScriptUnit
        && ((IJavaScriptUnit) element).isWorkingCopy()) return;

    if (element != null
        && element.getElementType() == IJavaScriptElement.JAVASCRIPT_UNIT
        && !isOnClassPath((IJavaScriptUnit) element)) return;

    // handle open and closing of a solution or project
    if (((flags & IJavaScriptElementDelta.F_CLOSED) != 0)
        || ((flags & IJavaScriptElementDelta.F_OPENED) != 0)) {
      postRefresh(null);
      return;
    }

    if (kind == IJavaScriptElementDelta.REMOVED) {
      Object parent = internalGetParent(element);
      if (isElementValidForView) {
        if (element instanceof IClassFile) {
          postRemove(((IClassFile) element).getType());
        } else if (element instanceof IJavaScriptUnit
            && !((IJavaScriptUnit) element).isWorkingCopy()) {
          postRefresh(null);
        } else if (element instanceof IJavaScriptUnit
            && ((IJavaScriptUnit) element).isWorkingCopy()) {
          if (getProvideWorkingCopy()) postRefresh(null);
        } else if (parent instanceof IJavaScriptUnit
            && getProvideWorkingCopy()
            && !((IJavaScriptUnit) parent).isWorkingCopy()) {
          if (element instanceof IJavaScriptUnit && ((IJavaScriptUnit) element).isWorkingCopy()) {
            // working copy removed from system - refresh
            postRefresh(null);
          }
        } else if (element instanceof IJavaScriptUnit
            && ((IJavaScriptUnit) element).isWorkingCopy()
            && parent != null
            && parent.equals(fInput))
          // closed editor - removing working copy
          postRefresh(null);
        else postRemove(element);
      }

      if (fBrowsingPart.isAncestorOf(element, fInput)) {
        if (element instanceof IJavaScriptUnit && ((IJavaScriptUnit) element).isWorkingCopy()) {
          postAdjustInputAndSetSelection(((IJavaScriptElement) fInput).getPrimaryElement());
        } else postAdjustInputAndSetSelection(null);
      }

      if (fInput != null && fInput.equals(element)) postRefresh(null);

      if (parent instanceof IPackageFragment && fBrowsingPart.isValidElement(parent)) {
        // refresh if package gets empty (might be filtered)
        if (isPackageFragmentEmpty((IPackageFragment) parent)
            && fViewer.testFindItem(parent) != null) postRefresh(null);
      }

      return;
    }
    if (kind == IJavaScriptElementDelta.ADDED
        && delta.getMovedFromElement() != null
        && element instanceof IJavaScriptUnit) return;

    if (kind == IJavaScriptElementDelta.ADDED) {
      if (isElementValidForView) {
        Object parent = internalGetParent(element);
        if (element instanceof IClassFile) {
          postAdd(parent, ((IClassFile) element).getType());
        } else if (element instanceof IJavaScriptUnit
            && !((IJavaScriptUnit) element).isWorkingCopy()) {
          postAdd(parent, ((IJavaScriptUnit) element).getTypes());
        } else if (parent instanceof IJavaScriptUnit
            && getProvideWorkingCopy()
            && !((IJavaScriptUnit) parent).isWorkingCopy()) {
          //	do nothing
        } else if (element instanceof IJavaScriptUnit
            && ((IJavaScriptUnit) element).isWorkingCopy()) {
          // new working copy comes to live
          postRefresh(null);
        } else postAdd(parent, element);
      } else if (fInput == null) {
        IJavaScriptElement newInput = fBrowsingPart.findInputForJavaElement(element);
        if (newInput != null) postAdjustInputAndSetSelection(element);
      } else if (element instanceof IType && fBrowsingPart.isValidInput(element)) {
        IJavaScriptElement cu1 = element.getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT);
        IJavaScriptElement cu2 =
            ((IJavaScriptElement) fInput).getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT);
        if (cu1 != null && cu2 != null && cu1.equals(cu2)) postAdjustInputAndSetSelection(element);
      }
      return;
    }

    if (kind == IJavaScriptElementDelta.CHANGED) {
      if (fInput != null
          && fInput.equals(element)
          && (flags & IJavaScriptElementDelta.F_CHILDREN) != 0
          && (flags & IJavaScriptElementDelta.F_FINE_GRAINED) != 0) {
        postRefresh(null, true);
        return;
      }
      if (isElementValidForView && (flags & IJavaScriptElementDelta.F_MODIFIERS) != 0) {
        postUpdateIcon(element);
      }
    }

    if (isClassPathChange(delta))
      // throw the towel and do a full refresh
      postRefresh(null);

    if ((flags & IJavaScriptElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0
        && fInput instanceof IJavaScriptElement) {
      IPackageFragmentRoot pkgRoot = (IPackageFragmentRoot) element;
      IJavaScriptElement inputsParent =
          ((IJavaScriptElement) fInput).getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT_ROOT);
      if (pkgRoot.equals(inputsParent)) postRefresh(null);
    }

    // the source attachment of a JAR has changed
    if (element instanceof IPackageFragmentRoot
        && (((flags & IJavaScriptElementDelta.F_SOURCEATTACHED) != 0
            || ((flags & IJavaScriptElementDelta.F_SOURCEDETACHED)) != 0))) postUpdateIcon(element);

    IJavaScriptElementDelta[] affectedChildren = delta.getAffectedChildren();
    if (affectedChildren.length > 1) {
      // a package fragment might become non empty refresh from the parent
      if (element instanceof IPackageFragment) {
        IJavaScriptElement parent = (IJavaScriptElement) internalGetParent(element);
        // avoid posting a refresh to an invisible parent
        if (element.equals(fInput)) {
          postRefresh(element);
        } else {
          postRefresh(parent);
        }
      }
      // more than one child changed, refresh from here downwards
      if (element instanceof IPackageFragmentRoot && isElementValidForView) {
        postRefresh(skipProjectPackageFragmentRoot((IPackageFragmentRoot) element));
        return;
      }
    }
    for (int i = 0; i < affectedChildren.length; i++) {
      processDelta(affectedChildren[i]);
    }
  }
 public RefactoringStatus initialize(final RefactoringArguments arguments) {
   if (arguments instanceof JavaRefactoringArguments) {
     final JavaRefactoringArguments extended = (JavaRefactoringArguments) arguments;
     final String selection = extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION);
     if (selection != null) {
       int offset = -1;
       int length = -1;
       final StringTokenizer tokenizer = new StringTokenizer(selection);
       if (tokenizer.hasMoreTokens()) offset = Integer.valueOf(tokenizer.nextToken()).intValue();
       if (tokenizer.hasMoreTokens()) length = Integer.valueOf(tokenizer.nextToken()).intValue();
       if (offset >= 0 && length >= 0) {
         fSelectionStart = offset;
         fSelectionLength = length;
       } else
         return RefactoringStatus.createFatalErrorStatus(
             Messages.format(
                 RefactoringCoreMessages.InitializableRefactoring_illegal_argument,
                 new Object[] {selection, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION}));
     } else
       return RefactoringStatus.createFatalErrorStatus(
           Messages.format(
               RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
               JDTRefactoringDescriptor.ATTRIBUTE_SELECTION));
     final String handle = extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
     if (handle != null) {
       final IJavaScriptElement element =
           JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
       if (element == null
           || !element.exists()
           || element.getElementType() != IJavaScriptElement.JAVASCRIPT_UNIT)
         return createInputFatalStatus(element, IJavaScriptRefactorings.EXTRACT_CONSTANT);
       else fCu = (IJavaScriptUnit) element;
     } else
       return RefactoringStatus.createFatalErrorStatus(
           Messages.format(
               RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
               JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
     final String visibility = extended.getAttribute(ATTRIBUTE_VISIBILITY);
     if (visibility != null && !"".equals(visibility)) { // $NON-NLS-1$
       int flag = 0;
       try {
         flag = Integer.parseInt(visibility);
       } catch (NumberFormatException exception) {
         return RefactoringStatus.createFatalErrorStatus(
             Messages.format(
                 RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
                 ATTRIBUTE_VISIBILITY));
       }
       fVisibility = JdtFlags.getVisibilityString(flag);
     }
     final String name = extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
     if (name != null && !"".equals(name)) // $NON-NLS-1$
     fConstantName = name;
     else
       return RefactoringStatus.createFatalErrorStatus(
           Messages.format(
               RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
               JDTRefactoringDescriptor.ATTRIBUTE_NAME));
     final String replace = extended.getAttribute(ATTRIBUTE_REPLACE);
     if (replace != null) {
       fReplaceAllOccurrences = Boolean.valueOf(replace).booleanValue();
     } else
       return RefactoringStatus.createFatalErrorStatus(
           Messages.format(
               RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
               ATTRIBUTE_REPLACE));
     final String declareFinal = extended.getAttribute(ATTRIBUTE_QUALIFY);
     if (declareFinal != null) {
       fQualifyReferencesWithDeclaringClassName = Boolean.valueOf(declareFinal).booleanValue();
     } else
       return RefactoringStatus.createFatalErrorStatus(
           Messages.format(
               RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
               ATTRIBUTE_QUALIFY));
   } else
     return RefactoringStatus.createFatalErrorStatus(
         RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
   return new RefactoringStatus();
 }
 /** Returns whether the two java elements are equals and have the same parent. */
 protected boolean equalsAndSameParent(IJavaScriptElement e1, IJavaScriptElement e2) {
   IJavaScriptElement parent1;
   return e1.equals(e2) && ((parent1 = e1.getParent()) != null) && parent1.equals(e2.getParent());
 }
 /* (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;
 }