/** Display screen */
  @RequestMapping(method = RequestMethod.GET)
  public ModelAndView showPage(
      HttpServletRequest req,
      HttpServletResponse res,
      @RequestParam(value = OPERATION, required = false) String operation,
      @RequestParam(value = FEATID, required = false) String featureId)
      throws Exception {

    // Environment de travail
    EnvironmenBean envBean = (EnvironmenBean) req.getSession().getAttribute(ATTR_ENVBEAN);
    if (null == envBean) {
      return new ModelAndView("redirect:loadConfig.do");
    }
    log.info("Page <FEATURES>, action<GET>, env<" + envBean.getEnvId() + ">");

    // Access features through HTTP store (all parsing done)
    FeatureStore fStore;
    if ("http".equalsIgnoreCase(envBean.getConnectionMode())) {
      // Access features through HTTP store (all parsing done)
      fStore = new FeatureStoreHttp(envBean.getEnvUrl() + "/" + FF4jWebConstants.RESOURCE_FF4J);
    } else if ("bean".equalsIgnoreCase(envBean.getConnectionMode())) {
      ClassPathXmlApplicationContext cpax = new ClassPathXmlApplicationContext(envBean.getEnvUrl());
      fStore = cpax.getBean(FF4j.class).getFeatureStore();
      cpax.close();
    } else if ("jmx".equalsIgnoreCase(envBean.getConnectionMode())) {
      throw new NotImplementedException("JMX Client is not yet implemented");
    } else {
      throw new IllegalArgumentException(
          "Invalid definition of store within configuration file, avaolable modes are 'http', 'jmx' and 'bean'");
    }

    // Data in the target screen
    FeaturesBean featBean = new FeaturesBean();

    try {

      // Check parameter to know what to do
      if (operation != null && !operation.isEmpty()) {
        log.debug("Performing operation <" + operation + "> on <" + featureId + ">");
        if (OP_DISABLE.equalsIgnoreCase(operation)) {
          opDisableFeature(fStore, featureId);
          String msg = buildMessage(featureId, "DISABLED");
          featBean.setMessage(msg);
          log.info(msg);
        } else if (OP_ENABLE.equalsIgnoreCase(operation)) {
          opEnableFeature(fStore, featureId);
          featBean.setMessage(buildMessage(featureId, "ENABLED"));
        } else if (OP_RMV_FEATURE.equalsIgnoreCase(operation)) {
          opDeleteFeature(fStore, featureId);
          String msg = buildMessage(featureId, "DELETED");
          featBean.setMessage(msg);
          log.info(msg);
        } else if (OP_EXPORT.equalsIgnoreCase(operation)) {
          opExportFile(fStore, res);
          featBean.setMessage("Feature have been success fully exported");
        }
      }

    } catch (Exception e) {
      featBean.setMessageType(MSG_ERROR);
      featBean.setMessage(e.getMessage());
      log.error("Error when retrieving features ", e);
    }

    // Updating Bean
    featBean.setListOfFeatures(new ArrayList<Feature>(fStore.readAll().values()));
    featBean.setHtmlPermissions(populatePermissionList(envBean));
    featBean.setGroupList(fStore.readAllGroups());

    // Create view
    ModelAndView mav = new ModelAndView(VIEW_FEATURES);
    mav.addObject(ATTR_ENVBEAN, envBean);
    mav.addObject(ATTR_FEATUREBEAN, featBean);
    return mav;
  }
  @RequestMapping(method = RequestMethod.POST)
  public ModelAndView executeThenShowPage(HttpServletRequest req, HttpServletResponse res)
      throws Exception {
    log.info("Page <FEATURES> on action <POST>");

    // Environment de travail
    EnvironmenBean envBean = (EnvironmenBean) req.getSession().getAttribute(ATTR_ENVBEAN);

    // Access features through HTTP store (all parsing done)
    FeatureStore storeHTTP =
        new FeatureStoreHttp(envBean.getEnvUrl() + "/" + FF4jWebConstants.RESOURCE_FF4J);

    // Data in the target screen
    FeaturesBean featBean = new FeaturesBean();
    try {
      // Import Features
      if (ServletFileUpload.isMultipartContent(req)) {
        List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(req);
        for (FileItem item : items) {
          if (item.isFormField()) {
            if (OPERATION.equalsIgnoreCase(item.getFieldName())) {
              log.info("Processing action : " + item.getString());
            }
          } else if (FLIPFILE.equalsIgnoreCase(item.getFieldName())) {
            String filename = FilenameUtils.getName(item.getName());
            if (filename.toLowerCase().endsWith("xml")) {
              opImportFile(storeHTTP, item.getInputStream());
              featBean.setMessage(
                  "The file <b>" + filename + "</b> has been successfully imported");
            } else {
              featBean.setMessage("Invalid FILE, must be XML files");
              featBean.setMessageType(MSG_ERROR);
            }
          }
        }

      } else {
        // Edit Operations
        String operation = req.getParameter(OPERATION);
        if (operation != null && !operation.isEmpty()) {

          if (OP_EDIT_FEATURE.equalsIgnoreCase(operation)) {
            opUpdateFeatureDescription(storeHTTP, req);
            featBean.setMessage(buildMessage(req.getParameter(FEATID), "UPDATED"));

          } else if (OP_CREATE_FEATURE.equalsIgnoreCase(operation)) {
            opCreateFeature(storeHTTP, req);
            featBean.setMessage(buildMessage(req.getParameter(FEATID), "ADDED"));

          } else if (OP_TOGGLE_GROUP.equalsIgnoreCase(operation)) {
            String groupName = req.getParameter(GROUPNAME);
            if (groupName != null && !groupName.isEmpty()) {
              String operationGroup = req.getParameter(SUBOPERATION);
              if (OP_ENABLE.equalsIgnoreCase(operationGroup)) {
                storeHTTP.enableGroup(groupName);
                featBean.setMessage(buildMessageGroup(groupName, "ENABLED"));
                log.info("Group '" + groupName + "' has been ENABLED.");
              } else if (OP_DISABLE.equalsIgnoreCase(operationGroup)) {
                storeHTTP.disableGroup(groupName);
                featBean.setMessage(buildMessageGroup(groupName, "DISABLED"));
                log.info("Group '" + groupName + "' has been DISABLED.");
              }
            }
          } else {
            log.error("Invalid POST OPERATION" + operation);
            featBean.setMessageType(MSG_ERROR);
            featBean.setMessage("Invalid REQUEST");
          }
        }
      }
    } catch (Exception e) {
      featBean.setMessageType(MSG_ERROR);
      featBean.setMessage(e.getMessage());
      e.printStackTrace();
    }

    // Updating bean
    featBean.setListOfFeatures(new ArrayList<Feature>(storeHTTP.readAll().values()));
    featBean.setHtmlPermissions(populatePermissionList(envBean));
    featBean.setGroupList(storeHTTP.readAllGroups());

    // Create view
    ModelAndView mav = new ModelAndView(VIEW_FEATURES);
    mav.addObject(ATTR_ENVBEAN, envBean);
    mav.addObject(ATTR_FEATUREBEAN, featBean);
    return mav;
  }