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

Source Code of org.waveprotocol.wave.model.document.raw.RawDocumentParserWithSelection$SelectionParsingListener

/**
* 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.Point;
import org.waveprotocol.wave.model.util.CollectionUtils;

/**
* Parses a string into a RawDocument
*
* @author danilatos@google.com (Daniel Danilatos)
*/
public class RawDocumentParserWithSelection<N, E extends N, T extends N,
                                            D extends RawDocument<N, E, T>> {
  private final RawDocument.Factory<D> factory;

  /**
   */
  public interface SelectionParsingListener<N> {
    /**
     */
    void onStartSelection(Point<N> start);

    /**
     */
    void onEndSelection(Point<N> end);
  }

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

  private RawDocumentParserWithSelection(RawDocument.Factory<D> factory) {
    this.factory = factory;
  }

  /**
   * @param xmlString
   * @return parsed string
   */
  public RawDocument<N, E, T> parse(String xmlString) {
    return parseIntoDocument(xmlString, null);
  }


  /**
   * @param xmlString
   * @param selectionListener
   * @return new document
   */
  public D parseIntoDocument(
      String xmlString, SelectionParsingListener<N> selectionListener) {
    SafeXmlPullParser parser;
    try {
      parser = XmlParserFactory.buffered(xmlString);
    } catch (XmlParseException e) {
      throw new RuntimeException("Cannot parse xml: " + xmlString, e);
    }

    while (parser.getCurrentType() != ItemType.START_ELEMENT) {
      parser.next();
    }

    D doc = factory.create(parser.getTagName(), CollectionUtils.newJavaMap(parser.getAttributes()));

    parseChildren(parser, selectionListener, doc, doc.getDocumentElement());

    return doc;
  }

  @SuppressWarnings("cast"// TODO(danilatos): Figure out how to avoid cast to Point<N>
  private E parseElement(SafeXmlPullParser parser, SelectionParsingListener<N> selectionListener,
      D doc, E parent, N nodeAfter) {
    return parseChildren(parser, selectionListener, doc,
        doc.createElement(parser.getTagName(),
            CollectionUtils.newJavaMap(parser.getAttributes()), parent, nodeAfter));
  }

  private E parseChildren(SafeXmlPullParser parser, SelectionParsingListener<N> selectionListener,
      D doc, E element) {

    int start = -1;
    int end = -1;
    boolean startBefore = false;
    boolean endBefore = false;
    N startNodeAfter = null;
    N endNodeAfter = null;

    N recentChild = null;

    parser.next();

    while (true) {

      ItemType type = parser.getCurrentType();

      if (type == ItemType.END_ELEMENT) {
        break;
      }

      switch (type) {
        case START_ELEMENT:
          recentChild = parseElement(parser, selectionListener, doc, element, null);
          break;
        case TEXT:
          String text = parser.getText();

          if (selectionListener != null) {
            start = text.indexOf('|');
            end = start;
            if (start >= 0) {
              text = removeChar(text, start);
            } else {
              start = text.indexOf('[');
              if (start >= 0) {
                text = removeChar(text, start);
              }
              end = text.indexOf(']');
              if (end >= 0) {
                text = removeChar(text, end);
              }
            }

            assert end == -1 || end >= start;
          }

          if (text.length() > 0) {
            recentChild = doc.createTextNode(text, element, null);

            if (start >= 0) {
              selectionListener.onStartSelection(Point.inText(recentChild, start));
            }
            if (end >= 0) {
              selectionListener.onEndSelection(Point.inText(recentChild, end));
            }
          } else {
            if (start >= 0) {
              startBefore = true;
            }
            if (end >= 0) {
              endBefore = true;
            }
          }

          parser.next();

          break;
      }

      if (startBefore && start == -1) {
        startNodeAfter = recentChild;
        startBefore = false;
      }
      if (endBefore && end == -1) {
        endNodeAfter = recentChild;
        endBefore = false;
      }

      start = -1;
      end = -1;
    }

    if (startBefore || startNodeAfter != null) {
      selectionListener.onStartSelection(Point.<N>inElement(element, startNodeAfter));
    }
    if (endBefore || endNodeAfter != null) {
      selectionListener.onEndSelection(Point.<N>inElement(element, endNodeAfter));
    }

    parser.next();
    return element;
  }

  private static String removeChar(String str, int pos) {
    return str.substring(0, pos) + str.substring(pos + 1);
  }
}
TOP

Related Classes of org.waveprotocol.wave.model.document.raw.RawDocumentParserWithSelection$SelectionParsingListener

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.