incubator-ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jspei...@apache.org
Subject svn commit: r1440067 [1/2] - in /incubator/ambari/trunk: ./ ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ ambari-server/src/main/java/org/apache/ambari/server/api/predicate/ ambari-server/src/main/java/org/apache/ambari/server/api/...
Date Tue, 29 Jan 2013 19:19:11 GMT
Author: jspeidel
Date: Tue Jan 29 19:19:10 2013
New Revision: 1440067

URL: http://svn.apache.org/viewvc?rev=1440067&view=rev
Log:
AMBARI-1280. Support explicit predicate grouping in API queries

Added:
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/InvalidQueryException.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/PredicateCompiler.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryLexer.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryParser.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/Token.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/AbstractExpression.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/Expression.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpression.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpressionFactory.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/NotLogicalExpression.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/RelationalExpression.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AbstractOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AndOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/EqualsOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterEqualsOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessEqualsOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperatorFactory.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/NotEqualsOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/NotOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/Operator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/OrOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/RelationalOperator.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/RelationalOperatorFactory.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/predicate/
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/predicate/QueryLexerTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/predicate/QueryParserTest.java
Modified:
    incubator/ambari/trunk/CHANGES.txt
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/BaseManagementHandler.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/TestSuite.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/QueryCreateHandlerTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/ReadHandlerTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/BaseRequestTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/DeleteRequestTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/GetRequestTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/PostRequestTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/PutRequestTest.java

Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1440067&r1=1440066&r2=1440067&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Tue Jan 29 19:19:10 2013
@@ -12,6 +12,8 @@ Trunk (unreleased changes):
 
  NEW FEATURES
 
+ AMBARI-1280. Support explicit predicate grouping in API queries. (jspeidel)
+
  AMBARI-1180. Display host check status results given by the agent as part
  of host registration. (yusaku)
 

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/BaseManagementHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/BaseManagementHandler.java?rev=1440067&r1=1440066&r2=1440067&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/BaseManagementHandler.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/BaseManagementHandler.java Tue Jan 29 19:19:10 2013
@@ -18,10 +18,12 @@
 
 package org.apache.ambari.server.api.handlers;
 
+import org.apache.ambari.server.api.predicate.InvalidQueryException;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.api.services.Request;
 import org.apache.ambari.server.api.services.Result;
 import org.apache.ambari.server.api.services.ResultImpl;
+import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.api.services.persistence.PersistenceManager;
 import org.apache.ambari.server.api.services.persistence.PersistenceManagerImpl;
 import org.apache.ambari.server.api.util.TreeNode;
@@ -57,7 +59,13 @@ public abstract class BaseManagementHand
 
   public Result handleRequest(Request request) {
     ResourceInstance resource = request.getResource();
-    Predicate queryPredicate = request.getQueryPredicate();
+    Predicate queryPredicate;
+    try {
+      queryPredicate = request.getQueryPredicate();
+    } catch (InvalidQueryException e) {
+      return new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST,
+          "Invalid Request: " + e.getMessage()));
+    }
     if (queryPredicate != null) {
       resource.getQuery().setUserPredicate(queryPredicate);
     }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java?rev=1440067&r1=1440066&r2=1440067&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java Tue Jan 29 19:19:10 2013
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.api.handlers;
 
+import org.apache.ambari.server.api.predicate.InvalidQueryException;
 import org.apache.ambari.server.api.services.Request;
 import org.apache.ambari.server.api.services.ResultImpl;
 import org.apache.ambari.server.api.services.ResultStatus;
@@ -51,9 +52,12 @@ public class ReadHandler implements Requ
       return new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e.getMessage()));
     }
 
-    query.setUserPredicate(request.getQueryPredicate());
     Result result;
+    Predicate p = null;
     try {
+      p = request.getQueryPredicate();
+      query.setUserPredicate(p);
+
       result = query.execute();
       result.setResultStatus(new ResultStatus(ResultStatus.STATUS.OK));
     } catch (SystemException e) {
@@ -63,7 +67,7 @@ public class ReadHandler implements Requ
     } catch (UnsupportedPropertyException e) {
       result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e.getMessage()));
     } catch (NoSuchResourceException e) {
-      if (request.getQueryPredicate() == null) {
+      if (p == null) {
         // no predicate specified, resource requested by id
         result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.NOT_FOUND, e.getMessage()));
       } else {
@@ -74,6 +78,9 @@ public class ReadHandler implements Requ
     } catch (IllegalArgumentException e) {
       result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST,
           "Invalid Request: " + e.getMessage()));
+    } catch (InvalidQueryException e) {
+      result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST,
+          "Invalid Request: " + e.getMessage()));
     } catch (RuntimeException e) {
       if (LOG.isErrorEnabled()) {
         LOG.error("Caught a runtime exception executing a query", e);

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/InvalidQueryException.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/InvalidQueryException.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/InvalidQueryException.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/InvalidQueryException.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate;
+
+/**
+ * Exception indicating that a query compilation error occurred.
+ */
+public class InvalidQueryException extends Exception {
+  /**
+   * Constructor.
+   *
+   * @param msg msg
+   */
+  public InvalidQueryException(String msg) {
+    super(msg);
+  }
+
+  /**
+   * Constructor.
+   *
+   * @param msg        msg
+   * @param throwable  root cause
+   */
+  public InvalidQueryException(String msg, Throwable throwable) {
+    super(msg, throwable);
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/PredicateCompiler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/PredicateCompiler.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/PredicateCompiler.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/PredicateCompiler.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate;
+
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Compiler which takes a query expression as input and produces a predicate instance as output.
+ */
+public class PredicateCompiler {
+
+  /**
+   * Lexer instance used to translate expressions into stream of tokens.
+   */
+  private QueryLexer lexer = new QueryLexer();
+
+  /**
+   * Parser instance used to produce a predicate instance from a stream of tokens.
+   */
+  private QueryParser parser = new QueryParser();
+
+  /**
+   * Generate a predicate from a query expression.
+   *
+   * @param exp  query expression
+   *
+   * @return a predicate instance
+   * @throws InvalidQueryException if unable to compile the expression
+   */
+  public Predicate compile(String exp) throws InvalidQueryException {
+    return parser.parse(lexer.tokens(exp));
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryLexer.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryLexer.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryLexer.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryLexer.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,473 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Scans a query expression and generates an array of tokens.
+ * Each token contains type and value information.
+ *
+ * First, the query expression is broken down into string tokens using
+ * a regular expression which splits on a set of deliminators which includes
+ * operators and brackets.
+ *
+ * Second, each string token is converted into a Token with type an value information.
+ */
+public class QueryLexer {
+  /**
+   * All valid deliminators.
+   */
+  private static final String[] ALL_DELIMS = {"<=",">=","!=","=","<",">","&","|","!","(", ")"};
+
+  /**
+   * Map of token type to list of valid handlers for next token.
+   */
+  private static final Map<Token.TYPE, List<TokenHandler>> TOKEN_HANDLERS =
+      new HashMap<Token.TYPE, List<TokenHandler>>();
+
+  /**
+   * Set of property names to ignore.
+   */
+  private static final Set<String> SET_IGNORE = new HashSet<String>();
+
+  /**
+   * Constructor.
+   * Register token handlers.
+   */
+  public QueryLexer() {
+    List<TokenHandler> listHandlers = new ArrayList<TokenHandler>();
+    listHandlers.add(new LogicalUnaryOperatorTokenHandler());
+    listHandlers.add(new OpenBracketTokenHandler());
+    listHandlers.add(new PropertyOperandTokenHandler());
+
+    TOKEN_HANDLERS.put(Token.TYPE.BRACKET_OPEN, listHandlers);
+    TOKEN_HANDLERS.put(Token.TYPE.LOGICAL_OPERATOR, listHandlers);
+    TOKEN_HANDLERS.put(Token.TYPE.LOGICAL_UNARY_OPERATOR, listHandlers);
+
+    listHandlers= new ArrayList<TokenHandler>();
+    listHandlers.add(new RelationalOperatorTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.PROPERTY_OPERAND, listHandlers);
+
+    listHandlers = new ArrayList<TokenHandler>();
+    listHandlers.add(new ValueOperandTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.RELATIONAL_OPERATOR, listHandlers);
+
+    listHandlers = new ArrayList<TokenHandler>();
+    listHandlers.add(new CloseBracketTokenHandler());
+    listHandlers.add(new LogicalOperatorTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.VALUE_OPERAND, listHandlers);
+    TOKEN_HANDLERS.put(Token.TYPE.BRACKET_CLOSE, listHandlers);
+  }
+
+
+  /**
+   * Scan the provided query and generate a token stream to be used by the query parser.
+   *
+   * @param exp  the query expression to scan
+   *
+   * @return an array of tokens
+   * @throws InvalidQueryException if the query is invalid
+   */
+  public Token[] tokens(String exp) throws InvalidQueryException {
+
+    ScanContext ctx = new ScanContext();
+
+    for (String tok : parseStringTokens(exp)) {
+      List<TokenHandler> listHandlers = TOKEN_HANDLERS.get(ctx.getLastTokenType());
+      boolean            processed    = false;
+      int                idx          = 0;
+
+      while (!processed && idx < listHandlers.size()) {
+        processed = listHandlers.get(idx++).handleToken(tok, ctx);
+      }
+
+      if (! processed) {
+        throw new InvalidQueryException("Invalid Query Token: token='" +
+            tok + "\', previous token type=" + ctx.getLastTokenType());
+      }
+    }
+
+    return ctx.getTokenList().toArray(new Token[ctx.getTokenList().size()]);
+  }
+
+  /**
+   * Uses a regular expression to scan a query expression and produce a list of string tokens.
+   * These tokens are the exact strings that exist in the original syntax.
+   *
+   * @param exp  the query expression
+   *
+   * @return list of string tokens from the query expression
+   */
+  private List<String> parseStringTokens(String exp) {
+    Pattern      pattern       = generatePattern();
+    Matcher      matcher       = pattern.matcher(exp);
+    List<String> listStrTokens = new ArrayList<String>();
+    int pos = 0;
+
+    while (matcher.find()) { // while there's a delimiter in the string
+      if (pos != matcher.start()) {
+        // add anything between the current and previous delimiter to the tokens list
+        listStrTokens.add(exp.substring(pos, matcher.start()));
+      }
+      listStrTokens.add(matcher.group()); // add the delimiter
+      pos = matcher.end(); // Remember end of delimiter
+    }
+    if (pos != exp.length()) {
+      // Add any chars remaining in the string after last delimiter
+      listStrTokens.add(exp.substring(pos));
+    }
+    return listStrTokens;
+  }
+
+  /**
+   * Generate the regex pattern to tokenize the query expression.
+   *
+   * @return the regex pattern
+   */
+  private Pattern generatePattern() {
+    StringBuilder sb = new StringBuilder();
+    sb.append('(');
+    for (String delim : ALL_DELIMS) { // For each delimiter
+      if (sb.length() != 1) sb.append('|');
+      sb.append('\\');
+      sb.append(delim);
+    }
+    sb.append(')');
+
+    return Pattern.compile(sb.toString());
+  }
+
+  /**
+   * Add property names that the lexer should ignore.
+   */
+  static {
+    // ignore values
+    SET_IGNORE.add("fields");
+    SET_IGNORE.add("_");
+  }
+
+  /**
+   * Scan context.  Provides contextual information related to the current scan.
+   */
+  private class ScanContext {
+    /**
+     * The last token type scanned.
+     */
+    private Token.TYPE m_lastType;
+
+    /**
+     * The last property operand value
+     */
+    private String m_propertyName;
+
+    /**
+     * List of tokens generated by the scan
+     */
+    private List<Token> m_listTokens = new ArrayList<Token>();
+
+    /**
+     * Whether the current expression should be ignored.
+     * This is used to ignore portions of the query string that are
+     * not query specific.
+     */
+    private boolean m_ignore = false;
+
+    /**
+     * Constructor.
+     */
+    private ScanContext() {
+      //init last type to the logical op type
+      m_lastType = Token.TYPE.LOGICAL_OPERATOR;
+    }
+
+    /**
+     * Set the ignore tokens flag.
+     *
+     * @param ignore  true to ignore tokens; false otherwise
+     */
+    public void setIgnoreTokens(boolean ignore) {
+      m_ignore = ignore;
+    }
+
+    /**
+     * Get the type of the last token.
+     *
+     * @return the type of the last token
+     */
+    public Token.TYPE getLastTokenType() {
+      return m_lastType;
+    }
+
+    /**
+     * Set the type of the last token.
+     *
+     * @param lastType  the type of the last token
+     */
+    public void setLastTokenType(Token.TYPE lastType) {
+      m_lastType = lastType;
+    }
+
+    /**
+     * Get the current property operand value.
+     * This is used to hold the property operand name until it is added since,
+     * the following relational operator token is added first.
+     *
+     * @return the current property operand value
+     */
+    public String getPropertyOperand() {
+      return m_propertyName;
+    }
+
+    /**
+     * Set the current property operand value.
+     * This is used to hold the property operand name until it is added since,
+     * the following relational operator token is added first.
+     */
+    public void setPropertyOperand(String prop) {
+      m_propertyName = prop;
+    }
+
+    /**
+     * Add a token.
+     *
+     * @param token  the token to add
+     */
+    public void addToken(Token token) {
+      if (! m_ignore) {
+        m_listTokens.add(token);
+      }
+    }
+
+    /**
+     * Get the list of generated tokens.
+     *
+     * @return the list of generated tokens
+     */
+    public List<Token> getTokenList() {
+      return m_listTokens;
+    }
+  }
+
+
+  /**
+   * Token handler base class.
+   * Token handlers are responsible for processing specific token type.
+   */
+  private abstract class TokenHandler {
+    /**
+     * Provides base token handler functionality then delegates to the individual concrete handlers.
+     *
+     * @param token   the token to process
+     * @param ctx     the scan context
+     *
+     * @return true if this handler processed the token; false otherwise
+     * @throws InvalidQueryException  if an invalid token is encountered
+     */
+    public boolean handleToken(String token, ScanContext ctx) throws InvalidQueryException {
+      if (handles(token, ctx.getLastTokenType())) {
+        _handleToken(token, ctx);
+        ctx.setLastTokenType(getType());
+        return true;
+      } else {
+        return false;
+      }
+    }
+
+    /**
+     * Process a token.
+     *
+     * @param token  the token to process
+     * @param ctx    the current scan context
+     * @throws InvalidQueryException if an invalid token is encountered
+     */
+    public abstract void _handleToken(String token, ScanContext ctx) throws InvalidQueryException;
+
+    /**
+     * Get the token handler type.
+     *
+     * @return the token handler type
+     */
+    public abstract Token.TYPE getType();
+
+    /**
+     * Determine if a handler handles a specific token type.
+     *
+     * @param token              the token type
+     * @param previousTokenType  the previous token type
+     *
+     * @return true if the handler handles the specified type; false otherwise
+     */
+    public abstract boolean handles(String token, Token.TYPE previousTokenType);
+  }
+
+  /**
+   * Property Operand token handler.
+   */
+  private class PropertyOperandTokenHandler extends TokenHandler {
+
+    @Override
+    public void _handleToken(String token, ScanContext ctx) throws InvalidQueryException {
+      //don't add prop name token until after operator token
+      if (! SET_IGNORE.contains(token)) {
+        ctx.setPropertyOperand(token);
+      } else {
+        ctx.setIgnoreTokens(true);
+        if (!ctx.getTokenList().isEmpty()) {
+        // remove '&' token that separates ignored token and query
+          ctx.getTokenList().remove(ctx.getTokenList().size() -1);
+        }
+      }
+    }
+
+    @Override
+    public Token.TYPE getType() {
+      return Token.TYPE.PROPERTY_OPERAND;
+    }
+
+    @Override
+    public boolean handles(String token, Token.TYPE previousTokenType) {
+      return token.matches("[^!&\\|<=|>=|!=|=|<|>\\(\\)]+");
+    }
+  }
+
+  /**
+   * Value Operand token handler.
+   */
+  private class ValueOperandTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(String token, ScanContext ctx) throws InvalidQueryException {
+      ctx.addToken(new Token(Token.TYPE.VALUE_OPERAND, token));
+    }
+
+    @Override
+    public Token.TYPE getType() {
+      return Token.TYPE.VALUE_OPERAND;
+    }
+
+    @Override
+    public boolean handles(String token, Token.TYPE previousTokenType) {
+      return token.matches("[^!&\\|<=|>=|!=|=|<|>\\(\\)]+");
+    }
+  }
+
+  /**
+   * Open Bracket token handler.
+   */
+  private class OpenBracketTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(String token, ScanContext ctx) throws InvalidQueryException {
+      ctx.addToken(new Token(Token.TYPE.BRACKET_OPEN, token));
+    }
+
+    @Override
+    public Token.TYPE getType() {
+      return Token.TYPE.BRACKET_OPEN;
+    }
+
+    @Override
+    public boolean handles(String token, Token.TYPE previousTokenType) {
+      return token.matches("\\(");
+    }
+  }
+
+  /**
+   * Close Bracker token handler.
+   */
+  private class CloseBracketTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(String token, ScanContext ctx) throws InvalidQueryException {
+      ctx.addToken(new Token(Token.TYPE.BRACKET_CLOSE, token));
+    }
+
+    @Override
+    public Token.TYPE getType() {
+      return Token.TYPE.BRACKET_CLOSE;
+    }
+
+    @Override
+    public boolean handles(String token, Token.TYPE previousTokenType) {
+      return token.matches("\\)");
+    }
+  }
+
+  /**
+   * Relational Operator token handler.
+   */
+  private class RelationalOperatorTokenHandler extends TokenHandler {
+    @Override
+  public void _handleToken(String token, ScanContext ctx) throws InvalidQueryException {
+      ctx.addToken(new Token(Token.TYPE.RELATIONAL_OPERATOR, token));
+      ctx.addToken(new Token(Token.TYPE.PROPERTY_OPERAND, ctx.getPropertyOperand()));
+    }
+
+    @Override
+    public Token.TYPE getType() {
+      return Token.TYPE.RELATIONAL_OPERATOR;
+    }
+
+    @Override
+    public boolean handles(String token, Token.TYPE previousTokenType) {
+      return token.matches("<=|>=|!=|=|<|>");
+    }
+  }
+
+  /**
+   * Logical Operator token handler.
+   */
+  private class LogicalOperatorTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(String token, ScanContext ctx) throws InvalidQueryException {
+      ctx.addToken(new Token(Token.TYPE.LOGICAL_OPERATOR, token));
+      ctx.setIgnoreTokens(false);
+    }
+
+    @Override
+    public Token.TYPE getType() {
+      return Token.TYPE.LOGICAL_OPERATOR;
+    }
+
+    @Override
+    public boolean handles(String token, Token.TYPE previousTokenType) {
+      return token.matches("[!&\\|]");
+    }
+  }
+
+  /**
+   * Logical Unary Operator token handler.
+   */
+  private class LogicalUnaryOperatorTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(String token, ScanContext ctx) throws InvalidQueryException {
+      ctx.addToken(new Token(Token.TYPE.LOGICAL_UNARY_OPERATOR, token));
+    }
+
+    @Override
+    public Token.TYPE getType() {
+      return Token.TYPE.LOGICAL_UNARY_OPERATOR;
+    }
+
+    @Override
+    public boolean handles(String token, Token.TYPE previousTokenType) {
+      return "!".equals(token);
+    }
+  }
+}
\ No newline at end of file

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryParser.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryParser.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryParser.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/QueryParser.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,417 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate;
+
+import org.apache.ambari.server.api.predicate.expressions.Expression;
+import org.apache.ambari.server.api.predicate.expressions.LogicalExpressionFactory;
+import org.apache.ambari.server.api.predicate.expressions.RelationalExpression;
+import org.apache.ambari.server.api.predicate.operators.*;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+import java.util.*;
+
+/**
+ * Parser which produces a predicate instance from an array of tokens,
+ * which is generated by the lexer.
+ */
+public class QueryParser {
+
+  /**
+   * Map of token type to token handlers.
+   */
+  private static final Map<Token.TYPE, TokenHandler> TOKEN_HANDLERS =
+      new HashMap<Token.TYPE, TokenHandler>();
+
+  /**
+   * Constructor.
+   * Register token handlers.
+   *
+   */
+  public QueryParser() {
+    TOKEN_HANDLERS.put(Token.TYPE.BRACKET_OPEN, new BracketOpenTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.BRACKET_CLOSE, new BracketCloseTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.RELATIONAL_OPERATOR, new RelationalOperatorTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.LOGICAL_OPERATOR, new LogicalOperatorTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.LOGICAL_UNARY_OPERATOR, new LogicalUnaryOperatorTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.PROPERTY_OPERAND, new PropertyOperandTokenHandler());
+    TOKEN_HANDLERS.put(Token.TYPE.VALUE_OPERAND, new ValueOperandTokenHandler());
+  }
+
+  /**
+   * Generate a Predicate instance from an array of tokens.
+   * Each input token contains a type and a value.
+   *
+   * Based on the token type and location, the tokens are first translated into a list of
+   * expressions, both relational and logical.  These expressions are then merged into a tree
+   * of expressions with a single root following operator precedence and explicit grouping rules.
+   * Depending on the query, this merging of expressions into a tree of expressions may occur in
+   * several passes, one pass per level of precedence starting at the highest level of precedence.
+   *
+   *  The predicate is built by traversing the expression tree in-order with each node expressing itself
+   *  as a predicate.
+   *
+   * @param tokens  an array of tokens which represent the query,
+   *                each token contains type and value information
+   *
+   * @return a new predicate instance based on the supplied tokens
+   * @throws InvalidQueryException if unable to parse the tokens and produce a predicate
+   */
+  public Predicate parse(Token[] tokens) throws InvalidQueryException {
+    ParseContext ctx = parseExpressions(tokens);
+
+    List<Expression> listExpressions       = ctx.getExpressions();
+    List<Expression> listMergedExpressions = mergeExpressions(listExpressions, ctx.getMaxPrecedence());
+
+    return listMergedExpressions.isEmpty() ? null :
+        listMergedExpressions.get(0).toPredicate();
+  }
+
+  /**
+   * Create parse context from an array of tokens. The parse context contains a list of expressions
+   * and other information about the expressions an parsed tokens.
+   *
+   * @param tokens  an array of tokens which represent the query,
+   *                each token contains type and value information
+   *
+   * @return a parse context which contains a list of expressions
+   * @throws InvalidQueryException if unable to properly parse the tokens into a parse context
+   */
+  private ParseContext parseExpressions(Token[] tokens) throws InvalidQueryException {
+    ParseContext ctx = new ParseContext();
+
+    for (Token token : tokens) {
+      TOKEN_HANDLERS.get(token.getType()).handleToken(token, ctx);
+    }
+
+    if (ctx.getPrecedenceLevel() != 0) {
+      throw new InvalidQueryException("Invalid query string: mismatched parentheses.");
+    }
+
+    return ctx;
+  }
+
+  /**
+   * Merge list of expressions into a tree of logical/relational expressions.
+   * This is done recursively in several passes, one per level of precedence starting at the
+   * highest precedence level. Recursion exits when a single expression remains.
+   *
+   * @param listExpressions  list of expressions to merge
+   * @param precedenceLevel  the precedence level that is to be merged
+   *
+   * @return  tree of expressions with a single root expression
+   */
+  private List<Expression> mergeExpressions(List<Expression> listExpressions, int precedenceLevel) {
+    if (listExpressions.size() > 1) {
+      Stack<Expression> stack = new Stack<Expression>();
+
+      stack.push(listExpressions.remove(0));
+      while (! listExpressions.isEmpty()) {
+        Expression exp = stack.pop();
+        Expression left = stack.empty() ? null : stack.pop();
+        Expression right = listExpressions.remove(0);
+        stack.addAll(exp.merge(left, right, precedenceLevel));
+      }
+      return mergeExpressions(new ArrayList<Expression>(stack), precedenceLevel - 1);
+
+    } else {
+      return listExpressions;
+    }
+  }
+
+  /**
+   * A parse context which contains information related to parsing the provided tokens into expressions.
+   */
+  private class ParseContext {
+    /**
+     * The current context precedence level.  This is dictated by bracket tokens.
+     */
+    private int m_precedence = 0;
+
+    /**
+     * The type of the previous token used in validation.
+     */
+    private Token.TYPE m_previousTokenType = null;
+
+    /**
+     * The list of expressions which are generated from the tokens.
+     */
+    private List<Expression> m_listExpressions = new ArrayList<Expression>();
+
+    /**
+     * Highest precedence level in expression.
+     */
+    int m_maxPrecedence = 0;
+
+    /**
+     * Increment the context precedence level.
+     *
+     * @param val  how much the level is increased by
+     */
+    public void incPrecedenceLevel(int val) {
+      m_precedence += val;
+    }
+
+    /**
+     * Decrement the context precedence level.
+     *
+     * @param val  how much the level is decremented by
+     * @throws InvalidQueryException if the level is decremented below 0
+     */
+    public void decPrecedenceLevel(int val) throws InvalidQueryException {
+      m_precedence -= val;
+      if (m_precedence < 0) {
+        throw new InvalidQueryException("Invalid query string: mismatched parentheses.");
+      }
+    }
+
+    /**
+     * Get the current context precedence level.
+     *
+     * @return current context precedence level
+     */
+    public int getPrecedenceLevel() {
+      return m_precedence;
+    }
+
+    /**
+     * Get the list of generated expressions.
+     *
+     * @return the list of generated expressions
+     */
+    public List<Expression> getExpressions() {
+      return m_listExpressions;
+    }
+
+    /**
+     * Get the last expression.
+     *
+     * @return the last expression
+     */
+    public Expression getPrecedingExpression() {
+      return m_listExpressions == null ? null :
+          m_listExpressions.get(m_listExpressions.size() - 1);
+    }
+
+    /**
+     * Get the highest operator precedence in the list of generated expressions.
+     *
+     * @return the max operator precedence
+     */
+    public int getMaxPrecedence() {
+      return m_maxPrecedence;
+    }
+
+    /**
+     * Update the max precedence level.
+     * The max precedence level is only updated if the provided level > the current level.
+     *
+     * @param precedenceLevel the new value
+     */
+    public void updateMaxPrecedence(int precedenceLevel) {
+      if (precedenceLevel > m_maxPrecedence) {
+        m_maxPrecedence = precedenceLevel;
+      }
+    }
+
+    /**
+     * Add a generated expression.
+     *
+     * @param exp  the expression to add
+     */
+    public void addExpression(Expression exp) {
+      m_listExpressions.add(exp);
+    }
+
+    /**
+     * Set the token type of the current token
+     *
+     * @param type  type of the current token
+     */
+    private void setTokenType(Token.TYPE type) {
+      m_previousTokenType = type;
+    }
+
+    /**
+     * Get the last token type set.
+     *
+     * @return the last token type set
+     */
+    public Token.TYPE getPreviousTokenType() {
+      return m_previousTokenType;
+    }
+  }
+
+
+  /**
+   * Base token handler.
+   * Token handlers are responsible for handling the processing of a specific token type.
+   */
+  private abstract class TokenHandler {
+    /**
+     * Process a token. Handles common token processing functionality then delegates to the individual
+     * concrete handlers.
+     *
+     * @param token  the token to process
+     * @param ctx    the current parse context
+     * @throws InvalidQueryException if unable to process the token
+     */
+    public void handleToken(Token token, ParseContext ctx) throws InvalidQueryException {
+      if (! validate(ctx.getPreviousTokenType())) {
+        throw new InvalidQueryException("Unexpected token encountered in query string. Last Token Type=" +
+            ctx.getPreviousTokenType() + ", Current Token[type=" + token.getType() +
+            ", value='" + token.getValue() + "']");
+      }
+      ctx.setTokenType(token.getType());
+      _handleToken(token, ctx);
+    }
+
+    /**
+     * Process a token.
+     *
+     * @param token  the token to process
+     * @param ctx    the current parse context
+     * @throws InvalidQueryException if unable to process the token
+     */
+    public abstract void _handleToken(Token token, ParseContext ctx) throws InvalidQueryException;
+
+    /**
+     * Validate the token based on the previous token.
+     *
+     * @param previousTokenType  the type of the previous token
+     * @return true if validation is successful, false otherwise
+     */
+    public abstract boolean validate(Token.TYPE previousTokenType);
+  }
+
+  /**
+   * Open Bracket token handler.
+   */
+  private class BracketOpenTokenHandler extends TokenHandler {
+
+    @Override
+    public void _handleToken(Token token, ParseContext ctx) {
+      ctx.incPrecedenceLevel(Operator.MAX_OP_PRECEDENCE);
+    }
+
+    @Override
+    public boolean validate(Token.TYPE previousTokenType) {
+     return previousTokenType == null                        ||
+            previousTokenType == Token.TYPE.BRACKET_OPEN     ||
+            previousTokenType == Token.TYPE.LOGICAL_OPERATOR ||
+            previousTokenType == Token.TYPE.LOGICAL_UNARY_OPERATOR;
+    }
+  }
+
+  /**
+   * Close Bracket token handler
+   */
+  private class BracketCloseTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(Token token, ParseContext ctx) throws InvalidQueryException{
+      ctx.decPrecedenceLevel(Operator.MAX_OP_PRECEDENCE);
+    }
+
+    @Override
+    public boolean validate(Token.TYPE previousTokenType) {
+      return previousTokenType == Token.TYPE.VALUE_OPERAND ||
+             previousTokenType == Token.TYPE.BRACKET_CLOSE;
+    }
+  }
+
+  /**
+   * Relational Operator token handler
+   */
+  private class RelationalOperatorTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(Token token, ParseContext ctx) throws InvalidQueryException {
+      RelationalOperator relationalOp = RelationalOperatorFactory.createOperator(token.getValue());
+      //todo: use factory to create expression
+      ctx.addExpression(new RelationalExpression(relationalOp));
+    }
+
+    @Override
+    public boolean validate(Token.TYPE previousTokenType) {
+      return previousTokenType == null                     ||
+          previousTokenType == Token.TYPE.BRACKET_OPEN     ||
+          previousTokenType == Token.TYPE.LOGICAL_OPERATOR ||
+          previousTokenType == Token.TYPE.LOGICAL_UNARY_OPERATOR;
+    }
+  }
+
+  /**
+   * Logical Operator token handler
+   */
+  private class LogicalOperatorTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(Token token, ParseContext ctx) throws InvalidQueryException {
+      LogicalOperator logicalOp = LogicalOperatorFactory.createOperator(token.getValue(), ctx.getPrecedenceLevel());
+      ctx.updateMaxPrecedence(logicalOp.getPrecedence());
+      ctx.addExpression(LogicalExpressionFactory.createLogicalExpression(logicalOp));
+    }
+
+    @Override
+    public boolean validate(Token.TYPE previousTokenType) {
+      return previousTokenType == Token.TYPE.VALUE_OPERAND ||
+             previousTokenType == Token.TYPE.BRACKET_CLOSE;
+    }
+  }
+
+  /**
+   * Logical Unary Operator token handler
+   */
+  private class LogicalUnaryOperatorTokenHandler extends LogicalOperatorTokenHandler {
+    @Override
+    public boolean validate(Token.TYPE previousTokenType) {
+      return previousTokenType == null                 ||
+          previousTokenType == Token.TYPE.BRACKET_OPEN ||
+          previousTokenType == Token.TYPE.LOGICAL_OPERATOR;
+    }
+  }
+
+  /**
+   * Property Operand token handler
+   */
+  private class PropertyOperandTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(Token token, ParseContext ctx) throws InvalidQueryException {
+      ctx.getPrecedingExpression().setLeftOperand(token.getValue());
+    }
+
+    @Override
+    public boolean validate(Token.TYPE previousTokenType) {
+      return previousTokenType == Token.TYPE.RELATIONAL_OPERATOR;
+    }
+  }
+
+  /**
+   * Value Operand token handler
+   */
+  private class ValueOperandTokenHandler extends TokenHandler {
+    @Override
+    public void _handleToken(Token token, ParseContext ctx) throws InvalidQueryException {
+      ctx.getPrecedingExpression().setRightOperand(token.getValue());
+    }
+
+    @Override
+    public boolean validate(Token.TYPE previousTokenType) {
+      return previousTokenType == Token.TYPE.PROPERTY_OPERAND;
+    }
+  }
+}
+

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/Token.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/Token.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/Token.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/Token.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,108 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate;
+
+/**
+ * Token representation which is generated by the lexer.
+ * Contains type and value information.
+ */
+public class Token {
+
+  /**
+   * Token types.
+   */
+  public enum TYPE {
+    /** Property name operand.  This is the left operand in relational expressions. */
+    PROPERTY_OPERAND,
+    /** Value operand.  This is the right operand in relational expressions. */
+    VALUE_OPERAND,
+    /** Relational operator */
+    RELATIONAL_OPERATOR,
+    /** Logical operator */
+    LOGICAL_OPERATOR,
+    /** Logical unary operator such as !*/
+    LOGICAL_UNARY_OPERATOR,
+    /** Opening bracket */
+    BRACKET_OPEN,
+    /** Closing bracket */
+    BRACKET_CLOSE
+  }
+
+  /**
+   * Token type.
+   */
+  private TYPE m_type;
+
+  /**
+   * Token value.
+   */
+  private String m_value;
+
+
+  /**
+   * Constructor.
+   *
+   * @param type   type
+   * @param value  value
+   */
+  public Token(TYPE type, String value) {
+    m_type = type;
+    m_value = value;
+  }
+
+  /**
+   * Get the token type.
+   * @return token type
+   */
+  public TYPE getType() {
+    return m_type;
+  }
+
+  /**
+   * Get the token value.
+   * @return token value
+   */
+  public String getValue() {
+    return m_value;
+  }
+
+  @Override
+  public String toString() {
+    return "Token{ type=" + m_type + ", value='" + m_value + "' }";
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    Token token = (Token) o;
+
+    return m_type == token.m_type &&
+        (m_value == null ? token.m_value == null : m_value.equals(token.m_value));
+  }
+
+  @Override
+  public int hashCode() {
+    int result = m_type.hashCode();
+    result = 31 * result + (m_value != null ? m_value.hashCode() : 0);
+
+    return result;
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/AbstractExpression.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/AbstractExpression.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/AbstractExpression.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/AbstractExpression.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,106 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.expressions;
+
+import org.apache.ambari.server.api.predicate.operators.Operator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base class for expressions.
+ */
+public abstract class AbstractExpression<T> implements Expression<T> {
+
+  /**
+   * The operator.
+   */
+  private final Operator m_op;
+
+  /**
+   * The left operand.
+   * */
+  private T m_left = null;
+
+  /**
+   * The right operand.
+   */
+  private T m_right = null;
+
+  /**
+   * Constructor.
+   *
+   * @param op  the expressions operator
+   */
+  protected AbstractExpression(Operator op) {
+    m_op = op;
+  }
+
+  @Override
+  public void setLeftOperand(T left) {
+    m_left = left;
+  }
+
+  @Override
+  public void setRightOperand(T right) {
+    m_right = right;
+  }
+
+  @Override
+  public T getLeftOperand() {
+    return m_left;
+  }
+
+  @Override
+  public T getRightOperand() {
+    return m_right;
+  }
+
+  @Override
+  public Operator getOperator() {
+    return m_op;
+  }
+
+  @Override
+  public List<Expression> merge(Expression left, Expression right, int precedence) {
+    return defaultMerge(left, right);
+  }
+
+  /**
+   * Base merge implementation.
+   * No merge is done, simply returns the left expression, this and the right expression.
+   *
+   * @param left   the expression to the left of this expression
+   * @param right  the expression to the right of this expression
+   *
+   * @return a list containing the un-merged left expression, this and right expression
+   */
+  protected List<Expression> defaultMerge(Expression left, Expression right) {
+    List<Expression> listExpressions = new ArrayList<Expression>();
+    if (left != null) {
+      listExpressions.add(left);
+    }
+    listExpressions.add(this);
+    if (right != null) {
+      listExpressions.add(right);
+    }
+
+    return listExpressions;
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/Expression.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/Expression.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/Expression.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/Expression.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.expressions;
+
+import org.apache.ambari.server.api.predicate.operators.Operator;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+import java.util.List;
+
+/**
+ * Expression representation.
+ * There are two types of expressions, relational and logical.
+ * Each expression has an operator and either 2 operands for binary
+ * expressions or 1 operand for unary expressions.
+ */
+public interface Expression<T> {
+
+  /**
+   * Merge expression with surrounding expressions.
+   *
+   * @param left        the preceding expression
+   * @param right       the following expression
+   * @param precedence  the precedence level being merged.  Only expressions at this precedence level
+   *                    should be merged. Others should simply return the left expression, themselves and
+   *                    the right expression in that order.
+   *
+   * @return a list of expressions after merging.  Do not return any null elements.
+   */
+  public List<Expression> merge(Expression left, Expression right, int precedence);
+
+
+  /**
+   * Get the predicate representation of the expression.
+   * @return a predicate instance for the expression
+   */
+  public Predicate toPredicate();
+
+  /**
+   * Set the expressions left operand.
+   *
+   * @param left  the left operand
+   */
+  public void setLeftOperand(T left);
+
+  /**
+   * Set the expressions right operand.
+   *
+   * @param right  the right operand
+   */
+  public void setRightOperand(T right);
+
+  /**
+   * Get the left operand expression.
+   *
+   * @return the left operand
+   */
+  public T getLeftOperand();
+
+  /**
+   * Get the right operand expression.
+   *
+   * @return the right operand.
+   */
+  public T getRightOperand();
+
+  /**
+   * Get the expression operator.
+   *
+   * @return the logical operator for the expression
+   */
+  public Operator getOperator();
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpression.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpression.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpression.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpression.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.expressions;
+
+import org.apache.ambari.server.api.predicate.operators.LogicalOperator;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Logical expression implementation.
+ * Always a binary expression that consists of a logical operator and
+ * expressions for the left and right operands.
+ */
+public class LogicalExpression extends AbstractExpression<Expression> {
+
+  /**
+   * Constructor.
+   *
+   * @param op  the logical operator of the expression
+   */
+  public LogicalExpression(LogicalOperator op) {
+    super(op);
+  }
+
+
+  @Override
+  public Predicate toPredicate() {
+    return ((LogicalOperator) getOperator()).
+        toPredicate(getLeftOperand().toPredicate(), getRightOperand().toPredicate());
+  }
+
+  @Override
+  public List<Expression> merge(Expression left, Expression right, int precedence) {
+    if (getOperator().getPrecedence() == precedence && getLeftOperand() == null) {
+      setLeftOperand(left);
+      setRightOperand(right);
+      return Collections.<Expression>singletonList(this);
+    } else {
+      return defaultMerge(left, right);
+    }
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpressionFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpressionFactory.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpressionFactory.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/LogicalExpressionFactory.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.expressions;
+
+import org.apache.ambari.server.api.predicate.InvalidQueryException;
+import org.apache.ambari.server.api.predicate.operators.LogicalOperator;
+
+/**
+ * Factory of logical expression instances.
+ */
+public class LogicalExpressionFactory {
+  /**
+   * Create a logical expression instance.
+   *
+   * @param op  the logical operator
+   *
+   * @return a new logical expression instance
+   * @throws InvalidQueryException
+   */
+  public static LogicalExpression createLogicalExpression(LogicalOperator op) throws InvalidQueryException {
+    switch (op.getType()) {
+      case AND:
+      case OR:
+        return new LogicalExpression(op);
+      case NOT :
+        return new NotLogicalExpression(op);
+      default:
+        throw new RuntimeException("An invalid logical operator type was encountered: " + op);
+    }
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/NotLogicalExpression.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/NotLogicalExpression.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/NotLogicalExpression.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/NotLogicalExpression.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.expressions;
+
+import org.apache.ambari.server.api.predicate.operators.LogicalOperator;
+import org.apache.ambari.server.controller.predicate.BasePredicate;
+import org.apache.ambari.server.controller.predicate.NotPredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A 'NOT' logical expression representation.
+ * Negates a corresponding right operand.
+ */
+public class NotLogicalExpression extends LogicalExpression {
+  /**
+   * Constructor.
+   *
+   * @param op  the logical operator
+   */
+  public NotLogicalExpression(LogicalOperator op) {
+    super(op);
+  }
+
+  @Override
+  public List<Expression> merge(Expression left, Expression right, int precedence) {
+    if (getOperator().getPrecedence() == precedence && getRightOperand() == null) {
+      List<Expression> listExpressions = new ArrayList<Expression>();
+      if (left != null) {
+        listExpressions.add(left);
+      }
+      setRightOperand(right);
+      listExpressions.add(this);
+      return listExpressions;
+    } else {
+      // do nothing, already merged
+      return defaultMerge(left, right);
+    }
+  }
+
+  @Override
+  public Predicate toPredicate() {
+    //todo: remove need to down cast to BasePredicate
+    return new NotPredicate((BasePredicate) getRightOperand().toPredicate());
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/RelationalExpression.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/RelationalExpression.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/RelationalExpression.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/expressions/RelationalExpression.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.expressions;
+
+import org.apache.ambari.server.api.predicate.operators.RelationalOperator;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Relational Expression.
+ * Consists of a property name for the left operand, a relational operator
+ * and a value as the right operand.
+ */
+public class RelationalExpression extends AbstractExpression<String> {
+
+  /**
+   * Constructor.
+   *
+   * @param op  relational operator
+   */
+  public RelationalExpression(RelationalOperator op) {
+    super(op);
+  }
+
+  @Override
+  public Predicate toPredicate() {
+    return ((RelationalOperator) getOperator()).
+        toPredicate(getLeftOperand(), getRightOperand());
+  }
+
+  @Override
+  public String toString() {
+    return "RelationalExpression{ property='" + getLeftOperand() + "\', value='"
+        + getRightOperand() + "\', op=" + getOperator() + " }";
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AbstractOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AbstractOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AbstractOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AbstractOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+/**
+ * Base operator implementation.
+ */
+public abstract class AbstractOperator implements Operator {
+  /**
+   * The precedence value for the current context.
+   */
+  private final int m_ctxPrecedence;
+
+
+  /**
+   * Constructor.
+   *
+   * @param ctxPrecedence  the context precedence value
+   */
+  protected AbstractOperator(int ctxPrecedence) {
+    m_ctxPrecedence = ctxPrecedence;
+  }
+
+  /**
+   * Return the base precedence for this operator.
+   * This is the value that is specific to the operator
+   * type and doesn't take context into account.
+   *
+   * @return the base precedence for this operator type
+   */
+  public int getBasePrecedence() {
+    // this value is used for all relational operators
+    // logical operators override this value
+    return -1;
+  }
+
+  @Override
+  public int getPrecedence() {
+    return getBasePrecedence() + m_ctxPrecedence;
+  }
+
+  @Override
+  public String toString() {
+    return getName();
+  }
+
+  /**
+   * Get the name of the operator.
+   *
+   * @return the operator name
+   */
+  public abstract String getName();
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AndOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AndOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AndOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/AndOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.controller.predicate.AndPredicate;
+import org.apache.ambari.server.controller.predicate.BasePredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * And operator implementation.
+ */
+public class AndOperator extends AbstractOperator implements LogicalOperator {
+
+  /**
+   * Constructor.
+   *
+   * @param ctxPrecedence  precedence value for the current context
+   */
+  public AndOperator(int ctxPrecedence) {
+    super(ctxPrecedence);
+  }
+
+  @Override
+  public TYPE getType() {
+    return TYPE.AND;
+  }
+
+  @Override
+  public String getName() {
+    return "AndOperator";
+  }
+
+  @Override
+  public int getBasePrecedence() {
+    return 2;
+  }
+
+  @Override
+  public Predicate toPredicate(Predicate left, Predicate right) {
+    //todo: refactor to not need down casts
+    return new AndPredicate((BasePredicate) left, (BasePredicate) right);
+  }
+
+  @Override
+  public String toString() {
+    return getName() + "[precedence=" + getPrecedence() + "]";
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/EqualsOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/EqualsOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/EqualsOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/EqualsOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.controller.predicate.EqualsPredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Equals operator implementation.
+ */
+public class EqualsOperator extends AbstractOperator implements RelationalOperator {
+
+  /**
+   * Constructor.
+   */
+  public EqualsOperator() {
+    super(0);
+  }
+
+  @Override
+  public TYPE getType() {
+    return TYPE.EQUAL;
+  }
+
+  @Override
+  public Predicate toPredicate(String prop, String val) {
+    return new EqualsPredicate<String>(prop, val);
+  }
+
+  @Override
+  public String getName() {
+    return "EqualsOperator";
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterEqualsOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterEqualsOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterEqualsOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterEqualsOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.controller.predicate.GreaterEqualsPredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Greater Than Or Equals operator implementation.
+ */
+public class GreaterEqualsOperator extends AbstractOperator implements RelationalOperator {
+
+  /**
+   * Constructor.
+   */
+  public GreaterEqualsOperator() {
+    super(0);
+  }
+
+  @Override
+  public TYPE getType() {
+    return TYPE.GREATER_EQUAL;
+  }
+
+  @Override
+  public Predicate toPredicate(String prop, String val) {
+    return new GreaterEqualsPredicate<String>(prop, val);
+  }
+
+  @Override
+  public String getName() {
+    return "GreaterEqualsOperator";
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/GreaterOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.controller.predicate.GreaterPredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Greater Than operator implementation.
+ */
+public class GreaterOperator extends AbstractOperator implements RelationalOperator {
+
+  /**
+   * Constructor.
+   */
+  public GreaterOperator() {
+    super(0);
+  }
+
+  @Override
+  public TYPE getType() {
+    return TYPE.GREATER;
+  }
+
+  @Override
+  public Predicate toPredicate(String prop, String val) {
+    return new GreaterPredicate<String>(prop, val);
+  }
+
+  @Override
+  public String getName() {
+    return "GreaterOperator";
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessEqualsOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessEqualsOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessEqualsOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessEqualsOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.controller.predicate.LessEqualsPredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Less Than or Equals operator implementation.
+ */
+public class LessEqualsOperator extends AbstractOperator implements RelationalOperator {
+
+  /**
+   * Constructor.
+   */
+  public LessEqualsOperator() {
+    super(0);
+  }
+
+  @Override
+  public TYPE getType() {
+    return TYPE.LESS_EQUAL;
+  }
+
+  @Override
+  public Predicate toPredicate(String prop, String val) {
+    return new LessEqualsPredicate<String>(prop, val);
+  }
+
+  @Override
+  public String getName() {
+    return "LessEqualsOperator";
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LessOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.controller.predicate.LessPredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Less Than operator implementation.
+ */
+public class LessOperator extends AbstractOperator implements RelationalOperator {
+
+  /**
+   * Constructor.
+   */
+  public LessOperator() {
+    super(0);
+  }
+
+  @Override
+  public TYPE getType() {
+    return TYPE.LESS;
+  }
+
+  @Override
+  public Predicate toPredicate(String prop, String val) {
+    return new LessPredicate<String>(prop, val);
+  }
+
+  @Override
+  public String getName() {
+    return "LessOperator";
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Logical operator external representation.
+ */
+public interface LogicalOperator extends Operator {
+  /**
+   * Create a predicate for this logical operator.
+   *
+   * @param left   left operand
+   * @param right  right operand
+   * @return a predicate instance for this operator
+   */
+  public Predicate toPredicate(Predicate left, Predicate right);
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperatorFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperatorFactory.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperatorFactory.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/LogicalOperatorFactory.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.api.predicate.InvalidQueryException;
+
+/**
+ * Factory of Logical Operators.
+ */
+public class LogicalOperatorFactory {
+  /**
+   * Creates a logical operator based on the operator token.
+   *
+   * @param operator      string representation of operator
+   * @param ctxPrecedence precedence value of current context
+   *
+   * @return a logical operator instance
+   * @throws InvalidQueryException if the operator string is invalid
+   */
+  public static LogicalOperator createOperator(String operator, int ctxPrecedence)
+      throws InvalidQueryException {
+    if ("&".equals(operator)) {
+      return new AndOperator(ctxPrecedence);
+    } else if ("|".equals(operator)) {
+      return new OrOperator(ctxPrecedence);
+    } else if ("!".equals(operator)) {
+      return new NotOperator(ctxPrecedence);
+    } else {
+      throw new RuntimeException("Invalid Logical Operator Type: " + operator);
+    }
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/NotEqualsOperator.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/NotEqualsOperator.java?rev=1440067&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/NotEqualsOperator.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/predicate/operators/NotEqualsOperator.java Tue Jan 29 19:19:10 2013
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.predicate.operators;
+
+import org.apache.ambari.server.controller.predicate.EqualsPredicate;
+import org.apache.ambari.server.controller.predicate.NotPredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+
+/**
+ * Not Equals relational operator implementation.
+ */
+public class NotEqualsOperator extends AbstractOperator implements RelationalOperator {
+
+  /**
+   * Constructor.
+   */
+  public NotEqualsOperator() {
+    super(0);
+  }
+
+  @Override
+  public TYPE getType() {
+    return TYPE.NOT_EQUAL;
+  }
+
+  @Override
+  public Predicate toPredicate(String prop, String val) {
+    return new NotPredicate(new EqualsPredicate<String>(prop, val));
+  }
+
+  @Override
+  public String getName() {
+    return "NotEqualsOperator";
+  }
+}



Mime
View raw message