ParamDeclarationParser.java :  » Testing » PolePosition-0.20 » com » versant » core » jdo » Java Open Source

Java Open Source » Testing » PolePosition 0.20 
PolePosition 0.20 » com » versant » core » jdo » ParamDeclarationParser.java

/*
 * Copyright (c) 1998 - 2005 Versant Corporation
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Versant Corporation - initial API and implementation
 */
package com.versant.core.jdo;

import com.versant.core.util.CharBuf;

import com.versant.core.common.BindingSupportImpl;

/**
 * This parses a comma separated list of query parameters into types and names.
 * TODO Make this parse array types e.g. String[]
 */
public class ParamDeclarationParser {

    /**
     * Callback interface for parsing results.
     */
    public static interface Handler {

        /**
         * The parser has sucessfully parsed a parameter type and name at
         * position index in the parameter list (first param is 0).
         */
        public void parameterParsed(int index, String type, String name);
    }

    private static final int STATE_START = 0;
    private static final int STATE_LOOK_FOR_TYPE = 1;
    private static final int STATE_IN_TYPE = 2;
    private static final int STATE_LOOK_FOR_NAME = 3;
    private static final int STATE_IN_NAME = 4;
    private static final int STATE_LOOK_FOR_COMMA = 5;

    /**
     * Parse params into types and names and return the number of parameters
     * parsed.
     */
    public static int parse(String params, Handler handler) {
        if (params == null) return 0;
        int len = params.length();
        if (len == 0) return 0;
        int state = STATE_START;
        String type = null;
        int count = 0;
        CharBuf buf = new CharBuf();
        for (int pos = 0; ; pos++) {
            if (pos < len) {
                char c = params.charAt(pos);
                switch (state) {
                    case STATE_START:
                    case STATE_LOOK_FOR_TYPE:
                        if (isIdStart(c)) {
                            buf.append(c);
                            state = STATE_IN_TYPE;
                        } else if (!isWs(c)) {
                            error(pos, "parameter type", c);
                        }
                        break;
                    case STATE_IN_TYPE:
                        if (isId(c) || c == '.') {
                            buf.append(c);
                        } else if (isWs(c)) {
                            type = buf.toString();
                            buf.clear();
                            state = STATE_LOOK_FOR_NAME;
                        } else {
                            error(pos, "parameter type", c);
                        }
                        break;
                    case STATE_LOOK_FOR_NAME:
                        if (isIdStart(c)) {
                            buf.append(c);
                            state = STATE_IN_NAME;
                        } else if (!isWs(c)) {
                            error(pos, "parameter name", c);
                        }
                        break;
                    case STATE_IN_NAME:
                        if (isId(c)) {
                            buf.append(c);
                        } else if (c == ',' || isWs(c)) {
                            handler.parameterParsed(count++, type, buf.toString());
                            buf.clear();
                            type = null;
                            if (c == ',') state = STATE_LOOK_FOR_TYPE;
                            else state = STATE_LOOK_FOR_COMMA;
                        } else {
                            error(pos, "parameter name", c);
                        }
                        break;
                    case STATE_LOOK_FOR_COMMA:
                        if (c == ',') {
                            state = STATE_LOOK_FOR_TYPE;
                        } else if (!isWs(c)) {
                            error(pos, "comma", c);
                        }
                        break;
                }
            } else {
                switch (state) {
                    case STATE_LOOK_FOR_TYPE:
                        error(pos, "parameter type", (char)-1);
                    case STATE_IN_TYPE:
                    case STATE_LOOK_FOR_NAME:
                        error(pos, "parameter name", (char)-1);
                    case STATE_IN_NAME:
                        handler.parameterParsed(count++, type, buf.toString());
                }
                break;
            }
        }
        return count;
    }

    private static boolean isWs(char c) {
        return c == ' ' || c == '\n' || c == '\t';
    }

    private static boolean isIdStart(char c) {
        return c == '_'
            || (c >= 'A' && c <= 'Z')
            || (c >= 'a' && c <= 'z');
    }

    private static boolean isId(char c) {
        return c == '_'
            || (c >= 'A' && c <= 'Z')
            || (c >= 'a' && c <= 'z')
            || (c >= '0' && c <= '9');
    }

    private static void error(int pos, String msg, char c) {
        throw BindingSupportImpl.getInstance().runtime("Invalid parameter declaration: Expected " +
            msg + ", got '" + c + "' at position " + pos);
    }

}

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.