public synchronized TemplateModel executeQuery(Object context, String xpathQuery)
     throws TemplateModelException {
   if (!(context instanceof Node)) {
     if (context != null) {
       if (isNodeList(context)) {
         int cnt = ((List) context).size();
         if (cnt != 0) {
           throw new TemplateModelException(
               "Cannot perform an XPath query against a node set of "
                   + cnt
                   + " nodes. Expecting a single node."
                   + ERRMSG_RECOMMEND_JAXEN);
         } else {
           throw new TemplateModelException(ERRMSG_EMPTY_NODE_SET);
         }
       } else {
         throw new TemplateModelException(
             "Cannot perform an XPath query against a "
                 + context.getClass().getName()
                 + ". Expecting a single org.w3c.dom.Node.");
       }
     } else {
       throw new TemplateModelException(ERRMSG_EMPTY_NODE_SET);
     }
   }
   Node node = (Node) context;
   try {
     XPath xpath = new XPath(xpathQuery, null, customPrefixResolver, XPath.SELECT, null);
     int ctxtNode = xpathContext.getDTMHandleFromNode(node);
     XObject xresult = xpath.execute(xpathContext, ctxtNode, customPrefixResolver);
     if (xresult instanceof XNodeSet) {
       NodeListModel result = new NodeListModel(node);
       result.xpathSupport = this;
       NodeIterator nodeIterator = xresult.nodeset();
       Node n;
       do {
         n = nodeIterator.nextNode();
         if (n != null) {
           result.add(n);
         }
       } while (n != null);
       return result.size() == 1 ? result.get(0) : result;
     }
     if (xresult instanceof XBoolean) {
       return ((XBoolean) xresult).bool() ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
     }
     if (xresult instanceof XNull) {
       return null;
     }
     if (xresult instanceof XString) {
       return new SimpleScalar(xresult.toString());
     }
     if (xresult instanceof XNumber) {
       return new SimpleNumber(new Double(((XNumber) xresult).num()));
     }
     throw new TemplateModelException("Cannot deal with type: " + xresult.getClass().getName());
   } catch (TransformerException te) {
     throw new TemplateModelException(te);
   }
 }
  public MaryData process(MaryData d) throws Exception {
    Document doc = d.getDocument();
    NodeIterator it = MaryDomUtils.createNodeIterator(doc, doc, MaryXML.TOKEN);
    Element t = null;
    while ((t = (Element) it.nextNode()) != null) {
      String text;

      // Do not touch tokens for which a transcription is already
      // given (exception: transcription contains a '*' character:
      if (t.hasAttribute("ph") && !t.getAttribute("ph").contains("*")) {
        continue;
      }
      if (t.hasAttribute("sounds_like")) text = t.getAttribute("sounds_like");
      else text = MaryDomUtils.tokenText(t);

      String pos = null;
      // use part-of-speech if available
      if (t.hasAttribute("pos")) {
        pos = t.getAttribute("pos");
      }

      if (text != null
          && !text.equals("")
          && (pos == null || !pos.startsWith("$") /*punctuation*/)) {
        // If text consists of several parts (e.g., because that was
        // inserted into the sounds_like attribute), each part
        // is transcribed separately.
        StringBuilder ph = new StringBuilder();
        String g2pMethod = null;
        StringTokenizer st = new StringTokenizer(text, " -");
        while (st.hasMoreTokens()) {
          String graph = st.nextToken();
          StringBuilder helper = new StringBuilder();

          String phon = phonemise(graph, pos, helper);

          if (ph.length() == 0) { // first part
            // The g2pMethod of the combined beast is
            // the g2pMethod of the first constituant.
            g2pMethod = helper.toString();
            ph.append(phon);
          } else { // following parts
            ph.append(" - ");
            // Reduce primary to secondary stress:
            ph.append(phon.replace('\'', ','));
          }
        }

        if (ph != null && ph.length() > 0) {
          setPh(t, ph.toString());
          t.setAttribute("g2p_method", g2pMethod);
        }
      }
    }
    MaryData result = new MaryData(outputType(), d.getLocale());
    result.setDocument(doc);
    return result;
  }
  /**
   * Use an XPath string to select a single node. XPath namespace prefixes are resolved from the
   * namespaceNode.
   *
   * @param contextNode The node to start searching from.
   * @param xpathnode
   * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
   * @return The first node found that matches the XPath, or null.
   * @throws TransformerException
   */
  public Node selectSingleNode(Node contextNode, Node xpathnode, Node namespaceNode)
      throws TransformerException {

    // Have the XObject return its result as a NodeSetDTM.
    NodeIterator nl = selectNodeIterator(contextNode, xpathnode, namespaceNode);

    // Return the first node, or null
    return nl.nextNode();
  }
Exemple #4
0
 /* all private methods */
 private void readEntries(
     final ZipInputStream zis, final ExtractedMetadata metadata, final Asset asset)
     throws Exception {
   ZipEntry entry;
   while ((entry = zis.getNextEntry()) != null) {
     final String name = entry.getName();
     if (name.equals(ENTRY_CORE) || name.equals(ENTRY_APP)) {
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       IOUtils.copy(zis, out);
       // build xml document to extract meta info
       DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
       documentBuilderFactory.setNamespaceAware(true);
       Document document =
           documentBuilderFactory
               .newDocumentBuilder()
               .parse(new ByteArrayInputStream(out.toByteArray()));
       IOUtils.closeQuietly(out);
       DocumentTraversal dt = (DocumentTraversal) document;
       NodeIterator nit = dt.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, null, true);
       nit.nextNode(); // skip first node
       Element next;
       while ((next = (Element) nit.nextNode()) != null) {
         metadata.setMetaDataProperty(next.getLocalName(), next.getTextContent());
       }
     } else if (name.equals(ENTRY_THUMBNAIL)) {
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       try {
         IOUtils.copy(zis, out);
         metadata.setProperty(META_KEY_THUMBNAIL, out.toByteArray());
       } finally {
         IOUtils.closeQuietly(out);
       }
     } else if (name.equals(ENTRY_THUMBNAIL_EMF)) {
       String mimeType = mimeTypeService.getMimeType(name);
       AssetHandler handler = store.getAssetHandler(mimeType);
       Rendition rend = asset.addRendition("thumbnail.emf", zis, mimeType);
       BufferedImage img = handler.getImage(rend);
       if (img != null) {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         try {
           ImageIO.write(img, JPEG_FORMAT, baos);
           baos.flush();
           metadata.setProperty(META_KEY_THUMBNAIL, baos.toByteArray());
         } finally {
           IOUtils.closeQuietly(baos);
         }
       } else {
         log.info("Cannot extract image from EMF format");
       }
     }
   }
 }
Exemple #5
0
  /**
   * Gets a List of nodes found by traversing the context node
   *
   * @param context Node containing child nodes
   * @return List of nodes found by traversing the context node
   */
  public static List getNodes(Node context) {

    Document doc = context.getOwnerDocument();

    // create node iterators to traverse the subtrees allowing only element
    // nodes
    NodeIterator source =
        ((DocumentTraversal) doc).createNodeIterator(context, NodeFilter.SHOW_ELEMENT, null, false);

    List nodes = getNodes(source);

    source.detach();

    return nodes;
  }
Exemple #6
0
  public static DocumentFragment shapeToSVG(SvgConversionContext context, NodeIterator shapeIt) {

    DocumentFragment docfrag = null;
    Document d = null;

    try {
      Object shape = null;
      if (shapeIt != null) {
        Node n = shapeIt.nextNode();
        if (n == null) {
          d = makeErr("[null node?!]");
        } else {
          log.debug("Handling " + n.getNodeName());

          if (n.getNodeName().equals("p:cxnSp")) {

            shape = nodeToObjectModel(n, CxnSp.class);
            d = CxnSpToSVG((CxnSp) shape);

          } else {
            log.info("** TODO " + n.getNodeName());
            d = makeErr("[" + n.getNodeName() + "]");
          }
        }
      }
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      d = makeErr(e.getMessage());
    }

    // Machinery
    docfrag = d.createDocumentFragment();
    docfrag.appendChild(d.getDocumentElement());
    return docfrag;
  }
Exemple #7
0
  public void updateState(NodeIterator fldCharNodeIt) {
    org.docx4j.wml.FldChar field = null;

    Node node = fldCharNodeIt.nextNode();

    try {
      field =
          (org.docx4j.wml.FldChar)
              XmlUtils.unmarshal(node, Context.jc, org.docx4j.wml.FldChar.class);
    } catch (JAXBException e1) {
      e1.printStackTrace();
    }

    STFldCharType fieldCharType = field.getFldCharType();

    if (fieldCharType == null) {

      log.debug("Ignoring unrecognised: " + XmlUtils.w3CDomNodeToString(node));

    } else {

      if (fieldCharType == STFldCharType.BEGIN) {
        inField = true;
      } else if (fieldCharType == STFldCharType.END) {
        inField = false;
      }
      // else ignore STFldCharType.SEPARATE
    }
  }
  public static void copyGraphicFiles(
      String baseFilename,
      String currentDirectory,
      String fileSeparator,
      NodeIterator graphicsElements) {

    Node currentNode = graphicsElements.nextNode();
    byte[] buffer = new byte[4096];
    int bytes_read;

    while (currentNode != null) {
      FileInputStream fis = null;
      FileOutputStream fos = null;
      File fileToCopy = null;
      File copiedFile = null;

      // We should make sure the node is a DOM Element. Our stylesheet
      // only passes Elements in, but that might change....
      if (currentNode instanceof Element) {
        String nextGraphicsFile = ((Element) currentNode).getAttribute("img");

        if (nextGraphicsFile == null || nextGraphicsFile.length() == 0)
          nextGraphicsFile = ((Element) currentNode).getAttribute("src");

        if (nextGraphicsFile != null
            && !nextGraphicsFile.substring(0, 4).equalsIgnoreCase("HTTP")) {
          try {
            fileToCopy = new File(nextGraphicsFile);
            copiedFile = new File(currentDirectory + fileSeparator + nextGraphicsFile);
            fis = new FileInputStream(fileToCopy);
            fos = new FileOutputStream(copiedFile);
            while ((bytes_read = fis.read(buffer)) != -1) {
              fos.write(buffer, 0, bytes_read);
            } // end while
            fos.flush();
            fos.close();
          } // end try
          catch (java.io.IOException ioe) {
            System.err.println("An error has occurred while copying graphic file:\n" + ioe);
            return;
          }
        } // end if not HTTP
      } // end if an element
      currentNode = graphicsElements.nextNode();
    }
  }
  public static String getCssForTableCells(HTMLConversionContext context, NodeIterator tables) {

    // The only way we seem to be able to make rules which
    // apply to all the cells in a particular table

    Tbl tbl;
    StringBuffer result = new StringBuffer();

    // DTMNodeProxy n = (DTMNodeProxy)tables.nextNode();
    Element n = (Element) tables.nextNode();
    if (n == null) {
      // No tables in this document
      return "";
    }
    int idx = 0;
    do {
      if (n.getNodeName().equals("w:tbl")) {
        // n.getLocalName() -> tbl
        // n.getNodeName() -> w:tbl

        Object jaxb;
        try {
          Unmarshaller u = Context.jc.createUnmarshaller();
          u.setEventHandler(new org.docx4j.jaxb.JaxbValidationEventHandler());
          jaxb = u.unmarshal(n);
          tbl = (Tbl) jaxb;

          result.append(getCssForTableCells(context, tbl, idx));

        } catch (JAXBException e1) {
          log.error("JAXB error", e1);
        } catch (ClassCastException e) {
          log.error("Couldn't cast to Tbl!");
        }

      } else {
        log.warn("Expected table but encountered: " + n.getNodeName());
      }
      // next
      idx++;
      n = (Element) tables.nextNode();

    } while (n != null);

    return result.toString();
  }
Exemple #10
0
  public static DocumentFragment createBlockForR(
      SvgConversionContext context, NodeIterator rPrNodeIt, NodeIterator childResults) {

    DocumentFragment docfrag = null;
    Document d = null;
    Element span = null;

    try {

      // Create a DOM builder and parse the fragment
      d = XmlUtils.getNewDocumentBuilder().newDocument();

      span = d.createElement("span");
      d.appendChild(span);

      CTTextCharacterProperties textCharProps =
          (CTTextCharacterProperties)
              nodeToObjectModel(rPrNodeIt.nextNode(), CTTextCharacterProperties.class);

      RPr rPr = TextStyles.getWmlRPr(textCharProps);

      // Does our rPr contain anything else?
      StringBuilder inlineStyle = new StringBuilder();
      HtmlCssHelper.createCss(context.getPmlPackage(), rPr, inlineStyle);
      if (!inlineStyle.toString().equals("")) {
        span.setAttribute("style", inlineStyle.toString());
      }

      Node n = childResults.nextNode();
      XmlUtils.treeCopy(n, span);

    } catch (Exception e) {
      log.error(e.getMessage(), e);
      // If something went wrong with the formatting,
      // still try to display the text!
      Node n = childResults.nextNode();
      XmlUtils.treeCopy(n, span);
    }

    // Machinery
    docfrag = d.createDocumentFragment();
    docfrag.appendChild(d.getDocumentElement());
    return docfrag;
  }
Exemple #11
0
  /**
   * Create a NodeSetDTM, and copy the members of the given DTMIterator into it.
   *
   * @param iterator Iterator which yields Nodes to be made members of the new set.
   */
  public NodeSetDTM(NodeIterator iterator, XPathContext xctxt) {

    super();

    Node node;
    m_manager = xctxt.getDTMManager();

    while (null != (node = iterator.nextNode())) {
      int handle = xctxt.getDTMHandleFromNode(node);
      addNodeInDocOrder(handle, xctxt);
    }
  }
Exemple #12
0
  /**
   * Gets a List of nodes found by traversing the node iterator
   *
   * @param source NodeIterator
   * @return List of nodes found by traversing the node iterator
   */
  public static List getNodes(NodeIterator source) {

    List nodes = new ArrayList();

    Node sourceNode = null;

    // iterate over the source nodes and add them to the map
    while ((sourceNode = source.nextNode()) != null) {

      // add the node to the list
      nodes.add(sourceNode);
    }

    return nodes;
  }
Exemple #13
0
  private static CTTextParagraphProperties unmarshalFormatting(NodeIterator lvlNpPr) {

    // Get the pPr node as a JAXB object,
    // so we can read it using our standard
    // methods.  Its a bit sad that we
    // can't just adorn our DOM tree with the
    // original JAXB objects?
    try {
      // CTTextListStyle lstStyle = null;
      CTTextParagraphProperties pPr = null;

      if (lvlNpPr != null) {
        Node n = lvlNpPr.nextNode();

        log.debug(n.getClass().getName());

        String str = XmlUtils.w3CDomNodeToString(n);
        // log.debug("'" + str + "'");

        // Convert to String first ...
        // unmarshalling the node directly doesn't work as expected
        // (see comment in XmlUtils)

        //			if (n!=null) {
        //				return  (CTTextParagraphProperties)XmlUtils.unmarshal(n, Context.jcPML,
        //						CTTextParagraphProperties.class);
        //			}

        if (!str.equals("")) {
          return (CTTextParagraphProperties)
              XmlUtils.unmarshalString(str, Context.jcPML, CTTextParagraphProperties.class);
        }
      }
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return null;
  }
Exemple #14
0
  public static DocumentFragment createBlockForP(
      SvgConversionContext context,
      String lvl,
      String cNvPrName,
      String phType,
      NodeIterator childResults,
      NodeIterator lvlNpPr) {

    StyleTree styleTree = null;
    try {
      styleTree = context.getPmlPackage().getStyleTree();
    } catch (InvalidFormatException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }

    log.debug("lvl:" + lvl);
    int level;
    if (lvl.equals("NaN")) {
      level = 1;
    } else {
      level = Integer.parseInt(lvl);
    }
    String pStyleVal;

    System.out.println("cNvPrName: " + cNvPrName + "; " + "phType: " + phType);

    if (cNvPrName.toLowerCase().indexOf("subtitle") > -1
        || phType.toLowerCase().indexOf("subtitle") > -1) {
      // Subtitle on first page in default layout is styled as a Body.
      pStyleVal = "Lvl" + level + "Master" + context.getResolvedLayout().getMasterNumber() + "Body";
    } else if (cNvPrName.toLowerCase().indexOf("title") > -1
        || phType.toLowerCase().indexOf("title") > -1) {
      pStyleVal =
          "Lvl" + level + "Master" + context.getResolvedLayout().getMasterNumber() + "Title";
    } else {
      // eg cNvPrName: TextBox 2; phType:
      pStyleVal =
          "Lvl" + level + "Master" + context.getResolvedLayout().getMasterNumber() + "Other";
    }
    System.out.println("--> " + pStyleVal);

    try {

      // Create a DOM builder and parse the fragment
      Document document = XmlUtils.getNewDocumentBuilder().newDocument();

      // log.info("Document: " + document.getClass().getName() );

      Node xhtmlP = document.createElement("p");
      document.appendChild(xhtmlP);

      // Set @class
      log.debug(pStyleVal);
      Tree<AugmentedStyle> pTree = styleTree.getParagraphStylesTree();
      org.docx4j.model.styles.Node<AugmentedStyle> asn = pTree.get(pStyleVal);
      ((Element) xhtmlP).setAttribute("class", StyleTree.getHtmlClassAttributeValue(pTree, asn));

      StringBuilder inlineStyle = new StringBuilder();
      // Do we have CTTextParagraphProperties
      // <a:lvl?pPr>
      // Convert it to a WordML pPr
      CTTextParagraphProperties lvlPPr = unmarshalFormatting(lvlNpPr);
      if (lvlPPr != null) {

        log.debug("We have lvlPPr");
        log.debug(
            XmlUtils.marshaltoString(
                lvlPPr,
                true,
                true,
                Context.jcPML,
                "FIXME",
                "lvl1pPr",
                CTTextParagraphProperties.class));
        PPr pPr = TextStyles.getWmlPPr(lvlPPr);
        if (pPr != null) {
          HtmlCssHelper.createCss(context.getPmlPackage(), pPr, inlineStyle, false, false);
        }
        // TODO RPR
      }
      // Without this, top-margin is too large in Webkit (Midor).
      // Not tested elsewhere...
      inlineStyle.append("margin-left:3px; margin-top:3px;");

      if (!inlineStyle.toString().equals("")) {
        ((Element) xhtmlP).setAttribute("style", inlineStyle.toString());
      }

      // Our fo:block wraps whatever result tree fragment
      // our style sheet produced when it applied-templates
      // to the child nodes
      // init
      Node n = childResults.nextNode();
      do {

        // getNumberXmlNode creates a span node, which is empty
        // if there is no numbering.
        // Let's get rid of any such <span/>.

        // What we actually get is a document node
        if (n.getNodeType() == Node.DOCUMENT_NODE) {
          log.debug("handling DOCUMENT_NODE");
          // Do just enough of the handling here
          NodeList nodes = n.getChildNodes();
          if (nodes != null) {
            for (int i = 0; i < nodes.getLength(); i++) {

              if (((Node) nodes.item(i)).getLocalName().equals("span")
                  && !((Node) nodes.item(i)).hasChildNodes()) {
                // ignore
                log.debug(".. ignoring <span/> ");
              } else {
                XmlUtils.treeCopy((Node) nodes.item(i), xhtmlP);
              }
            }
          }
        } else {

          //					log.info("Node we are importing: " + n.getClass().getName() );
          //					foBlockElement.appendChild(
          //							document.importNode(n, true) );
          /*
           * Node we'd like to import is of type org.apache.xml.dtm.ref.DTMNodeProxy
           * which causes
           * org.w3c.dom.DOMException: NOT_SUPPORTED_ERR: The implementation does not support the requested type of object or operation.
           *
           * See http://osdir.com/ml/text.xml.xerces-j.devel/2004-04/msg00066.html
           *
           * So instead of importNode, use
           */
          XmlUtils.treeCopy(n, xhtmlP);
        }
        // next
        n = childResults.nextNode();

      } while (n != null);

      DocumentFragment docfrag = document.createDocumentFragment();
      docfrag.appendChild(document.getDocumentElement());

      return docfrag;

    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }

    return null;
  }
  public void computeFeaturesFor(String basename) throws IOException, Exception {
    String text;
    Locale localVoice;
    localVoice = MaryUtils.string2locale(locale);

    // First, test if there is a corresponding .rawmaryxml file in textdir:
    File rawmaryxmlFile =
        new File(db.getProp(db.MARYXMLDIR) + basename + db.getProp(db.MARYXMLEXT));
    if (rawmaryxmlFile.exists()) {
      text = FileUtils.getFileAsString(rawmaryxmlFile, "UTF-8");
    } else {
      text =
          getMaryXMLHeaderWithInitialBoundary(locale)
              + FileUtils.getFileAsString(
                  new File(db.getProp(db.TEXTDIR) + basename + db.getProp(db.TEXTEXT)), "UTF-8")
              + "</maryxml>";
    }
    File pfeatFile = new File(unitfeatureDir, basename + featsExt);
    OutputStream os = new BufferedOutputStream(new FileOutputStream(pfeatFile));
    MaryClient maryClient = getMaryClient();
    /*Vector voices = maryClient.getVoices(localVoice);
    MaryClient.Voice defaultVoice = (MaryClient.Voice) voices.firstElement();
    String voiceName = defaultVoice.name();*/
    // maryClient.process(text, maryInputType, maryOutputType, null, null, os);

    maryClient.process(text, maryInputType, maryOutputType, locale, null, "slt-arctic", os);
    // maryClient.process(text, maryInputType, maryOutputType, null, "slt-arctic", os, timeout);
    // maryClient.getOutputDataTypes().size()
    // MaryData result = new MaryData(os);

    os.flush();
    os.close();

    // System.out.println(" TO STRING: "+new FileReader(pfeatFile).toString());
    // BufferedReader bfr = new BufferedReader(new FileReader(pfeatFile));
    String line;
    MaryData d = new MaryData(MaryDataType.get("PHONEMISED_EN"), Locale.US);
    // d.readFrom(new ByteArrayInputStream(os.toByteArray()));
    d.readFrom(new FileReader(pfeatFile));

    // MaryData d = new MaryData(pfeatFile);
    Document doc = d.getDocument();
    // Document acoustparams = d.getDocument();

    // NodeIterator it = ((DocumentTraversal)acoustparams).createNodeIterator(acoustparams,
    // NodeFilter.SHOW_ELEMENT,new NameNodeFilter(new String[]{MaryXML.TOKEN,
    // MaryXML.BOUNDARY}),false);
    NodeIterator it =
        ((DocumentTraversal) doc)
            .createNodeIterator(
                doc, NodeFilter.SHOW_ELEMENT, new NameNodeFilter(MaryXML.TOKEN), false);

    Element t = null;
    while ((t = (Element) it.nextNode()) != null) {
      if (t.hasAttribute("g2p_method")) {
        String g2p = t.getAttribute("g2p_method");
        String nodeText = t.getTextContent().trim();
        if (g2p.equals("rules")) { // && nodeText.equals("!")){
          System.out.print(basename + " ----> " + nodeText);
          if (bnl.contains(basename)) bnl.remove(basename);
          System.out.println(" SO removing basename: " + basename);
        }

        // System.out.println("G2P:"+t.getAttribute("g2p_method"));
        // System.out.println("Text:"+t.getTextContent());
      }
    }

    /*while((line =bfr.readLine()) != null){
        //boolean b = m.matches();
        if(Pattern.matches("rules", line))
                System.out.println(basename + " LINE ---> " + line);

    }*/
    // System.out.println(" TO STRING: "+line);

  }
Exemple #16
0
  /**
   * Adjust column widths in an HTML table.
   *
   * <p>The specification of column widths in CALS (a relative width plus an optional absolute
   * width) are incompatible with HTML column widths. This method adjusts CALS column width
   * specifiers in an attempt to produce equivalent HTML specifiers.
   *
   * <p>In order for this method to work, the CALS width specifications should be placed in the
   * "width" attribute of the &lt;col>s within a &lt;colgroup>. Then the colgroup result tree
   * fragment is passed to this method.
   *
   * <p>This method makes use of two parameters from the XSL stylesheet that calls it: <code>
   * nominal.table.width</code> and <code>table.width</code>. The value of <code>nominal.table.width
   * </code> must be an absolute distance. The value of <code>table.width</code> can be either
   * absolute or relative.
   *
   * <p>Presented with a mixture of relative and absolute lengths, the table width is used to
   * calculate appropriate values. If the <code>table.width</code> is relative, the nominal width is
   * used for this calculation.
   *
   * <p>There are three possible combinations of values:
   *
   * <ol>
   *   <li>There are no relative widths; in this case the absolute widths are used in the HTML
   *       table.
   *   <li>There are no absolute widths; in this case the relative widths are used in the HTML
   *       table.
   *   <li>There are a mixture of absolute and relative widths:
   *       <ol>
   *         <li>If the table width is absolute, all widths become absolute.
   *         <li>If the table width is relative, make all the widths absolute relative to the
   *             nominal table width then turn them all back into relative widths.
   *       </ol>
   * </ol>
   *
   * @param context The stylesheet context; supplied automatically by Xalan
   * @param xalanNI
   * @return The result tree fragment containing the adjusted colgroup.
   */
  public DocumentFragment adjustColumnWidths(ExpressionContext context, NodeIterator xalanNI) {

    int nominalWidth = convertLength(Params.getString(context, "nominal.table.width"));
    String tableWidth = Params.getString(context, "table.width");
    String styleType = Params.getString(context, "stylesheet.result.type");
    boolean foStylesheet = styleType.equals("fo");

    DocumentFragment xalanRTF = (DocumentFragment) xalanNI.nextNode();
    Element colgroup = (Element) xalanRTF.getFirstChild();

    // N.B. ...stree.ElementImpl doesn't implement getElementsByTagName()

    Node firstCol = null;
    // If this is an FO tree, there might be no colgroup...
    if (colgroup.getLocalName().equals("colgroup")) {
      firstCol = colgroup.getFirstChild();
    } else {
      firstCol = colgroup;
    }

    // Count the number of columns...
    Node child = firstCol;
    int numColumns = 0;
    while (child != null) {
      if (child.getNodeType() == Node.ELEMENT_NODE
          && (child.getNodeName().equals("col")
              || (child.getNamespaceURI().equals(foURI)
                  && child.getLocalName().equals("table-column")))) {
        numColumns++;
      }

      child = child.getNextSibling();
    }

    String widths[] = new String[numColumns];
    Element columns[] = new Element[numColumns];
    int colnum = 0;

    child = firstCol;
    while (child != null) {
      if (child.getNodeType() == Node.ELEMENT_NODE
          && (child.getNodeName().equals("col")
              || (child.getNamespaceURI().equals(foURI)
                  && child.getLocalName().equals("table-column")))) {
        Element col = (Element) child;

        columns[colnum] = col;

        if (foStylesheet) {
          if ("".equals(col.getAttribute("column-width"))) {
            widths[colnum] = "1*";
          } else {
            widths[colnum] = col.getAttribute("column-width");
          }
        } else {
          if ("".equals(col.getAttribute("width"))) {
            widths[colnum] = "1*";
          } else {
            widths[colnum] = col.getAttribute("width");
          }
        }

        colnum++;
      }
      child = child.getNextSibling();
    }

    float relTotal = 0;
    float relParts[] = new float[numColumns];

    float absTotal = 0;
    float absParts[] = new float[numColumns];

    for (int count = 0; count < numColumns; count++) {
      String width = widths[count];
      int pos = width.indexOf("*");
      if (pos >= 0) {
        String relPart = width.substring(0, pos);
        String absPart = width.substring(pos + 1);

        try {
          float rel = Float.parseFloat(relPart);
          relTotal += rel;
          relParts[count] = rel;
        } catch (NumberFormatException e) {
          System.out.println(relPart + " is not a valid relative unit.");
        }

        int pixels = 0;
        if (absPart != null && !absPart.equals("")) {
          pixels = convertLength(absPart);
        }

        absTotal += pixels;
        absParts[count] = pixels;
      } else {
        relParts[count] = 0;

        int pixels = 0;
        if (width != null && !width.equals("")) {
          pixels = convertLength(width);
        }

        absTotal += pixels;
        absParts[count] = pixels;
      }
    }

    // Ok, now we have the relative widths and absolute widths in
    // two parallel arrays.
    //
    // - If there are no relative widths, output the absolute widths
    // - If there are no absolute widths, output the relative widths
    // - If there are a mixture of relative and absolute widths,
    //   - If the table width is absolute, turn these all into absolute
    //     widths.
    //   - If the table width is relative, turn these all into absolute
    //     widths in the nominalWidth and then turn them back into
    //     percentages.

    if (relTotal == 0) {
      for (int count = 0; count < numColumns; count++) {
        Float f = new Float(absParts[count]);
        if (foStylesheet) {
          int pixels = f.intValue();
          float inches = (float) pixels / pixelsPerInch;
          widths[count] = inches + "in";
        } else {
          widths[count] = Integer.toString(f.intValue());
        }
      }
    } else if (absTotal == 0) {
      for (int count = 0; count < numColumns; count++) {
        float rel = relParts[count] / relTotal * 100;
        Float f = new Float(rel);
        widths[count] = Integer.toString(f.intValue());
      }
      widths = correctRoundingError(widths);
    } else {
      int pixelWidth = nominalWidth;

      if (tableWidth.indexOf("%") <= 0) {
        pixelWidth = convertLength(tableWidth);
      }

      if (pixelWidth <= absTotal) {
        System.out.println("Table is wider than table width.");
      } else {
        pixelWidth -= absTotal;
      }

      absTotal = 0;
      for (int count = 0; count < numColumns; count++) {
        float rel = relParts[count] / relTotal * pixelWidth;
        relParts[count] = rel + absParts[count];
        absTotal += rel + absParts[count];
      }

      if (tableWidth.indexOf("%") <= 0) {
        for (int count = 0; count < numColumns; count++) {
          Float f = new Float(relParts[count]);
          if (foStylesheet) {
            int pixels = f.intValue();
            float inches = (float) pixels / pixelsPerInch;
            widths[count] = inches + "in";
          } else {
            widths[count] = Integer.toString(f.intValue());
          }
        }
      } else {
        for (int count = 0; count < numColumns; count++) {
          float rel = relParts[count] / absTotal * 100;
          Float f = new Float(rel);
          widths[count] = Integer.toString(f.intValue());
        }
        widths = correctRoundingError(widths);
      }
    }

    // Now rebuild the colgroup with the right widths

    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = null;

    try {
      docBuilder = docFactory.newDocumentBuilder();
    } catch (ParserConfigurationException e) {
      System.out.println("PCE!");
      return xalanRTF;
    }
    Document doc = docBuilder.newDocument();
    DocumentFragment df = doc.createDocumentFragment();
    DOMBuilder rtf = new DOMBuilder(doc, df);

    try {
      String ns = colgroup.getNamespaceURI();
      String localName = colgroup.getLocalName();
      String name = colgroup.getTagName();

      if (colgroup.getLocalName().equals("colgroup")) {
        rtf.startElement(ns, localName, name, copyAttributes(colgroup));
      }

      for (colnum = 0; colnum < numColumns; colnum++) {
        Element col = columns[colnum];

        NamedNodeMap domAttr = col.getAttributes();

        AttributesImpl attr = new AttributesImpl();
        for (int acount = 0; acount < domAttr.getLength(); acount++) {
          Node a = domAttr.item(acount);
          String a_ns = a.getNamespaceURI();
          String a_localName = a.getLocalName();

          if ((foStylesheet && !a_localName.equals("column-width"))
              || !a_localName.equalsIgnoreCase("width")) {
            attr.addAttribute(
                a.getNamespaceURI(), a.getLocalName(), a.getNodeName(), "CDATA", a.getNodeValue());
          }
        }

        if (foStylesheet) {
          attr.addAttribute("", "column-width", "column-width", "CDATA", widths[colnum]);
        } else {
          attr.addAttribute("", "width", "width", "CDATA", widths[colnum]);
        }

        rtf.startElement(col.getNamespaceURI(), col.getLocalName(), col.getTagName(), attr);
        rtf.endElement(col.getNamespaceURI(), col.getLocalName(), col.getTagName());
      }

      if (colgroup.getLocalName().equals("colgroup")) {
        rtf.endElement(ns, localName, name);
      }
    } catch (SAXException se) {
      System.out.println("SE!");
      return xalanRTF;
    }

    return df;
  }
  // En la aplicación se encuentra guardado un fichero, "FixedHolidays.xml", este fichero tiene
  // almacenado todos los días festivos definidos por
  // el usuario. Esta función leera el fichero y almacenará en una lista todos los días del fichero.
  // Si se produce algun error almacenará el error.
  public ActionForward fixedHolydays(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response,
      SessionAPI session)
      throws Exception {

    // Comprobar si el usuario tiene asignadas las funciones adecuadas
    FunctionHelper.checkFunctions(
        request,
        session.getClientContext(),
        new int[] {ISecurityAPI.FUNC_COMP_CALENDARS_READ, ISecurityAPI.FUNC_COMP_CALENDARS_EDIT});

    // Se utilizan dos listas por si se produce un error de sintaxis en el fichero cuando ya se han
    // almacenado valores en la lista.
    List fixedHolidays = new ArrayList();
    List allFixedHolidays = new ArrayList();
    String language = request.getLocale().getLanguage();
    File xmlFixedHolidaysFile = new File(getISPACPath(PATH_FILE_FIXED_HOLIDAYS));
    if (!xmlFixedHolidaysFile.exists()) {

      ActionMessages errors = new ActionMessages();
      errors.add(
          ActionMessages.GLOBAL_MESSAGE,
          new ActionMessage("error.calendar.xmlNoExist", new String[] {PATH_FILE_FIXED_HOLIDAYS}));
      addErrors(request, errors);
    } else {

      try {
        XmlFacade xmlFacade = new XmlFacade(new FileInputStream(xmlFixedHolidaysFile));
        Node holydaysNode = xmlFacade.getSingleNode(TAG_HOLYDAYS);
        NodeIterator itrHolydays = XmlFacade.getNodeIterator(holydaysNode, TAG_HOLYDAY);
        for (Node nodeHolyday = itrHolydays.nextNode();
            nodeHolyday != null;
            nodeHolyday = itrHolydays.nextNode()) {
          String date = XmlFacade.get(nodeHolyday, TAG_DATE);
          Node labelsNode = XmlFacade.getSingleNode(nodeHolyday, TAG_LABELS);
          NodeIterator itrLabels = XmlFacade.getNodeIterator(labelsNode, TAG_LABEL);
          for (Node nodeLabel = itrLabels.nextNode();
              nodeLabel != null;
              nodeLabel = itrLabels.nextNode()) {
            String xmlLanguage = XmlFacade.getAttributeValue(nodeLabel, ATR_LANG);
            if (language.equalsIgnoreCase(xmlLanguage)) {
              String name = XmlFacade.getNodeValue(nodeLabel);
              if (!date.equalsIgnoreCase("") && !name.equalsIgnoreCase("")) {
                HolydayDef holydayDef = new HolydayDef();
                holydayDef.setName(name);
                holydayDef.setDate(date);
                fixedHolidays.add(holydayDef);
              }
            }
          }
        }
        allFixedHolidays.addAll(fixedHolidays);
      } catch (Exception e) {

        ActionMessages errors = new ActionMessages();
        errors.add(
            ActionMessages.GLOBAL_MESSAGE,
            new ActionMessage(
                "error.calendar.xmlBadFormat", new String[] {PATH_FILE_FIXED_HOLIDAYS}));
        addErrors(request, errors);
      }
    }

    request.setAttribute(DAYS_LIST, allFixedHolidays);

    return mapping.findForward("addFixedHolidays");
  }
  public MaryData process(MaryData d) throws Exception {
    // prevUnitIndex;
    // numberOfConsecutiveUnits;
    // basenameDuration;
    // phoneTier;
    // PraatIntervalTier unitTier;
    // PraatIntervalTier sourceTier;
    // sourceInterval;

    Document doc = d.getDocument();

    // initialize various variables:
    Double duration = 0.0;
    String phone = null;

    // initialize some class variables:
    PraatIntervalTier phoneTier = new PraatIntervalTier("phones");
    Double basenameDuration = 0.0;
    int prevUnitIndex = Integer.MIN_VALUE;
    int numberOfConsecutiveUnits = 0; // counter to track consecutive units
    PraatInterval sourceInterval = new PraatInterval(basenameDuration);

    // until we have a robust way of checking the voice type, just initialize unit and source tiers
    // anyway:
    PraatIntervalTier unitTier = new PraatIntervalTier("units");
    PraatIntervalTier sourceTier = new PraatIntervalTier("sources");

    // prepare to iterate only over the PHONE, SENTENCE, and BOUNDARY nodes in the MaryXML:
    NodeIterator ni = DomUtils.createNodeIterator(doc, PHONE, BOUNDARY);
    Element element;

    // now iterate over these nodes:
    while ((element = (Element) ni.nextNode()) != null) {
      switch (element.getTagName()) { // <s>, <ph>, or <boundary> as specified above
        case PHONE:
          phone = element.getAttribute("p");
          duration =
              Integer.parseInt(element.getAttribute("d")) / 1000.0; // duration is always in ms
          break;
        case BOUNDARY:
          phone =
              "_"; // TODO: perhaps we should access TargetFeatureComputer.getPauseSymbol() instead
          if (element.hasAttribute("duration")) {
            duration =
                Double.parseDouble(element.getAttribute("duration"))
                    / 1000.0; // duration is always in ms
          } else {
            duration = 0.0; // HMM voices can have duration-less <boundary/> tags
          }
          break;
        default:
          logger.error(
              "NodeIterator should not find an element of type " + element.getTagName() + " here!");
          break;
      }

      PraatInterval phoneInterval = new PraatInterval(duration, phone);

      // TODO: crude way of checking for unit selection voice; also, name of attribute could change!
      if (element.hasAttribute("units")) {
        // unitselectionProcessing(element, unitTier, prevUnitIndex, numberOfConsecutiveUnits,
        // basenameDuration,
        // sourceInterval, sourceTier);
        String units = element.getAttribute("units");
        String[] unitStrings = units.split("; "); // boundaries have only one unit string
        boolean differentSource = false;
        String basename = null;
        String unitRange = null;
        for (String unitString : unitStrings) {
          // TODO verify that unit string matches "UNITNAME BASENAME UNITINDEX UNITDURATION"
          String[] unitFields = unitString.split(" ");
          String unitName = unitFields[0];
          basename = unitFields[1];
          int unitIndex = Integer.parseInt(unitFields[2]);
          Double unitDuration = Double.parseDouble(unitFields[3]);

          // units are straightforward, just like phones:
          unitTier.appendInterval(new PraatInterval(unitDuration, unitString));

          // unit source processing is a little more elaborate:

          /*
           * Note: the following assumes that consecutive selected units are ALWAYS from the same basename! That could
           * change if basename boundaries are no longer marked by null units in the timeline.
           */
          differentSource =
              unitIndex
                  != prevUnitIndex + 1; // is source unit from a different part of the timeline?;
          if (differentSource) {
            // reset primary variables:
            numberOfConsecutiveUnits = 0;
            basenameDuration = 0.0;
          }
          // increment/increase primary variables:
          numberOfConsecutiveUnits++;
          basenameDuration += unitDuration;

          // construct unit index range string:
          unitRange = Integer.toString(unitIndex - numberOfConsecutiveUnits + 1);
          if (numberOfConsecutiveUnits > 1) {
            unitRange = unitRange + "-" + unitIndex;
          }

          // append source intervals to source tier:
          if (differentSource) {
            sourceInterval = new PraatInterval(basenameDuration, basename + ": " + unitRange);
            sourceTier.appendInterval(sourceInterval);
          } else {
            sourceInterval.setDuration(basenameDuration);
            sourceInterval.setText(basename + ": " + unitRange);
          }

          prevUnitIndex = unitIndex;
        }
        // HACK: arbitrary threshold to detect end points in ms (in the case of diphone voice or
        // boundary segment)
      } else if (duration > 10) {
        // TODO: there is still a bug somewhere regarding boundary durations with mbrola...
        phoneInterval.setDuration(duration / 1000.0);
      }
      phoneTier.appendInterval(phoneInterval);
    }

    PraatTextGrid textGrid = new PraatTextGrid();
    phoneTier.updateBoundaries(); // force full specification of timings
    textGrid.appendTier(phoneTier);

    // fragile way of checking whether this is a unit selection voice:
    if (unitTier.getNumberOfIntervals() > 0) {
      // complete and append unit and source tiers:
      unitTier.updateBoundaries();
      textGrid.appendTier(unitTier);
      sourceTier.updateBoundaries();
      textGrid.appendTier(sourceTier);
    }

    // return raw TextGrid as result:
    MaryData result = new MaryData(getOutputType(), d.getLocale());
    result.setPlainText(textGrid.toString());
    return result;
  }