com.axelor.studio.service.builder.FormBuilderService.java Source code

Java tutorial

Introduction

Here is the source code for com.axelor.studio.service.builder.FormBuilderService.java

Source

/**
 * Axelor Business Solutions
 *
 * Copyright (C) 2016 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.axelor.studio.service.builder;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import javax.xml.bind.JAXBException;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.axelor.meta.db.MetaField;
import com.axelor.meta.db.MetaSelect;
import com.axelor.meta.db.MetaView;
import com.axelor.meta.loader.XMLViews;
import com.axelor.meta.schema.ObjectViews;
import com.axelor.meta.schema.actions.Action;
import com.axelor.meta.schema.actions.ActionAttrs;
import com.axelor.meta.schema.actions.ActionAttrs.Attribute;
import com.axelor.meta.schema.actions.ActionRecord;
import com.axelor.meta.schema.actions.ActionRecord.RecordField;
import com.axelor.meta.schema.views.AbstractPanel;
import com.axelor.meta.schema.views.AbstractView;
import com.axelor.meta.schema.views.AbstractWidget;
import com.axelor.meta.schema.views.Button;
import com.axelor.meta.schema.views.Dashlet;
import com.axelor.meta.schema.views.FormView;
import com.axelor.meta.schema.views.Label;
import com.axelor.meta.schema.views.Menu;
import com.axelor.meta.schema.views.PanelEditor;
import com.axelor.meta.schema.views.Menu.Item;
import com.axelor.meta.schema.views.Panel;
import com.axelor.meta.schema.views.PanelField;
import com.axelor.meta.schema.views.PanelInclude;
import com.axelor.meta.schema.views.PanelMail;
import com.axelor.meta.schema.views.PanelMail.MailFollowers;
import com.axelor.meta.schema.views.PanelMail.MailMessages;
import com.axelor.meta.schema.views.PanelRelated;
import com.axelor.meta.schema.views.PanelTabs;
import com.axelor.meta.schema.views.Spacer;
import com.axelor.studio.db.ViewBuilder;
import com.axelor.studio.db.ViewItem;
import com.axelor.studio.db.ViewPanel;
import com.axelor.studio.service.FilterService;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.inject.Inject;

/**
 * This class generate form view from ViewBuilder of type 'form'. It use
 * ViewPanels to generate panels of formView. Also generate onNew action from
 * default value given in view field.
 * 
 * @author axelor
 */
public class FormBuilderService {

    protected Logger log = LoggerFactory.getLogger(getClass());

    // List of RecordFields generated for default values.
    private List<RecordField> defaultFields;

    private Map<String, AbstractPanel> panelMap;

    private List<ActionRecord> actionRecords;

    private List<AbstractWidget> formViewItems;

    private List<Attribute> attributes;

    private boolean autoCreate = false;

    private ActionAttrs parentCheckAction = null;

    @Inject
    private FilterService filterService;

    @Inject
    private FormBuilderService builderService;

    /**
     * Root method to access the service. It will generate FormView from
     * ViewBuilder
     * 
     * @param viewBuilder
     *            ViewBuilder record of type form.
     * @return FormView
     * @throws JAXBException
     */
    public FormView getView(ViewBuilder viewBuilder, boolean autoCreate) throws JAXBException {

        this.autoCreate = autoCreate;
        log.debug("View builder toolbar: {}", viewBuilder.getToolbar().size());

        defaultFields = new ArrayList<RecordField>();
        panelMap = new HashMap<String, AbstractPanel>();
        actionRecords = new ArrayList<ActionRecord>();
        attributes = new ArrayList<Attribute>();
        parentCheckAction = null;

        FormView formView = getFormView(viewBuilder);
        processFormView(formView, viewBuilder);

        processPanels(sortPanels(viewBuilder.getViewPanelList()), false, viewBuilder.getAddOnly());
        processPanels(sortPanels(viewBuilder.getViewSidePanelList()), true, viewBuilder.getAddOnly());

        if (viewBuilder.getAddStream()) {
            addStream();
        }

        if (!defaultFields.isEmpty()) {
            addOnNewAction(formView, viewBuilder.getModel());
            log.debug("On new actions: {}", formView.getOnNew());
        }

        if (!attributes.isEmpty()) {
            String parentCheck = "action-attrs-check-parent-" + viewBuilder.getName();
            log.debug("Adding on load: {}", parentCheck);
            parentCheckAction = new ActionAttrs();
            parentCheckAction.setName(parentCheck);
            parentCheckAction.setModuleToCheck(viewBuilder.getMetaModule().getName());
            parentCheckAction.setAttributes(attributes);
            formView.setOnLoad(getUpdatedAction(formView.getOnLoad(), parentCheck));
            formView.setOnNew(getUpdatedAction(formView.getOnNew(), parentCheck));
        }

        removeEmptyPanels(formViewItems);

        return formView;
    }

    private Iterator<ViewPanel> sortPanels(List<ViewPanel> viewPanelList) {

        Collections.sort(viewPanelList, new Comparator<ViewPanel>() {

            @Override
            public int compare(ViewPanel panel1, ViewPanel panel2) {
                Scanner scan1 = new Scanner(panel1.getPanelLevel());
                Scanner scan2 = new Scanner(panel2.getPanelLevel());
                scan1.useDelimiter("\\.");
                scan2.useDelimiter("\\.");
                try {
                    while (scan1.hasNextInt() && scan2.hasNextInt()) {
                        int v1 = scan1.nextInt();
                        int v2 = scan2.nextInt();
                        if (v1 < v2) {
                            return -1;
                        } else if (v1 > v2) {
                            return 1;
                        }
                    }

                    if (scan2.hasNextInt()) {
                        return -1;
                    }
                    if (scan1.hasNextInt()) {
                        return 1;
                    }

                    return 0;
                } finally {
                    scan1.close();
                    scan2.close();
                }

            }
        });

        return viewPanelList.iterator();
    }

    /**
     * Method update formView record by adding panels, toolbar buttons and onNew
     * action into it.
     * 
     * @param formView
     *            FormView generated from parent view.
     */
    private void processFormView(FormView formView, ViewBuilder viewBuilder) {

        processToolBar(formView, viewBuilder.getToolbar());

        processMenuBar(formView, viewBuilder.getMenubar());

        String onSave = getUpdatedAction(viewBuilder.getOnSave(), formView.getOnSave());
        log.debug("OnSave actions final: {}", onSave);
        formView.setOnSave(onSave);

        String onNew = getUpdatedAction(viewBuilder.getOnNew(), formView.getOnNew());
        formView.setOnNew(onNew);

        String onLoad = getUpdatedAction(viewBuilder.getOnLoad(), formView.getOnLoad());
        formView.setOnLoad(onLoad);

        formView.setWidthSpec("large");
        log.debug("Process form view: {}", formView.getName());

        formViewItems = formView.getItems();

        if (formViewItems == null) {
            formViewItems = new ArrayList<AbstractWidget>();
        } else {
            addPanelInclude(formViewItems);
        }

        mapPanels(formViewItems.iterator(), null, 0);

        log.debug("Panel map keys: {}", panelMap.keySet());

        formView.setItems(formViewItems);
    }

    private void addPanelInclude(List<AbstractWidget> items) {

        List<AbstractWidget> copyItems = new ArrayList<AbstractWidget>();
        copyItems.addAll(items);

        int index = -1;

        for (AbstractWidget item : copyItems) {
            index++;

            if (item instanceof PanelInclude) {
                PanelInclude panel = (PanelInclude) item;
                FormView form = (FormView) panel.getView();
                if (form != null && form.getItems() != null) {
                    List<AbstractWidget> subItems = form.getItems();
                    addPanelInclude(subItems);
                    items.remove(index);
                    items.addAll(index, subItems);
                    index += subItems.size() - 1;
                }
            } else if (item instanceof PanelTabs) {
                PanelTabs tabs = (PanelTabs) item;
                addPanelInclude(tabs.getItems());
                items.remove(index);
                items.add(index, tabs);
            } else if (item instanceof Panel) {
                Panel panel = (Panel) item;
                addPanelInclude(panel.getItems());
                items.remove(index);
                items.add(index, panel);
            }

        }

    }

    /**
     * Method generate final list of buttons to keep in formview. It removes old
     * button and add new button as per ViewBuilder toolbar.
     * @param items 
     * 
     * @param toolbar
     *            List of buttons of Parent form view.
     * @return List of button to keep in formView.
     */
    private void processToolBar(FormView formView, List<ViewItem> items) {

        List<Button> toolbar = new ArrayList<Button>();

        for (ViewItem viewButton : items) {
            log.debug("Button: {} onClick:{}", viewButton.getName(), viewButton.getOnClick());
            toolbar.add(getButton(viewButton));
        }

        if (!toolbar.isEmpty()) {
            formView.setToolbar(toolbar);
        }
    }

    private void processMenuBar(FormView formView, List<ViewItem> menuItems) {

        List<Menu> menubar = new ArrayList<Menu>();

        for (ViewItem viewItem : menuItems) {

            Menu menu = new Menu();
            menu.setIcon(viewItem.getIcon());
            menu.setTitle(viewItem.getTitle());

            List<AbstractWidget> items = new ArrayList<AbstractWidget>();
            log.debug("Total items for menubar: {} is : {}", menu.getTitle(), viewItem.getMenubarItems().size());
            for (ViewItem menuItem : viewItem.getMenubarItems()) {
                Item item = new Item();
                item.setAction(menuItem.getOnClick());
                item.setTitle(menuItem.getTitle());
                items.add(item);
            }

            menu.setItems(items);
            menubar.add(menu);
        }

        if (!menubar.isEmpty()) {
            formView.setMenubar(menubar);
        }
    }

    /**
     * Method to update onSave string with new actions.
     * 
     * @param actions
     *            String of actions separated by comma.
     * @return String of updated actions with onSave.
     */
    public static String getUpdatedAction(String oldAction, String action) {

        if (Strings.isNullOrEmpty(oldAction)) {
            return action;
        }
        if (Strings.isNullOrEmpty(action)) {
            return oldAction;
        }

        List<String> oldActions = new ArrayList<String>();
        oldActions.addAll(Arrays.asList(oldAction.split(",")));

        List<String> newActions = new ArrayList<String>();
        newActions.addAll(Arrays.asList(action.split(",")));
        newActions.removeAll(oldActions);

        oldActions.addAll(newActions);

        return Joiner.on(",").join(oldActions);
    }

    /**
     * Method to get generated ActionRecords, after generating form view.
     * 
     * @return
     */
    public List<ActionRecord> getActionRecords() {

        return actionRecords;
    }

    public ActionAttrs getParentCheckAction() {
        return parentCheckAction;
    }

    /**
     * Method to get FormView from parent form view or create new if no parent
     * form view.
     * 
     * @return FormView
     * @throws JAXBException
     *             Exception throws by xml parsing.
     */
    private FormView getFormView(ViewBuilder viewBuilder) throws JAXBException {

        FormView formView = null;

        MetaView metaView = viewBuilder.getMetaView();
        ViewBuilder parent = viewBuilder.getParent();

        String viewName = viewBuilder.getName();
        if (metaView != null) {
            ObjectViews objectViews = XMLViews.fromXML(metaView.getXml());
            List<AbstractView> views = objectViews.getViews();
            if (!views.isEmpty()) {
                formView = (FormView) views.get(0);
            }
        } else if (parent != null) {
            formView = builderService.getFormView(parent);
        } else {
            formView = new FormView();
            formView.setName(viewName);
            formView.setTitle(viewBuilder.getTitle());
            formView.setModel(viewBuilder.getModel());

        }

        formView.setXmlId(viewBuilder.getMetaModule().getName() + "-" + viewName);

        return formView;
    }

    /**
     * Method process viewPanels of viewBuilder to create new AbstractPanel and
     * update AbstractPanel.
     * 
     * @param sideBar
     *            boolean to check if panel is side panel or not
     */
    private void processPanels(Iterator<ViewPanel> panelIter, boolean sidebar, boolean addOnly) {

        if (!panelIter.hasNext()) {
            return;
        }

        ViewPanel viewPanel = panelIter.next();

        String panelLevel = viewPanel.getPanelLevel();

        log.debug("Panel level to process: {}", panelLevel);
        AbstractPanel panel = null;

        if (panelMap.containsKey(panelLevel)) {
            if (viewPanel.getNewPanel() && addOnly) {
                adjustPanelLevel(panelLevel);
                panel = addNewPanel(panelLevel, viewPanel.getIsNotebook());
            } else {
                panel = panelMap.get(panelLevel);
            }
        } else {
            if (viewPanel.getNewPanel()) {
                adjustPanelLevel(panelLevel);
            }
            panel = addNewPanel(panelLevel, viewPanel.getIsNotebook());
        }

        if (sidebar) {
            panel.setSidebar(sidebar);
        }

        if (addOnly) {
            if (viewPanel.getNewPanel()) {
                panel = updatePanel(panel, viewPanel);
            }
        } else {
            panel = updatePanel(panel, viewPanel);
        }

        processPanels(panelIter, sidebar, addOnly);

    }

    private void adjustPanelLevel(String panelLevel) {

        log.debug("Adjust panel level: {}", panelLevel);
        String[] levels = panelLevel.split("\\.");

        String[] parentLevels = null;

        int index = levels.length - 1;

        Integer upLevel = Integer.parseInt(levels[index]) + 1;

        String levelUp = upLevel.toString();

        if (levels.length > 1) {
            parentLevels = Arrays.copyOf(levels, levels.length - 1);
        }

        List<String> updateLevels = new ArrayList<String>();

        for (String level : panelMap.keySet()) {
            String[] keyLevels = level.split("\\.");
            if (keyLevels.length < levels.length) {
                continue;
            }

            if (parentLevels == null) {
                if (Integer.parseInt(levels[0]) <= Integer.parseInt(keyLevels[0])) {
                    updateLevels.add(level);
                }
            } else {
                String[] checkLevel = Arrays.copyOf(keyLevels, parentLevels.length);
                if (Arrays.equals(checkLevel, parentLevels)
                        && Integer.parseInt(levels[index]) <= Integer.parseInt(keyLevels[index])) {
                    updateLevels.add(level);
                }
            }

        }

        log.debug("Update levels: {}", updateLevels);
        Collections.sort(updateLevels);
        Collections.reverse(updateLevels);

        for (String level : updateLevels) {

            AbstractPanel panel = panelMap.get(level);

            panelMap.remove(level);

            String[] target = level.split("\\.");
            target[index] = levelUp;

            level = Joiner.on(".").join(target);

            panelMap.put(level, panel);
        }

    }

    /**
     * Method to create new Panel with specified panel level
     * 
     * @param panelLevel
     *            Level of panel in formView.
     * @param isNotebook
     *            Boolean to check if panel is notebook.
     * @return AbstractPanel
     */
    private AbstractPanel addNewPanel(String panelLevel, Boolean isNotebook) {

        AbstractPanel abstractPanel = new Panel();
        if (isNotebook) {
            abstractPanel = new PanelTabs();
        }
        abstractPanel.setColSpan(12);

        if (!panelLevel.contains(".")) {
            Integer panelIndex = Integer.parseInt(panelLevel);
            if (panelIndex < formViewItems.size()) {
                formViewItems.add(panelIndex + 1, abstractPanel);
            } else {
                formViewItems.add(abstractPanel);
            }
            panelMap.put(panelLevel, abstractPanel);

            return abstractPanel;
        }

        Integer lastIndex = panelLevel.lastIndexOf(".");
        String parentLevel = panelLevel.substring(0, lastIndex);
        if (!panelMap.containsKey(parentLevel)) {
            log.debug("No parent panel level: {}", panelLevel);
            return abstractPanel;
        }

        List<AbstractWidget> panelItems = null;

        if (panelMap.get(parentLevel) instanceof Panel) {
            Panel panel = (Panel) panelMap.get(parentLevel);
            panelItems = updatePanelItems(panel.getItems(), panelLevel, abstractPanel);
            panel.setItems(panelItems);
            panelMap.put(parentLevel, panel);
        } else if (panelMap.get(parentLevel) instanceof PanelTabs) {
            PanelTabs panelTabs = (PanelTabs) panelMap.get(parentLevel);
            panelItems = updatePanelItems(panelTabs.getItems(), panelLevel, abstractPanel);
            panelTabs.setItems(panelItems);
            panelMap.put(parentLevel, panelTabs);
        }

        return abstractPanel;

    }

    private List<AbstractWidget> updatePanelItems(List<AbstractWidget> panelItems, String panelLevel,
            AbstractPanel panel) {

        panelMap.put(panelLevel, panel);

        if (panelItems == null) {
            panelItems = new ArrayList<AbstractWidget>();
            panelItems.add(panel);
            return panelItems;
        }

        Integer index = Integer.parseInt(panelLevel.substring(panelLevel.lastIndexOf(".") + 1));

        if (index < panelItems.size()) {
            panelItems.add(index, panel);
        } else {
            panelItems.add(panel);
        }

        return panelItems;

    }

    /**
     * Method to update panelMap with generated paneLevel as key and Panel as
     * value.
     * 
     * @param widgetIterator
     *            Iterator of formView items.
     * @param level
     *            Parent panel level
     * @param levelCounter
     *            Current level counter.
     */
    private void mapPanels(Iterator<AbstractWidget> widgetIterator, String level, Integer levelCounter) {

        if (widgetIterator.hasNext()) {

            AbstractWidget widget = widgetIterator.next();
            String currentLevel = levelCounter.toString();
            if (level != null) {
                currentLevel = level + "." + currentLevel;
            }

            if (widget instanceof Panel) {
                Panel panel = (Panel) widget;
                panelMap.put(currentLevel, panel);
                mapPanels(panel.getItems().iterator(), currentLevel, 0);
                levelCounter += 1;
            } else if (widget instanceof PanelTabs) {
                PanelTabs panelTabs = (PanelTabs) widget;
                panelMap.put(currentLevel, panelTabs);
                mapPanels(panelTabs.getItems().iterator(), currentLevel, 0);
                levelCounter += 1;
            } else if (widget instanceof PanelRelated) {
                levelCounter += 1;
            }

            mapPanels(widgetIterator, level, levelCounter);
        }

    }

    /**
     * Method to update AbstractPanel from ViewPanel of formView .
     * 
     * @param abstractPanel
     *            Destination panel to be updated.
     * @param viewPanel
     *            Source panel.
     */
    private AbstractPanel updatePanel(AbstractPanel abstractPanel, ViewPanel viewPanel) {

        // if(!viewPanel.getNoTitle()){
        abstractPanel.setTitle(viewPanel.getTitle());
        // }

        String colspan = viewPanel.getColspan();
        if (colspan != null && StringUtils.isNumeric(colspan)) {
            abstractPanel.setColSpan(Integer.parseInt(colspan));
        }

        String name = viewPanel.getName();
        abstractPanel.setName(name);
        abstractPanel.setShowIf(checkParentIf(name, "show", viewPanel.getShowIf()));
        abstractPanel.setModuleToCheck(viewPanel.getIfModule());
        abstractPanel.setConditionToCheck(viewPanel.getIfConfig());
        abstractPanel.setReadonlyIf(checkParentIf(name, "readonly", viewPanel.getReadonlyIf()));
        abstractPanel.setHideIf(checkParentIf(name, "hidden", viewPanel.getHideIf()));

        if (viewPanel.getReadonly()) {
            abstractPanel.setReadonly(true);
        }

        if (viewPanel.getHidden()) {
            abstractPanel.setHidden(true);
        }

        if (abstractPanel instanceof Panel) {
            List<AbstractWidget> panelItems = new ArrayList<AbstractWidget>();
            Panel panel = (Panel) abstractPanel;
            if (panel.getItems() != null) {
                panelItems = panel.getItems();
            }

            List<ViewItem> itemList = viewPanel.getViewItemList();
            List<AbstractWidget> items = processItems(itemList, panel, viewPanel.getPanelLevel());

            if (viewPanel.getPlace() == 0) {
                panelItems.addAll(0, items);
            } else {
                panelItems.addAll(items);
            }

            panel.setItems(panelItems);

            return panel;
        }

        return abstractPanel;
    }

    public List<AbstractWidget> processItems(List<ViewItem> viewItems, Panel panel, String level) {

        List<AbstractWidget> items = new ArrayList<AbstractWidget>();

        if (viewItems == null) {
            return items;
        }

        Collections.sort(viewItems, new Comparator<ViewItem>() {

            @Override
            public int compare(ViewItem item1, ViewItem item2) {

                if (item1.getSequence() > item2.getSequence()) {
                    return 1;
                } else if (item1.getSequence() < item2.getSequence()) {
                    return -1;
                }

                return 0;
            }

        });

        for (ViewItem viewItem : viewItems) {

            Integer type = viewItem.getTypeSelect();

            switch (type) {
            case 0:
                String fieldType = viewItem.getFieldType();
                if (isPanelRelated(fieldType, viewItem)) {
                    setPanelRelated(viewItem, items, level);
                } else {
                    items.add(createField(viewItem));
                }
                checkDefaultValues(fieldType, viewItem);
                break;
            case 1:
                if (viewItem.getPanelTop()) {
                    setMenuItem(viewItem, panel);
                } else {
                    items.add(getButton(viewItem));
                }
                break;
            case 2:
                setLabel(viewItem, items);
                break;
            case 3:
                setSpacer(viewItem, items);
                break;
            case 4:
                setDashlet(viewItem, items);
                break;
            }

        }

        return items;
    }

    private boolean isPanelRelated(String fieldType, ViewItem viewItem) {

        if (fieldType == null) {
            return false;
        }

        if (viewItem.getWidget() != null) {
            return false;
        }

        if (viewItem.getName() != null && viewItem.getName().startsWith("$")) {
            return false;
        }

        if (!viewItem.getNestedViewItems().isEmpty()) {
            return false;
        }

        if ("one-to-many,many-to-many".contains(fieldType)) {
            return true;
        }

        return false;
    }

    /**
     * Method check if default value is there for ViewField. If defaultValue is
     * there it will update defaultFields list that will be used in onNew action
     * generation.
     * 
     * @param fieldType
     *            Type of field
     * @param fieldName
     *            Name of field
     * @param viewField
     *            ViewField to check for default vale.
     */
    private void checkDefaultValues(String fieldType, ViewItem viewItem) {

        String defaultVal = viewItem.getDefaultValue();
        String name = viewItem.getName();

        if (defaultVal != null) {

            // if(fieldType.equals("string")){
            // defaultVal = "'" + defaultVal + "'";
            // }

            RecordField recordField = new RecordField();
            recordField.setName(name);
            recordField.setExpression("eval:" + filterService.getTagValue(defaultVal, false));

            defaultFields.add(recordField);

        }

    }

    /**
     * Method update PanelItems list with new item created from viewField.
     * 
     * @param fieldName
     *            Name of field
     * @param viewField
     *            Source field.
     * @param panelItems
     *            Destination list to update.
     */
    private PanelField createField(ViewItem viewItem) {

        PanelField field = new PanelField();
        String name = viewItem.getName();
        field.setName(name);
        field.setOnChange(viewItem.getOnChange());
        field.setDomain(viewItem.getDomainCondition());
        field.setReadonlyIf(checkParentIf(name, "readonly", viewItem.getReadonlyIf()));
        field.setHideIf(checkParentIf(name, "hidden", viewItem.getHideIf()));
        field.setShowIf(checkParentIf(name, "show", viewItem.getShowIf()));
        field.setRequiredIf(checkParentIf(name, "required", viewItem.getRequiredIf()));
        field.setModuleToCheck(viewItem.getIfModule());
        field.setConditionToCheck(viewItem.getIfConfig());
        field.setFormView(viewItem.getFormView());
        field.setGridView(viewItem.getGridView());
        field.setColSpan(null);
        String selectWidget = viewItem.getWidget();
        String widget = null;
        setEditor(field, viewItem);

        if (viewItem.getHidden()) {
            field.setHidden(true);
        } else {
            field.setHidden(null);
        }

        if (viewItem.getRequired()) {
            field.setRequired(true);
        } else {
            field.setRequired(null);
        }

        if (viewItem.getReadonly()) {
            field.setReadonly(true);
        } else {
            field.setReadonly(null);
        }

        if (viewItem.getProgressBar()) {
            widget = "SelectProgress";
        } else if (viewItem.getHtmlWidget()) {
            field.setColSpan(12);
            widget = "html";
        } else if (selectWidget != null && !selectWidget.equals("normal")) {
            widget = selectWidget;
        }

        MetaField metaField = viewItem.getMetaField();
        if (metaField != null) {
            if (metaField.getIsDuration()) {
                widget = "duration";
            } else if (metaField.getIsUrl()) {
                widget = "url";
            } else if (metaField.getLarge()) {
                field.setColSpan(12);
            }
            if (metaField.getMultiselect()) {
                widget = "multi-select";
            }
            String relationship = metaField.getRelationship();
            if (autoCreate && relationship != null && "ManyToOne,ManyToMany,OneToOne".contains(relationship)) {
                field.setCanNew("true");
            }
        } else {
            field.setTitle(viewItem.getTitle());
            field.setServerType(viewItem.getFieldType());
            //         field.setTarget(viewItem.getTarget());
        }

        if (viewItem.getColSpan() > 0) {
            field.setColSpan(viewItem.getColSpan());
        }

        field.setWidget(widget);

        MetaSelect metaSelect = viewItem.getMetaSelect();
        if (metaSelect != null) {
            field.setSelection(metaSelect.getName());
        } else {
            field.setSelection(null);
        }

        if (viewItem.getHideTitle()) {
            field.setShowTitle(false);
        }

        return field;

    }

    private Button getButton(ViewItem viewItem) {

        Button button = new Button();
        String name = viewItem.getName();
        button.setName(name);
        button.setColSpan(viewItem.getColSpan());
        button.setTitle(viewItem.getTitle());
        button.setOnClick(viewItem.getOnClick());
        button.setPrompt(viewItem.getPromptMsg());
        button.setShowIf(checkParentIf(name, "show", viewItem.getShowIf()));
        button.setReadonlyIf(checkParentIf(name, "readonly", viewItem.getReadonlyIf()));
        button.setHideIf(checkParentIf(name, "hidden", viewItem.getHideIf()));
        button.setModuleToCheck(viewItem.getIfModule());
        button.setConditionToCheck(viewItem.getIfConfig());

        return button;

    }

    private Panel setMenuItem(ViewItem viewItem, Panel panel) {

        Menu menu = panel.getMenu();
        if (menu == null) {
            menu = new Menu();
        }

        List<AbstractWidget> items = menu.getItems();
        if (items == null) {
            items = new ArrayList<AbstractWidget>();
        }

        Integer oldIndex = null;
        for (AbstractWidget menuItem : items) {
            Item item = (Item) menuItem;
            String name = item.getName();
            if (name != null && name.equals(viewItem.getName())) {
                oldIndex = items.indexOf(item);
                break;
            }
        }

        Item item = new Item();
        // item.setName(viewItem.getName());
        item.setTitle(viewItem.getTitle());
        String onClick = viewItem.getOnClick();
        if (Strings.isNullOrEmpty(onClick)) {
            onClick = "";
        }
        item.setAction(onClick);

        if (oldIndex != null) {
            items.remove(oldIndex);
            items.add(oldIndex, item);
        } else {
            items.add(item);
        }

        menu.setItems(items);
        panel.setMenu(menu);

        return panel;
    }

    /**
     * Method to add panel related for o2m/m2m types of relational field. It
     * will add PanelRelated object created from viewField into list of
     * panelItems of parent panel.
     * 
     * @param fieldName
     *            Name of relational field.
     * @param viewField
     *            ViewField of relational type.
     * @param panelItems
     *            List of items of parent panel.
     */
    private void setPanelRelated(ViewItem viewItem, List<AbstractWidget> panelItems, String level) {

        PanelRelated panelRelated = new PanelRelated();
        String name = viewItem.getName();
        panelRelated.setName(name);
        Integer colspan = viewItem.getColSpan();
        if (colspan != null && colspan != 0) {
            panelRelated.setColSpan(colspan);
        } else {
            panelRelated.setColSpan(12);
        }

        panelRelated.setOnChange(viewItem.getOnChange());
        panelRelated.setDomain(viewItem.getDomainCondition());
        panelRelated.setReadonlyIf(checkParentIf(name, "readonly", viewItem.getReadonlyIf()));
        panelRelated.setHideIf(checkParentIf(name, "hidden", viewItem.getHideIf()));
        panelRelated.setShowIf(checkParentIf(name, "show", viewItem.getShowIf()));
        panelRelated.setModuleToCheck(viewItem.getIfModule());
        panelRelated.setConditionToCheck(viewItem.getIfConfig());
        panelRelated.setFormView(viewItem.getFormView());
        panelRelated.setGridView(viewItem.getGridView());

        if (viewItem.getReadonly()) {
            panelRelated.setReadonly(true);
        } else {
            panelRelated.setReadonly(null);
        }

        if (viewItem.getHidden()) {
            panelRelated.setHidden(true);
        } else {
            panelRelated.setHidden(null);
        }

        String itemLevel = viewItem.getPanelLevel();
        if (itemLevel != null && !itemLevel.startsWith(level)) {
            if (itemLevel.contains(".")) {
                AbstractPanel parentPanel = (AbstractPanel) panelMap
                        .get(itemLevel.substring(0, itemLevel.lastIndexOf(".")));
                if (parentPanel instanceof PanelTabs) {
                    ((PanelTabs) parentPanel).getItems().add(panelRelated);
                } else if (parentPanel instanceof Panel) {
                    ((Panel) parentPanel).getItems().add(panelRelated);
                }
            } else {
                formViewItems.add(panelRelated);
            }
            return;
        }

        panelItems.add(panelRelated);

    }

    /**
     * Method generate ActionRecord from defaultFields and using form view
     * details. Also it set onNew of formView.
     * 
     * @param formView
     *            Updated form view with onNew action.
     */
    private void addOnNewAction(FormView formView, String model) {

        //      String model = viewBuilder.getModel();
        String actionName = "custom-" + formView.getName() + "-default";
        Action action = XMLViews.findAction(actionName);
        ActionRecord actionRecord;

        if (action instanceof ActionRecord) {
            actionRecord = (ActionRecord) action;
            removeOldActionFields(actionRecord);
        } else {
            actionRecord = new ActionRecord();
            actionRecord.setName(actionName);
            actionRecord.setModel(model);
        }

        actionRecord.setFields(defaultFields);

        String onNew = getUpdatedAction(formView.getOnNew(), actionName);
        formView.setOnNew(onNew);

        actionRecords.add(actionRecord);
    }

    /**
     * Method remove old defaultFields and update new default field of
     * ActionRecord.
     * 
     * @param actionRecord
     *            ActionRecord to update.
     */

    private void removeOldActionFields(ActionRecord actionRecord) {

        List<RecordField> oldFields = actionRecord.getFields();

        for (RecordField recordField : defaultFields) {

            Iterator<RecordField> toRemove = oldFields.iterator();

            while (toRemove.hasNext()) {

                RecordField oldField = toRemove.next();

                if (oldField.getName().equals(recordField.getName())) {
                    toRemove.remove();
                    break;
                }

            }
        }

        defaultFields.addAll(oldFields);
    }

    private void addStream() {

        PanelMail panelMail = new PanelMail();

        List<AbstractWidget> items = new ArrayList<AbstractWidget>();

        MailMessages mailMessages = new MailMessages();
        mailMessages.setLimit(4);
        items.add(mailMessages);

        MailFollowers mailFollowers = new MailFollowers();
        items.add(mailFollowers);

        panelMail.setItems(items);

        formViewItems.add(panelMail);

    }

    private void setLabel(ViewItem item, List<AbstractWidget> items) {

        Label label = new Label();
        label.setTitle(item.getTitle());
        label.setName(item.getName());
        label.setHideIf(checkParentIf(item.getName(), "hidden", item.getHideIf()));
        label.setConditionToCheck(item.getIfConfig());
        label.setModuleToCheck(item.getIfModule());
        label.setColSpan(item.getColSpan());

        items.add(label);
    }

    private void setSpacer(ViewItem item, List<AbstractWidget> items) {

        Spacer spacer = new Spacer();
        spacer.setColSpan(item.getColSpan());
        spacer.setConditionToCheck(item.getIfConfig());
        spacer.setModuleToCheck(item.getIfModule());

        items.add(spacer);
    }

    private void setEditor(PanelField field, ViewItem viewItem) {

        List<AbstractWidget> items = processItems(viewItem.getNestedViewItems(), null, null);

        if (!items.isEmpty()) {
            PanelEditor editor = new PanelEditor();
            editor.setItems(items);
            field.setEditor(editor);
            field.setColSpan(12);
        }

    }

    private void removeEmptyPanels(List<AbstractWidget> items) {

        Iterator<AbstractWidget> itemIter = items.iterator();

        while (itemIter.hasNext()) {
            AbstractWidget widget = itemIter.next();
            if (widget instanceof Panel) {
                Panel panel = (Panel) widget;
                if (panel.getItems() == null || panel.getItems().isEmpty()) {
                    log.debug("Removing panel: {}", panel.getTitle());
                    itemIter.remove();
                } else {
                    removeEmptyPanels(panel.getItems());
                }
            } else if (widget instanceof PanelTabs) {
                PanelTabs panel = (PanelTabs) widget;
                if (panel.getItems() == null || panel.getItems().isEmpty()) {
                    itemIter.remove();
                } else {
                    removeEmptyPanels(panel.getItems());
                }
            }

        }
    }

    private void setDashlet(ViewItem viewItem, List<AbstractWidget> items) {

        if (viewItem.getName() != null) {
            log.debug("Adding dashlet:{}", viewItem.getName());
            Dashlet dashlet = new Dashlet();
            dashlet.setAction(viewItem.getName());

            if (viewItem.getColSpan() > 0) {
                dashlet.setColSpan(viewItem.getColSpan());
            } else {
                dashlet.setColSpan(12);
            }

            dashlet.setHeight("350");
            dashlet.setHidden(viewItem.getHidden());
            if (viewItem.getHideIf() != null) {
                dashlet.setHideIf(viewItem.getHideIf());
            }
            dashlet.setTitle(viewItem.getTitle());
            dashlet.setModuleToCheck(viewItem.getIfModule());
            dashlet.setReadonly(viewItem.getReadonly());
            if (viewItem.getReadonlyIf() != null) {
                dashlet.setReadonlyIf(viewItem.getReadonlyIf());
            }
            items.add(dashlet);

        }

    }

    private String checkParentIf(String field, String type, String condition) {

        if (field != null && condition != null && condition.contains("_parent.")) {
            Attribute attr = new Attribute();
            attr.setName(type.equals("show") ? "hidden" : type);
            attr.setFieldName(field);
            attr.setCondition(condition);
            attr.setExpression("eval:" + !type.equals("show"));
            attributes.add(attr);
            return null;
        }

        return condition;
    }

}