Пример #1
0
  /**
   * Set the match pattern in the reader. The match pattern is used to see whether current element
   * can be include in the result of parsing.
   *
   * @param matchPattern the match pattern
   */
  public void setMatch(final String matchPattern) {
    int index = 0;
    firstMatchElement =
        (matchPattern.indexOf(SLASH) != -1)
            ? matchPattern.substring(0, matchPattern.indexOf(SLASH))
            : matchPattern;

    while (index != -1) {
      final int start = matchPattern.indexOf(SLASH, index);
      final int end = matchPattern.indexOf(SLASH, start + 1);
      if (start != -1 && end != -1) {
        lastMatchElement.add(matchPattern.substring(start + 1, end));
        index = end;
      } else if (start != -1 && end == -1) {
        lastMatchElement.add(matchPattern.substring(start + 1));
        index = -1;
      }
    }
    matchList.add(firstMatchElement);
    final Iterator<String> it = lastMatchElement.iterator();
    final StringBuffer sb = new StringBuffer();
    while (it.hasNext()) {
      sb.append(it.next() + STRING_BLANK);
    }
    matchList.add(sb.toString());
  }
Пример #2
0
  @Override
  public void endElement(final String uri, final String localName, final String qName)
      throws SAXException {

    if (match) {
      if (validHref) {
        indexEntries.append(LESS_THAN);
        indexEntries.append(SLASH);
        indexEntries.append(qName);
        indexEntries.append(GREATER_THAN);
      }

      level--;
    }

    if (lastMatchElement.contains(qName) && level == 0) {
      if (match) {
        match = false;
      }
    }
    if (!match) {
      ancestorList.remove(ancestorList.size() - 1);
    }

    if (qName.equals(firstMatchElement) && verifyIndexEntries(indexEntries) && topicPath != null) {
      // if the href is not valid, topicPath will be null. We don't need to set the condition
      // to check validHref at here.
      /*
         String origin = (String) map.get(topicPath);
         if (origin != null) {
             map.put(topicPath, origin + indexEntries.toString());
         } else {
             map.put(topicPath, indexEntries.toString());
         }
         indexEntries = new StringBuffer(INT_1024);
      */
      String t = topicPath;
      String frag = SHARP;
      // Get topic id
      if (t.contains(SHARP)) {
        frag = t.indexOf(SHARP) + 1 >= t.length() ? SHARP : t.substring(t.indexOf(SHARP) + 1);
        // remove the "#" in topic file path
        t = t.substring(0, t.indexOf(SHARP));
      }
      Map<String, String> m = map.get(t);
      if (m != null) {
        final String orig = m.get(frag);
        m.put(frag, StringUtils.setOrAppend(orig, indexEntries.toString(), false));
      } else {
        m = new HashMap<String, String>(INT_16);
        m.put(frag, indexEntries.toString());
        map.put(t, m);
      }
      // TODO Added by William on 2009-06-16 for bug:2791696 reltable bug start
      indexEntries = new StringBuffer(INT_1024);
      // TODO Added by William on 2009-06-16 for bug:2791696 reltable bug end

    }
  }
Пример #3
0
 /**
  * Get index file name.
  *
  * @param outputFileRoot root path
  * @return index file name
  */
 @Override
 public String getIndexFileName(final String outputFileRoot) {
   final File indexDir = new File(outputFileRoot).getParentFile();
   setFilePath(indexDir.getAbsolutePath());
   final StringBuffer indexFilename =
       new StringBuffer(new File(indexDir, "index.xml").getAbsolutePath());
   return indexFilename.toString();
 }
 /**
  * Get up-levels relative path.
  *
  * @return path to up-level
  */
 private String getUpdateLevels() {
   int current = uplevels;
   final StringBuffer buff = new StringBuffer();
   while (current > 0) {
     buff.append(".." + FILE_SEPARATOR);
     current--;
   }
   return buff.toString();
 }
Пример #5
0
 /** Check whether the index entries we got is meaningful and valid */
 private static boolean verifyIndexEntries(final StringBuffer str) {
   if (str.length() == 0) {
     return false;
   }
   final int start = str.indexOf(GREATER_THAN); // start from first tag's end
   final int end = str.lastIndexOf(LESS_THAN); // end at last tag's start
   final String temp = str.substring(start + 1, end);
   if (temp.trim().length() != 0) {
     return true;
   }
   return false;
 }
Пример #6
0
  /**
   * Append XML content into root element
   *
   * @param hrefValue href of the topicref
   * @param parentResult XML content to insert into
   * @param tmpContent XML content to insert
   */
  private void insertAfter(String hrefValue, StringBuffer parentResult, CharSequence tmpContent) {
    int insertpoint = parentResult.lastIndexOf("</");
    final int end = parentResult.indexOf(">", insertpoint);

    if (insertpoint == -1 || end == -1) {
      logger.error(MessageUtils.getInstance().getMessage("DOTJ033E", hrefValue).toString());
    } else {
      if (ELEMENT_NAME_DITA.equals(parentResult.substring(insertpoint, end).trim())) {
        insertpoint = parentResult.lastIndexOf("</", insertpoint - 1);
      }
      parentResult.insert(insertpoint, tmpContent);
    }
  }
Пример #7
0
 @Override
 public void startEntity(final String name) throws SAXException {
   needResolveEntity = StringUtils.checkEntity(name);
   if (match && !needResolveEntity && validHref) {
     indexEntries.append(StringUtils.getEntity(name));
   }
 }
Пример #8
0
  @Override
  public void read(final String filename) {
    if (matchList.isEmpty()) {
      throw new IllegalStateException("matchList not initialized");
    }

    match = false;
    needResolveEntity = true;
    inputFile = new File(filename);
    filePath = inputFile.getParent();
    inputFile.getPath();
    if (indexEntries.length() != 0) {
      // delete all the content in indexEntries
      indexEntries = new StringBuffer(INT_1024);
    }

    try {
      reader.setErrorHandler(new DITAOTXMLErrorHandler(filename, logger));
      final InputSource source =
          URIResolverAdapter.convertToInputSource(
              DitaURIResolverFactory.getURIResolver().resolve(filename, null));
      reader.parse(source);
    } catch (final Exception e) {
      logger.logException(e);
    }
  }
Пример #9
0
  @Override
  public void characters(final char[] ch, final int start, final int length) throws SAXException {

    if (match && needResolveEntity && validHref) {
      final String temp = new String(ch, start, length);
      indexEntries.append(StringUtils.escapeXML(temp));
    }
  }
Пример #10
0
  @Override
  public void ignorableWhitespace(final char[] ch, final int start, final int length)
      throws SAXException {

    if (match && validHref) {
      final String temp = new String(ch, start, length);
      indexEntries.append(temp);
    }
  }
Пример #11
0
  @Override
  public void processingInstruction(final String target, final String data) throws SAXException {

    final String pi = (data != null) ? target + STRING_BLANK + data : target;

    if (match && needResolveEntity && validHref) {
      final String temp =
          LESS_THAN + QUESTION + StringUtils.escapeXML(pi) + QUESTION + GREATER_THAN;
      indexEntries.append(temp);
    }
  }
Пример #12
0
  @Override
  public void startElement(
      final String uri, final String localName, final String qName, final Attributes atts)
      throws SAXException {
    final int attsLen = atts.getLength();
    final String attrScope = atts.getValue(ATTRIBUTE_NAME_SCOPE);
    final String attrFormat = atts.getValue(ATTRIBUTE_NAME_FORMAT);

    if (qName.equals(firstMatchElement)) {
      final String hrefValue = atts.getValue(ATTRIBUTE_NAME_HREF);
      if (verifyIndexEntries(indexEntries) && topicPath != null) {
        /*
        String origin = (String) map.get(topicPath);
        map.put(topicPath, StringUtils.setOrAppend(origin, indexEntries.toString(), false));
         */
        String t = topicPath;
        String frag = SHARP;
        if (t.contains(SHARP)) {
          frag = t.indexOf(SHARP) + 1 >= t.length() ? SHARP : t.substring(t.indexOf(SHARP) + 1);
          t = t.substring(0, t.indexOf(SHARP));
        }
        Map<String, String> m = map.get(t);
        if (m != null) {
          final String orig = m.get(frag);
          m.put(frag, StringUtils.setOrAppend(orig, indexEntries.toString(), false));
        } else {
          m = new HashMap<String, String>(INT_16);
          m.put(frag, indexEntries.toString());
          map.put(t, m);
        }
        indexEntries = new StringBuffer(INT_1024);
      }
      topicPath = null;
      if (hrefValue != null
          && hrefValue.indexOf(INTERNET_LINK_MARK) == -1
          && (attrScope == null || ATTR_SCOPE_VALUE_LOCAL.equalsIgnoreCase(attrScope))
          && (attrFormat == null || ATTR_FORMAT_VALUE_DITA.equalsIgnoreCase(attrFormat))) {
        // If the href is internal dita topic file
        topicPath = FileUtils.resolveTopic(filePath, hrefValue);
        validHref = true;
      } else {
        // set up the boolean to prevent the invalid href's metadata inserted into indexEntries.
        topicPath = null;
        validHref = false;
      }
    }
    if (!match) {
      ancestorList.add(qName);
      if (lastMatchElement.contains(qName) && checkMatch()) {

        match = true;
        level = 0;
      }
    }

    if (match) {
      if (validHref) {
        indexEntries.append(LESS_THAN + qName + STRING_BLANK);

        for (int i = 0; i < attsLen; i++) {
          indexEntries.append(atts.getQName(i));
          indexEntries.append(EQUAL);
          indexEntries.append(QUOTATION);
          indexEntries.append(StringUtils.escapeXML(atts.getValue(i)));
          indexEntries.append(QUOTATION);
          indexEntries.append(STRING_BLANK);
        }

        indexEntries.append(GREATER_THAN);
      }
      level++;
    }
  }
Пример #13
0
 @Override
 public void startCDATA() throws SAXException {
   if (match && validHref) {
     indexEntries.append(CDATA_HEAD);
   }
 }
  private void processFile(String currentFile) throws DITAOTException {
    File fileToParse;
    final File file = new File(currentFile);
    if (file.isAbsolute()) {
      fileToParse = file;
      currentFile = FileUtils.getRelativePath(rootFile, currentFile);
    } else {
      fileToParse = new File(baseInputDir, currentFile);
    }
    try {
      fileToParse = fileToParse.getCanonicalFile();
    } catch (final IOException e1) {
      logger.logError(e1.toString());
    }
    logger.logInfo("Processing " + fileToParse.getAbsolutePath());
    String msg = null;
    final Properties params = new Properties();
    params.put("%1", currentFile);

    if (!fileToParse.exists()) {
      logger.logError(MessageUtils.getMessage("DOTX008E", params).toString());
      return;
    }
    try {
      if (FileUtils.isValidTarget(currentFile.toLowerCase())) {
        reader.setTranstype(transtype);
        reader.setCurrentDir(new File(currentFile).getParent());
        reader.parse(fileToParse);

      } else {
        // edited by Alan on Date:2009-11-02 for Work Item:#1590 start
        // logger.logWarn("Input file name is not valid DITA file name.");
        final Properties prop = new Properties();
        prop.put("%1", fileToParse);
        logger.logWarn(MessageUtils.getMessage("DOTJ053W", params).toString());
        // edited by Alan on Date:2009-11-02 for Work Item:#1590 end
      }

      // don't put it into dita.list if it is invalid
      if (reader.isValidInput()) {
        processParseResult(currentFile);
        categorizeCurrentFile(currentFile);
      } else if (!currentFile.equals(inputFile)) {
        logger.logWarn(MessageUtils.getMessage("DOTJ021W", params).toString());
      }
    } catch (final SAXParseException sax) {

      // To check whether the inner third level is DITAOTBuildException
      // :FATALERROR
      final Exception inner = sax.getException();
      if (inner != null && inner instanceof DITAOTException) { // second
        // level
        logger.logInfo(inner.getMessage());
        throw (DITAOTException) inner;
      }
      if (currentFile.equals(inputFile)) {
        // stop the build if exception thrown when parsing input file.
        final MessageBean msgBean = MessageUtils.getMessage("DOTJ012F", params);
        msg = MessageUtils.getMessage("DOTJ012F", params).toString();
        msg = new StringBuffer(msg).append(":").append(sax.getMessage()).toString();
        throw new DITAOTException(msgBean, sax, msg);
      }
      final StringBuffer buff = new StringBuffer();
      msg = MessageUtils.getMessage("DOTJ013E", params).toString();
      buff.append(msg).append(LINE_SEPARATOR).append(sax.getMessage());
      logger.logError(buff.toString());
    } catch (final Exception e) {

      if (currentFile.equals(inputFile)) {
        // stop the build if exception thrown when parsing input file.
        final MessageBean msgBean = MessageUtils.getMessage("DOTJ012F", params);
        msg = MessageUtils.getMessage("DOTJ012F", params).toString();
        msg = new StringBuffer(msg).append(":").append(e.getMessage()).toString();
        throw new DITAOTException(msgBean, e, msg);
      }
      final StringBuffer buff = new StringBuffer();
      msg = MessageUtils.getMessage("DOTJ013E", params).toString();
      buff.append(msg).append(LINE_SEPARATOR).append(e.getMessage());
      logger.logError(buff.toString());
    }

    if (!reader.isValidInput() && currentFile.equals(inputFile)) {

      if (xmlValidate == true) {
        // stop the build if all content in the input file was filtered
        // out.
        msg = MessageUtils.getMessage("DOTJ022F", params).toString();
        throw new DITAOTException(msg);
      } else {
        // stop the build if the content of the file is not valid.
        msg = MessageUtils.getMessage("DOTJ034F", params).toString();
        throw new DITAOTException(msg);
      }
    }

    doneList.add(currentFile);
    reader.reset();
  }
Пример #15
0
  private void processChunk(final Element topicref, final File outputFile) {
    final String hrefValue = getValue(topicref, ATTRIBUTE_NAME_HREF);
    final Collection<String> chunkValue = split(getValue(topicref, ATTRIBUTE_NAME_CHUNK));
    final String copytoValue = getValue(topicref, ATTRIBUTE_NAME_COPY_TO);
    final String scopeValue = getCascadeValue(topicref, ATTRIBUTE_NAME_SCOPE);
    final String classValue = getValue(topicref, ATTRIBUTE_NAME_CLASS);
    final String processRoleValue = getCascadeValue(topicref, ATTRIBUTE_NAME_PROCESSING_ROLE);

    File outputFileName = outputFile;
    Writer tempWriter = null;
    Set<String> tempTopicID = null;

    targetTopicId = null;
    selectMethod = CHUNK_SELECT_DOCUMENT;
    include = false;

    boolean needWriteDitaTag = true;

    try {
      String parseFilePath;
      if (copytoValue != null && !chunkValue.contains(CHUNK_TO_CONTENT)) {
        if (getFragment(hrefValue) != null) {
          parseFilePath = setFragment(copytoValue, getFragment(hrefValue));
        } else {
          parseFilePath = copytoValue;
        }
      } else {
        parseFilePath = hrefValue;
      }

      // if @copy-to is processed in chunk module, the list file needs to
      // be updated.
      // Because @copy-to should be included in fulltopiclist, and the
      // source of coyy-to should be excluded in fulltopiclist.
      if (copytoValue != null && chunkValue.contains(CHUNK_TO_CONTENT) && hrefValue != null) {
        copyto.add(copytoValue);
        if (getFragment(hrefValue) != null) {
          copytoSource.add(stripFragment(hrefValue));
          copytotarget2source.put(toURI(copytoValue), toURI(stripFragment(hrefValue)));
        } else {
          copytoSource.add(hrefValue);
          copytotarget2source.put(toURI(copytoValue), toURI(hrefValue));
        }
      }

      if (parseFilePath != null && !ATTR_SCOPE_VALUE_EXTERNAL.equals(scopeValue)) {
        // now the path to target file make sense
        if (chunkValue.contains(CHUNK_TO_CONTENT)) {
          // if current element contains "to-content" in chunk
          // attribute
          // we need to create new buffer and flush the buffer to
          // file
          // after processing is finished
          tempWriter = output;
          tempTopicID = topicID;
          output = new StringWriter();
          topicID = new HashSet<String>();
          if (MAP_MAP.matches(classValue)) {
            // Very special case, we have a map element with
            // href value.
            // This is a map that needs to be chunked to
            // content.
            // No need to parse any file, just generate a stub
            // output.
            outputFileName = resolve(filePath, parseFilePath);
            needWriteDitaTag = false;
          } else if (copytoValue != null) {
            // use @copy-to value as the new file name
            outputFileName = resolve(filePath, copytoValue);
          } else if (hrefValue != null) {
            // try to use href value as the new file name
            if (chunkValue.contains(CHUNK_SELECT_TOPIC)
                || chunkValue.contains(CHUNK_SELECT_BRANCH)) {
              if (getFragment(hrefValue) != null) {
                // if we have an ID here, use it.
                outputFileName = resolve(filePath, getFragment(hrefValue) + FILE_EXTENSION_DITA);
              } else {
                // Find the first topic id in target file if
                // any.
                final String firstTopic = getFirstTopicId(resolve(filePath, hrefValue).getPath());
                if (firstTopic != null) {
                  outputFileName = resolve(filePath, firstTopic + FILE_EXTENSION_DITA);
                } else {
                  outputFileName = resolve(filePath, hrefValue);
                }
              }
            } else {
              // otherwise, use the href value instead
              outputFileName = resolve(filePath, hrefValue);
            }
          } else {
            // use randomly generated file name
            outputFileName = resolve(filePath, generateFilename());
          }

          // Check if there is any conflict
          if (outputFileName.exists() && !MAP_MAP.matches(classValue)) {
            final File t = outputFileName;
            outputFileName = resolve(filePath, generateFilename());
            conflictTable.put(outputFileName.getPath(), t.getPath());
          }
          // add newly generated file to changTable
          // the new entry in changeTable has same key and value
          // in order to indicate it is a newly generated file
          changeTable.put(outputFileName.getPath(), outputFileName.getPath());
        }
        // "by-topic" couldn't reach here
        this.outputFile = outputFileName;

        final String path = resolveTopic(filePath, parseFilePath);
        // FIXME: Should be URI
        String newpath;
        if (getFragment(path) != null) {
          newpath = setFragment(outputFileName.getPath(), getFragment(path));
        } else {
          final String firstTopicID = getFirstTopicId(path);
          if (firstTopicID != null) {
            newpath = setFragment(outputFileName.getPath(), firstTopicID);
          } else {
            newpath = outputFileName.getPath();
          }
        }
        // add file name changes to changeTable, this will be
        // used in
        // TopicRefWriter's updateHref method, very important!!!
        changeTable.put(path, newpath);
        // update current element's @href value
        topicref.setAttribute(
            ATTRIBUTE_NAME_HREF,
            getRelativeUnixPath(filePath + UNIX_SEPARATOR + FILE_NAME_STUB_DITAMAP, newpath));

        if (getFragment(parseFilePath) != null) {
          targetTopicId = getFragment(parseFilePath);
        }

        final String s = getChunkByToken(chunkValue, "select-", null);
        if (s != null) {
          selectMethod = s;
          // if the current topic href referred to a entire
          // topic file,it will be handled in "document" level.
          if (targetTopicId == null) {
            selectMethod = CHUNK_SELECT_DOCUMENT;
          }
        }
        final File tempPath = currentParsingFile;
        currentParsingFile = resolve(filePath, parseFilePath);

        if (!ATTR_PROCESSING_ROLE_VALUE_RESOURCE_ONLY.equals(processRoleValue)) {
          currentParsingFileTopicIDChangeTable = new HashMap<String, String>();
          // TODO recursive point
          reader.parse(currentParsingFile.toURI().toString());
          if (currentParsingFileTopicIDChangeTable.size() > 0) {
            final URI href = toURI(topicref.getAttribute(ATTRIBUTE_NAME_HREF));
            final String pathtoElem = href.getFragment() != null ? href.getFragment() : "";
            final String old_elementid =
                pathtoElem.contains(SLASH)
                    ? pathtoElem.substring(0, pathtoElem.indexOf(SLASH))
                    : pathtoElem;
            if (!old_elementid.isEmpty()) {
              final String new_elementid = currentParsingFileTopicIDChangeTable.get(old_elementid);
              if (new_elementid != null && !new_elementid.isEmpty()) {
                topicref.setAttribute(
                    ATTRIBUTE_NAME_HREF, setFragment(href, new_elementid).toString());
              }
            }
          }
          currentParsingFileTopicIDChangeTable = null;
        }
        // restore the currentParsingFile
        currentParsingFile = tempPath;
      }

      if (topicref.hasChildNodes()) {
        // if current element has child nodes and chunk results for
        // this element has value
        // which means current element makes sense for chunk action.
        final StringWriter tempOutput = (StringWriter) output;
        output = new StringWriter();
        final NodeList children = topicref.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
          final Node current = children.item(i);
          if (MAP_TOPICREF.matches(current)) {
            processChunk((Element) current, outputFileName);
          }
        }

        // merge results
        final StringBuffer parentResult = tempOutput.getBuffer();
        final CharSequence tmpContent = ((StringWriter) output).getBuffer();
        // Skip empty parents and @processing-role='resource-only' entries.
        // append into root topic
        if (parentResult.length() > 0
            && parseFilePath != null
            && !ATTR_PROCESSING_ROLE_VALUE_RESOURCE_ONLY.equals(processRoleValue)) {
          insertAfter(hrefValue, parentResult, tmpContent);
          // replace contents
        } else {
          parentResult.append(tmpContent);
        }
        // restore back to parent's output this is a different temp
        output = tempOutput;
      }

      if (chunkValue.contains(CHUNK_TO_CONTENT)) {
        final String tmpContent = ((StringWriter) output).toString();
        writeToContentChunk(tmpContent, outputFileName, needWriteDitaTag);
        // restore back original output
        output = tempWriter;
        topicID = tempTopicID;
      }
    } catch (final RuntimeException e) {
      throw e;
    } catch (final Exception e) {
      logger.error(e.getMessage(), e);
    }
  }
  /**
   * Write result files.
   *
   * @throws DITAOTException if writing result files failed
   */
  private void outputResult() throws DITAOTException {
    final File dir = new File(tempDir);
    if (!dir.exists()) {
      dir.mkdirs();
    }

    Job prop = null;
    try {
      prop = new Job(dir);
    } catch (final IOException e) {
      throw new DITAOTException("Failed to create empty job: " + e.getMessage(), e);
    }

    prop.setProperty(INPUT_DIR, baseInputDir);
    prop.setProperty(INPUT_DITAMAP, prefix + inputFile);

    prop.setProperty(INPUT_DITAMAP_LIST_FILE_LIST, USER_INPUT_FILE_LIST_FILE);
    final File inputfile = new File(tempDir, USER_INPUT_FILE_LIST_FILE);
    Writer bufferedWriter = null;
    try {
      bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(inputfile)));
      bufferedWriter.write(prefix + inputFile);
      bufferedWriter.flush();
    } 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);
        }
      }
    }

    // add out.dita.files,tempdirToinputmapdir.relative.value to solve the
    // output problem
    relativeValue = prefix;
    formatRelativeValue = formatRelativeValue(relativeValue);
    prop.setProperty("tempdirToinputmapdir.relative.value", formatRelativeValue);

    prop.setProperty("uplevels", getUpdateLevels());
    addSetToProperties(prop, OUT_DITA_FILES_LIST, outDitaFilesSet);

    addSetToProperties(prop, FULL_DITAMAP_TOPIC_LIST, ditaSet);
    addSetToProperties(prop, FULL_DITA_TOPIC_LIST, fullTopicSet);
    addSetToProperties(prop, FULL_DITAMAP_LIST, fullMapSet);
    addSetToProperties(prop, HREF_DITA_TOPIC_LIST, hrefTopicSet);
    addSetToProperties(prop, CONREF_LIST, conrefSet);
    addSetToProperties(prop, IMAGE_LIST, imageSet);
    addSetToProperties(prop, FLAG_IMAGE_LIST, flagImageSet);
    addSetToProperties(prop, HTML_LIST, htmlSet);
    addSetToProperties(prop, HREF_TARGET_LIST, hrefTargetSet);
    addSetToProperties(prop, HREF_TOPIC_LIST, hrefWithIDSet);
    addSetToProperties(prop, CHUNK_TOPIC_LIST, chunkTopicSet);
    addSetToProperties(prop, SUBJEC_SCHEME_LIST, schemeSet);
    addSetToProperties(prop, CONREF_TARGET_LIST, conrefTargetSet);
    addSetToProperties(prop, COPYTO_SOURCE_LIST, copytoSourceSet);
    addSetToProperties(prop, SUBSIDIARY_TARGET_LIST, subsidiarySet);
    addSetToProperties(prop, CONREF_PUSH_LIST, conrefpushSet);
    addSetToProperties(prop, KEYREF_LIST, keyrefSet);
    addSetToProperties(prop, CODEREF_LIST, coderefSet);

    // @processing-role
    addSetToProperties(prop, RESOURCE_ONLY_LIST, resourceOnlySet);

    addFlagImagesSetToProperties(prop, REL_FLAGIMAGE_LIST, relFlagImagesSet);

    // Convert copyto map into set and output
    final Set<String> copytoSet = new HashSet<String>(INT_128);
    for (final Map.Entry<String, String> entry : copytoMap.entrySet()) {
      copytoSet.add(entry.toString());
    }
    addSetToProperties(prop, COPYTO_TARGET_TO_SOURCE_MAP_LIST, copytoSet);
    addKeyDefSetToProperties(prop, KEY_LIST, keysDefMap.values());

    try {
      logger.logInfo("Serializing job specification");
      prop.write();
    } catch (final IOException e) {
      throw new DITAOTException(
          "Failed to serialize job configuration files: " + e.getMessage(), e);
    }

    // Output relation-graph
    writeMapToXML(reader.getRelationshipGrap(), FILE_NAME_SUBJECT_RELATION);
    // Output topic-scheme dictionary
    writeMapToXML(this.schemeDictionary, FILE_NAME_SUBJECT_DICTIONARY);

    // added by Willam on 2009-07-17 for req #12014 start
    if (INDEX_TYPE_ECLIPSEHELP.equals(transtype)) {
      // Output plugin id
      final File pluginIdFile = new File(tempDir, FILE_NAME_PLUGIN_XML);
      final DelayConrefUtils delayConrefUtils = new DelayConrefUtils();
      delayConrefUtils.writeMapToXML(reader.getPluginMap(), pluginIdFile);
      // write the result into the file
      final StringBuffer result = reader.getResult();
      try {
        export.write(result.toString());
      } catch (final IOException e) {
        logger.logException(e);
      }
    }
    // added by Willam on 2009-07-17 for req #12014 end

  }
 /**
  * Escape regular expression special characters.
  *
  * @param value input
  * @return input with regular expression special characters escaped
  */
 private String formatRelativeValue(final String value) {
   final StringBuffer buff = new StringBuffer();
   if (value == null || value.length() == 0) {
     return "";
   }
   int index = 0;
   // $( )+.[^{\
   while (index < value.length()) {
     final char current = value.charAt(index);
     switch (current) {
       case '.':
         buff.append("\\.");
         break;
         // case '/':
         // case '|':
       case '\\':
         buff.append("[\\\\|/]");
         break;
       case '(':
         buff.append("\\(");
         break;
       case ')':
         buff.append("\\)");
         break;
       case '[':
         buff.append("\\[");
         break;
       case ']':
         buff.append("\\]");
         break;
       case '{':
         buff.append("\\{");
         break;
       case '}':
         buff.append("\\}");
         break;
       case '^':
         buff.append("\\^");
         break;
       case '+':
         buff.append("\\+");
         break;
       case '$':
         buff.append("\\$");
         break;
       default:
         buff.append(current);
     }
     index++;
   }
   return buff.toString();
 }