Package org.happyfaces.beans.base

Source Code of org.happyfaces.beans.base.BaseBean

package org.happyfaces.beans.base;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.happyfaces.domain.base.IEntity;
import org.happyfaces.jsf.datatable.PaginationConfiguration;
import org.happyfaces.services.base.IService;
import org.happyfaces.utils.FacesUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

/**
* Base bean class. Other jsf backing beans extends this class to get basic crud
* functionality + out of box search functionality. Bean should be ViewScoped.
*
* @author Ignas
*
* @param <T>
*            BaseBean entity type.
*/
public abstract class BaseBean<T extends IEntity> implements Serializable {

    /** */
    private static final long serialVersionUID = 1L;

    /** Logger. */
    private static Logger log = Logger.getLogger(BaseBean.class.getName());

    /** Search filters. */
    private Map<String, Object> filters;

    /** Class of backing bean. */
    private Class<T> clazz;

    /**
     * Loaded entity for edit or view.
     */
    private T entity;

    /**
     * Request parameter. Used for loading in object by its id.
     */
    private Long objectId;

    /**
     * Request parameter.
     */
    private boolean edit = false;

    /**
     * Datamodel for lazy dataloading in datatable.
     */
    private LazyDataModel<T> dataModel;

    /**
     * Bind datatable for search results.
     */
    private DataTable dataTable;

    /**
     * Selected Entities in multiselect datatable.
     */
    private IEntity[] selectedEntities;

    /**
     * Constructor.
     *
     * @param clazz
     *            Class.
     */
    public BaseBean(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    /**
     * Returns entity class.
     *
     * @return Class
     */
    public Class<T> getClazz() {
        return clazz;
    }

    /**
     * Initiates entity from request parameter id. If request parameter does not
     * exist - create new object for entity.
     *
     * @return Entity from database.
     */
    public T initEntity() {
        if (getObjectId() != null) {
            if (getFormFieldsToFetch() == null) {
                entity = getPersistenceService().findById(getObjectId());
            } else {
                entity = getPersistenceService().findById(getObjectId(), getFormFieldsToFetch());
            }
        } else {
            try {
                entity = getInstance();
            } catch (InstantiationException e) {
                log.error("Unexpected error!", e);
                throw new IllegalStateException("could not instantiate a class, abstract class");
            } catch (IllegalAccessException e) {
                log.error("Unexpected error!", e);
                throw new IllegalStateException("could not instantiate a class, constructor not accessible");
            }
        }
        return entity;
    }

    /**
     * When opened to view or edit entity - this getter method returns it. In
     * case entity is not loaded it will initialize it.
     *
     * @return Entity in current view state.
     */
    public T getEntity() {
        return entity != null ? entity : initEntity();
    }

    /**
     * This method is invoked from JSF page and current entity loaded in view
     * scope is saved or updated to database.
     */
    public String save() {
        try {
            if (entity != null) {
                saveOrUpdate(entity);
                return getViewAfterSave();
            } else {
                log.error("save() method was invoked when when no entity was loaded");
                FacesUtils.error("system.saveError");
            }
        } catch (Throwable e) {
            log.error(String.format("Unexpected error when saving entity %s with id %s", clazz.getName(), entity.getId()), e);
            FacesUtils.error("system.saveError");
        }
        return null;
    }

    /**
     * Save or update entity depending on if entity is transient.
     *
     * @param entity
     *            Entity to save.
     */
    public void saveOrUpdate(T entity) {
        if (entity.isTransient()) {
            getPersistenceService().add(entity);
            FacesUtils.info("save.successful");
        } else {
            getPersistenceService().update(entity);
            FacesUtils.info("update.successful");
        }
    }

    /**
     * Lists all entities.
     */
    public List<T> listAll() {
        return getPersistenceService().list();
    }

    /**
     * Returns view after save() operation. By default it goes back to list
     * view. Override if need different logic (for example return to one view
     * for save and another for update operations)
     */
    public String getViewAfterSave() {
        return getListViewName();
    }

    /**
     * Generating action name to get to entity creation page. Override this
     * method if its view name does not fit.
     */
    public String getNewViewName() {
        return getEditViewName();
    }

    /**
     * Generating action name to get to entity view/edit page. Override this
     * method if its view name does not fit.
     */
    public String getEditViewName() {
        String className = clazz.getSimpleName();
        StringBuilder sb = new StringBuilder(className);
        sb.append("Edit");
        char[] dst = new char[1];
        sb.getChars(0, 1, dst, 0);
        sb.replace(0, 1, new String(dst).toLowerCase());
        return sb.toString();
    }

    /**
     * Generating action name to get back to entity list view. Invoked from
     * save() method. Override this method if its view name does not fit.
     */
    public String getListViewName() {
        String className = clazz.getSimpleName();
        StringBuilder sb = new StringBuilder(className);
        char[] dst = new char[1];
        sb.getChars(0, 1, dst, 0);
        sb.replace(0, 1, new String(dst).toLowerCase());
        sb.append("s");
        return sb.toString();
    }

    /**
     * Delete Entity using it's ID. Add error message to statusMessages.
     * if unsuccessful.
     *
     * @param id
     *            Entity id to delete
     */
    public void delete(Long id) {
        try {
            log.info(String.format("Deleting entity %s with id = %s", clazz.getName(), id));
            getPersistenceService().delete(id);
            FacesUtils.info("delete.successful");
        } catch (Throwable t) {
            if (t.getCause() instanceof ConstraintViolationException) {
                log.info("delete was unsuccessful because entity is used in the system", t);
                FacesUtils.error("delete.entityUsed");
            } else {
                log.info("unexpected exception when deleting!", t);
                FacesUtils.error("delete.unexpected");
            }
        }
    }

    /**
     * Delete checked entities. Add error message to statusMessages if
     * unsuccessful.
     */
    public void deleteMany() {
        try {
            if (selectedEntities != null && selectedEntities.length > 0) {
                Set<Long> idsToDelete = new HashSet<Long>();
                StringBuilder idsString = new StringBuilder();
                for (IEntity entityToDelete : selectedEntities) {
                    idsToDelete.add((Long) entityToDelete.getId());
                    idsString.append(entityToDelete.getId()).append(" ");
                }
                log.info(String.format("Deleting multiple entities %s with ids = %s", clazz.getName(), idsString.toString()));
                getPersistenceService().deleteMany(idsToDelete);
                FacesUtils.info("delete.successful");
            } else {
                FacesUtils.warn("delete.noSelection");
            }
        } catch (Throwable t) {
            if (t.getCause() instanceof ConstraintViolationException) {
                log.info("delete was unsuccessful because entity is used in the system", t);
                FacesUtils.error("delete.entityUsed");
            } else {
                log.info("unexpected exception when deleting!", t);
                FacesUtils.error("delete.unexpected");
            }
        }
    }

    /**
     * Gets search filters map.
     *
     * @return Filters map.
     */
    public Map<String, Object> getFilters() {
        if (filters == null) {
            filters = new HashMap<String, Object>();
        }
        return filters;
    }

    /**
     * Clean search fields in datatable.
     */
    public void clean() {
        filters = new HashMap<String, Object>();
    }

    /**
     * Reset values to the last state.
     */
    public void resetFormEntity() {
        entity = null;
        entity = getEntity();
    }

    /**
     * Get new instance for backing bean class.
     *
     * @return New instance.
     *
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public T getInstance() throws InstantiationException, IllegalAccessException {
        return clazz.newInstance();
    }

    /**
     * Method that returns concrete PersistenceService. That service is then
     * used for operations on concrete entities (eg. save, delete etc).
     *
     * @return Persistence service
     */
    protected abstract IService<T> getPersistenceService();

    /**
     * Override this method if you need to fetch any fields when selecting list
     * of entities in data table. Return list of field names that has to be
     * fetched.
     */
    protected List<String> getListFieldsToFetch() {
        return null;
    }

    /**
     * Override this method if you need to fetch any fields when selecting one
     * entity to show it a form. Return list of field names that has to be
     * fetched.
     */
    protected List<String> getFormFieldsToFetch() {
        return null;
    }

    /**
     * DataModel for primefaces lazy loading datatable component.
     *
     * @return LazyDataModel implementation.
     */
    public LazyDataModel<T> getLazyDataModel() {
        if (dataModel == null) {
            dataModel = new LazyDataModel<T>() {

                private static final long serialVersionUID = 1L;

                private Integer rowCount;

                private Integer rowIndex;

                /**
                 * @see org.primefaces.model.LazyDataModel#load(int, int,
                 *      java.lang.String, org.primefaces.model.SortOrder,
                 *      java.util.Map)
                 */
                @Override
                public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> loadingFilters) {
                    Map<String, Object> copyOfFilters = new HashMap<String, Object>();
                    copyOfFilters.putAll(getFilters());
                    setRowCount((int) getPersistenceService().count(
                            new PaginationConfiguration(first, pageSize, copyOfFilters, getListFieldsToFetch(), sortField, sortOrder)));
                    if (getRowCount() > 0) {
                        copyOfFilters = new HashMap<String, Object>();
                        copyOfFilters.putAll(getFilters());
                        return getPersistenceService().list(
                                new PaginationConfiguration(first, pageSize, copyOfFilters, getListFieldsToFetch(), sortField, sortOrder));
                    } else {
                        return null; // no need to load then
                    }
                }

                /**
                 * @see org.primefaces.model.LazyDataModel#getRowData(java.lang.String)
                 */
                @Override
                public T getRowData(String rowKey) {
                    return getPersistenceService().findById(Long.valueOf(rowKey));
                }

                /**
                 * @see org.primefaces.model.LazyDataModel#getRowKey(java.lang.Object)
                 */
                @Override
                public Object getRowKey(T object) {
                    return object.getId();
                }

                /**
                 * @see org.primefaces.model.LazyDataModel#setRowIndex(int)
                 */
                @Override
                public void setRowIndex(int rowIndex) {
                    if (rowIndex == -1 || getPageSize() == 0) {
                        this.rowIndex = rowIndex;
                    } else {
                        this.rowIndex = rowIndex % getPageSize();
                    }
                }

                /**
                 * @see org.primefaces.model.LazyDataModel#getRowData()
                 */
                @SuppressWarnings("unchecked")
                @Override
                public T getRowData() {
                    return ((List<T>) getWrappedData()).get(rowIndex);
                }

                /**
                 * @see org.primefaces.model.LazyDataModel#isRowAvailable()
                 */
                @SuppressWarnings({ "unchecked" })
                @Override
                public boolean isRowAvailable() {
                    if (getWrappedData() == null) {
                        return false;
                    }

                    return rowIndex >= 0 && rowIndex < ((List<T>) getWrappedData()).size();
                }

                /**
                 * @see org.primefaces.model.LazyDataModel#getRowIndex()
                 */
                @Override
                public int getRowIndex() {
                    return this.rowIndex;
                }

                /**
                 * @see org.primefaces.model.LazyDataModel#setRowCount(int)
                 */
                @Override
                public void setRowCount(int rowCount) {
                    this.rowCount = rowCount;
                }

                /**
                 * @see org.primefaces.model.LazyDataModel#getRowCount()
                 */
                @Override
                public int getRowCount() {
                    if (rowCount == null) {
                        rowCount = (int) getPersistenceService().count();
                    }
                    return rowCount;
                }

            };
        }
        return dataModel;
    }

    /**
     * Invoked when search button is pressed. Primefaces datatable is reset on
     * that action.
     */
    public String search() {
        dataTable.reset();
        return null;
    }

    /**
     * Return binded primefaces datatable.
     */
    public DataTable getDataTable() {
        return dataTable;
    }

    /**
     * Set primefaces datatable.
     */
    public void setDataTable(DataTable dataTable) {
        this.dataTable = dataTable;
    }

    /**
     * Selected entities getter. (selected with checkoboxes in first datatable
     * column).
     */
    public IEntity[] getSelectedEntities() {
        if (selectedEntities != null) {
            return Arrays.copyOf(selectedEntities, selectedEntities.length);
        } else {
            return null;
        }
    }

    /**
     * Selected entities setter.
     */
    public void setSelectedEntities(IEntity[] selectedEntities) {
        if (selectedEntities != null) {
            this.selectedEntities = Arrays.copyOf(selectedEntities, selectedEntities.length);
        }
    }

    /**
     * Object id set from url param in edit form. If not set then form is used
     * for new entity creation.
     */
    public Long getObjectId() {
        return objectId;
    }

    /**
     * ObjectId setter.
     */
    public void setObjectId(Long objectId) {
        this.objectId = objectId;
    }

    /**
     * Object id set from url param in edit form. If not set then form is used
     * for new entity creation.
     */
    public boolean isEdit() {
        return edit;
    }

    /**
     * ObjectId setter.
     */
    public void setEdit(boolean edit) {
        this.edit = edit;
    }

}
TOP

Related Classes of org.happyfaces.beans.base.BaseBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.