/*
* Name: DirectiveParser
* Author: Richard Rodger
*
* Copyright (c) 2000-2004 Richard Rodger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
// package
package org.jostraca.directive;
// import
import org.jostraca.util.ValueSet;
import org.jostraca.util.ValueCode;
import java.io.StringReader;
import java.io.Reader;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
/** Parses directive text.
*/
public class DirectiveParser {
// private static
private static final String PARSER_IS_NULL = "iParser is null => call parse method first";
// private instance
private String iSource = "";
private DirectiveAntlrParser iParser = null;
private String[] iDirectiveNameElements = null;
// public methods
public void parse( String pDirectiveExpr ) throws DirectiveException {
iSource = pDirectiveExpr;
StringReader booleanExprReader = new StringReader( pDirectiveExpr );
parse( booleanExprReader, pDirectiveExpr );
}
private void parse( Reader pReader, String pDirectiveExpr ) throws DirectiveException {
try {
// always create new lexer and parser
DirectiveAntlrLexer lexer = new DirectiveAntlrLexer( pReader );
DirectiveAntlrParser parser = new DirectiveAntlrParser( lexer );
parser.root();
iParser = parser;
}
catch( Exception e ) {
throw new DirectiveException( DirectiveException.CODE_parse, new ValueSet( ValueCode.DIRECTIVE, pDirectiveExpr ), e );
}
}
public String getName() {
if( null != iParser ) {
iDirectiveNameElements = parseDirectiveName( iParser.getName() );
return iDirectiveNameElements[0];
}
else {
throw new IllegalStateException( PARSER_IS_NULL );
}
}
public String getFullName() {
if( null != iParser ) {
return iParser.getName();
}
else {
throw new IllegalStateException( PARSER_IS_NULL );
}
}
public String[] getNameElements() {
if( null != iParser ) {
if( null == iDirectiveNameElements ) {
iDirectiveNameElements = getNameElements( iParser.getName() );
}
return (String[]) iDirectiveNameElements.clone();
}
else {
throw new IllegalStateException( PARSER_IS_NULL );
}
}
/** Used if the directive name is externally specified */
public static String[] getNameElements( String pName ) {
if( null != pName ) {
return parseDirectiveName( pName );
}
else {
throw new IllegalArgumentException( "rName is null" );
}
}
public Vector getUnnamedArgs() {
if( null != iParser ) {
return iParser.getUnnamedArgs();
}
else {
throw new IllegalStateException( PARSER_IS_NULL );
}
}
public Hashtable getNamedArgs() {
if( null != iParser ) {
return iParser.getNamedArgs();
}
else {
throw new IllegalStateException( PARSER_IS_NULL );
}
}
public Hashtable getCanonicalArgs( Vector pUnnamedArgNames, Hashtable pArgDefaults ) {
if( null == pUnnamedArgNames ) {
pUnnamedArgNames = new Vector();
}
if( null == pArgDefaults ) {
pArgDefaults = new Hashtable();
}
Hashtable canonical = (Hashtable) pArgDefaults.clone();
// get names for unnamed
// NOTE: no name, no canonical arg returned
Vector unnamedV = getUnnamedArgs();
int numUN = unnamedV.size();
int numUNAN = pUnnamedArgNames.size();
for( int unI = 0; unI < numUN && unI < numUNAN; unI++ ) {
canonical.put( pUnnamedArgNames.elementAt(unI), unnamedV.elementAt(unI) );
}
// named args can override unnamed
Hashtable namedArgsHT = getNamedArgs();
Enumeration names = namedArgsHT.keys();
while( names.hasMoreElements() ) {
String name = (String) names.nextElement();
String value = (String) namedArgsHT.get( name );
canonical.put( name, value );
}
return canonical;
}
public String toString() {
return "[directive="+iParser.getName()+", s=["+iSource+"] unamed="+getUnnamedArgs()+" named="+getNamedArgs()+"]";
}
// private methods
/** Not done with antlr because it's too hard :) */
private static String[] parseDirectiveName( String pFullName ) {
String[] res = new String[] { "" };
if( null != pFullName && !"".equals( pFullName ) ) {
Vector elements = new Vector();
int slashIndex = -1;
int lastPos = 0;
try {
while( -1 != ( slashIndex = pFullName.indexOf( "/", lastPos ) ) ) {
//System.out.println( "lp:"+lastPos+" si:"+slashIndex );
elements.addElement( pFullName.substring( lastPos, slashIndex ) );
lastPos = slashIndex + 1;
}
}
catch( Exception e ) {
// REVIEW: handle substring errors xproperly
e.printStackTrace();
}
finally {
if( lastPos > -1 && lastPos <= pFullName.length() ) {
elements.addElement( pFullName.substring( lastPos ) );
}
}
if( 0 < elements.size() ) {
int numE = elements.size();
res = new String[ numE ];
for( int eI = 0; eI < numE; eI++ ) {
res[eI] = (String) elements.elementAt(eI);
}
}
}
return res;
}
}