You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ma...@apache.org on 2012/10/09 02:55:08 UTC

svn commit: r1395830 [1/2] - in /incubator/ambari/branches/AMBARI-666: ./ ambari-api/src/main/java/org/apache/ambari/api/handlers/ ambari-api/src/main/java/org/apache/ambari/api/query/ ambari-api/src/main/java/org/apache/ambari/api/resource/ ambari-api...

Author: mahadev
Date: Tue Oct  9 00:55:06 2012
New Revision: 1395830

URL: http://svn.apache.org/viewvc?rev=1395830&view=rev
Log:
AMBARI-824. Provide basic management functionality (create/update) in the rest api (John Speidel via mahadev)

Added:
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/BaseManagementHandler.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/BaseResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ClusterResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ComponentResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostComponentResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ServiceResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BasePersistenceManager.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/CreatePersistenceManager.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/DeletePersistenceManager.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/PersistenceManager.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/UpdatePersistenceManager.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/parsers/
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/parsers/JsonPropertyParser.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/parsers/RequestBodyParser.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/handlers/CreateHandlerTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/handlers/DeleteHandlerTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/handlers/UpdateHandlerTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/CreatePersistenceManagerTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/DeletePersistenceManagerTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/UpdatePersistenceManagerTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/parsers/
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/parsers/JsonPropertyParserTest.java
Removed:
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resource/BaseResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resource/ClusterResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resource/ComponentResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resource/HostComponentResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resource/HostResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resource/ResourceDefinition.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resource/ServiceResourceDefinition.java
Modified:
    incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/CreateHandler.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/DeleteHandler.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/UpdateHandler.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/Query.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/QueryImpl.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BaseService.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ClusterService.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ComponentService.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostComponentService.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostService.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/Request.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestFactory.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestImpl.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ResultPostProcessorImpl.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ServiceService.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/serializers/JsonSerializer.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/TestSuite.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/handlers/ReadHandlerTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/query/QueryImplTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/ClusterServiceTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/ComponentServiceTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/HostComponentServiceTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/HostServiceTest.java
    incubator/ambari/branches/AMBARI-666/ambari-api/src/test/java/org/apache/ambari/api/services/ServiceServiceTest.java
    incubator/ambari/branches/AMBARI-666/ambari-server/src/test/java/org/apache/ambari/server/controller/predicate/ResourceImpl.java
    incubator/ambari/branches/AMBARI-666/ambari-server/src/test/java/org/apache/ambari/server/resources/TestResources.java

Modified: incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt (original)
+++ incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt Tue Oct  9 00:55:06 2012
@@ -12,6 +12,9 @@ AMBARI-666 branch (unreleased changes)
 
   NEW FEATURES
 
+  AMBARI-824. Provide basic management functionality (create/update) in the
+  rest api (John Speidel via mahadev)
+
   AMBARI-825. Controller layer implementation part 3. (hitesh)
 
   AMBARI-823. Fix security filter on the server agent ports and remove

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/BaseManagementHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/BaseManagementHandler.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/BaseManagementHandler.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/BaseManagementHandler.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,39 @@
+/**
+ * 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.api.handlers;
+
+import org.apache.ambari.api.resources.ResourceDefinition;
+import org.apache.ambari.api.services.Request;
+import org.apache.ambari.api.services.Result;
+import org.apache.ambari.api.services.ResultImpl;
+
+/**
+ * Base handler for operations that persist state to the back-end.
+ */
+public class BaseManagementHandler implements RequestHandler {
+  @Override
+  public Result handleRequest(Request request) {
+    ResourceDefinition resource = request.getResourceDefinition();
+    resource.setProperties(request.getHttpBodyProperties());
+    request.getPersistenceManager().persist(resource);
+
+    //todo: what to return from persist?  Possibly just the href of the updated resource.
+    return new ResultImpl();
+  }
+}

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/CreateHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/CreateHandler.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/CreateHandler.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/CreateHandler.java Tue Oct  9 00:55:06 2012
@@ -18,16 +18,18 @@
 
 package org.apache.ambari.api.handlers;
 
-import org.apache.ambari.api.services.Request;
-import org.apache.ambari.api.services.Result;
+import org.apache.ambari.api.services.*;
+
 
 /**
  * Responsible for create requests.
  */
-public class CreateHandler implements RequestHandler {
+public class CreateHandler extends BaseManagementHandler {
   @Override
   public Result handleRequest(Request request) {
-    //TODO: implement
-    return null;
+    Result result = super.handleRequest(request);
+    //todo: what to return from create?
+    //todo: create specific exceptions
+    return result;
   }
 }

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/DeleteHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/DeleteHandler.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/DeleteHandler.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/DeleteHandler.java Tue Oct  9 00:55:06 2012
@@ -24,10 +24,10 @@ import org.apache.ambari.api.services.Re
 /**
  * Responsible for delete requests.
  */
-public class DeleteHandler implements RequestHandler {
+public class DeleteHandler extends BaseManagementHandler {
   @Override
   public Result handleRequest(Request request) {
-    //TODO: implement
-    return null;
+    //todo: delete specific return information, delete specific exceptions
+    return super.handleRequest(request);
   }
 }

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/UpdateHandler.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/UpdateHandler.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/UpdateHandler.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/handlers/UpdateHandler.java Tue Oct  9 00:55:06 2012
@@ -18,16 +18,18 @@
 
 package org.apache.ambari.api.handlers;
 
-import org.apache.ambari.api.services.Request;
-import org.apache.ambari.api.services.Result;
+import org.apache.ambari.api.services.*;
+
 
 /**
  * Responsible for update requests.
  */
-public class UpdateHandler implements RequestHandler {
+public class UpdateHandler extends BaseManagementHandler {
   @Override
   public Result handleRequest(Request request) {
-    //TODO: implement
-    return null;
+    Result result = super.handleRequest(request);
+    //todo: what to return from update?
+    //todo: update specific exceptions
+    return result;
   }
 }

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/Query.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/Query.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/Query.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/Query.java Tue Oct  9 00:55:06 2012
@@ -20,6 +20,7 @@ package org.apache.ambari.api.query;
 
 import org.apache.ambari.api.services.Result;
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.PropertyId;
 
 
@@ -52,4 +53,12 @@ public interface Query {
    * @return the result of the query.
    */
   public Result execute() throws AmbariException;
+
+  /**
+   * Return the predicate used to identify the associated resource.  This includes the primary key and
+   * all parent id's;
+   *
+   * @return the predicate used to identify the associated resource
+   */
+  public Predicate getPredicate();
 }

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/QueryImpl.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/QueryImpl.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/query/QueryImpl.java Tue Oct  9 00:55:06 2012
@@ -28,7 +28,7 @@ import org.apache.ambari.server.controll
 import org.apache.ambari.api.services.Result;
 import org.apache.ambari.api.services.ResultImpl;
 import org.apache.ambari.server.controller.spi.*;
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
 import org.apache.ambari.api.util.TreeNode;
 
 import java.util.*;
@@ -146,6 +146,10 @@ public class QueryImpl implements Query 
     return result;
   }
 
+  @Override
+  public Predicate getPredicate() {
+    return createPredicate(m_resourceDefinition);
+  }
 
   private boolean addPropertyToSubResource(String path, String property) {
     boolean resourceAdded = false;
@@ -186,7 +190,7 @@ public class QueryImpl implements Query 
 
     Set<Predicate> setPredicates = new HashSet<Predicate>();
     for (Map.Entry<Resource.Type, String> entry : mapResourceIds.entrySet()) {
-      //todo: this is a hack for host_component and component queries where serviceId is not available for
+      //todo: null check is a hack for host_component and component queries where serviceId is not available for
       //todo: host_component queries and host is not available for component queries.
       //todo: this should be rectified when the data model is changed for host_component
       if (entry.getValue() != null) {

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/BaseResourceDefinition.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/BaseResourceDefinition.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/BaseResourceDefinition.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/BaseResourceDefinition.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,186 @@
+/**
+ * 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.api.resources;
+
+
+import org.apache.ambari.api.controller.utilities.ClusterControllerHelper;
+import org.apache.ambari.api.query.Query;
+import org.apache.ambari.api.query.QueryImpl;
+import org.apache.ambari.api.services.Request;
+import org.apache.ambari.server.controller.spi.ClusterController;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Schema;
+import org.apache.ambari.api.util.TreeNode;
+
+import java.util.*;
+
+/**
+ * Base resource definition.  Contains behavior common to all resource types.
+ */
+public abstract class BaseResourceDefinition implements ResourceDefinition {
+
+  /**
+   * Resource type.  One of {@link Resource.Type}
+   */
+  private Resource.Type m_type;
+
+  /**
+   * Value of the id property for the resource.
+   */
+  private String m_id;
+
+  /**
+   * Query associated with the resource definition.
+   */
+  private Query m_query;
+
+  /**
+   * Map of primary and foreign keys and values necessary to identify the resource.
+   */
+  private Map<Resource.Type, String> m_mapResourceIds = new HashMap<Resource.Type, String>();
+
+  //TODO: Refactor out of this class when setProperties is moved.
+  private Map<PropertyId, Object> m_properties = new HashMap<PropertyId, Object>();
+
+
+  /**
+   * Constructor.
+   *
+   * @param resourceType resource type
+   * @param id           value of primary key
+   */
+  public BaseResourceDefinition(Resource.Type resourceType, String id) {
+    m_type = resourceType;
+    setId(id);
+    m_query = new QueryImpl(this);
+  }
+
+  @Override
+  public void setParentId(Resource.Type type, String value) {
+    setResourceId(type, value);
+  }
+
+  @Override
+  public String getId() {
+    return m_id;
+  }
+
+  void setId(String val) {
+    setResourceId(getType(), val);
+    m_id = val;
+  }
+
+  @Override
+  public Resource.Type getType() {
+    return m_type;
+  }
+
+
+  @Override
+  public Query getQuery() {
+    return m_query;
+  }
+
+  protected void setResourceId(Resource.Type resourceType, String val) {
+    m_mapResourceIds.put(resourceType, val);
+  }
+
+  @Override
+  public Map<Resource.Type, String> getResourceIds() {
+    return m_mapResourceIds;
+  }
+
+  ClusterController getClusterController() {
+    return ClusterControllerHelper.getClusterController();
+  }
+
+  @Override
+  public List<PostProcessor> getPostProcessors() {
+    List<PostProcessor> listProcessors = new ArrayList<PostProcessor>();
+    listProcessors.add(new BaseHrefPostProcessor());
+
+    return listProcessors;
+  }
+
+  //todo: refactor set/get property methods out of this class
+  @Override
+  public void setProperty(PropertyId property, Object value) {
+    m_properties.put(property, value);
+  }
+
+  @Override
+  public void setProperties(Map<PropertyId, Object> mapProperties) {
+    m_properties.putAll(mapProperties);
+  }
+
+  @Override
+  public Map<PropertyId, Object> getProperties() {
+    return m_properties;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof BaseResourceDefinition)) return false;
+
+    BaseResourceDefinition that = (BaseResourceDefinition) o;
+
+    if (m_id != null ? !m_id.equals(that.m_id) : that.m_id != null) return false;
+    if (m_mapResourceIds != null ? !m_mapResourceIds.equals(that.m_mapResourceIds) : that.m_mapResourceIds != null)
+      return false;
+
+    return m_type == that.m_type;
+
+  }
+
+  @Override
+  public int hashCode() {
+    int result = m_type != null ? m_type.hashCode() : 0;
+    result = 31 * result + (m_id != null ? m_id.hashCode() : 0);
+    result = 31 * result + (m_mapResourceIds != null ? m_mapResourceIds.hashCode() : 0);
+    return result;
+  }
+
+  class BaseHrefPostProcessor implements PostProcessor {
+    @Override
+    public void process(Request request, TreeNode<Resource> resultNode, String href) {
+      Resource r = resultNode.getObject();
+      TreeNode<Resource> parent = resultNode.getParent();
+
+      if (parent.getName() != null) {
+        String parentName = parent.getName();
+        Schema schema = getClusterController().getSchema(r.getType());
+        String id = r.getPropertyValue(schema.getKeyPropertyId(r.getType()));
+
+        int i = href.indexOf("?");
+        if (i != -1) {
+          href = href.substring(0, i);
+        }
+
+        if (!href.endsWith("/")) {
+          href = href + '/';
+        }
+        String isCollectionResource = parent.getProperty("isCollection");
+        href = "true".equals(isCollectionResource) ? href + id : href + parentName + '/' + id;
+      }
+      resultNode.setProperty("href", href);
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ClusterResourceDefinition.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ClusterResourceDefinition.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ClusterResourceDefinition.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ClusterResourceDefinition.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,73 @@
+/**
+ * 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.api.resources;
+
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.*;
+
+/**
+ * Cluster resource definition.
+ */
+public class ClusterResourceDefinition extends BaseResourceDefinition {
+
+  /**
+   * Constructor.
+   *
+   * @param id value of primary key
+   */
+  public ClusterResourceDefinition(String id) {
+    super(Resource.Type.Cluster, id);
+
+    if (id == null) {
+      getQuery().addProperty(getClusterController().getSchema(
+          Resource.Type.Cluster).getKeyPropertyId(Resource.Type.Cluster));
+    }
+  }
+
+  @Override
+  public String getPluralName() {
+    return "clusters";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "cluster";
+  }
+
+  @Override
+  public Map<String, ResourceDefinition> getSubResources() {
+    Map<String, ResourceDefinition> mapChildren = new HashMap<String, ResourceDefinition>();
+
+    ServiceResourceDefinition serviceResource = new ServiceResourceDefinition(null, getId());
+    PropertyId serviceIdProperty = getClusterController().getSchema(
+        Resource.Type.Service).getKeyPropertyId(Resource.Type.Service);
+    serviceResource.getQuery().addProperty(serviceIdProperty);
+    mapChildren.put(serviceResource.getPluralName(), serviceResource);
+
+    HostResourceDefinition hostResource = new HostResourceDefinition(null, getId());
+    PropertyId hostIdProperty = getClusterController().getSchema(
+        Resource.Type.Host).getKeyPropertyId(Resource.Type.Host);
+    hostResource.getQuery().addProperty(hostIdProperty);
+    mapChildren.put(hostResource.getPluralName(), hostResource);
+
+    return mapChildren;
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ComponentResourceDefinition.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ComponentResourceDefinition.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ComponentResourceDefinition.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ComponentResourceDefinition.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,132 @@
+/**
+ * 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.api.resources;
+
+import org.apache.ambari.api.controller.utilities.ClusterControllerHelper;
+import org.apache.ambari.api.services.Request;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Schema;
+import org.apache.ambari.api.util.TreeNode;
+
+import org.apache.ambari.api.services.ResultPostProcessor;
+
+import java.util.*;
+
+/**
+ * Component resource definition.
+ */
+public class ComponentResourceDefinition extends BaseResourceDefinition {
+
+  /**
+   * value of clusterId foreign key
+   */
+  private String m_clusterId;
+
+  /**
+   * value of serviceId foreign key
+   */
+  private String m_serviceId;
+
+
+  /**
+   * Constructor.
+   *
+   * @param id        value of component id
+   * @param clusterId value of cluster id
+   * @param serviceId value of service id
+   */
+  public ComponentResourceDefinition(String id, String clusterId, String serviceId) {
+    super(Resource.Type.Component, id);
+    m_clusterId = clusterId;
+    m_serviceId = serviceId;
+    setResourceId(Resource.Type.Cluster, m_clusterId);
+    setResourceId(Resource.Type.Service, m_serviceId);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "components";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "component";
+  }
+
+
+  @Override
+  public Map<String, ResourceDefinition> getSubResources() {
+    Map<String, ResourceDefinition> mapChildren = new HashMap<String, ResourceDefinition>();
+
+    // for host_component collection need host id property
+    HostComponentResourceDefinition hostComponentResource = new HostComponentResourceDefinition(
+        getId(), m_clusterId, null);
+    PropertyId hostIdProperty = getClusterController().getSchema(
+        Resource.Type.HostComponent).getKeyPropertyId(Resource.Type.Host);
+    hostComponentResource.getQuery().addProperty(hostIdProperty);
+    mapChildren.put(hostComponentResource.getPluralName(), hostComponentResource);
+    return mapChildren;
+
+  }
+
+  @Override
+  public List<PostProcessor> getPostProcessors() {
+    List<PostProcessor> listProcessors = super.getPostProcessors();
+    listProcessors.add(new ComponentHrefProcessor());
+
+    return listProcessors;
+  }
+
+  @Override
+  public void setParentId(Resource.Type type, String value) {
+    if (type == Resource.Type.HostComponent) {
+      setId(value);
+    } else {
+      super.setParentId(type, value);
+    }
+  }
+
+  /**
+   * Base resource processor which generates href's.  This is called by the {@link ResultPostProcessor} during post
+   * processing of a result.
+   */
+  private class ComponentHrefProcessor extends BaseHrefPostProcessor {
+    @Override
+    public void process(Request request, TreeNode<Resource> resultNode, String href) {
+      TreeNode<Resource> parent = resultNode.getParent();
+
+      if (parent.getParent() != null && parent.getParent().getObject().getType() == Resource.Type.HostComponent) {
+        Resource r = resultNode.getObject();
+        String clusterId = getResourceIds().get(Resource.Type.Cluster);
+        Schema schema = ClusterControllerHelper.getClusterController().getSchema(r.getType());
+        String serviceId = r.getPropertyValue(schema.getKeyPropertyId(Resource.Type.Service));
+        String componentId = r.getPropertyValue(schema.getKeyPropertyId(r.getType()));
+
+        href = href.substring(0, href.indexOf(clusterId) + clusterId.length() + 1) +
+            "services/" + serviceId + "/components/" + componentId;
+
+        resultNode.setProperty("href", href);
+      } else {
+        super.process(request, resultNode, href);
+      }
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostComponentResourceDefinition.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostComponentResourceDefinition.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostComponentResourceDefinition.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostComponentResourceDefinition.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,151 @@
+/**
+ * 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.api.resources;
+
+import org.apache.ambari.api.controller.internal.PropertyIdImpl;
+import org.apache.ambari.api.controller.utilities.ClusterControllerHelper;
+import org.apache.ambari.api.services.Request;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Schema;
+import org.apache.ambari.api.util.TreeNode;
+
+import org.apache.ambari.api.services.ResultPostProcessor;
+
+import java.util.*;
+
+/**
+ * Host_Component resource definition.
+ */
+public class HostComponentResourceDefinition extends BaseResourceDefinition {
+
+  /**
+   * value of cluster id foreign key
+   */
+  private String m_clusterId;
+
+  /**
+   * value of host id foreign key
+   */
+  private String m_hostId;
+
+
+  /**
+   * Constructor.
+   *
+   * @param id        value of host_component id
+   * @param clusterId value of cluster id foreign key
+   * @param hostId    value of host id foreign key
+   */
+  public HostComponentResourceDefinition(String id, String clusterId, String hostId) {
+    super(Resource.Type.HostComponent, id);
+    m_clusterId = clusterId;
+    m_hostId = hostId;
+    setResourceId(Resource.Type.Cluster, m_clusterId);
+    setResourceId(Resource.Type.Host, m_hostId);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "host_components";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "host_component";
+  }
+
+
+  @Override
+  public Map<String, ResourceDefinition> getSubResources() {
+    Map<String, ResourceDefinition> mapChildren = new HashMap<String, ResourceDefinition>();
+
+    ComponentResourceDefinition componentResource = new ComponentResourceDefinition(
+        getId(), m_clusterId, null);
+    PropertyId serviceIdProperty = getClusterController().getSchema(
+        Resource.Type.Component).getKeyPropertyId(Resource.Type.Service);
+    componentResource.getQuery().addProperty(serviceIdProperty);
+    mapChildren.put(componentResource.getSingularName(), componentResource);
+
+    return mapChildren;
+  }
+
+  @Override
+  public List<PostProcessor> getPostProcessors() {
+    List<PostProcessor> listProcessors = new ArrayList<PostProcessor>();
+    listProcessors.add(new HostComponentHrefProcessor());
+    listProcessors.add(new HostComponentHostProcessor());
+
+    return listProcessors;
+  }
+
+  @Override
+  public void setParentId(Resource.Type type, String value) {
+    if (type == Resource.Type.Component) {
+      setId(value);
+    } else {
+      super.setParentId(type, value);
+    }
+  }
+
+
+  /**
+   * Host_Component resource processor which is responsible for generating href's for host components.
+   * This is called by the {@link ResultPostProcessor} during post processing of a result.
+   */
+  private class HostComponentHrefProcessor extends BaseHrefPostProcessor {
+    @Override
+    public void process(Request request, TreeNode<Resource> resultNode, String href) {
+      TreeNode<Resource> parent = resultNode.getParent();
+
+      if (parent.getParent() != null && parent.getParent().getObject().getType() == Resource.Type.Component) {
+        Resource r = resultNode.getObject();
+        String clusterId = getResourceIds().get(Resource.Type.Cluster);
+        Schema schema = ClusterControllerHelper.getClusterController().getSchema(r.getType());
+        String host = r.getPropertyValue(schema.getKeyPropertyId(Resource.Type.Host));
+        String hostComponent = r.getPropertyValue(schema.getKeyPropertyId(r.getType()));
+
+        href = href.substring(0, href.indexOf(clusterId) + clusterId.length() + 1) +
+            "hosts/" + host + "/host_components/" + hostComponent;
+
+        resultNode.setProperty("href", href);
+      } else {
+        super.process(request, resultNode, href);
+      }
+
+    }
+  }
+
+  /**
+   * Host_Component resource processor which is responsible for generating a host section for host components.
+   * This is called by the {@link ResultPostProcessor} during post processing of a result.
+   */
+  private class HostComponentHostProcessor implements PostProcessor {
+    @Override
+    public void process(Request request, TreeNode<Resource> resultNode, String href) {
+      //todo: look at partial request fields to ensure that hosts should be returned
+      if (request.getResourceDefinition().getType() == getType()) {
+        // only add host if query host_resource was directly queried
+        String nodeHref = resultNode.getProperty("href");
+        resultNode.getObject().setProperty(new PropertyIdImpl("href", "host", false),
+            nodeHref.substring(0, nodeHref.indexOf("/host_components/")));
+      }
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostResourceDefinition.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostResourceDefinition.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostResourceDefinition.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/HostResourceDefinition.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,70 @@
+/**
+ * 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.api.resources;
+
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.*;
+
+/**
+ * Host resource definition.
+ */
+public class HostResourceDefinition extends BaseResourceDefinition {
+
+  /**
+   * value of cluster id foreign key
+   */
+  private String m_clusterId;
+
+  /**
+   * Constructor.
+   *
+   * @param id        host id value
+   * @param clusterId cluster id value
+   */
+  public HostResourceDefinition(String id, String clusterId) {
+    super(Resource.Type.Host, id);
+    m_clusterId = clusterId;
+    setResourceId(Resource.Type.Cluster, m_clusterId);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "hosts";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "host";
+  }
+
+  @Override
+  public Map<String, ResourceDefinition> getSubResources() {
+    Map<String, ResourceDefinition> mapChildren = new HashMap<String, ResourceDefinition>();
+
+    HostComponentResourceDefinition hostComponentResource = new HostComponentResourceDefinition(
+        null, m_clusterId, getId());
+    PropertyId hostComponentIdProperty = getClusterController().getSchema(
+        Resource.Type.HostComponent).getKeyPropertyId(Resource.Type.HostComponent);
+    hostComponentResource.getQuery().addProperty(hostComponentIdProperty);
+    mapChildren.put(hostComponentResource.getPluralName(), hostComponentResource);
+    return mapChildren;
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ResourceDefinition.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ResourceDefinition.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ResourceDefinition.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ResourceDefinition.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,135 @@
+/**
+ * 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.api.resources;
+
+import org.apache.ambari.api.query.Query;
+import org.apache.ambari.api.services.Request;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.api.util.TreeNode;
+
+import org.apache.ambari.api.services.ResultPostProcessor;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Resource Definition.
+ * Provides information specific to a specific resource type.
+ */
+public interface ResourceDefinition {
+  /**
+   * Obtain the plural name of the resource.
+   *
+   * @return the plural name of the resource
+   */
+  public String getPluralName();
+
+  /**
+   * Obtain the singular name of the resource.
+   *
+   * @return the singular name of the resource
+   */
+  public String getSingularName();
+
+  /**
+   * Obtain the value of the primary id of the resource.
+   *
+   * @return the value of the primary id of the resource
+   */
+  public String getId();
+
+  /**
+   * Obtain the type of resource.  Is one of {@link Resource.Type}.
+   *
+   * @return the type of resource
+   */
+  public Resource.Type getType();
+
+  /**
+   * Set the value of the parent foreign key.
+   *
+   * @param type  resource type of the parent
+   * @param value vale of the parent id
+   */
+  public void setParentId(Resource.Type type, String value);
+
+  /**
+   * Obtain the primary and foreign key properties for the resource.
+   *
+   * @return map of primary and foreign key values keyed by resource type
+   */
+  public Map<Resource.Type, String> getResourceIds();
+
+  /**
+   * Obtain sub-resources of this resource.  A sub-resource is a resource that is contained in
+   * another parent resource.
+   *
+   * @return map of sub resource definitions keyed by resource name
+   */
+  public Map<String, ResourceDefinition> getSubResources();
+
+  /**
+   * Return the query associated with the resource.
+   * Each resource has one query.
+   *
+   * @return the associated query
+   */
+  public Query getQuery();
+
+  /**
+   * Obtain any resource post processors.  A resource processor is used to provide resource specific processing of
+   * results and is called by the {@link ResultPostProcessor} while post processing a result.
+   *
+   * @return list of resource specific result processors
+   */
+  public List<PostProcessor> getPostProcessors();
+
+  //TODO: refactor set/get Property methods out of this class
+  /**
+   * Set a property on this resource.
+   *
+   * @param property the property
+   * @param value    the value
+   */
+  public void setProperty(PropertyId property, Object value);
+
+  /**
+   * Set a map of properties on the resource.
+   *
+   * @param mapProperties a map of properties
+   */
+  public void setProperties(Map<PropertyId, Object> mapProperties);
+
+  /**
+   * Get the properties which have been set on this resource.
+   *
+   * @return the properties which have been set on this resource
+   */
+  public Map<PropertyId, Object> getProperties();
+
+  /**
+   * Resource specific result processor.
+   * Used to provide resource specific processing of a result.
+   */
+  public interface PostProcessor {
+    public void process(Request request, TreeNode<Resource> resultNode, String href);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ServiceResourceDefinition.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ServiceResourceDefinition.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ServiceResourceDefinition.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/resources/ServiceResourceDefinition.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,70 @@
+/**
+ * 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.api.resources;
+
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.*;
+
+/**
+ * Service resource definition.
+ */
+public class ServiceResourceDefinition extends BaseResourceDefinition {
+
+  /**
+   * value of cluster id foreign key
+   */
+  private String m_clusterId;
+
+  /**
+   * Constructor.
+   *
+   * @param id        service id value
+   * @param clusterId cluster id value
+   */
+  public ServiceResourceDefinition(String id, String clusterId) {
+    super(Resource.Type.Service, id);
+    m_clusterId = clusterId;
+    setResourceId(Resource.Type.Cluster, m_clusterId);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "services";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "service";
+  }
+
+  @Override
+  public Map<String, ResourceDefinition> getSubResources() {
+    Map<String, ResourceDefinition> mapChildren = new HashMap<String, ResourceDefinition>();
+    // for component collection need id property
+    ComponentResourceDefinition componentResourceDefinition =
+        new ComponentResourceDefinition(null, m_clusterId, getId());
+    PropertyId componentIdProperty = getClusterController().getSchema(
+        Resource.Type.Component).getKeyPropertyId(Resource.Type.Component);
+    componentResourceDefinition.getQuery().addProperty(componentIdProperty);
+    mapChildren.put(componentResourceDefinition.getPluralName(), componentResourceDefinition);
+    return mapChildren;
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BasePersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BasePersistenceManager.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BasePersistenceManager.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BasePersistenceManager.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,42 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.api.controller.internal.RequestImpl;
+import org.apache.ambari.api.controller.utilities.ClusterControllerHelper;
+import org.apache.ambari.server.controller.spi.ClusterController;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Request;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Base PersistenceManager functionality.
+ */
+public abstract class BasePersistenceManager implements PersistenceManager {
+
+  protected ClusterController getClusterController() {
+    return ClusterControllerHelper.getClusterController();
+  }
+
+  protected Request createControllerRequest(Map<PropertyId, Object> properties) {
+    return new RequestImpl(null, Collections.singleton(properties));
+  }
+}

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BaseService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BaseService.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BaseService.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/BaseService.java Tue Oct  9 00:55:06 2012
@@ -20,7 +20,7 @@ package org.apache.ambari.api.services;
 
 import org.apache.ambari.api.handlers.DelegatingRequestHandler;
 import org.apache.ambari.api.handlers.RequestHandler;
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
 import org.apache.ambari.api.services.serializers.ResultSerializer;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -37,16 +37,19 @@ public abstract class BaseService {
    * This consists of creating a {@link Request} instance, invoking the correct {@link RequestHandler} and
    * applying the proper {@link ResultSerializer} to the result.
    *
+   *
+   *
    * @param headers            http headers
+   * @param body
    * @param uriInfo            uri information
    * @param requestType        http request type
    * @param resourceDefinition resource definition that is being acted on
    * @return the response of the operation in serialized form
    */
-  protected Response handleRequest(HttpHeaders headers, UriInfo uriInfo, Request.Type requestType,
+  protected Response handleRequest(HttpHeaders headers, String body, UriInfo uriInfo, Request.Type requestType,
                                    ResourceDefinition resourceDefinition) {
 
-    Request request = getRequestFactory().createRequest(headers, uriInfo, requestType, resourceDefinition);
+    Request request = getRequestFactory().createRequest(headers, body, uriInfo, requestType, resourceDefinition);
     Result result = getRequestHandler().handleRequest(request);
 
     return getResponseFactory().createResponse(request.getResultSerializer().serialize(result, uriInfo));

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ClusterService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ClusterService.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ClusterService.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ClusterService.java Tue Oct  9 00:55:06 2012
@@ -18,8 +18,8 @@
 
 package org.apache.ambari.api.services;
 
-import org.apache.ambari.api.resource.ClusterResourceDefinition;
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.ClusterResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
 
 import javax.ws.rs.*;
 import javax.ws.rs.core.*;
@@ -46,7 +46,7 @@ public class ClusterService extends Base
   public Response getCluster(@Context HttpHeaders headers, @Context UriInfo ui,
                              @PathParam("clusterName") String clusterName) {
 
-    return handleRequest(headers, ui, Request.Type.GET, createResourceDefinition(clusterName));
+    return handleRequest(headers, null, ui, Request.Type.GET, createResourceDefinition(clusterName));
   }
 
   /**
@@ -60,7 +60,7 @@ public class ClusterService extends Base
   @GET
   @Produces("text/plain")
   public Response getClusters(@Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(headers, ui, Request.Type.GET, createResourceDefinition(null));
+    return handleRequest(headers, null, ui, Request.Type.GET, createResourceDefinition(null));
   }
 
   /**
@@ -74,10 +74,10 @@ public class ClusterService extends Base
    */
   @PUT
   @Produces("text/plain")
-  public Response createCluster(@Context HttpHeaders headers, @Context UriInfo ui,
+  public Response createCluster(String body, @Context HttpHeaders headers, @Context UriInfo ui,
                                 @PathParam("clusterName") String clusterName) {
 
-    return handleRequest(headers, ui, Request.Type.PUT, createResourceDefinition(clusterName));
+    return handleRequest(headers, body, ui, Request.Type.PUT, createResourceDefinition(clusterName));
   }
 
   /**
@@ -91,10 +91,10 @@ public class ClusterService extends Base
    */
   @POST
   @Produces("text/plain")
-  public Response updateCluster(@Context HttpHeaders headers, @Context UriInfo ui,
+  public Response updateCluster(String body, @Context HttpHeaders headers, @Context UriInfo ui,
                                 @PathParam("clusterName") String clusterName) {
 
-    return handleRequest(headers, ui, Request.Type.POST, createResourceDefinition(clusterName));
+    return handleRequest(headers, body, ui, Request.Type.POST, createResourceDefinition(clusterName));
   }
 
   /**
@@ -111,7 +111,7 @@ public class ClusterService extends Base
   public Response deleteCluster(@Context HttpHeaders headers, @Context UriInfo ui,
                                 @PathParam("clusterName") String clusterName) {
 
-    return handleRequest(headers, ui, Request.Type.DELETE, createResourceDefinition(clusterName));
+    return handleRequest(headers, null, ui, Request.Type.DELETE, createResourceDefinition(clusterName));
   }
 
   /**

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ComponentService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ComponentService.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ComponentService.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ComponentService.java Tue Oct  9 00:55:06 2012
@@ -18,13 +18,10 @@
 
 package org.apache.ambari.api.services;
 
-import org.apache.ambari.api.resource.ComponentResourceDefinition;
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.ComponentResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import javax.ws.rs.*;
 import javax.ws.rs.core.*;
 
 /**
@@ -53,7 +50,7 @@ public class ComponentService extends Ba
   }
 
   /**
-   * Handles URL: /clusters/{clusterID}/services/{serviceID}/components/{componentID}
+   * Handles GET: /clusters/{clusterID}/services/{serviceID}/components/{componentID}
    * Get a specific component.
    *
    * @param headers       http headers
@@ -67,12 +64,12 @@ public class ComponentService extends Ba
   public Response getComponent(@Context HttpHeaders headers, @Context UriInfo ui,
                                @PathParam("componentName") String componentName) {
 
-    return handleRequest(headers, ui, Request.Type.GET,
+    return handleRequest(headers, null, ui, Request.Type.GET,
         createResourceDefinition(componentName, m_clusterName, m_serviceName));
   }
 
   /**
-   * Handles URL: /clusters/{clusterID}/services/{serviceID}/components
+   * Handles GET: /clusters/{clusterID}/services/{serviceID}/components
    * Get all components for a service.
    *
    * @param headers http headers
@@ -82,11 +79,69 @@ public class ComponentService extends Ba
   @GET
   @Produces("text/plain")
   public Response getComponents(@Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(headers, ui, Request.Type.GET,
+    return handleRequest(headers, null, ui, Request.Type.GET,
         createResourceDefinition(null, m_clusterName, m_serviceName));
   }
 
   /**
+   * Handles: PUT /clusters/{clusterID}/services/{serviceID}/components/{componentID}
+   * Create a specific component.
+   *
+   * @param body          http body
+   * @param headers       http headers
+   * @param ui            uri info
+   * @param componentName component id
+   *
+   * @return information regarding the created component
+   */
+  @PUT
+  @Produces("text/plain")
+  public Response createComponent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT,
+        createResourceDefinition(componentName, m_clusterName, m_serviceName));
+  }
+
+  /**
+   * Handles: POST /clusters/{clusterID}/services/{serviceID}/components/{componentID}
+   * Update a specific component.
+   *
+   * @param body                http body
+   * @param headers       http headers
+   * @param ui            uri info
+   * @param componentName component id
+   *
+   * @return information regarding the updated component
+   */
+  @POST
+  @Produces("text/plain")
+  public Response updateComponent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST, createResourceDefinition(
+        componentName, m_clusterName, m_serviceName));
+  }
+
+  /**
+   * Handles: DELETE /clusters/{clusterID}/services/{serviceID}/components/{componentID}
+   * Delete a specific component.
+   *
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param componentName cluster id
+   * @return information regarding the deleted cluster
+   */
+  @DELETE
+  @Produces("text/plain")
+  public Response deleteComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE, createResourceDefinition(
+        componentName, m_clusterName, m_serviceName));
+  }
+
+  /**
    * Create a component resource definition.
    *
    * @param clusterName   cluster name

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/CreatePersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/CreatePersistenceManager.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/CreatePersistenceManager.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/CreatePersistenceManager.java Tue Oct  9 00:55:06 2012
@@ -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.api.services;
+
+import org.apache.ambari.api.resources.ResourceDefinition;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.spi.ClusterController;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Schema;
+
+import java.util.Map;
+
+/**
+ * Responsible for persisting the creation of a resource in the back end.
+ */
+public class CreatePersistenceManager extends BasePersistenceManager {
+  @Override
+  public void persist(ResourceDefinition resource) {
+    ClusterController controller = getClusterController();
+    Map<Resource.Type, String> mapResourceIds = resource.getResourceIds();
+    Resource.Type type = resource.getType();
+    Schema schema = controller.getSchema(type);
+
+    for (Map.Entry<Resource.Type, String> entry : mapResourceIds.entrySet()) {
+      resource.setProperty(schema.getKeyPropertyId(entry.getKey()), entry.getValue());
+    }
+    try {
+      controller.createResources(type, createControllerRequest(resource.getProperties()));
+    } catch (AmbariException e) {
+      //todo: handle exception
+      throw new RuntimeException("Create of resource failed: " + e, e);
+
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/DeletePersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/DeletePersistenceManager.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/DeletePersistenceManager.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/DeletePersistenceManager.java Tue Oct  9 00:55:06 2012
@@ -0,0 +1,38 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.api.resources.ResourceDefinition;
+import org.apache.ambari.server.AmbariException;
+
+/**
+ * Responsible for persisting the deletion of a resource in the back end.
+ */
+public class DeletePersistenceManager extends BasePersistenceManager {
+  @Override
+  public void persist(ResourceDefinition resource) {
+    try {
+      getClusterController().deleteResources(resource.getType(),
+          resource.getQuery().getPredicate());
+    } catch (AmbariException e) {
+      //todo: handle exception
+      throw new RuntimeException("Delete of resource failed: " + e, e);
+    }
+  }
+}

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostComponentService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostComponentService.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostComponentService.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostComponentService.java Tue Oct  9 00:55:06 2012
@@ -18,13 +18,10 @@
 
 package org.apache.ambari.api.services;
 
-import org.apache.ambari.api.resource.HostComponentResourceDefinition;
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.HostComponentResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import javax.ws.rs.*;
 import javax.ws.rs.core.*;
 
 /**
@@ -53,7 +50,7 @@ public class HostComponentService extend
   }
 
   /**
-   * Handles URL: /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
+   * Handles GET /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
    * Get a specific host_component.
    *
    * @param headers           http headers
@@ -67,12 +64,12 @@ public class HostComponentService extend
   public Response getHostComponent(@Context HttpHeaders headers, @Context UriInfo ui,
                                    @PathParam("hostComponentName") String hostComponentName) {
 
-    return handleRequest(headers, ui, Request.Type.GET,
+    return handleRequest(headers, null, ui, Request.Type.GET,
         createResourceDefinition(hostComponentName, m_clusterName, m_hostName));
   }
 
   /**
-   * Handles URL: /clusters/{clusterID}/hosts/{hostID}/host_components/
+   * Handles GET /clusters/{clusterID}/hosts/{hostID}/host_components/
    * Get all host components for a host.
    *
    * @param headers http headers
@@ -82,11 +79,73 @@ public class HostComponentService extend
   @GET
   @Produces("text/plain")
   public Response getHostComponents(@Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(headers, ui, Request.Type.GET,
+    return handleRequest(headers, null, ui, Request.Type.GET,
         createResourceDefinition(null, m_clusterName, m_hostName));
   }
 
   /**
+   * Handles PUT /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
+   * Create a specific host_component.
+   *
+   * @param body              http body
+   * @param headers           http headers
+   * @param ui                uri info
+   * @param hostComponentName host_component id
+   *
+   * @return host_component resource representation
+   */
+  @PUT
+  @Path("{hostComponentName}")
+  @Produces("text/plain")
+  public Response createHostComponent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                   @PathParam("hostComponentName") String hostComponentName) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT,
+        createResourceDefinition(hostComponentName, m_clusterName, m_hostName));
+  }
+
+  /**
+   * Handles POST /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
+   * Updates a specific host_component.
+   *
+   * @param body              http body
+   * @param headers           http headers
+   * @param ui                uri info
+   * @param hostComponentName host_component id
+   *
+   * @return host_component resource representation
+   */
+  @POST
+  @Path("{hostComponentName}")
+  @Produces("text/plain")
+  public Response updateHostComponent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                      @PathParam("hostComponentName") String hostComponentName) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST,
+        createResourceDefinition(hostComponentName, m_clusterName, m_hostName));
+  }
+
+  /**
+   * Handles DELETE /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
+   * Delete a specific host_component.
+   *
+   * @param headers           http headers
+   * @param ui                uri info
+   * @param hostComponentName host_component id
+   *
+   * @return host_component resource representation
+   */
+  @DELETE
+  @Path("{hostComponentName}")
+  @Produces("text/plain")
+  public Response deleteHostComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+                                   @PathParam("hostComponentName") String hostComponentName) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE,
+        createResourceDefinition(hostComponentName, m_clusterName, m_hostName));
+  }
+
+  /**
    * Create a host_component resource definition.
    *
    * @param hostComponentName host_component name

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostService.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostService.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/HostService.java Tue Oct  9 00:55:06 2012
@@ -18,13 +18,10 @@
 
 package org.apache.ambari.api.services;
 
-import org.apache.ambari.api.resource.HostResourceDefinition;
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.HostResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import javax.ws.rs.*;
 import javax.ws.rs.core.*;
 
 /**
@@ -47,7 +44,7 @@ public class HostService extends BaseSer
   }
 
   /**
-   * Handles URL: /clusters/{clusterID}/hosts/{hostID}
+   * Handles GET /clusters/{clusterID}/hosts/{hostID}
    * Get a specific host.
    *
    * @param headers  http headers
@@ -61,12 +58,12 @@ public class HostService extends BaseSer
   public Response getHost(@Context HttpHeaders headers, @Context UriInfo ui,
                           @PathParam("hostName") String hostName) {
 
-    return handleRequest(headers, ui, Request.Type.GET,
+    return handleRequest(headers, null, ui, Request.Type.GET,
         createResourceDefinition(hostName, m_clusterName));
   }
 
   /**
-   * Handles URL: /clusters/{clusterID}/hosts or /clusters/hosts
+   * Handles GET /clusters/{clusterID}/hosts or /clusters/hosts
    * Get all hosts for a cluster.
    *
    * @param headers http headers
@@ -76,7 +73,70 @@ public class HostService extends BaseSer
   @GET
   @Produces("text/plain")
   public Response getHosts(@Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(headers, ui, Request.Type.GET, createResourceDefinition(null, m_clusterName));
+    return handleRequest(headers, null, ui, Request.Type.GET, createResourceDefinition(null, m_clusterName));
+  }
+
+  /**
+   * Handles PUT /clusters/{clusterID}/hosts/{hostID}
+   * Create a specific host.
+   *
+   * @param body     http body
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param hostName host id
+   *
+   * @return host resource representation
+   */
+
+  @PUT
+  @Path("{hostName}")
+  @Produces("text/plain")
+  public Response createHost(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                          @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT,
+        createResourceDefinition(hostName, m_clusterName));
+  }
+
+  /**
+   * Handles POST /clusters/{clusterID}/hosts/{hostID}
+   * Updates a specific host.
+   *
+   * @param body     http body
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param hostName host id
+   *
+   * @return host resource representation
+   */
+  @POST
+  @Path("{hostName}")
+  @Produces("text/plain")
+  public Response updateHost(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                          @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST,
+        createResourceDefinition(hostName, m_clusterName));
+  }
+
+  /**
+   * Handles DELETE /clusters/{clusterID}/hosts/{hostID}
+   * Deletes a specific host.
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param hostName host id
+   *
+   * @return host resource representation
+   */
+  @DELETE
+  @Path("{hostName}")
+  @Produces("text/plain")
+  public Response deleteHost(@Context HttpHeaders headers, @Context UriInfo ui,
+                             @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE,
+        createResourceDefinition(hostName, m_clusterName));
   }
 
   /**

Added: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/PersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/PersistenceManager.java?rev=1395830&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/PersistenceManager.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/PersistenceManager.java Tue Oct  9 00:55:06 2012
@@ -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.api.services;
+
+import org.apache.ambari.api.resources.ResourceDefinition;
+
+/**
+ * Persistence manager which is responsible for persisting a resource state to the back end.
+ * This includes create, update and delete operations.
+ */
+public interface PersistenceManager {
+  /**
+   * Persist a resource to the back end.
+   *
+   * @param resource  the resource to persist
+   *
+   */
+  public void persist(ResourceDefinition resource);
+}

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/Request.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/Request.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/Request.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/Request.java Tue Oct  9 00:55:06 2012
@@ -18,8 +18,10 @@
 
 package org.apache.ambari.api.services;
 
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
+import org.apache.ambari.api.services.parsers.RequestBodyParser;
 import org.apache.ambari.api.services.serializers.ResultSerializer;
+import org.apache.ambari.server.controller.spi.PropertyId;
 
 import java.net.URI;
 import java.util.List;
@@ -87,7 +89,7 @@ public interface Request {
   /**
    * Obtain the result serializer for the request. The default serializer is of type JSON.
    *
-   * @return the result serializer fo rthe request
+   * @return the result serializer for the request
    */
   public ResultSerializer getResultSerializer();
 
@@ -112,4 +114,19 @@ public interface Request {
    * @return the http body
    */
   public String getHttpBody();
+
+  /**
+   * Obtain the properties which have been parsed from the http body.
+   *
+   * @return a map containing the properties contained in the http body
+   */
+  public Map<PropertyId, Object> getHttpBodyProperties();
+
+    //TODO: refactor persistence mechanism
+  /**
+   * Obtain the appropriate persistence manager.
+   *
+   * @return the appropriate persistence manager
+   */
+  public PersistenceManager getPersistenceManager();
 }

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestFactory.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestFactory.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestFactory.java Tue Oct  9 00:55:06 2012
@@ -18,7 +18,7 @@
 
 package org.apache.ambari.api.services;
 
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.UriInfo;
@@ -36,9 +36,9 @@ public class RequestFactory {
    * @param resourceDefinition associated resource definition
    * @return a new Request instance
    */
-  public Request createRequest(HttpHeaders headers, UriInfo uriInfo, Request.Type requestType,
+  public Request createRequest(HttpHeaders headers, String body, UriInfo uriInfo, Request.Type requestType,
                                ResourceDefinition resourceDefinition) {
 
-    return new RequestImpl(headers, uriInfo, requestType, resourceDefinition);
+    return new RequestImpl(headers, body, uriInfo, requestType, resourceDefinition);
   }
 }

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestImpl.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestImpl.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/RequestImpl.java Tue Oct  9 00:55:06 2012
@@ -18,9 +18,12 @@
 
 package org.apache.ambari.api.services;
 
-import org.apache.ambari.api.resource.*;
+import org.apache.ambari.api.resources.*;
+import org.apache.ambari.api.services.parsers.JsonPropertyParser;
+import org.apache.ambari.api.services.parsers.RequestBodyParser;
 import org.apache.ambari.api.services.serializers.JsonSerializer;
 import org.apache.ambari.api.services.serializers.ResultSerializer;
+import org.apache.ambari.server.controller.spi.PropertyId;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.UriInfo;
@@ -43,6 +46,11 @@ public class RequestImpl implements Requ
   private HttpHeaders m_headers;
 
   /**
+   * Http Body
+   */
+  private String m_body;
+
+  /**
    * Http request type
    */
   private Type m_Type;
@@ -52,18 +60,23 @@ public class RequestImpl implements Requ
    */
   private ResourceDefinition m_resourceDefinition;
 
+
   /**
    * Constructor.
    *
    * @param headers            http headers
+   * @param body               http body
    * @param uriInfo            uri information
    * @param requestType        http request type
    * @param resourceDefinition associated resource definition
    */
-  public RequestImpl(HttpHeaders headers, UriInfo uriInfo, Type requestType, ResourceDefinition resourceDefinition) {
-    m_uriInfo = uriInfo;
-    m_headers = headers;
-    m_Type = requestType;
+  public RequestImpl(HttpHeaders headers, String body, UriInfo uriInfo, Type requestType,
+                     ResourceDefinition resourceDefinition) {
+
+    m_headers            = headers;
+    m_body               = body;
+    m_uriInfo            = uriInfo;
+    m_Type               = requestType;
     m_resourceDefinition = resourceDefinition;
   }
 
@@ -109,7 +122,13 @@ public class RequestImpl implements Requ
 
   @Override
   public String getHttpBody() {
-    return null;
+    return m_body;
+  }
+
+  @Override
+  public Map<PropertyId, Object> getHttpBodyProperties() {
+    return m_body == null ? Collections.<PropertyId, Object>emptyMap() :
+        getHttpBodyParser().parse(getHttpBody());
   }
 
   @Override
@@ -121,4 +140,24 @@ public class RequestImpl implements Requ
   public ResultPostProcessor getResultPostProcessor() {
     return new ResultPostProcessorImpl(this);
   }
+
+  @Override
+  public PersistenceManager getPersistenceManager() {
+    switch (getRequestType()) {
+      case PUT:
+        return new CreatePersistenceManager();
+      case POST:
+        return new UpdatePersistenceManager();
+      case DELETE:
+        return new DeletePersistenceManager();
+      case GET:
+        throw new IllegalStateException("Tried to get persistence manager for get operation");
+      default:
+        throw new IllegalStateException("Tried to get persistence manager for unknown operation type");
+    }
+  }
+
+  private  RequestBodyParser getHttpBodyParser() {
+    return new JsonPropertyParser();
+  }
 }

Modified: incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ResultPostProcessorImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ResultPostProcessorImpl.java?rev=1395830&r1=1395829&r2=1395830&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ResultPostProcessorImpl.java (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-api/src/main/java/org/apache/ambari/api/services/ResultPostProcessorImpl.java Tue Oct  9 00:55:06 2012
@@ -18,7 +18,7 @@
 
 package org.apache.ambari.api.services;
 
-import org.apache.ambari.api.resource.ResourceDefinition;
+import org.apache.ambari.api.resources.ResourceDefinition;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.api.util.TreeNode;