/**
* Abiquo community edition
* cloud management application for hybrid clouds
* Copyright (C) 2008-2010 - Abiquo Holdings S.L.
*
* This application is free software; you can redistribute it and/or
* modify it under the terms of the GNU LESSER GENERAL PUBLIC
* LICENSE as published by the Free Software Foundation under
* version 3 of the License
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* LESSER GENERAL PUBLIC LICENSE v.3 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package com.abiquo.api.resources;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.apache.wink.common.annotations.Parent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.abiquo.api.exceptions.APIError;
import com.abiquo.api.exceptions.BadRequestException;
import com.abiquo.api.services.InfrastructureService;
import com.abiquo.api.util.IRESTBuilder;
import com.abiquo.model.util.ModelTransformer;
import com.abiquo.server.core.infrastructure.Rack;
import com.abiquo.server.core.infrastructure.RackDto;
/*
* THIS CLASS RESOURCE IS USED AS THE DEFAULT ONE TO DEVELOP THE REST AND
* FOR THIS REASON IS OVER-COMMENTED AND DOESN'T HAVE JAVADOC! PLEASE DON'T COPY-PASTE ALL OF THIS
* COMMENTS BECAUSE IS WILL BE SO UGLY TO MAINTAIN THE CODE IN THE API!
*
*/
@Parent(RacksResource.class)
@Path(RackResource.RACK_PARAM)
@Controller
public class RackResource extends AbstractResource
{
// Define the static variables that represent the URI and the PARAM.
public static final String RACK = "rack";
public static final String RACK_PARAM = "{" + RACK + "}";
public static final String RACK_ACTION_LOGICSERVERS_ASSOCIATE = "logicservers/associate";
public static final String RACK_ACTION_LOGICSERVERS_DISSOCIATE = "logicservers/dissociate";
public static final String RACK_ACTION_LOGICSERVERS = "logicservers";
public static final String RACK_ACTION_LOGICSERVERS_DELETE = "logicservers/delete";
public static final String RACK_ACTION_LOGICSERVERS_CLONE = "logicservers/clone";
public static final String RACK_ACTION_ORGANIZATIONS = "organizations";
public static final String RACK_ACTION_FSM = "fsm";
public static final String RACK_ACTION_LOGICSERVERS_TEMPLATES = "lstemplates";
public static final String RACK_ACTION_LOGICSERVERS_ASSOCIATE_TEMPLATE =
"logicservers/assoctemplate";
public static final String RACK_ACTION_LOGICSERVERS_ASSOCIATE_CLONE = "logicservers/assocclone";
public static final String RACK_ACTION_LOGICSERVERS_ASSOCIATE_REL = "ls-associate";
public static final String RACK_ACTION_LOGICSERVERS_DISSOCIATE_REL = "ls-dissociate";
public static final String RACK_ACTION_LOGICSERVERS_REL = "logicservers";
public static final String RACK_ACTION_LOGICSERVERS_DELETE_REL = "ls-delete";
public static final String RACK_ACTION_LOGICSERVERS_CLONE_REL = "ls-clone";
public static final String RACK_ACTION_ORGANIZATIONS_REL = "organizations";
public static final String RACK_ACTION_LOGICSERVERS_TEMPLATES_REL = "ls-templates";
public static final String RACK_ACTION_FSM_REL = "fsm";
public static final String RACK_ACTION_LOGICSERVERS_ASSOCIATE_TEMPLATE_REL =
"ls-associatetemplate";
public static final String RACK_ACTION_LOGICSERVERS_ASSOCIATE_CLONE_REL = "ls-associateclone";
// Define its service. It should only have ONE
@Autowired
private InfrastructureService service;
/**
* Returns a rack
*
* @title Retrieve a Rack
* @param datacenterId identifier of the datacenter
* @param rackId identifier of the rack
* @param restBuilder a Context-injected object to create the links of the Dto
* @return a {RackDto} object with the recuested rack
* @throws Exception
*/
// Get the Rack. Please note the method annotations to check the parameters can not be null
// nor lesser than 1. You don't have to do anything with it. Only declare it. A custom handler
// previous to this call is the responsible of manage it.
@GET
@Produces(RackDto.MEDIA_TYPE)
public RackDto getRack(
@PathParam(DatacenterResource.DATACENTER) @NotNull @Min(1) final Integer datacenterId,
@PathParam(RACK) @NotNull @Min(1) final Integer rackId,
@Context final IRESTBuilder restBuilder) throws Exception
{
// Receive the Rack and convert it as RackDto in the 'createTransferObject' method. That's
// enough!
Rack rack = service.getRack(datacenterId, rackId);
return createTransferObject(rack, restBuilder);
}
/**
* Modifies a rack
*
* @title Update an existing Rack
* @param datacenterId identifier of the datacenter
* @param rackId identifier of the rack
* @param rackDto rack to modify
* @param restBuilder a Context-injected object to create the links of the Dto
* @return a {rackDto} object with the modified rack
* @throws Exception
*/
// Modify the Rack. Please note the method annotations to check the parameters can not be null
// nor lesser than 1. You don't have to do anything with it. Only declare it. A custom handler
// previous to this call is the responsible of manage it. Please note the entity Rack does not
// have any constraint. Constraints inside the entity are checked later.
@PUT
@Consumes(RackDto.MEDIA_TYPE)
@Produces(RackDto.MEDIA_TYPE)
public RackDto modifyRack(
@PathParam(DatacenterResource.DATACENTER) @NotNull @Min(1) final Integer datacenterId,
@PathParam(RACK) @NotNull @Min(1) final Integer rackId, final RackDto rackDto,
@Context final IRESTBuilder restBuilder) throws Exception
{
if (rackDto.getId() == null)
{
throw new BadRequestException(APIError.REQUIRED_ID);
}
// Check the parameter id of the rack has the same id than the rackId.
if (!rackDto.getId().equals(rackId))
{
// Throw a BadRequestException!. Please, when you add a new APIError, execute the main
// process in the class {@link APIError} and copy-paste the output at the wiki page:
// http://wiki.abiquo.com/display/ABI{XX}/API+Error+Code+List where XX is the current
// confluence space.
throw new BadRequestException(APIError.INCOHERENT_IDS);
}
// Create the peristence object from the Dto, pass it to modify, and return back the
// modified entity. That's important for one reason: imagine an entity that doesn't allow to
// modify all of its attributes.
// we need to create a feedback to tell the API Client that some fields have not been
// changed even the response is 200OK. So we don't return the same entity that we have
// received.
Rack rack = createPersistenceObject(rackDto);
// Pass the whole hierarchy ids at the service!
rack = service.modifyRack(datacenterId, rackId, rack);
return createTransferObject(rack, restBuilder);
}
/**
* Deletes a rack
*
* @title Delete a Rack
* @param datacenterId identifier of the datacenter
* @param rackId indentifier of the rack
* @param force boolean to force cascade deletion
*/
// Get the Rack. Please note the method annotations to check the parameters can not be null
// nor lesser than 1. You don't have to do anything with it. Only declare it. A custom handler
// previous to this call is the responsible of manage it.
@DELETE
public void deleteRack(
@PathParam(DatacenterResource.DATACENTER) @NotNull @Min(1) final Integer datacenterId,
@PathParam(RACK) @NotNull @Min(1) final Integer rackId,
@QueryParam("force") final boolean force)
{
// Pass the whole hierarchy ids at the service to retive the rack and remove it.
Rack rack = service.getRack(datacenterId, rackId);
service.removeRack(rack, force);
}
// Create the transfer object. ModelTransformer do the dirty work. You should only
// create custom links depending on the entity.
public static RackDto createTransferObject(final Rack rack, final IRESTBuilder restBuilder)
throws Exception
{
RackDto dto = ModelTransformer.transportFromPersistence(RackDto.class, rack);
// Add the links.
dto.addLinks(restBuilder.buildRackLinks(rack.getDatacenter().getId(), dto));
return dto;
}
// Create the persistence object.
public static Rack createPersistenceObject(final RackDto rack) throws Exception
{
return ModelTransformer.persistenceFromTransport(Rack.class, rack);
}
}