/**
   * Update the full library list, including indirect dependencies. The result is returned by {@link
   * #getFullLibraryProjects()}.
   */
  void updateFullLibraryList() {
    ArrayList<IProject> list = new ArrayList<IProject>();
    synchronized (mLibraries) {
      buildFullLibraryDependencies(mLibraries, list);
    }

    mLibraryProjects = Collections.unmodifiableList(list);
  }
  /**
   * Resolves a given list of libraries, finds out if they depend on other libraries, and returns a
   * full list of all the direct and indirect dependencies in the proper order (first is higher
   * priority when calling aapt).
   *
   * @param inLibraries the libraries to resolve
   * @param outLibraries where to store all the libraries.
   */
  private void buildFullLibraryDependencies(
      List<LibraryState> inLibraries, ArrayList<IProject> outLibraries) {
    // loop in the inverse order to resolve dependencies on the libraries, so that if a library
    // is required by two higher level libraries it can be inserted in the correct place
    for (int i = inLibraries.size() - 1; i >= 0; i--) {
      LibraryState library = inLibraries.get(i);

      // get its libraries if possible
      ProjectState libProjectState = library.getProjectState();
      if (libProjectState != null) {
        List<LibraryState> dependencies = libProjectState.getLibraries();

        // build the dependencies for those libraries
        buildFullLibraryDependencies(dependencies, outLibraries);

        // and add the current library (if needed) in front (higher priority)
        if (outLibraries.contains(libProjectState.getProject()) == false) {
          outLibraries.add(0, libProjectState.getProject());
        }
      }
    }
  }