/**
   * add FlagImangesSet to Properties, which needn't to change the dir level, just ouput to the
   * ouput dir.
   *
   * @param prop job configuration
   * @param key list name
   * @param set relative flag image files
   */
  private void addFlagImagesSetToProperties(
      final Job prop, final String key, final Set<String> set) {
    String value = null;
    final Set<String> newSet = new LinkedHashSet<String>(INT_128);
    for (final String file : set) {
      if (new File(file).isAbsolute()) {
        // no need to append relative path before absolute paths
        newSet.add(FileUtils.normalize(file));
      } else {
        // In ant, all the file separator should be slash, so we need to
        // replace all the back slash with slash.
        newSet.add(
            FileUtils.separatorsToUnix(
                FileUtils.normalize(new StringBuffer().append(file).toString())));
      }
    }

    // write list attribute to file
    final String fileKey = key.substring(0, key.lastIndexOf("list")) + "file";
    prop.setProperty(fileKey, key.substring(0, key.lastIndexOf("list")) + ".list");
    final File list = new File(tempDir, prop.getProperty(fileKey));
    Writer bufferedWriter = null;
    try {
      bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(list)));
      final Iterator<String> it = newSet.iterator();
      while (it.hasNext()) {
        bufferedWriter.write(it.next());
        if (it.hasNext()) {
          bufferedWriter.write("\n");
        }
      }
      bufferedWriter.flush();
      bufferedWriter.close();
    } catch (final FileNotFoundException e) {
      logger.logException(e);
    } catch (final IOException e) {
      logger.logException(e);
    } finally {
      if (bufferedWriter != null) {
        try {
          bufferedWriter.close();
        } catch (final IOException e) {
          logger.logException(e);
        }
      }
    }

    value = StringUtils.assembleString(newSet, COMMA);

    prop.setProperty(key, value);

    // clear set
    set.clear();
    newSet.clear();
  }
 /**
  * Add key definition to job configuration
  *
  * @param prop job configuration
  * @param key list name
  * @param set key defintions to add
  */
 private void addKeyDefSetToProperties(
     final Job prop, final String key, final Collection<KeyDef> set) {
   // update value
   final Collection<KeyDef> updated = new ArrayList<KeyDef>(set.size());
   for (final KeyDef file : set) {
     String keys = FileUtils.separatorsToUnix(FileUtils.normalize(prefix + file.keys));
     String href = file.href;
     String source = file.source;
     if (prefix.length() != 0) {
       // cases where keymap is in map ancestor folder
       keys = keys.substring(prefix.length());
       if (href == null) {
         // href = FileUtils.separatorsToUnix(FileUtils.normalize(prefix));
         source = FileUtils.separatorsToUnix(FileUtils.normalize(prefix + source));
       } else {
         if (!exKeyDefMap.containsKey(file.keys)) {
           href = FileUtils.separatorsToUnix(FileUtils.normalize(prefix + href));
         }
         source = FileUtils.separatorsToUnix(FileUtils.normalize(prefix + source));
       }
     }
     final KeyDef keyDef = new KeyDef(keys, href, source);
     updated.add(keyDef);
   }
   // write key definition
   try {
     writeKeydef(new File(tempDir, "keydef.xml"), updated);
   } catch (final DITAOTException e) {
     logger.logError("Failed to write key definition file: " + e.getMessage(), e);
   }
   // write list file
   final Set<String> newSet = new LinkedHashSet<String>(set.size());
   for (final KeyDef keydef : updated) {
     newSet.add(keydef.toString());
   }
   prop.setSet(key, newSet);
   final String fileKey = key.substring(0, key.lastIndexOf("list")) + "file";
   prop.setProperty(fileKey, key.substring(0, key.lastIndexOf("list")) + ".list");
   try {
     prop.writeList(key);
   } catch (final IOException e) {
     logger.logError("Failed to write key list file: " + e.getMessage(), e);
   }
 }
  /**
   * Add set of values of job configuration
   *
   * @param prop job configuration
   * @param key list name
   * @param set values to add
   */
  private void addSetToProperties(final Job prop, final String key, final Set<String> set) {
    // update value
    final Set<String> newSet = new LinkedHashSet<String>(INT_128);
    for (final String file : set) {
      if (new File(file).isAbsolute()) {
        // no need to append relative path before absolute paths
        newSet.add(FileUtils.normalize(file));
      } else {
        // In ant, all the file separator should be slash, so we need to
        // replace all the back slash with slash.
        final int index = file.indexOf(EQUAL);
        if (index != -1) {
          // keyname
          final String to = file.substring(0, index);
          final String source = file.substring(index + 1);

          newSet.add(
              FileUtils.separatorsToUnix(
                      FileUtils.normalize(new StringBuffer(prefix).append(to).toString()))
                  + EQUAL
                  + FileUtils.separatorsToUnix(
                      FileUtils.normalize(new StringBuffer(prefix).append(source).toString())));
        } else {
          newSet.add(
              FileUtils.separatorsToUnix(
                  FileUtils.normalize(new StringBuffer(prefix).append(file).toString())));
        }
      }
    }
    prop.setSet(key, newSet);
    // write list file
    final String fileKey = key.substring(0, key.lastIndexOf("list")) + "file";
    prop.setProperty(fileKey, key.substring(0, key.lastIndexOf("list")) + ".list");
    try {
      prop.writeList(key);
    } catch (final IOException e) {
      logger.logError("Failed to write list file: " + e.getMessage(), e);
    }
  }
  /**
   * Update uplevels if needed.
   *
   * @param file file path
   */
  private void updateUplevels(String file) {

    // Added by william on 2009-08-06 for bug:2832696 start
    if (file.contains(STICK)) {
      file = file.substring(0, file.indexOf(STICK));
    }
    // Added by william on 2009-08-06 for bug:2832696 end

    // for uplevels (../../)
    // modified start by wxzhang 20070518
    // ".."-->"../"
    final int lastIndex = FileUtils.separatorsToUnix(FileUtils.normalize(file)).lastIndexOf("../");
    // modified end by wxzhang 20070518
    if (lastIndex != -1) {
      final int newUplevels = lastIndex / 3 + 1;
      uplevels = newUplevels > uplevels ? newUplevels : uplevels;
    }
  }
  private void parseInputParameters(final AbstractPipelineInput input) {
    final String basedir = input.getAttribute(ANT_INVOKER_PARAM_BASEDIR);
    final String ditaInput = input.getAttribute(ANT_INVOKER_PARAM_INPUTMAP);

    tempDir = input.getAttribute(ANT_INVOKER_PARAM_TEMPDIR);
    ditaDir = input.getAttribute(ANT_INVOKER_EXT_PARAM_DITADIR);
    ditavalFile = input.getAttribute(ANT_INVOKER_PARAM_DITAVAL);
    xmlValidate = Boolean.valueOf(input.getAttribute(ANT_INVOKER_EXT_PARAM_VALIDATE));

    // Added by William on 2009-07-18 for req #12014 start
    // get transtype
    transtype = input.getAttribute(ANT_INVOKER_EXT_PARAM_TRANSTYPE);
    // Added by William on 2009-07-18 for req #12014 start

    gramcache = "yes".equalsIgnoreCase(input.getAttribute(ANT_INVOKER_EXT_PARAM_GRAMCACHE));
    setSystemid = "yes".equalsIgnoreCase(input.getAttribute(ANT_INVOKER_EXT_PARAN_SETSYSTEMID));

    // For the output control
    outputUtils = new OutputUtils();
    outputUtils.setGeneratecopyouter(input.getAttribute(ANT_INVOKER_EXT_PARAM_GENERATECOPYOUTTER));
    outputUtils.setOutterControl(input.getAttribute(ANT_INVOKER_EXT_PARAM_OUTTERCONTROL));
    outputUtils.setOnlyTopicInMap(input.getAttribute(ANT_INVOKER_EXT_PARAM_ONLYTOPICINMAP));

    // Set the OutputDir
    final File path = new File(input.getAttribute(ANT_INVOKER_EXT_PARAM_OUTPUTDIR));
    if (path.isAbsolute()) {
      outputUtils.setOutputDir(path.getAbsolutePath());
    } else {
      throw new IllegalArgumentException("Output directory " + tempDir + " must be absolute");
    }

    // Resolve relative paths base on the basedir.
    File inFile = new File(ditaInput);
    if (!inFile.isAbsolute()) {
      // XXX Shouldn't this be resolved to current directory, not Ant script base directory?
      inFile = new File(basedir, ditaInput);
    }
    try {
      inFile = inFile.getCanonicalFile();
    } catch (final IOException e1) {
      logger.logException(e1);
    }
    if (!new File(tempDir).isAbsolute()) {
      throw new IllegalArgumentException("Temporary directory " + tempDir + " must be absolute");
    } else {
      tempDir = FileUtils.normalize(tempDir);
    }
    if (!new File(ditaDir).isAbsolute()) {
      throw new IllegalArgumentException(
          "DITA-OT installation directory " + tempDir + " must be absolute");
    } else {
      ditaDir = FileUtils.normalize(ditaDir);
    }
    if (ditavalFile != null && !new File(ditavalFile).isAbsolute()) {
      // XXX Shouldn't this be resolved to current directory, not Ant script base directory?
      ditavalFile = new File(basedir, ditavalFile).getAbsolutePath();
    }

    baseInputDir = new File(inFile.getAbsolutePath()).getParent();
    baseInputDir = FileUtils.normalize(baseInputDir);

    rootFile = inFile.getAbsolutePath();
    rootFile = FileUtils.normalize(rootFile);

    inputFile = inFile.getName();
    try {
      // Added by William on 2009-06-09 for scheme key bug
      // create the keydef file for scheme files
      schemekeydef =
          XMLSerializer.newInstance(new FileOutputStream(new File(tempDir, "schemekeydef.xml")));
      schemekeydef.writeStartDocument();
      schemekeydef.writeStartElement(ELEMENT_STUB);

      // Added by William on 2009-06-25 for req #12014 start
      // create the export file for exportanchors
      // write the head
      export =
          new OutputStreamWriter(new FileOutputStream(new File(tempDir, FILE_NAME_EXPORT_XML)));
      export.write(XML_HEAD);
      export.write("<stub>");
      // Added by William on 2009-06-25 for req #12014 end
    } catch (final FileNotFoundException e) {
      logger.logException(e);
    } catch (final IOException e) {
      logger.logException(e);
    } catch (final SAXException e) {
      logger.logException(e);
    }

    // Set the mapDir
    outputUtils.setInputMapPathName(inFile.getAbsolutePath());
  }