Package org.waveprotocol.wave.model.document.raw

Source Code of org.waveprotocol.wave.model.document.raw.RawDocumentParserImpl

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.waveprotocol.wave.model.document.raw;

import org.waveprotocol.wave.model.document.parser.ItemType;
import org.waveprotocol.wave.model.document.parser.XmlParseException;
import org.waveprotocol.wave.model.document.parser.XmlParserFactory;
import org.waveprotocol.wave.model.document.parser.SafeXmlPullParser;
import org.waveprotocol.wave.model.document.util.DocumentParser;
import org.waveprotocol.wave.model.util.CollectionUtils;

/**
* Parses a string into a RawDocument
*
* @author danilatos@google.com (Daniel Danilatos)
* @author hearnden@google.com (David Hearnden)
*/
public class RawDocumentParserImpl<N, E extends N, T extends N, D extends RawDocument<N, E, T>>
    implements DocumentParser<D> {

  private final RawDocument.Factory<D> factory;

  /**
   * Creates a parser that uses a particular builder.
   *
   * @param factory  builder to use when parsing
   * @return a new parser.
   */
  public static <N, E extends N, T extends N, D extends RawDocument<N, E, T>>
      RawDocumentParserImpl<N, E, T, D> create(RawDocument.Factory<D> factory) {
    return new RawDocumentParserImpl<N, E, T, D>(factory);
  }

  /**
   * Creates a parser.
   *
   * @param factory  builder to use
   */
  private RawDocumentParserImpl(RawDocument.Factory<D> factory) {
    this.factory = factory;
  }

  /**
   * @param xmlString
   * @return parsed string
   */
  public D parse(String xmlString) {
    SafeXmlPullParser parser;
    try {
      parser = XmlParserFactory.buffered(xmlString);
    } catch (XmlParseException e) {
      throw new RuntimeException("Cannot parse xml: " + xmlString, e);
    }
    // TODO(ohler): This can be an infinite loop.  Fix that.
    while (parser.getCurrentType() != ItemType.START_ELEMENT) {
      parser.next();
    }

    D document =
        factory.create(parser.getTagName(), CollectionUtils.newJavaMap(parser.getAttributes()));
    parseChildren(parser, document, document.getDocumentElement());

    return document;
  }

  /**
   * Parses an element.
   *
   * @param parser  tokenizer
   * @param parentElement the parent element to attach the parsed node to
   * @return a new element.
   */
  private E parseElement(SafeXmlPullParser parser, D doc, E parentElement) {
    E element =
        doc.createElement(parser.getTagName(), CollectionUtils.newJavaMap(parser.getAttributes()),
        parentElement, null);
    parseChildren(parser, doc, element);
    return element;
  }

  private void parseChildren(SafeXmlPullParser parser, D doc, E element) {
    boolean done = false;
    do {
      N child = null;
      parser.next();

      switch (parser.getCurrentType()) {
        case TEXT:
          child = parseText(parser, doc, element);
          break;
        case START_ELEMENT:
          child = parseElement(parser, doc, element);
          break;
        case END_ELEMENT:
          done = true;
          break;
      }
      if (child != null) {
        doc.insertBefore(element, child, null);
      }
      // This is a bit of judgment call. If this happens, the document is
      // invalid, since the closing tag is missing. By exiting the loop when
      // parser is out of tokens we're silently repairing the invalid doc.
    } while (!done && parser.hasNext());
  }

  /**
   * Parses a text node.
   *
   * @param parser  tokenizer
   * @param parentElement the parent element to attach the parsed node to
   * @return a new text node.
   */
  private T parseText(SafeXmlPullParser parser, D doc, E parentElement) {
    String text = parser.getText();
    T child = null;
    if (text.length() > 0) {
      child = doc.createTextNode(text, parentElement, null);
    }
    return child;
  }
}
TOP

Related Classes of org.waveprotocol.wave.model.document.raw.RawDocumentParserImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.