/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */
package com.queplix.core.integrator;

import com.queplix.core.client.app.rpc.DisplayableException;
import com.queplix.core.client.app.rpc.DisplayableStackTraceException;
import com.queplix.core.client.app.vo.ContextMenuMeta;
import com.queplix.core.client.app.vo.EntityMeta;
import com.queplix.core.client.app.vo.FamgMeta;
import com.queplix.core.client.app.vo.FieldMeta;
import com.queplix.core.client.app.vo.FocusMeta;
import com.queplix.core.client.app.vo.FormButtonMeta;
import com.queplix.core.client.app.vo.FormHtmlElementMeta;
import com.queplix.core.client.app.vo.FormLayoutMeta;
import com.queplix.core.client.app.vo.FormLinkMeta;
import com.queplix.core.client.app.vo.FormMeta;
import com.queplix.core.client.app.vo.GridMeta;
import com.queplix.core.client.app.vo.InFormGridFieldMeta;
import com.queplix.core.client.app.vo.MenuItemMeta;
import com.queplix.core.client.app.vo.MetaData;
import com.queplix.core.client.app.vo.PortalConfigMeta;
import com.queplix.core.client.app.vo.ProductMeta;
import com.queplix.core.client.app.vo.SubFocusMeta;
import com.queplix.core.client.app.vo.TabMeta;
import com.queplix.core.client.app.vo.UserProfile;
import com.queplix.core.client.app.vo.chart.ChartModel;
import com.queplix.core.client.app.vo.uisettings.DialogUISettings;
import com.queplix.core.client.app.vo.uisettings.FormUISettings;
import com.queplix.core.client.app.vo.uisettings.GridUISettings;
import com.queplix.core.client.app.vo.util.InvariantDate;
import com.queplix.core.client.common.CollectionsHelper;
import com.queplix.core.error.GenericSystemException;
import com.queplix.core.integrator.chart.ChartDataManager;
import com.queplix.core.integrator.entity.EntityOperationsHelper;
import com.queplix.core.integrator.entity.EntityViewHelper;
import com.queplix.core.integrator.security.AccessLevel;
import com.queplix.core.integrator.security.AccessRightsManager;
import com.queplix.core.integrator.security.CommonActionTypes;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.integrator.security.Permission;
import com.queplix.core.integrator.security.PermissionObjectType;
import com.queplix.core.integrator.security.PermissionSet;
import com.queplix.core.integrator.security.SecurityHelper;
import com.queplix.core.integrator.security.User;
import com.queplix.core.integrator.security.WebLoginManager;
import com.queplix.core.jxb.entity.ChainTable;
import com.queplix.core.jxb.entity.Chainref;
import com.queplix.core.jxb.entity.Entity;
import com.queplix.core.modules.config.ejb.ContextMenuConfigManagerLocal;
import com.queplix.core.modules.config.ejb.EntityViewConfigManagerLocal;
import com.queplix.core.modules.config.ejb.FocusConfigManagerLocal;
import com.queplix.core.modules.config.ejb.PortalConfigManagerLocal;
import com.queplix.core.modules.config.ejb.UserPropertyManagerLocal;
import com.queplix.core.modules.config.jxb.Button;
import com.queplix.core.modules.config.jxb.Col;
import com.queplix.core.modules.config.jxb.ContextMenu;
import com.queplix.core.modules.config.jxb.ExternalForm;
import com.queplix.core.modules.config.jxb.Filter;
import com.queplix.core.modules.config.jxb.Filters;
import com.queplix.core.modules.config.jxb.Focus;
import com.queplix.core.modules.config.jxb.Form;
import com.queplix.core.modules.config.jxb.Header;
import com.queplix.core.modules.config.jxb.HiddenControl;
import com.queplix.core.modules.config.jxb.Htmlelement;
import com.queplix.core.modules.config.jxb.Htmlelements;
import com.queplix.core.modules.config.jxb.Link;
import com.queplix.core.modules.config.jxb.LinkedDataset;
import com.queplix.core.modules.config.jxb.MenuItem;
import com.queplix.core.modules.config.jxb.Row;
import com.queplix.core.modules.config.jxb.SubFocus;
import com.queplix.core.modules.config.jxb.Tab;
import com.queplix.core.modules.config.jxb.portal.Control;
import com.queplix.core.modules.config.jxb.portal.PortalConfig;
import com.queplix.core.modules.config.jxb.types.PermissionsType;
import com.queplix.core.modules.config.utils.DialogSetting;
import com.queplix.core.modules.config.utils.EntityHelper;
import com.queplix.core.modules.config.utils.FormSetting;
import com.queplix.core.modules.config.utils.GridSetting;
import com.queplix.core.modules.config.utils.SysPropertyManager;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.inbox.InboxHelper;
import com.queplix.core.utils.StringHelper;
import com.queplix.core.utils.dao.AbstractPropertyFactory;
import com.queplix.core.utils.log.AbstractLogger;
import com.queplix.core.utils.log.Log;

import javax.servlet.ServletContext;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;

/**
 * Class helps to retrieve metadata for application which is based on core 3.0.
 *
 * @author Sergey Kozmin
 * @since 24 Nov 2006
 */
public class ApplicationMetadataHelper {
    private static final String FORM_AND_FIELD_DIV = ":";
    private static final String VERSION_PROP_FILE = "version.properties";

    private static final String MY_QUEWEB_FOCUS_NAME = "myqueweb";
    private static final String MY_QUEWEB_SUBFOCUS_NAME = "myqueweb";
    private static final String MY_QUEWEB_TAB_NAME = "myqueweb";
    private static final String DASHBOARD_TAB_NAME = "dashboard";
    
    private static final String CHECK_MAIL_TIMEOUT = "CHECK_MAIL_TIMEOUT";

    private static final AbstractLogger logger = Log.getLog(
            ApplicationMetadataHelper.class);

    public static MetaData getMetaData(LogonSession ls, InvariantDate clientNow,
                                       ServletContext ctx)
            throws DisplayableException {
        User user = ls.getUser();
        ActionContext actx = IntegratorHelper.getActionContext(ctx);

        checkUserRoles(user, actx);

        FocusConfigManagerLocal focusManager = actx.getFocusConfigManager();
        Collection<Focus> focuses = focusManager.getLocalizedFocuses(
                user.getLangID());

        PortalConfigManagerLocal portalManager = actx.getPortalConfigManager();
        PortalConfig portalConfig = portalManager.getPortalConfig(ls.getPortalType());
        
        PermissionSet permissions = AccessRightsManager.getPermissionSetForUser(
                user);
        Map<String, DialogSetting> dialogSettings = getDialogSettings(ls, ctx);
        Map<String, GridSetting> gridSettings = getGridSttings(ls, ctx);
        Map<String, FormSetting> formSettings = getFormSttings(ls, ctx);
        List<FocusMeta> metaFocuses = new ArrayList<FocusMeta>();
        for(Focus focus : focuses) {
            Permission permissionForObject = permissions.getPermissionObject(
                    PermissionObjectType.FOCUS, focus.getName());
            if(permissionForObject
                    != null) {//if user has some of rights, it means user can read.
                metaFocuses.add(new FocusMeta(focus.getCaption(),
                        focus.getIcon(), focus.getName(),
                        getSubFocusMeta(focus, permissions, dialogSettings,
                                gridSettings, formSettings, ls, ctx)));
            }
        }
        checkUserPermissons(user, actx, metaFocuses);

        MetaData metaData = new MetaData(metaFocuses.toArray(new FocusMeta[0]));
        String checkMailTimeout = SysPropertyManager.getProperty(CHECK_MAIL_TIMEOUT);
        if (checkMailTimeout != null && !checkMailTimeout.isEmpty()) {
            metaData.setCheckMailTimeout(Integer.parseInt(checkMailTimeout)*1000);
        } else {
            metaData.setCheckMailTimeout(0);
        }
        metaData.setProductMeta(getProductMeta());
        metaData.setPortalConfigMeta(getPortalConfigMeta(portalConfig));

        metaData.setSessionTimeoutMinutes(
                WebLoginManager.getSessionTimeoutMinutes());
        metaData.setSessionTimeoutWarnBeforeMinutes(
                WebLoginManager.getSessionTimeoutWarnBeforeMinutes());

        String defaultFocus = user.getDefaultFocus();
        FocusMeta.Index defaultFocusIndex = metaData.getFocusIndex(
                defaultFocus);
        metaData.setDefaultFocusIndex(defaultFocusIndex);

        TimeZone userTimeZone = SecurityHelper.getJavaTimezone(
                user.getTimeZoneID());
        Calendar cldClientNow = Calendar.getInstance(userTimeZone);

        Calendar cldUserNow = Calendar.getInstance(userTimeZone);
        cldUserNow.set(clientNow.getYear() + 1900, clientNow.getMonth(),
                clientNow.getDate(),
                clientNow.getHours(), clientNow.getMinutes(),
                clientNow.getSeconds());

        long offsetDelta = cldUserNow.getTimeInMillis() - cldClientNow
                .getTimeInMillis();
        metaData.setTimeZoneOffset((int) offsetDelta);

        fillExternalFormIndexes(metaData, focuses);

        fillJoinableFormIndexes(metaData, ctx);

        fillLinkedFormIndexes(metaData);
        
        fillFormFiltersMeta(focuses, metaData);

        UserProfile up = new UserProfile();
        up.setUserID(user.getUserID());
        up.setFullName(user.getFullName());
        if(!StringHelper.isEmpty(user.getEmail())) {
            up.setEmail(user.getEmail());
        } else {
            String defaultSender = InboxHelper.getDefSender(ls);
            up.setEmail(defaultSender);
        }

        metaData.setUserProfile(up);

        createMyQueWebTab(metaData);
        createAdhocReportGridMeta(metaData, ls, ctx);
        createDashboardTab(metaData, ls, actx);

        fillInformGridControls(metaData, focuses, permissions);
        return metaData;
    }

    /**
     * Check user's permissions, and if she/he doesn't hold a role
     * it will throw the DisplayableException
     *
     * @param user user
     * @param actx action context
     * @throws DisplayableException if user doesn't hold a role
     */
    private static void checkUserRoles(User user, ActionContext actx)
            throws DisplayableException {
        if(user.getRolesIDs().size() <= 0) {
            String locMessage = EntityOperationsHelper.
                    getLocalizedServerMessage("no_permission_to_login",
                            new Object[0], user.getLangID(), actx);
            throw new DisplayableStackTraceException(locMessage, locMessage);
        }
    }
    
    private static void checkUserPermissons(User user, ActionContext actx,
                                List metaFocuses) throws DisplayableException {
        if (metaFocuses.isEmpty()) {
            String locMessage = EntityOperationsHelper.
                    getLocalizedServerMessage("no_permission_to_login",
                            new Object[0], user.getLangID(), actx);
            throw new DisplayableStackTraceException(locMessage, locMessage);
        }
    }

    /**
     * Adds linking information to the dataset fields.
     *
     * @param metaData    built metadata
     * @param focuses     focuses
     * @param permissions user permissions
     */
    private static void fillInformGridControls(MetaData metaData,
                                               Collection<Focus> focuses,
                                               PermissionSet permissions) {

        for(Focus focus : focuses) {
            SubFocus[] subfocuses = focus.getSubFocus();
            for(SubFocus subFocus : subfocuses) {
                Tab[] tabs = subFocus.getTab();
                for(Tab tab : tabs) {
                    Form[] forms = tab.getForm();
                    for(Form form : forms) {
                        LinkedDataset[] linkedDatasets = form
                                .getLinkedDataset();
                        for(LinkedDataset linkedDataset : linkedDatasets) {
                            String linkedFormName = linkedDataset.getForm();
                            String datasetName = linkedDataset.getName();
                            fillUpDatasetParams(form, metaData, datasetName,
                                    linkedFormName, permissions);
                        }
                    }
                }
            }
        }
    }

    /**
     * Fill up dataset param with the given referencing linked form name
     *
     * @param form           form to be updated
     * @param metaData       all forms metadata
     * @param datasetName    dataset to be linked to linkedFormName
     * @param linkedFormName form to be linked.
     * @param permissions    permission object
     */
    private static void fillUpDatasetParams(Form form, MetaData metaData,
                                            String datasetName,
                                            String linkedFormName,
                                            PermissionSet permissions) {
        try {
            String formId = form.getName();
            FamgMeta.Index formIndex = (FamgMeta.Index) metaData.getIndexByID(
                    formId);

            if(formIndex == null) {//check if we have access to the form.
                return;
            }

            FamgMeta famgMeta = metaData.getFamgMeta(formIndex);
            FieldMeta datasetMeta = famgMeta.getForm().getEntityMeta().getField(
                    datasetName);
            if(datasetMeta != null
                    && datasetMeta.getDataType() == FieldMeta
                    .IN_FORM_GRID) {//for now ignore other types
                FamgMeta.Index linkedFormIndex = (FamgMeta.Index) metaData
                        .getIndexByID(linkedFormName);
                FamgMeta linkedFormMeta = metaData.getFamgMeta(linkedFormIndex);

                Permission permissionForForm = permissions.getPermissionObject(
                        PermissionObjectType.FORM,
                        linkedFormName);
                if(permissionForForm != null) {
                    InFormGridFieldMeta informMeta
                            = ((InFormGridFieldMeta) datasetMeta);
                    informMeta.setFilteringGridMeta(linkedFormMeta.getGrid());
                    informMeta.setFilteringFormMeta(linkedFormMeta.getForm());
                } else {//have no rights to this form. remove field from meta.
                    famgMeta.getForm().getEntityMeta().removeField(datasetName);
                }
            }
        } catch (ClassCastException e) {
            logger.WARN("Couldn't parse linked form name [" +
                    linkedFormName + "]. Probably it's malformed form name.",
                    e);
        }
    }

    private static Map<String, DialogSetting> getDialogSettings(LogonSession ls,
                                                                ServletContext ctx) {
        Map<String, DialogSetting> ret = new HashMap<String, DialogSetting>();
        UserPropertyManagerLocal propsMgr = IntegratorHelper.getActionContext(
                ctx).getUserPropertyManager();
        Collection<DialogSetting> userSettings = propsMgr.loadDialogsUISettings(
                ls.getUser());
        for(DialogSetting userSetting : userSettings) {
            ret.put(getKey(userSetting.getFormId(), userSetting.getFieldId()),
                    userSetting);
        }
        return ret;
    }

    private static Map<String, GridSetting> getGridSttings(LogonSession ls,
                                                           ServletContext ctx) {
        Map<String, GridSetting> ret = new HashMap<String, GridSetting>();
        UserPropertyManagerLocal propsMgr = IntegratorHelper.getActionContext(
                ctx).getUserPropertyManager();
        Collection<GridSetting> userSettings = propsMgr.loadGridSettings(
                ls.getUser());
        for(GridSetting userSetting : userSettings) {
            ret.put(userSetting.getFormID(), userSetting);
        }
        return ret;
    }

    private static Map<String, FormSetting> getFormSttings(LogonSession ls,
                                                           ServletContext ctx) {
        Map<String, FormSetting> ret = new HashMap<String, FormSetting>();
        UserPropertyManagerLocal propsMgr = IntegratorHelper.getActionContext(
                ctx).getUserPropertyManager();
        Collection<FormSetting> userSettings = propsMgr.loadFormSettings(
                ls.getUser());
        for(FormSetting userSetting : userSettings) {
            ret.put(userSetting.getFormID(), userSetting);
        }
        return ret;
    }

    private static void fillJoinableFormIndexes(MetaData metaData,
                                                ServletContext ctx) {
        Map<String, Set<FamgMeta>> famgSet
                = new TreeMap<String, Set<FamgMeta>>();

        for(FocusMeta focusMeta : metaData.getFocuses()) {
            for(SubFocusMeta subFocusMeta : focusMeta.getSubFocuses()) {
                for(TabMeta tabMeta : subFocusMeta.getTabs()) {
                    for(FamgMeta famgMeta : tabMeta.getFamgs()) {
                        if(famgMeta.getFormID() != null) {
                            String entityName = famgMeta.getEntityName();
                            if(!famgSet.containsKey(entityName)) {
                                famgSet.put(entityName,
                                        new HashSet<FamgMeta>());
                            }

                            famgSet.get(entityName).add(famgMeta);
                        }
                    }
                }
            }
        }
        Set<String> entityNames = famgSet.keySet();
        for(String e1 : entityNames) {
            for(String e2 : entityNames) {
                if(e1.equals(e2)) {
                    continue;
                }

                if(canJoinEntities(e1, e2, ctx)) {
                    setJoinableForms(metaData, famgSet.get(e1), famgSet.get(
                            e2));
                    setJoinableForms(metaData, famgSet.get(e2), famgSet.get(
                            e1));
                }
            }
        }
    }

    private static void setJoinableForms(MetaData metaData,
                                         Set<FamgMeta> targetFamgs,
                                         Set<FamgMeta> joinableFamgs) {
        Set<FamgMeta.Index> joinableForms = new HashSet<FamgMeta.Index>();
        for(FamgMeta joinableFamg : joinableFamgs) {
            joinableForms.add(getFamgIndex(metaData, joinableFamg.getFormID()));
        }
        for(FamgMeta targetFamg : targetFamgs) {
            FormMeta targetForm = targetFamg.getForm();
            Set oldJoinableForms = targetForm.getJoinableForms();
            if(oldJoinableForms != null && oldJoinableForms.size() > 0) {
                joinableForms.addAll(oldJoinableForms);
            }
            targetForm.setJoinableForms(joinableForms);
//            targetForm.setJoinableForms(new ArrayList<FamgMeta.Index>(joinableForms));
        }
    }

    private static boolean canJoinEntities(String e1, String e2,
                                           ServletContext ctx) {
        EntityViewConfigManagerLocal manager = IntegratorHelper
                .getActionContext(ctx).getEntityViewConfigManager();
        Entity entity1 = manager.getEntityViewConfig(e1);
        ChainTable chain = EntityHelper.getChainTable(e2, entity1);
        if(chain == null) {
            return false;
        }

        Chainref chainRef = chain.getChainref();
        if(chainRef != null) {
            String e3 = chainRef.getEntity();
            if(!canJoinEntities(e1, e3, ctx)) {
                return false;
            }

            if(!canJoinEntities(e2, e3, ctx)) {
                return false;
            }
        }

        return true;
    }

    private static void fillExternalFormIndexes(MetaData metaData,
                                                Collection<Focus> focuses) {
        for(FocusMeta focusMeta : metaData.getFocuses()) {
            String focusName = focusMeta.getFocusName();
            Focus focus = getFocusByName(focusName, focuses);

            for(SubFocusMeta subFocusMeta : focusMeta.getSubFocuses()) {
                String subfocusName = focusName + EntityHelper
                        .FORM_NAME_SEPARATOR + subFocusMeta.getSubFocusName();
                SubFocus subfocus = (SubFocus) focus.getObject(subfocusName);

                for(TabMeta tabMeta : subFocusMeta.getTabs()) {
                    String tabName = subfocusName + EntityHelper
                            .FORM_NAME_SEPARATOR + tabMeta.getTabName();
                    Tab tab = (Tab) subfocus.getObject(tabName);

                    for(FamgMeta famgMeta : tabMeta.getFamgs()) {
                        if(famgMeta.getFormID() != null) {
                            Form theForm = (Form) tab.getObject(
                                    famgMeta.getFormID());
                            if(theForm != null) {
                                ExternalForm[] externalForms = theForm
                                        .getExternalForm();
                                for(ExternalForm externalForm : externalForms) {
                                    FormMeta formMeta = famgMeta.getForm();
                                    FamgMeta.Index index = getFamgIndex(
                                            metaData, externalForm.getName());
                                    if(index != null) {
                                        formMeta.addExternalForms(index);
                                    } else {
                                        logger.WARN(
                                                "Couldn't find form index for form:"
                                                        + externalForm
                                                        .getName());
                                    }
                                }
                            } else {
                                logger.WARN(
                                        "FocusManager couldn't find form for formID :"
                                                + famgMeta.getFormID());
                            }
                        } else {
                            logger.ERROR("Form id wasn't filled up for tab:"
                                    + famgMeta.getIndex().serialize());
                        }
                    }
                }
            }
        }
    }

    private static Focus getFocusByName(String focusName,
                                        Collection<Focus> focuses) {
        for(Focus focus : focuses) {
            if(focus.getName().equalsIgnoreCase(focusName)) {
                return focus;
            }
        }
        return null;
    }

    private static FamgMeta.Index getFamgIndex(MetaData metaData,
                                               String formID) {
        try {
            String entityName = EntityHelper.getFormEntityName(formID);
            String tmpID = EntityHelper.getParentTabName(formID);
            String tabID = getShortName(tmpID);
            tmpID = EntityHelper.getParentSubFocusName(tmpID);
            String subFocusID = getShortName(tmpID);
            String focusID = EntityHelper.getParentFocusName(tmpID);
            return metaData.getFormIndex(focusID, subFocusID, tabID,
                    entityName);
        } catch (Exception e) {
            logger.ERROR(MessageFormat.format(
                    "Cannot find Index for form by name \"{0}\".", formID));
            return null;
        }
    }

    private static String getShortName(String compoundName) {
        int pos = compoundName.lastIndexOf(EntityHelper.FORM_NAME_SEPARATOR);
        if(pos < 0) {
            return compoundName;
        } else {
            return compoundName.substring(
                    pos + EntityHelper.FORM_NAME_SEPARATOR.length());
        }
    }

    private static SubFocusMeta[] getSubFocusMeta(Focus focus,
                                                  PermissionSet permissions,
                                                  Map<String, DialogSetting> dialogSettings,
                                                  Map<String, GridSetting> gridSettings,
                                                  Map<String, FormSetting> formSettings,
                                                  LogonSession ls,
                                                  ServletContext ctx) {
        List<SubFocusMeta> metaList = new ArrayList<SubFocusMeta>();
        for(int i = 0; i < focus.getSubFocusCount(); i++) {
            SubFocus subFocus = focus.getSubFocus(i);
            Permission permissionForObject = permissions.getPermissionObject(
                    PermissionObjectType.SUB_FOCUS, subFocus.getName());
            if(permissionForObject
                    != null) {//if user has some of rights, it means user can read.
                metaList.add(new SubFocusMeta(subFocus.getCaption(),
                        subFocus.getIcon(),
                        getShortName(subFocus.getName()), getTabMeta(subFocus,
                        permissions, dialogSettings, gridSettings, formSettings,
                        ls, ctx)));
            }
        }
        return metaList.toArray(new SubFocusMeta[metaList.size()]);
    }

    private static TabMeta[] getTabMeta(SubFocus subFocus,
                                        PermissionSet permissions,
                                        Map<String, DialogSetting> dialogSettings,
                                        Map<String, GridSetting> gridSettings,
                                        Map<String, FormSetting> formSettings,
                                        LogonSession ls, ServletContext ctx) {
        List<TabMeta> metaList = new ArrayList<TabMeta>();
        for(int i = 0; i < subFocus.getTabCount(); i++) {
            Tab tab = subFocus.getTab(i);
            Permission permissionForObject = permissions.getPermissionObject(
                    PermissionObjectType.TAB, tab.getName());
            if(permissionForObject
                    != null) {//if user has some of rights, it means user can read.
                TabMeta tabMeta = new TabMeta(tab.getCaption(), getShortName(
                        tab.getName()),
                        getFamgMeta(tab, permissions, dialogSettings,
                                gridSettings, formSettings, ls, ctx));
                tabMeta.setInFrameLinks(tab.getInframelinks());
                tabMeta.setHaveGrid(tab.getGrid());
                tabMeta.setHelpLink(tab.getHelplink());
                metaList.add(tabMeta);
            }
        }
        return metaList.toArray(new TabMeta[metaList.size()]);
    }

    private static FamgMeta[] getFamgMeta(Tab tab, PermissionSet permissions,
                                          Map<String, DialogSetting> dialogSettings,
                                          Map<String, GridSetting> gridSettings,
                                          Map<String, FormSetting> formSettings,
                                          LogonSession ls, ServletContext ctx) {
        Form[] forms = tab.getForm();
        List<FamgMeta> famgMetas = new LinkedList<FamgMeta>();
        ActionContext actx = IntegratorHelper.getActionContext(ctx);

        for(Form form : forms) {
            Permission permissionForObject = permissions.getPermissionObject(
                    PermissionObjectType.FORM, form.getName());
            if(permissionForObject
                    != null) {//if user has some of rights, it means user can read.
                String langID = ls.getUser().getLangID();

                FieldMeta[] fields = EntityViewHelper.getMetaInfoForEntity(
                        form.getEntity(),
                        EntityViewHelper.FieldsModificator.FORM,
                        true, ls, actx);
/*
                //get metadata for form
                Set<String> formFields = getAllFormFields(form);
                FieldMeta[] fields = EntityViewHelper.getMetaInfoForEntity(form.getEntity(),
                        EntityViewHelper.FieldsModificator.FORM,
                        true, ls, actx);
                // Search all entity fields that lay on form
                ArrayList<FieldMeta> entityFormFields = new ArrayList<FieldMeta>();
                for (FieldMeta field : fields) {
                    if (formFields.contains(field.getFieldID())) {
                        entityFormFields.add(field);
                    }
                }
                FieldMeta[] availableFormFields = entityFormFields.toArray(new FieldMeta[entityFormFields.size()]);*/
                addDialogSettings(dialogSettings, fields, form.getName());
                EntityMeta entityMeta = new EntityMeta(form.getEntity(),
                        fields);
                FormMeta formMeta = new FormMeta(entityMeta, form.getCaption(),
                        getContextMenuMeta(form, permissions, langID, ctx),
                        EntityViewHelper.getPkeyID(form.getEntity(), actx));
                FormLayoutMeta layoutMeta = createLayoutMetaFromLayout(form,
                        permissionForObject);
                formMeta.setLayoutMeta(layoutMeta);
                formMeta.setButtons(createButtonsMeta(
                        EntityHelper.FormHelper.getFormButtons(form),
                        permissionForObject));
                formMeta.setLinks(createLinksMeta(
                        EntityHelper.FormHelper.getFormLinks(form)));
                formMeta.setLabelsOrientation(
                        form.getLabelsOrientation().getType());
                formMeta.setInMyQueWeb(form.getMyqueweb());
                formMeta.setDescription(form.getDescription());
                formMeta.setAutoSearch(form.getAutosearch());
                formMeta.setUISettings(getFormSetting(formSettings,
                        form.getName()));
                formMeta.setVisible(form.getVisible());

                // htmlelements
                Htmlelements htmlElements = form.getHtmlelements();
                if(htmlElements != null) {
                    List<FormHtmlElementMeta> htmlElementMetas
                            = new ArrayList<FormHtmlElementMeta>();
                    for(Htmlelement htmlElement : htmlElements
                            .getHtmlelement()) {
                        htmlElementMetas.add(new FormHtmlElementMeta(
                                htmlElement.getName(),
                                htmlElement.getHtmlcontent()));
                    }
                    formMeta.setHtmlElements(htmlElementMetas.toArray(
                            new FormHtmlElementMeta[0]));
                }
                
                //get metadata for grid
                long[] selectedIDs = EntityViewHelper.getSelectedIndexes(
                        form.getEntity(),
                        EntityViewHelper.FieldsModificator.CUSTOMIZED_GRID,
                        actx, ls);

                GridMeta gridMeta = new GridMeta(fields, selectedIDs,
                        getGridSetting(gridSettings, form.getName()));

                famgMetas.add(new FamgMeta(formMeta, gridMeta, form.getName()));
            }
        }
        return famgMetas.toArray(new FamgMeta[famgMetas.size()]);
    }

    private static GridUISettings getGridSetting(
            Map<String, GridSetting> gridSettings, String name) {
        GridUISettings ret = null;
        if(gridSettings.containsKey(name)) {
            GridSetting setts = gridSettings.get(name);
            ret = new GridUISettings(setts.isCounterOn(), setts.getPageSize(),
                    setts.getColumnWidths());
        }
        return ret;
    }

    private static FormUISettings getFormSetting(
            Map<String, FormSetting> formSettings, String name) {
        FormUISettings ret = null;
        if(formSettings.containsKey(name)) {
            FormSetting setts = formSettings.get(name);
            ret = new FormUISettings(setts.isMinimized());
        }
        return ret;
    }

    private static String getKey(String formId, String fieldId) {
        return formId + FORM_AND_FIELD_DIV + fieldId;
    }

    private static void addDialogSettings(
            Map<String, DialogSetting> dialogSettings, FieldMeta[] fields,
            String formName) {
        for(FieldMeta field : fields) {
            DialogSetting setting = dialogSettings.get(getKey(formName,
                    field.getFieldID()));
            if(setting != null) {
                field.setUISettings(new DialogUISettings(setting.getLeft(),
                        setting.getTop(), setting.getWidth(),
                        setting.getHeight()));
            }
        }
    }

    private static FormButtonMeta[] createButtonsMeta(Button[] buttons,
                                                      Permission formPermissions) {
        List<FormButtonMeta> metaButtons = new LinkedList<FormButtonMeta>();
        for(Button button : buttons) {
            if(AccessRightsManager.canUserPerformAction(
                    formPermissions.getLevel(), getActionForButton(button))) {
                metaButtons.add(new FormButtonMeta(button.getName(),
                        button.getCaption()));
            }
        }
        return metaButtons.toArray(new FormButtonMeta[metaButtons.size()]);
    }

    private static CommonActionTypes getActionForButton(Button button) {
        String buttonName = button.getName();
        if("FORM_NEW_BUTTON".equalsIgnoreCase(buttonName)) {
            return CommonActionTypes.WRITE;
        } else if("FORM_CHANGE_BUTTON".equalsIgnoreCase(buttonName)) {
            return CommonActionTypes.WRITE;
        } else if("FORM_UPDATE_BUTTON".equalsIgnoreCase(buttonName)) {
            return CommonActionTypes.WRITE;
        } else if("FORM_CHANGE_OR_UPDATE_BUTTON".equalsIgnoreCase(buttonName)) {
            return CommonActionTypes.WRITE;
        }
        PermissionsType permission = button.getPermission();
        if(permission != null) {
            AccessLevel level = AccessLevel.getByLevelConstant(
                    permission.getType());
            if(level == AccessLevel.READ) {
                return CommonActionTypes.READ;
            } else if(level == AccessLevel.WRITE) {
                return CommonActionTypes.WRITE;
            } else if(level == AccessLevel.OWNER) {
                return CommonActionTypes.DELETE_OWNED_RECORDS;
            } else if(level == AccessLevel.FULL_CONTROL) {
                return CommonActionTypes.DELETE_ANY_RECORD;
            }
        }
        return CommonActionTypes.READ; //if button has custom, or search, clear names it means user should at least has read access to see that.
    }

    private static FormLinkMeta[] createLinksMeta(Link[] links) {
        FormLinkMeta[] metaLinks = new FormLinkMeta[links.length];
        for(int i = 0; i < links.length; i++) {
            metaLinks[i] = new FormLinkMeta(links[i].getField(),
                    links[i].getForm());
        }
        return metaLinks;
    }

    private static FormLayoutMeta createLayoutMetaFromLayout(Form form,
                                                             Permission formPermissions) {
        Row[] rows = EntityHelper.FormHelper.getLayoutRows(form);
        if(rows.length > 0) {
            //convert headers
            Header[] headers = EntityHelper.FormHelper.getLayoutHeaders(form);
            FormLayoutMeta.ColumnHeader[] metaHeaders
                    = new FormLayoutMeta.ColumnHeader[headers.length];
            for(int i = 0; i < headers.length; i++) {
                metaHeaders[i] = new FormLayoutMeta.ColumnHeader(
                        headers[i].getClientwidth());
            }
            //convert rows
            FormLayoutMeta.Row[] metaRows = new FormLayoutMeta.Row[rows.length];
            for(int rowIdx = 0; rowIdx < rows.length; rowIdx++) {
                Col[] cols = rows[rowIdx].getCol();
                FormLayoutMeta.Col[] metaCols
                        = new FormLayoutMeta.Col[cols.length];
                for(int colIdx = 0; colIdx < cols.length; colIdx++) {
                    Col col = cols[colIdx];
                    String fieldId = col.getFieldid();
                    Button button = EntityHelper.FormHelper.getButtonById(form,
                            fieldId);
                    if(button != null &&
                            !AccessRightsManager.canUserPerformAction(
                                    formPermissions.getLevel(),
                                    getActionForButton(button))) {
                        metaCols[colIdx] = new FormLayoutMeta.Col("",
                                col.getRowspan(), col.getColspan());
                    } else {
                        metaCols[colIdx] = new FormLayoutMeta.Col(fieldId,
                                col.getRowspan(), col.getColspan());
                    }
                }
                metaRows[rowIdx] = new FormLayoutMeta.Row(metaCols);
            }
            HiddenControl[] hiddenControls = EntityHelper.FormHelper
                    .getHiddenControls(form);
            String[] hiddenControlsIds = new String[hiddenControls.length];
            for(int i = 0; i < hiddenControls.length; i++) {
                hiddenControlsIds[i] = hiddenControls[i].getFieldid();
            }
            return new FormLayoutMeta(metaRows, metaHeaders, hiddenControlsIds);
        } else {
            return null;
        }
    }

    private static ContextMenuMeta getContextMenuMeta(Form form,
                                                      PermissionSet permissions,
                                                      String langId,
                                                      ServletContext ctx) {
        ContextMenuConfigManagerLocal contextMenuManager = IntegratorHelper
                .getActionContext(ctx).getContextMenuManager();
        ContextMenu contextMenu = contextMenuManager.getContextMenuByForm(
                form.getName());
        ContextMenuMeta meta = null;
        if(contextMenu != null) {
            contextMenu = contextMenuManager.getLocalizedContextMenu(langId,
                    contextMenu);
            List<MenuItemMeta> menuItems = new ArrayList<MenuItemMeta>();
            for(MenuItem menuItem : contextMenu.getMenuItem()) {
                MenuItemMeta metaItem = null;
                if("delete".equalsIgnoreCase(menuItem.getName())) {
                    Permission formPerm = permissions.getPermissionObject(
                            PermissionObjectType.FORM, form.getName());
                    if(AccessRightsManager.canUserPerformAction(
                            formPerm.getLevel(),
                            CommonActionTypes.DELETE_OWNED_RECORDS)) {
                        metaItem = new MenuItemMeta(menuItem.getName(),
                                menuItem.getCaption());
                    }
                } else {
                    metaItem = new MenuItemMeta(menuItem.getName(),
                            menuItem.getCaption());
                }
                if(metaItem != null) {
                    menuItems.add(metaItem);
                }
            }

            meta = new ContextMenuMeta(menuItems.toArray(new MenuItemMeta[0]));
        }
        return meta;
    }

    private static void fillLinkedFormIndexes(MetaData metaData) {
        for(FocusMeta focusMeta : metaData.getFocuses()) {
            for(SubFocusMeta subFocusMeta : focusMeta.getSubFocuses()) {
                for(TabMeta tabMeta : subFocusMeta.getTabs()) {
                    for(FamgMeta meta : tabMeta.getFamgs()) {
                        Map<String, String> links
                                = new HashMap<String, String>();
                        FormLinkMeta[] linksMeta = meta.getForm().getLinks();
                        for(FormLinkMeta link : linksMeta) {
                            links.put(link.getFieldId(),
                                    link.getLinkedFormId());
                        }
                        FieldMeta[] fields = meta.getForm().getEntityMeta()
                                .getFields();
                        for(FieldMeta field : fields) {
                            String formId = links.get(field.getFieldID());
                            if(formId != null) {
                                field.setLinkedForm(getFamgIndex(metaData,
                                        formId));
                            }
                        }
                    }
                }
            }
        }
    }
    
    private static void fillFormFiltersMeta(Collection<Focus> focuses, MetaData metaData) {
        for (Focus focus : focuses) {
            // no access rights
            String focusName = focus.getName();
            if(metaData.getFocusIndex(focusName) == null)
                continue;

            for (SubFocus subFocus : focus.getSubFocus()) {
                // no access rights
                String subFocusName = subFocus.getName();
                SubFocusMeta.Index subFocusIdx = metaData.getSubFocusIndex(
                        focusName, getShortName(subFocusName));
                if(subFocusIdx == null)
                    continue;
                
                for (Tab tab : subFocus.getTab()) {
                    // no access rights
                    String tabName = tab.getName();
                    TabMeta.Index tabIdx = metaData.getTabIndex(
                            focusName, getShortName(subFocusName), getShortName(tabName));
                    if(tabIdx == null)
                        continue;

                    for (Form form : tab.getForm()) {
                        // no access rights
                        FamgMeta.Index formIdx
                                = (FamgMeta.Index) metaData.getIndexByID(form.getName());
                        if (formIdx == null)
                            continue;
                        
                        FormMeta formMeta = metaData.getFormMeta(formIdx);

                        Filters filterContainer = form.getFilters();
                        if (filterContainer != null) {
                            
                            Filter[] filters = filterContainer.getFilter();
                            FormMeta.FieldFilterMeta[] filtersMeta
                                    = new FormMeta.FieldFilterMeta[filters.length];

                            for (int i = 0; i < filters.length; i++) {
                                Filter filter = filters[i];
                                FamgMeta.Index byFormIdx = (FamgMeta.Index) metaData
                                        .getIndexByID(filter.getByFormId());
                                
                                if (byFormIdx == null) {
                                    throw new IllegalStateException(
                                            "Unable to resolve form index to filter by. formId=" + filter.getByFormId());
                                }

                                filtersMeta[i] = new FormMeta.FieldFilterMeta(
                                        filter.getFieldId(), byFormIdx, filter.getByFieldId());
                            }

                            formMeta.setFieldFiltersMeta(filtersMeta);
                        }
                    }
                }
            }
        }
    }
    
    private static void addButton(ArrayList<FormButtonMeta> buttons,
                                  String id, String caption, String icon,
                                  String tag,
                                  String captionStyle) {
        FormButtonMeta meta;
        meta = new FormButtonMeta(id, caption, FormButtonMeta.BUTTON_TYPE_LINK,
                icon, captionStyle);
        meta.setTag(tag);
        buttons.add(meta);
    }

    private static FormLayoutMeta createLayout(FormButtonMeta[] resultButtons) {
        final int TOTAL_COLUMNS = 6;
        final int FORMS_FIRST_COLUMN = 2;
        final int INDENT_WIDTH = 30;
        final int DESCRIPTION_INDENT_WIDTH = 300;

        ArrayList<FormLayoutMeta.Row> rowsList
                = new ArrayList<FormLayoutMeta.Row>();
        int n = resultButtons.length;
        int i = 0;
        while(i < n) {
            FormButtonMeta buttonMeta = resultButtons[i];
            String objectType = buttonMeta.getTag();
            FormLayoutMeta.Col[] cols;
            if("FORM".equals(objectType)) {
                cols = createLayoutColumns(TOTAL_COLUMNS);
                int j = FORMS_FIRST_COLUMN;
                do {
                    cols[j].setFieldID(buttonMeta.getId());
                    cols[j + 1].setFieldID(buttonMeta.getId() + "_desc");
                    j += 2;
                    i++;
                    if(i < n) {
                        buttonMeta = resultButtons[i];
                        objectType = buttonMeta.getTag();
                    }
                } while((i < n) && (j < TOTAL_COLUMNS) && "FORM".equals(
                        objectType));
            } else {
                int position = -1;
                if("TAB".equals(objectType)) {
//                    position = 2;
                } else if("SUBFOCUS".equals(objectType)) {
                    position = 1;
                } else if("FOCUS".equals(objectType)) {
                    position = 0;
                }
                cols = createLayoutColumnsWithColspan(position + 1,
                        TOTAL_COLUMNS);
                cols[position].setFieldID(buttonMeta.getId());
                i++;
            }
            FormLayoutMeta.Row row = new FormLayoutMeta.Row(cols);
            rowsList.add(row);
        }
        FormLayoutMeta.Row[] rows = rowsList.toArray(new FormLayoutMeta.Row[0]);
        FormLayoutMeta resultFormLayout = new FormLayoutMeta(rows);

        FormLayoutMeta.ColumnHeader[] headers
                = new FormLayoutMeta.ColumnHeader[TOTAL_COLUMNS];
        for(int j = 0; j < headers.length; j++) {
            headers[j] = new FormLayoutMeta.ColumnHeader();
            if(j < FORMS_FIRST_COLUMN) {
                headers[j].setClientWidth(INDENT_WIDTH);
            } else
            if((j == FORMS_FIRST_COLUMN + 1) || (j == FORMS_FIRST_COLUMN + 3)) {
                headers[j].setClientWidth(DESCRIPTION_INDENT_WIDTH);
            }
        }
        resultFormLayout.setHeaders(headers);

        return resultFormLayout;
    }

    private static FormLayoutMeta.Col[] createLayoutColumns(int columnsNumber) {
        FormLayoutMeta.Col[] cols = new FormLayoutMeta.Col[columnsNumber];
        for(int j = 0; j < cols.length; j++) {
            cols[j] = new FormLayoutMeta.Col();
        }
        return cols;
    }

    private static FormLayoutMeta.Col[] createLayoutColumnsWithColspan(
            int columnsNumber, int totalColumnsNumber) {
        FormLayoutMeta.Col[] cols = createLayoutColumns(columnsNumber);
        int colspan = totalColumnsNumber - columnsNumber + 1;
        cols[columnsNumber - 1].setColspan(colspan);
        return cols;
    }

    private static void createAdhocReportGridMeta(MetaData metaData,
                                                  LogonSession ls,
                                                  ServletContext ctx) {
        FieldMeta[] fieldsForGrid = EntityViewHelper.getMetaInfoForEntity(
                IntegratorReports.REPORT_SAVING_ENTITY,
                EntityViewHelper.FieldsModificator.GRID, true, ls,
                IntegratorHelper.getActionContext(ctx));
        metaData.setAdhocReportsMeta(new GridMeta(fieldsForGrid,
                CollectionsHelper.createIncrementalArray(fieldsForGrid.length,
                        0)));
    }

    private static void createMyQueWebTab(MetaData metaData) {
        TabMeta tabMeta = metaData.getTabMeta(
                MY_QUEWEB_FOCUS_NAME, MY_QUEWEB_SUBFOCUS_NAME,
                MY_QUEWEB_TAB_NAME);
        if(tabMeta == null) {
            return; // the user does not have My QueWeb tab
        }

        ArrayList<FamgMeta> resultFamgs = new ArrayList<FamgMeta>();
        EntityMeta resultEntity = new EntityMeta();
        FormMeta resultForm = new FormMeta(resultEntity, "My QueWeb");
        GridMeta resultGrid = new GridMeta(resultEntity.getFields(),
                new long[0]);
        FamgMeta resultFamg = new FamgMeta(resultForm, resultGrid, "MyQueWeb");
        resultFamgs.add(resultFamg);
        ArrayList<FormButtonMeta> resultButtonsList
                = new ArrayList<FormButtonMeta>();
        ArrayList<FormHtmlElementMeta> resultHtmlElementsList
                = new ArrayList<FormHtmlElementMeta>();

        FocusMeta[] focuses = metaData.getFocuses();
        for(int i = 0; i < focuses.length; i++) {
            FocusMeta focus = focuses[i];
            String focusID = focus.getFocusName();
            if(focusID.equalsIgnoreCase("MyQueWeb")) {
                continue; // ignore My QueWeb focus
            }

            addButton(resultButtonsList, focusID,
                    focus.getCaption(), focus.getIcon(), "FOCUS",
                    "myQueWeb_focus");

            SubFocusMeta[] subFocuses = focus.getSubFocuses();
            for(int j = 0; j < subFocuses.length; j++) {
                SubFocusMeta subFocus = subFocuses[j];
                String subFocusID = focusID + "__" + subFocus.getSubFocusName();
                addButton(resultButtonsList, subFocusID,
                        subFocus.getCaption(), subFocus.getIcon(), "SUBFOCUS",
                        "myQueWeb_subFocus");
                TabMeta[] tabs = subFocus.getTabs();
                for(int k = 0; k < tabs.length; k++) {
                    TabMeta tab = tabs[k];
//                    String tabID = subFocusID + "__" + tab.getTabName();
//                    addButton(resultButtonsList, tabID,
//                            tab.getCaption(), tab.getIcon(), "TAB");
                    FamgMeta[] famgs = tab.getFamgs();
                    for(int l = 0; l < famgs.length; l++) {
                        FormMeta form = famgs[l].getForm();
                        if(form.isInMyQueWeb()) {
                            String formID = famgs[l].getFormID();
                            addButton(resultButtonsList, formID,
                                    form.getCaption(), form.getIcon(), "FORM",
                                    "myQueWeb_form");
                            FormHtmlElementMeta htmlMeta
                                    = new FormHtmlElementMeta(formID + "_desc",
                                    "<div style='padding: 2px 20px; color: blue;'>"
                                            +
                                            form.getDescription() +
                                            "</div>");
                            resultHtmlElementsList.add(htmlMeta);
                        }
                    }
                }
            }
        }

        FormButtonMeta[] resultButtons = resultButtonsList.toArray(
                new FormButtonMeta[0]);
        resultForm.setButtons(resultButtons);
        FormHtmlElementMeta[] resultHtmlElements = resultHtmlElementsList
                .toArray(new FormHtmlElementMeta[0]);
        resultForm.setHtmlElements(resultHtmlElements);
        // create layout:
        FormLayoutMeta resultFormLayout = createLayout(resultButtons);
        resultForm.setLayoutMeta(resultFormLayout);

        FamgMeta[] famgs = resultFamgs.toArray(new FamgMeta[0]);

        tabMeta.setFamgs(famgs);
    }

    private static void createDashboardTab(MetaData metaData, LogonSession ls,
                                           ActionContext ctx) {
        TabMeta tabMeta = metaData.getTabMeta(
                MY_QUEWEB_FOCUS_NAME, MY_QUEWEB_SUBFOCUS_NAME,
                DASHBOARD_TAB_NAME);
        if(tabMeta == null) {
            return; // the user does not have the Dashboard tab
        }

        EntityMeta entityMeta = new EntityMeta();
        FormMeta formMeta = new FormMeta(entityMeta,
                "Dashboard"); // TODO caption?
        GridMeta gridMeta = new GridMeta(); // no grid
        FamgMeta famgMeta = new FamgMeta(formMeta, gridMeta,
                "dashboard"); // TODO formID?

        ChartModel[] chartModels = new ChartModel[0];
        try {
            chartModels = ChartDataManager.getSystemCharts(ls, ctx);
            logger.DEBUG(
                    "Count of loaded system charts: " + chartModels.length);
        } catch (EQLException e) {
            logger.ERROR("Unable to retrieve system charts", e);
            throw new GenericSystemException("Unable to retrieve system charts",
                    e);
        }

        formMeta.setCharts(chartModels);

        // create layout:
        List<FormLayoutMeta.Row> rows = new ArrayList<FormLayoutMeta.Row>();
        FormLayoutMeta.Row row = null;
        List<FormLayoutMeta.Col> cols = new ArrayList<FormLayoutMeta.Col>();
        for(int i = 0; i < chartModels.length; i++) {
            String chartId = chartModels[i].getMeta().getID().toString();
            cols.add(new FormLayoutMeta.Col(chartId));

            if((i + 1) % 2 == 0 || (i + 1) == chartModels.length) {
                row = new FormLayoutMeta.Row(cols.toArray(
                        new FormLayoutMeta.Col[0]));
                rows.add(row);
                cols.clear();
            }
        }
        FormLayoutMeta layoutMeta = new FormLayoutMeta(rows.toArray(
                new FormLayoutMeta.Row[0]));

        formMeta.setLayoutMeta(layoutMeta);

        tabMeta.setFamgs(new FamgMeta[]{famgMeta});
    }

    private static ProductMeta getProductMeta() {
        Properties props = AbstractPropertyFactory.loadSysProperties(
                VERSION_PROP_FILE);
        String name = props.getProperty("name");
        String version = props.getProperty("version");
        ProductMeta res = new ProductMeta(name, version);
        return res;
    }

    private static Set<String> getAllFormFields(Form form) {
        HashSet<String> formFields = new HashSet<String>();
        Row[] rows = EntityHelper.FormHelper.getLayoutRows(form);
        for(Row row : rows) {
            Col[] cols = row.getCol();
            for(Col col : cols) {
                formFields.add(col.getFieldid());
            }
        }
        HiddenControl[] hiddenControls = EntityHelper.FormHelper
                .getHiddenControls(form);
        for(HiddenControl hiddenControl : hiddenControls) {
            formFields.add(hiddenControl.getFieldid());
        }
        return formFields;
    }
    
    private static PortalConfigMeta.MainToolbarMeta createDefaultMainToolbar() {
        List<String> controls = new ArrayList<String>();
        controls.add("company_logo");
        controls.add("divider");
        controls.add("back");
        controls.add("forward");
        controls.add("divider");
        controls.add("clear_all");
        controls.add("last_search");
        controls.add("divider");
        controls.add("print_form");
        controls.add("divider");
        controls.add("e_mail");
        controls.add("divider");
        controls.add("adhoc_reports");
        controls.add("divider");
        controls.add("save_settings");
        controls.add("divider");
        return new PortalConfigMeta.MainToolbarMeta(controls.toArray(new String[0]));
    }

    private static PortalConfigMeta getPortalConfigMeta(PortalConfig portalConfig) {
        PortalConfigMeta portalConfigMeta = new PortalConfigMeta();
        if (portalConfig == null || portalConfig.getMenus() == null) {
            portalConfigMeta.setShowFocusMenu(true);
            portalConfigMeta.setShowSubFocusMenu(true);
        }
        else {
            portalConfigMeta.setShowFocusMenu(portalConfig.getMenus().
                getShowFocusMenu());
            portalConfigMeta.setShowSubFocusMenu(portalConfig.getMenus().
                getShowSubfocusMenu());
        }
        if (portalConfig == null || portalConfig.getCss() == null) {
            portalConfigMeta.setCssFileName(null);
        }
        else {
            portalConfigMeta.setCssFileName(portalConfig.getCss().getFilename());
        }
        PortalConfigMeta.MainToolbarMeta toolbar = createDefaultMainToolbar();
        if (portalConfig != null && portalConfig.getMainToolbar() != null && 
            portalConfig.getMainToolbar().getControlCount() != 0) {
            String[] controls = new String[portalConfig.
                                           getMainToolbar().getControlCount()];
            int count = 0;
            for (Control control: portalConfig.getMainToolbar().getControl()) {
                controls[count++] = control.getName();
            }
            toolbar.setControls(controls);
        }
        portalConfigMeta.setToolbar(toolbar);
        return portalConfigMeta;
    }

}

