public void updateCachedFilePaths(String pattern, HashMap<String, String> explicitChangeSets) {
    // FIXME
    // There might be concurrent exception risk here
    if (explicitChangeSets != null && explicitChangeSets.size() > 0) {
      ArrayList<String> targetCaches;
      if (FilePathUrlManager.SMART_MUSIC.equals(pattern)) {
        targetCaches = mAudioPatternFilePaths;
      } else if (FilePathUrlManager.SMART_IMAGE.equals(pattern)) {
        targetCaches = mImagePatternFilePaths;
      } else if (FilePathUrlManager.SMART_MOVIES.equals(pattern)) {
        targetCaches = mVideoPatternFilePaths;
      } else if (FilePathUrlManager.SMART_APK.equals(pattern)) {
        targetCaches = mApkPatternFilePaths;
      } else {
        return;
      }

      if (targetCaches == null) {
        return;
      }

      for (String oldValue : explicitChangeSets.keySet()) {
        if (targetCaches.contains(oldValue)) {
          int index = targetCaches.indexOf(oldValue);
          String newValue = explicitChangeSets.get(oldValue);
          if (newValue != null) {
            targetCaches.set(index, explicitChangeSets.get(oldValue));
          } else {
            targetCaches.remove(oldValue);
          }
        } else {
          if (FileUtil.NEW_GENERATED_FILE.equals(oldValue)) {
            targetCaches.add(explicitChangeSets.get(oldValue));
          }
        }
      }
    }
  }
  @SuppressWarnings("unchecked")
  private ArrayList<String> populateCurrentUrlContent() {
    if (!mCurrentUrlContent.isEmpty()) {
      mCurrentUrlContent.clear();
    }

    // Smart folder mode
    // Return clone list instead the pattern file path list itself,
    // because they maybe get modified by setter method when caller of this
    // method is using the list
    if (FilePathUrlManager.SMART_MUSIC.equals(getSmartPattern(getCurrentUrl()))) {
      return (ArrayList<String>) mAudioPatternFilePaths.clone();
    } else if (FilePathUrlManager.SMART_IMAGE.equals(getSmartPattern(getCurrentUrl()))) {
      return (ArrayList<String>) mImagePatternFilePaths.clone();
    } else if (FilePathUrlManager.SMART_MOVIES.equals(getSmartPattern(getCurrentUrl()))) {
      return (ArrayList<String>) mVideoPatternFilePaths.clone();
    } else if (FilePathUrlManager.SMART_APK.equals(getSmartPattern(getCurrentUrl()))) {
      return (ArrayList<String>) mApkPatternFilePaths.clone();
    } else if (FilePathUrlManager.SMART_FILE.equals(getSmartPattern(getCurrentUrl()))) {
      String searchId = buildSearchId(getQueryStr(getCurrentUrl()), getDir(getCurrentUrl()));
      Log.i(TAG, "search id: " + searchId);
      ArrayList<String> searchRecord = mSearchPatternFilePaths.get(searchId);
      if (searchRecord != null) {
        return (ArrayList<String>) searchRecord.clone();
      } else {
        return null;
      }
    }

    // Common folder mode
    File file = new File(getCurrentUrl());

    if (file.exists() && file.canRead()) {
      String currentPath = file.getPath();
      if (!currentPath.equals(mLastMonitoringPath)) {
        // monitoring the new current directory
        if (mCurrentDirMonitor != null) {
          mCurrentDirMonitor.stopWatching();
        }
        mCurrentDirMonitor = new DirectoryMonitor(currentPath, FilePathUrlManager.this);
        mCurrentDirMonitor.startWatching();
        mLastMonitoringPath = currentPath;
      }

      String[] children = file.list();
      if (children != null) {
        int len = children.length;

        /* add files/folder to ArrayList depending on hidden status */
        for (int i = 0; i < len; i++) {
          if (!mShowHiddenFiles) {
            if (children[i].toString().charAt(0) != '.') {
              if (currentPath.endsWith("/")) {
                mCurrentUrlContent.add(currentPath + children[i]);
              } else {
                mCurrentUrlContent.add(currentPath + "/" + children[i]);
              }
            }
          } else {
            mCurrentUrlContent.add(file.getPath() + "/" + children[i]);
          }
        }
      }

      /* sort the ArrayList that was made from above for loop */
      switch (mPreSortType) {
        case SORT_NONE:
          // no sorting needed
          break;
        case SORT_ALPHA:
          Object[] tt = mCurrentUrlContent.toArray();
          mCurrentUrlContent.clear();

          Arrays.sort(tt, mAlphComparator);

          for (Object a : tt) {
            mCurrentUrlContent.add((String) a);
          }
          break;
      }
    }

    return mCurrentUrlContent;
  }