org.squashtest.tm.web.internal.controller.customfield.CustomFieldController.java Source code

Java tutorial

Introduction

Here is the source code for org.squashtest.tm.web.internal.controller.customfield.CustomFieldController.java

Source

/**
 *     This file is part of the Squashtest platform.
 *     Copyright (C) 2010 - 2016 Henix, henix.fr
 *
 *     See the NOTICE file distributed with this work for additional
 *     information regarding copyright ownership.
 *
 *     This 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, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     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 for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with this software.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.squashtest.tm.web.internal.controller.customfield;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.inject.Inject;
import javax.validation.Valid;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.util.HtmlUtils;
import org.squashtest.tm.core.foundation.collection.PagedCollectionHolder;
import org.squashtest.tm.core.foundation.collection.Pagings;
import org.squashtest.tm.core.foundation.collection.SinglePageCollectionHolder;
import org.squashtest.tm.domain.customfield.CustomField;
import org.squashtest.tm.domain.customfield.CustomFieldOption;
import org.squashtest.tm.domain.customfield.InputType;
import org.squashtest.tm.domain.customfield.SingleSelectField;
import org.squashtest.tm.domain.project.GenericProject;
import org.squashtest.tm.exception.DomainException;
import org.squashtest.tm.service.customfield.CustomFieldManagerService;
import org.squashtest.tm.service.project.ProjectFinder;
import org.squashtest.tm.web.internal.controller.RequestParams;
import org.squashtest.tm.web.internal.helper.JEditablePostParams;
import org.squashtest.tm.web.internal.model.datatable.DataTableDrawParameters;
import org.squashtest.tm.web.internal.model.datatable.DataTableModel;
import org.squashtest.tm.web.internal.model.datatable.DataTableModelBuilder;
import org.squashtest.tm.web.internal.model.datatable.DataTableModelConstants;
import org.squashtest.tm.web.internal.model.jquery.RenameModel;

/**
 * Controller for the Custom Fields resources.
 *
 * @author Gregory Fouquet
 *
 */
@Controller
@RequestMapping("/custom-fields")
public class CustomFieldController {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomFieldController.class);

    private static final String CUSTOM_FIELD = "customField";

    @Inject
    private CustomFieldManagerService customFieldManager;

    @Inject
    private ProjectFinder projectFinder;

    @Inject
    private MessageSource messageSource;

    @ModelAttribute("customFieldOptionsPageSize")
    public long populateCustomFieldsPageSize() {
        return Pagings.DEFAULT_PAGING.getPageSize();
    }

    @RequestMapping(value = "/new", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    @ResponseBody
    public void createNew(@RequestBody NewCustomField field) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Will create cutsom field {}", ToStringBuilder.reflectionToString(field));
        }
        customFieldManager.persist(field.createTransientEntity());
    }

    /**
     * Shows the custom field modification page.
     *
     * @param customFieldId
     *            the id of the custom field to show
     * @param model
     * @return
     */
    @RequestMapping(value = "/{customFieldId}", method = RequestMethod.GET)
    public String showCustomFieldModificationPage(@PathVariable Long customFieldId, Model model) {
        CustomField customField = customFieldManager.findById(customFieldId);

        if (customField.getInputType() == InputType.DROPDOWN_LIST) {
            SingleSelectField cuf = customFieldManager.findSingleSelectFieldById(customFieldId);
            model.addAttribute(CUSTOM_FIELD, cuf);
        } else {
            model.addAttribute(CUSTOM_FIELD, customField);
        }

        return "custom-field-modification.html";
    }

    @RequestMapping(value = "/name/{name}", params = "id")
    @ResponseBody
    public Object getIdByName(@PathVariable String name) {
        CustomField field = customFieldManager.findByName(name);

        if (field != null) {
            Map<String, Long> res = new HashMap<>(1);
            res.put("id", field.getId());
            return res;
        } else {
            return null;
        }
    }

    /**
     * Changes the label of the concerned custom field
     *
     * @param customFieldId
     *            the id of the concerned custom field
     * @param label
     *            the new label
     * @return
     */
    @RequestMapping(value = "/{customFieldId}", method = RequestMethod.POST, params = { "id=cuf-label",
            JEditablePostParams.VALUE }, produces = "text/plain;charset=UTF-8")
    @ResponseBody
    public String changeLabel(@PathVariable long customFieldId,
            @RequestParam(JEditablePostParams.VALUE) String label) {
        customFieldManager.changeLabel(customFieldId, label);
        return HtmlUtils.htmlEscape(label);
    }

    /**
     * Changes the code of the concerned custom field
     *
     * @param customFieldId
     *            the id of the concerned custom field
     * @param label
     *            the new code
     * @return
     */
    @RequestMapping(value = "/{customFieldId}", method = RequestMethod.POST, params = { "id=cuf-code",
            JEditablePostParams.VALUE })
    @ResponseBody
    public String changeCode(@PathVariable long customFieldId,
            @RequestParam(JEditablePostParams.VALUE) String code) {
        customFieldManager.changeCode(customFieldId, code);
        return code;
    }

    /**
     * Changes the name of the concerned custom field
     *
     * @param customFieldId
     *            the id of the concerned custom field
     * @param name
     *            the new name
     * @return
     */
    @RequestMapping(value = "/{customFieldId}/name", method = RequestMethod.POST, params = {
            JEditablePostParams.VALUE })
    @ResponseBody
    public Object changeName(@PathVariable long customFieldId,
            @RequestParam(JEditablePostParams.VALUE) String name) {
        customFieldManager.changeName(customFieldId, name);
        return new RenameModel(name);
    }

    /**
     * Changes the whether the custom-field is optional or not.
     *
     * @param customFieldId
     *            the id of the concerned custom field
     * @param optional
     *            : true if the custom field is optional
     * @return
     */
    @RequestMapping(value = "/{customFieldId}/optional", method = RequestMethod.POST, params = {
            JEditablePostParams.VALUE })
    @ResponseBody
    public boolean changeOptional(@PathVariable long customFieldId,
            @RequestParam(JEditablePostParams.VALUE) Boolean optional) {
        customFieldManager.changeOptional(customFieldId, optional);
        return optional;
    }

    /**
     * Changes the default value of the concerned custom-field
     *
     * @param customFieldId
     *            : the id of concerned custom-field
     * @param defaultValue
     *            : the new default-value for the custom-field
     * @param locale
     *            : the browser's locale
     *
     * @return defaultValue
     */
    @RequestMapping(value = "/{customFieldId}", method = RequestMethod.POST, params = { "id=cuf-default-value",
            JEditablePostParams.VALUE })
    @ResponseBody
    public String changeDefaultValueJedit(@PathVariable long customFieldId,
            @RequestParam(JEditablePostParams.VALUE) String defaultValue, Locale locale) {
        customFieldManager.changeDefaultValue(customFieldId, defaultValue);
        CustomField customField = customFieldManager.findById(customFieldId);
        String toReturn = defaultValue;
        if (customField.getInputType() == InputType.CHECKBOX) {
            toReturn = messageSource.getMessage("label." + defaultValue, null, locale);
        }
        return toReturn;
    }

    /**
     * Changes the default value of the concerned custom-field
     *
     * @param customFieldId
     *            : the id of concerned custom-field
     * @param defaultValue
     *            : the new default-value for the custom-field
     */
    @RequestMapping(value = "/{customFieldId}/defaultValue", method = RequestMethod.POST, params = {
            JEditablePostParams.VALUE })
    @ResponseBody
    public String changeDefaultValue(@PathVariable long customFieldId,
            @RequestParam(JEditablePostParams.VALUE) String defaultValue) {
        customFieldManager.changeDefaultValue(customFieldId, defaultValue);
        return defaultValue;
    }

    /**
     * Changes the label of the concerned custom-field's option
     *
     * @param customFieldId
     *            : the id of the concerned custom-field
     * @param optionLabel
     *            : the label of the concerned custom-field's option
     * @param newLabel
     *            : the new label for the concerned custom-field's option
     * @return
     */
    @RequestMapping(value = "/{customFieldId}/options/{optionLabel}/label", method = RequestMethod.POST, params = {
            JEditablePostParams.VALUE })
    @ResponseBody
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    public void changeOptionLabel(@PathVariable long customFieldId, @PathVariable String optionLabel,
            @RequestParam(JEditablePostParams.VALUE) String newLabel) {
        try {
            customFieldManager.changeOptionLabel(customFieldId, optionLabel, newLabel);
        } catch (DomainException e) {
            e.setObjectName("rename-cuf-option");
            throw e;
        }
    }

    /**
     * Changes the code of the concerned custom-field's option
     *
     * @param customFieldId
     *            : the id of the concerned custom-field
     * @param optionCode
     *            : the label of the concerned custom-field's option
     * @param newCode
     *            : the new code for the concerned custom-field's option
     * @return
     */
    @RequestMapping(value = "/{customFieldId}/options/{optionLabel}/code", method = RequestMethod.POST, params = {
            JEditablePostParams.VALUE })
    @ResponseBody
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    public void changeOptionCode(@PathVariable long customFieldId, @PathVariable String optionLabel,
            @RequestParam(JEditablePostParams.VALUE) String newCode) {
        try {
            customFieldManager.changeOptionCode(customFieldId, optionLabel, newCode);
        } catch (DomainException e) {
            e.setObjectName("change-cuf-option");
            throw e;
        }
    }

    /**
     * Adds an option to the concerned custom-field
     *
     * @param customFieldId
     *            : the id of the concerned custom-field
     * @param option
     *            : the new option
     */
    @RequestMapping(value = "/{customFieldId}/options/new", method = RequestMethod.POST)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    public void addOption(@PathVariable long customFieldId,
            @Valid @ModelAttribute("new-cuf-option") CustomFieldOption option) {
        try {
            customFieldManager.addOption(customFieldId, option);
        } catch (DomainException e) {
            e.setObjectName("new-cuf-option");
            throw e;
        }
    }

    /**
     * Remove a customField's option
     *
     * @param customFieldId
     *            : the id of the concerned custom-field
     * @param optionLabel
     *            : the label of the option to remove
     */
    @RequestMapping(value = "/{customFieldId}/options/{optionLabel}", method = RequestMethod.DELETE)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    public void removeOption(@PathVariable long customFieldId, @PathVariable String optionLabel) {
        customFieldManager.removeOption(customFieldId, optionLabel);
    }

    /**
     * Return the DataTableModel to display the table of all custom field's option.
     *
     * @param customFieldId
     *            : the id of the concerned custom field
     * @param params
     *            the {@link DataTableDrawParameters} for the custom field's options table
     * @return the {@link DataTableModel} with organized {@link CustomFieldOption} infos.
     */
    @RequestMapping(value = "/{customFieldId}/options", method = RequestMethod.GET, params = RequestParams.S_ECHO_PARAM)
    @ResponseBody
    public DataTableModel getCustomFieldsTableModel(@PathVariable long customFieldId,
            final DataTableDrawParameters params) {
        SingleSelectField customField = customFieldManager.findSingleSelectFieldById(customFieldId);
        List<CustomFieldOption> customFieldOptions = customField.getOptions();
        PagedCollectionHolder<List<CustomFieldOption>> holder = new SinglePageCollectionHolder<>(
                customFieldOptions);
        return new CustomFieldOptionsDataTableModelHelper(customField).buildDataModel(holder, params.getsEcho());
    }

    /**
     * Will help to create the {@link DataTableModel} to fill the data-table of custom field's options
     *
     */
    private static final class CustomFieldOptionsDataTableModelHelper
            extends DataTableModelBuilder<CustomFieldOption> {

        private CustomField customField;

        private CustomFieldOptionsDataTableModelHelper(CustomField customField) {
            this.customField = customField;
        }

        @Override
        public Map<String, Object> buildItemData(CustomFieldOption item) {

            Map<String, Object> res = new HashMap<>();
            String checked = " ";
            if (customField.getDefaultValue().equals(item.getLabel())) {
                checked = " checked='checked' ";
            }
            res.put(DataTableModelConstants.DEFAULT_ENTITY_INDEX_KEY, getCurrentIndex());
            res.put("opt-label", item.getLabel());
            res.put("opt-code", item.getCode());
            res.put("opt-default",
                    "<input type='checkbox' name='default' value='" + item.getLabel() + "'" + checked + "/>");
            res.put(DataTableModelConstants.DEFAULT_EMPTY_DELETE_HOLDER_KEY, " ");
            return res;
        }
    }

    /**
     * Will change custom field's options positions.
     *
     * @param customFieldId
     *            : the id of the concerned CustomField.
     * @param newIndex
     *            : the lowest index for the moved selection
     * @param optionsLabels
     *            : the labels of the moved options
     */
    @RequestMapping(value = "/{customFieldId}/options/positions", method = RequestMethod.POST, params = {
            "itemIds[]", "newIndex" })
    @ResponseBody
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    public void changeOptionsPositions(@PathVariable long customFieldId, @RequestParam int newIndex,
            @RequestParam("itemIds[]") List<String> optionsLabels) {
        customFieldManager.changeOptionsPositions(customFieldId, newIndex, optionsLabels);
    }

    @ResponseBody
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @RequestMapping(value = "/{customFieldIds}", method = RequestMethod.DELETE)
    public void deleteCustomField(@PathVariable("customFieldIds") List<Long> customFieldIds) {
        customFieldManager.deleteCustomField(customFieldIds);
    }

    @RequestMapping(value = "/tags/{boundEntity}", method = RequestMethod.GET)
    @ResponseBody
    public List<String> getPossibleTagValues(@PathVariable("boundEntity") String boundEntity) {

        List<Long> projectIds = (List<Long>) CollectionUtils.collect(projectFinder.findAllOrderedByName(),
                new Transformer() {

                    @Override
                    public Object transform(Object input) {
                        return ((GenericProject) input).getId();
                    }
                });

        return customFieldManager.getAvailableTagsForEntity(boundEntity, projectIds);
    }
}