You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by js...@apache.org on 2013/03/11 20:26:50 UTC

svn commit: r1455293 [1/4] - 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/services/ ambari-server/src/main/java/org/apache/ambari/server/api/s...

Author: jspeidel
Date: Mon Mar 11 19:26:49 2013
New Revision: 1455293

URL: http://svn.apache.org/r1455293
Log:
AMBARI-1406. Provide API support for including query string in http message body

Added:
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/NamedPropertySet.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestBody.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/BodyParseException.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/NamedPropertySetTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/QueryPostRequestTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/RequestBodyTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/BodyParseExceptionTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java
Removed:
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/RequestHandlerFactory.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonPropertyParser.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonPropertyParserTest.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/CreateHandler.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/DeleteHandler.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/QueryCreateHandler.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/handlers/UpdateHandler.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/BaseService.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeleteRequest.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/GetRequest.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PostRequest.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PutRequest.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/QueryPostRequest.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/api/services/RequestFactory.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HttpProxyPropertyProvider.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/ActionServiceTest.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/BaseServiceTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/ClusterServiceTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/ComponentServiceTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/ConfigurationServiceTest.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/HostComponentServiceTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/HostServiceTest.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
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/ServiceServiceTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/StacksServiceTest.java

Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Mon Mar 11 19:26:49 2013
@@ -15,6 +15,8 @@ Trunk (unreleased changes):
  AMBARI-1602. Edit User - drop the requirement to specify the old 
  password. (swagle)
 
+ AMBARI-1406. Provide API support for including query string in http message body. (jspeidel)
+
  AMBARI-1592. Change how configurations are propagated (ncole)
 
  AMBARI-1593. Change host override JSON to include version tag (ncole)

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=1455293&r1=1455292&r2=1455293&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 Mon Mar 11 19:26:49 2013
@@ -18,12 +18,11 @@
 
 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.NamedPropertySet;
 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;
@@ -35,6 +34,7 @@ import org.apache.ambari.server.controll
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
@@ -54,29 +54,32 @@ public abstract class BaseManagementHand
    */
   PersistenceManager m_pm = new PersistenceManagerImpl(getClusterController());
 
+  /**
+   * Constructor.
+   */
   protected BaseManagementHandler() {
   }
 
+
+  @Override
   public Result handleRequest(Request request) {
-    ResourceInstance resource = request.getResource();
-    Predicate queryPredicate;
-    try {
-      queryPredicate = request.getQueryPredicate();
-    } catch (InvalidQueryException e) {
-      return new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST,
-          "Invalid Request: " + e.getMessage()));
-    }
+    ResourceInstance resource       = request.getResource();
+    Predicate        queryPredicate = request.getQueryPredicate();
+
     if (queryPredicate != null) {
       resource.getQuery().setUserPredicate(queryPredicate);
     }
 
-    return handleRequest(resource, request.getHttpBodyProperties());
-  }
-
-  protected Result handleRequest(ResourceInstance resource, Set<Map<String, Object>> setProperties) {
-    return persist(resource, setProperties);
+    return persist(resource, getHttpBodyProperties(request));
   }
 
+  /**
+   * Create a result from a request status.
+   *
+   * @param requestStatus  the request stats to build the result from.
+   *
+   * @return  a Result instance for the provided request status
+   */
   protected Result createResult(RequestStatus requestStatus) {
 
     boolean            isSynchronous = requestStatus.getStatus() == RequestStatus.Status.Complete;
@@ -98,18 +101,55 @@ public abstract class BaseManagementHand
         resourcesNode.addChild(resource, resource.getType() + ":" + count++);
       }
     }
-
     return result;
   }
 
-  //todo: controller should be injected
+  /**
+   * Obtain a set of property maps from the request.
+   * Convenience method that converts a Set<NamedPropertySet> from the request to a Set<Map<String, Object>>.
+   *
+   * @param request  the current request
+   *
+   * @return  a set of property maps for the request
+   */
+  protected Set<Map<String, Object>> getHttpBodyProperties(Request request) {
+    Set<NamedPropertySet> setNamedProps = request.getHttpBodyProperties();
+    Set<Map<String, Object>> setProps = new HashSet<Map<String, Object>>(setNamedProps.size());
+
+    for (NamedPropertySet namedProps : setNamedProps) {
+      setProps.add(namedProps.getProperties());
+    }
+
+    return setProps;
+  }
+
+  //todo: inject ClusterController, PersistenceManager
+
+  /**
+   * Get the cluster controller instance.
+   *
+   * @return cluster controller
+   */
   protected ClusterController getClusterController() {
     return ClusterControllerHelper.getClusterController();
   }
 
+  /**
+   * Get the persistence manager instance.
+   *
+   * @return persistence manager
+   */
   protected PersistenceManager getPersistenceManager() {
     return m_pm;
   }
 
-  protected abstract Result persist(ResourceInstance r, Set<Map<String, Object>> properties);
+  /**
+   * Persist the operation to the back end.
+   *
+   * @param request           the requests resource instance
+   * @param setProperties  request properties
+   *
+   * @return the result of the persist operation
+   */
+  protected abstract Result persist(ResourceInstance request, Set<Map<String, Object>> setProperties);
 }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java Mon Mar 11 19:26:49 2013
@@ -33,10 +33,10 @@ import java.util.Set;
 public class CreateHandler extends BaseManagementHandler {
 
   @Override
-  protected Result persist(ResourceInstance r, Set<Map<String, Object>> properties) {
+  protected Result persist(ResourceInstance request, Set<Map<String, Object>> setProperties) {
     Result result;
     try {
-      RequestStatus status = getPersistenceManager().create(r, properties);
+      RequestStatus status = getPersistenceManager().create(request, setProperties);
 
       result = createResult(status);
 

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/DeleteHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/DeleteHandler.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/DeleteHandler.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/DeleteHandler.java Mon Mar 11 19:26:49 2013
@@ -33,10 +33,10 @@ import java.util.Set;
 public class DeleteHandler extends BaseManagementHandler implements RequestHandler {
 
   @Override
-  protected Result persist(ResourceInstance r, Set<Map<String, Object>> properties) {
+  protected Result persist(ResourceInstance request, Set<Map<String, Object>> setProperties) {
     Result result;
       try {
-        RequestStatus status = getPersistenceManager().delete(r, properties);
+        RequestStatus status = getPersistenceManager().delete(request, setProperties);
         result = createResult(status);
 
         if (result.isSynchronous()) {
@@ -49,7 +49,7 @@ public class DeleteHandler extends BaseM
       } catch (NoSuchParentResourceException e) {
         result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.NOT_FOUND, e));
       } catch (NoSuchResourceException e) {
-        if (r.isCollectionResource()) {
+        if (request.isCollectionResource()) {
           //todo: The query didn't match any resource so no resources were updated.
           //todo: 200 may be ok but we need to return a collection
           //todo: of resources that were updated.

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/QueryCreateHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/QueryCreateHandler.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/QueryCreateHandler.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/QueryCreateHandler.java Mon Mar 11 19:26:49 2013
@@ -22,10 +22,8 @@ package org.apache.ambari.server.api.han
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.api.resources.ResourceInstanceFactory;
 import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl;
+import org.apache.ambari.server.api.services.*;
 import org.apache.ambari.server.api.services.Request;
-import org.apache.ambari.server.api.services.ResultStatus;
-import org.apache.ambari.server.api.services.Result;
-import org.apache.ambari.server.api.services.ResultImpl;
 import org.apache.ambari.server.api.util.TreeNode;
 import org.apache.ambari.server.controller.spi.*;
 
@@ -44,30 +42,55 @@ public class QueryCreateHandler extends 
     if (queryResult.getStatus().isErrorState() ||
         queryResult.getResultTree().getChildren().isEmpty()) {
 
-      //return the query result if result has error state or contains no resources
-      //todo: For case where no resources are returned, will return 200 ok.
-      //todo: What is the appropriate status code?
+      //if query result has error state or contains no resources return it
+      // currently returns 200 for case where query returns no rows
       return queryResult;
     }
 
-    ResourceInstance resource = request.getResource();
-    Resource.Type createType = getCreateType(request.getHttpBody(), resource);
-    Set<Map<String, Object>> setProperties = buildCreateSet(request, queryResult, createType);
+    Map<Resource.Type, Set<Map<String, Object>>> mapProperties;
+    try {
+      mapProperties = buildCreateSet(request, queryResult);
+    } catch (IllegalArgumentException e) {
+      return createInvalidRequestResult(e.getMessage());
+    }
+
+    if (mapProperties.size() != 1) {
+      return createInvalidRequestResult(mapProperties.size() == 0 ?
+          "A minimum of one sub-resource must be specified for creation." :
+          "Multiple sub-resource types may not be created in the same request.");
+    }
+
+    Map.Entry<Resource.Type, Set<Map<String, Object>>> entry = mapProperties.entrySet().iterator().next();
     ResourceInstance createResource = getResourceFactory().createResource(
-        createType, request.getResource().getIds());
+        entry.getKey(), request.getResource().getIds());
 
-    return super.handleRequest(createResource, setProperties);
+    return persist(createResource, entry.getValue());
   }
 
-  private Set<Map<String, Object>> buildCreateSet(Request request, Result queryResult, Resource.Type createType) {
-    Set<Map<String, Object>> setRequestProps = request.getHttpBodyProperties();
-    Set<Map<String, Object>> setCreateProps = new HashSet<Map<String, Object>>(setRequestProps.size());
+  /**
+   * Build the property set for all sub-resource to be created.
+   * This includes determining the sub-resource type and creating a property set for each matching parent.
+   *
+   * @param request      the current request
+   * @param queryResult  the result of the query for matching parents
+   *
+   * @return a map of sub-resource types to be created and their associated properties
+   *
+   * @throws IllegalArgumentException  if no sub-resource type was specified or it is not a valid
+   *                                   sub-resource of the parent.
+   */
+  private Map<Resource.Type, Set<Map<String, Object>>> buildCreateSet(Request request, Result queryResult)
+    throws IllegalArgumentException {
+
+    Set<NamedPropertySet> setRequestProps = request.getHttpBodyProperties();
+
+    HashMap<Resource.Type, Set<Map<String, Object>>> mapProps =
+        new HashMap<Resource.Type, Set<Map<String, Object>>>();
 
     ResourceInstance  resource            = request.getResource();
     Resource.Type     type                = resource.getResourceDefinition().getType();
     ClusterController controller          = getClusterController();
     String            resourceKeyProperty = controller.getSchema(type).getKeyPropertyId(type);
-    String            createKeyProperty   = controller.getSchema(createType).getKeyPropertyId(type);
 
     TreeNode<Resource> tree = queryResult.getResultTree();
     Collection<TreeNode<Resource>> treeChildren = tree.getChildren();
@@ -75,29 +98,61 @@ public class QueryCreateHandler extends 
       Resource r = node.getObject();
       Object keyVal = r.getPropertyValue(resourceKeyProperty);
 
-      for (Map<String, Object> mapProps : setRequestProps) {
-        Map<String, Object> mapResourceProps = new HashMap<String, Object>(mapProps);
-        mapResourceProps.put(createKeyProperty, keyVal);
+      for (NamedPropertySet namedProps : setRequestProps) {
+        Map<String, Object> mapResourceProps = new HashMap<String, Object>(namedProps.getProperties());
+        Resource.Type createType = getCreateType(resource, namedProps.getName());
+        mapResourceProps.put(controller.getSchema(createType).
+            getKeyPropertyId(resource.getResourceDefinition().getType()), keyVal);
+        Set<Map<String, Object>> setCreateProps = mapProps.get(createType);
+        if (setCreateProps == null) {
+          setCreateProps = new HashSet<Map<String, Object>>();
+          mapProps.put(createType, setCreateProps);
+        }
         setCreateProps.add(mapResourceProps);
       }
     }
-    return setCreateProps;
+    return mapProps;
   }
 
-  private Resource.Type getCreateType(String requestBody, ResourceInstance resource) {
-    int startIdx = requestBody.indexOf("\"") + 1;
-    int endIdx = requestBody.indexOf("\"", startIdx + 1);
+  /**
+   * Determine the sub-resurce type(s) to be created.
+   *
+   * @param resource         the requests resource instance
+   * @param subResourceName  the name of the sub-resource to be created
+   * @return  the resource type
+   *
+   * @throws IllegalArgumentException  if the specified sub-resource name is empty or it is not a valid
+   *                                   sub-resource of the parent.
+   */
+  private Resource.Type getCreateType(ResourceInstance resource, String subResourceName) throws IllegalArgumentException{
+    if (subResourceName == null || subResourceName.equals("")) {
+      throw new IllegalArgumentException("A sub-resource name must be supplied.");
+    }
+    ResourceInstance res = resource.getSubResources().get(subResourceName);
+
+    if (res == null) {
+      throw new IllegalArgumentException("The specified sub-resource name is not valid: '" + subResourceName + "'.");
+    }
 
-    ResourceInstance res =  resource.getSubResources().get(requestBody.substring(startIdx, endIdx));
-    return res == null ? null : res.getResourceDefinition().getType();
+    return res.getResourceDefinition().getType();
+  }
+
+  /**
+   * Convenience method to create a result for invalid requests.
+   *
+   * @param msg  message indicating why the request is invalid
+   *
+   * @return  a request with a 400 status and msg set
+   */
+  private Result createInvalidRequestResult(String msg) {
+    return new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, "Invalid Request: " + msg));
   }
 
   @Override
-  protected Result persist(ResourceInstance r, Set<Map<String, Object>> properties) {
+  protected Result persist(ResourceInstance request, Set<Map<String, Object>> setProperties) {
     Result result;
     try {
-      RequestStatus status = getPersistenceManager().create(r, properties);
-
+      RequestStatus status = getPersistenceManager().create(request, setProperties);
       result = createResult(status);
 
       if (result.isSynchronous()) {
@@ -105,7 +160,6 @@ public class QueryCreateHandler extends 
       } else {
         result.setResultStatus(new ResultStatus(ResultStatus.STATUS.ACCEPTED));
       }
-
     } catch (UnsupportedPropertyException e) {
       result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e));
     } catch (ResourceAlreadyExistsException e) {
@@ -119,10 +173,20 @@ public class QueryCreateHandler extends 
     return result;
   }
 
+  /**
+   * Get the resource factory instance.
+   * @return  a factory for creating resource instances
+   */
   protected ResourceInstanceFactory getResourceFactory() {
+    //todo: inject
     return new ResourceInstanceFactoryImpl();
   }
 
+  /**
+   * Read handler instance.  Used for obtaining matching parents which match the query.
+   *
+   * @return  read handler instance
+   */
   protected RequestHandler getReadHandler() {
     return m_readHandler;
   }

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=1455293&r1=1455292&r2=1455293&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 Mon Mar 11 19:26:49 2013
@@ -18,7 +18,6 @@
 
 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;
@@ -78,10 +77,7 @@ 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) {
+    }  catch (RuntimeException e) {
       if (LOG.isErrorEnabled()) {
         LOG.error("Caught a runtime exception executing a query", e);
       }
@@ -91,7 +87,13 @@ public class ReadHandler implements Requ
     return result;
   }
 
-  private void addFieldsToQuery(Request request, Query query) throws IllegalArgumentException {
+  /**
+   * Add partial response fields to the provided query.
+   *
+   * @param request  the current request
+   * @param query    the associated query   *
+   */
+  private void addFieldsToQuery(Request request, Query query) {
     //Partial response
     for (Map.Entry<String, TemporalInfo> entry : request.getFields().entrySet()) {
       // Iterate over map and add props/temporalInfo

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java Mon Mar 11 19:26:49 2013
@@ -32,10 +32,10 @@ import java.util.Set;
 public class UpdateHandler extends BaseManagementHandler {
 
   @Override
-  protected Result persist(ResourceInstance r, Set<Map<String, Object>> properties) {
+  protected Result persist(ResourceInstance request, Set<Map<String, Object>> setProperties) {
     Result result;
     try {
-      RequestStatus status = getPersistenceManager().update(r, properties);
+      RequestStatus status = getPersistenceManager().update(request, setProperties);
 
       result = createResult(status);
       if (result.isSynchronous()) {
@@ -49,7 +49,7 @@ public class UpdateHandler extends BaseM
     } catch (NoSuchParentResourceException e) {
       result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.NOT_FOUND, e));
     } catch (NoSuchResourceException e) {
-      if (r.isCollectionResource()) {
+      if (request.isCollectionResource()) {
         //todo: what is the correct status code here.  The query didn't match any resource
         //todo: so no resource were updated.  200 may be ok but we would need to return a collection
         //todo: of resources that were updated.

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java Mon Mar 11 19:26:49 2013
@@ -18,16 +18,15 @@
 
 package org.apache.ambari.server.api.services;
 
+import org.apache.ambari.server.api.handlers.RequestHandler;
 import org.apache.ambari.server.api.predicate.InvalidQueryException;
 import org.apache.ambari.server.api.predicate.PredicateCompiler;
 import org.apache.ambari.server.api.resources.*;
-import org.apache.ambari.server.api.services.parsers.JsonPropertyParser;
-import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
-import org.apache.ambari.server.api.services.serializers.JsonSerializer;
-import org.apache.ambari.server.api.services.serializers.ResultSerializer;
 import org.apache.ambari.server.controller.internal.TemporalInfoImpl;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.TemporalInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.UriInfo;
@@ -55,29 +54,58 @@ public abstract class BaseRequest implem
   /**
    * Http Body
    */
-  private String m_body;
+  private RequestBody m_body;
 
+  /**
+   * Query Predicate
+   */
+  private Predicate m_predicate;
 
   /**
    * Associated resource definition
    */
   private ResourceInstance m_resource;
 
+  /**
+   *  Logger instance.
+   */
+  private final static Logger LOG = LoggerFactory.getLogger(Request.class);
+
 
   /**
    * Constructor.
    *
-   * @param headers      http headers
-   * @param body         http body
-   * @param uriInfo      uri information
-   * @param resource     associated resource definition
-   */
-  public BaseRequest(HttpHeaders headers, String body, UriInfo uriInfo, ResourceInstance resource) {
-
-    m_headers  = headers;
-    m_body     = body;
-    m_uriInfo  = uriInfo;
-    m_resource = resource;
+   * @param headers           http headers
+   * @param body              http body
+   * @param uriInfo           uri information
+   * @param resource          associated resource definition
+   *
+   */
+  public BaseRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, ResourceInstance resource) {
+    m_headers     = headers;
+    m_uriInfo     = uriInfo;
+    m_resource    = resource;
+    m_body        = body;
+  }
+
+  @Override
+  public Result process() {
+    LOG.info("Handling API Request: '" + getURI() + "'");
+
+    Result result;
+    try {
+      parseQueryPredicate();
+      result = getRequestHandler().handleRequest(this);
+    } catch (InvalidQueryException e) {
+      result =  new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST,
+          "Unable to compile query predicate: " + e.getMessage()));
+    }
+
+    if (! result.getStatus().isErrorState()) {
+      getResultPostProcessor().process(result);
+    }
+
+    return result;
   }
 
   @Override
@@ -96,16 +124,12 @@ public abstract class BaseRequest implem
 
   @Override
   public int getAPIVersion() {
-    return 0;
+    return 1;
   }
 
   @Override
-  public Predicate getQueryPredicate() throws InvalidQueryException {
-    String uri     = getURI();
-    int    qsBegin = uri.indexOf("?");
-
-    return (qsBegin == -1) ? null :
-        getPredicateCompiler().compile(uri.substring(qsBegin + 1));
+  public Predicate getQueryPredicate() {
+    return m_predicate;
   }
 
   @Override
@@ -158,29 +182,60 @@ public abstract class BaseRequest implem
 
   @Override
   public String getHttpBody() {
-    return m_body;
+    return m_body.getBody();
   }
 
   @Override
-  public Set<Map<String, Object>> getHttpBodyProperties() {
-    return getHttpBodyParser().parse(getHttpBody());
+  public Set<NamedPropertySet> getHttpBodyProperties() {
+    return m_body.getPropertySets();
   }
 
-  @Override
-  public ResultSerializer getResultSerializer() {
-    return new JsonSerializer();
-  }
-
-  @Override
-  public ResultPostProcessor getResultPostProcessor() {
+  /**
+   * Obtain the result post processor for the request.
+   *
+   * @return the result post processor
+   */
+  protected ResultPostProcessor getResultPostProcessor() {
+    //todo: inject
     return new ResultPostProcessorImpl(this);
   }
 
-  protected RequestBodyParser getHttpBodyParser() {
-    return new JsonPropertyParser();
-  }
-
+  /**
+   * Obtain the predicate compiler which is used to compile the query string into
+   * a predicate.
+   *
+   * @return the predicate compiler
+   */
   protected PredicateCompiler getPredicateCompiler() {
     return new PredicateCompiler();
   }
+
+
+  /**
+   * Parse the query string and compile it into a predicate.
+   * The query string may have already been extracted from the http body.
+   * If the query string didn't exist in the body use the query string in the URL.
+   *
+   * @throws InvalidQueryException  if unable to parse a non-null query string into a predicate
+   */
+  private void parseQueryPredicate() throws InvalidQueryException {
+    String queryString = m_body.getQueryString();
+    if (queryString == null) {
+      String uri     = getURI();
+      int    qsBegin = uri.indexOf("?");
+
+      queryString = (qsBegin == -1) ? null : uri.substring(qsBegin + 1);
+    }
+
+    if (queryString != null) {
+      m_predicate = getPredicateCompiler().compile(queryString);
+    }
+  }
+
+  /**
+   * Obtain the underlying request handler for the request.
+   *
+   * @return  the request handler
+   */
+  protected abstract RequestHandler getRequestHandler();
 }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java Mon Mar 11 19:26:49 2013
@@ -18,15 +18,15 @@
 
 package org.apache.ambari.server.api.services;
 
-import org.apache.ambari.server.api.handlers.RequestHandler;
-import org.apache.ambari.server.api.handlers.RequestHandlerFactory;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.api.resources.ResourceInstanceFactory;
 import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl;
+import org.apache.ambari.server.api.services.parsers.BodyParseException;
+import org.apache.ambari.server.api.services.parsers.JsonRequestBodyParser;
+import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
+import org.apache.ambari.server.api.services.serializers.JsonSerializer;
 import org.apache.ambari.server.api.services.serializers.ResultSerializer;
 import org.apache.ambari.server.controller.spi.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
@@ -44,19 +44,14 @@ public abstract class BaseService {
   private ResourceInstanceFactory m_resourceFactory = new ResourceInstanceFactoryImpl();
 
   /**
-   * Factory for creating request handlers.
+   * Result serializer.
    */
-  private RequestHandlerFactory m_handlerFactory = new RequestHandlerFactory();
+  private ResultSerializer m_serializer = new JsonSerializer();
 
-  /**
-   *  Logger instance.
-   */
-  private final static Logger LOG = LoggerFactory.getLogger(BaseService.class);
 
   /**
    * All requests are funneled through this method so that common logic can be executed.
-   * This consists of creating a {@link Request} instance, invoking the correct {@link RequestHandler} and
-   * applying the proper {@link ResultSerializer} to the result.
+   * Creates a request instance and invokes it's process method.
    *
    * @param headers      http headers
    * @param body         http body
@@ -66,21 +61,22 @@ public abstract class BaseService {
    *
    * @return the response of the operation in serialized form
    */
-  protected Response handleRequest(HttpHeaders headers, String body, UriInfo uriInfo, Request.Type requestType,
-                                   ResourceInstance resource) {
-
-    Request request = getRequestFactory().createRequest(
-        headers, body, uriInfo, requestType, resource);
-
-    LOG.info("Handling API Request: '" + request.getURI() + "'");
+  protected Response handleRequest(HttpHeaders headers, String body, UriInfo uriInfo,
+                                   Request.Type requestType, ResourceInstance resource) {
 
-    Result result = getRequestHandler(request.getRequestType()).handleRequest(request);
-    if (! result.getStatus().isErrorState()) {
-      request.getResultPostProcessor().process(result);
+    Result result;
+    try {
+      RequestBody requestBody = getBodyParser().parse(body);
+      Request request = getRequestFactory().createRequest(
+          headers, requestBody, uriInfo, requestType, resource);
+
+      result = request.process();
+    } catch (BodyParseException e) {
+      result =  new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e.getMessage()));
     }
 
     return Response.status(result.getStatus().getStatusCode()).entity(
-        request.getResultSerializer().serialize(result)).build();
+        getResultSerializer().serialize(result)).build();
   }
 
   /**
@@ -93,17 +89,6 @@ public abstract class BaseService {
   }
 
   /**
-   * Obtain the appropriate RequestHandler for the request.
-   *
-   * @param requestType  the request type
-   *
-   * @return the request handler to invoke
-   */
-  RequestHandler getRequestHandler(Request.Type requestType) {
-    return m_handlerFactory.getRequestHandler(requestType);
-  }
-
-  /**
    * Create a resource instance.
    *
    * @param type    the resource type
@@ -114,4 +99,12 @@ public abstract class BaseService {
   ResourceInstance createResource(Resource.Type type, Map<Resource.Type, String> mapIds) {
     return m_resourceFactory.createResource(type, mapIds);
   }
+
+  protected ResultSerializer getResultSerializer() {
+    return m_serializer;
+  }
+
+  protected RequestBodyParser getBodyParser() {
+    return new JsonRequestBodyParser();
+  }
 }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeleteRequest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeleteRequest.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeleteRequest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeleteRequest.java Mon Mar 11 19:26:49 2013
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.api.services;
 
+import org.apache.ambari.server.api.handlers.DeleteHandler;
+import org.apache.ambari.server.api.handlers.RequestHandler;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -35,7 +37,7 @@ public class DeleteRequest extends BaseR
    * @param uriInfo     uri information
    * @param resource    associated resource definition
    */
-  public DeleteRequest(HttpHeaders headers, String body, UriInfo uriInfo, ResourceInstance resource) {
+  public DeleteRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, ResourceInstance resource) {
     super(headers, body, uriInfo, resource);
   }
 
@@ -44,4 +46,8 @@ public class DeleteRequest extends BaseR
     return Type.DELETE;
   }
 
+  @Override
+  protected RequestHandler getRequestHandler() {
+    return new DeleteHandler();
+  }
 }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/GetRequest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/GetRequest.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/GetRequest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/GetRequest.java Mon Mar 11 19:26:49 2013
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.api.services;
 
+import org.apache.ambari.server.api.handlers.ReadHandler;
+import org.apache.ambari.server.api.handlers.RequestHandler;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -35,7 +37,7 @@ public class GetRequest extends BaseRequ
    * @param uriInfo     uri information
    * @param resource    associated resource definition
    */
-  public GetRequest(HttpHeaders headers, String body, UriInfo uriInfo, ResourceInstance resource) {
+  public GetRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, ResourceInstance resource) {
     super(headers, body, uriInfo, resource);
   }
 
@@ -43,4 +45,9 @@ public class GetRequest extends BaseRequ
   public Type getRequestType() {
     return Type.GET;
   }
+
+  @Override
+  protected RequestHandler getRequestHandler() {
+    return new ReadHandler();
+  }
 }

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/NamedPropertySet.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/NamedPropertySet.java?rev=1455293&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/NamedPropertySet.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/NamedPropertySet.java Mon Mar 11 19:26:49 2013
@@ -0,0 +1,85 @@
+/**
+ * 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.services;
+
+import java.util.Map;
+
+/**
+ * A named set of related properties.
+ */
+public class NamedPropertySet {
+  /**
+   * The name of this set of properties.
+   */
+  private String m_name;
+
+  /**
+   * Property name/value pairs.
+   */
+  private Map<String, Object> m_mapProperties;
+
+
+  /**
+   * Constructor.
+   *
+   * @param name           name of this property set
+   * @param mapProperties  associated properties
+   */
+  public NamedPropertySet(String name, Map<String, Object> mapProperties) {
+    m_name = name;
+    m_mapProperties = mapProperties;
+  }
+
+  /**
+   * Obtain the name of this property set.
+   *
+   * @return the name of this property set
+   */
+  public String getName() {
+    return m_name;
+  }
+
+  /**
+   * Obtain the associated properties.
+   *
+   * @return  the associated properties
+   */
+  public Map<String, Object> getProperties() {
+    return m_mapProperties;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    NamedPropertySet that = (NamedPropertySet) o;
+
+    return (m_mapProperties == null ? that.m_mapProperties == null : m_mapProperties.equals(that.m_mapProperties)) &&
+        (m_name == null ? that.m_name == null : m_name.equals(that.m_name));
+
+  }
+
+  @Override
+  public int hashCode() {
+    int result = m_name != null ? m_name.hashCode() : 0;
+    result = 31 * result + (m_mapProperties != null ? m_mapProperties.hashCode() : 0);
+    return result;
+  }
+}

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PostRequest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PostRequest.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PostRequest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PostRequest.java Mon Mar 11 19:26:49 2013
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.api.services;
 
+import org.apache.ambari.server.api.handlers.CreateHandler;
+import org.apache.ambari.server.api.handlers.RequestHandler;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -35,7 +37,7 @@ public class PostRequest extends BaseReq
    * @param uriInfo     uri information
    * @param resource    associated resource definition
    */
-  public PostRequest(HttpHeaders headers, String body, UriInfo uriInfo, ResourceInstance resource) {
+  public PostRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, ResourceInstance resource) {
     super(headers, body, uriInfo, resource);
   }
 
@@ -44,4 +46,8 @@ public class PostRequest extends BaseReq
     return Type.POST;
   }
 
+  @Override
+  protected RequestHandler getRequestHandler() {
+    return new CreateHandler();
+  }
 }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PutRequest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PutRequest.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PutRequest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/PutRequest.java Mon Mar 11 19:26:49 2013
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.api.services;
 
+import org.apache.ambari.server.api.handlers.RequestHandler;
+import org.apache.ambari.server.api.handlers.UpdateHandler;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -35,7 +37,7 @@ public class PutRequest extends BaseRequ
    * @param uriInfo     uri information
    * @param resource    associated resource definition
    */
-  public PutRequest(HttpHeaders headers, String body, UriInfo uriInfo, ResourceInstance resource) {
+  public PutRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, ResourceInstance resource) {
     super(headers, body, uriInfo, resource);
   }
 
@@ -44,4 +46,8 @@ public class PutRequest extends BaseRequ
     return Type.PUT;
   }
 
+  @Override
+  protected RequestHandler getRequestHandler() {
+    return new UpdateHandler();
+  }
 }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/QueryPostRequest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/QueryPostRequest.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/QueryPostRequest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/QueryPostRequest.java Mon Mar 11 19:26:49 2013
@@ -19,12 +19,12 @@
 
 package org.apache.ambari.server.api.services;
 
+import org.apache.ambari.server.api.handlers.QueryCreateHandler;
+import org.apache.ambari.server.api.handlers.RequestHandler;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.UriInfo;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * Request for creating sub-resources of instances based on a query.
@@ -38,22 +38,17 @@ public class QueryPostRequest extends Po
    * @param uriInfo      uri information
    * @param resource     associated resource instance
    */
-  public QueryPostRequest(HttpHeaders headers, String body, UriInfo uriInfo, ResourceInstance resource) {
+  public QueryPostRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, ResourceInstance resource) {
     super(headers, body, uriInfo, resource);
   }
 
   @Override
-  public Set<Map<String, Object>> getHttpBodyProperties() {
-    String httpBody = getHttpBody();
-    //strip array name
-    int startIdx = httpBody.indexOf("[");
-    int endIdx = httpBody.lastIndexOf("]");
-
-    return getHttpBodyParser().parse(httpBody.substring(startIdx, endIdx + 1));
+  public Type getRequestType() {
+    return Type.QUERY_POST;
   }
 
   @Override
-  public Type getRequestType() {
-    return Type.QUERY_POST;
+  protected RequestHandler getRequestHandler() {
+    return new QueryCreateHandler();
   }
 }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java Mon Mar 11 19:26:49 2013
@@ -18,10 +18,8 @@
 
 package org.apache.ambari.server.api.services;
 
-import org.apache.ambari.server.api.predicate.InvalidQueryException;
 import org.apache.ambari.server.api.resources.ResourceDefinition;
 import org.apache.ambari.server.api.resources.ResourceInstance;
-import org.apache.ambari.server.api.services.serializers.ResultSerializer;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.TemporalInfo;
 
@@ -46,6 +44,13 @@ public interface Request {
   }
 
   /**
+   * Process the request.
+   *
+   * @return the result
+   */
+  public Result process();
+
+  /**
    * Obtain the resource definition which corresponds to the resource being operated on by the request.
    * The resource definition provides information about the resource type;
    *
@@ -76,13 +81,12 @@ public interface Request {
 
   /**
    * Obtain the query predicate that was built from the user provided predicate fields in the query string.
-   * If multiple predicates are supplied, then they will be combined using the appropriate grouping predicate
-   * such as 'AND'.
+   * If multiple predicates are supplied, then they will be combined using the appropriate logical grouping
+   * predicate such as 'AND'.
    *
    * @return the user defined predicate
-   * @throws InvalidQueryException if the query syntax is invalid
    */
-  public Predicate getQueryPredicate() throws InvalidQueryException;
+  public Predicate getQueryPredicate();
 
   /**
    * Obtain the partial response fields and associated temporal information which were provided
@@ -93,21 +97,6 @@ public interface Request {
   public Map<String, TemporalInfo> getFields();
 
   /**
-   * Obtain the result serializer for the request. The default serializer is of type JSON.
-   *
-   * @return the result serializer for the request
-   */
-  public ResultSerializer getResultSerializer();
-
-  /**
-   * Obtain the processor which processes the result returned from the request handler.
-   * The post processor adds additional information such as href fields to the result.
-   *
-   * @return the result processor associated with the request
-   */
-  public ResultPostProcessor getResultPostProcessor();
-
-  /**
    * Obtain the http headers associated with the request.
    *
    * @return the http headers
@@ -116,6 +105,9 @@ public interface Request {
 
   /**
    * Obtain the http body associated with the request.
+   * If query or partial response fields exist in the original body,
+   * they are not included in the returned body.  Query and partial
+   * response data are available via the corresponding getters.
    *
    * @return the http body
    */
@@ -126,5 +118,5 @@ public interface Request {
    *
    * @return a set of maps containing the properties contained in the http body
    */
-  public Set<Map<String, Object>> getHttpBodyProperties();
+  public Set<NamedPropertySet> getHttpBodyProperties();
 }

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestBody.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestBody.java?rev=1455293&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestBody.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestBody.java Mon Mar 11 19:26:49 2013
@@ -0,0 +1,124 @@
+/**
+ * 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.services;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Represents the http body of the request.
+ */
+public class RequestBody {
+
+  /**
+   * The associated query.
+   */
+  private String m_query;
+
+  /**
+   * The associated partial response fields.
+   */
+  private String m_fields;
+
+  /**
+   * The body properties.
+   */
+  private Set<NamedPropertySet> m_propertySets = new HashSet<NamedPropertySet>();
+
+  /**
+   * The request body.  Query and partial response data is stripped before setting.
+   */
+  private String m_body;
+
+
+  /**
+   * Set the query string.
+   *
+   * @param query the query string from the body
+   */
+  public void setQueryString(String query) {
+    m_query = query;
+  }
+
+  /**
+   * Obtain that query that was specified in the body.
+   *
+   * @return the query from the body or null if no query was present in the body
+   */
+  public String getQueryString() {
+    return m_query;
+  }
+
+  /**
+   * Set the partial response fields from the body.
+   *
+   * @param fields  the partial response fields
+   */
+  public void setPartialResponseFields(String fields) {
+    m_fields = fields;
+  }
+
+  /**
+   * Obtain the partial response fields that were specified in the body.
+   *
+   * @return  the partial response fields or null if not specified in the body
+   */
+  public String getPartialResponseFields() {
+    return m_fields;
+  }
+
+  /**
+   * Add a property set.
+   * A property set is a set of related properties and values.
+   * For example, if the body contained properties for three different resources to
+   * be created, each would be represented as distinct property set.
+   *
+   * @param propertySet  the property set to add
+   */
+  public void addPropertySet(NamedPropertySet propertySet) {
+    m_propertySets.add(propertySet);
+  }
+
+  /**
+   * Obtain all property sets or an empty set if no properties were specified in the body.
+   *
+   * @return  all property sets or an empty set
+   */
+  public Set<NamedPropertySet> getPropertySets() {
+    return m_propertySets;
+  }
+
+  /**
+   * Set the body from the request.
+   *
+   * @param body the request body
+   */
+  public void setBody(String body) {
+    m_body = body;
+  }
+
+  /**
+   * Obtain the request body.
+   *
+   * @return the request body
+   */
+  public String getBody() {
+    return m_body;
+  }
+}

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java Mon Mar 11 19:26:49 2013
@@ -37,7 +37,7 @@ public class RequestFactory {
    *
    * @return a new Request instance
    */
-  public Request createRequest(HttpHeaders headers, String body, UriInfo uriInfo, Request.Type requestType,
+  public Request createRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, Request.Type requestType,
                                ResourceInstance resource) {
     switch (requestType) {
       case GET:
@@ -47,7 +47,7 @@ public class RequestFactory {
       case DELETE:
         return new DeleteRequest(headers, body, uriInfo, resource);
       case POST:
-        return (uriInfo.getQueryParameters().isEmpty() || body == null) ?
+        return ((uriInfo.getQueryParameters().isEmpty() && body.getQueryString() == null) || body == null) ?
             new PostRequest(headers, body, uriInfo, resource) :
             new QueryPostRequest(headers, body, uriInfo, resource);
       default:

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/BodyParseException.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/BodyParseException.java?rev=1455293&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/BodyParseException.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/BodyParseException.java Mon Mar 11 19:26:49 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.services.parsers;
+
+/**
+ * Exception indicating that a failure occurred while parsing the request body.
+ */
+public class BodyParseException extends Exception {
+  /**
+   * Create exception by specifying the entire message.
+   *
+   * @param msg  the message to set
+   */
+  public BodyParseException(String msg) {
+    super(msg);
+  }
+
+  /**
+   * Create exception with messaged based on an exception.
+   *
+   * @param e  the exception to base the msg on
+   */
+  public BodyParseException(Exception e) {
+    super("Invalid Request: Malformed Request Body.  An exception occurred parsing the request body: "
+        + e.getMessage());
+  }
+}

Added: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java?rev=1455293&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java (added)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java Mon Mar 11 19:26:49 2013
@@ -0,0 +1,116 @@
+/**
+ * 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.services.parsers;
+
+import org.apache.ambari.server.api.services.NamedPropertySet;
+import org.apache.ambari.server.api.services.RequestBody;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * JSON parser which parses a JSON string into a map of properties and values.
+ */
+public class JsonRequestBodyParser implements RequestBodyParser {
+  /**
+   *  Logger instance.
+   */
+  private final static Logger LOG = LoggerFactory.getLogger(JsonRequestBodyParser.class);
+
+  private String m_body;
+
+  @Override
+  public RequestBody parse(String s) throws BodyParseException {
+    m_body = s;
+    RequestBody body = new RequestBody();
+
+    if (s != null && s.length() != 0) {
+      s = ensureArrayFormat(s);
+      ObjectMapper mapper = new ObjectMapper();
+      try {
+        JsonNode root = mapper.readTree(s);
+
+        Iterator<JsonNode> iter = root.getElements();
+        while (iter.hasNext()) {
+          Map<String, Object> mapProperties = new HashMap<String, Object>();
+          NamedPropertySet propertySet = new NamedPropertySet("", mapProperties);
+          JsonNode node = iter.next();
+          processNode(node, "", propertySet, body);
+
+          String query = (String) mapProperties.remove(QUERY_FIELD_PATH);
+          if (query != null) {
+            body.setQueryString(query);
+          }
+          if (propertySet.getProperties().size() != 0) {
+            body.addPropertySet(propertySet);
+          }
+        }
+
+        if (body.getPropertySets().size() != 0) {
+          body.setBody(m_body);
+        }
+      } catch (IOException e) {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Caught exception parsing msg body.");
+          LOG.debug("Message Body: " + s, e);
+        }
+        throw new BodyParseException(e);
+      }
+    }
+    return body;
+  }
+
+  private void processNode(JsonNode node, String path, NamedPropertySet propertySet, RequestBody body) {
+    Iterator<String> iter = node.getFieldNames();
+    String name;
+    while (iter.hasNext()) {
+      name = iter.next();
+      JsonNode child = node.get(name);
+      if (child.isArray()) {
+        //array
+        Iterator<JsonNode> arrayIter = child.getElements();
+        while (arrayIter.hasNext()) {
+          NamedPropertySet arrayPropertySet = new NamedPropertySet(name, new HashMap<String, Object>());
+          processNode(arrayIter.next(), "", arrayPropertySet, body);
+          body.addPropertySet(arrayPropertySet);
+        }
+      } else if (child.isContainerNode()) {
+        // object
+        if (name.equals(BODY_TITLE)) {
+          name = "";
+          m_body = child.toString();
+        }
+        processNode(child, path.isEmpty() ? name : path + '/' + name, propertySet, body);
+      } else {
+        // field
+       propertySet.getProperties().put(PropertyHelper.getPropertyId(
+           path.equals(BODY_TITLE) ? "" : path, name), child.asText());
+      }
+    }
+  }
+
+  private String ensureArrayFormat(String s) {
+    return s.startsWith("[") ? s : '[' + s + ']';
+  }
+}

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java Mon Mar 11 19:26:49 2013
@@ -18,20 +18,29 @@
 
 package org.apache.ambari.server.api.services.parsers;
 
-import java.util.Map;
-import java.util.Set;
+import org.apache.ambari.server.api.services.RequestBody;
 
 /**
  * Parse the provided String into a map of properties and associated values.
  */
 public interface RequestBodyParser {
   /**
-   * Parse the provided string into a map of properties and values.
-   * The key contains both the category hierarchy and the property name.
+   * Path to the query property.
+   */
+  public static final String QUERY_FIELD_PATH = "RequestInfo/query";
+
+  /**
+   * Path to the body object.
+   */
+  public static final String BODY_TITLE = "Body";
+
+  /**
+   * Parse the provided string into a request body which contains all properties in the string.
+   *
    *
    * @param s  the string body to be parsed
    *
-   * @return a set of maps of properties or an empty set if no properties exist
+   * @return RequestBody instance containing all properties in the string
    */
-  public Set<Map<String, Object>> parse(String s);
+  public RequestBody parse(String s) throws BodyParseException;
 }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HttpProxyPropertyProvider.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HttpProxyPropertyProvider.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HttpProxyPropertyProvider.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HttpProxyPropertyProvider.java Mon Mar 11 19:26:49 2013
@@ -24,7 +24,10 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.ambari.server.api.services.parsers.JsonPropertyParser;
+import org.apache.ambari.server.api.services.NamedPropertySet;
+import org.apache.ambari.server.api.services.RequestBody;
+import org.apache.ambari.server.api.services.parsers.BodyParseException;
+import org.apache.ambari.server.api.services.parsers.JsonRequestBodyParser;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.PropertyProvider;
 import org.apache.ambari.server.controller.spi.Request;
@@ -110,12 +113,21 @@ public class HttpProxyPropertyProvider e
     InputStream in = null;
     try {
       in = streamProvider.readFrom(url);
-      r.setProperty(propertyIdToSet, new JsonPropertyParser().parse(IOUtils.toString(in, "UTF-8")));
+      //todo: should not use JsonRequestBodyParser as this is intended only for parsing http bodies.
+      RequestBody body = (new JsonRequestBodyParser().parse(IOUtils.toString(in, "UTF-8")));
+      Set<NamedPropertySet> setNamedProps = body.getPropertySets();
+      Set<Map<String,Object>> setProps = new HashSet<Map<String, Object>>(setNamedProps.size());
+      for (NamedPropertySet ps : setNamedProps) {
+        setProps.add(ps.getProperties());
+      }
+      r.setProperty(propertyIdToSet, setProps);
     }
     catch (IOException ioe) {
+      //todo: should not eat exception
       LOG.error("Error reading HTTP response from " + url);
-    }
-    finally {
+    } catch (BodyParseException e) {
+      LOG.error("Error Parsing Json.", e);
+    } finally {
       if (null != in) {
         try {
           in.close();

Modified: incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/TestSuite.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/TestSuite.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/TestSuite.java (original)
+++ incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/TestSuite.java Mon Mar 11 19:26:49 2013
@@ -29,7 +29,8 @@ import org.apache.ambari.server.api.pred
 import org.apache.ambari.server.api.query.QueryImplTest;
 import org.apache.ambari.server.api.resources.ResourceInstanceImplTest;
 import org.apache.ambari.server.api.services.*;
-import org.apache.ambari.server.api.services.parsers.JsonPropertyParserTest;
+import org.apache.ambari.server.api.services.parsers.BodyParseExceptionTest;
+import org.apache.ambari.server.api.services.parsers.JsonRequestBodyParserTest;
 import org.apache.ambari.server.api.services.serializers.JsonSerializerTest;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
@@ -37,12 +38,13 @@ import org.junit.runners.Suite;
 @RunWith(Suite.class)
 @Suite.SuiteClasses({ClusterServiceTest.class, HostServiceTest.class, ServiceServiceTest.class,
     ComponentServiceTest.class, HostComponentServiceTest.class, ReadHandlerTest.class, QueryImplTest.class,
-    JsonPropertyParserTest.class, CreateHandlerTest.class, UpdateHandlerTest.class, DeleteHandlerTest.class,
+    JsonRequestBodyParserTest.class, CreateHandlerTest.class, UpdateHandlerTest.class, DeleteHandlerTest.class,
     PersistenceManagerImplTest.class, GetRequestTest.class, PutRequestTest.class, PostRequestTest.class,
-    DeleteRequestTest.class, JsonSerializerTest.class, QueryCreateHandlerTest.class, ResourceInstanceImplTest.class,
-    QueryLexerTest.class, QueryParserTest.class, IsEmptyOperatorTest.class, InOperatorTest.class,
-    AndOperatorTest.class, OrOperatorTest.class, EqualsOperatorTest.class, GreaterEqualsOperatorTest.class,
-    GreaterOperatorTest.class, LessEqualsOperatorTest.class, LessEqualsOperatorTest.class, NotEqualsOperatorTest.class,
-    NotOperatorTest.class})
+    DeleteRequestTest.class, QueryPostRequestTest.class, JsonSerializerTest.class, QueryCreateHandlerTest.class,
+    ResourceInstanceImplTest.class, QueryLexerTest.class, QueryParserTest.class, IsEmptyOperatorTest.class,
+    InOperatorTest.class,AndOperatorTest.class, OrOperatorTest.class, EqualsOperatorTest.class,
+    GreaterEqualsOperatorTest.class, GreaterOperatorTest.class, LessEqualsOperatorTest.class,
+    LessEqualsOperatorTest.class, NotEqualsOperatorTest.class, NotOperatorTest.class, RequestBodyTest.class,
+    NamedPropertySetTest.class, BodyParseExceptionTest.class})
 public class TestSuite {
 }

Modified: incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java Mon Mar 11 19:26:49 2013
@@ -18,8 +18,8 @@
 
 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.NamedPropertySet;
 import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.api.services.persistence.PersistenceManager;
 import org.apache.ambari.server.api.services.Request;
@@ -27,7 +27,6 @@ import org.apache.ambari.server.api.serv
 import org.apache.ambari.server.api.util.TreeNode;
 import org.apache.ambari.server.controller.spi.RequestStatus;
 import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.junit.Test;
 
 import java.util.*;
@@ -41,6 +40,57 @@ import static org.junit.Assert.*;
 public class CreateHandlerTest {
 
   @Test
+  public void testHandleRequest__Synchronous_NoPropsInBody() throws Exception {
+    Request request = createNiceMock(Request.class);
+    ResourceInstance resource = createNiceMock(ResourceInstance.class);
+    PersistenceManager pm = createStrictMock(PersistenceManager.class);
+    RequestStatus status = createNiceMock(RequestStatus.class);
+    Resource resource1 = createNiceMock(Resource.class);
+    Resource resource2 = createNiceMock(Resource.class);
+
+
+    Set<Resource> setResources = new HashSet<Resource>();
+    setResources.add(resource1);
+    setResources.add(resource2);
+
+    // expectations
+    expect(request.getResource()).andReturn(resource).atLeastOnce();
+    expect(request.getQueryPredicate()).andReturn(null).atLeastOnce();
+    expect(request.getHttpBodyProperties()).andReturn(new HashSet<NamedPropertySet>()).atLeastOnce();
+
+    expect(pm.create(eq(resource), eq(new HashSet<Map<String, Object>>()))).andReturn(status);
+    expect(status.getStatus()).andReturn(RequestStatus.Status.Complete);
+    expect(status.getAssociatedResources()).andReturn(setResources);
+    expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
+    expect(resource2.getType()).andReturn(Resource.Type.Cluster).anyTimes();
+
+    replay(request, resource, pm, status, resource1, resource2);
+
+    Result result = new TestCreateHandler(pm).handleRequest(request);
+
+    assertNotNull(result);
+    TreeNode<Resource> tree = result.getResultTree();
+    assertEquals(1, tree.getChildren().size());
+    TreeNode<Resource> resourcesNode = tree.getChild("resources");
+    assertEquals(2, resourcesNode.getChildren().size());
+    boolean foundResource1 = false;
+    boolean foundResource2 = false;
+    for(TreeNode<Resource> child : resourcesNode.getChildren()) {
+      Resource r = child.getObject();
+      if (r == resource1 && ! foundResource1) {
+        foundResource1 = true;
+      } else if (r == resource2 && ! foundResource2) {
+        foundResource2 = true;
+      } else {
+        fail();
+      }
+    }
+
+    assertEquals(ResultStatus.STATUS.CREATED, result.getStatus().getStatus());
+    verify(request, resource, pm, status, resource1, resource2);
+  }
+
+  @Test
   public void testHandleRequest__Synchronous() throws Exception {
     Request request = createNiceMock(Request.class);
     ResourceInstance resource = createNiceMock(ResourceInstance.class);
@@ -49,7 +99,14 @@ public class CreateHandlerTest {
     Resource resource1 = createNiceMock(Resource.class);
     Resource resource2 = createNiceMock(Resource.class);
 
-    Set<Map<String, Object>> setResourceProperties = new HashSet<Map<String, Object>>();
+    Set<NamedPropertySet> setResourceProperties = new HashSet<NamedPropertySet>();
+    Map<String, Object> mapProps = new HashMap<String, Object>();
+    mapProps.put("foo", "bar");
+    NamedPropertySet namedPropSet = new NamedPropertySet("name", mapProps);
+    setResourceProperties.add(namedPropSet);
+
+    Set<Map<String, Object>> setProps = new HashSet<Map<String, Object>>();
+    setProps.add(mapProps);
 
     Set<Resource> setResources = new HashSet<Resource>();
     setResources.add(resource1);
@@ -60,7 +117,7 @@ public class CreateHandlerTest {
     expect(request.getQueryPredicate()).andReturn(null).atLeastOnce();
     expect(request.getHttpBodyProperties()).andReturn(setResourceProperties).atLeastOnce();
 
-    expect(pm.create(resource, setResourceProperties)).andReturn(status);
+    expect(pm.create(eq(resource), eq(setProps))).andReturn(status);
     expect(status.getStatus()).andReturn(RequestStatus.Status.Complete);
     expect(status.getAssociatedResources()).andReturn(setResources);
     expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
@@ -102,7 +159,6 @@ public class CreateHandlerTest {
     Resource resource2 = createNiceMock(Resource.class);
     Resource requestResource = createNiceMock(Resource.class);
 
-    Set<Map<String, Object>> setResourceProperties = new HashSet<Map<String, Object>>();
 
     Set<Resource> setResources = new HashSet<Resource>();
     setResources.add(resource1);
@@ -110,10 +166,10 @@ public class CreateHandlerTest {
 
     // expectations
     expect(request.getResource()).andReturn(resource);
-    expect(request.getHttpBodyProperties()).andReturn(setResourceProperties);
+    expect(request.getHttpBodyProperties()).andReturn(new HashSet<NamedPropertySet>()).atLeastOnce();
     expect(request.getQueryPredicate()).andReturn(null).atLeastOnce();
 
-    expect(pm.create(resource, setResourceProperties)).andReturn(status);
+    expect(pm.create(eq(resource), eq(new HashSet<Map<String, Object>>()))).andReturn(status);
     expect(status.getStatus()).andReturn(RequestStatus.Status.Accepted);
     expect(status.getAssociatedResources()).andReturn(setResources);
     expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
@@ -163,21 +219,4 @@ public class CreateHandlerTest {
       return m_testPm;
     }
   }
-
-  @Test
-  public void testHandleRequest__InvalidQuery() throws Exception {
-    Request request = createNiceMock(Request.class);
-    ResourceInstance resource = createNiceMock(ResourceInstance.class);
-    Exception e = new InvalidQueryException("test exception");
-
-    expect(request.getResource()).andReturn(resource);
-    expect(request.getQueryPredicate()).andThrow(e);
-    replay(request, resource);
-
-    Result result = new CreateHandler().handleRequest(request);
-    assertEquals(ResultStatus.STATUS.BAD_REQUEST, result.getStatus().getStatus());
-    assertTrue(result.getStatus().getMessage().contains(e.getMessage()));
-
-    verify(request, resource);
-  }
 }

Modified: incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java?rev=1455293&r1=1455292&r2=1455293&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java Mon Mar 11 19:26:49 2013
@@ -18,9 +18,9 @@ package org.apache.ambari.server.api.han
  * limitations under the License.
  */
 
-import org.apache.ambari.server.api.predicate.InvalidQueryException;
 import org.apache.ambari.server.api.query.Query;
 import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.NamedPropertySet;
 import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.api.services.persistence.PersistenceManager;
 import org.apache.ambari.server.api.services.Request;
@@ -43,7 +43,7 @@ import static org.junit.Assert.assertEqu
 public class DeleteHandlerTest {
 
   @Test
-  public void testHandleRequest__Synchronous() throws Exception {
+  public void testHandleRequest__Synchronous_NoPropsInBody() throws Exception {
     Request request = createMock(Request.class);
     ResourceInstance resource = createMock(ResourceInstance.class);
     PersistenceManager pm = createStrictMock(PersistenceManager.class);
@@ -53,12 +53,74 @@ public class DeleteHandlerTest {
     Predicate userPredicate = createNiceMock(Predicate.class);
     Query query = createNiceMock(Query.class);
 
-    Set<Map<String, Object>> setResourceProperties = new HashSet<Map<String, Object>>();
+    Set<Resource> setResources = new HashSet<Resource>();
+    setResources.add(resource1);
+    setResources.add(resource2);
+
+    // expectations
+    expect(request.getResource()).andReturn(resource).atLeastOnce();
+    expect(request.getHttpBodyProperties()).andReturn(new HashSet<NamedPropertySet>()).atLeastOnce();
+
+    expect(request.getQueryPredicate()).andReturn(userPredicate).atLeastOnce();
+    expect(resource.getQuery()).andReturn(query).atLeastOnce();
+    query.setUserPredicate(userPredicate);
+
+    expect(pm.delete(eq(resource), eq(new HashSet<Map<String, Object>>()))).andReturn(status);
+    expect(status.getStatus()).andReturn(RequestStatus.Status.Complete);
+    expect(status.getAssociatedResources()).andReturn(setResources);
+    expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
+    expect(resource2.getType()).andReturn(Resource.Type.Cluster).anyTimes();
+
+    replay(request, resource, pm, status, resource1, resource2, userPredicate, query);
+
+    Result result = new TestDeleteHandler(pm).handleRequest(request);
+
+    assertNotNull(result);
+    TreeNode<Resource> tree = result.getResultTree();
+    assertEquals(1, tree.getChildren().size());
+    TreeNode<Resource> resourcesNode = tree.getChild("resources");
+    assertEquals(2, resourcesNode.getChildren().size());
+    boolean foundResource1 = false;
+    boolean foundResource2 = false;
+    for(TreeNode<Resource> child : resourcesNode.getChildren()) {
+      Resource r = child.getObject();
+      if (r == resource1 && ! foundResource1) {
+        foundResource1 = true;
+      } else if (r == resource2 && ! foundResource2) {
+        foundResource2 = true;
+      } else {
+        fail();
+      }
+    }
+
+    assertEquals(ResultStatus.STATUS.OK, result.getStatus().getStatus());
+    verify(request, resource, pm, status, resource1, resource2, userPredicate, query);
+  }
+
+  @Test
+  public void testHandleRequest__Synchronous() throws Exception {
+    Request request = createMock(Request.class);
+    ResourceInstance resource = createMock(ResourceInstance.class);
+    PersistenceManager pm = createStrictMock(PersistenceManager.class);
+    RequestStatus status = createMock(RequestStatus.class);
+    Resource resource1 = createMock(Resource.class);
+    Resource resource2 = createMock(Resource.class);
+    Predicate userPredicate = createNiceMock(Predicate.class);
+    Query query = createNiceMock(Query.class);
 
     Set<Resource> setResources = new HashSet<Resource>();
     setResources.add(resource1);
     setResources.add(resource2);
 
+    Set<NamedPropertySet> setResourceProperties = new HashSet<NamedPropertySet>();
+    Map<String, Object> mapProps = new HashMap<String, Object>();
+    mapProps.put("foo", "bar");
+    NamedPropertySet namedPropSet = new NamedPropertySet("name", mapProps);
+    setResourceProperties.add(namedPropSet);
+
+    Set<Map<String, Object>> setProps = new HashSet<Map<String, Object>>();
+    setProps.add(mapProps);
+
     // expectations
     expect(request.getResource()).andReturn(resource).atLeastOnce();
     expect(request.getHttpBodyProperties()).andReturn(setResourceProperties).atLeastOnce();
@@ -67,7 +129,7 @@ public class DeleteHandlerTest {
     expect(resource.getQuery()).andReturn(query).atLeastOnce();
     query.setUserPredicate(userPredicate);
 
-    expect(pm.delete(resource, setResourceProperties)).andReturn(status);
+    expect(pm.delete(eq(resource), eq(setProps))).andReturn(status);
     expect(status.getStatus()).andReturn(RequestStatus.Status.Complete);
     expect(status.getAssociatedResources()).andReturn(setResources);
     expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
@@ -99,6 +161,7 @@ public class DeleteHandlerTest {
     verify(request, resource, pm, status, resource1, resource2, userPredicate, query);
   }
 
+
   @Test
   public void testHandleRequest__Asynchronous() throws Exception {
     Request request = createMock(Request.class);
@@ -109,19 +172,17 @@ public class DeleteHandlerTest {
     Resource resource2 = createMock(Resource.class);
     Resource requestResource = createMock(Resource.class);
 
-    Set<Map<String, Object>> setResourceProperties = new HashSet<Map<String, Object>>();
-
     Set<Resource> setResources = new HashSet<Resource>();
     setResources.add(resource1);
     setResources.add(resource2);
 
     // expectations
     expect(request.getResource()).andReturn(resource);
-    expect(request.getHttpBodyProperties()).andReturn(setResourceProperties);
+    expect(request.getHttpBodyProperties()).andReturn(new HashSet<NamedPropertySet>()).atLeastOnce();
     // test delete with no user predicate
     expect(request.getQueryPredicate()).andReturn(null).atLeastOnce();
 
-    expect(pm.delete(resource, setResourceProperties)).andReturn(status);
+    expect(pm.delete(eq(resource), eq(new HashSet<Map<String, Object>>()))).andReturn(status);
     expect(status.getStatus()).andReturn(RequestStatus.Status.Accepted);
     expect(status.getAssociatedResources()).andReturn(setResources);
     expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
@@ -171,21 +232,4 @@ public class DeleteHandlerTest {
       return m_testPm;
     }
   }
-
-  @Test
-  public void testHandleRequest__InvalidQuery() throws Exception {
-    Request request = createNiceMock(Request.class);
-    ResourceInstance resource = createNiceMock(ResourceInstance.class);
-    Exception e = new InvalidQueryException("test exception");
-
-    expect(request.getResource()).andReturn(resource);
-    expect(request.getQueryPredicate()).andThrow(e);
-    replay(request, resource);
-
-    Result result = new DeleteHandler().handleRequest(request);
-    assertEquals(ResultStatus.STATUS.BAD_REQUEST, result.getStatus().getStatus());
-    assertTrue(result.getStatus().getMessage().contains(e.getMessage()));
-
-    verify(request, resource);
-  }
 }
\ No newline at end of file