/**
     * Constructor for class BackupAssociation
     *
     * @param assoc given Association (not null)
     * @param regLeve given regLevel
     */
    protected BackupAssociation(Association assoc, int regLevel) {
      curMimeType = assoc.getMimeType();

      Iterator iter = null;
      List temFileExtList = assoc.getFileExtList();
      if (temFileExtList != null) {
        iter = temFileExtList.iterator();
      }
      if (iter != null) {
        if (iter.hasNext()) {
          curFileExt = (String) iter.next();
        }
      }

      if (curMimeType != null) {
        curMimeTypeExisted = WinRegistryUtil.isMimeTypeExist(curMimeType, regLevel);
      } else {
        curMimeTypeExisted = false;
      }

      if (curFileExt != null) {
        curFileExtExisted = WinRegistryUtil.isFileExtExist(curFileExt, regLevel);
      } else {
        curFileExtExisted = false;
      }

      if (curMimeTypeExisted) {
        backupFileExt = WinRegistryUtil.getFileExtByMimeType(curMimeType, regLevel);
      }

      if (curFileExtExisted) {
        backupClassID = WinRegistryUtil.getClassIDByFileExt(curFileExt, regLevel);
        backupMimeType = WinRegistryUtil.getMimeTypeByFileExt(curFileExt, regLevel);
      }
    }
 /**
  * Checks whether the given assocation is valid for unregistration. If both the mimeType and
  * fileExtensionList field is null, throw exception.
  *
  * @param assoc a given Association object.
  * @param level a given MIME database level.
  * @throws IllegalArgumentException if the given association is not valid for unregistration.
  */
 public void checkAssociationValidForUnregistration(Association assoc)
     throws IllegalArgumentException {
   boolean isFileExtListEmpty = true;
   if (assoc.getFileExtList() != null) {
     isFileExtListEmpty = assoc.getFileExtList().isEmpty();
   }
   if ((assoc.getMimeType() == null) && isFileExtListEmpty) {
     throw new IllegalArgumentException(
         "The given association is invalid. It should "
             + "specify both the mimeType and fileExtensionList fields to perform this operation.");
   }
 }
  /**
   * Checks whether the given assocation is valid for registration.
   *
   * <PRE>
   * 1. The file extension list and mime type can't all be null
   * 2. If any of the fileds: description, iconFile, actionList is not null,
   *    then fileExtensionList should not be empty
   * </PRE>
   *
   * @param assoc a given Association object.
   * @param level a given MIME database level.
   * @throws IllegalArgumentException if the given association is not valid for registration.
   */
  public void checkAssociationValidForRegistration(Association assoc)
      throws IllegalArgumentException {
    boolean isActionListEmpty = true;
    boolean isFileExtensionEmpty = true;
    boolean isValid = false;

    // Check if actionlist is empty
    if (assoc.getActionList() != null) {
      isActionListEmpty = assoc.getActionList().isEmpty();
    }
    // Check if file extension list is empty
    if (assoc.getFileExtList() != null) {
      isFileExtensionEmpty = assoc.getFileExtList().isEmpty();
    }

    if (isFileExtensionEmpty && (assoc.getMimeType() == null)) {
      isValid = false;
    } else if ((assoc.getDescription() != null)
        || (assoc.getIconFileName() != null)
        || (!isActionListEmpty)) {
      isValid = !isFileExtensionEmpty;
    } else {
      isValid = true;
    }

    if (!isValid) {
      throw new IllegalArgumentException(
          "The given association is invalid. It should "
              + "specify both the mimeType and fileExtensionList fields to perform this operation.");
    }
  }
  /**
   * Checks whether the given assocation already existed in Windows registry.
   *
   * <PRE>
   * The evaluation will based on the following rule:
   * 1. mimetype == null && fileExt == null
   *    return false
   * 2. mimetype == null && fileExt != null
   *    return !(fileExt existed in the reg table)
   * 3. mimetype != null && fileExt == null
   *    return !(mimetype existed in the reg table)
   * 4. mimetype != null && fileExt != null
   *    return ( (mimetype existed in the reg table) &&
   *             (fileExt existed in the reg table) &&
   *             (getFileExtByMimeType(mimetype) == fileExt) &&
   *             (getMimeTypeByFileExt(fileExt) == mimetype) )
   * </PRE>
   *
   * @param assoc given association (not null)
   * @param regLevel given registry level
   * @return true if the given association existed
   */
  public boolean isAssociationExist(Association assoc, int regLevel) {
    String temFileExt = null;
    String temMimeType = assoc.getMimeType();
    Iterator temFileExtIter;
    if (assoc.getFileExtList() != null) {
      temFileExtIter = assoc.getFileExtList().iterator();
    } else {
      temFileExtIter = null;
    }

    if (temFileExtIter != null) {
      if (temFileExtIter.hasNext()) {
        temFileExt = (String) temFileExtIter.next();
      }
    }

    // Check if there is the same file extension define in Win2k
    // HKEY_CURRENT_USER\\software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts
    if (WinRegistryUtil.isWin2kUserDefinedFileExtExist(temFileExt)) {
      return true;
    }

    if ((temMimeType == null) && (temFileExt == null)) {
      return false;
    } else if ((temMimeType == null) && (temFileExt != null)) {
      return WinRegistryUtil.isFileExtExist(temFileExt, regLevel);
    } else if ((temMimeType != null) && (temFileExt == null)) {
      return WinRegistryUtil.isMimeTypeExist(temMimeType, regLevel);
    } else {
      String regMimeType = WinRegistryUtil.getMimeTypeByFileExt(temFileExt, regLevel);
      String regFileExt = WinRegistryUtil.getFileExtByMimeType(temMimeType, regLevel);

      return ((WinRegistryUtil.isMimeTypeExist(temMimeType, regLevel))
          && (WinRegistryUtil.isFileExtExist(temFileExt, regLevel))
          && (temFileExt == null ? regFileExt == null : temFileExt.equals(regFileExt))
          && (temMimeType == null ? regMimeType == null : temMimeType.equals(regMimeType)));
    }
  }
  /**
   * Registers the given association info in the specified level.
   *
   * <PRE>
   *
   * The register process will following the rules below
   * 1. mimetype == null && fileExt != null
   *    Since fileExt does not exist in this case
   *    1.1 adds the fileExt
   *    1.2 adds description, icon file and action list for this fileExt
   * 2. mimetype != null && fileExt == null
   *    Since mimetype does not exist in this case
   *    just adds the mimetype in the reg table
   * 3. mimetype != null && fileExt != null
   *    3.1 Adds the mime type into the reg table if necessary
   *    3.2 Adds the file extension into the reg table if necessary
   *    3.3 Adds the description, icon file and action list for the fileExt
   *    3.4 Sets the mutual reference of the mime type and file extension
   * </PRE>
   *
   * @param assoc given association (not null)
   * @param regLevel given registry level
   */
  public void registerAssociation(Association assoc, int regLevel) throws RegisterFailedException {
    // Note: Windows 98, Windows ME & Windows NT will only take care of registry information from
    // LOCAL_MACHINE. Association, in this case, should only be written into LOCAL_MACHINE rather
    // than the CURRENT_USER.
    boolean isOldWindows = false;
    String osName = System.getProperty("os.name").toLowerCase();
    if ((osName.indexOf("98") != -1)
        || (osName.indexOf("me") != -1)
        || (osName.indexOf("nt") != -1)) {
      isOldWindows = true;
    }
    if (isOldWindows) {
      regLevel = AppConstants.SYSTEM_LEVEL;
    }
    BackupAssociation backupAssoc = new BackupAssociation(assoc, regLevel);
    String curMimeType = backupAssoc.getCurMimeType();
    String curFileExt = backupAssoc.getCurFileExt();
    String curDescription = assoc.getDescription();
    String curIconFileName = assoc.getIconFileName();
    List curActionList = assoc.getActionList();
    boolean curMimeTypeExisted = backupAssoc.getCurMimeTypeExisted();
    boolean curFileExtExisted = backupAssoc.getCurFileExtExisted();

    try {
      if ((curMimeType == null) && (curFileExt != null)) {
        WinRegistryUtil.addFileExt(curFileExt, regLevel);
        if (curDescription != null) {
          WinRegistryUtil.setDescriptionByFileExt(curDescription, curFileExt, regLevel);
        }
        if (curIconFileName != null) {
          WinRegistryUtil.setIconFileNameByFileExt(curIconFileName, curFileExt, regLevel);
        }
        if (curActionList != null) {
          WinRegistryUtil.setActionListByFileExt(curActionList, curFileExt, regLevel);
        }
        // Mark the classID generator field
        WinRegistryUtil.markGeneratorByFileExt(curFileExt, regLevel);
      } else if ((curMimeType != null) && (curFileExt == null)) {
        WinRegistryUtil.addMimeType(curMimeType, regLevel);
      } else if ((curMimeType != null) && (curFileExt != null)) {
        if (!curMimeTypeExisted) {
          WinRegistryUtil.addMimeType(curMimeType, regLevel);
        }
        if (!curFileExtExisted) {
          WinRegistryUtil.addFileExt(curFileExt, regLevel);
        }
        if (curDescription != null) {
          WinRegistryUtil.setDescriptionByFileExt(curDescription, curFileExt, regLevel);
        }
        if (curIconFileName != null) {
          WinRegistryUtil.setIconFileNameByFileExt(curIconFileName, curFileExt, regLevel);
        }
        if (curActionList != null) {
          WinRegistryUtil.setActionListByFileExt(curActionList, curFileExt, regLevel);
        }
        // Mark the classID generator field.
        WinRegistryUtil.markGeneratorByFileExt(curFileExt, regLevel);
        WinRegistryUtil.setMutualRef(curFileExt, curMimeType, regLevel);
      }
    } catch (RegisterFailedException e) { // Question write to file. log.
      restoreAssociationRegistration(backupAssoc, regLevel);

      throw e;
    }
  }