Package com.sun.jsft.facelets

Source Code of com.sun.jsft.facelets.CommandReader

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
* Portions Copyright (c) 2011 Ken Paulsen
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package com.sun.jsft.facelets;

import com.sun.jsft.event.Command;
import com.sun.jsft.event.ELCommand;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
<p>  This class is responsible for reading in all the commands for the
*  given String.  The String typically is passed in from the body
*  content of event.</p>
*
@author  Ken Paulsen (kenapaulsen@gmail.com)
*/
public class CommandReader {

    /**
     *  <p> Constructor.</p>
     */
    public CommandReader(String str) {
  this(new ByteArrayInputStream(
    ("{" + CommandReader.unwrap(str) + "}").getBytes()));
    }

    /**
     *  <p> Constructor.</p>
     *
     *  @param  stream  The <code>InputStream</code> for the {@link Command}.
     */
    protected CommandReader(InputStream stream) {
  _parser = new CommandParser(stream);
    }

    /**
     *  <p> The read method uses the {@link CommandParser} to parses the
     *      template.  It populates a {@link LayoutDefinition} structure, which
     *      is returned.</p>
     *
     *  @return  The {@link LayoutDefinition}
     *
     *  @throws  IOException
     */
    public List<Command> read() throws IOException {
  // Start...
  _parser.open();

  try {
      // Populate the LayoutDefinition from the Document
      return readCommandList();
  } finally {
      _parser.close();
  }
    }

    /**
     *
     */
// FIXME: Parenthesis are not well supported.  When convertKeywords is called,
// FIXME: it receivces "(foo...)".  First foo() is not recognized because of
// FIXME: the leading '('.  Second, there is a good possibility that other
// FIXME: keywords may exist in the middle of the string.  Need to rethink how
// FIXME: this conversion is done.
    private Command readCommand() throws IOException {
  // Skip White Space...
  _parser.skipCommentsAndWhiteSpace(CommandParser.SIMPLE_WHITE_SPACE);

  // Read the next Command
  String commandLine = _parser.readUntil(new int[] {';', '{', '}'}, true);

  // Read the children
  int ch = _parser.nextChar();
  List<Command> commandChildren = null;
  if (ch == '{') {
      // Read the Command Children
      commandChildren = readCommandList();
  } else if (ch == '}') {
      _parser.unread(ch);
  }

  // Check to see if there is a variable to store the result...
  String variable = null;
  int idx = indexOf((byte) '=', commandLine);
  if (idx != -1) {
      // We have a result variable, store it separately...
      variable = commandLine.substring(0, idx).trim();
      commandLine = commandLine.substring(++idx).trim();
  }

  // If "if" handle "else" if present
  Command elseCommand = null;
  if (commandLine.startsWith("if")) {
      // First convert "if" to the real if handler...
      commandLine = "jsft._if" + commandLine.substring(2);

      // Check the next few characters to see if they are "else"...
      _parser.skipCommentsAndWhiteSpace(CommandParser.SIMPLE_WHITE_SPACE);
      int next[] = new int[] {
    _parser.nextChar(),
    _parser.nextChar(),
    _parser.nextChar(),
    _parser.nextChar(),
    _parser.nextChar()
      };
      if ((next[0] == 'e')
        && (next[1] == 'l')
        && (next[2] == 's')
        && (next[3] == 'e')
        && (Character.isWhitespace((char) next[4]))) {
    // This is an else case, parse it...
    elseCommand = readCommand();
      } else {
    // Not an else, restore the parser state
    for (idx=4; idx > -1; idx--) {
        if (next[idx] != -1) {
      _parser.unread(next[idx]);
        }
    }
      }
  }

  // Create the Command
  Command command = null;
  if ((commandLine.length() > 0) || (commandChildren != null)) {
      command = new ELCommand(
        variable,
        convertKeywords(commandLine),
        commandChildren,
        elseCommand);
  }

  // Return the LayoutElement
  return command;
    }

    /**
     *  <p> This method replaces keywords with the "real" syntax for
     *      developer convenience.</p>
     */
    private String convertKeywords(String exp) {
  if (exp == null) {
      return null;
  }

  // Get the key to lookup
  String key = exp;
  int paren = exp.indexOf(OPEN_PAREN);
  if (paren != -1) {
      key = exp.substring(0, paren);
      if (key.indexOf(".") != -1) {
    // '.' found, this is not a keyword...
    return exp;
      }
  }
  key = key.trim();

  // Check for mapping...
  String value = _reservedMappings.get(key);
  if (value != null) {
      exp = value + exp.substring(key.length());
  }

  return exp;
    }

    /**
     *  <p> This method looks for the given <code>char</code> in the given
     *      <code>String</code>.  It will not match any values that are
     *      found within parenthesis or quotes.</p>
     */
    private int indexOf(byte ch, String str) {
  byte[] bytes = str.getBytes();
 
  int idx = 0;
  int insideChar = -1;
  for (byte curr : bytes) {
      if (insideChar == -1) {
    // Not inside anything...
    if (ch == curr) {
        break;
    } else if (('\'' == curr) || ('"' == curr)) {
        insideChar = curr;
    } else if (OPEN_PAREN == curr) {
        insideChar = CLOSE_PAREN;
    } else if (OPEN_BRACKET == curr) {
        insideChar = CLOSE_BRACKET;
    }
      } else if (insideChar == curr) {
    // Was inside something, ending now...
    insideChar = -1;
      }
      idx++;
  }

  // If we found it return it, otherwise return -1
  if (idx >= bytes.length) {
      idx = -1;
  }
  return idx;
    }

    /**
     *  <p> This method reads Commands until a closing '}' is encountered.</p>
     */
    private List<Command> readCommandList() throws IOException {
  int ch = _parser.nextChar();
  List<Command> commands = new ArrayList<Command>();
  Command command = null;
  while (ch != '}') {
      // Make sure readCommand gets the full command line...
      if (ch != '{') {
    // We want to throw this char away...
    _parser.unread(ch);
      }

      // Read a Command
      command = readCommand();
      if (command != null) {
    commands.add(command);
      }

      // Skip White Space...
      _parser.skipCommentsAndWhiteSpace(CommandParser.SIMPLE_WHITE_SPACE);

      // Get the next char...
      ch = _parser.nextChar();
      if (ch == -1)  {
    throw new IOException(
        "Unexpected end of stream! Expected to find '}'.");
      }
  }

  // Return the Commands
  return commands;
    }

    /**
     *  <p> This function removes the containing CDATA tags, if found.</p>
     */
    private static String unwrap(String str) {
  str = str.trim();
  if (str.startsWith(OPEN_CDATA)) {
      int endingIdx = str.lastIndexOf(CLOSE_CDATA);
      if (endingIdx != -1) {
    // Remove the CDATA wrapper
    str = str.substring(OPEN_CDATA.length(), endingIdx);
      }
  }
  return str;
    }

    // Map to hold shortcut mappings (e.g. keywords)
    private static Map<String, String> _reservedMappings    =
      new HashMap<String, String>(16);
    static {
  _reservedMappings.put("foreach", "jsft.foreach");
  _reservedMappings.put("for", "jsft._for");
  _reservedMappings.put("println", "jsft.println");
  _reservedMappings.put("write", "jsft.write");
  _reservedMappings.put("setAttribute", "jsft.setAttribute");
  _reservedMappings.put("responseComplete", "jsft.responseComplete");
  _reservedMappings.put("renderResponse", "jsft.renderResponse");
  _reservedMappings.put("printStackTrace", "jsft.printStackTrace");
  _reservedMappings.put("getNanoTime", "jsft.getNanoTime");
    }

    private static final char      OPEN_BRACKET    = '[';
    private static final char      CLOSE_BRACKET   = ']';
    private static final char      OPEN_PAREN      = '(';
    private static final char      CLOSE_PAREN      = ')';
    private static final String      OPEN_CDATA      = "<![CDATA[";
    private static final String      CLOSE_CDATA      = "]]>";

    private CommandParser  _parser    = null;
}
TOP

Related Classes of com.sun.jsft.facelets.CommandReader

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.