org.amanzi.asn1.parser.token.TokenAnalyzer.java Source code

Java tutorial

Introduction

Here is the source code for org.amanzi.asn1.parser.token.TokenAnalyzer.java

Source

/* AWE - Amanzi Wireless Explorer
 * http://awe.amanzi.org
 * (C) 2008-2009, AmanziTel AB
 *
 * This library is provided under the terms of the Eclipse Public License
 * as described at http://www.eclipse.org/legal/epl-v10.html. Any use,
 * reproduction or distribution of the library constitutes recipient's
 * acceptance of this agreement.
 *
 * This library is distributed WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

package org.amanzi.asn1.parser.token;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.amanzi.asn1.parser.AbstractStream;
import org.amanzi.asn1.parser.token.impl.ControlSymbol;
import org.amanzi.asn1.parser.token.impl.ReservedWord;
import org.amanzi.asn1.parser.token.impl.SimpleToken;
import org.apache.commons.lang3.ArrayUtils;

/**
 * TODO Purpose of
 * <p>
 * </p>
 * 
 * @author Nikolay Lagutko (nikolay.lagutko@amanzitel.com)
 * @since 1.0.0
 */
public class TokenAnalyzer extends AbstractStream<IToken> {

    /** int END_OF_FILE_CHARACTER field */
    private static final int END_OF_FILE_CHARACTER = -1;

    /**
     * Default size of Stream Buffer
     */
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 100;

    /**
     * Character for a Next Line
     */
    private static final int NEXT_LINE_CHARACTER = '\n';

    /**
     * Default Separations Characters
     */
    private static final int[] DEFAULT_SKIP_CHARACTERS = new int[] { ' ', NEXT_LINE_CHARACTER, '\t', '\r' };

    /*
     * Cache for Tokens to prevent re-creation of similar tokens
     */
    private Map<String, IToken> tokenCache = new HashMap<String, IToken>();

    /*
     * Input Stream for an Analyzer
     */
    private InputStream inputStream;

    /*
     * String to a Default Token that trails main Token
     */
    private String trailingToken;

    /*
     * True if parsed token is BIT STRING or OCTET STRING
     */
    private boolean isBitOrOctetString;

    private boolean isPreviousCharacter;
    private char previousCharacter;

    /**
     * Creates a TokenAnalyzer based on InputStream
     * 
     * @param inputStream
     */
    public TokenAnalyzer(InputStream inputStream) {
        this.inputStream = new BufferedInputStream(inputStream, DEFAULT_BUFFER_SIZE);
    }

    @Override
    protected IToken readNextElement() {
        try {
            String tokenText = readNextToken();

            if (tokenText.isEmpty()) {
                return null;
            }

            IToken token = tokenCache.get(tokenText);
            if (token == null) {
                token = convertToToken(tokenText);
                tokenCache.put(tokenText, token);
            }

            return token;
        } catch (IOException e) {
            // TODO: add logger, log exception here
        }

        return null;
    }

    /**
     * Converts read Text to a Token entity
     * 
     * @param tokenText
     * @return
     */
    private IToken convertToToken(String tokenText) {
        IToken result = null;

        result = ControlSymbol.findByText(tokenText);

        if (result == null) {
            result = ReservedWord.findByText(tokenText);
        }

        if (result == null) {
            result = new SimpleToken(tokenText);
        }

        return result;
    }

    /**
     * Read next Token from an input stream
     * 
     * @return
     */
    private String readNextToken() throws IOException {
        if (trailingToken != null) {
            String toReturn = trailingToken;
            trailingToken = null;
            return toReturn;
        }

        StringBuffer token = new StringBuffer();

        parsing_loop: while (true) {
            int read = inputStream.read();

            if (read != END_OF_FILE_CHARACTER) {
                char readChar = (char) read;

                if (isPreviousCharacter) {
                    token.append(previousCharacter);
                }

                isPreviousCharacter = false;
                boolean space = false;

                if (ArrayUtils.contains(DEFAULT_SKIP_CHARACTERS, read)) {
                    if (token.length() == 0) {
                        continue;
                    } else {
                        space = true;
                    }
                }

                token.append(readChar);

                if (isBitOrOctetString) {
                    isBitOrOctetString = false;
                    if ((!ControlSymbol.LEFT_BRACE.getTokenText().equals(token.toString()))
                            && (!ControlSymbol.LEFT_BRACKET.getTokenText().equals(token.toString()))) {
                        isPreviousCharacter = true;
                        previousCharacter = readChar;
                        return ControlSymbol.RIGHT_BRACE.getTokenText();
                    }
                }

                String tokenString = token.toString();

                for (ReservedWord reservedWord : ReservedWord.getPossibleTokens(readChar)) {
                    if (reservedWord.getTokenText().startsWith(tokenString)) {
                        continue parsing_loop;
                    }
                }

                if (space) {
                    String result = token.toString().trim();
                    if (ReservedWord.BIT_STRING.getTokenText().equals(result)
                            || ReservedWord.OCTET_STRING.getTokenText().equals(result)) {
                        isBitOrOctetString = true;
                    }
                    return result;
                }

                for (ControlSymbol singleToken : ControlSymbol.getPossibleTokens(readChar)) {
                    if (singleToken.checkText(tokenString)) {
                        trailingToken = singleToken.getTokenText();
                        String toReturn = singleToken.cut(tokenString);

                        if (toReturn.isEmpty()) {
                            toReturn = trailingToken;
                            trailingToken = null;
                        }

                        if (singleToken == ControlSymbol.COMMENT) {
                            skipUntilNextLine();
                            token.delete(0, token.length());
                            break;
                        }

                        return toReturn;

                    }
                }
            } else {
                if ((token.length() > 0) || (read == END_OF_FILE_CHARACTER)) {
                    break;
                }
            }
        }

        return token.toString();
    }

    /**
     * In case of
     */
    private void skipUntilNextLine() throws IOException {
        int read = END_OF_FILE_CHARACTER;

        do {
            read = inputStream.read();
        } while ((read != END_OF_FILE_CHARACTER) && (read != NEXT_LINE_CHARACTER));
    }

}