/** * Copyright 2014 Comcast Cable Communications Management, LLC * * This file is part of CATS. * * CATS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CATS 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CATS. If not, see <http://www.gnu.org/licenses/>. */ package com.comcast.cats.domain.service; import java.util.ArrayList; import java.util.List; import javax.inject.Named; import org.springframework.http.HttpStatus; import com.comcast.cats.domain.Allocation; import com.comcast.cats.domain.AllocationCategory; import com.comcast.cats.domain.SettopDesc; import com.comcast.cats.domain.exception.AllocationInstantiationException; import com.comcast.cats.domain.exception.AllocationNotFoundException; import com.comcast.cats.domain.exception.DomainServiceException; import com.comcast.cats.domain.exception.SameUserAllocationException; import com.comcast.cats.domain.util.AssertUtil; import com.comcast.cats.domain.util.CommonUtil; /** * Implementation of {@link AllocationService}. * * @author subinsugunan * */ @Named public class AllocationServiceImpl extends DomainServiceImpl< Allocation > implements AllocationService { /** * Try to allocate a device for use with a specified componentId The * duration value,authtoken,allocation category is taken from the cats * properties. The value can be set by setting the value cats.lock.duration * in cats.props If the device is currently allocated the allocation should * fail. * * @param componentId * - Id of the {@linkplain SettopDesc} * @return The {@linkplain Allocation} * @throws AllocationInstantiationException */ @Override public Allocation createByComponentId( String componentId ) throws AllocationInstantiationException { return createByComponentId( componentId, properties.getAllocationDuration(), properties.getAuthToken(), properties.getAllocationCategory() ); } /** * Try to allocate a device for use with a specified componentId and for a * given duration. If the device is currently allocated the allocation * should fail. * * @param componentId * - Id of the {@linkplain SettopDesc} * @param duration * - {@linkplain Allocation} duration * @return The {@linkplain Allocation} * @throws AllocationInstantiationException */ @Override public Allocation createByComponentId( String componentId, Integer duration ) throws AllocationInstantiationException { return createByComponentId( componentId, duration, properties.getAuthToken(), properties.getAllocationCategory() ); } /** * Try to allocate a device for use with a specified componentId and for a * given duration with auth token. If the device is currently allocated the * allocation should fail. * * @param componentId * - Id of the {@linkplain SettopDesc} * @param duration * - {@linkplain Allocation} duration * @param authToken * @return The {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public Allocation createByComponentId( String componentId, Integer duration, String authToken ) throws AllocationInstantiationException { return createByComponentId( componentId, duration, authToken, properties.getAllocationCategory() ); } /** * Try to allocate a device for use with a specified componentId and for a * given duration with auth token and allocationCategory. If the device is * currently allocated the allocation should fail. * * @param componentId * - Id of the {@linkplain SettopDesc} * @param duration * - {@linkplain Allocation} duration * @param authToken * @param allocationCategory * {@linkplain AllocationCategory} * @return The {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public Allocation createByComponentId( String componentId, Integer duration, String authToken, AllocationCategory allocationCategory ) throws AllocationInstantiationException { return createByComponentId( componentId, duration, authToken, allocationCategory, false ); } private Allocation createByComponentId( String componentId, Integer duration, String authToken, AllocationCategory allocationCategory, boolean reacquireFlag ) throws AllocationInstantiationException { AssertUtil.isNullOrEmpty( componentId, "Cannot create Allocation. componentId cannot be null or empty" ); String requestUrl = getBaseUrl( ALLOCATION ) + COMPONENT + BACK_SLASH + ALLOCATE + CommonUtil.getNameValuePair( getParamMapByIdDurationAndToken( componentId, duration, authToken, allocationCategory, reacquireFlag ) ); Allocation allocation = null; try { allocation = postForDomainObject( requestUrl, Allocation.class ); } catch ( DomainServiceException e ) { Integer errorCode = e.getErrorCode(); HttpStatus statusCode = HttpStatus.valueOf( errorCode ); // NOT acceptable is thrown in the case where the same user has // acquired the lock if ( statusCode == HttpStatus.NOT_ACCEPTABLE ) { throw new SameUserAllocationException( e.getMessage() ); } else { throw new AllocationInstantiationException( e.getMessage() ); } } return allocation; } /** * Try to reacquire a device for use with a specified componentId If the * device is currently not allocated by the same user,this call will fail. * * @param componentId * - Id of the {@linkplain SettopDesc} * @return The {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public Allocation reacquireByComponentId( String componentId ) throws AllocationInstantiationException { return createByComponentId( componentId, REACQUIRE_DURATION, properties.getAuthToken(), properties.getAllocationCategory(), true ); } /** * Try to reacquire a device for use with a specified componentId If the * device is currently not allocated by the same user,this call will fail. * * @param componentId * - Id of the {@linkplain SettopDesc} * @param authToken * @param allocationCategory * {@linkplain AllocationCategory} * @return The {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public Allocation reacquireByComponentId( String componentId, String authToken, AllocationCategory allocationCategory ) throws AllocationInstantiationException { return createByComponentId( componentId, REACQUIRE_DURATION, authToken, allocationCategory, true ); } /** * Finds all active allocations (Not expired and status is 'Active') * * @return A {@linkplain List} of {@linkplain Allocation} */ @Override public List< Allocation > findActive() { return findActive( 0, 0 ); } /** * Finds all active allocations (Not expired and status is 'Active') * * @param offset * - The start position * @param count * - The max result * @return A {@linkplain List} of {@linkplain Allocation} */ @Override public List< Allocation > findActive( Integer offset, Integer count ) { String requestUrl = getBaseUrl( MDS + BACK_SLASH + ALLOCATIONS ) + ACTIVE + BACK_SLASH + offset + BACK_SLASH + count; List< Allocation > activeAllocations = new ArrayList< Allocation >(); try { activeAllocations = getResponseAsDomainList( requestUrl, Allocation.class ); } catch ( DomainServiceException e ) { logger.error( "Failed to retrieve active allocations list. " + e.getMessage() ); } return activeAllocations; } /** * Finds an allocation based on the macId specified. * * @param componentId * - The id of the {@linkplain SettopDesc} * @return The {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public Allocation findByComponentId( String componentId ) throws AllocationNotFoundException { AssertUtil.isNullOrEmpty( componentId, "Cannot search Allocation. componentId cannot be null" ); String requestUrl = getBaseUrl( ALLOCATION ) + COMPONENT + BACK_SLASH + SHOW + CommonUtil.getNameValuePair( getParamMapByIdAndToken( componentId ) ); Allocation allocation = null; try { allocation = getResponseAsDomain( requestUrl, Allocation.class ); } catch ( DomainServiceException e ) { throw new AllocationNotFoundException( e.getMessage() ); } return allocation; } /** * Check to see if the {@linkplain Allocation} is valid. * * @param allocationId * - Id of the {@linkplain Allocation} * @return True if the {@linkplain Allocation} is valid, False otherwise */ @Override public Boolean verify( String allocationId ) { return verify( allocationId, properties.getAuthToken() ); } /** * Check to see if the {@linkplain Allocation} is valid. * * @param allocationId * - Id of the {@linkplain Allocation} * @param authToken * @return True if the {@linkplain Allocation} is valid, False otherwise */ @Override public Boolean verify( String allocationId, String authToken ) { AssertUtil.isNullOrEmpty( allocationId, "Cannot verify Allocation. allocationId cannot be null" ); String requestUrl = getBaseUrl( ALLOCATION ) + VERIFY + CommonUtil.getNameValuePair( getParamMapByIdAndToken( allocationId, authToken ) ); Boolean status = false; try { status = getResponseAsBoolean( requestUrl ); } catch ( DomainServiceException e ) { logger.warn( "Verify allocation thrown exception: " + e.getMessage() ); } return status; } /** * Update the specified allocation by extending the end time from now by the * specified number of minutes. The extension duration is taken from * cats.props. * * @param allocationId * - Id of the {@linkplain Allocation} * @return The updated {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public Allocation update( String allocationId ) throws AllocationNotFoundException { return update( allocationId, properties.getAllocationDuration(), properties.getAuthToken() ); } /** * Update the specified allocation by extending the end time from now by the * specified number of minutes. * * @param allocationId * - Id of the {@linkplain Allocation} * @param duration * - This will be added to the current system time to to set the * new end date for the {@linkplain Allocation} * @return The updated {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public Allocation update( String allocationId, Integer minutes ) throws AllocationNotFoundException { return update( allocationId, minutes, properties.getAuthToken() ); } /** * Update the specified allocation by extending the end time from now by the * specified number of minutes and authToken. * * @param allocationId * - Id of the {@linkplain Allocation} * @param minutes * - This will be added to the current system time to to set the * new end date for the {@linkplain Allocation} * @param authToken * @return The updated {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public Allocation update( String allocationId, Integer minutes, String authToken ) throws AllocationNotFoundException { AssertUtil.isNullOrEmpty( allocationId, "Cannot update Allocation. allocationId cannot be null" ); String requestUrl = getBaseUrl( ALLOCATION ) + UPDATE + CommonUtil.getNameValuePair( getParamMapByIdDurationAndToken( allocationId, minutes, authToken ) ); Allocation allocation = null; try { allocation = postForDomainObject( requestUrl, Allocation.class ); } catch ( DomainServiceException e ) { throw new AllocationNotFoundException( e.getMessage() ); } return allocation; } /** * Release the allocation. * * @param allocation * - The {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public void release( Allocation allocation ) throws AllocationNotFoundException { AssertUtil.isNull( allocation, "Cannot release Allocation. allocation cannot be null" ); AssertUtil.isNullOrEmpty( allocation.getId(), "Cannot release Allocation. allocationId cannot be null" ); release( allocation.getId() ); } /** * Release the allocation based on the allocationId specified. * * @param allocationId * - Id of the {@linkplain Allocation} * @throws {@linkplain AllocationInstantiationException} */ @Override public void release( String allocationId ) throws AllocationNotFoundException { release( allocationId, properties.getAuthToken() ); } /** * Release the allocation based on the allocationId specified and authToken. * * @param allocationId * - Id of the {@linkplain Allocation} * @param authToken * @throws {@linkplain AllocationInstantiationException} */ @Override public void release( String allocationId, String authToken ) throws AllocationNotFoundException { AssertUtil.isNullOrEmpty( allocationId, "Cannot release Allocation. allocationId cannot be null" ); String requestUrl = getBaseUrl( ALLOCATION ) + RELEASE + CommonUtil.getNameValuePair( getParamMapByIdAndToken( allocationId, authToken ) ); releaseAllocation( requestUrl ); } /** * Release this allocation based on the macId specified. * * @param componentId * - The id of the {@linkplain SettopDesc} * @throws {@linkplain AllocationInstantiationException} */ @Override public void releaseByComponentId( String componentId ) throws AllocationNotFoundException { AssertUtil.isNullOrEmpty( componentId, "Cannot release Allocation. componentId cannot be null" ); String requestUrl = getBaseUrl( ALLOCATION ) + COMPONENT + BACK_SLASH + RELEASE + CommonUtil.getNameValuePair( getParamMapByIdAndToken( componentId ) ); releaseAllocation( requestUrl ); } private void releaseAllocation( String requestUrl ) throws AllocationNotFoundException { try { put( requestUrl ); } catch ( DomainServiceException e ) { throw new AllocationNotFoundException( e.getMessage() ); } } /** * Finds the count of total active allocations. * * @return The count of active {@linkplain Allocation} */ @Override public Integer countActive() { String requestUrl = getBaseUrl( MDS + BACK_SLASH + ALLOCATIONS ) + ACTIVE + BACK_SLASH + COUNT; Integer count = 0; try { count = getResponseAsNumber( requestUrl ); } catch ( DomainServiceException e ) { logger.error( "Failed to retrieve active allocations count. " + e.getMessage() ); } return count; } }