Package org.apdplat.platform.action

Source Code of org.apdplat.platform.action.ExtJSSimpleAction

/**
*
* APDPlat - Application Product Development Platform
* Copyright (c) 2013, 杨尚川, yang-shangchuan@qq.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
*/

package org.apdplat.platform.action;

import org.apdplat.module.security.model.User;
import org.apdplat.module.system.service.ExcelService;
import org.apdplat.platform.action.converter.DateTypeConverter;
import org.apdplat.platform.annotation.ModelAttr;
import org.apdplat.platform.annotation.ModelAttrRef;
import org.apdplat.platform.annotation.ModelCollRef;
import org.apdplat.platform.annotation.RenderIgnore;
import org.apdplat.platform.criteria.Property;
import org.apdplat.platform.model.Model;
import org.apdplat.platform.result.Page;
import org.apdplat.platform.util.ReflectionUtils;
import org.apdplat.platform.util.SpringContextUtils;
import org.apdplat.platform.util.Struts2Utils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import org.apache.commons.lang.StringUtils;
import org.apdplat.platform.annotation.RenderDate;
import org.apdplat.platform.annotation.RenderTime;

/**
*
*控制器接口的抽象实现类
*支持EXT JS
* @author 杨尚川
*/
public abstract class ExtJSSimpleAction<T extends Model> extends ExtJSActionSupport implements Action {
    private boolean search=false;
    protected T model = null;
    protected Class<T> modelClass;
    protected Page<T> page = new Page<>();
    @Resource(name = "springContextUtils")
    protected SpringContextUtils springContextUtils;
    @Resource(name = "excelService")
    protected ExcelService excelService;
    protected Map map=null;

    @PostConstruct
    private void initModel() {
        try{
            if (this.model == null) {
                String modelName=getDefaultModelName();
                if("model".equals(modelName)){
                    this.model = (T)getRequest().getAttribute("model");
                }else{
                    this.model = (T) springContextUtils.getBean(modelName);
                }
                modelClass=(Class<T>)model.getClass();
            }
        }catch(Exception e){
            LOG.error("initModel fail");
        }
    }
   
    public String report(){
       
        return null;
    }

    public String chart(){
        if(StringUtils.isNotBlank(getQueryString())){
            //搜索出所有数据  
            beforeSearch();
            page=getService().search(getQueryString(), null, modelClass);
            List<T> models=processSearchResult(page.getModels());
            page.setModels(models);
        }else{
            beforeQuery();
            this.setPage(getService().query(modelClass));
        }
        //生成报表XML数据
        String data=generateReportData(page.getModels());
        if(StringUtils.isBlank(data)){
            LOG.info("生成的报表数据为空");
            return null;
        }
        Struts2Utils.renderXml(data);
        //业务处理完毕后删除页面数据引用,加速垃圾回收
        this.getPage().getModels().clear();
        this.setPage(null);
       
        return null;
    }

    protected String generateReportData(List<T> models){
        return null;
    }
    private String getDefaultModelName(){
        return getDefaultModelName(this.getClass());
    }

    @Override
    protected User refreshUser(User user){
        return getService().retrieve(User.class, user.getId());
    }
    @Override
    public String create() {
        try{
            try{
                checkModel(model);
            }catch(Exception e){
                map=new HashMap();
                map.put("success", false);
                map.put("message", e.getMessage()+",不能添加");
                Struts2Utils.renderJson(map);
                return null;
            }
            assemblyModelForCreate(model);
            objectReference(model);
            getService().create(model);
            afterSuccessCreateModel(model);
        }catch(Exception e){
            LOG.error("创建模型失败",e);
            afterFailCreateModel(model);

            map=new HashMap();
            map.put("success", false);
            map.put("message", "创建失败 "+e.getMessage());
            Struts2Utils.renderJson(map);
            return null;
        }
        map=new HashMap();
        map.put("success", true);
        map.put("message", "创建成功");
        Struts2Utils.renderJson(map);
        return null;
    }

    @Override
    public String createForm() {
        return FORM;
    }
    @Override
    public String retrieve() {
        this.setModel(getService().retrieve(modelClass, model.getId()));
        if(model==null){
            Struts2Utils.renderText("false");
            return null;
        }
        afterRetrieve(model);
        Map temp = new HashMap();
        renderJsonForRetrieve(temp);
        retrieveAfterRender(temp,model);
        Struts2Utils.renderJson(temp);

        return null;
    }
  
    protected void afterRetrieve(T model){
       
    }
   
    @Override
    public String updateForm() {
        setModel(getService().retrieve(modelClass, model.getId()));
        return null;
    }

    @Override
    public String updatePart() {
        try{
            Integer version=model.getVersion();
            //此时的model里面存的值是从浏览器传输过来的
            List<Property> properties=getPartProperties(model);
            //此时的model里面存的值是从数据库里面加载的
            model=getService().retrieve(modelClass,model.getId());
           
            //数据版本控制,防止多个用户同时修改一条数据,造成更新丢失问题
            if(version==null){
                LOG.info("前台界面没有传递版本信息");
                throw new RuntimeException("您的数据没有版本信息");
            }else{
                LOG.info("前台界面传递了版本信息,version="+version);
            }
            if(version!=model.getVersion()){
                LOG.info("当前数据的版本为 "+model.getVersion()+",您的版本为 "+version);
                throw new RuntimeException("您的数据已过期,请重新修改");
            }
           
            old(model);
            for(Property property : properties){
                //把从浏览器传来的值射入model
                if(property.getName().contains(".")){
                     //处理两个对象之间的引用,如:model.org.id=1
                     if(property.getName().contains(".id")){
                        String[] attr=property.getName().replace(".",",").split(",");
                        if(attr.length==2){
                            Field field=ReflectionUtils.getDeclaredField(model, attr[0]);
                            T change=getService().retrieve((Class<T>)field.getType(), (Integer)property.getValue());
                            ReflectionUtils.setFieldValue(model, attr[0], change);
                        }
                     }
                }
                else{
                    ReflectionUtils.setFieldValue(model, property.getName(), property.getValue());
                }
            }
            now(model);
            //在更新前调用模板方法对模型进行处理
            assemblyModelForUpdate(model);
            getService().update(model);
            afterSuccessPartUpdateModel(model);
        }catch(Exception e){
            LOG.error("更新模型失败",e);
            afterFailPartUpdateModel(model);
            map=new HashMap();
            map.put("success", false);
            map.put("message", "修改失败 "+e.getMessage());
            Struts2Utils.renderJson(map);
            return null;
        }
        map=new HashMap();
        map.put("success", true);
        map.put("message", "修改成功");
        Struts2Utils.renderJson(map);
        return null;
    }
    @Override
    public String updateWhole() {
        try{
            assemblyModelForUpdate(model);
            getService().update(model);
            afterSuccessWholeUpdateModel(model);
        }catch(Exception e){
            LOG.error("更新模型失败",e);
            afterFailWholeUpdateModel(model);
            Struts2Utils.renderText("false");
            return null;
        }
        Struts2Utils.renderText("true");
        return null;
    }
    public void prepareForDelete(Integer[] ids){

    }
    public String deleteSession() {
        return null;
    }
    @Override
    public String delete() {
        try{
            prepareForDelete(getIds());
            List<Integer> deletedIds=getService().delete(modelClass, getIds());
            afterDelete(deletedIds);
        }catch(Exception e){
            LOG.info("删除数据出错",e);
            Struts2Utils.renderText(e.getMessage());
            return null;
        }
        Struts2Utils.renderText("删除成功");
        return null;
    }
    public void afterDelete(List<Integer> deletedIds){

    }
    @Override
    public String query() {
        beforeQuery();
        if(search){
            search();
            return null;
        }
        this.setPage(getService().query(modelClass, getPageCriteria(), buildPropertyCriteria(), buildOrderCriteria()));
        Map json = new HashMap();
        json.put("totalProperty", page.getTotalRecords());
        List<Map> result = new ArrayList<>();
        renderJsonForQuery(result);
        json.put("root", result);
        Struts2Utils.renderJson(json);
        //业务处理完毕后删除页面数据引用,加速垃圾回收
        this.getPage().getModels().clear();
        this.setPage(null);
       
        return null;
    }

    public String export() {
        if(search){
            //导出全部搜索结果
            page=getService().search(getQueryString(), null, modelClass);
            List<T> models=processSearchResult(page.getModels());
            page.setModels(models);
            //导出当前页的搜索结果
            //this.setPage(getService().search(getQueryString(), getPageCriteria(), modelClass));
        }else{
            //导出全部数据
            this.setPage(getService().query(modelClass, null, buildPropertyCriteria(), buildOrderCriteria()));
            //导出当前页的数据
            //this.setPage(getService().query(modelClass, getPageCriteria(), buildPropertyCriteria(), buildOrderCriteria()));
        }
        List<List<String>> result = new ArrayList<>();
        renderForExport(result);
        String path=excelService.write(result, exportFileName());
        Struts2Utils.renderText(path);
        //业务处理完毕后删除页面数据引用,加速垃圾回收
        this.getPage().getModels().clear();
        this.setPage(null);
       
        return null;
    }
    private List<T> processSearchResult(List<T> models){
        List<T> result =  new ArrayList<>();
        for(T obj : models){
            T t=getService().retrieve(modelClass, obj.getId());
            if(t!=null){
                result.add(t);
            }
        }
        return result;
    }
    @Override
    public String search() {
        beforeSearch();
        page=getService().search(getQueryString(), getPageCriteria(), modelClass);
        //List<T> models=processSearchResult(page.getModels());
        //page.setModels(models);

        Map json = new HashMap();
        json.put("totalProperty", page.getTotalRecords());
        List<Map> result = new ArrayList<>();
        renderJsonForSearch(result);
        json.put("root", result);
        Struts2Utils.renderJson(json);
        return null;
    }
    protected  void beforeQuery(){

    }
    protected  void beforeSearch(){

    }
    protected void checkModel(T model) throws Exception{

    }
    /**
     * 在【添加】一个特定的【完整】的Model之前对Model的组装,以确保组装之后的Model是一个语义完整的模型
     * @return
     */
    protected void assemblyModelForCreate(T model) {

    }
    protected void assemblyModelForUpdate(T model) {

    }
    /**
     * 模型【部分】【更新成功】后的回调方法
     * @return
     */
    protected void afterSuccessPartUpdateModel(T model) {

    }
    protected void old(T model) {

    }
    protected void now(T model) {

    }
    /**
     * 模型【部分】【更新失败】后的回调方法
     * @return
     */
    protected void afterFailPartUpdateModel(T model) {

    }
    /**
     * 模型【完整】【更新成功】后的回调方法
     * @return
     */
    protected void afterSuccessWholeUpdateModel(T model) {

    }
    /**
     * 模型【完整】【更新失败】后的回调方法
     * @return
     */
    protected void afterFailWholeUpdateModel(T model) {

    }
    /**
     * 模型【创建成功】后的回调方法
     * @return
     */
    protected void afterSuccessCreateModel(T model) {

    }
    /**
     * 模型【创建失败】后的回调方法
     * @return
     */
    protected void afterFailCreateModel(T model) {

    }

    /////////////////////////////////////以下三个方法有默认实现,可以简化Action,如果有特殊需要,子类Action可以覆写
    /**
     * 渲染需要在页面【详细信息】中显示的字段
     * @return
     */
    protected void renderJsonForRetrieve(Map map) {
        render(map,model);
    }
    /**
     * 渲染需要在页面【搜索结果表格】表格中显示的字段
     * @return
     */
    protected void renderJsonForSearch(List result) {
        renderJsonForQuery(result);
    }
    /**
     * 渲染需要在页面【表格】中显示的字段
     * @return
     */
    protected void renderJsonForQuery(List result) {
        for (T obj : page.getModels()) {
            Map temp = new HashMap();
            render(temp,obj);
            afterRender(temp,obj);
            result.add(temp);
        }
    }
    /**
     * 自动生成和自定义相结合
     * @param map 自动渲染好的对象
     */
    protected void afterRender(Map map,T obj){
       
    }
    protected void retrieveAfterRender(Map map,T obj){
       
    }
   
    protected void render(Map map,T obj){
        //获取所有字段,包括继承的
        List<Field> fields = ReflectionUtils.getDeclaredFields(model);
        for (Field field : fields) {
            if(field.isAnnotationPresent(RenderIgnore.class)){
                continue;
            }
            addFieldValue(obj, field, map);
        }
    }
    /**
     * @param src
     * 源字符串
     * @return 字符串,将src的第一个字母转换为大写,src为空时返回null
     */
    public static String change(String src) {
        if (src != null) {
            StringBuilder sb = new StringBuilder(src);
            sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
            return sb.toString();
        } else {
            return null;
        }
    }

    protected String  exportFileName() {
        return model.getMetaData()+".xls";
    }

    protected void renderForExport(List<List<String>> result) {
        List<String> data = new ArrayList<>();
        //获取所有字段,包括继承的
        List<Field> fields = ReflectionUtils.getDeclaredFields(model);
        for (Field field : fields) {
            if(field.isAnnotationPresent(ModelAttr.class)){
                ModelAttr attr = field.getAnnotation(ModelAttr.class);
                String fieldAttr = attr.value();
                data.add(fieldAttr);
            }
        }
       result.add(data);
       for( T obj : page.getModels()){
           data =new ArrayList<>();
           renderDataForExport(data,obj);
           result.add(data);
       }
    }
    private void renderDataForExport(List<String> data, T obj) {
        //获取所有字段,包括继承的
        List<Field> fields = ReflectionUtils.getDeclaredFields(obj);

        for (Field field : fields) {
            if(field.isAnnotationPresent(ModelAttr.class)){
                //导出的时候,如果是复杂类型,则忽略*_id属性
                Map<String,String> temp=new HashMap<>();
                addFieldValue(obj,field,temp);
                //复杂类型对应两个值
                temp.remove(field.getName()+"_id");
                data.addAll(temp.values());
            }
        }
    }
    private void addFieldValue(T obj, Field field, List<String> data){
        Map<String,String> temp=new HashMap<>();
        addFieldValue(obj,field,temp);
        data.addAll(temp.values());
    }
    private void addFieldValue(T obj, Field field, Map<String,String> data){
        String fieldName = field.getName();
        try{
            if(field.isAnnotationPresent(Lob.class)){
                LOG.debug("字段["+fieldName+"]为大对象,忽略生成JSON字段");
                return;
            }
            Object value = ReflectionUtils.getFieldValue(obj, field);
            if(value==null){
                data.put(fieldName, "");
                return;
            }
            //处理集合类型
            if(field.isAnnotationPresent(ModelCollRef.class)){
                ModelCollRef ref = field.getAnnotation(ModelCollRef.class);
                String fieldRef = ref.value();
                Collection col=(Collection)value;
                String colStr="";
                if(col!=null){
                    LOG.debug("处理集合,字段为:"+field.getName()+",大小为:"+col.size());
                    if(col.size()>0){
                        StringBuilder str=new StringBuilder();
                        for(Object m : col){
                            str.append(ReflectionUtils.getFieldValue(m, fieldRef).toString()).append(",");
                        }
                        str=str.deleteCharAt(str.length()-1);
                        colStr=str.toString();
                    }
                }else{
                    LOG.debug("处理集合失败,"+value+" 不能转换为集合");
                }
                data.put(fieldName, colStr);
                return ;
            }
            //处理复杂对象类型
            if(field.isAnnotationPresent(ModelAttrRef.class)){
                LOG.debug("处理对象,字段为:"+field.getName());
                ModelAttrRef ref = field.getAnnotation(ModelAttrRef.class);
                String fieldRef = ref.value();
                //加入复杂对象的ID
                Object id = ReflectionUtils.getFieldValue(value, "id");
                data.put(fieldName+"_id", id.toString());
                //因为是复杂对象,所以变换字段名称
                fieldName=fieldName+"_"+fieldRef;
                //获取fieldRef的值
                value = ReflectionUtils.getFieldValue(value, fieldRef);
            }
            if(value.getClass()==null){
                data.put(fieldName, "");
                return;
            }
            String valueClass=value.getClass().getSimpleName();

            if("PersistentBag".equals(valueClass)){
                value="";
            }
            if("Timestamp".equals(valueClass) || "Date".equals(valueClass)){
                if(field.isAnnotationPresent(RenderDate.class)){
                    value=DateTypeConverter.toDefaultDate((Date)value);
                }else if(field.isAnnotationPresent(RenderTime.class)){
                    value=DateTypeConverter.toDefaultDateTime((Date)value);
                }else{
                    //如果没有指定渲染类型,则根据@Temporal来判断
                    String temporal = "TIMESTAMP";
                    if(field.isAnnotationPresent(Temporal.class)){
                        temporal = field.getAnnotation(Temporal.class).value().name();
                    }
                    switch (temporal) {
                        case "TIMESTAMP":
                            value=DateTypeConverter.toDefaultDateTime((Date)value);
                            break;
                        case "DATE":
                            value=DateTypeConverter.toDefaultDate((Date)value);
                            break;
                    }
                }
            }
            //处理下拉菜单
            if("DicItem".equals(valueClass)){
                //当修改数据的时候,需要该值
                data.put(fieldName+"Id", ReflectionUtils.getFieldValue(value, "id").toString());
               
                value = ReflectionUtils.getFieldValue(value, "name");
            }
            data.put(fieldName, value.toString());
        }catch(Exception e){
            LOG.error("获取字段值失败",e);
        }
    }
    public T getModel() {
        return this.model;
    }

    public void setModel(T model) {
        this.model = model;
    }

    public Page<T> getPage() {
        return page;
    }

    public void setPage(Page<T> page) {
        this.page = page;
    }

    public boolean isSearch() {
        return search;
    }

    public void setSearch(boolean search) {
        this.search = search;
    }

    protected void objectReference(T model) {
        Field[] fields = model.getClass().getDeclaredFields();//获得对象方法集合
        for (Field field : fields) {// 遍历该数组
            if(field.isAnnotationPresent(ManyToOne.class) || field.isAnnotationPresent(OneToOne.class)){
                LOG.debug(model.getMetaData()+" 有ManyToOne 或 OneToOne映射,字段为"+field.getName());
                Model value=(Model)ReflectionUtils.getFieldValue(model, field);
                if(value==null){
                    LOG.debug(model.getMetaData()+" 的字段"+field.getName()+"没有值,忽略处理");
                    continue;
                }
                int id=value.getId();
                LOG.debug("id: "+id);
                value=getService().retrieve(value.getClass(), id);
                ReflectionUtils.setFieldValue(model, field, value);
            }
        }
    }
}
TOP

Related Classes of org.apdplat.platform.action.ExtJSSimpleAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.