org.openlegacy.terminal.mvc.web.DefaultGenericScreensController.java Source code

Java tutorial

Introduction

Here is the source code for org.openlegacy.terminal.mvc.web.DefaultGenericScreensController.java

Source

/*******************************************************************************
 * Copyright (c) 2014 OpenLegacy Inc.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     OpenLegacy Inc. - initial API and implementation
 *******************************************************************************/
package org.openlegacy.terminal.mvc.web;

import flexjson.JSONSerializer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openlegacy.definitions.ActionDefinition;
import org.openlegacy.definitions.TableDefinition;
import org.openlegacy.modules.table.TableWriter;
import org.openlegacy.modules.table.drilldown.TableScrollStopConditions;
import org.openlegacy.mvc.MvcUtils;
import org.openlegacy.mvc.web.AbstractGenericEntitiesController;
import org.openlegacy.mvc.web.MvcConstants;
import org.openlegacy.mvc.web.OpenLegacyViewResolver;
import org.openlegacy.terminal.ScreenEntity;
import org.openlegacy.terminal.TerminalSession;
import org.openlegacy.terminal.actions.TerminalAction;
import org.openlegacy.terminal.actions.TerminalActions;
import org.openlegacy.terminal.definitions.ScreenEntityDefinition;
import org.openlegacy.terminal.definitions.ScreenTableDefinition;
import org.openlegacy.terminal.definitions.TerminalActionDefinition;
import org.openlegacy.terminal.exceptions.ScreenEntityNotAccessibleException;
import org.openlegacy.terminal.json.JsonSerializationUtil;
import org.openlegacy.terminal.modules.login.LoginMetadata;
import org.openlegacy.terminal.modules.table.ScrollableTableUtil;
import org.openlegacy.terminal.providers.TablesDefinitionProvider;
import org.openlegacy.terminal.support.binders.MultyScreenTableBindUtil;
import org.openlegacy.terminal.utils.ScreenEntityUtils;
import org.openlegacy.utils.SpringUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestDataBinder;
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.bind.annotation.ResponseBody;

import java.io.IOException;
import java.net.MalformedURLException;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

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

/**
 * OpenLegacy default web controller for a terminal session. Handles GET/POST requests of a web application. Works closely with
 * generic.jspx / composite.jspx. Saves the need for a dedicated controller and page for each screen API, if such doesn't exists.
 * 
 * @author Roi Mor
 * 
 */
@Controller
public class DefaultGenericScreensController extends AbstractGenericEntitiesController<TerminalSession> {

    private final static Log logger = LogFactory.getLog(DefaultGenericScreensController.class);

    private static final String TARGET = "target";

    @Inject
    private ScreenEntityUtils screenEntityUtils;

    @Inject
    private TablesDefinitionProvider tablesDefinitionProvider;

    @Inject
    private TableWriter tableWriter;

    @Inject
    private ApplicationContext applicationContext;

    @Inject
    private LoginMetadata loginMetadata;

    @Inject
    private ScreenBindUtils screenBindUtil;

    @Inject
    private MultyScreenTableBindUtil tableBindUtil;

    @Override
    protected String prepareView(Object entity, Model uiModel, boolean partial, HttpServletRequest request)
            throws MalformedURLException {
        String viewName = super.prepareView(entity, uiModel, partial, request);
        screenBindUtil.bindCollectTable(getSession(), entity, uiModel);
        return viewName;
    }

    @RequestMapping(value = "/{entity}", method = RequestMethod.POST)
    public String postEntity(@PathVariable("entity") String entityName,
            @RequestParam(defaultValue = "", value = ACTION) String action,
            @RequestParam(value = "partial", required = false) String partial,
            @RequestParam(value = TARGET, required = false) String target, HttpServletRequest request,
            HttpServletResponse response, Model uiModel) throws IOException {
        return postEntityWithKey(entityName, null, action, partial, target, request, response, uiModel);
    }

    @RequestMapping(value = "/{entity}/{key:[[\\w\\p{L}]+[:-_ ,]*[\\w\\p{L}]+]+}", method = RequestMethod.POST)
    public String postEntityWithKey(@PathVariable("entity") String entityName, @PathVariable("key") String key,
            @RequestParam(defaultValue = "", value = ACTION) String action,
            @RequestParam(value = "partial", required = false) String partial,
            @RequestParam(value = TARGET, required = false) String target, HttpServletRequest request,
            HttpServletResponse response, Model uiModel) throws IOException {
        Class<?> entityClass = findAndHandleNotFound(entityName, response);
        if (entityClass == null) {
            return null;
        }

        ScreenEntity screenEntity = (ScreenEntity) getSession().getEntity(entityName, key);
        boolean isPartial = request.getParameter("partial") != null;
        if (screenEntity == null) {
            ScreenEntity currentEntity = getSession().getEntity();
            return handleEntity(request, uiModel, currentEntity, isPartial ? null : MvcConstants.REDIRECT);
        }

        ServletRequestDataBinder binder = new ServletRequestDataBinder(screenEntity);
        MvcUtils.registerEditors(binder, getEntitiesRegistry());
        binder.bind(request);
        screenBindUtil.bindTables(request, entityClass, screenEntity);

        ScreenEntityDefinition beforeEntityDefinition = (ScreenEntityDefinition) getEntitiesRegistry()
                .get(entityClass);
        TerminalActionDefinition matchedActionDefinition = screenEntityUtils.findAction(screenEntity, action);
        ScreenEntity resultEntity = getSession().doAction((TerminalAction) matchedActionDefinition.getAction(),
                screenEntity);
        if (matchedActionDefinition != null && matchedActionDefinition.getTargetEntity() != null) {
            resultEntity = (ScreenEntity) getSession().getEntity(matchedActionDefinition.getTargetEntity());
        }

        String urlPrefix = isPartial ? null : MvcConstants.REDIRECT;
        if (resultEntity != null) {
            ScreenEntityDefinition afterEntityDefinition = (ScreenEntityDefinition) getEntitiesRegistry()
                    .get(resultEntity.getClass());
            if (!beforeEntityDefinition.isWindow() && afterEntityDefinition.isWindow()) {
                urlPrefix = OpenLegacyViewResolver.WINDOW_URL_PREFIX;
            } else if (beforeEntityDefinition.isWindow() && !afterEntityDefinition.isWindow()) {
                urlPrefix = MvcConstants.REDIRECT;
            } else if (!beforeEntityDefinition.isWindow() && !afterEntityDefinition.isWindow()
                    && !beforeEntityDefinition.getEntityName().equals(afterEntityDefinition.getEntityName())) {
                urlPrefix = MvcConstants.REDIRECT;
            }
        }
        if (target != null) {
            return urlPrefix + target;
        } else {
            return handleEntity(request, uiModel, resultEntity, urlPrefix);
        }
    }

    @Override
    protected String handleFallbackUrl(RuntimeException e) {
        if (!getSession().isConnected() && loginMetadata.getLoginScreenDefinition() != null) {
            logger.error(e.getMessage());
            return MvcConstants.LOGIN_URL;
        } else if (e instanceof ScreenEntityNotAccessibleException) {
            if (getSession().getEntity() != null) {
                ScreenEntityDefinition definition = (ScreenEntityDefinition) getEntitiesRegistry()
                        .get(getSession().getEntity().getClass());
                return MessageFormat.format("{0}{1}?{2}={3}", MvcConstants.REDIRECT, definition.getEntityName(),
                        TARGET, ((ScreenEntityNotAccessibleException) e).getTargetEntity());
            } else {
                return super.handleFallbackUrl(e);
            }
        } else {
            return super.handleFallbackUrl(e);
        }
    }

    /**
     * handle ajax request for load more
     * 
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @RequestMapping(value = "/{screen}/more", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<String> more(@PathVariable("screen") String entityName) {
        // sync the current entity
        ScreenEntity screenBefore = (ScreenEntity) getSession().getEntity(entityName);
        ScreenEntity nextScreen = getSession().doAction(TerminalActions.PAGE_DOWN());

        TableScrollStopConditions tableScrollStopConditions = SpringUtil.getDefaultBean(applicationContext,
                TableScrollStopConditions.class);

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/text; charset=utf-8");

        Map<String, ScreenTableDefinition> tableDefinitions = tablesDefinitionProvider
                .getTableDefinitions(nextScreen.getClass());
        if (tableDefinitions.size() == 0) {
            logger.error("Next screen after PAGEDOWN does not contain a table");
            return new ResponseEntity<String>("", headers, HttpStatus.OK);
        }

        if (tableScrollStopConditions.shouldStop(screenBefore, nextScreen)) {
            return new ResponseEntity<String>("", headers, HttpStatus.OK);
        }

        List<?> records = ScrollableTableUtil.getSingleScrollableTable(tablesDefinitionProvider, nextScreen);
        String result = new JSONSerializer().serialize(records);
        return new ResponseEntity<String>(result, headers, HttpStatus.OK);
    }

    // export to excel
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @RequestMapping(value = "/{screen}/excel", method = RequestMethod.GET)
    public void excel(@PathVariable("screen") String entityName, HttpServletResponse response) throws IOException {
        ScreenEntity entity = (ScreenEntity) getSession().getEntity(entityName);
        if (entity == null) {
            return;
        }
        List<?> records = ScrollableTableUtil.getSingleScrollableTable(tablesDefinitionProvider, entity);
        response.setContentType("application/vnd.ms-excel");
        response.addHeader("Content-Disposition",
                MessageFormat.format("attachment; filename=\"{0}.xls\"", entityName));
        Entry<String, ScreenTableDefinition> tableDefinition = ScrollableTableUtil
                .getSingleScrollableTableDefinition(tablesDefinitionProvider, entity.getClass());
        tableWriter.writeTable(records, (TableDefinition) tableDefinition.getValue(), response.getOutputStream());
    }

    /**
     * handle Ajax request for auto compete fields
     * 
     * @param screenEntityName
     * @param fieldName
     * @return JSON content
     */
    @RequestMapping(value = "/{screen}/{field}Values", method = RequestMethod.GET, headers = "X-Requested-With=XMLHttpRequest")
    @ResponseBody
    public ResponseEntity<String> autoCompleteJson(@PathVariable("screen") String screenEntityName,
            @PathVariable("field") String fieldName, @RequestParam(value = "name", required = false) String text) {

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/text; charset=utf-8");

        if (text != null) {
            text = text.replace("*", "");
        }

        Map<Object, Object> fieldValues = tableBindUtil.getRecords(getSession(), text, screenEntityName, fieldName);

        String result = JsonSerializationUtil.toDojoFormat(fieldValues, text);
        return new ResponseEntity<String>(result, headers, HttpStatus.OK);
    }

    @Override
    protected ActionDefinition findAction(Object entity, String action) {
        return screenEntityUtils.findAction((ScreenEntity) entity, action);
    }

}