eu.europa.ec.grow.espd.controller.EspdController.java Source code

Java tutorial

Introduction

Here is the source code for eu.europa.ec.grow.espd.controller.EspdController.java

Source

/*
 *
 * Copyright 2016 EUROPEAN COMMISSION
 *
 * Licensed under the EUPL, Version 1.1 or  as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 *
 * You may not use this work except in compliance with the Licence.
 *
 * You may obtain a copy of the Licence at:
 *
 * https://joinup.ec.europa.eu/community/eupl/og_page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 *
 */

package eu.europa.ec.grow.espd.controller;

import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.springframework.http.MediaType.APPLICATION_XML_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.output.CountingOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.MultipartFile;

import com.google.common.base.Optional;

import eu.europa.ec.grow.espd.domain.EconomicOperatorImpl;
import eu.europa.ec.grow.espd.domain.EconomicOperatorRepresentative;
import eu.europa.ec.grow.espd.domain.EspdDocument;
import eu.europa.ec.grow.espd.domain.enums.other.Country;
import eu.europa.ec.grow.espd.ted.TedRequest;
import eu.europa.ec.grow.espd.ted.TedResponse;
import eu.europa.ec.grow.espd.ted.TedService;
import eu.europa.ec.grow.espd.xml.EspdExchangeMarshaller;

@Controller
@SessionAttributes("espd")
class EspdController {

    private static final String WELCOME_PAGE = "welcome";
    private static final String REQUEST_CA_PROCEDURE_PAGE = "request/ca/procedure";
    private static final String RESPONSE_EO_PROCEDURE_PAGE = "response/eo/procedure";
    private static final String PRINT_PAGE = "response/eo/print";

    private final EspdExchangeMarshaller exchangeMarshaller;

    private final TedService tedService;

    @Autowired
    EspdController(EspdExchangeMarshaller exchangeMarshaller, TedService tedService) {
        this.exchangeMarshaller = exchangeMarshaller;
        this.tedService = tedService;
    }

    @ModelAttribute("espd")
    public EspdDocument newDocument() {
        return new EspdDocument();
    }

    @RequestMapping("/")
    public String index() {
        return WELCOME_PAGE;
    }

    @RequestMapping("/{page:filter|contact}")
    public String getPage(@PathVariable String page) {
        return page;
    }

    @RequestMapping(value = "/welcome")
    public String cancel(SessionStatus status) {
        try {
            return WELCOME_PAGE;
        } finally {
            status.setComplete();
        }
    }

    @RequestMapping(value = "/filter", params = "action", method = POST)
    public String whoAreYouScreen(@RequestParam("authority.country") Country country, @RequestParam String action,
            @RequestPart List<MultipartFile> attachments, @ModelAttribute("espd") EspdDocument document,
            Model model, BindingResult result) throws IOException {
        if ("ca_create_espd_request".equals(action)) {
            return createNewRequestAsCA(country, document);
        } else if ("ca_reuse_espd_request".equals(action)) {
            return reuseRequestAsCA(attachments.get(0), model, result);
        } else if ("ca_review_espd_response".equals(action)) {
            return reviewResponseAsCA(attachments.get(0), model, result);
        } else if ("eo_import_espd".equals(action)) {
            return importEspdAsEo(country, attachments.get(0), model, result);
        } else if ("eo_merge_espds".equals(action)) {
            return mergeTwoEspds(attachments, model, result);
        } else if ("eo_create_response".equals(action)) {
            return createNewResponseAsEO(country, document);
        }
        return "filter";
    }

    private String createNewRequestAsCA(Country country, EspdDocument document) {
        document.getAuthority().setCountry(country);
        document.selectCAExclusionCriteria();
        copyTedInformation(document);
        return redirectToPage(REQUEST_CA_PROCEDURE_PAGE);
    }

    private void copyTedInformation(EspdDocument document) {
        TedResponse tedResponse = tedService.getContractNoticeInformation(
                TedRequest.builder().receptionId(document.getTedReceptionId()).build());
        document.setOjsNumber(tedResponse.getNoDocOjs());
        TedResponse.TedNotice notice = tedResponse.getFirstNotice();
        document.getAuthority().setName(notice.getOfficialName());
        document.setProcedureTitle(notice.getTitle());
        document.setProcedureShortDesc(notice.getShortDescription());
        document.setFileRefByCA(notice.getReferenceNumber());
        document.setTedUrl(notice.getTedUrl());
    }

    private String reuseRequestAsCA(MultipartFile attachment, Model model, BindingResult result)
            throws IOException {
        try (InputStream is = attachment.getInputStream()) {
            Optional<EspdDocument> espd = exchangeMarshaller.importEspdRequest(is);
            if (espd.isPresent()) {
                model.addAttribute("espd", espd.get());
                return redirectToPage(REQUEST_CA_PROCEDURE_PAGE);
            }
        }

        result.rejectValue("attachments", "espd_upload_request_error");
        return "filter";
    }

    private String reviewResponseAsCA(MultipartFile attachment, Model model, BindingResult result)
            throws IOException {
        try (InputStream is = attachment.getInputStream()) {
            Optional<EspdDocument> espd = exchangeMarshaller.importEspdResponse(is);
            if (espd.isPresent()) {
                model.addAttribute("espd", espd.get());
                return redirectToPage(PRINT_PAGE);
            }
        }

        result.rejectValue("attachments", "espd_upload_response_error");
        return "filter";
    }

    private String importEspdAsEo(Country country, MultipartFile attachment, Model model, BindingResult result)
            throws IOException {
        try (InputStream is = attachment.getInputStream()) {
            Optional<EspdDocument> wrappedEspd = exchangeMarshaller.importAmbiguousEspdFile(is);

            // how can wrappedEspd be null???
            if (wrappedEspd != null && wrappedEspd.isPresent()) {
                EspdDocument espd = wrappedEspd.get();
                if (espd.getEconomicOperator() == null) {
                    espd.setEconomicOperator(new EconomicOperatorImpl());
                }
                if (needsToLoadProcurementProcedureInformation(espd)) {
                    // in this case we need to contact TED again to load the procurement information
                    copyTedInformation(espd);
                }
                espd.getEconomicOperator().setCountry(country);
                model.addAttribute("espd", espd);
                return redirectToPage(RESPONSE_EO_PROCEDURE_PAGE);
            }
        }

        result.rejectValue("attachments", "espd_upload_error");
        return "filter";
    }

    private boolean needsToLoadProcurementProcedureInformation(EspdDocument espdDocument) {
        return isBlank(espdDocument.getOjsNumber()) && isNotBlank(espdDocument.getTedReceptionId());
    }

    private String mergeTwoEspds(List<MultipartFile> attachments, Model model, BindingResult result)
            throws IOException {
        try (InputStream reqIs = attachments.get(1).getInputStream();
                InputStream respIs = attachments.get(2).getInputStream()) {
            Optional<EspdDocument> wrappedEspd = exchangeMarshaller.mergeEspdRequestAndResponse(reqIs, respIs);
            if (wrappedEspd.isPresent()) {
                model.addAttribute("espd", wrappedEspd.get());
                return redirectToPage(RESPONSE_EO_PROCEDURE_PAGE);
            }
        }

        result.rejectValue("attachments", "espd_upload_error");
        return "filter";
    }

    private String createNewResponseAsEO(Country country, EspdDocument document) {
        if (document.getEconomicOperator() == null) {
            document.setEconomicOperator(new EconomicOperatorImpl());
        }
        document.getEconomicOperator().setCountry(country);
        document.giveLifeToAllExclusionCriteria();
        document.giveLifeToAllSelectionCriteria();
        return redirectToPage(RESPONSE_EO_PROCEDURE_PAGE);
    }

    @RequestMapping("/{flow:request|response}/{agent:ca|eo}/{step:procedure|exclusion|selection|finish|print}")
    public String view(@PathVariable String flow, @PathVariable String agent, @PathVariable String step,
            @ModelAttribute("espd") EspdDocument espd) {
        return flow + "_" + agent + "_" + step;
    }

    @RequestMapping(value = "/{flow:request|response}/{agent:ca|eo}/{step:procedure|exclusion|selection|finish|print}", method = POST, params = "prev")
    public String previous(@PathVariable String flow, @PathVariable String agent, @PathVariable String step,
            @RequestParam String prev, @ModelAttribute("espd") EspdDocument espd, BindingResult bindingResult) {
        return bindingResult.hasErrors() ? flow + "_" + agent + "_" + step
                : redirectToPage(flow + "/" + agent + "/" + prev);
    }

    @RequestMapping(value = "/{flow:request|response}/{agent:ca|eo}/{step:procedure|exclusion|selection|finish}", method = POST, params = "print")
    public String print(@PathVariable String flow, @PathVariable String agent, @PathVariable String step,
            @RequestParam String print, @ModelAttribute("espd") EspdDocument espd, BindingResult bindingResult) {
        return bindingResult.hasErrors() ? flow + "_" + agent + "_" + step
                : redirectToPage(flow + "/" + agent + "/print");
    }

    @RequestMapping(value = "/{flow:request|response}/{agent:ca|eo}/{step:procedure}", method = POST, params = "add")
    public String addRepresentative(@PathVariable String flow, @PathVariable String agent,
            @PathVariable String step, @RequestParam Integer add, @ModelAttribute("espd") EspdDocument espd,
            BindingResult bindingResult) {
        espd.getEconomicOperator().getRepresentatives().add(add, new EconomicOperatorRepresentative());
        return redirectToPage(flow + "/" + agent + "/" + step + "#representative" + add);
    }

    @RequestMapping(value = "/{flow:request|response}/{agent:ca|eo}/{step:procedure}", method = POST, params = "remove")
    public String removeRepresentative(@PathVariable String flow, @PathVariable String agent,
            @PathVariable String step, @RequestParam Integer remove, @ModelAttribute("espd") EspdDocument espd,
            BindingResult bindingResult) {
        espd.getEconomicOperator().getRepresentatives().remove(remove.intValue());
        if (espd.getEconomicOperator().getRepresentatives().size() == 0) {
            espd.getEconomicOperator().getRepresentatives().add(new EconomicOperatorRepresentative());
        }
        remove = Math.min(espd.getEconomicOperator().getRepresentatives().size() - 1, remove);
        return redirectToPage(flow + "/" + agent + "/" + step + "#representative" + remove);
    }

    @RequestMapping(value = "/{flow:request|response}/{agent:ca|eo}/{step:procedure|exclusion|selection|finish|generate|print}", method = POST, params = "next")
    public String next(@PathVariable String flow, @PathVariable String agent, @PathVariable String step,
            @RequestParam String next, @ModelAttribute("espd") EspdDocument espd, HttpServletResponse response,
            BindingResult bindingResult) throws IOException {
        if (bindingResult.hasErrors()) {
            return flow + "_" + agent + "_" + step;
        }

        if (!"generate".equals(next)) {
            return redirectToPage(flow + "/" + agent + "/" + next);
        }

        downloadEspdFile(agent, espd, response);

        return null;
    }

    private static String redirectToPage(String pageName) {
        return "redirect:/" + pageName;
    }

    private void downloadEspdFile(@PathVariable String agent, @ModelAttribute("espd") EspdDocument espd,
            HttpServletResponse response) throws IOException {
        try (CountingOutputStream out = new CountingOutputStream(response.getOutputStream())) {
            response.setContentType(APPLICATION_XML_VALUE);
            if ("eo".equals(agent)) {
                response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"espd-response.xml\"");
                exchangeMarshaller.generateEspdResponse(espd, out);
            } else {
                response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"espd-request.xml\"");
                exchangeMarshaller.generateEspdRequest(espd, out);
            }
            response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(out.getByteCount()));
            out.flush();
        }
    }

    @InitBinder
    private void dateBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, editor);
    }
}