org.azrul.langkuik.framework.webgui.BeanView.java Source code

Java tutorial

Introduction

Here is the source code for org.azrul.langkuik.framework.webgui.BeanView.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.azrul.langkuik.framework.webgui;

import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.fieldgroup.BeanFieldGroup;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
import com.vaadin.data.util.converter.AbstractStringToNumberConverter;
import com.vaadin.navigator.Navigator;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.server.Resource;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.server.UserError;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractTextField;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.DateField;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Window;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import org.azrul.langkuik.annotations.Choice;
import org.azrul.langkuik.annotations.EntityUserMap;
import org.azrul.langkuik.annotations.WebEntity;
import org.azrul.langkuik.annotations.WebField;
import org.azrul.langkuik.dao.DataAccessObject;
import org.azrul.langkuik.dao.HibernateGenericDAO;
import org.azrul.langkuik.framework.PageParameter;
import org.azrul.langkuik.framework.activechoice.ActiveChoiceEnum;
import org.azrul.langkuik.framework.activechoice.ActiveChoiceTarget;
import org.azrul.langkuik.framework.activechoice.ActiveChoiceUtils;
import org.azrul.langkuik.framework.activechoice.EmptyEnum;
import org.azrul.langkuik.framework.customtype.CustomType;
import org.azrul.langkuik.framework.customtype.attachment.AttachmentCustomTypeUICreator;
import org.azrul.langkuik.framework.webgui.breadcrumb.BreadCrumbBuilder;
import org.azrul.langkuik.framework.webgui.breadcrumb.History;
import org.azrul.langkuik.security.constant.ComponentState;
import org.azrul.langkuik.security.role.EntityRight;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

public class BeanView<P, C> extends VerticalView {

    private C currentBean;
    private P parentBean;
    private String parentToCurrentBeanField;
    private final DataAccessObject<C> dao;
    private final PageParameter pageParameter;

    public BeanView(C currentBean, P parentBean, String parentToCurrentBeanField, PageParameter pageParameter) {
        this.currentBean = currentBean;
        this.pageParameter = pageParameter;
        this.dao = new HibernateGenericDAO<>(pageParameter.getEntityManagerFactory(),
                (Class<C>) currentBean.getClass());
        this.parentBean = parentBean;
        this.parentToCurrentBeanField = parentToCurrentBeanField;
        // this.parentBean = parentBean;
    }

    public void setViewResource(String key, Resource resource) {
        this.setResource(key, resource);

    }

    public Resource getViewResource(String key) {
        return this.getResource(key);
    }

    @Override
    public void enter(final ViewChangeListener.ViewChangeEvent vcevent) {
        setCurrentView(vcevent.getViewName());
        //reset form
        this.removeAllComponents();

        //determine user details
        UserDetails userDetails = null;
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (!(auth instanceof AnonymousAuthenticationToken)) {
            userDetails = (UserDetails) auth.getPrincipal();
        } else {
            return;
        }

        final Set<String> currentUserRoles = new HashSet<>();
        for (GrantedAuthority grantedAuth : userDetails.getAuthorities()) {
            currentUserRoles.add(grantedAuth.getAuthority());
        }

        //determine entity rights 
        EntityRight entityRight = null;

        EntityUserMap[] entityUserMaps = ((WebEntity) currentBean.getClass().getAnnotation(WebEntity.class))
                .userMap();
        for (EntityUserMap e : entityUserMaps) {
            if (currentUserRoles.contains(e.role()) || ("*").equals(e.role())) {
                entityRight = e.right();
                break;
            }
        }
        if (entityRight == null) { //if entityRight=EntityRight.NONE, still allow to go through because field level might be accessible
            //Not accessible
            return;
        }

        //create bean utils
        final BeanUtils beanUtils = new BeanUtils();

        //rebuild pageParameter.getBreadcrumb()
        BreadCrumbBuilder.buildBreadCrumb(vcevent.getNavigator(), pageParameter.getBreadcrumb(),
                pageParameter.getHistory());

        //rebuild components
        if (currentBean == null) {
            return;
        }

        //refresh current item
        C newBean = dao.refresh(currentBean);
        if (newBean != null) {
            currentBean = newBean;
        }

        final BeanFieldGroup fieldGroup = new BeanFieldGroup(currentBean.getClass());
        fieldGroup.setItemDataSource(currentBean);
        final FormLayout form = new FormLayout();
        Map<String, Map<Integer, FieldContainer>> groups = beanUtils.createGroupsFromBean(currentBean.getClass());

        //render form according to tab
        if (groups.size() == 1) {
            createForm(entityRight, currentUserRoles, groups, fieldGroup, pageParameter.getCustomTypeDaos(),
                    vcevent.getNavigator(), form);
        } else {
            TabSheet tabSheet = new TabSheet();
            for (String group : groups.keySet()) {
                if (("All").equals(group)) {
                    createForm(entityRight, currentUserRoles, groups, group, fieldGroup,
                            pageParameter.getCustomTypeDaos(), vcevent.getNavigator(), form);
                } else {
                    FormLayout tab = new FormLayout();
                    createForm(entityRight, currentUserRoles, groups, group, fieldGroup,
                            pageParameter.getCustomTypeDaos(), vcevent.getNavigator(), tab);
                    tabSheet.addTab(tab, group);

                }
            }
            form.addComponent(tabSheet);
        }

        //Navigation and actions
        HorizontalLayout navButtons = new HorizontalLayout();
        navButtons.setSpacing(true);

        Button saveAndBackBtn = new Button("Save and back", new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                try {
                    fieldGroup.commit();
                    currentBean = (C) fieldGroup.getItemDataSource().getBean();
                    currentBean = saveBean(currentBean, parentBean, beanUtils, currentUserRoles);
                    if (!pageParameter.getHistory().isEmpty()) {
                        String currentView = pageParameter.getHistory().pop().getViewHandle();
                        String lastView = pageParameter.getHistory().peek().getViewHandle();
                        vcevent.getNavigator().removeView(currentView);
                        vcevent.getNavigator().navigateTo(lastView);
                    }
                } catch (FieldGroup.CommitException ex) {
                    handleFieldsError(fieldGroup);
                }
            }

        });
        navButtons.addComponent(saveAndBackBtn);
        saveAndBackBtn.setId(saveAndBackBtn.getCaption());

        form.addComponent(navButtons);
        form.setMargin(new MarginInfo(true));
        this.addComponent(form);
    }

    private void createForm(EntityRight entityRight, final Set<String> currentUserRoles,
            final Map<String, Map<Integer, FieldContainer>> groups, final BeanFieldGroup fieldGroup,
            final List<DataAccessObject<?>> customTypeDaos, Navigator nav, final FormLayout form)
            throws FieldGroup.BindException, UnsupportedOperationException {
        createForm(entityRight, currentUserRoles, groups, null, fieldGroup, customTypeDaos, nav, form);
    }

    private void createForm(EntityRight entityRight, final Set<String> currentUserRoles,
            final Map<String, Map<Integer, FieldContainer>> groups, String group, final BeanFieldGroup fieldGroup,
            final List<DataAccessObject<?>> customTypeDaos, final Navigator nav, final FormLayout form)
            throws FieldGroup.BindException, UnsupportedOperationException {
        //create bean utils
        final BeanUtils beanUtils = new BeanUtils();

        //select which group we want
        Map<Integer, FieldContainer> fieldContainerMap = null;
        if (group == null) {
            fieldContainerMap = groups.entrySet().iterator().next().getValue();
        } else {
            fieldContainerMap = groups.get(group);
        }

        //collect all activechoices
        Map<com.vaadin.ui.ComboBox, ActiveChoiceTarget> activeChoicesWithFieldAsKey = new HashMap<>();
        Map<String, com.vaadin.ui.ComboBox> activeChoicesFieldWithHierarchyAsKey = new HashMap<>();

        //collect all cutsom types
        List<Class> customTypes = new ArrayList<>();
        for (DataAccessObject<?> ctDao : customTypeDaos) {
            customTypes.add(ctDao.getType());
        }
        //deal with every field
        everyField: for (Map.Entry<Integer, FieldContainer> entry : fieldContainerMap.entrySet()) {
            final FieldContainer fieldContainer = entry.getValue();
            final ComponentState effectiveFieldState = beanUtils
                    .calculateEffectiveComponentState(fieldContainer.getPojoField(), currentUserRoles, entityRight);

            //Create form
            if (ComponentState.INVISIBLE.equals(effectiveFieldState)) {
                continue everyField; //Continue with next field
            }

            //deal with normal form element
            com.vaadin.ui.Field uifield = null;
            //deal with plain choices
            if (fieldContainer.getWebField().choices().length > 0) {
                //deal with choices
                com.vaadin.ui.ComboBox formComboBox = new com.vaadin.ui.ComboBox(
                        fieldContainer.getWebField().name());
                formComboBox.setImmediate(true);
                fieldGroup.bind(formComboBox, fieldContainer.getPojoField().getName());
                for (Choice choice : fieldContainer.getWebField().choices()) {
                    if (choice.value() == -1) {
                        formComboBox.addItem(choice.textValue());
                        formComboBox.setItemCaption(choice.textValue(), choice.display());
                    } else {
                        formComboBox.addItem(choice.value());
                        formComboBox.setItemCaption(choice.value(), choice.display());
                    }
                }
                form.addComponent(formComboBox);
                uifield = formComboBox;
                //deal with active choices
            } else if (fieldContainer.getWebField().activeChoice().enumTree() != EmptyEnum.class) {
                //collect active choices - 
                com.vaadin.ui.ComboBox formComboBox = new com.vaadin.ui.ComboBox(
                        fieldContainer.getWebField().name());
                formComboBox.setImmediate(true);
                fieldGroup.bind(formComboBox, fieldContainer.getPojoField().getName());
                String hierarchy = fieldContainer.getWebField().activeChoice().hierarchy();
                Class<ActiveChoiceEnum> enumTree = (Class<ActiveChoiceEnum>) fieldContainer.getWebField()
                        .activeChoice().enumTree();
                ActiveChoiceTarget activeChoiceTarget = ActiveChoiceUtils.build(enumTree, hierarchy);
                for (String choice : activeChoiceTarget.getSourceChoices()) {
                    formComboBox.addItem(choice);
                    activeChoicesWithFieldAsKey.put(formComboBox, activeChoiceTarget);
                    activeChoicesFieldWithHierarchyAsKey.put(hierarchy, formComboBox);
                }

                form.addComponent(formComboBox);
                uifield = formComboBox;

                //deal with relationship
            } else if (fieldContainer.getPojoField().isAnnotationPresent(OneToMany.class)
                    || fieldContainer.getPojoField().isAnnotationPresent(ManyToOne.class)
                    || fieldContainer.getPojoField().isAnnotationPresent(ManyToMany.class)) {

                //special relationship: deal with custom type form element
                int state = 0;
                Class classOfField = null;
                while (true) {
                    if (state == 0) {
                        if (Collection.class.isAssignableFrom(fieldContainer.getPojoField().getType())) {
                            classOfField = (Class) ((ParameterizedType) fieldContainer.getPojoField()
                                    .getGenericType()).getActualTypeArguments()[0];
                            state = 1;
                        } else {
                            state = 3;
                            break;
                        }
                    }
                    if (state == 1) {
                        if (CustomType.class.isAssignableFrom(classOfField)) {
                            state = 2;
                            break;
                        } else {
                            state = 3;
                            break;
                        }
                    }
                }

                if (state == 2) { //Custom type
                    Button openCustom = new Button("Manage " + fieldContainer.getWebField().name(),
                            new Button.ClickListener() {
                                @Override
                                public void buttonClick(ClickEvent event) {
                                    try {
                                        fieldGroup.commit();
                                        currentBean = (C) fieldGroup.getItemDataSource().getBean();
                                        currentBean = saveBean(currentBean, parentBean, beanUtils,
                                                currentUserRoles);
                                        fieldGroup.setItemDataSource(currentBean);
                                        //field class
                                        Class iclassOfField = (Class) ((ParameterizedType) fieldContainer
                                                .getPojoField().getGenericType()).getActualTypeArguments()[0];

                                        //find a custom type dao
                                        DataAccessObject<? extends CustomType> chosenCTDao = null;
                                        for (DataAccessObject cdao : customTypeDaos) {
                                            if (cdao.getType().isAssignableFrom(iclassOfField)) {
                                                chosenCTDao = cdao;
                                                break;
                                            }
                                        }

                                        //deal with windows
                                        final Window window = new Window();
                                        final AttachmentCustomTypeUICreator<C> attachmentCustomTypeUICreator = new AttachmentCustomTypeUICreator();
                                        Component customTypeComponent = attachmentCustomTypeUICreator
                                                .createUIForForm(currentBean, iclassOfField,
                                                        fieldContainer.getPojoField().getName(), BeanView.this, dao,
                                                        chosenCTDao, pageParameter.getRelationManagerFactory(),
                                                        pageParameter.getConfig(), effectiveFieldState, window);
                                        customTypeComponent
                                                .setCaption("Manage " + fieldContainer.getWebField().name());
                                        customTypeComponent.setId(customTypeComponent.getCaption());
                                        window.setCaption(customTypeComponent.getCaption());
                                        window.setId(window.getCaption());
                                        window.setContent(customTypeComponent);
                                        window.setModal(true);

                                        BeanView.this.getUI().addWindow(window);
                                    } catch (CommitException ex) {
                                        handleFieldsError(fieldGroup);
                                    }
                                }
                            });
                    openCustom.setId(openCustom.getCaption());
                    form.addComponent(openCustom);

                } else { //relationship
                    try {
                        fieldContainer.getPojoField().setAccessible(true);
                        final WebField webField = fieldContainer.getPojoField().getAnnotation(WebField.class);
                        Button relationshipButton = null;
                        if (fieldContainer.getPojoField().isAnnotationPresent(OneToMany.class)) {
                            relationshipButton = new Button("Manage " + webField.name(),
                                    new Button.ClickListener() {
                                        @Override
                                        public void buttonClick(Button.ClickEvent event) {
                                            try {
                                                fieldGroup.commit();
                                                currentBean = (C) fieldGroup.getItemDataSource().getBean();
                                                currentBean = saveBean(currentBean, parentBean, beanUtils,
                                                        currentUserRoles);

                                                Class classOfField = (Class) ((ParameterizedType) fieldContainer
                                                        .getPojoField().getGenericType())
                                                                .getActualTypeArguments()[0];
                                                EditorTableView view = new EditorTableView(currentBean,
                                                        fieldContainer.getPojoField().getName(),
                                                        effectiveFieldState, classOfField, ChoiceType.CHOOSE_MANY,
                                                        pageParameter);
                                                String targetView = "BEAN_VIEW_" + UUID.randomUUID().toString();
                                                History his = new History(targetView, "Manage " + webField.name());
                                                pageParameter.getHistory().push(his);
                                                nav.addView(targetView, view);
                                                nav.navigateTo(targetView);
                                            } catch (CommitException ex) {
                                                handleFieldsError(fieldGroup);
                                            }
                                        }
                                    });

                        } else if (fieldContainer.getPojoField().isAnnotationPresent(ManyToOne.class)) {
                            relationshipButton = new Button("Manage " + webField.name(),
                                    new Button.ClickListener() {
                                        @Override
                                        public void buttonClick(Button.ClickEvent event) {
                                            try {
                                                fieldGroup.commit();
                                                currentBean = (C) fieldGroup.getItemDataSource().getBean();
                                                fieldGroup.commit();
                                                currentBean = (C) fieldGroup.getItemDataSource().getBean();
                                                currentBean = saveBean(currentBean, parentBean, beanUtils,
                                                        currentUserRoles);

                                                EditorTableView view = new EditorTableView(currentBean,
                                                        fieldContainer.getPojoField().getName(),
                                                        effectiveFieldState,
                                                        fieldContainer.getPojoField().getType(),
                                                        ChoiceType.CHOOSE_ONE, pageParameter);
                                                String targetView = "BEAN_VIEW_" + UUID.randomUUID().toString();
                                                History his = new History(targetView, "Manage " + webField.name());
                                                pageParameter.getHistory().push(his);
                                                nav.addView(targetView, view);
                                                nav.navigateTo(targetView);
                                            } catch (CommitException ex) {
                                                handleFieldsError(fieldGroup);
                                            }
                                        }
                                    });
                        } else if (fieldContainer.getPojoField().isAnnotationPresent(ManyToMany.class)) {
                            relationshipButton = new Button("Manage " + webField.name(),
                                    new Button.ClickListener() {
                                        @Override
                                        public void buttonClick(Button.ClickEvent event) {
                                            try {
                                                fieldGroup.commit();
                                                currentBean = (C) fieldGroup.getItemDataSource().getBean();
                                                fieldGroup.commit();
                                                currentBean = (C) fieldGroup.getItemDataSource().getBean();
                                                currentBean = saveBean(currentBean, parentBean, beanUtils,
                                                        currentUserRoles);

                                                Class classOfField = (Class) ((ParameterizedType) fieldContainer
                                                        .getPojoField().getGenericType())
                                                                .getActualTypeArguments()[0];
                                                EditorTableView view = new EditorTableView(currentBean,
                                                        fieldContainer.getPojoField().getName(),
                                                        effectiveFieldState, classOfField, ChoiceType.CHOOSE_MANY,
                                                        pageParameter);

                                                String targetView = "BEAN_VIEW_" + UUID.randomUUID().toString();
                                                History his = new History(targetView, "Manage " + webField.name());
                                                pageParameter.getHistory().push(his);
                                                nav.addView(targetView, view);
                                                nav.navigateTo(targetView);
                                            } catch (CommitException ex) {
                                                handleFieldsError(fieldGroup);
                                            }
                                        }
                                    });
                        }
                        relationshipButton.setId(relationshipButton.getCaption());
                        form.addComponent(relationshipButton);
                    } catch (IllegalArgumentException ex) {
                        Logger.getLogger(BeanView.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                //deal with id
            } else if (fieldContainer.getPojoField().isAnnotationPresent(Id.class)) {
                com.vaadin.ui.Field formField = fieldGroup.buildAndBind(fieldContainer.getWebField().name(),
                        fieldContainer.getPojoField().getName());
                if (Number.class.isAssignableFrom(fieldContainer.getPojoField().getType())) {
                    ((TextField) formField).setConverter(
                            new NumberBasedIDConverter((Class<Number>) fieldContainer.getPojoField().getType()));
                }

                form.addComponent(formField);
                uifield = formField;

                //deal with nominal form element
            } else {
                com.vaadin.ui.Field formField = fieldGroup.buildAndBind(fieldContainer.getWebField().name(),
                        fieldContainer.getPojoField().getName());
                if (fieldContainer.getPojoField().getType().equals(Date.class)) {
                    //deal with date
                    DateField dateField = (DateField) formField;
                    dateField.setDateFormat(pageParameter.getConfig().get("dateFormat"));
                    dateField.setWidth(100f, Unit.PIXELS);
                } else if (fieldContainer.getPojoField().getType().equals(BigDecimal.class)) {
                    TextField bdField = (TextField) formField;
                    bdField.setConverter(new StringToBigDecimalConverter());
                }

                form.addComponent(formField);
                uifield = formField;
            }

            if (uifield != null) {
                //deal with read only
                if (ComponentState.READ_ONLY.equals(effectiveFieldState)) {
                    uifield.setReadOnly(true);
                } else {
                    uifield.setReadOnly(false);
                    if (fieldContainer.getWebField().required() == true) {
                        uifield.setRequired(true);
                    }
                }

                //set null presentation
                if (uifield instanceof AbstractTextField) {
                    AbstractTextField textField = (AbstractTextField) uifield;
                    textField.setNullRepresentation("");
                }

                //set debug id
                uifield.setId(uifield.getCaption());
            }
        }

        //deal with active choice
        for (final com.vaadin.ui.ComboBox sourceField : activeChoicesWithFieldAsKey.keySet()) {
            final ActiveChoiceTarget target = activeChoicesWithFieldAsKey.get(sourceField);
            final com.vaadin.ui.ComboBox targetField = activeChoicesFieldWithHierarchyAsKey
                    .get(target.getTargetHierarchy());
            sourceField.addValueChangeListener(new ValueChangeListener() {
                @Override
                public void valueChange(Property.ValueChangeEvent event) {
                    List<String> targetValues = target.getTargets().get(sourceField.getValue());
                    if (targetValues != null && !targetValues.isEmpty() && targetField != null) {
                        targetField.removeAllItems();
                        for (String targetValue : targetValues) {
                            targetField.addItem(targetValue);
                        }
                    }
                }
            });

        }
    }

    private C saveBean(C bean, P pbean, BeanUtils beanUtils, Set<String> currentUserRoles) {
        if (beanUtils.isEditable(bean.getClass(), currentUserRoles)
                || beanUtils.isCreatable(bean.getClass(), currentUserRoles)) {
            if (pbean == null) {
                return dao.save(bean);
            } else {
                return dao.saveAndAssociate(bean, pbean, parentToCurrentBeanField,
                        pageParameter.getRelationManagerFactory().create((Class<P>) pbean.getClass(),
                                (Class<C>) bean.getClass()));
            }
        } else {
            return null;
        }
    }

    private List<com.vaadin.ui.Field<?>> validateFields(BeanFieldGroup fg) {
        List<com.vaadin.ui.Field<?>> invFields = new ArrayList<>();
        Collection<com.vaadin.ui.Field<?>> fields = fg.getFields();
        for (com.vaadin.ui.Field f : fields) {
            try {
                f.validate();
            } catch (InvalidValueException ivex) {
                invFields.add(f);

            }
        }
        return invFields;
    }

    private void handleFieldsError(BeanFieldGroup fieldGroup) {
        List<com.vaadin.ui.Field<?>> invFields = validateFields(fieldGroup);
        if (invFields.size() > 0) {
            invFields.iterator().next().focus();
            for (com.vaadin.ui.Field<?> invf : invFields) {
                if (invf instanceof AbstractComponent) {
                    ((AbstractComponent) invf).setComponentError(new UserError("Invalid value"));
                }
            }
        }
        Notification.show("Invalid value in a field", Notification.Type.HUMANIZED_MESSAGE);
    }
}

class StringToBigDecimalConverter extends AbstractStringToNumberConverter<BigDecimal> {

    @Override
    protected NumberFormat getFormat(Locale locale) {
        NumberFormat numberFormat = super.getFormat(locale);
        if (numberFormat instanceof DecimalFormat) {
            ((DecimalFormat) numberFormat).setParseBigDecimal(true);
        }

        return numberFormat;
    }

    @Override
    public BigDecimal convertToModel(String value, Class<? extends BigDecimal> targetType, Locale locale)
            throws com.vaadin.data.util.converter.Converter.ConversionException {
        return (BigDecimal) convertToNumber(value, BigDecimal.class, locale);
    }

    @Override
    public Class<BigDecimal> getModelType() {
        return BigDecimal.class;
    }
}