//
// MOFToken.java
//
// The contents of this file are subject to the SNIA Public License Version 1.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.snia.org/resources/openSource.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 
// License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is MOFToken.java
// 
// The Initial Developer of the Original Code is David Simons.
//
// Contributor(s):
//
//
// This source uses the Solaris WBEM APIs version 2.2. 
// Synchronization will be maintained with the Solaris WBEM APIS,
// which are being standardized through the Java Community Process.
//
//
// $Id: MOFToken.java,v 1.1 2003/07/17 18:32:55 kumpf Exp $
//
// $Log: MOFToken.java,v $
// Revision 1.1  2003/07/17 18:32:55  kumpf
// HP-BAPU: PEP-64 CIM Client and CIM Listener Java Interface
//
// Revision 1.1.1.1  2001/10/31 18:16:26  karl
// import of SNIA 0_7
//
// Revision 1.7  2000/08/16 05:59:58  shawn
// merge P_TOMCAT31 branch
//
// Revision 1.6.6.1  2000/08/10 00:03:34  shawn
// head merge
//
// Revision 1.6  2000/07/19 16:54:46  davidsi
// - Removed non applicable TODO.
//
// Revision 1.5  2000/05/11 10:11:36  davidsi
// - Fixed tabs.
//
// Revision 1.4  2000/05/06 17:12:02  davidsi
// - Many performance improvements
// - Brought in line with SUN WBEM APIs 2.2
//
// Revision 1.3  2000/04/09 14:19:42  davidsi
// - Added locale and include tokens.
// - Added support for tracking line numbers.
//
// Revision 1.2  2000/02/13 15:09:54  davidsi
// - Added text to cover re-use of Solaris WBEM APIs.
//
// Revision 1.1.1.1  2000/02/06 16:41:03  davidsi
// Initial version.
//
//
//
package org.snia.wbemcmd.mof;

import java.util.Vector;

class MOFToken	{
    static int inc=0;
    static public int CONST_PRAGAMA=inc++;
    static public int PRECOMP_LINE=inc++;
    static public int PRECOMP_FILE=inc++;
    static public int PRAGMA=inc++;
    static public int NAMESPACE=5;
    static public int SCHEMA=inc++;
    static public int SOURCE=inc++;
    static public int NONLOCALE=inc++;
    static public int INSTANCELOCALE=inc++;
    static public int CLASS=inc++;
    static public int ASSOCIATION=inc++;
    static public int INDICATION=inc++;
    static public int PROPERTY=inc++;
    static public int REFERENCE=inc++;
    static public int METHOD=inc++;
    static public int PARAMETER=inc++;
    static public int ANY=inc++;
    static public int REF=inc++;
    static public int INSTANCE=inc++;
    static public int OF=inc++;
    static public int AS=inc++;
    static public int QUALIFIER=inc++;
    static public int SCOPE=inc++;
    static public int FLAVOR=inc++;
    static public int ENABLEOVERRIDE=inc++;
    static public int DISABLEOVERRIDE=inc++;
    static public int TRANSLATABLE=inc++;
    static public int TOSUBCLASS=inc++;
    static public int RESTRICTED=inc++;
    static public int DT_UINT8=inc++;
    static public int DT_SINT8=inc++;
    static public int DT_UINT16=inc++;
    static public int DT_SINT16=inc++;
    static public int DT_UINT32=inc++;
    static public int DT_SINT32=inc++;
    static public int DT_UINT64=inc++;
    static public int DT_SINT64=inc++;
    static public int DT_REAL32=inc++;
    static public int DT_REAL64=inc++;
    static public int DT_CHAR16=inc++;
    static public int DT_STR=inc++;
    static public int DT_BOOL=inc++;
    static public int DT_DATETIME=inc++;
    static public int TRUE_VALUE=inc++;
    static public int FALSE_VALUE=inc++;
    static public int NULL_VALUE=inc++;
    static public int BINARY_VALUE=inc++;
    static public int OCTAL_VALUE=inc++;
    static public int DECIMAL_VALUE=inc++;
    static public int HEX_VALUE=inc++;
    static public int REAL_VALUE=inc++;
    static public int STRING_VALUE=inc++;
    static public int CHAR_VALUE=inc++;
    static public int IDENTIFIER=inc++;
    static public int ALIAS_IDENTIFIER=inc++;
    static public int COMMA=inc++;
    static public int COLON=inc++;
    static public int SEMICOLON=inc++;
    static public int EQUAL=inc++;
    static public int OPEN_CUR_BRA=inc++;
    static public int CLOSE_CUR_BRA=inc++;
    static public int OPEN_SQU_BRA=inc++;
    static public int CLOSE_SQU_BRA=inc++;
    static public int OPEN_BRA=inc++;
    static public int CLOSE_BRA=inc++;
    static public int UNEXPECTED=inc++;
    static private String[] tokenNames=new String[inc];
    
    static private char[] charMap=new char[100];
    static private int[] charMapToken=new int [100];		// same index as charMap
    static private int charMapIndex=0;
    static private int MAX_ARR_SIZE='z'-'a'+2;
    static private int MAX_HITS=9;
    static private int MAX_TOKEN_LENGTH=16;
    static private String[][][] stringMap=new String[MAX_ARR_SIZE][MAX_TOKEN_LENGTH][MAX_HITS];
    static private int[][][] stringMapToken=new int [MAX_ARR_SIZE][MAX_TOKEN_LENGTH][MAX_HITS]; 	// same index as stringMap
    static private int[][] stringMapIndex=new int[MAX_ARR_SIZE][MAX_TOKEN_LENGTH];
    static private Vector tokenNumbers=new Vector();
    static private Vector tokenStrings=new Vector();
    static private int maxID=0;
    private char []inarray;
    public int id;
    
    static void addToMap(String str,int tkid) {
	str=str.toUpperCase();
	char[] values=str.toCharArray();
	
	if (str.length()<0)
	    return;
    
	if (tkid>maxID)
	    maxID=tkid;
	
	tokenNames[tkid]=str;
	tokenNumbers.addElement(new Integer(tkid));
	tokenStrings.addElement(str);
	
	char firstChar=values[0];
	
	if ( (str.length()==1) &&
	    !( (firstChar>='a' && firstChar<='z')
	    ||(firstChar>='A' && firstChar<='Z')
	    ||(firstChar>='0' && firstChar<='9'))) {
		//
		// Treat one-off non-alpha characters specially
		//
		charMap[charMapIndex]=values[0];
		charMapToken[charMapIndex]=tkid;
		charMapIndex++;
		return;
	}
	int arrIndex;
	if ((firstChar>='a' && firstChar<='z'))
	    arrIndex=firstChar-'a';
	else if ((firstChar>='A' && firstChar<='Z'))
	    arrIndex=firstChar-'A';
	else
	    arrIndex=MAX_ARR_SIZE-1;
	
	int length=str.length();
	if (length>=MAX_TOKEN_LENGTH) {
	    System.err.println("Could not stored token - reset MAX_TOKEN_LENGTH :"+str);
	    return;
	}
	int indexer=stringMapIndex[arrIndex][length];
	
	if (indexer>=MAX_HITS) {
	    System.err.println("Could not stored token - reset MAX_HITS :"+str);
	    return;
	}
	
	stringMap[arrIndex][length][indexer]=str;
	stringMapToken[arrIndex][length][indexer]=tkid;
	stringMapIndex[arrIndex][length] += 1;
	
							
    }
    
    static {
	for(int i=0;i<MAX_ARR_SIZE;i++)
	    for(int j=0;j<MAX_TOKEN_LENGTH;j++)
		stringMapIndex[i][j]=0;
     
	addToMap("#PRAGMA",PRAGMA);
	addToMap("NAMESPACE",NAMESPACE);
	addToMap("SCHEMA",SCHEMA);
	addToMap("SOURCE",SOURCE);
	addToMap("NONLOCALE",NONLOCALE);
	addToMap("INSTANCELOCALE",INSTANCELOCALE);
	addToMap("CLASS",CLASS); 
       
	addToMap("ASSOCIATION",ASSOCIATION);
	addToMap("INDICATION",INDICATION);
	addToMap("PROPERTY",PROPERTY);
	addToMap("REFERENCE",REFERENCE);
	addToMap("METHOD",METHOD);
	addToMap("PARAMETER",PARAMETER);
	addToMap("ANY",ANY);
	addToMap("REF",REF);
	addToMap("INSTANCE",INSTANCE);
	addToMap("OF",OF);
	addToMap("AS",AS);
	addToMap("QUALIFIER",QUALIFIER);
	addToMap("SCOPE",SCOPE);
	addToMap("FLAVOR",FLAVOR);
	addToMap("ENABLEOVERRIDE",ENABLEOVERRIDE);
	addToMap("DISABLEOVERRIDE",DISABLEOVERRIDE);
	addToMap("TRANSLATABLE",TRANSLATABLE);
	addToMap("TOSUBCLASS",TOSUBCLASS);
	addToMap("RESTRICTED",RESTRICTED);
	addToMap("TRUE",TRUE_VALUE);
	addToMap("FALSE",FALSE_VALUE);	   
	addToMap("NULL",NULL_VALUE);
	addToMap("UINT8",DT_UINT8);
	addToMap("SINT8",DT_SINT8);
	addToMap("UINT16",DT_UINT16);
	addToMap("SINT16",DT_SINT16);
	addToMap("UINT32",DT_UINT32);
	addToMap("SINT32",DT_SINT32);
	addToMap("UINT64",DT_UINT64);
	addToMap("SINT64",DT_SINT64);
	addToMap("REAL32",DT_REAL32);
	addToMap("REAL64",DT_REAL64);
	addToMap("CHAR16",DT_CHAR16);
	addToMap("STRING",DT_STR);
	addToMap("BOOLEAN",DT_BOOL);
	addToMap("DATETIME",DT_DATETIME);
     
      
	addToMap(",",COMMA);
	addToMap(":",COLON);
	addToMap(";",SEMICOLON);
	addToMap("=",EQUAL);
	addToMap("{",OPEN_CUR_BRA);
	addToMap("}",CLOSE_CUR_BRA);
	addToMap("[",OPEN_SQU_BRA);
	addToMap("]",CLOSE_SQU_BRA);
	addToMap("(",OPEN_BRA);
	addToMap(")",CLOSE_BRA);
    }
    
    static int getMaxID() {
	return(maxID);
    }
    
    public int tokenNumber() throws
	    IllegalArgumentException {
	throw new IllegalArgumentException("Token "+tokenName()+" is not numeric");
    }
    
    public String tokenString() throws
	    IllegalArgumentException {
	if (id==UNEXPECTED)
	    return("[UNXPTD]");

	if (id<inc)
	    return(tokenNames[id]);

	return("[BADTOK]"); 
    }
    

    public String tokenName() {
	return(tokenName(id));
    }
    
    static public String tokenName(int val) {
	if (val==UNEXPECTED)
	    return("[UNXPTD]");

	if (val<inc)
	    return(tokenNames[val]);

	return("[BADTOK]");
    }
    
    public void setInputArray(char []inarray) {
	this.inarray=inarray;
    }
    
    public int parse(int offset,int maxlen) throws
	    IllegalArgumentException {
	
	int i;
	char firstChar=inarray[offset];
	
	//
	// If its the start of string quit right now!
	//
	if (firstChar=='"')
	    throw new IllegalArgumentException("Not valid token");

	
	if (!( (firstChar>='a' && firstChar<='z')
		||(firstChar>='A' && firstChar<='Z')
		||(firstChar>='0' && firstChar<='9'))) {
	    //
	    // Look for special chars
	    //
	    for(i=0;i<charMapIndex;i++) {
		if (firstChar==charMap[i]) {
		    id=charMapToken[i];
		    return(offset+1);
		}
	    }
	}

	int arrIndex;
	if ((firstChar>='a' && firstChar<='z'))
	    arrIndex=firstChar-'a';
	else if ((firstChar>='A' && firstChar<='Z'))
	    arrIndex=firstChar-'A';
	else
	    arrIndex=MAX_ARR_SIZE-1;

	
	String[][] stringArrayToCompare=stringMap[arrIndex];
	int[] indexArray=stringMapIndex[arrIndex];
	int[][] tokenArray=stringMapToken[arrIndex];
	
	int maxToken=MAX_TOKEN_LENGTH;
	if (offset + maxToken>maxlen)
	    maxToken=maxlen-offset;
	
	for(int splice=1;splice<maxToken;splice++) {
	    //
	    // If we locate a space then the token can't be any
	    // longer so break out
	    //
	    char endToken=inarray[offset + splice-1];
	    if (endToken==' ' || endToken==',' ) { //|| endToken==';') {
		break;
	    }
	    
	    //
	    // No tokens of this length...
	    //
	    if (indexArray[splice]==0)
		continue;
	    
	    String posttoken;
	    char term;
	      
	    //
	    // Off the end and it will only get longer as we go thru the main
	    // loop so break...
	    if (offset+splice>=maxlen)
		break;
		    
	    term=inarray[offset];   
	    if ((term>='a' && term<='z')||(term>='A' && term<='Z')) {
		term=inarray[offset + splice];

		//
		// If the character following the possible token would be a continuation
		// for an identifier then this can't be a match
		//
		 if ( (term>='a' && term<='z')
		    ||(term>='A' && term<='Z')
		    ||(term>='0' && term<='9')
		    ||(term=='_')) {
		       continue;
		    }
	    }

		
	    //
	    // Now get strings for this particular length
	    //
	    String[] stringsToCompare=stringArrayToCompare[splice];
	    int maxTokens=indexArray[splice];
	    int[] tokenarray=tokenArray[splice];
	    posttoken=String.valueOf(inarray,offset,splice).toUpperCase();
	    
	    for(i=0;i<maxTokens;i++) {
		if (stringsToCompare[i].equals(posttoken)) {
		    id=tokenarray[i];
		    return(offset+splice);
		} 
	    }
	}
	throw new IllegalArgumentException("Not valid token");
    }

    //
    // Constructors
    //
    public MOFToken(int iid) {
	id=iid;
    }
    public MOFToken() {
	id=UNEXPECTED;
    }
	
    
}
