📄 parser.java
字号:
/*
* j2wap is distributed under the terms of the GNU Public License
*
* j2wap was written by:
*
* Scott Campbell
* Michael Nordling
* Karl Maftoum
* Julian Bright
*
* This was a final project for Comp.Engineering at the University of Canberra, Australia
*
* Now released as Open Source software. 28 November 2000
*
* Email: k_maftoum@hotmail.com for more info
*
* Use entirely at your own risk.
*/
package wae;
import java.io.IOException;
import java.util.Stack;
import java.util.Vector;
import ui.*;
/**
* Title: Parser
* Descrfiption: An abstract class, which contains functionality required for
* the parsing of both cards and templates.
* Company: J2wap.com
* @author: Scott campbell
* @version 1.1
*/
abstract class Parser extends WbxmlUtility
{
/** Flags whether a event element is currently being parsed. */
protected boolean c_bolInEventElement = false;
/** Flags whether we have finished parsing the desired card or template. */
protected boolean c_bolFinishedParsing = false;
/**
* Flags whether navigation to the card was via a <code>go</code> or
* <code>prev</code> event.
*/
protected boolean c_bolNavDirectionFlag = true;
/** Flags whether a <code>anchor</code> element is currently being parsed. */
protected boolean c_bolInAnchorElement = false;
/** Flags whether a <code>onevent</code> element is currently being parsed. */
protected boolean c_bolInOnevent = false;
/** Flags whether a <code>ontimer</code> element has been found. */
protected boolean c_bolFoundOntimer = false;
/**
* Flags whether the last <code>go</code> element parsed contained
* <code>setvar</code> or <code>postfield</code> elements.
*/
protected boolean c_bolLastGoHasVars = false;
/** A count of open elements. */
protected int c_intOpenElements = 0;
/** Contains the end tags of currently open elements. */
protected Stack c_clsStackEndTags = new Stack ();
/** Reference to the <code>BrowserCore</code> object. */
protected BrowserCore c_clsBrowserCore;
/** Reference to the <code>CurrentDeck</code> object containing the bytecode.*/
protected CurrentDeck c_clsDeck;
/** Reference to the <code>EventManagement</code> object. */
protected EventManagement c_clsEventManagement;
/** Reference to the <code>BrowserContext</code> object. */
protected BrowserContext c_clsBrContext;
/** Flags if we are currently parsing the deck's <code>template</code>. */
protected boolean c_bolParsingTemplate;
/**
* Attribute start and value delimeter as represented on the card vector
* created by the parser.
*/
protected static final String ATTR_DELIM = (String) "=";
/** Length of the start and value delimeter. */
protected static final int ATTR_DELIM_LEN = ATTR_DELIM.length();
/** */
public String c_strMethod = new String();
/**
* Set up links to other objects.
* @param in_clsBrowserCore Reference to the </code>BrowserCore</code>.
* @param in_clsDeck Reference to the </code>CurrentDeck</code>.
* @param in_clsEventManagement Reference to the </code>EventManagaement</code>.
* @param in_clsBrContext Reference to the </code>BrowserContext</code>.
*/
public void init (BrowserCore in_clsBrowserCore,
CurrentDeck in_clsDeck,
EventManagement in_clsEventManagement,
BrowserContext in_clsBrContext)
{
c_clsBrowserCore = in_clsBrowserCore;
c_clsDeck = in_clsDeck;
c_clsEventManagement = in_clsEventManagement;
c_clsBrContext = in_clsBrContext;
} // init
/**
* Resolve the value of the variable that the extension token refers to.
* @param bytId Token in byte form.
* @return String representing the extension.
*/
public String handleExtensions (int bytId)
throws IOException, NullPointerException, J2WapException
{
String clsVariableValue;
switch (bytId)
{
case Wbxml.EXT_I_0: case Wbxml.EXT_I_1: case Wbxml.EXT_I_2:
// Variable substitution - escaped. Name of the variable is inline and
// follows as termstr.
return (c_clsBrowserCore.getVariable (readInlineString()));
case Wbxml.EXT_T_0: case Wbxml.EXT_T_1: case Wbxml.EXT_T_2:
// Variable substitution - escaped. Variable name is encoded as a
// reference into the string table.
return (c_clsBrowserCore.getVariable (readStringFromStringTable()));
case Wbxml.EXT_0: case Wbxml.EXT_1: case Wbxml.EXT_2:
// Reserved for future use.
break;
case Wbxml.OPAQUE:
int len = readMultiByteInteger ();
byte [] buf = new byte[len];
for (int i = 0; i < len; i++)
buf [len] = nextByte ();
// Represent byte array as a String and put it in the vector.
return (new String(buf));
} // switch
return "";
} // handleExtensions
/**
* Get the string that the extension token is referring to.
* @param: byte Extension Token.
* @return: String The String that the extension token is referring to.
*/
public String resolveExtension (int bytId)
throws IOException, NullPointerException, J2WapException
{
String clsVariableValue;
switch (bytId)
{
case Wbxml.EXT_I_0: case Wbxml.EXT_I_1: case Wbxml.EXT_I_2:
// Variable substitution - Name of the variable is inline and
// follows as termstr.
return ("$" + readInlineString() + "$");
case Wbxml.EXT_T_0: case Wbxml.EXT_T_1: case Wbxml.EXT_T_2:
// Variable substitution - Name of the variable is encoded as a
// reference into the string table.
return ("$" + readStringFromStringTable() + "$");
case Wbxml.EXT_0: case Wbxml.EXT_1: case Wbxml.EXT_2:
// Reserved for future use.
break;
case Wbxml.OPAQUE:
int len = readMultiByteInteger ();
byte [] buf = new byte[len];
for (int i = 0; i < len; i++)
buf [len] = nextByte ();
// Represent byte array as a String and put it in the vector.
return (new String(buf));
} // switch
return "";
} // resolveExtension
/**
* Parses a card or template's attributes. If an intrinsic event is found,
* check if it should be acted upon.
* @param in_bolCardOrTemplate Indicates whether a card or template is
* being parsed.
* @return Event ID of any intrinsic event that is invoked. If non,
* WmlTags.NO_EVENT is returned.
*/
public int readCardOrTemplateAttrs (boolean in_bolCardOrTemplate)
throws IOException, NullPointerException, J2WapException
{
int intAttrDelim;
String clsStrAttr = null;
String clsStrAttrValue = null;
byte bytId = nextByte ();
while (bytId != Wbxml.END)
{
clsStrAttr = new String (readAttribute (bytId));
intAttrDelim = clsStrAttr.indexOf ("=");
clsStrAttrValue = clsStrAttr.substring(intAttrDelim+2,
clsStrAttr.length()-1);
if (bytId == WmlTags.BYTE_NEWCONT_TRUE && parsingDesiredCard())
c_clsBrContext.resetBrowserContext ();
else if (isAnIntrinsicEvent (bytId))
{
/* We have an intrinsic event. Check if the the direction of navigation
* to the card fires the event. A <template> only has intrinsic events
* as attributes, hence the elseif.
*/
if (parsingDesiredCardOrTemplate ())
{
if (bytId == WmlTags.BYTE_ONTIMER)
c_clsBrowserCore.setOntimerId (c_clsEventManagement.registerGo (
clsStrAttrValue, false, null, null));
else if (fireIntrinsicEvent (bytId))
return c_clsEventManagement.registerGo (
clsStrAttrValue, false, null, null);
} // if
} // if
else if (parsingDesiredCard ()) // Templates only have intrinsic event attrs.
conditionalAddToVector (clsStrAttr); // Add attribute to vector.
bytId = nextByte ();
} // while
// Have all the attributes. Add the end of attributes flag to vector.
conditionalAddToVector(WmlTags.ENDATTRIBS);
return WmlTags.NO_EVENT;
} // readCardOrTemplateAttrs
/**
* Determines if a byte represents an intrinsic event.
* @param in_bytId Tag as a byte.
* @return True if byte repesents an intrinsic event, false otherwise.
*/
private boolean isAnIntrinsicEvent (byte in_bytId)
{
return ((in_bytId == WmlTags.TYPE_ONENTERFWRDS) ||
(in_bytId == WmlTags.TYPE_ONENTERBKWRDS) ||
(in_bytId == WmlTags.BYTE_ONTIMER));
} // isAnIntrinsicEvent
/**
* Determines if an intrinsic event should be invoked.
* @param in_bytId Tag as a byte.
* @return True if intrinsic event should be invoked, false otherwise.
*/
private boolean fireIntrinsicEvent (byte in_bytId)
{
return (((in_bytId == WmlTags.BYTE_ONENTERFORWARDS ||
in_bytId == WmlTags.AVAL_ONENTERFWRDS ||
in_bytId == WmlTags.TYPE_ONENTERFWRDS) &&
c_bolNavDirectionFlag == WmlTags.ONENTER_FORWARDS) ||
((in_bytId == WmlTags.BYTE_ONENTERBACKWARDS ||
in_bytId == WmlTags.AVAL_ONENTERBKWRDS ||
in_bytId == WmlTags.TYPE_ONENTERBKWRDS) &&
c_bolNavDirectionFlag == WmlTags.ONENTER_BACKWARDS));
} // fireIntrinsicEvent
/**
* Parses a card's attributes. If an intrinsic event is found, check
* if it should be acted upon, otherwise just add the attribute to
* the vector.
* @return Event ID of event that is invoked. WmlTags.NO_EVENT if no event
* was invoked.
*/
public int readOnevent ()
throws IOException, NullPointerException, J2WapException
{
int intEventId = 0;
// Get "type" attribute.
byte bytId = nextByte ();
byte bytEventType = (byte) intrinsicEventType (bytId);
if (bytEventType == Wbxml.INVALID_BYTE)
{
J2WapException clsExc = new J2WapException ("The \"type\" attribute " +
"of an <onevent> is not a valid intrinsic event");
throw (clsExc);
} // if
// Check if the intrinisic enevent identified by the "type" attribute
// is to be executed.
if ((bytEventType == WmlTags.BYTE_ONENTERFORWARDS &&
c_bolNavDirectionFlag == true) ||
(bytEventType == WmlTags.BYTE_ONENTERBACKWARDS &&
c_bolNavDirectionFlag == WmlTags.ONENTER_BACKWARDS))
{
// Get the content, (Either <go>, <prev>, <refresh> or <noop>) then
// read past the end attributes byte.
byte bytTemp = nextByte (); // Get past the end of attribute token.
bytTemp = nextByte ();
bytId = (byte) (Wbxml.ELEMENT_TAG_ID & bytTemp);
if (bytId == WmlTags.GO)
return readGoEvent(true, hasContent(bytId));
else if (bytId == WmlTags.PREV || bytId == WmlTags.REFRESH)
return readPrevOrResfreshEvent(bytId, true);
}
else if (bytEventType == WmlTags.BYTE_ONPICK ||
bytEventType == WmlTags.BYTE_ONTIMER)
{
// Check if the attribute is legal.
if (!c_bolFoundOntimer)
c_bolFoundOntimer = true;
else
{
// Raise exception.
J2WapException clsExcep = new J2WapException(
"Too many <timer> elements. A <timer> element " +
"has already been found in the card.");
throw (clsExcep);
} // if-else
// Get the content, (Either <go>, <prev>, <refresh> or <noop>) then
// read past the end attributes byte.
byte bytTemp = nextByte (); // Get past the end of attribute token.
bytTemp = nextByte ();
bytId = (byte) (bytTemp & Wbxml.ELEMENT_TAG_ID);
if (bytId == WmlTags.GO)
intEventId = readGoEvent(false, hasContent(bytId));
else if (bytId == WmlTags.PREV || bytId == WmlTags.REFRESH)
intEventId = readPrevOrResfreshEvent(bytId, false);
// If the type is "ontimer" than set the ontimer event id.
if (parsingDesiredCardOrTemplate () &&
bytEventType == WmlTags.BYTE_ONTIMER)
c_clsBrowserCore.setOntimerId (intEventId);
}
else
{
// Error. Raise an exception.
J2WapException clsExcep = new J2WapException(
"The type attribute (" + bytId + ") of an <onevent> was illegal");
throw (clsExcep);
} // if-else
// Get the onevent end tag.
if (nextByte () != Wbxml.END)
{
// Error raise an exception.
J2WapException clsExcep = new J2WapException(
"Too many elements. An <onevent> can only have one element.");
throw (clsExcep);
}
return WmlTags.NO_EVENT;
} // readOnevent
/**
* Check what type of intrinsic event the type attribute really represents
* @param in_bytId First byte of the <code>onevent</code> "type" attribute.
* @return Type of intrinsic event.
*/
private byte intrinsicEventType (byte in_bytId)
throws IOException, NullPointerException
{
switch (in_bytId)
{
case WmlTags.TYPE_ONENTERBKWRDS:
return WmlTags.BYTE_ONENTERBACKWARDS;
case WmlTags.TYPE_ONENTERFWRDS:
return WmlTags.BYTE_ONENTERFORWARDS;
case WmlTags.TYPE_ONTIMER:
return WmlTags.BYTE_ONTIMER;
case WmlTags.BYTE_TYPE:
byte bytAttrVal = nextByte ();
if (bytAttrVal == WmlTags.AVAL_ONENTERBKWRDS)
return WmlTags.BYTE_ONENTERBACKWARDS;
if (bytAttrVal == WmlTags.AVAL_ONENTERFWRDS)
return WmlTags.BYTE_ONENTERFORWARDS;
if (bytAttrVal == WmlTags.AVAL_ONTIMER)
return WmlTags.BYTE_ONTIMER;
} // switch
// This return is only in here so that the method will compile.
return Wbxml.INVALID_BYTE;
} // intrinsicEventType
/**
* Read the next attribute of an element. This method is called in a loop by
* another method to read all attributes of an element.
* @param in_bytId Attribute start token as a byte.
* @return Attribute start = attribute value as a string.
*/
public String readAttribute (byte in_bytId)
throws IOException, NullPointerException, J2WapException
{
StringBuffer clsSBufAttrib = new StringBuffer ();
// Get the attribute start token
clsSBufAttrib.append (c_clsDeck.resolveAttrStartToken (in_bytId));
// Find the position of '=' in name.
int intDelim = clsSBufAttrib.toString().indexOf ('=');
/* If attribute start token does not contain part of attribute
value, '=' or '"', then append or insert '="' or '"' as needed. */
if (intDelim == -1)
clsSBufAttrib.append("=\"");
else
clsSBufAttrib.insert(intDelim+1, "\"");
// Append a " (double quote) to the attribute then return it.
readRestOfAttr (clsSBufAttrib, true);
return (clsSBufAttrib.append ("\"").toString ());
} // readAttribute
/**
* Reads whats left of the attribute.
* @param in_clsSBufAttr The rest of the attribute is appended to this.
* @param in_bolGetValue If True the value of the variable will be
* obtained. Otherwise "$" followed by the variable name will
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -