Package net.percederberg.mibble

Source Code of net.percederberg.mibble.MibAnalyzerUtil

/*
* MibAnalyzerUtil.java
*
* This work 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 work 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* Copyright (c) 2004-2007 Per Cederberg. All rights reserved.
*/

package net.percederberg.mibble;

import java.util.ArrayList;
import java.util.HashMap;

import net.percederberg.grammatica.parser.Node;
import net.percederberg.grammatica.parser.Production;
import net.percederberg.grammatica.parser.Token;
import net.percederberg.mibble.asn1.Asn1Constants;

/**
* Helper and utility functions for the MIB file analyzer.
*
* @author   Per Cederberg, <per at percederberg dot net>
* @version  2.9
* @since    2.9
*/
class MibAnalyzerUtil {

    /**
     * An internal hash map containing all the used comment tokens.
     * When a comment string is returned by the getComments() method,
     * the corresponding tokens will be added to this hash map and
     * not returned on subsequent calls.
     */
    private static HashMap commentTokens = new HashMap();

    /**
     * Checks if a node corresponds to a bit value. This method is
     * used to distinguish between bit values and object identifier
     * values during the analysis.
     *
     * @param node           the parse tree node to check
     *
     * @return true if the node contains a bit value, or
     *         false otherwise
     */
    static boolean isBitValue(Node node) {
        if (node.getId() == Asn1Constants.COMMA) {
            return true;
        } else if (node.getId() == Asn1Constants.NAME_VALUE_LIST
                && node.getChildCount() < 4) {

            return true;
        } else {
            for (int i = 0; i < node.getChildCount(); i++) {
                if (isBitValue(node.getChildAt(i))) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * Returns all the comments associated with a specified node. If
     * there are multiple comment lines, these will be concatenated
     * into a single string. This method handles comments before,
     * inside and after (starting on the same line) as the specified
     * node. It also updates the comment token cache to avoid
     * returning the same comments twice.
     *
     * @param node           the production or token node
     *
     * @return the comment string, or
     *         null if no comments were found
     */
    static String getComments(Node node) {
        String  comment = "";
        String  str;
        Token   token;

        str = getCommentsBefore(node);
        if (str != null) {
            comment = str;
        }
        str = getCommentsInside(node);
        if (str != null) {
            if (comment.length() > 0) {
                comment += "\n\n";
            }
            comment += str;
        }
        token = getCommentTokenSameLine(node);
        if (token != null) {
            if (comment.length() > 0) {
                comment += "\n\n";
            }
            token = token.getPreviousToken();
            comment += getCommentsAfter(token);
        }
        return comment.length() <= 0 ? null : comment;
    }

    /**
     * Returns all the footer comments after the specified node. This
     * method also clears the comment cache and should be called
     * exactly once after each MIB file parsed, in order to free
     * memory used by the comment token cache.
     *
     * @param node           the production or token node
     *
     * @return the comment string, or
     *         null if no comments were found
     */
    static String getCommentsFooter(Node node) {
        String  comment = getCommentsAfter(node);

        commentTokens.clear();
        return comment;
    }

    /**
     * Returns all the comments before the specified node. If
     * there are multiple comment lines possibly separated by
     * whitespace, they will be concatenated into one string.
     *
     * @param node          the production or token node
     *
     * @return the comment string, or
     *         null if no comments were found
     */
    private static String getCommentsBefore(Node node) {
        Token         token = getFirstToken(node);
        ArrayList     comments = new ArrayList();
        StringBuffer  buffer = new StringBuffer();
        String        res = "";

        if (token != null) {
            token = token.getPreviousToken();
        }
        while (token != null) {
            if (token.getId() == Asn1Constants.WHITESPACE) {
                comments.add(getLineBreaks(token.getImage()));
            } else if (token.getId() == Asn1Constants.COMMENT &&
                       !commentTokens.containsKey(token)) {

                commentTokens.put(token, null);
                comments.add(token.getImage().substring(2).trim());
            } else {
                break;
            }
            token = token.getPreviousToken();
        }
        for (int i = comments.size() - 1; i >= 0; i--) {
            buffer.append(comments.get(i));
        }
        res = buffer.toString().trim();
        return res.length() <= 0 ? null : res;
    }

    /**
     * Returns all the comments after the specified node. If
     * there are multiple comment lines possibly separated by
     * whitespace, they will be concatenated into one string.
     *
     * @param node           the production or token node
     *
     * @return the comment string, or
     *         null if no comments were found
     */
    private static String getCommentsAfter(Node node) {
        Token         token = getLastToken(node);
        StringBuffer  comment = new StringBuffer();
        String        res;

        if (token != null) {
            token = token.getNextToken();
        }
        while (token != null) {
            if (token.getId() == Asn1Constants.WHITESPACE) {
                comment.append(getLineBreaks(token.getImage()));
            } else if (token.getId() == Asn1Constants.COMMENT &&
                       !commentTokens.containsKey(token)) {

                commentTokens.put(token, null);
                comment.append(token.getImage().substring(2).trim());
            } else {
                break;
            }
            token = token.getNextToken();
        }
        res = comment.toString().trim();
        return res.length() <= 0 ? null : res;
    }

    /**
     * Returns all the unhandled comments inside the specified node.
     * Note that only comment tokens not present in the token cache
     * will be returned by this method.
     *
     * @param node           the production or token node
     *
     * @return the comment string, or
     *         null if no comments were found
     */
    private static String getCommentsInside(Node node) {
        Token         token = getFirstToken(node);
        Token         last = getLastToken(node);
        StringBuffer  comment = new StringBuffer();
        String        res;

        while (token != null && token != last) {
            if (token.getId() == Asn1Constants.COMMENT &&
                !commentTokens.containsKey(token)) {

                commentTokens.put(token, null);
                comment.append(token.getImage().substring(2).trim());
                comment.append("\n");
            }
            token = token.getNextToken();
        }
        res = comment.toString().trim();
        return res.length() <= 0 ? null : res;
    }

    /**
     * Returns the first comment token on the same line.
     *
     * @param node           the production node
     *
     * @return the first comment token on the same line
     */
    private static Token getCommentTokenSameLine(Node node) {
        Token  last = getLastToken(node);
        Token  token;

        if (last == null) {
            return null;
        }
        token = last.getNextToken();
        while (token != null) {
            switch (token.getId()) {
            case Asn1Constants.WHITESPACE:
            case Asn1Constants.COMMA:
                // Skip to next
                break;
            case Asn1Constants.COMMENT:
                if (last.getEndLine() == token.getStartLine()) {
                    return token;
                } else {
                    return null;
                }
            default:
                return null;
            }
            token = token.getNextToken();
        }
        return null;
    }

    /**
     * Returns the first token in a production.
     *
     * @param node           the production or token node
     *
     * @return the first token in the production, or
     *         null if none was found
     */
    private static Token getFirstToken(Node node) {
        while (node instanceof Production) {
            node = node.getChildAt(0);
        }
        return (Token) node;
    }

    /**
     * Returns the last token in a production.
     *
     * @param node           the production or token node
     *
     * @return the last token in the production, or
     *         null if none was found
     */
    private static Token getLastToken(Node node) {
        while (node instanceof Production) {
            node = node.getChildAt(node.getChildCount() - 1);
        }
        return (Token) node;
    }

    /**
     * Returns a string containing the line breaks of an input
     * string.
     *
     * @param str            the input string
     *
     * @return a string containing zero or more line breaks
     */
    private static String getLineBreaks(String str) {
        StringBuffer  res = new StringBuffer();

        if (str == null) {
            return null;
        }
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == '\n') {
                res.append('\n');
            }
        }
        return res.toString();
    }
}
TOP

Related Classes of net.percederberg.mibble.MibAnalyzerUtil

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.