/*
 * 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.ListIterator;

import javax.mail.MessagingException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import com.queplix.core.client.app.rpc.DisplayableException;
import com.queplix.core.client.app.vo.AccumulatedEntitiesRequestObject;
import com.queplix.core.client.app.vo.AccumulatedEntityDataResponse;
import com.queplix.core.client.app.vo.ClearEntityRequestObject;
import com.queplix.core.client.app.vo.CustomizeGridRequestObject;
import com.queplix.core.client.app.vo.DateFieldData;
import com.queplix.core.client.app.vo.EmailComposeRequestObject;
import com.queplix.core.client.app.vo.EntityData;
import com.queplix.core.client.app.vo.EntityDataResponseObject;
import com.queplix.core.client.app.vo.EntityDeleteRequestObject;
import com.queplix.core.client.app.vo.EntityIDRequestObject;
import com.queplix.core.client.app.vo.EntityReferenceData;
import com.queplix.core.client.app.vo.EntityReferenceDataRequest;
import com.queplix.core.client.app.vo.EntityReferenceOnDemandData;
import com.queplix.core.client.app.vo.EntityUpdateRequestObject;
import com.queplix.core.client.app.vo.EntityUpdateResponseObject;
import com.queplix.core.client.app.vo.FieldData;
import com.queplix.core.client.app.vo.FieldDataRequest;
import com.queplix.core.client.app.vo.FieldMeta;
import com.queplix.core.client.app.vo.FieldOnDemandData;
import com.queplix.core.client.app.vo.FieldType;
import com.queplix.core.client.app.vo.FormatDataRequestObject;
import com.queplix.core.client.app.vo.FormatDataResponseObject;
import com.queplix.core.client.app.vo.GetControlDataInformRequest;
import com.queplix.core.client.app.vo.GetControlInformOnDemandData;
import com.queplix.core.client.app.vo.GetRecordsDataInformRequest;
import com.queplix.core.client.app.vo.GetSortedDataInformRequest;
import com.queplix.core.client.app.vo.GetRecordsInformOnDemandData;
import com.queplix.core.client.app.vo.SortField;
import com.queplix.core.client.app.vo.GridData;
import com.queplix.core.client.app.vo.HistoryDataRequest;
import com.queplix.core.client.app.vo.HistoryOnDemandData;
import com.queplix.core.client.app.vo.InFormDataRequest;
import com.queplix.core.client.app.vo.InFormGridOnDemandData;
import com.queplix.core.client.app.vo.InFormGridType;
import com.queplix.core.client.app.vo.ListBoxOnDemandData;
import com.queplix.core.client.app.vo.ListboxDataRequest;
import com.queplix.core.client.app.vo.MemoFieldData;
import com.queplix.core.client.app.vo.MoreDataResponseObject;
import com.queplix.core.client.app.vo.MultiselectDataRequest;
import com.queplix.core.client.app.vo.MultiselectOnDemandData;
import com.queplix.core.client.app.vo.NewEntityRequestObject;
import com.queplix.core.client.app.vo.ParseDateRequestObject;
import com.queplix.core.client.app.vo.ParseDateResponseObject;
import com.queplix.core.client.app.vo.PrintFormRequestObject;
import com.queplix.core.client.app.vo.PrintGridRequestObject;
import com.queplix.core.client.app.vo.RecordFilter;
import com.queplix.core.client.app.vo.RowData;
import com.queplix.core.client.app.vo.SavedSearchDeleteRequestObject;
import com.queplix.core.client.app.vo.SavedSearchObject;
import com.queplix.core.client.app.vo.SearchGridRecordsResponseObject;
import com.queplix.core.client.app.vo.SearchInformOnDemandData;
import com.queplix.core.client.app.vo.SortedInformOnDemandData;
import com.queplix.core.client.app.vo.SearchInformRequest;
import com.queplix.core.client.app.vo.SubsetData;
import com.queplix.core.client.app.vo.SubsetItemMeta;
import com.queplix.core.client.app.vo.SubsetMeta;
import com.queplix.core.client.app.vo.TextboxFieldData;
import com.queplix.core.integrator.entity.BoundFormsOperationsHelper;
import com.queplix.core.integrator.entity.EntityFacade;
import com.queplix.core.integrator.entity.EntityOperationsHelper;
import com.queplix.core.integrator.entity.EntitySerializeHelper;
import com.queplix.core.integrator.entity.EntityViewHelper;
import com.queplix.core.integrator.entity.IntegratedRecord;
import com.queplix.core.integrator.entity.IntegratedRecordSet;
import com.queplix.core.integrator.entity.LogicalOperations;
import com.queplix.core.integrator.entity.RecordDoesntExistsException;
import com.queplix.core.integrator.entity.RequestProperties;
import com.queplix.core.integrator.security.LogonSession;
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.modules.config.ejb.PortalConfigManagerLocal;
import com.queplix.core.modules.config.ejb.UserPropertyManagerLocal;
import com.queplix.core.modules.config.jxb.portal.PortalConfig;
import com.queplix.core.modules.eql.EQLERes;
import com.queplix.core.modules.eql.ejb.HistoryLocal;
import com.queplix.core.modules.eql.ejb.LockManagerLocal;
import com.queplix.core.modules.eql.error.EQLConstraintViolationException;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.eql.error.EQLLockException;
import com.queplix.core.modules.eql.error.EQLSystemException;
import com.queplix.core.modules.eql.error.UserQueryParseException;
import com.queplix.core.modules.eqlext.jxb.gr.Report;
import com.queplix.core.modules.eqlext.jxb.gr.Reqs;
import com.queplix.core.modules.eqlext.jxb.gr.ResField;
import com.queplix.core.modules.eqlext.jxb.gr.Ress;
import com.queplix.core.modules.eqlext.utils.ExtDateParser;
import com.queplix.core.modules.eqlext.utils.ReportBuilder;
import com.queplix.core.modules.inbox.InboxHelper;
import com.queplix.core.modules.inbox.InboxMessage;
import com.queplix.core.modules.inbox.ejb.InboxManagerLocal;
import com.queplix.core.modules.mail.MailAddress;
import com.queplix.core.utils.DateHelper;
import com.queplix.core.utils.StringHelper;

/**
 * @author rustem.nizamiev
 * @author Sergey Kozmin
 */
public class IntegratorGetRecords {
    private static final String SEARCH_SAVING_ENTITY = "search.search";

    public static SearchGridRecordsResponseObject searchWithMultipleFormConstraints(
            AccumulatedEntitiesRequestObject searchRequest,
            HttpServletRequest request)
            throws DisplayableException {
        SearchGridRecordsResponseObject gridResult = null;

        try {
            LogonSession ls = WebLoginManager.getLogonSession(request);
            RequestProperties props = new RequestProperties();
            props.setDoCount(searchRequest.getProps().isDoCount());
            props.setPage(searchRequest.getProps().getPage());
            props.setPagesize(searchRequest.getProps().getPageSize());
            props.setSortField(searchRequest.getProps().getSortField());
            props.setIgnoreSendOnRequest(false);

            String entityName = EntityOperationsHelper.getEntityNameFromFormID(
                    searchRequest.getFormID());
            List<EntityData> entityFilters = (List<EntityData>) searchRequest
                    .getEntityFilters();
            ActionContext actx = IntegratorHelper.getActionContext(request);
            RequestBuilder requestBuilder = RequestBuilderFactory
                    .createRequestBuilder(entityName, entityFilters, props, ls,
                            actx);

            gridResult = IntegratorHelper.getNotEmptyResult(props.getPage(),
                    requestBuilder,
                    entityName,
                    EntityViewHelper.FieldsModificator.CUSTOMIZED_GRID,
                    ls, actx);
        } catch (UserQueryParseException ex) {
            IntegratorHelper.throwException("Incorrect value: " + ex.getValue()
                    + ". Entity: " + ex.getEntityName() + ". Field: " +
                    ex.getFieldCaption(), ex);
        } catch (EQLSystemException ex) {
            IntegratorHelper.throwException(
                    "EQL System Exception. " + ex.getMessage(), ex);
        } catch (EQLException ex) {
            IntegratorHelper.throwException("EQL Exception. " + ex.getMessage(),
                    ex);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return gridResult;
    }

    public static AccumulatedEntityDataResponse getEntityData(
            EntityIDRequestObject entityDataRequest, HttpServletRequest request)
            throws DisplayableException {
        AccumulatedEntityDataResponse entityData = null;
        try {
            ServletContext ctx = request.getSession().getServletContext();
            LogonSession ls = WebLoginManager.getLogonSession(request);

            BoundFormsOperationsHelper.ResultFormStructure boundResultSet =
                    BoundFormsOperationsHelper.getBoundFormResult(
                            entityDataRequest.getFormID(),
                            entityDataRequest.getRowID(), ls,
                            IntegratorHelper.getActionContext(ctx));
            List<EntityData> entities = boundResultSet.getEntityDatas();
            List<EntityData> fields = boundResultSet.getFieldDatas();
            List<GridData> gridData = boundResultSet.getGridData();
            entityData = new AccumulatedEntityDataResponse(entities.toArray(
                    new EntityData[entities.size()]),
                    fields.toArray(new EntityData[fields.size()]), gridData);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return entityData;
    }

    public static AccumulatedEntityDataResponse getLockForEditRecord(
            EntityIDRequestObject entityDataRequest, HttpServletRequest request)
            throws DisplayableException {
        ServletContext ctx = request.getSession().getServletContext();
        AccumulatedEntityDataResponse resp = null;
        Long rowID = entityDataRequest.getRowID();
        try {
            LogonSession ls = WebLoginManager.getLogonSession(request);
            String formID = entityDataRequest.getFormID();
            //trying to lock record with specified pkey (row id)
            String entityName = EntityOperationsHelper.getEntityNameFromFormID(
                    formID);
            ActionContext actx = IntegratorHelper.getActionContext(ctx);
            IntegratedRecordSet resultset = EntityFacade.getEntityByIDRequest(
                    entityName, rowID, ls, actx);
            if(resultset.getRowsCount() > 0) {
                LockManagerLocal locker = actx.getRecordsLockManager();
                EQLERes eqleRes = (EQLERes) resultset.getInitialResultSet()
                        .getEQLRes(); //todo implemented in old core. EJB's use the same way. Need to change non-safe down-cast.
                //lock the record, and after we lock it, get it, because it can be changed, before we lock the record.
                locker.lock(eqleRes, getFocusIDFromFormID(formID), 0L, ls);

                //get bound records.
                BoundFormsOperationsHelper.ResultFormStructure boundResultSet =
                        BoundFormsOperationsHelper.getBoundFormResult(
                                entityDataRequest.getFormID(),
                                entityDataRequest.getRowID(), ls, actx);
                List<EntityData> entities = boundResultSet.getEntityDatas();
                List<EntityData> fields = boundResultSet.getFieldDatas();
                List<GridData> gridData = boundResultSet.getGridData();
                resp = new AccumulatedEntityDataResponse(entities.toArray(
                        new EntityData[entities.size()]),
                        fields.toArray(new EntityData[fields.size()]),
                        gridData);
            } else {
                IntegratorHelper.throwException(
                        "System could not find the record you are trying to lock. "
                                +
                                "Probably, the record was deleted, update your data. ");
            }
        } catch (EQLLockException e) {
            IntegratorHelper.throwException("Record is already locked. ", e);
        } catch (EQLException e) {
            IntegratorHelper.throwException("Eql exception occured. Caused by :"
                    + e.getMessage() + ". ", e);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return resp;
    }

    public static AccumulatedEntityDataResponse unlockAfterEditRecord(
            EntityIDRequestObject entityDataRequest, HttpServletRequest request)
            throws DisplayableException {
        ServletContext ctx = request.getSession().getServletContext();
        LogonSession ls = WebLoginManager.getLogonSession(request);
        Long rowID = entityDataRequest.getRowID();
        String formID = entityDataRequest.getFormID();
        ActionContext servletCacheActionContext = IntegratorHelper
                .getActionContext(ctx);
        try {
            //trying to lock record with specified pkey (row id)
            String entityName = EntityOperationsHelper.getEntityNameFromFormID(
                    formID);
            IntegratedRecordSet resultset = EntityFacade.getEntityByIDRequest(
                    entityName, rowID, ls, servletCacheActionContext);
            if(resultset.getRowsCount() > 0) {
                LockManagerLocal locker = servletCacheActionContext
                        .getRecordsLockManager();
                EQLERes eqleRes = (EQLERes) resultset.getInitialResultSet()
                        .getEQLRes(); //todo implemented in old core. EJB's use the same way. Need to change non-safe down-cast.
                //lock the record, and after we lock it, get it, because it can be changed, before we lock the record.
                locker.unlock(eqleRes, ls, eqleRes.getRecord(0));
            } else {
                IntegratorHelper.throwException(
                        "System could not find the record you are trying to unlock. "
                                +
                                "Probably, the record was deleted, update your data. ");
            }
        } catch (EQLException e) {
            IntegratorHelper.throwException("Eql exception occured. Caused by :"
                    + e.getMessage() + ". ", e);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }

        AccumulatedEntityDataResponse entityData = null;
        try {
            BoundFormsOperationsHelper.ResultFormStructure boundResultSet =
                    BoundFormsOperationsHelper.getClearBoundFormResult(formID,
                            ls, servletCacheActionContext);
            List<EntityData> fields = boundResultSet.getFieldDatas();
            EntityData[] ed = new EntityData[0];
            entityData = new AccumulatedEntityDataResponse(ed, fields.toArray(
                    new EntityData[fields.size()]), null);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return entityData;
    }

    private static String getFocusIDFromFormID(String formID) {
        return formID.substring(0, formID.indexOf("__"));
    }

    public static EntityUpdateResponseObject insertRecord(
            EntityUpdateRequestObject updateRequest, HttpServletRequest request)
            throws DisplayableException {
        return changeRecord(request, updateRequest, true);
    }

    public static EntityUpdateResponseObject updateRecord(
            EntityUpdateRequestObject updateRequest, HttpServletRequest request)
            throws DisplayableException {
        return changeRecord(request, updateRequest, false);
    }

    private static EntityUpdateResponseObject changeRecord(
            HttpServletRequest request, EntityUpdateRequestObject updateRequest,
            boolean toBeInsterted)
            throws DisplayableException {
        ServletContext ctx = request.getSession().getServletContext();
        EntityUpdateResponseObject resp = null;

        LogonSession ls = WebLoginManager.getLogonSession(request);
        String entityName = EntityOperationsHelper.getEntityNameFromFormID(
                updateRequest.getFormID());
        Long rowID = updateRequest.getRowID();

        try {
            Collection<FieldData> col = (Collection<FieldData>) updateRequest
                    .getFieldsFilterData();
            //initial entity that contains the proposed to update result
            EntityData entityData = new EntityData(entityName, rowID,
                    col.toArray(new FieldData[col.size()]));
            //entity, that is returned after update
            ActionContext actx = IntegratorHelper.getActionContext(ctx);
            if(toBeInsterted) {
                EntityFacade.insertRecord(entityData, actx, ls);
            } else {
                EntityFacade.updateRecord(entityData, actx, ls);
            }
            IntegratedRecordSet integrResp = EntityFacade.getEntityByIDRequest(
                    entityName, rowID, ls, actx);
            if(integrResp.getRowsCount() > 0) {
                //retrieve updating record and fill up result grid row.
                ArrayList<String> columnValues = new ArrayList<String>();
                Set<String> gridMetas = integrResp.getGridFields();
                IntegratedRecord rec = integrResp.getRecordSet().get(0);
                Map<String, FieldData> fieldDataFields = rec.getFieldSet();

                for(String fieldName : gridMetas) {
                    String gridValue = EntitySerializeHelper
                            .getStringRepresentationForGrid(
                                    fieldDataFields.get(fieldName),
                                    integrResp.getRecordMeta().get(fieldName),
                                    ls, actx);
                    columnValues.add(gridValue);
                }
                String key = integrResp.getPkeyFieldName();
                Long newRowID = Long.parseLong(
                        EntitySerializeHelper.getValueStringRepresentation(
                                fieldDataFields.get(key),
                                integrResp.getRecordMeta().get(key)));
                RowData rowdata = new RowData(newRowID, columnValues.toArray(
                        new String[columnValues.size()]));

                //get bound result to fill up all the forms, bound with updating one.
                BoundFormsOperationsHelper.ResultFormStructure boundResultSet =
                        BoundFormsOperationsHelper.getBoundFormResult(
                                updateRequest.getFormID(), rowID, ls, actx);
                List<EntityData> entities = boundResultSet.getEntityDatas();
                List<EntityData> fields = boundResultSet.getFieldDatas();
                resp = new EntityUpdateResponseObject(entities.toArray(
                        new EntityData[entities.size()]),
                        fields.toArray(new EntityData[fields.size()]), rowdata);
            } else {
                IntegratorHelper.throwException(
                        "Could not select the updated record, probably it wasn't updated properly. ");
            }
        } catch (EQLException e) {
            IntegratorHelper.throwException(e, ls.getUser().getLangID(), ctx);
        } catch (RecordDoesntExistsException e) {
            IntegratorHelper.throwException(e.getMessage(), e);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return resp;
    }

    public static EntityDataResponseObject createEntity(
            NewEntityRequestObject newEntityObjectRequest,
            HttpServletRequest request)
            throws DisplayableException {
        ServletContext ctx = request.getSession().getServletContext();
        EntityDataResponseObject resp = null;

        try {
            LogonSession ls = WebLoginManager.getLogonSession(request);
            String formID = newEntityObjectRequest.getFormID();
            String entityName = EntityOperationsHelper.getEntityNameFromFormID(
                    formID);
            Collection<FieldData> prototypeDataList
                    = (Collection<FieldData>) newEntityObjectRequest
                    .getFieldsFilterData();

            EntityData entityData = EntityFacade.createEntityPrototype(
                    entityName, prototypeDataList, ls,
                    IntegratorHelper.getActionContext(ctx));
            resp = new EntityDataResponseObject(entityData);
        } catch (UserQueryParseException ex) {
            IntegratorHelper.throwException("Incorrect value: " + ex.getValue()
                    + ". Entity: " + ex.getEntityName() + ". Field: " +
                    ex.getFieldCaption(), ex);
        } catch (EQLSystemException ex) {
            IntegratorHelper.throwException(
                    "EQL System Exception. " + ex.getMessage(), ex);
        } catch (EQLException ex) {
            IntegratorHelper.throwException("EQL Exception. " + ex.getMessage(),
                    ex);
        } catch (RecordDoesntExistsException e) {
            IntegratorHelper.reThrowException(e);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return resp;
    }

    public static MoreDataResponseObject getMoreData(
            FieldDataRequest elementRequest, HttpServletRequest request)
            throws DisplayableException {
        MoreDataResponseObject resp = null;

        try {
            LogonSession ls = WebLoginManager.getLogonSession(request);

            resp = getMoreData(elementRequest, ls,
                    IntegratorHelper.getActionContext(request));
        } catch (UserQueryParseException ex) {
            IntegratorHelper.throwException("Incorrect value: " + ex.getValue()
                    + ". Entity: " + ex.getEntityName() + ". Field: " +
                    ex.getFieldCaption(), ex);
        } catch (EQLSystemException ex) {
            IntegratorHelper.throwException(
                    "EQL System Exception. " + ex.getMessage(), ex);
        } catch (EQLException ex) {
            IntegratorHelper.throwException("EQL Exception. " + ex.getMessage(),
                    ex);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return resp;
    }

    private static MoreDataResponseObject getMoreData(
            FieldDataRequest elementRequest, LogonSession ls,
            ActionContext ctx)
            throws EQLException, DisplayableException {
        MoreDataResponseObject resp = null;
        switch(elementRequest.getRequestType()) {
            case FieldType.ENTITYREFERENCE: {
                EntityReferenceDataRequest req
                        = (EntityReferenceDataRequest) elementRequest;
                FieldOnDemandData onDemandData = getMoreDataForEntityReference(
                        req, ls, ctx);
                resp = new MoreDataResponseObject(onDemandData);
                break;
            }
            case FieldType.LISTBOX: {
                ListboxDataRequest req = (ListboxDataRequest) elementRequest;
                SubsetMeta availableChoises = getAvailableChoises(
                        req.getEntityName(), req.getAdditionalFilters(),
                        req.getEqlFilter(), ls, ctx
                );
                resp = new MoreDataResponseObject(new ListBoxOnDemandData(
                        req.getElementID(), availableChoises));
                break;
            }
            case FieldType.MULTISELECT: {
                MultiselectDataRequest req
                        = (MultiselectDataRequest) elementRequest;
                SubsetMeta availableChoises = getAvailableChoises(
                        req.getEntityName(), req.getAdditionalFilters(),
                        req.getEqlFilter(), ls, ctx
                );
                resp = new MoreDataResponseObject(new MultiselectOnDemandData(
                        req.getElementID(), availableChoises));
                break;
            }
            case FieldType.HISTORY: {
                HistoryDataRequest req = (HistoryDataRequest) elementRequest;
                resp = new MoreDataResponseObject(loadHistory(req, ls, ctx));
                break;
            }
            case FieldType.IN_FORM_GRID: {
                FieldOnDemandData onDemandData = getMoreDataForInFormGrid(
                        (InFormDataRequest) elementRequest, ls, ctx);
                resp = new MoreDataResponseObject(onDemandData);
                break;
            }
            default: {
                IntegratorHelper.throwException(
                        "Could not find 'more data' functionality for control of type:"
                                + elementRequest.getRequestType() + ". ");
            }
        }
        return resp;
    }

    private static FieldOnDemandData getMoreDataForInFormGrid(
            InFormDataRequest inFormDataRequest, LogonSession ls,
            ActionContext ctx) throws DisplayableException {
        InFormGridOnDemandData data = null;
        try {
            int type = inFormDataRequest.getInformGridRequestType();
            switch(type) {
                case InFormGridType.SEARCH_TYPE: {
                    String entityName = inFormDataRequest.getRequestingEntity();
                    SearchInformRequest req
                            = (SearchInformRequest) inFormDataRequest;

                    RequestProperties props = new RequestProperties();
                    props.setDoCount(req.getGridProperties().isDoCount());
                    props.setPage(req.getGridProperties().getPage());
                    props.setPagesize(req.getGridProperties().getPageSize());
                    props.setSortField(req.getGridProperties().getSortField());
                    props.setIgnoreSendOnRequest(false);

                    RequestBuilder requestBuilder = RequestBuilderFactory
                            .createRequestBuilder(
                                    entityName, entityName,
                                    (Collection<FieldData>) req
                                            .getFieldsFilters(), props, ls,
                                    ctx);
                    SearchGridRecordsResponseObject result = IntegratorHelper
                            .getNotEmptyResult(props.getPage(), requestBuilder,
                                    entityName,
                                    EntityViewHelper.FieldsModificator.CUSTOMIZED_GRID,
                                    ls, ctx);
                    data = new SearchInformOnDemandData(
                            inFormDataRequest.getElementID(),
                            new ArrayList<RowData>(Arrays.asList(
                                    result.getGridData().getRows())),
                            result.getCurrentPage(),
                            result.getTotalRecordsCount());

                    break;
                }
                case InFormGridType.GET_CONTROL_DATA_TYPE: {
                    GetControlDataInformRequest req
                            = (GetControlDataInformRequest) inFormDataRequest;
                    data = new GetControlInformOnDemandData(req.getElementID(),
                            getMoreData(req.getRequest(), ls,
                                    ctx).getFieldData());
                    break;
                }
                case InFormGridType.GET_SORTED_DATA: {
                    GetSortedDataInformRequest req
                            = (GetSortedDataInformRequest) inFormDataRequest;
                    SortField sortField = req.getSortField();
                    String entityName = req.getRequestingEntity();
                    RowData[] dataToSort = req.getRowData();
                    RequestProperties props = new RequestProperties();
                    props.setSortField(sortField);

                    RequestBuilder requestBuilder = RequestBuilderFactory
                            .createRequestBuilder(
                                    entityName, entityName,
                                    null, props, ls,
                                    ctx);
                    SearchGridRecordsResponseObject result = IntegratorHelper
                            .getNotEmptyResult(0, requestBuilder,
                                    entityName,
                                    EntityViewHelper.FieldsModificator.CUSTOMIZED_GRID,
                                    ls, ctx);

                    RowData[] resultRows = result.getGridData().getRows();

                    ArrayList<RowData> processed = new ArrayList<RowData>();
                    for(RowData row : resultRows) {
                        long id = row.getId();
                        for(RowData filterRow : dataToSort) {
                            long filterId = filterRow.getId();
                            if(id == filterId) {
                                processed.add(row);
                            }
                        }
                    }

                    data = new SortedInformOnDemandData(
                            inFormDataRequest.getElementID(), processed);
                    break;
                }
                case InFormGridType.GET_RECORDS_DATA_TYPE: {
                    GetRecordsDataInformRequest req
                            = (GetRecordsDataInformRequest) inFormDataRequest;
                    String entityName = req.getRequestingEntity();
                    RecordFilter filter = req.getFilter();

                    List<RowData> rows;
                    if(filter.isRecordsFilter()) {
                        RequestProperties props = new RequestProperties();
                        props.setOperation(LogicalOperations.OR);
                        RequestBuilder requestBuilder = RequestBuilderFactory
                                .createRequestBuilder(entityName,
                                        filter.getRecordIds(),
                                        props, ls, ctx);

                        SearchGridRecordsResponseObject result
                                = IntegratorHelper
                                .getNotEmptyResult(props.getPage(), requestBuilder,
                                        entityName,
                                        EntityViewHelper.FieldsModificator.CUSTOMIZED_GRID,
                                        ls, ctx);
                        rows = new ArrayList<RowData>(Arrays.asList(
                                result.getGridData().getRows()));
                    } else {
                        RowData row = EntityOperationsHelper
                                .retrieveGridRowsDataFromResult(entityName,
                                        filter.getFiltersList(),
                                        EntityViewHelper.FieldsModificator.CUSTOMIZED_GRID,
                                        ls, ctx);
                        rows = new ArrayList<RowData>();
                        rows.add(row);
                    }
                    data = new GetRecordsInformOnDemandData(req.getElementID(),
                            rows,
                            req.getFilter().getFiltersList());//for now we just resend the filters,
                    // but it can be a case, when we need to verify or process them.  
                    break;
                }
                default: {
                    throw new IllegalArgumentException(
                            "Couldn't create in-form grid "
                                    + "data of type [" + type + "].");
                }
            }
        } catch (UserQueryParseException ex) {
            IntegratorHelper.throwException("Incorrect value: " + ex.getValue()
                    + ". Entity: " + ex.getEntityName() + ". Field: " +
                    ex.getFieldCaption(), ex);
        } catch (EQLSystemException ex) {
            IntegratorHelper.throwException(
                    "EQL System Exception. " + ex.getMessage(), ex);
        } catch (EQLException ex) {
            IntegratorHelper.throwException("EQL Exception. " + ex.getMessage(),
                    ex);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return data;
    }

    /**
     * Builds available choises list
     *
     * @param entityName
     * @param fieldFilters
     * @param eqlFilters
     * @param ls
     * @param ctx
     * @return
     * @throws EQLException
     */
    private static SubsetMeta getAvailableChoises(String entityName,
                                                  List<FieldData> fieldFilters,
                                                  String eqlFilters,
                                                  LogonSession ls,
                                                  ActionContext ctx)
            throws EQLException {
        //build options
        LinkedList<SubsetItemMeta> optionsList = EntityViewHelper
                .getOptionsForSubsetMeta(entityName, fieldFilters, eqlFilters,
                        ls,
                        ctx);
        //build response
        return new SubsetMeta(optionsList.toArray(
                new SubsetItemMeta[optionsList.size()]));
    }

    private static FieldOnDemandData getMoreDataForEntityReference(
            EntityReferenceDataRequest elementRequest,
            LogonSession ls, ActionContext actx)
            throws EQLException {
        String entityName = elementRequest.getEntityName();

        //build filters for direct linked entity (see xml description)
        ArrayList<EntityData> filters = new ArrayList<EntityData>();
        FieldData mainEntityFilter = null;
        //if entity selected, choose it by pkey, otherwise try to add name filter to listfield.
        if(elementRequest.getId() != null) {
            String pkeyName = EntityViewHelper.getPkeyID(entityName, actx);
            mainEntityFilter = new TextboxFieldData(pkeyName, Long.toString(
                    elementRequest.getId()));
        } else if(!StringHelper.isEmpty(elementRequest.getFilter())) {
            String listfieldName = EntityViewHelper.getListFieldNameForEntity(
                    entityName, actx);
            mainEntityFilter = new TextboxFieldData(listfieldName,
                    elementRequest.getFilter());
        }
        if(mainEntityFilter != null) {
            filters.add(new EntityData(entityName, -1L,
                    new FieldData[]{mainEntityFilter}));
        }
        //add all additional filters
        filters.addAll(elementRequest.getAdditionalFilters());

        RequestProperties properties = new RequestProperties();
        properties.setDoCount(elementRequest.isCounterToggledOn());
        properties.setPage((int) elementRequest.getPage());
        properties.setPagesize(elementRequest.getPageSize());
        properties.setSortField(elementRequest.getSortOrder());

        Reqs castorRequest = EntityFacade.buildReqsFromEntities(filters,
                elementRequest.getEqlFilter(), entityName, properties, ls,
                actx);

        RowData[] responseRecords;
        HashMap<Long, String> listfieldValues;
        int totalRecordsCount = 0;
        int currentPage = 0;
        try {
            IntegratedRecordSet integratedRecordSet = EntityFacade
                    .performRequest(castorRequest, entityName, ls, actx,
                            EntityViewHelper.FieldsModificator.GRID);

            Ress ress = integratedRecordSet.getInitialResultSet().getRess();
            totalRecordsCount = ress.getCount();
            currentPage = ress.getPage();
            responseRecords = EntityOperationsHelper
                    .retrieveGridRowsDataFromResult(integratedRecordSet, ls,
                            actx);

            //build listfield values array
            String key = integratedRecordSet.getListRefFieldName();
            FieldMeta listfieldMeta = integratedRecordSet.getRecordMeta().get(
                    key);
            listfieldValues = new HashMap<Long, String>(
                    integratedRecordSet.getRowsCount());
            for(IntegratedRecord record : integratedRecordSet.getRecordSet()) {
                FieldData listfield = record.getFieldSet().get(key);
                String fieldData = EntitySerializeHelper
                        .getStringRepresentationForGrid(listfield,
                                listfieldMeta, ls, actx);
                String pkeyFieldName = integratedRecordSet.getPkeyFieldName();
                Long rowID = Long.parseLong(
                        EntitySerializeHelper.getValueStringRepresentation(
                                record.getFieldSet().get(pkeyFieldName),
                                integratedRecordSet.getRecordMeta().get(
                                        pkeyFieldName)));
                listfieldValues.put(rowID, fieldData);
            }
        } catch (UserQueryParseException ex) {//in case of some incorrect entered data
            responseRecords = new RowData[0];
            listfieldValues = new HashMap<Long, String>();
        }

        return new EntityReferenceOnDemandData(elementRequest.getElementID(),
                new GridData(responseRecords, entityName), listfieldValues,
                totalRecordsCount, currentPage);
    }

    public static void printForm(PrintFormRequestObject printRequest,
                                 HttpServletRequest req)
            throws DisplayableException {
        ServletContext ctx = req.getSession().getServletContext();
        LogonSession ls = WebLoginManager.getLogonSession(req);
        long processId = printRequest.getProcessId();

        RequestProperties prop = new RequestProperties();
        prop.setDoCount(printRequest.isDoCount());
        prop.setPage(printRequest.getPage());
        prop.setPagesize(printRequest.getPageSize());
        prop.setDoHeader(true);
        Report report = new Report();
        report.setProcessId(processId);
        report.setPrintPage(printRequest.isPrintPage());
        report.setIgnoreIncludeToReport(true);

        Reqs r = null;
        try {
            r = EntityFacade.buildRequestByID(
                    EntityOperationsHelper.getEntityNameFromFormID(
                            printRequest.getFormID()),
                    printRequest.getRowID(), prop, ls,
                    IntegratorHelper.getActionContext(ctx));
        } catch (EQLException ex) {
            IntegratorHelper.throwException("Eql exception occured. ", ex);
        }

        report.setReqs(new Reqs[]{r});

        // Construct ReportBuilder object.
        ReportBuilder reportBuilder = new ReportBuilder(ls, processId, report);

        // Put it in cache.
        IntegratorHelper.getReportBuilderCache(req.getSession())
                .putReportBuilder(reportBuilder);
    }

    public static void printGrid(PrintGridRequestObject printRequest,
                                 HttpServletRequest req)
            throws DisplayableException {
        ServletContext ctx = req.getSession().getServletContext();
        LogonSession ls = WebLoginManager.getLogonSession(req);
        long processId = printRequest.getProcessId();

        RequestProperties prop = new RequestProperties();
        prop.setDoCount(printRequest.isDoCount());
        prop.setPage(printRequest.getPage());
        prop.setPagesize(printRequest.getPageSize());
        prop.setDoHeader(true);
        Report report = new Report();
        report.setProcessId(processId);
        report.setPrintPage(printRequest.isPrintPage());
        report.setIgnoreIncludeToReport(true);
        try {
            ActionContext actx = IntegratorHelper.getActionContext(ctx);
            report.setReqs(new Reqs[]{
                    EntityFacade.buildReqsFromThisEntityFields(
                            (List<FieldData>) printRequest
                                    .getFieldsFilterData(),
                            EntityOperationsHelper.getEntityNameFromFormID(
                                    printRequest.getFormID()),
                            null, prop,
                            ls, actx)
            });
        } catch (EQLException ex) {
            IntegratorHelper.throwException("Eql exception occured. ", ex);
        }

        // Construct ReportBuilder object.
        ReportBuilder reportBuilder = new ReportBuilder(ls, processId, report);

        // Put it in cache.
        IntegratorHelper.getReportBuilderCache(req.getSession())
                .putReportBuilder(reportBuilder);
    }


    public static void saveSearch(SavedSearchObject search,
                                  HttpServletRequest request)
            throws DisplayableException {
        final String searchEntity = SEARCH_SAVING_ENTITY;
        LogonSession ls = WebLoginManager.getLogonSession(request);
        ServletContext ctx = request.getSession().getServletContext();

        String formId = search.getFormId();
        String entity = EntityOperationsHelper.getEntityNameFromFormID(formId);
        ActionContext actx = IntegratorHelper.getActionContext(ctx);
        Map<String, FieldMeta> meta = EntityViewHelper.getMetaForEntity(entity,
                EntityViewHelper.FieldsModificator.FORM, false, ls,
                actx);
        try {
            ArrayList<FieldData> l = new ArrayList<FieldData>();
            l.add(new TextboxFieldData("name", search.getSearchName()));
            l.add(new TextboxFieldData("focus_id",
                    EntityOperationsHelper.getFocusNameFromFormID(formId)));
            l.add(new TextboxFieldData("tab_id",
                    EntityOperationsHelper.getTabNameFromFormID(formId)));
            l.add(new TextboxFieldData("form_id", formId));
            l.add(new EntityReferenceData("owner_id", "",
                    ls.getUser().getUserID()));
            l.add(new DateFieldData("timestamp", DateHelper.getNowDate(),
                    DateHelper.getNowDate(), DateHelper.formatDate(
                    DateHelper.getNowDate())));
            if(search.isRowIDSet()) {
                IntegratedRecordSet resultset = EntityFacade
                        .getEntityByIDRequest(searchEntity, search.getRowID(),
                                ls, actx);
                LockManagerLocal locker = actx.getRecordsLockManager();
                EQLERes eqleRes = (EQLERes) resultset.getInitialResultSet()
                        .getEQLRes();
                locker.lock(eqleRes, "", 0L, ls);
                l.add(new TextboxFieldData("search_id",
                        search.getRowID().toString()));
                l.add(new MemoFieldData("body", EntitySerializeHelper.serialize(
                        search.getFieldsData(), meta), search.getRowID()));
                EntityData entityData = new EntityData(searchEntity,
                        search.getRowID(), l.toArray(new FieldData[l.size()]));
                EntityFacade.updateRecord(entityData, actx, ls);
            } else {
                EntityData d = EntityFacade.createEntityPrototype(searchEntity,
                        new LinkedList<FieldData>(), ls, actx);
                l.add(new TextboxFieldData("search_id",
                        d.getRowID().toString()));
                l.add(new MemoFieldData("body", EntitySerializeHelper.serialize(
                        search.getFieldsData(), meta), d.getRowID()));
                EntityData entityData = new EntityData(searchEntity, (long) -1,
                        l.toArray(new FieldData[l.size()]));
                EntityFacade.insertRecord(entityData, actx, ls);
            }
        } catch (EQLException ex) {
            IntegratorHelper.throwException("Eql exception occured. ", ex);
        } catch (RecordDoesntExistsException ex) {
            IntegratorHelper.throwException(
                    "Record doesn't exist exception occured. ", ex);
        }
    }

    public static SavedSearchObject[] loadSavedSearches(
            HttpServletRequest request)
            throws EQLException {
        LogonSession ls = WebLoginManager.getLogonSession(request);
        RequestProperties props = new RequestProperties();
        ServletContext ctx = request.getSession().getServletContext();


        ActionContext actx = IntegratorHelper.getActionContext(ctx);
        Reqs reqs = EntityFacade.buildReqsFromFields(new ArrayList<FieldData>(),
                SEARCH_SAVING_ENTITY, SEARCH_SAVING_ENTITY, null, props, ls,
                actx);
        IntegratedRecordSet set = EntityFacade.performRequest(reqs,
                SEARCH_SAVING_ENTITY, ls, actx,
                EntityViewHelper.FieldsModificator.CUSTOMIZED_GRID);
        List<IntegratedRecord> l = set.getRecordSet();

        SavedSearchObject[] ret = new SavedSearchObject[l.size()];
        Iterator<IntegratedRecord> it = l.iterator();
        int i = 0;
        while(it.hasNext()) {
            IntegratedRecord record = it.next();
            Map<String, FieldData> fields = record.getFieldSet();
            TextboxFieldData idField = (TextboxFieldData) fields.get(
                    "search_id");
            TextboxFieldData nameField = (TextboxFieldData) fields.get("name");
            TextboxFieldData formIdField = (TextboxFieldData) fields.get(
                    "form_id");

            String serializedFields = ((MemoFieldData) fields.get("body"))
                    .getText();
            String formId = formIdField.getText();
            String entity = EntityOperationsHelper.getEntityNameFromFormID(
                    formId);
            Map<String, FieldMeta> meta = EntityViewHelper.getMetaForEntity(
                    entity, EntityViewHelper.FieldsModificator.FORM,
                    false, ls,
                    actx);
            FieldData[] fieldsData = EntitySerializeHelper.deSerializeFields(
                    serializedFields, entity, meta, ls, actx);

            ret[i] = new SavedSearchObject(nameField.getText(), formId,
                    fieldsData, Long.parseLong(idField.getText()));
            i++;
        }
        return ret;
    }

    public static ParseDateResponseObject parseDate(
            ParseDateRequestObject parseRequest, HttpServletRequest req) {
        LogonSession ls = WebLoginManager.getLogonSession(req);

        // user localized attrs
        User user = ls.getUser();
        Locale locale = SecurityHelper.getJavaLocale(user.getCountryID(),
                user.getLangID());
        TimeZone tz = SecurityHelper.getJavaTimezone(user.getTimeZoneID());
        String datePattern = user.getDatePattern();
        String timePattern = user.getTimePattern();
        boolean dayPosFirst = user.isDatePositionFirst();

        ParseDateResponseObject result;
        long sysDateMls;
        try {
            if(parseRequest.getStringToParse().indexOf("..") == -1) {
                if(parseRequest.getStringToParse().indexOf(" ") == -1) {
                    sysDateMls = ExtDateParser.parseDate(
                            parseRequest.getStringToParse(), dayPosFirst,
                            locale, tz, datePattern, null);
                } else {
                    sysDateMls = ExtDateParser.parseDate(
                            parseRequest.getStringToParse(), dayPosFirst,
                            locale, tz, datePattern, timePattern);
                }
                Date userDate = new Date(DateHelper.toUser(sysDateMls, tz));
                result = new ParseDateResponseObject(userDate
/*new Date(parseRequest.getStringToParse())*/, true);
            } else {
                String[] dates = parseRequest.getStringToParse().split(
                        "[.]{2}");
                long l = ExtDateParser.parseDate(dates[0], dayPosFirst, locale,
                        tz, datePattern, timePattern);
                Date startDate = new Date(DateHelper.toUser(l, tz));
                l = ExtDateParser.parseDate(dates[1], dayPosFirst, locale, tz,
                        datePattern, timePattern);
                Date endDate = new Date(DateHelper.toUser(l, tz));
                result = new ParseDateResponseObject(startDate, endDate, true);
            }
        } catch (java.text.ParseException ex) {
            ex.printStackTrace();
            result = new ParseDateResponseObject();
        }

        return result;
    }

    public static FormatDataResponseObject formatDate(
            FormatDataRequestObject request, HttpServletRequest req) {
        LogonSession ls = WebLoginManager.getLogonSession(req);

        // user localized attrs
        User user = ls.getUser();
        String datePattern = user.getDatePattern();
        String timePattern = user.getTimePattern();

        Date startDate = new Date(request.getStartDate().getYear(),
                request.getStartDate().getMonth(),
                request.getStartDate().getDate(),
                request.getStartDate().getHours(),
                request.getStartDate().getMinutes());
        Date endDate = null;
        if(request.getEndDate() != null) {
            endDate = new Date(request.getEndDate().getYear(),
                    request.getEndDate().getMonth(),
                    request.getEndDate().getDate(),
                    request.getEndDate().getHours(),
                    request.getEndDate().getMinutes());
        }

        String formattedDate = EntitySerializeHelper
                .getDateStringRepresentation(startDate, endDate, datePattern,
                        timePattern, null);
        return new FormatDataResponseObject(formattedDate);
    }

    public static void customizeGrid(CustomizeGridRequestObject request,
                                     HttpServletRequest req)
            throws DisplayableException {
        LogonSession ls = WebLoginManager.getLogonSession(req);
        ServletContext ctx = req.getSession().getServletContext();

        // user localized attrs
        User user = ls.getUser();
        String entity = EntityOperationsHelper.getEntityNameFromFormID(
                request.getFormID());

        SubsetData columnsData = request.getColumns();
        if(columnsData == null) {
            IntegratorHelper.throwException(
                    "Unable to retrieve data about selected columns");
        }

        long[] ids = columnsData.getSelectedIDs();
        String[] fields = new String[ids.length];
        ActionContext actx = IntegratorHelper.getActionContext(ctx);
        FieldMeta[] metas = EntityViewHelper.getMetaInfoForEntity(entity,
                EntityViewHelper.FieldsModificator.FORM, false, ls,
                actx);
        for(int i = 0; i < ids.length; i++) {
            int idx = (int) ids[i];
            fields[i] = metas[idx].getFieldID();
        }

        try {
            UserPropertyManagerLocal userPropManager = actx
                    .getUserPropertyManager();
            userPropManager.setFieldsForGrid(user, entity, fields);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
    }

    public static void deleteRecord(EntityDeleteRequestObject deleteRequest,
                                    HttpServletRequest httpRequest)
            throws DisplayableException {
        String entityName = EntityOperationsHelper.getEntityNameFromFormID(
                deleteRequest.getFormID());
        List<EntityData> entityData = new ArrayList<EntityData>();
        for(Long rowID : (List<Long>) deleteRequest.getRowIDs()) {
            entityData.add(new EntityData(entityName, rowID, null));
        }

        ServletContext ctx = httpRequest.getSession().getServletContext();
        LogonSession ls = WebLoginManager.getLogonSession(httpRequest);

        try {
            ActionContext actx = IntegratorHelper.getActionContext(ctx);
            EntityFacade.deleteRecord(entityData.toArray(
                    new EntityData[entityData.size()]), actx, ls);
        } catch (EQLException e) {
            IntegratorHelper.throwException("Eql exception occured. Caused by :"
                    + e.getMessage() + ". ", e);
        } catch (RuntimeException th) {
            if(th.getCause() != null &&
                    th.getCause() instanceof EQLConstraintViolationException) {
                IntegratorHelper.throwConstraintException(
                        (EQLConstraintViolationException) th.getCause(), ls,
                        ctx);
            } else {
                IntegratorHelper.reThrowException(th);
            }
        }
    }

    public static void deleteSavedSearch(SavedSearchDeleteRequestObject request,
                                         HttpServletRequest httpRequest)
            throws DisplayableException {

        String entityName = SEARCH_SAVING_ENTITY;
        List<EntityData> entityData = new ArrayList<EntityData>();
        for(Long rowID : request.getRowIDs()) {
            entityData.add(new EntityData(entityName, rowID, null));
        }
        ServletContext ctx = httpRequest.getSession().getServletContext();
        LogonSession ls = WebLoginManager.getLogonSession(httpRequest);
        try {
            EntityFacade.deleteRecord(entityData.toArray(
                    new EntityData[entityData.size()]),
                    IntegratorHelper.getActionContext(ctx), ls);
        } catch (EQLException e) {
            IntegratorHelper.throwException("Eql exception occured. Caused by :"
                    + e.getMessage() + ". ", e);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
    }
    
    public static PortalConfig getPortalConfig(String portalType, 
                                         ServletContext ctx) {
        PortalConfigManagerLocal portalManager = IntegratorHelper.
            getActionContext(ctx).getPortalConfigManager();
        return portalManager.getPortalConfig(portalType);
    }
    
    public static void setMessageReadFlag(long messageId, boolean isRead,
                                          ServletContext ctx) {
        InboxManagerLocal inbox = IntegratorHelper.getActionContext(ctx).
                                                        getInboxManagerLocal();
        inbox.setMessageReadFlag(messageId, isRead);
    }
    
    public static boolean hasUnreadMessages(HttpServletRequest request, 
                                            ServletContext ctx) {
        InboxManagerLocal inbox = IntegratorHelper.getActionContext(ctx).
                                                        getInboxManagerLocal();
        return inbox.hasUnreadMessages(WebLoginManager.getLogonSession(request));
    }

    public static HistoryOnDemandData loadHistory(HistoryDataRequest request,
                                                  LogonSession ls,
                                                  ActionContext actx)
            throws DisplayableException {
        HistoryOnDemandData ret = null;

        try {
            IntegratedRecordSet result = EntityFacade.getEntityByIDRequest(
                    "history", request.getRecordId(), ls, actx);
            if(result.getRowsCount() > 0) {
                ResField historyResField = result.getInitialResultSet()
                        .getRess().getRes().getResRecord(0).getResField(1);
                String history = historyResField.getResFieldValue();

                HistoryLocal historyMgr = actx.getHistoryManager();
                ret = new HistoryOnDemandData(request.getElementID(),
                        historyMgr.toHTML(history));
            }
        } catch (EQLException e) {
            IntegratorHelper.throwException("Eql exception occured. Caused by :"
                    + e.getMessage() + ". ", e);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }

        return ret;
    }

    public static AccumulatedEntityDataResponse clearEntity(
            ClearEntityRequestObject clearRequest, HttpServletRequest request)
            throws DisplayableException {
        AccumulatedEntityDataResponse response = null;
        try {
            ServletContext ctx = request.getSession().getServletContext();
            LogonSession ls = WebLoginManager.getLogonSession(request);

            BoundFormsOperationsHelper.ResultFormStructure boundResultSet =
                    BoundFormsOperationsHelper.getClearBoundFormResult(
                            clearRequest.getFormID(), ls,
                            IntegratorHelper.getActionContext(ctx));
            List<EntityData> fields = boundResultSet.getFieldDatas();
            response = new AccumulatedEntityDataResponse(new EntityData[0],
                    fields.toArray(new EntityData[fields.size()]), null);
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
        }
        return response;
    }

    public static boolean sendEmail(EmailComposeRequestObject request,
                                    HttpServletRequest httpRequest)
            throws DisplayableException {
        LogonSession ls = WebLoginManager.getLogonSession(httpRequest);
        ServletContext ctx = httpRequest.getSession().getServletContext();


        MailAddress[] to = MailAddress.parse(request.getTo());
        MailAddress from;
        String fromAddr = request.getFrom();
        if(!StringHelper.isEmpty(fromAddr)) {
            from = new MailAddress(fromAddr);
        } else {
            String defaultSender = InboxHelper.getDefSender(ls);
            from = new MailAddress(defaultSender);
        }

        InboxMessage message = new InboxMessage(to, from, request.getSubject(),
                request.getBody());

        String ccAddr = request.getCc();
        if(!StringHelper.isEmpty(ccAddr)) {
            message.setCc(MailAddress.parse(ccAddr));
        }

        message.setProcessId(request.getProcess_id());

        InboxManagerLocal inboxLocal = IntegratorHelper.getActionContext(ctx)
                .getInboxManagerLocal();
        try {
            inboxLocal.sendEmailMessage(ls, message, null);
        } catch (MessagingException ex) {
            //IntegratorHelper.reThrowException(ex);
            return false;
        } catch (RuntimeException th) {
            IntegratorHelper.reThrowException(th);
            return false;
        }
        return true;
    }
}
