/* $Author: chenlingfeng7543 // $Date: 2018/7/26 15:02 // $Revision: 1.0 */ package leaf.plugin.export; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.*; import java.util.logging.Level; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import com.alibaba.fastjson.JSON; import com.hand.hap.core.impl.RequestHelper; import com.hand.hls.excel.dto.ExcelExportInfo; import com.hand.hls.excel.service.IExcelExportInfoService; import com.hand.hls.utils.SpringContextHolder; import leaf.application.config.BaseServiceConfig; import leaf.database.actions.ModelQuery; import leaf.database.actions.config.ModelQueryConfig; import leaf.database.service.BusinessModelService; import leaf.database.service.DatabaseServiceFactory; import leaf.i18n.ILocalizedMessageProvider; import leaf.i18n.IMessageProvider; import leaf.plugin.export.task.IReportTask; import leaf.plugin.poi.ExcelExportImpl; import leaf.presentation.component.std.config.DataSetConfig; import leaf.service.ServiceContext; import leaf.service.ServiceInstance; import leaf.service.ServiceOutputConfig; import leaf.service.http.HttpServiceInstance; import leaf.utils.ObjectRegistryHolder; import org.apache.commons.lang3.StringUtils; import uncertain.composite.CompositeMap; import uncertain.composite.TextParser; import uncertain.event.EventModel; import uncertain.exception.BuiltinExceptionFactory; import uncertain.logging.ILogger; import uncertain.logging.LoggingContext; import uncertain.ocm.IObjectRegistry; public class ModelOutput { public final static String KEY_COLUMN_CONFIG = "_column_config_"; public final static String KEY_FILE_NAME = "_file_name_"; public final static String KEY_CHARSET = "GBK"; public final static String KEY_PROMPT = "prompt"; public final static String KEY_DATA_INDEX = "name"; public final static String KEY_MERGE_COLUMN = "_merge_column_"; public final static String KEY_COLUMN = "column"; public final static String KEY_WIDTH = "width"; public final static String KEY_GENERATE_STATE = "_generate_state"; public final static String KEY_FORMAT = "_format"; public final static String KEY_SEPARATOR = "separator"; public final static String KEY_ENABLETASK = "enableTask"; private File excelDir; public final static String KEY_XLSX = "xlsx"; public final static String KEY_TXT = "txt"; public final static String KEY_XLS = "xls"; public final static String KEY_XLS_MEMORY = "xls_memory"; IObjectRegistry mObjectRegistry; int modelQueryTagNum; public ModelOutput(IObjectRegistry registry) { mObjectRegistry = registry; } public int preInvokeService(ServiceContext context) throws Exception { CompositeMap parameters = context.getParameter(); if (!parameters.getBoolean(KEY_GENERATE_STATE, false)) return EventModel.HANDLE_NORMAL; // Excel导出 boolean isAsync = true;// "Y".equals(parameters.getString("__async__"); //if(isAsync) { if("Y".equals(parameters.getString("__async__"))){ DatabaseServiceFactory dsf = ObjectRegistryHolder.getInstanceOfType(DatabaseServiceFactory.class); String bmName = context.getString("requested_bm_name"); if(bmName != null) { BusinessModelService modelService = dsf.getModelService(bmName, context.getObjectContext()); StringBuffer querySql = modelService.getSql("query"); int index = querySql.indexOf(":@"); int lastIndex = 0; while (index > 0) { // 可能存在${:@trx_id} // 右边大括号 int right = querySql.indexOf("}", index); int left = -1; int pos = index - 1; while (left < 0 && pos > lastIndex) { char c = querySql.charAt(pos); if (c == '$') { left = pos; } else { pos--; } } String fullString = querySql.substring(left, right+1); String valuePath = StringUtils.replaceChars(fullString, "${:}", ""); Object object = parameters.getObject(valuePath); if (object == null) { throw new RuntimeException("Can not get value from: " + valuePath); } querySql.replace(left, right+1, object.toString()); lastIndex = index; index = querySql.lastIndexOf(":@"); } List<CompositeMap> columns = context.getParameter().getChild("_column_config_").getChild("column").getChilds(); transfer(columns); String fileName = parameters.getString(KEY_FILE_NAME, "excel"); String format = parameters.getString(KEY_FORMAT); ExcelExportInfo info = new ExcelExportInfo(); info.setColumnInfo(JSON.toJSONString(columns)); info.setSqlContent(TextParser.parse(querySql.toString().replaceAll("\\$\\{.*?}", "'$0'"), parameters)); info.setStatus("NEW"); info.setFileName(fileName); info.setFileType(format); IExcelExportInfoService service = SpringContextHolder.getBean(IExcelExportInfoService.class); service.insertSelective(RequestHelper.getCurrentRequest(), info); return EventModel.HANDLE_NORMAL; } else { parameters.put("__excel_export__", "Y"); } } // End Excel导出 ILogger mLogger = LoggingContext.getLogger("leaf.plugin.export", mObjectRegistry); ServiceInstance svc = ServiceInstance.getInstance(context.getObjectContext()); // 修改fetchall为ture CompositeMap config = svc.getServiceConfigData().getChild( BaseServiceConfig.KEY_INIT_PROCEDURE); if (config == null) { mLogger.log(Level.SEVERE, "init-procedure tag must be defined"); throw new ServletException("init-procedure tag must be defined"); } String return_path = (String) svc.getServiceConfigData().getObject( ServiceOutputConfig.KEY_SERVICE_OUTPUT + "/@" + ServiceOutputConfig.KEY_OUTPUT); if (return_path == null) { mLogger.log(Level.SEVERE, "service-output tag must be defined"); throw new ServletException("service-output tag must be defined"); } else { if (!return_path.startsWith("/")) return_path = "/" + return_path; } modelQueryTagNum = 0; if (createConsumerTag(config, return_path, parameters)) { if (modelQueryTagNum == 0) { mLogger.log(Level.SEVERE, "The path '" + return_path + "' can't find model-query tag"); throw new ServletException("The path '" + return_path + "' can't find model-query tag"); } } boolean enableTask = isEnableTask(parameters); if (enableTask){ if (excelDir == null) { IReportTask excelTask = (IReportTask) mObjectRegistry.getInstanceOfType(IReportTask.class); if (excelTask == null) throw BuiltinExceptionFactory.createInstanceNotFoundException(null, IReportTask.class, this.getClass().getCanonicalName()); File excelDirectory = new File(excelTask.getReportDir()); if (!excelDirectory.exists()) throw new IllegalArgumentException("File " + excelTask.getReportDir() + " is not exits!"); if (!excelDirectory.isDirectory()) throw new IllegalArgumentException("File " + excelTask.getReportDir() + " is not directory!"); excelDir = excelDirectory; } } return EventModel.HANDLE_NORMAL; } private void transfer(List<CompositeMap> list){ if(list == null || list.size() < 1){ return; } for (CompositeMap map : list) { Object column = map.getObject("column"); if(column != null){ CompositeMap compositeMap = (CompositeMap) column; List<CompositeMap> childs = compositeMap.getChilds(); transfer(childs); map.put("column", childs); } } } boolean createConsumerTag(CompositeMap actionConfig, String return_path, CompositeMap parameters) { if (modelQueryTagNum != 0) return true; Iterator iterator = actionConfig.getChildIterator(); if (iterator != null) { while (iterator.hasNext()) { if (createConsumerTag((CompositeMap) iterator.next(), return_path, parameters)) { break; } } } else { String rootpath = actionConfig.getString("rootpath"); if (rootpath != null) { if (!rootpath.startsWith("/")) rootpath = "/model/" + rootpath; if ("model-query".equals(actionConfig.getName()) && return_path.equalsIgnoreCase(rootpath)) { actionConfig.putBoolean(DataSetConfig.PROPERTITY_FETCHALL, true); String format = parameters.getString(KEY_FORMAT); if (KEY_XLSX.equals(format)||KEY_XLS.equals(format)) { actionConfig .createChildByTag("consumer") .createChildByTag("output-excel") .setNameSpaceURI( "http://www.leaf-framework.org/application"); modelQueryTagNum++; return true; } if (KEY_TXT.equals(format)) { actionConfig .createChildByTag("consumer") .createChildByTag("output-txt") .setNameSpaceURI( "http://www.leaf-framework.org/application"); modelQueryTagNum++; return true; } } } } return false; } public int preCreateSuccessResponse(ServiceContext context) throws Exception { CompositeMap parameter = context.getParameter(); if (!parameter.getBoolean(KEY_GENERATE_STATE, false)) return EventModel.HANDLE_NORMAL; if (!KEY_XLS_MEMORY.equals(parameter.getString(KEY_FORMAT))) return EventModel.HANDLE_STOP; // get ILocalizedMessageProvider IMessageProvider msgProvider = (IMessageProvider) mObjectRegistry .getInstanceOfType(IMessageProvider.class); String langString = context.getSession().getString("lang", "ZHS"); ILocalizedMessageProvider localMsgProvider = msgProvider .getLocalizedMessageProvider(langString); ServiceInstance svc = ServiceInstance.getInstance(context .getObjectContext()); ExcelExportImpl excelFactory = new ExcelExportImpl(localMsgProvider); if (!isEnableTask(parameter)) { HttpServletResponse response = ((HttpServiceInstance) svc).getResponse(); String fileName = parameter.getString(KEY_FILE_NAME, "excel"); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding(KEY_CHARSET); String userAgent = ((HttpServiceInstance) svc).getRequest().getHeader("User-Agent"); if (userAgent != null) { userAgent = userAgent.toLowerCase(); if (userAgent.indexOf("msie") != -1) { fileName=new String(fileName.getBytes("GBK"),"ISO-8859-1"); }else{ fileName=new String(fileName.getBytes("UTF-8"),"ISO-8859-1"); } } response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".xls\""); response.setHeader("cache-control", "must-revalidate"); response.setHeader("pragma", "public"); excelFactory.createExcel(getExportData(context), getColumnConfig(context), response.getOutputStream(), (CompositeMap) context .getParameter().getChild(this.KEY_MERGE_COLUMN)); } else { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); String date = dateFormat.format(new Date()); String fileName = parameter.getString(KEY_FILE_NAME, "excel_") + date + "_" + System.currentTimeMillis() + ".xls"; File excel = new File(excelDir, fileName); if (excel.createNewFile()) { OutputStream os = new FileOutputStream(excel); try { excelFactory.createExcel(getExportData(context), getColumnConfig(context), os, (CompositeMap) context .getParameter().getChild(this.KEY_MERGE_COLUMN)); } finally { if (os != null) { os.flush(); os.close(); } } } parameter.put("file_path", excel.getCanonicalPath()); } return EventModel.HANDLE_STOP; } CompositeMap getExportData(ServiceContext context) throws ServletException { ILogger mLogger = LoggingContext.getLogger("leaf.plugin.export", mObjectRegistry); ServiceInstance svc = ServiceInstance.getInstance(context .getObjectContext()); String return_path = (String) svc.getServiceConfigData().getObject( ServiceOutputConfig.KEY_SERVICE_OUTPUT + "/@" + ServiceOutputConfig.KEY_OUTPUT); if (return_path == null) { mLogger.log(Level.SEVERE, "service-output must be defined"); throw new ServletException("service-output must be defined"); } CompositeMap exportData = (CompositeMap) context.getObjectContext() .getObject(return_path); return exportData; } CompositeMap getColumnConfig(ServiceContext context) throws ServletException { ILogger mLogger = LoggingContext.getLogger("leaf.plugin.export", mObjectRegistry); CompositeMap column_config = (CompositeMap) context.getParameter() .getObject(KEY_COLUMN_CONFIG + "/" + KEY_COLUMN); if (column_config == null) { mLogger.log(Level.SEVERE, "_column_config_ tag and column attibute must be defined"); throw new ServletException( "_column_config_ tag and column attibute must be defined"); } CompositeMap contextMap = context.getObjectContext(); CompositeMap datatype = (CompositeMap) contextMap .getObject("/_export_datatype"); if (datatype != null) { Iterator it = datatype.getChildIterator(); if (it != null) { while (it.hasNext()) { CompositeMap record = (CompositeMap) it.next(); String name = record.getString("field"); CompositeMap columnRecord = column_config.getChildByAttrib( "record", "name", name); columnRecord.put(ExcelExportImpl.KEY_DATA_TYPE, record .getString(ExcelExportImpl.KEY_DATA_TYPE .toLowerCase())); } } } return column_config; } private boolean isEnableTask(CompositeMap parameter){ if(parameter == null) return false; boolean enableTask = parameter.getBoolean(KEY_ENABLETASK, false); return enableTask; } }