mdkInventory1/ControllerServlet.java


package mdkInventory1;

import java.io.IOException;
import java.util.Vector;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import mdkInventory1.bean.BasicDataHandler;
import mdkInventory1.bean.TableViewDefinition;

import com.sap.ip.me.api.logging.AbstractLogging;
import com.sap.ip.me.api.logging.AppLog;
import com.sap.ip.me.api.logging.Severities;
import com.sap.ip.me.api.runtime.jsp.AbstractMEHttpServlet;
import com.sap.ip.me.api.services.MEResourceBundle;

public class ControllerServlet extends AbstractMEHttpServlet implements Constants {
    public static MEResourceBundle RESOURCE_BUNDLE;

    private TableViewDefinition tableViewDefinition;
    private BasicDataHandler dataHandler;
    private String headLine;
    private int start_index;
    private int sort_index;
    private boolean sort_ascending;
    private String buttontext;
    private String pageTitle;
    private String currentPageFooter;
    private String buttontextQuery;
    private String filter_string;
    private String current_filter_string;
    private Vector commandLine = new Vector();
    /**
     * Must be overwritten - return the name of the application
     */
    public String getApplicationName() {
        return MI_APPLICATION_NAME;
    }

    /**
     * doIntialize - called when the servlet is activated the first time
     */
    public void doInitialize() throws ServletException {
        // The Resource bundle is used to define the table headers. The bundle contains the field names
        // (the names that come from the server and are defined in the merep.xml file) and as value it
        // has the name that is displayed on the screen.
        // If a field name is not defined in the bundle it is not displayed on the screen - that means the
        // entire column is not displayed. This gives the opportunity to control, which columns should be displayed.
        // The add.jsp also only displays fields that are defined in the bundle.
        setResourceBundle("mdkInventory1.properties.inventory");
        RESOURCE_BUNDLE = getResourceBundle();

        setFilterOff();

        //    Prepare a log output - Level DEBUG - Information about classloader
        ClassLoader cl = getClass().getClassLoader();
        AbstractLogging aLogger = AppLog.getInstance(MI_APPLICATION_NAME);
        aLogger.log(Severities.DEBUG, "MIClientInfo: Create MIClientInfoServlet.doInitialize with Classloader {0}", (cl == null ? "(null)" : cl.toString()));

        // Setup Commands for this example. Commands are displayed on the top of the centerpage.
        // In this example we use add, delete, filter and list all commands.
        setCommands();
    }

    /**
     * doHandleEvent - called any subsequent time when an event on the web client occurs.
     */

    public String doHandleEvent(String eventName, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Set the name of the JSP that has to be called when this method is finished.
        // INITIAL_JSP ist defined in the interface Constants.java and refers to welcome.jsp. This JSP displays a welcome message
        // and asks for your name. Welcome.jsp has a submit button which generates the event EVENT_NAME. When this event occurs,
        // the tableView.jsp is called and displays system information.
        // The welcome.jsp is called by default - if the servlet is called the first time or an unknown event occurs.

        // Set default JSP.
        String nextJSP = INITIAL_JSP;
        pageTitle = "Inventory Management";
        currentPageFooter = "menu.jsp";
        // Set default text for headline
        headLine = WELCOME_MESSAGE;

        // First we handle the events that have influence on the data provided by the dataHandler. These events are the
        // navigation events and the sort event (by clicking in the product id header line).
        // Once we handled the navigation and sortorder event, the variables like start_index, sort_ascending etc is
        // set correctly and the getBeansFromContext can immediatly read the correct syncbos.

        nextJSP = INITIAL_JSP;
        // Sort order event
        if (eventName.equals(EVENT_SORTBYPRODUCTID)) {
            // Sort by Model has been clicked. The car attributes start with 0. Therefore we decrement I_MAKE by 1.
            sort_index = I_PRODUCTID;
            if (sort_ascending == true)
                sort_ascending = false;
            else
                sort_ascending = true;
        }
        // Checking for navigation events
        // First Page
        if (eventName.equals(EVENT_FIRSTPAGE)) {
            start_index = 0;
        }
        // Last Page
        if (eventName.equals(EVENT_LASTPAGE)) {
            start_index = ((dataHandler.getRowsInDataset() - 1) / MAX_TABLE_ROWS) * MAX_TABLE_ROWS;
        }
        if (eventName.equals(EVENT_PAGEUP)) {
            if (start_index >= MAX_TABLE_ROWS)
                start_index = start_index - MAX_TABLE_ROWS;
        }
        if (eventName.equals(EVENT_PAGEDOWN)) {
            start_index = start_index + MAX_TABLE_ROWS;
        }
        // The "input" object with type = image in menu.jsp delivers the eventname with .x and .y appended to it
        // So we check the beginning of the eventname.
        if (eventName.startsWith(EVENT_GOTOPAGE)) {
            String inputField = (String) request.getParameter("GOTO_PAGE");
            int number = Integer.parseInt(inputField);
            setCurrenPage(number);
        }
        //
        // Events in add.jsp
        // Add a new entry. Since the iterator has to refreshed as well, we also do this check before
        // the getBeansFromContext method.
        if (eventName.equals(EVENT_ADDENTRYSUBMIT)) {
            // Event occurs when the submit button has been pressed on the ADD ENTRY JSP
            addEntry(request);
        }

        //
        // Events in query.jsp
        // Set a filter string. Since the iterator has to refreshed as well, we also do this check before
        // the getBeansFromContext method.
        if (eventName.equals(EVENT_QUERYSUBMIT)) {
            // Event occurs when the OK button has been pressed. The Filter string is set for the Query.
            nextJSP = setFilter(request);
        }
        //
        // We also check if the eventName is empty. An empty eventName means that the servlet has been called from
        // the MI home page - in this case we have to to refresh the syncBo counter, because new data could have been
        // synched from the server
        // Because it is time consuming to get the number od syncbos we do not refresh the count all the time.
        boolean refreshSyncBoCount = false; 
        if (eventName.trim().length() < 1) refreshSyncBoCount = true;

        // Get bean, if there is one, in the session context, otherwise create a new instance.
        // For the datahandler we always create a new instance to get the actual data.
        getBeansFromContext(request, refreshSyncBoCount);

        //
        // Events in menu.jsp

        if (eventName.equals(EVENT_ADDENTRY)) {
            // Event occurs when the ADD button in menu.jsp has been pressed.
            // We display add.jsp as next JSP.
            pageTitle = "Add inventory item";
            currentPageFooter = "add.jsp";
            nextJSP = ADD_JSP;
        }

        if (eventName.equals(EVENT_QUERY)) {
            // Event occurs when the FILTER button in menu.jsp has been pressed.
            // We display query.jsp.
            nextJSP = QUERY_JSP;
        }

        if (eventName.equals(EVENT_SAVE)) {
            // Event occurs when the DELETE button in menu.jsp has been pressed.
            nextJSP = saveEntries(request);
        }

        //
        // Events from add.jsp or delete.jsp (Cancel event - is handled the same for both JSP
        //
        if (eventName.equals(EVENT_ADDENTRYCANCEL)) {
            // Event occurs when the cancel button has been pressed on the ADD ENTRY JSP. No action. Show initial screen
            nextJSP = INITIAL_JSP;
        }

        //
        // Event in delete.jsp - is the OK button to acknowledge the information text
        //
        if (eventName.equals(EVENT_DELETEENTRYSUBMIT)) {
            nextJSP = INITIAL_JSP;
        }

        //
        // Event in query.jsp
        //
        if (eventName.equals(EVENT_QUERYCANCEL)) {
            // Event occurs when the cancel button has been pressed on the Cancel button. No action. Show initial screen
            nextJSP = INITIAL_JSP;
        }

        // Load bean with values from persistence layer
        loadBean();

        // Put bean in the session context.
        putBeansIntoContext(request);

        // Exit with name of JSP.
        return nextJSP;
    }

    /**
     *  set the current page
     * @param number - current page number
     */
    private void setCurrenPage(int number) {
        start_index = (number - 1) * MAX_TABLE_ROWS;
        // If a page is specified that is higher than the maximum pages for the dataset
        // we set the last page as current page
        int max_index = ((dataHandler.getRowsInDataset() - 1) / MAX_TABLE_ROWS) * MAX_TABLE_ROWS;
        if (start_index > max_index)
            start_index = max_index;
        // Check for negative page value - if so set frist page            
        if (start_index < 0)
            start_index = 0;
    }

    /**
     * @param eventName checks if event comes from table entry
     * @return the true if detailpage should be called
     */
    private boolean getDetailPage(String eventName) {
        boolean detail = false;
        // Check if event matches entry in frist column
        for (int i = 0; i < dataHandler.getTableRows(); i++) {
            if (eventName.equals(dataHandler.getCurrentSubTableContent(i, 0))) {
                detail = true;
            }
        }
        return detail;
    }

    /**
     * Method saveEntries - saves the data
     * @return String - next JSP to call.
     */
    private String saveEntries(HttpServletRequest request) {
        String nextJSP = null;
        boolean valuesOK = true;
        // We loop through all entries and check
        // which row has been selected. If we find a selected row we delete the entry.
        // We use the request.getParameter(valueOfCheckbox) method to find out which checkbox is clicked. The valueOfCheckbox
        // is stored in the first column of the databean.
        // If no row is selected we display a hint to select a row first.
        for (int i = 0; i < dataHandler.getTableRows(); i++) {
            String inputFieldString = (String) request.getParameter(dataHandler.getCurrentSubTableContent(i, 0));
            if (inputFieldString != null) {
                // Inputfield contains new amount for stock
                String synckey = dataHandler.getCurrentSubTableContent(i, 0);

                // If there is a synckey, get entry and check if value has been changed
                if (synckey.length() > 0) {
                    String currentAmount = dataHandler.getCurrentSubTableContent(i, I_QUANTITY);
                    int newAmount = 0;
                    int oldAmount = 0;
                    try {
                        newAmount = Integer.parseInt(inputFieldString);
                    } catch (NumberFormatException e) {
                        // Not a integer value - do not save value
                        valuesOK = false;
                    }
                    try {
                        oldAmount = Integer.parseInt(currentAmount);
                    } catch (NumberFormatException e) {
                        // Not a integer value - probably an empty field
                        oldAmount = 0;
                    }
                    if (oldAmount != newAmount && valuesOK == true) {
                        System.out.println("Save new value");
                        dataHandler.modifyEntry(synckey, inputFieldString, I_QUANTITY);
                    }
                }
            }
        }

        nextJSP = INITIAL_JSP;
        if (valuesOK == false)
            nextJSP = SAVEFAIL_JSP;

        return nextJSP;
    }

    /**
     * Method addEntry. - Adds an Entry according to user input
     * @return String - next JSP to call
     */
    private void addEntry(HttpServletRequest request) {

        // We take the content of the inputfield in the JSP named according to the tableheadername
        // As next JSP we set the INITIAL_JSP again.

        String[] newValues = new String[dataHandler.getColumns()];

        for (int i = 0; i < dataHandler.getColumns(); i++) {
            if (dataHandler.getTableHeaderName(i) != null) {
                newValues[i] = (String) request.getParameter(dataHandler.getTableHeaderName(i));
            }
            // Quantity default value is 0
            if (i == I_QUANTITY) {
                newValues[i] = "0";
            }
        }
        dataHandler.addEntry(newValues);
        return;
    }

    /**
     * Method setFilter - according to user input a filter string will be set up.
     * @param request
     * @return String - next JSP to call
     */
    private String setFilter(HttpServletRequest request) {
        filter_string = (String) request.getParameter("PRODUCTID");
        if (filter_string.length() == 0) {
            setFilterOff();
        } else {
            // The product id can be filtered. When the filter is activated, only products with a product ID that starts
            // with the specified filter are displayed.
            setFilterOn(I_PRODUCTID, filter_string);
            // we also set the current page to one - so that we see the entries
            setCurrenPage(1);
        }
        return INITIAL_JSP;
    }

    private void getBeansFromContext(HttpServletRequest request, boolean refreshSyncBoCount) {
        // Get table defintion bean from session context. There is a bean, when this servlet has already been called once.
        tableViewDefinition = (TableViewDefinition) request.getSession().getAttribute("tableViewDefinition");
        // No bean in session context - create a new instance.
        if (tableViewDefinition == null)
            tableViewDefinition = new TableViewDefinition();

        // we create a new dataHandler instance to read all data according to the actual settings
        dataHandler = BasicDataHandler.instance(refreshSyncBoCount, start_index, MAX_TABLE_ROWS, sort_index, sort_ascending, filter_string);
    }

    public void loadBean() {
        // Set headerpanel
        // The left side displays the MI icon, that canbe clicked to go back to the MI home page
        tableViewDefinition.setHeaderPanelEntryLeft("<a href=\"http://127.0.0.1:4444/me\" > <img src=\"mimes/milogo.gif\" alt=\"MI Home\" ></a>");
        // The right side displays the text MDK
        tableViewDefinition.setHeaderPanelEntryRight("MDK");
        // Setup Commands for this example. Commands are displayed on the top of the centerpage.
        // In this example we use add, delete, filter and list all commands.
        setCommands();

        // Set footerpanel
        // The left side displays the application name
        tableViewDefinition.setFooterPanelEntryLeft(current_filter_string);
        // The right side displays the type of the example
        tableViewDefinition.setFooterPanelEntryRight(currentPageFooter);

        // set commands for application - the commands have been set in the initialize method already
        tableViewDefinition.setCommandLine(commandLine);

        // set title of the center window
        tableViewDefinition.setCenterPageTitle(pageTitle);

        // Generate table header
        setTableHeader();

        // Generate data and set Vector in bean
        dataHandler.getDataArray();

        // The following variables are necessary for the navigation
        dataHandler.setTableRows(MAX_TABLE_ROWS);
        dataHandler.setTableColumns(dataHandler.getColumns());
        dataHandler.setRowsInDataset(dataHandler.getRowsInDataset());
        dataHandler.setCurrentIndex(start_index);
    }

    private void putBeansIntoContext(HttpServletRequest request) {
        // Put table definition bean in session context
        if (tableViewDefinition == null) {
            request.getSession().removeAttribute("tableViewDefintion");
        } else {
            request.getSession().setAttribute("tableViewDefinition", tableViewDefinition);
        }

        // Put data defintion in session context
        if (dataHandler == null) {
            request.getSession().removeAttribute("dataHandler");
        } else {
            request.getSession().setAttribute("dataHandler", dataHandler);
        }
    }

    /**
     * Method setFilterOff - All Data without Filter are displayed.
     */
    private void setFilterOff() {
        sort_index = I_PRODUCTID;
        // Set sorting variables.
        sort_ascending = true;
        buttontextQuery = BUTTON_QUERY_TEXT;
        current_filter_string = "No Filter";
        filter_string = "";
    }

    private void setFilterOn(int index, String filter_string) {
        buttontextQuery = BUTTON_QUERY_RESET_TEXT;
        current_filter_string = "Filter: " + filter_string;
        sort_index = index;
    }

    private void setCommands() {
        // The command line contain add, delete, set filter and list all
        // Add command 
        // commandLine.clear();
        commandLine.removeAllElements();
        // commandLine.add("<input type=\"submit\" value=\"Add\" class=\"image\" name=\"_event_" + EVENT_ADDENTRY + "\">");
        commandLine.addElement("<input type=\"submit\" value=\"Add\" class=\"image\" name=\"_event_" + EVENT_ADDENTRY + "\">");
        // Set Filter command 
        // commandLine.add("<input type=\"submit\" value=\"" + buttontextQuery + "\" class=\"image\" name=\"_event_" + EVENT_QUERY + "\">");
        commandLine.addElement("<input type=\"submit\" value=\"" + buttontextQuery + "\" class=\"image\" name=\"_event_" + EVENT_QUERY + "\">");
        // Delete command 
        // commandLine.add("<input type=\"submit\" value=\"Save\" class=\"image\" name=\"_event_" + EVENT_SAVE + "\">");
        commandLine.addElement("<input type=\"submit\" value=\"Save\" class=\"image\" name=\"_event_" + EVENT_SAVE + "\">");

    }

    // Load array in Bean with Information about the Mobile Engine, i is the index for the entries
    private void setTableHeader() {
        int headercol = dataHandler.getColumns();
        dataHandler.initTableHeader(headercol);

        for (int i = 0; i < headercol; i++) {
            // dataHandler.setTableHeaderEntry(i, dataHandler.getTableHeaderName(i));
            dataHandler.setTableHeaderEntry(dataHandler.getTableHeaderName(i), i);
        }
    }
}