public void writeFormattedText()

in trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/FormattedTextParser.java [69:317]


  public void writeFormattedText(
    FacesContext context,
    String           text) throws IOException
  {
    int length = text.length();

    ArrayList<ElementInfo> elementStack = 
      new ArrayList<ElementInfo>(10);

    // Constant for current parsing state
    int state = _OUT_OF_ELEMENT;
    ResponseWriter writer = context.getResponseWriter();

    int i = 0;
    while (i < length)
    {
      char c = text.charAt(i);
      switch (state)
      {
        case _OUT_OF_ELEMENT:
          // Start of an element tag:
          if (c == '<')
          {
            // First, find out if we're starting a new
            // element or closing an earlier one
            boolean close = false;
            if (((i + 1) < length) && (text.charAt(i + 1) == '/'))
            {
              close = true;
              i++;
            }

            // Seek to the end of this element name
            int endOfElementName = _getEndOfElementName(text, i + 1, length);
            if (endOfElementName < 0)
            {
              i = length;
              break;
            }

            // Retrieve the element name
            String elementName = text.substring(i + 1, endOfElementName);

            // Find out information about this element;  in particular,
            // is this an allowed element?
            ElementInfo info = _elements.get(elementName);

            // Allowed elements.
            if (info != null)
            {
              if (close)
              {
                if (_popElement(context, elementStack, info))
                {
                  // Render (only if "popping" found a match)
                  info.endElement(context);
                }

                // and skip to the end of the element
                int endOfElement = text.indexOf('>', i);
                if (endOfElement < 0)
                {
                  _parseError("Unterminated element", i);
                  i = length;
                  break;
                }

                i = endOfElement + 1;
              }
              // Starting an allowed element
              else
              {
                // Render and move to the start of the attributes
                _pushElement(context, elementStack, info);
                info.startElement(context);
                state = (info.isEmptyElement()
                         ? _IN_EMPTY_ELEMENT :  _IN_ELEMENT);

                i = endOfElementName;
              }
            }
            // An unsupported element.  Jump past its end, and output
            // nothing.
            else
            {
              int endOfElement = text.indexOf('>', i);
              if (endOfElement < 0)
              {
                _parseError("Unterminated element", i);
                i = length;
                break;
              }

              i = endOfElement + 1;
            }
          }
          // Not in an element;  render the text
          else
          {
            // An entity?
            if (c == '&')
            {
              int endOfEntity = _getEndOfEntity(text, i, length);

              // Couldn't find a semicolon;  this probably wasn't
              // intended as an entity.  Just output the
              // ampersand directly
              if (endOfEntity < 0)
              {
                char[] chars = new char[1];
        chars[0] = c;
        writer.writeText(chars, 0, 1);
                i++;
              }
              // It's an entity - output it.
              else
              {
                c = _getEntity(text, i, endOfEntity);
                if (c != 0)
        {
                   char[] chars = new char[1];
           chars[0] = c;
           writer.writeText(chars, 0, 1);
                }
        i = endOfEntity + 1;
              }
            }
            // Just write out the character
            else
            {
        char[] chars = new char[1];
        chars[0] = c;
        writer.writeText(chars, 0, 1);
              i++;
            }
          }
          break;

        case _IN_EMPTY_ELEMENT:
        case _IN_ELEMENT:
          // Inside an element;  process attributes until
          // the element ends.
          if (c == '>')
          {
            // Ending an empty element - end it here.
            if (state == _IN_EMPTY_ELEMENT)
            {
              ElementInfo info = _peekElement(elementStack);
              info.endElement(context);
              _popElement(context, elementStack, info);
            }

            state = _OUT_OF_ELEMENT;
            i++;
          }
          else if (!Character.isWhitespace(c))
          {
            // Starting an attribute
            int endOfAttributeName = _getEndOfAttributeName(text, i, length);
            if (endOfAttributeName < 0)
            {
              _parseError("Unterminated attribute name", i);
              i = length;
              break;
            }

            String attributeName = text.substring(i, endOfAttributeName);
            // An attribute with a value
            if ('=' == text.charAt(endOfAttributeName))
            {
              if (endOfAttributeName + 1 >= length)
              {
                _parseError("Unterminated attribute value",
                            endOfAttributeName);
                i = length;
                break;
              }

              StringBuffer buffer = new StringBuffer();
              int endOfAttributeValue =
                 _getAttributeValue(text,
                                    endOfAttributeName + 1,
                                    length,
                                    buffer);

              if (endOfAttributeValue < 0)
              {
                _parseError("Unterminated attribute value",
                            endOfAttributeName + 1);
                i = length;
                break;
              }

              ElementInfo info = _peekElement(elementStack);

              // Output only the allowed attributes - CSS attributes only
              // and <font>'s size attribute.
              if ("class".equalsIgnoreCase(attributeName))
              {
                info.writeStyleClass(context, buffer.toString());
              }
              else if ("style".equalsIgnoreCase(attributeName))
              {
                info.writeInlineStyle(context, buffer.toString());
              }
              else if ("href".equalsIgnoreCase(attributeName))
              {
                info.writeHRef(context, buffer.toString());
              }
              else if ("size".equalsIgnoreCase(attributeName))
              {
                info.writeSize(context, buffer.toString());
              }

              i = endOfAttributeValue + 1;
            }
            // An empty attribute (no value) - treat as Boolean.TRUE
            else
            {
              // =-=AEW We don't currently support any boolean attributes!
              // out.writeAttribute(attributeName, Boolean.TRUE);
              if ('>' == text.charAt(endOfAttributeName))
                i = endOfAttributeName;
              else
                i = endOfAttributeName + 1;
            }
          }
          else
          {
            // Whitespace in an element - just skip over it.
            i++;
          }

          break;
      }
    }

    // Close up any leftover elements
    int size = elementStack.size() - 1;
    while (size >= 0)
    {
      ElementInfo info = elementStack.get(size);
      info.endElement(context);
      // These _should_ all be elements that do not require being closed.
      if (info.isCloseRequired())
        _parseError("Unterminated element " + info.getName(),  i);
      --size;
    }
  }