/**
 * Copyright (c) 2012-2015 Edgar Espina
 * <p>
 * This file is part of Handlebars.java.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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 cn.ibizlab.codegen.templating.handlebars;

import cn.ibizlab.codegen.model.BaseModel;
import cn.ibizlab.codegen.model.IModel;
import com.github.jknack.handlebars.ValueResolver;
import com.github.jknack.handlebars.context.MethodValueResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static org.apache.commons.lang3.Validate.notNull;

/**
 * A JavaBean method value resolver.
 *
 * @author edgar.espina
 * @since 0.1.1
 */
public class BaseModelValueResolver implements ValueResolver {

  final Logger LOGGER = LoggerFactory.getLogger(BaseModelValueResolver.class);
  /**
   * A concurrent and thread-safe cache for {@link Member}.
   */
  private final Map<Class<?>, Map<String, Method>> cache = new ConcurrentHashMap<>();

  private static Map<String,String> classMap = new HashMap<String,String>(){{
    put("net.ibizsys.model.codelist.PSCodeListImpl", "net.ibizsys.model.codelist.IPSCodeList");
    put("net.ibizsys.model.wf.PSWorkflowImpl", "net.ibizsys.model.wf.IPSWorkflow");
    put("net.ibizsys.model.wf.PSWFDEImpl", "net.ibizsys.model.wf.IPSWFDE");
    put("net.ibizsys.model.dataentity.PSDataEntityImpl", "net.ibizsys.model.dataentity.IPSDataEntity");
    put("net.ibizsys.model.dataentity.defield.PSDEFieldImpl", "net.ibizsys.model.dataentity.defield.IPSDEField");
    put("net.ibizsys.model.wf.StartPSWFProcessImpl", "net.ibizsys.model.wf.IPSWFProcess");
    put("net.ibizsys.model.wf.EndPSWFProcessImpl", "net.ibizsys.model.wf.IPSWFProcess");
    put("net.ibizsys.model.wf.PSWFInteractiveProcessImpl", "net.ibizsys.model.wf.IPSWFProcess");
    put("net.ibizsys.model.wf.PSWFDEActionProcessImpl", "net.ibizsys.model.wf.IPSWFProcess");
    put("net.ibizsys.model.dataentity.action.PSDEUserCustomActionImpl", "net.ibizsys.model.dataentity.action.IPSDEAction");
    put("net.ibizsys.model.wf.PSWFExclusiveGatewayProcessImpl", "net.ibizsys.model.wf.IPSWFProcess");
    put("net.ibizsys.model.security.PSSysUniResImpl", "net.ibizsys.model.security.IPSSysUniRes");
    put("net.ibizsys.model.app.appmenu.PSAppMenuModelImpl", "net.ibizsys.model.app.appmenu.IPSAppMenuModel");
    put("net.ibizsys.model.control.menu.PSAppMenuItemImpl", "net.ibizsys.model.control.menu.IPSAppMenuItem");
    put("net.ibizsys.model.system.PSSystemModuleImpl", "net.ibizsys.model.system.IPSSystemModule");
    put("net.ibizsys.model.wf.PSWFVersionImpl", "net.ibizsys.model.wf.IPSWFVersion");
    put("net.ibizsys.model.dataentity.defield.PSDEFSearchModeImpl", "net.ibizsys.model.dataentity.defield.IPSDEFSearchMode");
    put("net.ibizsys.model.app.func.PSAppFuncImpl", "net.ibizsys.model.app.func.IPSAppFunc");
    put("net.ibizsys.model.app.view.PSAppDEGridViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.IPSAppDEView", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEEditViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.IPSAppIndexView", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppIndexViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.codelist.IPSAppCodeList", "net.ibizsys.model.app.codelist.IPSCodeList");
    put("net.ibizsys.model.app.codelist.PSAppCodeListImpl", "net.ibizsys.model.codelist.IPSCodeList");
    put("net.ibizsys.model.codelist.PSCodeItemImpl", "net.ibizsys.model.codelist.IPSCodeItem");
    put("net.ibizsys.model.app.dataentity.PSAppDataEntityImpl", "net.ibizsys.model.app.dataentity.IPSAppDataEntity");
    put("net.ibizsys.model.app.dataentity.PSAppDEFieldImpl2", "net.ibizsys.model.app.dataentity.IPSAppDEField");
    put("net.ibizsys.model.app.dataentity.PSAppDEMethodImpl", "net.ibizsys.model.app.dataentity.IPSAppDEMethod");
    put("net.ibizsys.model.dataentity.service.PSDEServiceAPIMethodImpl", "net.ibizsys.model.dataentity.service.IPSDEServiceAPIMethod");
    put("net.ibizsys.model.control.ajax.PSAjaxControlHandlerActionImpl", "net.ibizsys.model.control.IPSControlHandlerAction");
    put("net.ibizsys.model.control.ajax.PSMDAjaxControlHandlerImpl", "net.ibizsys.model.control.IPSControlHandler");
    put("net.ibizsys.model.app.view.PSAppViewLogicImpl", "net.ibizsys.model.app.view.IPSAppViewLogic");
    put("net.ibizsys.model.app.logic.BuiltinPSAppUINewDataLogicImpl", "net.ibizsys.model.app.logic.IPSAppUILogic");
    put("net.ibizsys.model.app.logic.PSAppUILogicRefViewImpl", "net.ibizsys.model.app.logic.IPSAppUILogicRefView");
    put("net.ibizsys.model.app.logic.BuiltinPSAppUIOpenDataLogicImpl", "net.ibizsys.model.app.logic.IPSAppUILogic");
    put("net.ibizsys.model.app.view.PSAppViewNavParamImpl", "net.ibizsys.model.control.IPSNavigateParam");
    put("net.ibizsys.model.app.view.PSAppDERedirectViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.layout.PSGridLayoutPosImpl", "net.ibizsys.model.control.layout.IPSLayoutPos");
    put("net.ibizsys.model.control.form.PSDEFormPageImpl", "net.ibizsys.model.control.form.IPSDEFormPage");
    put("net.ibizsys.model.control.editor.PSTextBoxImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.form.PSDEFormGroupPanelImpl", "net.ibizsys.model.control.form.IPSDEFormDetail");
    put("net.ibizsys.model.control.layout.PSGrid24LayoutImpl", "net.ibizsys.model.control.layout.IPSLayout");
    put("net.ibizsys.model.control.editor.PSDatePickerImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSTextAreaImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSHiddenImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSSpanImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSFileUploaderImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSDropDownListImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSPictureImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSPickerImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.form.PSDEFormDRUIPartImpl", "net.ibizsys.model.control.form.IPSDEFormDetail");
    put("net.ibizsys.model.app.PSAppModuleImpl", "net.ibizsys.model.app.IPSAppModule");
    put("net.ibizsys.model.control.form.PSDEFDCatGroupLogicImpl", "net.ibizsys.model.control.form.IPSDEFDCatGroupLogic");
    put("net.ibizsys.model.control.form.PSDEFDSingleLogicImpl", "net.ibizsys.model.control.form.IPSDEFDLogic");
    put("net.ibizsys.model.app.view.PSAppDEPickupGridViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.grid.PSDEGridDataItemImpl", "net.ibizsys.model.control.grid.IPSDEGridDataItem");
    put("net.ibizsys.model.control.grid.PSDEGridFieldColumnImpl", "net.ibizsys.model.control.grid.IPSDEGridColumn");
    put("net.ibizsys.model.control.grid.HiddenPSDEGridEditItemImpl", "net.ibizsys.model.control.grid.IPSDEGridEditItem");
    put("net.ibizsys.model.app.view.PSAppDEWFDynaEditViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEWFDynaActionViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEWFDynaStartViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMPickupViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.dataentity.service.PSDEServiceAPIMethodInputImpl", "net.ibizsys.model.dataentity.service.IPSDEServiceAPIMethodInput");
    put("net.ibizsys.model.dataentity.service.PSDEMethodDTOImpl", "net.ibizsys.model.dataentity.service.IPSDEMethodDTO");
    put("net.ibizsys.model.dataentity.service.PSDEServiceAPIMethodReturnImpl", "net.ibizsys.model.dataentity.service.IPSDEServiceAPIMethodReturn");
    put("net.ibizsys.model.dataentity.ds.PSDEDataSetImpl", "net.ibizsys.model.dataentity.ds.IPSDEDataSet");
    put("net.ibizsys.model.app.view.PSAppDETreeExplorerViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDETabExplorerViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEDashboardViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEHtmlViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEListViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEWizardViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppPortalViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.res.PSLanguageResImpl", "net.ibizsys.model.res.IPSLanguageRes");
    put("net.ibizsys.model.res.PSSysImageImpl", "net.ibizsys.model.res.IPSSysImage");
    put("net.ibizsys.model.app.view.PSAppViewNavContextImpl", "net.ibizsys.model.control.IPSNavigateContext");
    put("net.ibizsys.model.res.PSSysCssImpl", "net.ibizsys.model.res.IPSSysCss");
    put("net.ibizsys.model.app.view.PSAppViewRefImpl", "net.ibizsys.model.app.view.IPSAppViewRef");
    put("net.ibizsys.model.app.view.PSAppDETreeViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEGridExplorerViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.PSNavigateContextImpl", "net.ibizsys.model.control.IPSNavigateContext");
    put("net.ibizsys.model.control.IPSNavigateParam", "net.ibizsys.model.control.IPSNavigateContext");
    put("net.ibizsys.model.control.PSNavigateParamImpl", "net.ibizsys.model.control.IPSNavigateParam");
    put("net.ibizsys.model.control.form.PSDEFormRawItemImpl", "net.ibizsys.model.control.form.IPSDEFormDetail");
    put("net.ibizsys.model.control.editor.PSCheckBoxImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSNumberEditorImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.form.PSDEFormItemUpdateImpl", "net.ibizsys.model.control.form.IPSDEFormItemUpdate");
    put("net.ibizsys.model.control.form.PSDEFIUpdateDetailImpl", "net.ibizsys.model.control.form.IPSDEFIUpdateDetail");
    put("net.ibizsys.model.app.view.PSAppDEKanbanViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDECalendarExplorerViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEChartViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEGanttViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.dashboard.PSDBAppViewPortletPartImpl", "net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.dashboard.PSDBPortletPartImpl", "net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.dashboard.PSDBContainerPortletPartImpl", "net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.layout.PSFlexLayoutImpl", "net.ibizsys.model.control.layout.IPSLayout");
    put("net.ibizsys.model.control.dashboard.PSDBChartPortletPartImpl", "net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.dataentity.ac.PSDEACModeImpl", "net.ibizsys.model.app.dataentity.IPSAppDEACMode");
    put("net.ibizsys.model.control.editor.PSMDropDownListImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSHtmlImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSPasswordImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.app.view.PSAppDEGridView9Impl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.form.PSDEFormButtonImpl", "net.ibizsys.model.control.form.IPSDEFormDetail");
    put("net.ibizsys.model.control.editor.PSCheckBoxListImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.app.view.PSAppDEMEditViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.editor.PSRadioButtonListImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.layout.PSFlexLayoutPosImpl", "net.ibizsys.model.control.layout.IPSLayoutPos");
    put("net.ibizsys.model.app.view.PSAppDEEditView9Impl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.form.PSDEFormTabPanelImpl", "net.ibizsys.model.control.form.IPSDEFormDetail");
    put("net.ibizsys.model.control.PSEditorImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSRawImpl", "net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.form.PSDEFormItemVRImpl", "net.ibizsys.model.control.form.IPSDEFormItemVR");
    put("net.ibizsys.model.dataentity.uiaction.PSDEUIActionImpl", "net.ibizsys.model.view.IPSUIAction");
    put("net.ibizsys.model.control.form.PSDEFDGroupLogicImpl", "net.ibizsys.model.control.form.IPSDEFDLogic");
    put("net.ibizsys.model.valuerule.PSSysValueRuleImpl", "net.ibizsys.model.valuerule.IPSSysValueRule");
    put("net.ibizsys.model.dataentity.uiaction.IPSDEUIActionGroup", "net.ibizsys.model.view.IPSUIActionGroup");
    put("net.ibizsys.model.dataentity.uiaction.PSDEUIActionGroupImpl", "net.ibizsys.model.view.IPSUIActionGroup");
    put("net.ibizsys.model.dataentity.uiaction.PSDEUIActionGroupDetailImpl", "net.ibizsys.model.view.IPSUIActionGroupDetail");
    put("net.ibizsys.model.app.view.PSAppDEListExplorerViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEIndexPickupDataViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.viewpanel.PSDETabViewPanelImpl", "net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.tree.PSDETreeDataSetNodeImpl", "net.ibizsys.model.control.tree.IPSDETreeNode");
    put("net.ibizsys.model.control.tree.PSDETreeStaticNodeImpl", "net.ibizsys.model.control.tree.IPSDETreeNode");
    put("net.ibizsys.model.control.tree.PSDETreeNodeRSImpl", "net.ibizsys.model.control.tree.IPSDETreeNodeRS");
    put("net.ibizsys.model.dataentity.der.PSDER1NImpl", "net.ibizsys.model.dataentity.der.IPSDER1N");
    put("net.ibizsys.model.control.searchbar.PSSysSearchBarFilterImpl", "net.ibizsys.model.control.searchbar.IPSSearchBarFilter");
    put("net.ibizsys.model.control.grid.PSDEGridUAColumnImpl", "net.ibizsys.model.control.grid.IPSDEGridColumn");
    put("net.ibizsys.model.control.grid.PSDEGridEditItemVRImpl", "net.ibizsys.model.control.grid.IPSDEGridEditItemVR");
    put("net.ibizsys.model.app.view.PSAppDEPickupViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDECalendarViewImpl", "net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.service.PSSubSysServiceAPIImpl", "net.ibizsys.model.service.IPSSubSysServiceAPI");
    put("net.ibizsys.model.service.PSSysServiceAPIImpl","net.ibizsys.model.service.IPSSysServiceAPI");
    put("net.ibizsys.model.PSSystemImpl", "net.ibizsys.model.IPSSystem");
    put("net.ibizsys.model.wf.PSWFInteractiveLinkImpl","net.ibizsys.model.wf.IPSWFLink");
    put("net.ibizsys.model.wf.PSWFRouteLinkImpl","net.ibizsys.model.wf.IPSWFLink");
    put("net.ibizsys.model.msg.PSSysMsgTemplImpl","net.ibizsys.model.wf.IPSSysMsgTempl");
    put("net.ibizsys.model.dataentity.mainstate.PSDEMainStateImpl","net.ibizsys.model.dataentity.mainstate.IPSDEMainState");
    put("net.ibizsys.model.app.PSApplicationImpl","net.ibizsys.model.app.IPSApplication");

    put("net.ibizsys.model.app.view.PSAppDEChartExplorerViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDECustomViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEDataViewExplorerViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEDataViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMapExplorerViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMapViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobCalendarViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobChartViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobDashboardViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobEditViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobHtmlViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobMapViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobMDViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobMEditViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobMPickupViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobPanelViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobPickupMDViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobPickupTreeViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobPickupViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobTabExplorerViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEMobTreeViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEPanelViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEPickupTreeViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEReportViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDETreeGridExViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.app.view.PSAppDEWFGridViewImpl","net.ibizsys.model.app.view.IPSAppView");
    put("net.ibizsys.model.control.dashboard.PSDBAppMenuPortletPartImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.dashboard.PSDBHtmlPortletPartImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.dashboard.PSDBListPortletPartImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.dashboard.PSDBRawItemPortletPartImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.dashboard.PSDBToolbarPortletPartImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.dashboard.PSSysDashboardImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.editor.PSAutoCompleteImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSCodeImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSIPAddressImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSListBoxImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSListBoxPickerImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSMailAddressImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSMarkdownImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSMPickerImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSPickupViewImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSRatingImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSSliderImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.editor.PSStepperImpl","net.ibizsys.model.control.IPSEditor");
    put("net.ibizsys.model.control.expbar.PSTabExpPanelImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.expbar.PSTreeExpBarImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.form.PSDEEditFormImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.form.PSDEFormIFrameImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.form.PSDEFormItemImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.form.PSDESearchFormImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.grid.PSDEGridGroupColumnImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.grid.PSDEGridImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.menu.PSAppMenuImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.searchbar.PSSysSearchBarImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.toolbar.PSDEToolbarImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.tree.PSDETreeCodeListNodeImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.tree.PSDETreeGridExImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.tree.PSDETreeImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.tree.PSDETreeNodeDataItemImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.control.viewpanel.PSDEPickupViewPanelImpl","net.ibizsys.model.control.IPSControl");
    put("net.ibizsys.model.dataentity.action.PSDELogicActionImpl","net.ibizsys.model.dataentity.action.IPSDEAction");
    put("net.ibizsys.model.dataentity.action.PSDEScriptActionImpl","net.ibizsys.model.dataentity.action.IPSDEAction");
    put("net.ibizsys.model.dataentity.datasync.PSDEDataSyncImpl","net.ibizsys.model.dataentity.datasync.IPSDEDataSync");
    put("net.ibizsys.model.dataentity.defield.PSFormulaDEFieldImpl","net.ibizsys.model.dataentity.defield.IPSDEField");
    put("net.ibizsys.model.dataentity.defield.PSLinkDEFieldImpl","net.ibizsys.model.dataentity.defield.IPSDEField");
    put("net.ibizsys.model.dataentity.defield.PSOne2ManyDataDEFieldImpl","net.ibizsys.model.dataentity.defield.IPSDEField");
    put("net.ibizsys.model.dataentity.defield.PSPickupDEFieldImpl","net.ibizsys.model.dataentity.defield.IPSDEField");

  }};

  private static Set<String> checkSet=new HashSet<>();

  public static String getSimpleName(String fileName) {
    if ((fileName != null) && (fileName.length() > 0)) {
      int dot = fileName.lastIndexOf('.');
      if ((dot > -1) && (dot < (fileName.length() - 1))) {
        return fileName.substring(dot + 1);
      }
    }
    return fileName;
  }

  @Override
  public final Object resolve(final Object context,  String name) {
    Class<?> key = context.getClass();
    Map<String, Method> mcache = cache(key);

    Method member = mcache.get(name);
    if (member == null) {
      if(context instanceof IModel)
      {
        Class<?> subKey=((IModel) context).getOpt().getClass();
        mcache = cache(subKey);
        member = mcache.get(name);
        if (member == null) {
          return UNRESOLVED;
        } else {

          String rtType=null;
          Type genericReturnType = member.getGenericReturnType();
          //获取返回值的泛型参数
          if(genericReturnType!=null&&genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType)genericReturnType).getActualTypeArguments();
            if(actualTypeArguments!=null&&actualTypeArguments.length>0)
              rtType=actualTypeArguments[0].getTypeName();
          }
          if(StringUtils.isEmpty(rtType))
            rtType=member.getReturnType().getName();
          String mainType=key.getName();
          String subType=subKey.getName();
          if(classMap.containsKey(mainType))
            mainType=classMap.get(mainType);
          if(classMap.containsKey(rtType))
            rtType=classMap.get(rtType);
          if(classMap.containsKey(subType))
            subType=classMap.get(subType);

          String id=mainType+"-"+name+"-"+rtType;
          if(!checkSet.contains(id))
          {
            checkSet.add(id);
            LOGGER.trace("{}-{}-{}",getSimpleName(mainType),name,getSimpleName(rtType));
          }
          id=subType+"-"+name+"-"+rtType;
          if(!checkSet.contains(id))
          {
            checkSet.add(id);
            LOGGER.trace("{}-{}-{}",getSimpleName(subType),name,getSimpleName(rtType));
          }
          return invokeMember(member, ((IModel) context).getOpt());
        }
      }
      return UNRESOLVED;
    } else {

      String rtType=null;
      Type genericReturnType = member.getGenericReturnType();
      //获取返回值的泛型参数
      if(genericReturnType!=null&&genericReturnType instanceof ParameterizedType){
        Type[] actualTypeArguments = ((ParameterizedType)genericReturnType).getActualTypeArguments();
        if(actualTypeArguments!=null&&actualTypeArguments.length>0)
          rtType=actualTypeArguments[0].getTypeName();
      }
      if(StringUtils.isEmpty(rtType))
        rtType=member.getReturnType().getName();
      String mainType=key.getName();
      if(classMap.containsKey(mainType))
        mainType=classMap.get(mainType);
      if(classMap.containsKey(rtType))
        rtType=classMap.get(rtType);
      String id=mainType+"-"+name+"-"+rtType;
      if(!checkSet.contains(id))
      {
        checkSet.add(id);
        LOGGER.trace("{}-{}-{}",getSimpleName(mainType),name,getSimpleName(rtType));
      }
      return invokeMember(member, context);
    }
  }

  @Override
  public Object resolve(final Object context) {
    return UNRESOLVED;
  }

  /**
   * Get or build a class member cache.
   *
   * @param clazz Owner/key.
   * @return A class cache.
   */
  private Map<String, Method> cache(final Class<?> clazz) {
    Map<String, Method> mcache = this.cache.get(clazz);
    if (mcache == null) {
      mcache = new HashMap<>();
      Set<Method> members = members(clazz);
      for (Method m : members) {
        // Mark as accessible.
        if (m instanceof AccessibleObject) {
          ((AccessibleObject) m).setAccessible(true);
        }
        String name=memberName(m);

        mcache.put(name, m);
        if(name.startsWith("pS"))
        {
          mcache.put("ps"+name.substring(2),m);
        }
        mcache.put(m.getName(),m);
      }
      this.cache.put(clazz, mcache);
    }
    return mcache;
  }


  /**
   * True if the member is public.
   *
   * @param member The member object.
   * @return True if the member is public.
   */
  protected boolean isPublic(final Method member) {
    return Modifier.isPublic(member.getModifiers());
  }

  /**
   * True if the member is private.
   *
   * @param member The member object.
   * @return True if the member is private.
   */
  protected boolean isPrivate(final Method member) {
    return Modifier.isPrivate(member.getModifiers());
  }

  /**
   * True if the member is protected.
   *
   * @param member The member object.
   * @return True if the member is protected.
   */
  protected boolean isProtected(final Method member) {
    return Modifier.isProtected(member.getModifiers());
  }

  /**
   * True if the member is static.
   *
   * @param member The member object.
   * @return True if the member is static.
   */
  protected boolean isStatic(final Method member) {
    return Modifier.isStatic(member.getModifiers());
  }



  @Override
  public Set<Map.Entry<String, Object>> propertySet(final Object context) {
    notNull(context, "The context is required.");
    if (context instanceof Map) {
      return Collections.emptySet();
    } else if (context instanceof Collection) {
      return Collections.emptySet();
    }
    Collection<Method> members = cache(context.getClass()).values();
    Map<String, Object> propertySet = new LinkedHashMap<>();
    for (Method member : members) {
      String name = memberName(member);
      propertySet.put(name, resolve(context, name));
    }
    return propertySet.entrySet();
  }



  /**
   * Args for getters.
   */
  private static final Object[] EMPTY_ARGS = new Object[0];


  protected Object invokeMember(final Method member, final Object context) {
    try {
      return member.invoke(context, EMPTY_ARGS);
    } catch (InvocationTargetException ex) {
      Throwable cause = ex.getCause();
      if (cause instanceof RuntimeException) {
        throw (RuntimeException) cause;
      }
      throw new IllegalStateException("Execution of '" + member.getName() + "' failed", cause);
    } catch (IllegalAccessException ex) {
      throw new IllegalStateException(
              "Could not access method:  '" + member.getName() + "'", ex);
    }
  }

  protected Set<Method> members(final Class<?> clazz) {
    Set<Method> members = new LinkedHashSet<>();
    members(clazz, members);
    return members;
  }


  /**
   * The 'is' prefix.
   */
  private static final String IS_PREFIX = "is";

  /**
   * The 'get' prefix.
   */
  private static final String GET_PREFIX = "get";

  /**
   * The default value resolver.
   */
  public static final ValueResolver INSTANCE = new BaseModelValueResolver();

  public boolean matches(final Method method, final String name) {
    if (name.equals("length") && method.getName().equals("size")) {
      boolean isCollection = isCollectionMethod(method);
      if (isCollection) {
        return true;
      }
    }

    boolean isStatic = isStatic(method);
    boolean isPublic = isPublic(method);
    boolean isGet = method.getName().equals(javaBeanMethod(GET_PREFIX, name));
    boolean isBoolGet = method.getName().equals(javaBeanMethod(IS_PREFIX, name));
    int parameterCount = method.getParameterTypes().length;

    return !isStatic && isPublic && parameterCount == 0 && (isGet || isBoolGet);
  }

  /**
   * Convert the property's name to a JavaBean read method name.
   *
   * @param prefix The prefix: 'get' or 'is'.
   * @param name   The unqualified property name.
   * @return The javaBean method name.
   */
  private static String javaBeanMethod(final String prefix,
      final String name) {
    StringBuilder buffer = new StringBuilder(prefix);
    buffer.append(name);
    buffer.setCharAt(prefix.length(), Character.toUpperCase(name.charAt(0)));
    return buffer.toString();
  }

  protected String memberName(final Method member) {
    if (member.getName().equals("size")) {
      boolean isCollection = isCollectionMethod(member);

      if (isCollection) {
        return "length";
      }
    }

    String name = member.getName();
    if (name.startsWith(GET_PREFIX)) {
      name = name.substring(GET_PREFIX.length());
    } else if (name.startsWith(IS_PREFIX)) {
      name = name.substring(IS_PREFIX.length());
    } else {
      return name;
    }
    if (name.length() > 0) {
      return Character.toLowerCase(name.charAt(0)) + name.substring(1);
    }
    return member.getName();
  }

  /**
   * Collect all the method from the given class.
   *
   * @param clazz The base class.
   * @param members The members result set.
   */
  protected void members(final Class<?> clazz, final Set<Method> members) {
    if (clazz != Object.class) {
      // Keep backing up the inheritance hierarchy.
      Method[] methods = clazz.getDeclaredMethods();
      for (Method method : methods) {
        if (matches(method, memberName(method))) {
          members.add(method);
        }
      }
      if (clazz.getSuperclass() != null) {
        members(clazz.getSuperclass(), members);
      }
      for (Class<?> superIfc : clazz.getInterfaces()) {
        members(superIfc, members);
      }
    }
  }

  /**
   * Check is method class implements Collection interface.
   *
   * @param method from class
   * @return true/false
   */
  private boolean isCollectionMethod(final Method method) {
    for (Class clazz : method.getDeclaringClass().getInterfaces()) {
      if (Collection.class.equals(clazz)) {
        return true;
      }
    }
    return false;
  }
}
