org.opentestsystem.shared.progman.rest.AssetGroupController.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.shared.progman.rest.AssetGroupController.java

Source

/*******************************************************************************
 * Educational Online Test Delivery System
 * Copyright (c) 2013 American Institutes for Research
 * 
 * Distributed under the AIR Open Source License, Version 1.0
 * See accompanying file AIR-License-1_0.txt or at
 * http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf
 ******************************************************************************/
package org.opentestsystem.shared.progman.rest;

import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.opentestsystem.shared.exception.LocalizedException;
import org.opentestsystem.shared.exception.RestException;
import org.opentestsystem.shared.progman.domain.Asset;
import org.opentestsystem.shared.progman.domain.Asset.AssetType;
import org.opentestsystem.shared.progman.domain.AssetGroup;
import org.opentestsystem.shared.progman.domain.Tenant;
import org.opentestsystem.shared.progman.domain.TenantChain;
import org.opentestsystem.shared.progman.domain.TenantType;
import org.opentestsystem.shared.progman.domain.search.AssetGroupSearchRequest;
import org.opentestsystem.shared.progman.service.AssetGroupService;
import org.opentestsystem.shared.progman.service.TenantChainService;
import org.opentestsystem.shared.search.domain.SearchResponse;
import org.opentestsystem.shared.web.AbstractRestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

@Controller
@SuppressWarnings("PMD.ExcessiveImports")
public class AssetGroupController extends AbstractRestController {

    private static final int TOTAL_COUNT_THRESHOLD = 0;

    @Autowired
    private AssetGroupService assetGroupService;

    @Autowired
    private TenantChainService tenantChainService;

    @Value("${pm.rest.service.endpoint}")
    private transient String pmBaseUrl;

    /**
     * Can query the /assetGroup endpoint with query parameters in a querystring. or with JSON. Valid parameters are:
     * componentName or tenantId
     * 
     * @param request HttpServletRequest
     * @return SearchResponse<AssetGroup>
     */
    @RequestMapping(value = "/assetGroup", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @Secured({ "ROLE_Progman Read" })
    @ResponseBody
    public SearchResponse<AssetGroup> searchAssetGroup(final HttpServletRequest request) {

        AssetGroupSearchRequest searchRequest = new AssetGroupSearchRequest(request.getParameterMap());
        SearchResponse<AssetGroup> searchResponse;
        if (searchRequest.isValid()) {
            searchResponse = assetGroupService.searchAssetGroups(searchRequest);
        } else {
            throw new RestException("assetGroup.search.invalidSearchCriteria");
        }

        return searchResponse;
    }

    /**
     * Retrieve the /assetGroup with query parameter or with JSON (assetGroupId).
     * 
     * @param request
     *        HttpServletRequest
     * @return AssetGroup
     */
    @RequestMapping(value = "/assetGroup/{assetGroupId}", method = RequestMethod.GET, produces = {
            MediaType.APPLICATION_JSON_VALUE })
    @Secured({ "ROLE_Progman Read" })
    @ResponseBody
    public AssetGroup getAssetGroup(@PathVariable final String assetGroupId) {
        AssetGroup ret = assetGroupService.getAssetGroup(assetGroupId);
        populateBaseUrlForAssets(ret);
        return ret;
    }

    /**
     * Creates AssetGroup.
     * 
     * @param assetGroup
     *        to be saved.
     * @param response
     *        HttpServletResponse.
     * @return AssetGroup newly created assetGroup object.
     */
    @ResponseStatus(HttpStatus.CREATED)
    @RequestMapping(value = "/assetGroup", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = {
            MediaType.APPLICATION_JSON_VALUE })
    @Secured({ "ROLE_Progman Admin" })
    @ResponseBody
    public AssetGroup createAssetGroup(@RequestBody @Valid final AssetGroup assetGroup,
            final HttpServletResponse response) {
        if (StringUtils.isNotEmpty(assetGroup.getId())) {
            throw new LocalizedException("assetGroup.exists", new String[] { assetGroup.getId() });
        }

        AssetGroup savedAssetGroup = assetGroupService.saveAssetGroup(assetGroup);
        response.setHeader("Location", savedAssetGroup.getUrl());
        return savedAssetGroup;
    }

    /**
     * Updates AssetGroup.
     * 
     * @param assetGroup
     *        to be saved.
     * @param response
     *        HttpServletResponse.
     * @return AssetGroup newly created assetGroup object.
     */
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/assetGroup/{assetGroupId}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, produces = {
            MediaType.APPLICATION_JSON_VALUE })
    @Secured({ "ROLE_Progman Admin" })
    @ResponseBody
    public AssetGroup updateAssetGroup(@PathVariable final String assetGroupId,
            @RequestBody @Valid final AssetGroup assetGroup, final HttpServletResponse response) {
        if (assetGroup == null || StringUtils.isEmpty(assetGroup.getId())
                || !assetGroupId.equals(assetGroup.getId())) {
            throw new LocalizedException("assetGroup.invalid.id");
        }

        AssetGroup savedAssetGroup = assetGroupService.saveAssetGroup(assetGroup);
        response.setHeader("Location", savedAssetGroup.getUrl());
        return savedAssetGroup;
    }

    /**
     * Deletes AssetGroup.
     * 
     * @param assetGroup
     *        to be deleted.
     * @param response
     *        HttpServletResponse.
     * @return AssetGroup newly created assetGroup object.
     */
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @RequestMapping(value = "/assetGroup/remove/{assetGroupId}", method = RequestMethod.DELETE)
    @Secured({ "ROLE_Progman Admin" })
    public void deleteAssetGroup(@PathVariable final String assetGroupId, final HttpServletResponse response) {
        assetGroupService.deleteAssetGroup(assetGroupId);
    }

    /**
     * We want to do an Asset Group Search starting from the first result in the tenant chain
     * until we find a Tenant that returns assets.
     * This will get the Tenant Chain and walk the chain until it finds a asset group.
     * The chain is walked in reverse hierarchical order... so institution, district, district group, state, state group
     */
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/skinnableAssets/{componentName}", method = RequestMethod.GET, produces = {
            MediaType.APPLICATION_JSON_VALUE })
    @Secured({ "ROLE_Progman Read" })
    @ResponseBody
    public AssetGroup getAssetGroupForUser(@PathVariable final String componentName,
            final HttpServletRequest request, final HttpServletResponse response) {

        Map<TenantType, String> typeAndValues = TenantType.findTypes(request.getParameterMap());
        TenantChain chain = tenantChainService.findTenantChain(typeAndValues);
        Set<Tenant> tenants = chain.getTenants();

        AssetGroup group = null;
        if (tenants != null) {
            // The chain's tenants are inherently ordered from most qualified/specific to least (institution...consortium)
            for (Tenant myTenant : tenants) {
                SearchResponse<AssetGroup> groups = assetGroupService
                        .searchAssetGroups(buildAssetGroupSearchRequest(componentName, myTenant.getId()));
                if (groups.getReturnCount() > TOTAL_COUNT_THRESHOLD) {
                    group = groups.getSearchResults().get(0);
                    if (group != null) {
                        // once a tenant is found for the given component drop out
                        break;
                    }
                }
            }
        }
        if (group != null) {
            response.setHeader("Location", group.getUrl());
            populateBaseUrlForAssets(group);
        }
        return group;

    }

    private AssetGroupSearchRequest buildAssetGroupSearchRequest(final String componentName,
            final String tenantId) {
        Map<String, String[]> groupSearch = ImmutableMap.of(AssetGroupSearchRequest.SEARCH_KEY_COMPONENT_NAME,
                Iterables.toArray(Lists.newArrayList(componentName), String.class),
                AssetGroupSearchRequest.SEARCH_KEY_TENANT_ID,
                Iterables.toArray(Lists.newArrayList(tenantId), String.class));
        return new AssetGroupSearchRequest(groupSearch);
    }

    private void populateBaseUrlForAssets(final AssetGroup group) {
        if (group != null && group.getAssets() != null) {
            for (Asset asset : group.getAssets()) {
                if (AssetType.PROPERTY.equals(asset.getType())) {
                    asset.setBasePath("");
                } else {
                    asset.setBasePath(pmBaseUrl);
                }
            }
        }
    }
}