org.squashtest.tm.web.internal.controller.report.ReportController.java Source code

Java tutorial

Introduction

Here is the source code for org.squashtest.tm.web.internal.controller.report.ReportController.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.report;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.apache.commons.io.IOUtils;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
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.servlet.ModelAndView;
import org.squashtest.tm.api.report.Report;
import org.squashtest.tm.api.report.criteria.Criteria;
import org.squashtest.tm.api.report.form.Input;
import org.squashtest.tm.api.report.form.InputType;
import org.squashtest.tm.api.report.form.OptionInput;
import org.squashtest.tm.api.report.form.RadioButtonsGroup;
import org.squashtest.tm.api.report.form.composite.TagPickerOption;
import org.squashtest.tm.domain.project.GenericProject;
import org.squashtest.tm.domain.project.Project;
import org.squashtest.tm.service.customfield.CustomFieldManagerService;
import org.squashtest.tm.service.project.ProjectFinder;
import org.squashtest.tm.web.internal.helper.JsonHelper;
import org.squashtest.tm.web.internal.model.jquery.FilterModel;
import org.squashtest.tm.web.internal.report.ReportsRegistry;
import org.squashtest.tm.web.internal.report.criteria.ConciseFormToCriteriaConverter;
import org.squashtest.tm.web.internal.report.criteria.FormToCriteriaConverter;

import com.lowagie.text.pdf.codec.Base64;

/**
 * @author Gregory Fouquet
 *
 */
@Controller
@RequestMapping("/reports/{namespace}/{index}")
public class ReportController {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReportController.class);
    @Inject
    private ReportsRegistry reportsRegistry;

    @Inject
    private ProjectFinder projectFinder;

    @Inject
    private CustomFieldManagerService customFieldFinder;

    @Inject
    @Value("${report.criteria.project.multiselect:false}")
    private boolean projectMultiselect;

    /**
     * Populates model and returns the fragment panel showing a report.
     *
     * @param namespace
     *            namespace of the report
     * @param index
     *            0-based index of the report in its namespace
     * @param model
     * @return
     */
    @RequestMapping(value = "/panel", method = RequestMethod.GET)
    public String showReportPanel(@PathVariable String namespace, @PathVariable int index, Model model) {
        populateModelWithReport(namespace, index, model);
        // XXX shouldnt these 2 lines go in populateMWR ? check if "report viewer" works as expected (see
        // showReportViexwer)
        model.addAttribute("projectMultiselect", projectMultiselect);
        model.addAttribute("projectFilterModel", findProjectsModels());
        return "report-panel.html";
    }

    private FilterModel findProjectsModels() {
        List<Project> projects = projectFinder.findAllOrderedByName();
        return new FilterModel(projects);
    }

    private void populateModelWithReport(String namespace, int index, Model model) {
        Report report = reportsRegistry.findReport(namespace, index);
        model.addAttribute("report", report);

        // used for tag picker prefilling.
        populateTagsIfRequired(report, model);

    }

    /**
     * Populates model and returns the full page showing a report.
     *
     * @param namespace
     *            namespace of the report
     * @param index
     *            0-based index of the report in its namespace
     * @param model
     * @return
     */
    @RequestMapping(value = "/viewer", method = RequestMethod.GET)
    public String showReportViewer(@PathVariable String namespace, @PathVariable int index, Model model) {
        populateModelWithReport(namespace, index, model);
        model.addAttribute("hasBackButton", Boolean.TRUE);
        return "report-viewer.html";
    }

    /**
     * Generates report view from a standard post with a data attribute containing a serialized JSON form.
     *
     * @param namespace
     * @param index
     * @param viewIndex
     * @param format
     * @return
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     * @deprecated since #3762 #getReportView should be called by gui
     */
    @Deprecated
    @RequestMapping(value = "/views/{viewIndex}/formats/{format}", method = RequestMethod.GET, params = {
            "parameters" })
    public ModelAndView generateReportViewUsingGet(@PathVariable String namespace, @PathVariable int index,
            @PathVariable int viewIndex, @PathVariable String format, @RequestParam("parameters") String parameters)
            throws JsonParseException, JsonMappingException, IOException {
        Map<String, Object> form = JsonHelper.deserialize(parameters);
        Map<String, Criteria> crit = new FormToCriteriaConverter().convert(form);

        Report report = reportsRegistry.findReport(namespace, index);

        return report.buildModelAndView(viewIndex, format, crit);

    }

    @RequestMapping(value = "/views/{viewIndex}/formats/{format}", method = RequestMethod.GET, params = { "json" })
    public ModelAndView getReportView(@PathVariable String namespace, @PathVariable int index,
            @PathVariable int viewIndex, @PathVariable String format, @RequestParam("json") String parameters)
            throws JsonParseException, JsonMappingException, IOException {
        Map<String, Object> form = JsonHelper.deserialize(parameters);
        Report report = reportsRegistry.findReport(namespace, index);
        List<Project> projects = projectFinder.findAllOrderedByName();
        Map<String, Criteria> crit = new ConciseFormToCriteriaConverter(report, projects).convert(form);

        ModelAndView mav;
        if ("docx".equals(format)) {
            Map<String, Object> model = report.buildModelAndView(viewIndex, format, crit).getModel();
            mav = new ModelAndView("docx.html");
            mav.addObject("model", model.get("data"));
            mav.addObject("html", model.get("html"));
            mav.addObject("fileName", model.get("fileName"));
            mav.addObject("namespace", namespace);
            mav.addObject("index", index);
            mav.addObject("viewIndx", viewIndex);
        } else {
            mav = report.buildModelAndView(viewIndex, format, crit);
        }

        return mav;

    }

    @RequestMapping(value = "/views/{viewIndex}/docxtemplate", method = RequestMethod.GET)
    public void getTemplate(@PathVariable String namespace, @PathVariable int index, @PathVariable int viewIndex,
            HttpServletRequest request, HttpServletResponse response) throws Exception {

        Report report = reportsRegistry.findReport(namespace, index);
        report.getViews()[viewIndex].getSpringView().render(null, request, response);

    }

    public static byte[] decompress(byte[] str) throws IOException {
        byte[] buf = new byte[str.length * 10];
        GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(str));
        int len;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        while ((len = gis.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        return out.toByteArray();
    }

    public static byte[] base64Decoding(String str) {
        return Base64.decode(str);
    }

    @RequestMapping(value = "/ie9", method = RequestMethod.POST)
    public void ie9Sucks(HttpServletResponse response, @RequestParam("b64") String b64,
            @RequestParam("fileName") String fileName) throws IOException {

        final File tempFile = File.createTempFile(fileName, ".tmp");
        tempFile.deleteOnExit();
        byte decoded[] = base64Decoding(b64);

        FileOutputStream fos = new FileOutputStream(tempFile);
        fos.write(decoded);
        fos.close();

        InputStream in = new BufferedInputStream(new FileInputStream(tempFile));

        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".docx");
        IOUtils.copy(in, response.getOutputStream());
        response.flushBuffer();
        in.close();

    }

    // TODO : make it work for the regular tagpicker. Currently it only
    // works for radiobutton-grouped-pickers.
    // Also lots of wtf because on the rush
    private void populateTagsIfRequired(Report report, Model model) {
        // also supply the list of available tags if the tag picker is used
        for (Input input : report.getForm()) {
            if (input.getType() == InputType.RADIO_BUTTONS_GROUP) {
                RadioButtonsGroup container = (RadioButtonsGroup) input;
                for (OptionInput opt : container.getOptions()) {
                    if (opt instanceof TagPickerOption) {
                        String entityType = ((TagPickerOption) opt).getPickerBoundEntity();
                        List<String> availableTags = getPossibleTagValues(entityType);
                        if (availableTags.isEmpty()) {
                            availableTags = null;
                        }
                        model.addAttribute("availableTags", availableTags);
                        return; // OOOOh !
                    }
                }
            }
        }
    }

    public List<String> getPossibleTagValues(String boundEntity) {

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

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

        return customFieldFinder.getAvailableTagsForEntity(boundEntity, projectIds);
    }

}