recite18th.controller.Controller.java Source code

Java tutorial

Introduction

Here is the source code for recite18th.controller.Controller.java

Source

/*
Recite18th is a simple, easy to use and straightforward Java Database 
Web Application Framework. See http://code.google.com/p/recite18th
Copyright (C) 2011  Eko Suprapto Wibowo (swdev.bali@gmail.com)
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program 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 General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see http://www.gnu.org/licenses/.
    
HISTORY:
1) Forgot of when 1st created this file
2) August 4, 2011 = about to add reporting feature using iText
http://www.geek-tutorials.com/java/itext/servlet_jsp_output_pdf.php0C
 */
package recite18th.controller;

import recite18th.model.Model;
import recite18th.util.ServletUtil;
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//multi-part data
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.servlet.*;
import org.apache.commons.fileupload.disk.*;
import java.io.*;
import java.util.*;
import org.apache.commons.beanutils.PropertyUtils;

//authorization
import recite18th.util.LoginUtil;

//reporting

import java.sql.*;
import recite18th.library.Db;
import application.config.*;
import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.HeaderFooter;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfTemplate;
import com.lowagie.text.pdf.PdfWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class Controller extends HttpServlet {

    protected Model modelForm;
    protected Model modelRow;
    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected String viewPage;
    protected String formPage;
    private Hashtable params; //parameter for sql INSERT/UPDATE manipulation
    private HashMap formParams = new HashMap(); //parameter populate by form. I make it private, I want to make sure all field data get by method getFormFieldValue
    protected List row = new ArrayList();
    protected String controllerName;
    protected String sqlViewDataPerPage;
    protected String sqlViewDataPerPageForReport;
    boolean isMultipart;
    //authorization things...
    protected boolean isNeedAuthorization = false;//default controller is free
    protected String authorList = null;//if isNeedAuthorization is true, then this mean all authorized user can access this controller. IDEA: controller level || method level authorization :)

    public void doSave() {
        modelForm.save(fillParams());
    }

    public void goAfterSave() {
        ServletUtil.redirect(Config.base_url + "index/" + controllerName, request, response);
    }

    public boolean isNewData() {
        //get field value of primary key
        modelForm.setPkFieldValue(getFormFieldValue(modelForm.getPkFieldName()));
        boolean bIsNewData = "".equals(modelForm.getPkFieldValue());
        Logger.getLogger(Controller.class.getName()).log(Level.INFO, "isNewData = " + bIsNewData);
        return bIsNewData;
    }

    public void save() {
        processFormData();
        if (validationRun()) {
            doSave();
            goAfterSave();
        } else {
            //restored inputted values
            input("-2");//TOFIX : somehow, I can not move the -2 case code from input() into this place...
        }
    }

    protected void initSqlViewDataPerPage() {
        Model model = initModel();
        if (sqlViewDataPerPage == null) {
            sqlViewDataPerPage = "select * from " + model.getTableName();
        }
    }

    protected Model initModel() {
        Model model;
        if (modelRow == null) {
            model = modelForm;
        } else {
            model = modelRow;
        }
        return model;
    }
    /*
    Extracted from index() to allow getting default list of model be called from another method, e.g print()
     */

    protected List getDefaultListOfModel() {
        row = null;
        Model model = initModel();
        ;

        if (model != null) {
            initSqlViewDataPerPage();
            row = model.getDataPerPage(sqlViewDataPerPage);
        }
        return row;
    }

    /**
     * Open main view for this controller
     */
    public void index() {
        // check whether we need to prepare database model to be displayed
        row = getDefaultListOfModel();
        if (row != null) {
            request.setAttribute("row", row);
        }

        // AUTHORIZATION MODULE : check whether current authorization is enough
        // TODO : A more flexible approach.
        try {
            if (!isNeedAuthorization)//doesn't need authorization
            {
                ServletUtil.dispatch("/WEB-INF/views/" + viewPage, request, response);
            } else {
                if (isNeedAuthorization && LoginUtil.isLogin(request))//need authorization and already login
                {
                    if (authorList == null || "".equals(authorList))//.. but with no authorlist defined
                    {
                        ServletUtil.dispatch("/WEB-INF/views/" + viewPage, request, response);
                    } else //..with authorlist defined
                    {
                        String role = LoginUtil.getLoginRole(request);
                        //TOFIX : not just contains(), but split it, and compare each component of it
                        if (authorList.contains(role)) {
                            ServletUtil.dispatch("/WEB-INF/views/" + viewPage, request, response);
                        }
                    }

                } else if (isNeedAuthorization && !LoginUtil.isLogin(request)) //need authorization and not login
                {
                    ServletUtil.redirect(Config.base_url + "index/" + Config.loginController, request, response);
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
            ServletUtil.dispatch(Config.base_url + Config.page404, request, response);
        }
    }

    /**
     * open another view for this controller
     * @param page
     */
    public void index(String page) {
        ServletUtil.dispatch("/WEB-INF/views/" + page, request, response);
        /*String oldViewPage = viewPage;
        viewPage = page;
        index();
        viewPage = oldViewPage;*/
    }

    public void input(String pkFieldValue) {
        try {
            if (pkFieldValue.equals("-2")) {
                //masukkan nilai yg tadi dimasukkan.. hadeuh...            
                //Drawbacks : semua field harus didefinisikan jenis validasinya. dan itu ga baik. TODO : ubah ke formParams
                //dan sesuaikan dengan ada/tidaknya fieldnya dari model. Jika ada, baru diset. Jika tidak, berarti kontrol lain,e.g, Submit
                //SOLVED! Already use formParams to refill the value

                Enumeration e = validation.keys();
                Model.session = request.getSession();//store session here
                modelForm = modelForm.createNewModel();
                while (e.hasMoreElements()) {
                    //TOFIX : restore PK Field Value and Foreign Field. 
                    //SOLVED. PK Field restored by refilled the value using formParams, whilst Foreign Field restored by adding translated value in corresponding model class
                    String ruleName = (String) e.nextElement();
                    String value = getFormFieldValue(ruleName);
                    try {
                        PropertyUtils.setSimpleProperty(modelForm, ruleName, value);
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                                "validasi error, mengisi kembali " + ruleName + ", dengan value = " + value);
                    } catch (Exception exception) {
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO, exception.getMessage());
                    }
                }

                String key = null, value = null;
                Iterator it = formParams.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry pairs = (Map.Entry) it.next();
                    Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                            pairs.getKey() + " = " + pairs.getValue());

                    try {
                        key = pairs.getKey() + "";
                        value = pairs.getValue() + "";
                        if (key.equals("hidden_" + modelForm.getPkFieldName())) {
                            PropertyUtils.setSimpleProperty(modelForm, modelForm.getPkFieldName(), value);
                        } else {
                            PropertyUtils.setSimpleProperty(modelForm, key, value);
                        }
                    } catch (Exception ex) {
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                                "prop error = " + key + ", " + value);
                    }
                }
            } else if (pkFieldValue == null || pkFieldValue.equals("") || pkFieldValue.equals("-1")) {
                Logger.getLogger(Controller.class.getName()).log(Level.INFO, "Buat Model baru");
                Model.session = request.getSession();
                modelForm = modelForm.createNewModel();
            } else {
                Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                        "Ambil model dengan ID " + pkFieldValue);
                Model.session = request.getSession();
                modelForm = modelForm.getModelById(pkFieldValue);
            }

            //TODO : maybe automatified here. But currently it's suffice ... (or being autogenerated by Synch.java.. that's it! later...)
            //expand for FOREIGN KEY label... No need. Model subclass just derived its corresponding _***Model.java, 
            //..and add a property that translate its FK field (using Db.findValue is suffice. 

            request.setAttribute("model", modelForm);
            ServletUtil.dispatch("/WEB-INF/views/" + formPage, request, response);
        } catch (Exception ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void delete(String pkFieldValue) {
        modelForm.delete(pkFieldValue);
        ServletUtil.redirect(Config.base_url + "index/" + controllerName, request, response);
    }

    public void setRequest(HttpServletRequest request) {
        this.request = request;
    }

    public void setResponse(HttpServletResponse response) {
        this.response = response;
    }

    public void processFormData() {
        //==== START OF penanganan multi-part data

        isMultipart = ServletFileUpload.isMultipartContent(request);
        if (isMultipart) {
            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);
            List items = null;
            try {
                items = upload.parseRequest(request);
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
            Iterator itr = items.iterator();

            while (itr.hasNext()) {
                FileItem item = (FileItem) itr.next();
                if (item.isFormField()) {

                    String name = item.getFieldName();
                    String value = item.getString();
                    formParams.put(name, value);
                } else {
                    //upload file here
                    try {
                        String itemName = item.getName();
                        //TOFIX : kalau FFox, itemName hanya nama file saja. Kalau IE, lengkap dengan nama folder.
                        //make sure upload folder exist
                        File fDir = new File(Config.base_path + "upload");
                        if (!fDir.exists()) {
                            fDir.mkdir();
                        }
                        String path = Config.base_path + "upload" + Config.path_delimiter + itemName;//TODO : save all to this folder || allow customization
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO, "Try to write file " + path);
                        File savedFile = new File(path);
                        item.write(savedFile);
                        formParams.put(item.getFieldName(), savedFile.getName());
                    } catch (Exception e) {
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                                "Possibly, that file doesn't exist");//TODO: better information to user
                    }
                }
            }
        }
        //==== ENDOF penanganan multi-part data
    }
    /*
     * populate a hashtable with value from form, with regards to model public field 
     * added the ability to process multi-part data (form with file field)
     */

    private Hashtable fillParams() {
        try {
            params = new Hashtable();
            Class cl = Class.forName("application.models._" + modelForm.getPlainClassName());
            //TOFIX: because we use cl.getFields(), all fields neet to be define as public
            Field[] fields = cl.getFields();
            String fieldValue;
            String fieldName;

            // NEXT : Rephrase this
            for (int i = 0; i < fields.length; i++) {
                fieldName = fields[i].getName();
                fieldValue = getFormFieldValue(fieldName);

                if (fieldName.equals(modelForm.getPkFieldName())) {
                    modelForm.setPkFieldValue(getFormFieldValue("hidden_" + fieldName));
                    Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                            "Putting field primary key from {0} into params", "hidden_" + fieldName);
                    params.put("hidden_" + fieldName, getFormFieldValue("hidden_" + fieldName));
                }

                if (fieldValue != null) {
                    params.put(fieldName, fieldValue);
                    Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                            "Putting field form {0} into params", fieldName);
                }
            }
            return params;
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;

    }

    Hashtable<String, String> validation = new Hashtable();

    public void clearValidation() {
        validation.clear();
    }

    public void validationAddRule(String ruleName, String rule) {
        validation.put(ruleName, rule);
    }

    public boolean validationRun() {
        Enumeration e = validation.keys();
        boolean allPass = true;

        Logger.getLogger(Controller.class.getName()).log(Level.INFO, "Running Validation");
        while (e.hasMoreElements()) {
            String ruleName = (String) e.nextElement();
            String rule = validation.get(ruleName);
            StringTokenizer st = new StringTokenizer(rule, "|");
            String fieldValue;
            request.removeAttribute(ruleName);
            while (st.hasMoreTokens()) {
                String token = st.nextToken().toLowerCase();
                Logger.getLogger(Controller.class.getName()).log(Level.INFO, "Rule for " + ruleName + ", " + token);
                fieldValue = getFormFieldValue(ruleName);
                if (token.equals("required")) {
                    if (fieldValue == null || "".equals(fieldValue)) {
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                                "ERROR" + ruleName + ", " + token);
                        request.setAttribute(ruleName + "_error", ruleName + " required");
                        allPass = false;
                    }
                } else if (token.contains("!=")) {
                    StringTokenizer st2 = new StringTokenizer(token, "!=");
                    String value = st2.nextToken();
                    if (fieldValue == null || value.equals(fieldValue)) {
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                                "ERROR" + ruleName + ", " + token);
                        request.setAttribute(ruleName + "_error", ruleName + " required");
                        allPass = false;
                    }
                } else if (token.contains("len==")) {
                    StringTokenizer st2 = new StringTokenizer(token, "len==");
                    String value = st2.nextToken();
                    if (fieldValue != null && fieldValue.length() != Integer.parseInt(value)) {
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                                "ERROR" + ruleName + ", " + token);
                        request.setAttribute(ruleName + "_error", ruleName + " harus memiliki panjang " + value);
                        allPass = false;
                    }
                } else if (token.equals("integer_bigger_than_zero")) {

                    int iValue = 0;
                    try {
                        iValue = Integer.parseInt(fieldValue);
                    } catch (NumberFormatException nfe) {
                        allPass = false;
                    }

                    if (iValue <= 0) {
                        allPass = false;
                    }
                    if (!allPass) {
                        Logger.getLogger(Controller.class.getName()).log(Level.INFO,
                                "ERROR" + ruleName + ", " + token);
                        request.setAttribute(ruleName + "_error", ruleName + " must be non negative");
                        allPass = false;
                    }
                }
            }
        }
        return allPass;
    }

    public String getFormFieldValue(String fieldName) {
        return isMultipart ? (formParams.get(fieldName) == null ? null : formParams.get(fieldName) + "")
                : request.getParameter(fieldName);
    }

    public void print(String action) {
        /** thanks to http://www.java2s.com/Code/Java/PDF-RTF/DemonstratesthecreatingPDFinportraitlandscape.htm
         * QUICK FIX : do landscape
         */
        response.setContentType("application/pdf"); // Code 1
        if (action.equals("download")) {
            response.setHeader("Content-Transfer-Encoding", "binary");
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + "Report " + controllerName + ".pdf\"");
        }
        Document document = new Document(PageSize.A1.rotate());
        try {
            PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream()); // Code 2
            document.open();

            // various fonts
            BaseFont bf_helv = BaseFont.createFont(BaseFont.HELVETICA, "Cp1252", false);
            BaseFont bf_times = BaseFont.createFont(BaseFont.TIMES_ROMAN, "Cp1252", false);
            BaseFont bf_courier = BaseFont.createFont(BaseFont.COURIER, "Cp1252", false);
            BaseFont bf_symbol = BaseFont.createFont(BaseFont.SYMBOL, "Cp1252", false);

            String headerImage = Config.base_path + "images/report-logo.gif";

            Image imghead = Image.getInstance(headerImage);
            imghead.setAbsolutePosition(0, 0);
            PdfContentByte cbhead = writer.getDirectContent();
            PdfTemplate tpLogo = cbhead.createTemplate(600, 300);
            tpLogo.addImage(imghead);

            PdfTemplate tpTitle = cbhead.createTemplate(1100, 300);
            String txtHeader = "BADAN KEPEGAWAIAN DAERAH PEMERINTAH DAERAH";//Config.application_title;
            tpTitle.beginText();
            tpTitle.setFontAndSize(bf_times, 36);
            tpTitle.showText(txtHeader);
            tpTitle.endText();

            PdfTemplate tpTitle2 = cbhead.createTemplate(900, 300);
            String txtHeader2 = "         KABUPATEN BANTUL YOGYAKARTA";
            tpTitle2.beginText();
            tpTitle2.setFontAndSize(bf_times, 36);
            tpTitle2.showText(txtHeader2);
            tpTitle2.endText();

            PdfTemplate tpAlamat = cbhead.createTemplate(1000, 400);
            tpAlamat.beginText();
            tpAlamat.setFontAndSize(bf_times, 24);
            tpAlamat.showText(
                    "Alamat : Jln. R. W. Monginsidi No. 01 Kompleks Parasamya Bantul, Telp. (0274) 367509");
            tpAlamat.endText();

            DateFormat df = new SimpleDateFormat("dd MMM yyyy");
            java.util.Date dt = new java.util.Date();
            PdfTemplate tp3 = cbhead.createTemplate(600, 300);
            tp3.beginText();
            tp3.setFontAndSize(bf_times, 16);

            tp3.showText("Tanggal : " + df.format(dt));
            tp3.endText();

            cbhead.addTemplate(tpLogo, 800, 1500);//logo
            cbhead.addTemplate(tpTitle, 1000, 1580);
            cbhead.addTemplate(tpTitle2, 1000, 1540);
            cbhead.addTemplate(tpAlamat, 1000, 1500);//alamat
            cbhead.addTemplate(tp3, 270, 1500);//tanggal

            HeaderFooter header = new HeaderFooter(new Phrase(cbhead + "", new Font(bf_helv)), false);
            header.setAlignment(Element.ALIGN_CENTER);

            document.setHeader(header);

            //PdfContentByte cb = writer.getDirectContent();
            Paragraph par = new Paragraph(
                    "\n\n\n\n\n\n\nLAPORAN DATA SELURUH " + controllerName.toUpperCase() + "\n");
            par.getFont().setStyle(Font.BOLD);
            par.getFont().setSize(18);
            par.setAlignment("center");
            document.add(par);
            document.add(new Paragraph("\n\n"));

            // get data
            initSqlViewDataPerPage();
            if (sqlViewDataPerPageForReport == null) {
                sqlViewDataPerPageForReport = sqlViewDataPerPage;
            }
            PreparedStatement pstmt = Db.getCon().prepareStatement(sqlViewDataPerPageForReport,
                    ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
            ResultSet resultSet = pstmt.executeQuery();
            ResultSetMetaData metaColumn = resultSet.getMetaData();
            int nColoumn = metaColumn.getColumnCount();
            // thanks to set cell width http://www.jexp.ru/index.php/Java/PDF_RTF/Table_Cell_Size#Setting_Cell_Widths
            if (nColoumn > 0) {
                Model model = initModel();
                String tableName = model.getTableName();
                // create table header
                //     float[] widths = {1, 4};
                PdfPTable table;// = new PdfPTable(nColoumn);
                PdfPCell cell = new PdfPCell(new Paragraph("Daftar " + controllerName));

                Hashtable hashModel = TableCustomization.getTable(model.getTableName());

                int ncolumnHeader = nColoumn + 1; // +1 because of row. number
                if (hashModel != null) {
                    ncolumnHeader = Integer.parseInt("" + hashModel.get("columnCount")) + 1;
                }
                table = new PdfPTable(ncolumnHeader);
                cell.setColspan(ncolumnHeader);
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);

                Paragraph p2 = new Paragraph("No.");
                p2.getFont().setSize(20);
                PdfPCell cellColNo = new PdfPCell(p2);
                cellColNo.setNoWrap(true);
                cellColNo.setMinimumHeight(50);
                cellColNo.setHorizontalAlignment(Element.ALIGN_CENTER);
                table.addCell(cellColNo);

                if (hashModel != null) {
                    Enumeration k = hashModel.keys();
                    while (k.hasMoreElements()) {
                        String key = (String) k.nextElement();
                        if (key.equals("columnCount")) {
                            continue;
                        }
                        PdfPCell cellCol = new PdfPCell(new Paragraph(hashModel.get(key) + ""));
                        cellCol.setNoWrap(true);
                        cellCol.setMinimumHeight(50);
                        cellCol.setHorizontalAlignment(Element.ALIGN_CENTER);

                        table.addCell(cellCol);
                    }
                } else {
                    for (int i = 1; i < ncolumnHeader; i++) {
                        System.out.println("DATA = " + metaColumn.getColumnName(i));
                        Paragraph p1 = new Paragraph(metaColumn.getColumnName(i) + "");
                        p1.getFont().setSize(20);
                        PdfPCell cellCol = new PdfPCell(p1);
                        cellCol.setHorizontalAlignment(Element.ALIGN_CENTER);
                        table.addCell(cellCol);
                    }
                }

                //iterate all columns : table data
                resultSet.beforeFirst();
                int row = 1;
                while (resultSet.next()) {
                    System.out.println(row);
                    Paragraph p3 = new Paragraph(row + "");
                    p3.getFont().setSize(20);
                    cell = new PdfPCell(p3);
                    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                    table.addCell(cell);
                    if (hashModel != null) {//skip dulu u/ kasus ga pny class kustomasi table
                        Enumeration k = hashModel.keys();
                        while (k.hasMoreElements()) {
                            String key = (String) k.nextElement();
                            if (key.equals("columnCount")) {
                                continue;
                            }
                            table.addCell(resultSet.getObject(key) + "");
                        }
                    } else {
                        for (int i = 1; i < ncolumnHeader; i++) {
                            System.out.println("DATA = " + metaColumn.getColumnName(i));
                            Paragraph p1 = new Paragraph(resultSet.getObject(metaColumn.getColumnName(i)) + "");
                            p1.getFont().setSize(18);
                            PdfPCell cellCol = new PdfPCell(p1);
                            cellCol.setHorizontalAlignment(Element.ALIGN_CENTER);
                            table.addCell(cellCol);
                        }
                    }

                    row++;
                }

                document.add(table);
                document.add(new Paragraph("\n\n"));
                par = new Paragraph("Mengetahui");
                par.setAlignment("center");
                document.add(par);
                par = new Paragraph("Kepada Badan Kepegawaian");
                par.setAlignment("center");
                document.add(par);
                par = new Paragraph("\n\n\n");

                document.add(par);
                par = new Paragraph("Drs. Maman Permana");
                par.setAlignment("center");
                document.add(par);
                par = new Paragraph("Nip: 197802042006041013");
                par.setAlignment("center");

                document.add(par);

            }
            document.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}