在使用自定义检查异常时使用StringTokenizer评估用户输入

时间:2014-11-03 18:41:14

标签: java exception-handling stringtokenizer

过去几天我一直在研究一个java项目,虽然事情进展顺利,但我遇到了一些障碍。

项目的目的是创建一个排序查询,用户使用GUI界面搜索报告,并且应用程序会吐出所有相关数据。

Ex:报告所有质量> 3

我使用StringTokenizer对象来断开String并评估每个标记。第一个令牌必须是报告,第二个令牌必须全部,第三个令牌必须其中,第四个令牌必须是质量 basePrice numInStock ,第五个标记必须是关系运算符(>< < = > = == )。如果任何令牌与它们应该匹配,我们被指示抛出自定义检查的异常。到目前为止,我已经评估了每个令牌,并throw Exception,如果预期的令牌不是它应该的那样。

现在,当我到达关系运算符后,我应该将其转储到名为String的新optok中。问题是,我似乎无法让我的程序执行此操作,并且我很难搞清楚如何执行此操作。我尝试过很多不同的东西,似乎没什么用。

最终目标是,一旦评估并检查了所有令牌,就调用方法来打印正确的查询以及与所述查询一起的所有数据。如果其中一个令牌不匹配,则Exceptionthrown

以下是我评估每个令牌的代码,以检查它是否格式正确:

public void detectUserInput(String input) throws MissingInputException
    {
        if (input.equals(""))
        {
            System.out.println("Null input");
            throw new MissingInputException();
        }
        else 
        {
            System.out.println("Input is not null");
        }

    }//end detectUserInput 

    public void countTokens(String input) throws IncorrectFormatException
    {
        StringTokenizer tokenLength = new StringTokenizer(input, " ,");

        if (tokenLength.countTokens() < 6)
        {
            throw new IncorrectFormatException();
        }
    }//end countTokens

    public void evaluateTokens(String input) throws IllegalStartOfQueryException,
                                                    InvalidSelectorException,
                                                     InvalidQualifierException,
                                                      InvalidLValueException,
                                                       InvalidOperatorException
    {
        StringTokenizer testTokens = new StringTokenizer(input, " ,");

        if (!testTokens.nextToken().equalsIgnoreCase("report"))
        {
            throw new IllegalStartOfQueryException();
        }
        else if (!testTokens.nextToken().equalsIgnoreCase("all"))
        {
            throw new InvalidSelectorException();
        }
        else if (!testTokens.nextToken().equalsIgnoreCase("where"))
        {
            throw new InvalidQualifierException();
        }
        else if (!testTokens.nextToken().matches("quality|numInStock|basePrice"))
        {
            throw new InvalidLValueException();
        }
        else if (!testTokens.nextToken().matches(">|<|>=|<=|=="))
        {
            throw new InvalidOperatorException();
        }

        //here is where I try to take the relational operator
        //and dump it into optok, after all the previous input
        //has been validated, but it doesnt work :(
        while (testTokens.hasMoreTokens())
        {
            tok = testTokens.nextToken();

            if (tok.matches("<|>|>=|<=|=="))
            {
                optok = tok;
            }
        }

    }//end evaluateTokens

以下是我的计划的actionPerformed(),当用户将其查询输入TextField并按 GO! JButton时,会对此做出反应:

private class ButtonHandler implements ActionListener
{
    public void actionPerformed(ActionEvent ev)
    {
        if (ev.getSource() == goBtn)
        {
            input = queryFld.getText();

            try
            {
                detectUserInput(input);
                countTokens(input);
                evaluateTokens(input);
            }
            catch (MissingInputException mie)
            {
                errorFld.setText("Enter an expression");
                queryFld.setText("");
                System.err.println(mie);
                mie.printStackTrace();
            }
            catch (IncorrectFormatException ife)
            {
                errorFld.setText("Too few terms");
                queryFld.setText("");
                System.err.println(ife);
                ife.printStackTrace();
            }
            catch (IllegalStartOfQueryException isqe)
            {
                errorFld.setText("Word REPORT expected");
                queryFld.setText("");
                System.err.println(isqe);
                isqe.printStackTrace();
            }
            catch (InvalidSelectorException ise)
            {
                errorFld.setText("Selector must be ALL");
                queryFld.setText("");
                System.err.println(ise);
                ise.printStackTrace();
            }
            catch (InvalidQualifierException iqe)
            {
                errorFld.setText("Qualifier error - keyword WHERE missing");
                queryFld.setText("");
                System.err.println(iqe);
                iqe.printStackTrace();
            }
            catch (InvalidLValueException ilve)
            {
                errorFld.setText("Invalid query. quality, numInStock, "
                                + "or basePrice expected");
                queryFld.setText("");
                System.err.println(ilve);
                ilve.printStackTrace();
            }
            catch (InvalidOperatorException ioe)
            {
                errorFld.setText("InvalidOperatorException. < <= > >= == expected");
                queryFld.setText("");
                System.err.println(ioe);
                ioe.printStackTrace();
            }


        }
    }//end actionPerformed
}//end ButtonHandler

如果这看似微不足道,我道歉,但由于某种原因,我很难搞清楚。我感谢任何意见或建议。如果我错过任何需要的信息,请告诉我,我会尽快添加。此外,以下是此细分的说明:

11)现在,重点关注evaluateAll方法。获取下一个令牌。它应该是3个单词中的任何一个: “basePrice”或“quality”或“numInStock”。如果不是,请将消息“无效的查询,质量,numInStock或basePrice预期。如果是这3个单词中的一个,你期望一个关系运算符,所以得到下一个标记,但将其保存在一个新的String中,称之为optok。如果它不是正确的运算符,请将消息“无效查询, 你现在有两个字符串:令牌,它是“basePrice”或“quality”或“numInStock”,以及一个optok,它是上面列出的5个关系运算符之一。

提前致谢:)

1 个答案:

答案 0 :(得分:1)

您没有发布堆栈跟踪,所以我猜测您没有例外,并且从您的代码中读取我试图了解可能发生的事情......所以我可能错了。

在我看来,你正在使用一个标记器。令牌化器就像一个流,一旦你调用nextToken()它就会返回令牌,除非你将它保存在某个地方,否则下一次调用nextToken()会使前一个令牌无法访问。

所以,你在哪里:

    else if (!testTokens.nextToken().matches("quality|numInStock|basePrice"))
    {
        throw new InvalidLValueException();
    }
    else if (!testTokens.nextToken().matches(">|<|>=|<=|=="))
    {
        throw new InvalidOperatorException();
    }

您正在使用令牌。结果,当你到达时:

while (testTokens.hasMoreTokens()) {

所有令牌都被消耗掉了,所以它不会在这里迭代。

您应该将您的令牌保存在变量中,以便您可以检查并使用它们:

    StringTokenizer testTokens = new StringTokenizer(input, " ,");

    if (!testTokens.nextToken().equalsIgnoreCase("report"))
    {
        throw new IllegalStartOfQueryException();
    }
    else if (!testTokens.nextToken().equalsIgnoreCase("all"))
    {
        throw new InvalidSelectorException();
    }
    else if (!testTokens.nextToken().equalsIgnoreCase("where"))
    {
        throw new InvalidQualifierException();
    }

    // TODO here i use local variables, since you need to use these outside this method,
    // maybe use class fields or whatever else
    String subject = testTokens.nextToken();
    String opttok = testTokens.nextToken();

    if (!subject.matches("quality|numInStock|basePrice"))
    {
        throw new InvalidLValueException();
    }
    else if (!opttok.matches(">|<|>=|<=|=="))
    {
        throw new InvalidOperatorException();
    }

    // done, now you have opttok and subject