forked from fanruan/design
Browse Source
* commit '2a520423a459a4d48f3fc5c4ed87389a4af9080a': REPORT-15314 103模板信息收集=>重构=>调整代码 REPORT-15314 103模板信息收集=>重构 REPORT-15314 103模板信息收集=>重构=>单元测试 REPORT-15314 103模板信息收集=>重构=>去掉8.0时期的兼容代码 REPORT-15314 103模板信息收集=>重构research/10.0
20 changed files with 604 additions and 648 deletions
@ -0,0 +1,44 @@ |
|||||||
|
package com.fr.design.mainframe.template.info; |
||||||
|
|
||||||
|
import com.fr.design.mainframe.SiteCenterToken; |
||||||
|
import com.fr.general.CloudCenter; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.general.http.HttpToolbox; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.HashMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* 负责向服务器发送信息 |
||||||
|
* Created by plough on 2019/4/18. |
||||||
|
*/ |
||||||
|
class SendHelper { |
||||||
|
private static final String CONSUMING_URL = CloudCenter.getInstance().acquireUrlByKind("tempinfo.consuming") + "/single"; |
||||||
|
private static final String PROCESS_URL = CloudCenter.getInstance().acquireUrlByKind("tempinfo.process") + "/single"; |
||||||
|
|
||||||
|
private static boolean sendConsumingInfo(String content) { |
||||||
|
return sendSingleTemplateInfo(CONSUMING_URL, content); |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean sendProcessInfo(String content) { |
||||||
|
return sendSingleTemplateInfo(PROCESS_URL, content); |
||||||
|
} |
||||||
|
|
||||||
|
static boolean sendTemplateInfo(TemplateInfo templateInfo) { |
||||||
|
return SendHelper.sendConsumingInfo(templateInfo.getConsumingMapJsonString()) && SendHelper.sendProcessInfo(templateInfo.getProcessMapJsonString()); |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean sendSingleTemplateInfo(String url, String content) { |
||||||
|
HashMap<String, String> para = new HashMap<>(); |
||||||
|
para.put("token", SiteCenterToken.generateToken()); |
||||||
|
para.put("content", content); |
||||||
|
|
||||||
|
try { |
||||||
|
String res = HttpToolbox.get(url, para); |
||||||
|
return ComparatorUtils.equals(new JSONObject(res).get("status"), "success"); |
||||||
|
} catch (IOException ignore) { |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,230 @@ |
|||||||
|
package com.fr.design.mainframe.template.info; |
||||||
|
|
||||||
|
import com.fr.config.MarketConfig; |
||||||
|
import com.fr.design.DesignerEnvManager; |
||||||
|
import com.fr.general.GeneralUtils; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.stable.ProductConstants; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.xml.XMLPrintWriter; |
||||||
|
import com.fr.stable.xml.XMLReadable; |
||||||
|
import com.fr.stable.xml.XMLWriter; |
||||||
|
import com.fr.stable.xml.XMLableReader; |
||||||
|
|
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.Calendar; |
||||||
|
import java.util.HashMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* 对应一张模版的记录 |
||||||
|
* Created by plough on 2019/4/18. |
||||||
|
*/ |
||||||
|
class TemplateInfo implements XMLReadable, XMLWriter { |
||||||
|
static final String XML_TAG = "TemplateInfo"; |
||||||
|
|
||||||
|
private static final String XML_PROCESS_MAP = "processMap"; |
||||||
|
private static final String XML_CONSUMING_MAP = "consumingMap"; |
||||||
|
private static final String ATTR_DAY_COUNT = "day_count"; |
||||||
|
private static final String ATTR_TEMPLATE_ID = "templateID"; |
||||||
|
private static final String ATTR_PROCESS = "process"; |
||||||
|
private static final String ATTR_FLOAT_COUNT = "float_count"; |
||||||
|
private static final String ATTR_WIDGET_COUNT = "widget_count"; |
||||||
|
private static final String ATTR_CELL_COUNT = "cell_count"; |
||||||
|
private static final String ATTR_BLOCK_COUNT = "block_count"; |
||||||
|
private static final String ATTR_REPORT_TYPE = "report_type"; |
||||||
|
private static final String ATTR_ACTIVITYKEY = "activitykey"; |
||||||
|
private static final String ATTR_JAR_TIME = "jar_time"; |
||||||
|
private static final String ATTR_CREATE_TIME = "create_time"; |
||||||
|
private static final String ATTR_UUID = "uuid"; |
||||||
|
private static final String ATTR_TIME_CONSUME = "time_consume"; |
||||||
|
private static final String ATTR_VERSION = "version"; |
||||||
|
private static final String ATTR_USERNAME = "username"; |
||||||
|
|
||||||
|
private static final int VALID_CELL_COUNT = 5; // 有效报表模板的格子数
|
||||||
|
private static final int VALID_WIDGET_COUNT = 5; // 有效报表模板的控件数
|
||||||
|
private static final int COMPLETE_DAY_COUNT = 15; // 判断模板是否完成的天数
|
||||||
|
|
||||||
|
private int idleDayCount; // 到现在为止,模版闲置(上次保存后没有再编辑过)的天数
|
||||||
|
private String templateID; |
||||||
|
// todo: processMap 和 consumingMap 还可以再拆解为小类,以后继续重构
|
||||||
|
private HashMap<String, Object> processMap = new HashMap<>(); |
||||||
|
private HashMap<String, Object> consumingMap = new HashMap<>(); |
||||||
|
|
||||||
|
private TemplateInfo() { |
||||||
|
} |
||||||
|
|
||||||
|
static TemplateInfo newInstanceByRead(XMLableReader reader) { |
||||||
|
TemplateInfo templateInfo = new TemplateInfo(); |
||||||
|
reader.readXMLObject(templateInfo); |
||||||
|
return templateInfo; |
||||||
|
} |
||||||
|
|
||||||
|
static TemplateInfo newInstance(String templateID) { |
||||||
|
HashMap<String, Object> consumingMap = new HashMap<>(); |
||||||
|
|
||||||
|
String username = MarketConfig.getInstance().getBbsUsername(); |
||||||
|
String uuid = DesignerEnvManager.getEnvManager().getUUID(); |
||||||
|
String activitykey = DesignerEnvManager.getEnvManager().getActivationKey(); |
||||||
|
String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(Calendar.getInstance().getTime()); |
||||||
|
String jarTime = GeneralUtils.readBuildNO(); |
||||||
|
String version = ProductConstants.VERSION; |
||||||
|
consumingMap.put(ATTR_USERNAME, username); |
||||||
|
consumingMap.put(ATTR_UUID, uuid); |
||||||
|
consumingMap.put(ATTR_ACTIVITYKEY, activitykey); |
||||||
|
consumingMap.put(ATTR_TEMPLATE_ID, templateID); |
||||||
|
consumingMap.put(ATTR_CREATE_TIME, createTime); |
||||||
|
consumingMap.put(ATTR_TIME_CONSUME, 0); |
||||||
|
consumingMap.put(ATTR_JAR_TIME, jarTime); |
||||||
|
consumingMap.put(ATTR_VERSION, version); |
||||||
|
|
||||||
|
TemplateInfo templateInfo = new TemplateInfo(); |
||||||
|
templateInfo.consumingMap = consumingMap; |
||||||
|
|
||||||
|
return templateInfo; |
||||||
|
} |
||||||
|
|
||||||
|
String getTemplateID() { |
||||||
|
return templateID; |
||||||
|
} |
||||||
|
|
||||||
|
HashMap<String, Object> getTemplateInfo() { |
||||||
|
HashMap<String, Object> templateInfo = new HashMap<>(); |
||||||
|
templateInfo.put(XML_PROCESS_MAP, processMap); |
||||||
|
templateInfo.put(XML_CONSUMING_MAP, consumingMap); |
||||||
|
templateInfo.put(ATTR_DAY_COUNT, idleDayCount); |
||||||
|
return templateInfo; |
||||||
|
} |
||||||
|
|
||||||
|
public void writeXML(XMLPrintWriter writer) { |
||||||
|
writer.startTAG(XML_TAG); |
||||||
|
if (StringUtils.isNotEmpty(templateID)) { |
||||||
|
writer.attr(ATTR_TEMPLATE_ID, this.templateID); |
||||||
|
} |
||||||
|
if (idleDayCount >= 0) { |
||||||
|
writer.attr(ATTR_DAY_COUNT, this.idleDayCount); |
||||||
|
} |
||||||
|
writeProcessMap(writer); |
||||||
|
writeConsumingMap(writer); |
||||||
|
|
||||||
|
writer.end(); |
||||||
|
} |
||||||
|
|
||||||
|
private void writeProcessMap(XMLPrintWriter writer) { |
||||||
|
writer.startTAG(XML_PROCESS_MAP); |
||||||
|
writer.attr(ATTR_PROCESS, (String) processMap.get(ATTR_PROCESS)); |
||||||
|
writer.attr(ATTR_FLOAT_COUNT, (int) processMap.get(ATTR_FLOAT_COUNT)); |
||||||
|
writer.attr(ATTR_WIDGET_COUNT, (int) processMap.get(ATTR_WIDGET_COUNT)); |
||||||
|
writer.attr(ATTR_CELL_COUNT, (int) processMap.get(ATTR_CELL_COUNT)); |
||||||
|
writer.attr(ATTR_BLOCK_COUNT, (int) processMap.get(ATTR_BLOCK_COUNT)); |
||||||
|
writer.attr(ATTR_REPORT_TYPE, (int) processMap.get(ATTR_REPORT_TYPE)); |
||||||
|
writer.end(); |
||||||
|
} |
||||||
|
|
||||||
|
private void writeConsumingMap(XMLPrintWriter writer) { |
||||||
|
writer.startTAG(XML_CONSUMING_MAP); |
||||||
|
writer.attr(ATTR_ACTIVITYKEY, (String) consumingMap.get(ATTR_ACTIVITYKEY)); |
||||||
|
writer.attr(ATTR_JAR_TIME, (String) consumingMap.get(ATTR_JAR_TIME)); |
||||||
|
writer.attr(ATTR_CREATE_TIME, (String) consumingMap.get(ATTR_CREATE_TIME)); |
||||||
|
writer.attr(ATTR_UUID, (String) consumingMap.get(ATTR_UUID)); |
||||||
|
writer.attr(ATTR_TIME_CONSUME, (long) consumingMap.get(ATTR_TIME_CONSUME)); |
||||||
|
writer.attr(ATTR_VERSION, (String) consumingMap.get(ATTR_VERSION)); |
||||||
|
writer.attr(ATTR_USERNAME, (String) consumingMap.get(ATTR_USERNAME)); |
||||||
|
writer.end(); |
||||||
|
} |
||||||
|
|
||||||
|
public void readXML(XMLableReader reader) { |
||||||
|
if (!reader.isChildNode()) { |
||||||
|
idleDayCount = reader.getAttrAsInt(ATTR_DAY_COUNT, 0); |
||||||
|
templateID = reader.getAttrAsString(ATTR_TEMPLATE_ID, StringUtils.EMPTY); |
||||||
|
} else { |
||||||
|
try { |
||||||
|
String name = reader.getTagName(); |
||||||
|
if (XML_PROCESS_MAP.equals(name)) { |
||||||
|
processMap.put(ATTR_PROCESS, reader.getAttrAsString(ATTR_PROCESS, StringUtils.EMPTY)); |
||||||
|
processMap.put(ATTR_FLOAT_COUNT, reader.getAttrAsInt(ATTR_FLOAT_COUNT, 0)); |
||||||
|
processMap.put(ATTR_WIDGET_COUNT, reader.getAttrAsInt(ATTR_WIDGET_COUNT, 0)); |
||||||
|
processMap.put(ATTR_CELL_COUNT, reader.getAttrAsInt(ATTR_CELL_COUNT, 0)); |
||||||
|
processMap.put(ATTR_BLOCK_COUNT, reader.getAttrAsInt(ATTR_BLOCK_COUNT, 0)); |
||||||
|
processMap.put(ATTR_REPORT_TYPE, reader.getAttrAsInt(ATTR_REPORT_TYPE, 0)); |
||||||
|
processMap.put(ATTR_TEMPLATE_ID, templateID); |
||||||
|
} else if (XML_CONSUMING_MAP.equals(name)) { |
||||||
|
consumingMap.put(ATTR_ACTIVITYKEY, reader.getAttrAsString(ATTR_ACTIVITYKEY, StringUtils.EMPTY)); |
||||||
|
consumingMap.put(ATTR_JAR_TIME, reader.getAttrAsString(ATTR_JAR_TIME, StringUtils.EMPTY)); |
||||||
|
consumingMap.put(ATTR_CREATE_TIME, reader.getAttrAsString(ATTR_CREATE_TIME, StringUtils.EMPTY)); |
||||||
|
consumingMap.put(ATTR_TEMPLATE_ID, templateID); |
||||||
|
consumingMap.put(ATTR_UUID, reader.getAttrAsString(ATTR_UUID, StringUtils.EMPTY)); |
||||||
|
consumingMap.put(ATTR_TIME_CONSUME, reader.getAttrAsLong(ATTR_TIME_CONSUME, 0)); |
||||||
|
consumingMap.put(ATTR_VERSION, reader.getAttrAsString(ATTR_VERSION, "8.0")); |
||||||
|
consumingMap.put(ATTR_USERNAME, reader.getAttrAsString(ATTR_USERNAME, StringUtils.EMPTY)); |
||||||
|
} |
||||||
|
} catch (Exception ex) { |
||||||
|
// 什么也不做,使用默认值
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
boolean isTestTemplate() { |
||||||
|
if (!isComplete()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
int reportType = (int) processMap.get(ATTR_REPORT_TYPE); |
||||||
|
int cellCount = (int) processMap.get(ATTR_CELL_COUNT); |
||||||
|
int floatCount = (int) processMap.get(ATTR_FLOAT_COUNT); |
||||||
|
int blockCount = (int) processMap.get(ATTR_BLOCK_COUNT); |
||||||
|
int widgetCount = (int) processMap.get(ATTR_WIDGET_COUNT); |
||||||
|
boolean isTestTemplate = false; |
||||||
|
if (reportType == 0) { // 普通报表
|
||||||
|
isTestTemplate = cellCount <= VALID_CELL_COUNT && floatCount <= 1 && widgetCount <= VALID_WIDGET_COUNT; |
||||||
|
} else if (reportType == 1) { // 聚合报表
|
||||||
|
isTestTemplate = blockCount <= 1 && widgetCount <= VALID_WIDGET_COUNT; |
||||||
|
} else { // 表单(reportType == 2)
|
||||||
|
isTestTemplate = widgetCount <= 1; |
||||||
|
} |
||||||
|
return isTestTemplate; |
||||||
|
} |
||||||
|
|
||||||
|
boolean isComplete() { |
||||||
|
return idleDayCount > COMPLETE_DAY_COUNT; |
||||||
|
} |
||||||
|
|
||||||
|
String getConsumingMapJsonString() { |
||||||
|
return new JSONObject(consumingMap).toString(); |
||||||
|
} |
||||||
|
|
||||||
|
String getProcessMapJsonString() { |
||||||
|
return new JSONObject(processMap).toString(); |
||||||
|
} |
||||||
|
|
||||||
|
boolean isReadyForSend() { |
||||||
|
return isComplete() && !isTestTemplate(); |
||||||
|
} |
||||||
|
|
||||||
|
void addTimeConsume(long timeConsume) { |
||||||
|
timeConsume += (long) consumingMap.get(ATTR_TIME_CONSUME); // 加上之前的累计编辑时间
|
||||||
|
consumingMap.put(ATTR_TIME_CONSUME, timeConsume); |
||||||
|
} |
||||||
|
|
||||||
|
void updateProcessMap(TemplateProcessInfo processInfo) { |
||||||
|
HashMap<String, Object> processMap = new HashMap<>(); |
||||||
|
|
||||||
|
// 暂不支持模版制作过程的收集
|
||||||
|
processMap.put(ATTR_PROCESS, StringUtils.EMPTY); |
||||||
|
|
||||||
|
processMap.put(ATTR_REPORT_TYPE, processInfo.getReportType()); |
||||||
|
processMap.put(ATTR_CELL_COUNT, processInfo.getCellCount()); |
||||||
|
processMap.put(ATTR_FLOAT_COUNT, processInfo.getFloatCount()); |
||||||
|
processMap.put(ATTR_BLOCK_COUNT, processInfo.getBlockCount()); |
||||||
|
processMap.put(ATTR_WIDGET_COUNT, processInfo.getWidgetCount()); |
||||||
|
|
||||||
|
this.processMap = processMap; |
||||||
|
} |
||||||
|
|
||||||
|
void resetIdleDayCount() { |
||||||
|
this.idleDayCount = 0; |
||||||
|
} |
||||||
|
|
||||||
|
void addIdleDayCountByOne() { |
||||||
|
this.idleDayCount += 1; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,233 @@ |
|||||||
|
package com.fr.design.mainframe.template.info; |
||||||
|
|
||||||
|
import com.fr.base.FRContext; |
||||||
|
import com.fr.design.DesignerEnvManager; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.ProductConstants; |
||||||
|
import com.fr.stable.StableUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.xml.XMLPrintWriter; |
||||||
|
import com.fr.stable.xml.XMLReadable; |
||||||
|
import com.fr.stable.xml.XMLTools; |
||||||
|
import com.fr.stable.xml.XMLWriter; |
||||||
|
import com.fr.stable.xml.XMLableReader; |
||||||
|
import com.fr.third.javax.xml.stream.XMLStreamException; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.FileOutputStream; |
||||||
|
import java.io.FileReader; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Calendar; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 做模板的过程和耗时收集,辅助类 |
||||||
|
* Created by plough on 2017/2/21. |
||||||
|
*/ |
||||||
|
public class TemplateInfoCollector implements XMLReadable, XMLWriter { |
||||||
|
private static final String XML_TAG = "TplInfo"; |
||||||
|
private static final String XML_DESIGNER_OPEN_DATE = "DesignerOpenDate"; |
||||||
|
private static final String XML_TEMPLATE_INFO_LIST = "TemplateInfoList"; |
||||||
|
private static final String XML_FILE_NAME = "tpl.info"; |
||||||
|
private static TemplateInfoCollector instance; |
||||||
|
private Map<String, TemplateInfo> templateInfoMap; |
||||||
|
private String designerOpenDate; //设计器最近一次打开日期
|
||||||
|
|
||||||
|
private TemplateInfoCollector() { |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
public static TemplateInfoCollector getInstance() { |
||||||
|
if (instance == null) { |
||||||
|
instance = new TemplateInfoCollector(); |
||||||
|
} |
||||||
|
return instance; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据模板ID是否在收集列表中,判断是否需要收集当前模板的信息 |
||||||
|
*/ |
||||||
|
public boolean contains(String templateID) { |
||||||
|
return StringUtils.isNotEmpty(templateID) && templateInfoMap.containsKey(templateID); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 收集模板信息。如果之前没有记录,则新增;如果已有记录,则更新。 |
||||||
|
* 同时将最新数据保存到文件中。 |
||||||
|
* @param timeConsume 本次制作耗时,单位为 s |
||||||
|
*/ |
||||||
|
public void collectInfo(String templateID, TemplateProcessInfo processInfo, long timeConsume) { |
||||||
|
if (!shouldCollectInfo()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
TemplateInfo templateInfo = getOrCreateTemplateInfoByID(templateID); |
||||||
|
// 收集制作耗时
|
||||||
|
templateInfo.addTimeConsume(timeConsume); |
||||||
|
// 收集模版基本信息
|
||||||
|
templateInfo.updateProcessMap(processInfo); |
||||||
|
// 刷新闲置日计数器
|
||||||
|
templateInfo.resetIdleDayCount(); |
||||||
|
|
||||||
|
// 每次更新之后,都同步到暂存文件中
|
||||||
|
saveInfo(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 发送本地模板信息到服务器,并清空已发送模版的本地记录 |
||||||
|
*/ |
||||||
|
public void sendTemplateInfo() { |
||||||
|
addIdleDayCount(); |
||||||
|
|
||||||
|
removeTestTemplates(); |
||||||
|
|
||||||
|
for (String key : templateInfoMap.keySet()) { |
||||||
|
TemplateInfo templateInfo = templateInfoMap.get(key); |
||||||
|
if (templateInfo.isReadyForSend()) { |
||||||
|
if (SendHelper.sendTemplateInfo(templateInfo)) { |
||||||
|
// 清空记录
|
||||||
|
removeFromTemplateInfoList(templateInfo.getTemplateID()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
saveInfo(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取缓存文件存放路径 |
||||||
|
*/ |
||||||
|
private static File getInfoFile() { |
||||||
|
return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), XML_FILE_NAME)); |
||||||
|
} |
||||||
|
|
||||||
|
private void init() { |
||||||
|
templateInfoMap = new HashMap<>(); |
||||||
|
setDesignerOpenDate(); |
||||||
|
|
||||||
|
if (!getInfoFile().exists()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
try { |
||||||
|
XMLableReader xmlReader = XMLableReader.createXMLableReader(new FileReader(getInfoFile())); |
||||||
|
xmlReader.readXMLObject(this); |
||||||
|
} catch (XMLStreamException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} catch (FileNotFoundException e) { |
||||||
|
// do nothing
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private TemplateInfo getOrCreateTemplateInfoByID(String templateID) { |
||||||
|
if (templateInfoMap.containsKey(templateID)) { |
||||||
|
return templateInfoMap.get(templateID); |
||||||
|
} |
||||||
|
TemplateInfo templateInfo = TemplateInfo.newInstance(templateID); |
||||||
|
templateInfoMap.put(templateID, templateInfo); |
||||||
|
return templateInfo; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 把设计器最近打开日期设定为当前日期 |
||||||
|
*/ |
||||||
|
private void setDesignerOpenDate() { |
||||||
|
designerOpenDate = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断今天是否第一次打开设计器,为了防止同一天内,多次 addIdleDayCount |
||||||
|
*/ |
||||||
|
private boolean designerOpenFirstTime() { |
||||||
|
String today = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); |
||||||
|
return !ComparatorUtils.equals(today, designerOpenDate); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean shouldCollectInfo() { |
||||||
|
//只收集本地环境的
|
||||||
|
if (!WorkContext.getCurrent().isLocal()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return DesignerEnvManager.getEnvManager().isJoinProductImprove() && FRContext.isChineseEnv(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 将包含所有信息的对象保存到文件 |
||||||
|
*/ |
||||||
|
private void saveInfo() { |
||||||
|
try { |
||||||
|
FileOutputStream out = new FileOutputStream(getInfoFile()); |
||||||
|
XMLTools.writeOutputStreamXML(this, out); |
||||||
|
} catch (Exception ex) { |
||||||
|
FineLoggerFactory.getLogger().error(ex.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新 day_count:打开设计器却未编辑模板的连续日子 |
||||||
|
*/ |
||||||
|
private void addIdleDayCount() { |
||||||
|
if (designerOpenFirstTime()) { |
||||||
|
for (TemplateInfo templateInfo : templateInfoMap.values()) { |
||||||
|
templateInfo.addIdleDayCountByOne(); |
||||||
|
} |
||||||
|
setDesignerOpenDate(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 删除所有已完成的测试模版
|
||||||
|
private void removeTestTemplates() { |
||||||
|
ArrayList<String> testTemplateKeys = new ArrayList<>(); // 保存测试模板的key
|
||||||
|
for (String key : templateInfoMap.keySet()) { |
||||||
|
if (templateInfoMap.get(key).isTestTemplate()) { |
||||||
|
testTemplateKeys.add(key); |
||||||
|
} |
||||||
|
} |
||||||
|
// 删除测试模板
|
||||||
|
for (String key : testTemplateKeys) { |
||||||
|
removeFromTemplateInfoList(key); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void removeFromTemplateInfoList(String key) { |
||||||
|
templateInfoMap.remove(key); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void readXML(XMLableReader reader) { |
||||||
|
if (reader.isChildNode()) { |
||||||
|
try { |
||||||
|
String name = reader.getTagName(); |
||||||
|
if (XML_DESIGNER_OPEN_DATE.equals(name)) { |
||||||
|
this.designerOpenDate = reader.getElementValue(); |
||||||
|
} else if (TemplateInfo.XML_TAG.equals(name)) { |
||||||
|
TemplateInfo templateInfo = TemplateInfo.newInstanceByRead(reader); |
||||||
|
templateInfoMap.put(templateInfo.getTemplateID(), templateInfo); |
||||||
|
} |
||||||
|
} catch (Exception ex) { |
||||||
|
// 什么也不做,使用默认值
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void writeXML(XMLPrintWriter writer) { |
||||||
|
writer.startTAG(XML_TAG); |
||||||
|
|
||||||
|
writer.startTAG(XML_DESIGNER_OPEN_DATE); |
||||||
|
writer.textNode(designerOpenDate); |
||||||
|
writer.end(); |
||||||
|
|
||||||
|
writer.startTAG(XML_TEMPLATE_INFO_LIST); |
||||||
|
for (TemplateInfo templateInfo : templateInfoMap.values()) { |
||||||
|
templateInfo.writeXML(writer); |
||||||
|
} |
||||||
|
writer.end(); |
||||||
|
|
||||||
|
writer.end(); |
||||||
|
} |
||||||
|
} |
@ -1,10 +1,14 @@ |
|||||||
package com.fr.design.mainframe.templateinfo; |
package com.fr.design.mainframe.template.info; |
||||||
|
|
||||||
import com.fr.base.io.BaseBook; |
import com.fr.base.io.BaseBook; |
||||||
|
|
||||||
/** |
/** |
||||||
* Created by plough on 2017/3/17. |
* Created by plough on 2017/3/17. |
||||||
*/ |
*/ |
||||||
|
// todo: 重构
|
||||||
|
// 1. 命名不好,表意不清晰。
|
||||||
|
// 2. 逻辑混乱,到底是一个 Info 类,还是一个 InfoCollector 类?
|
||||||
|
// 3. 耦合太强,用组合替代继承
|
||||||
public abstract class TemplateProcessInfo<T extends BaseBook> { |
public abstract class TemplateProcessInfo<T extends BaseBook> { |
||||||
|
|
||||||
protected T template; |
protected T template; |
@ -1,550 +0,0 @@ |
|||||||
package com.fr.design.mainframe.templateinfo; |
|
||||||
|
|
||||||
import com.fr.base.FRContext; |
|
||||||
import com.fr.base.io.BaseBook; |
|
||||||
import com.fr.config.MarketConfig; |
|
||||||
import com.fr.design.DesignerEnvManager; |
|
||||||
import com.fr.design.mainframe.DesignerContext; |
|
||||||
import com.fr.design.mainframe.JTemplate; |
|
||||||
import com.fr.design.mainframe.SiteCenterToken; |
|
||||||
import com.fr.general.CloudCenter; |
|
||||||
import com.fr.general.ComparatorUtils; |
|
||||||
import com.fr.general.GeneralUtils; |
|
||||||
import com.fr.general.IOUtils; |
|
||||||
import com.fr.general.http.HttpClient; |
|
||||||
import com.fr.json.JSONObject; |
|
||||||
import com.fr.log.FineLoggerFactory; |
|
||||||
import com.fr.stable.EncodeConstants; |
|
||||||
import com.fr.stable.ProductConstants; |
|
||||||
import com.fr.stable.StableUtils; |
|
||||||
import com.fr.stable.StringUtils; |
|
||||||
import com.fr.stable.xml.XMLPrintWriter; |
|
||||||
import com.fr.stable.xml.XMLReadable; |
|
||||||
import com.fr.stable.xml.XMLTools; |
|
||||||
import com.fr.stable.xml.XMLWriter; |
|
||||||
import com.fr.stable.xml.XMLableReader; |
|
||||||
import com.fr.third.javax.xml.stream.XMLStreamException; |
|
||||||
import com.fr.workspace.WorkContext; |
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream; |
|
||||||
import java.io.File; |
|
||||||
import java.io.FileInputStream; |
|
||||||
import java.io.FileNotFoundException; |
|
||||||
import java.io.FileOutputStream; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.InputStream; |
|
||||||
import java.io.InputStreamReader; |
|
||||||
import java.io.ObjectInputStream; |
|
||||||
import java.io.Serializable; |
|
||||||
import java.io.UnsupportedEncodingException; |
|
||||||
import java.text.SimpleDateFormat; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Calendar; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
/** |
|
||||||
* 做模板的过程和耗时收集,辅助类 |
|
||||||
* Created by plough on 2017/2/21. |
|
||||||
*/ |
|
||||||
public class TemplateInfoCollector<T extends BaseBook> implements Serializable, XMLReadable, XMLWriter { |
|
||||||
static final long serialVersionUID = 2007L; |
|
||||||
private static final String FILE_NAME = "tpl.info"; |
|
||||||
private static final String OBJECT_FILE_NAME = "tplInfo.ser"; |
|
||||||
private static final int VALID_CELL_COUNT = 5; // 有效报表模板的格子数
|
|
||||||
private static final int VALID_WIDGET_COUNT = 5; // 有效报表模板的控件数
|
|
||||||
private static final int COMPLETE_DAY_COUNT = 15; // 判断模板是否完成的天数
|
|
||||||
private static final int ONE_THOUSAND = 1000; |
|
||||||
private static final String XML_DESIGNER_OPEN_DATE = "DesignerOpenDate"; |
|
||||||
private static final String XML_TEMPLATE_INFO_LIST = "TemplateInfoList"; |
|
||||||
private static final String XML_TEMPLATE_INFO = "TemplateInfo"; |
|
||||||
private static final String XML_PROCESS_MAP = "processMap"; |
|
||||||
private static final String XML_CONSUMING_MAP = "consumingMap"; |
|
||||||
private static final String ATTR_DAY_COUNT = "day_count"; |
|
||||||
private static final String ATTR_TEMPLATE_ID = "templateID"; |
|
||||||
private static final String ATTR_PROCESS = "process"; |
|
||||||
private static final String ATTR_FLOAT_COUNT = "float_count"; |
|
||||||
private static final String ATTR_WIDGET_COUNT = "widget_count"; |
|
||||||
private static final String ATTR_CELL_COUNT = "cell_count"; |
|
||||||
private static final String ATTR_BLOCK_COUNT = "block_count"; |
|
||||||
private static final String ATTR_REPORT_TYPE = "report_type"; |
|
||||||
private static final String ATTR_ACTIVITYKEY = "activitykey"; |
|
||||||
private static final String ATTR_JAR_TIME = "jar_time"; |
|
||||||
private static final String ATTR_CREATE_TIME = "create_time"; |
|
||||||
private static final String ATTR_UUID = "uuid"; |
|
||||||
private static final String ATTR_TIME_CONSUME = "time_consume"; |
|
||||||
private static final String ATTR_VERSION = "version"; |
|
||||||
private static final String ATTR_USERNAME = "username"; |
|
||||||
private static final String JSON_CONSUMING_MAP = "jsonConsumingMap"; |
|
||||||
private static final String JSON_PROCESS_MAP = "jsonProcessMap"; |
|
||||||
private static TemplateInfoCollector instance; |
|
||||||
private Map<String, HashMap<String, Object>> templateInfoList; |
|
||||||
private String designerOpenDate; //设计器最近一次打开日期
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
private TemplateInfoCollector() { |
|
||||||
templateInfoList = new HashMap<>(); |
|
||||||
setDesignerOpenDate(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取缓存文件存放路径 |
|
||||||
*/ |
|
||||||
private static File getInfoFile() { |
|
||||||
return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), FILE_NAME)); |
|
||||||
} |
|
||||||
|
|
||||||
private static File getObjectInfoFile() { |
|
||||||
return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), OBJECT_FILE_NAME)); |
|
||||||
} |
|
||||||
|
|
||||||
public static TemplateInfoCollector getInstance() { |
|
||||||
if (instance == null) { |
|
||||||
instance = new TemplateInfoCollector(); |
|
||||||
readXMLFile(instance, getInfoFile()); |
|
||||||
// 兼容过渡。如果没有新文件,则从老文件读取数据。以后都是读写新的 xml 文件
|
|
||||||
if (!getInfoFile().exists() && getObjectInfoFile().exists()) { |
|
||||||
try { |
|
||||||
ObjectInputStream is = new ObjectInputStream(new FileInputStream(getObjectInfoFile())); |
|
||||||
instance = (TemplateInfoCollector) is.readObject(); |
|
||||||
} catch (Exception ex) { |
|
||||||
// 什么也不做,instance 使用新值
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return instance; |
|
||||||
} |
|
||||||
|
|
||||||
private static void readXMLFile(XMLReadable xmlReadable, File xmlFile) { |
|
||||||
if (xmlFile == null || !xmlFile.exists()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
String charset = EncodeConstants.ENCODING_UTF_8; |
|
||||||
try { |
|
||||||
String fileContent = getFileContent(xmlFile); |
|
||||||
InputStream xmlInputStream = new ByteArrayInputStream(fileContent.getBytes(charset)); |
|
||||||
InputStreamReader inputStreamReader = new InputStreamReader(xmlInputStream, charset); |
|
||||||
XMLableReader xmlReader = XMLableReader.createXMLableReader(inputStreamReader); |
|
||||||
|
|
||||||
if (xmlReader != null) { |
|
||||||
xmlReader.readXMLObject(xmlReadable); |
|
||||||
} |
|
||||||
xmlInputStream.close(); |
|
||||||
} catch (FileNotFoundException e) { |
|
||||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
|
||||||
} catch (IOException e) { |
|
||||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
|
||||||
} catch (XMLStreamException e) { |
|
||||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
private static String getFileContent(File xmlFile) throws FileNotFoundException, UnsupportedEncodingException { |
|
||||||
InputStream is = new FileInputStream(xmlFile); |
|
||||||
return IOUtils.inputStream2String(is); |
|
||||||
} |
|
||||||
|
|
||||||
public static void main(String[] args) { |
|
||||||
TemplateInfoCollector tic = TemplateInfoCollector.getInstance(); |
|
||||||
tic.sendTemplateInfo(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 把设计器最近打开日期设定为当前日期 |
|
||||||
*/ |
|
||||||
private void setDesignerOpenDate() { |
|
||||||
designerOpenDate = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 判断今天是否第一次打开设计器 |
|
||||||
*/ |
|
||||||
private boolean designerOpenFirstTime() { |
|
||||||
String today = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); |
|
||||||
return !ComparatorUtils.equals(today, designerOpenDate); |
|
||||||
} |
|
||||||
|
|
||||||
private boolean shouldCollectInfo() { |
|
||||||
//只收集本地环境的
|
|
||||||
if (!WorkContext.getCurrent().isLocal()) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
return DesignerEnvManager.getEnvManager().isJoinProductImprove() && FRContext.isChineseEnv(); |
|
||||||
} |
|
||||||
|
|
||||||
public void appendProcess(String log) { |
|
||||||
if (!shouldCollectInfo()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
// 获取当前编辑的模板
|
|
||||||
JTemplate jt = DesignerContext.getDesignerFrame().getSelectedJTemplate(); |
|
||||||
// 追加过程记录
|
|
||||||
jt.appendProcess(log); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 加载已经存储的模板过程 |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public String loadProcess(T t) { |
|
||||||
HashMap<String, Object> processMap = (HashMap<String, Object>) templateInfoList.get(t.getTemplateID()).get(XML_PROCESS_MAP); |
|
||||||
return (String) processMap.get(ATTR_PROCESS); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 根据模板ID是否在收集列表中,判断是否需要收集当前模板的信息 |
|
||||||
*/ |
|
||||||
public boolean inList(T t) { |
|
||||||
return templateInfoList.containsKey(t.getTemplateID()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 将包含所有信息的对象保存到文件 |
|
||||||
*/ |
|
||||||
private void saveInfo() { |
|
||||||
try { |
|
||||||
FileOutputStream out = new FileOutputStream(getInfoFile()); |
|
||||||
XMLTools.writeOutputStreamXML(this, out); |
|
||||||
} catch (Exception ex) { |
|
||||||
FineLoggerFactory.getLogger().error(ex.getMessage()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 更新 day_count:打开设计器却未编辑模板的连续日子 |
|
||||||
*/ |
|
||||||
private void addDayCount() { |
|
||||||
if (designerOpenFirstTime()) { |
|
||||||
for (String key : templateInfoList.keySet()) { |
|
||||||
HashMap<String, Object> templateInfo = templateInfoList.get(key); |
|
||||||
int dayCount = (int) templateInfo.get(ATTR_DAY_COUNT) + 1; |
|
||||||
templateInfo.put(ATTR_DAY_COUNT, dayCount); |
|
||||||
} |
|
||||||
setDesignerOpenDate(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 收集模板信息。如果之前没有记录,则新增;如果已有记录,则更新。 |
|
||||||
* 同时将最新数据保存到文件中。 |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public void collectInfo(T t, JTemplate jt, long openTime, long saveTime) { |
|
||||||
if (!shouldCollectInfo()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
HashMap<String, Object> templateInfo; |
|
||||||
|
|
||||||
long timeConsume = ((saveTime - openTime) / ONE_THOUSAND); // 制作模板耗时(单位:s)
|
|
||||||
String templateID = t.getTemplateID(); |
|
||||||
|
|
||||||
if (inList(t)) { // 已有记录
|
|
||||||
templateInfo = templateInfoList.get(templateID); |
|
||||||
// 更新 conusmingMap
|
|
||||||
HashMap<String, Object> consumingMap = (HashMap<String, Object>) templateInfo.get(XML_CONSUMING_MAP); |
|
||||||
timeConsume += (long) consumingMap.get(ATTR_TIME_CONSUME); // 加上之前的累计编辑时间
|
|
||||||
consumingMap.put(ATTR_TIME_CONSUME, timeConsume); |
|
||||||
} else { // 新增
|
|
||||||
templateInfo = new HashMap<>(); |
|
||||||
templateInfo.put(XML_CONSUMING_MAP, getNewConsumingMap(templateID, openTime, timeConsume)); |
|
||||||
} |
|
||||||
|
|
||||||
// 直接覆盖 processMap
|
|
||||||
templateInfo.put(XML_PROCESS_MAP, getProcessMap(templateID, jt)); |
|
||||||
|
|
||||||
// 保存模板时,让 day_count 归零
|
|
||||||
templateInfo.put(ATTR_DAY_COUNT, 0); |
|
||||||
|
|
||||||
templateInfoList.put(templateID, templateInfo); |
|
||||||
|
|
||||||
saveInfo(); // 每次更新之后,都同步到暂存文件中
|
|
||||||
} |
|
||||||
|
|
||||||
private HashMap<String, Object> getNewConsumingMap(String templateID, long openTime, long timeConsume) { |
|
||||||
HashMap<String, Object> consumingMap = new HashMap<>(); |
|
||||||
|
|
||||||
String username = MarketConfig.getInstance().getBbsUsername(); |
|
||||||
String uuid = DesignerEnvManager.getEnvManager().getUUID(); |
|
||||||
String activitykey = DesignerEnvManager.getEnvManager().getActivationKey(); |
|
||||||
String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(Calendar.getInstance().getTime()); |
|
||||||
String jarTime = GeneralUtils.readBuildNO(); |
|
||||||
String version = ProductConstants.VERSION; |
|
||||||
consumingMap.put(ATTR_USERNAME, username); |
|
||||||
consumingMap.put(ATTR_UUID, uuid); |
|
||||||
consumingMap.put(ATTR_ACTIVITYKEY, activitykey); |
|
||||||
consumingMap.put(ATTR_TEMPLATE_ID, templateID); |
|
||||||
consumingMap.put(ATTR_CREATE_TIME, createTime); |
|
||||||
consumingMap.put(ATTR_TIME_CONSUME, timeConsume); |
|
||||||
consumingMap.put(ATTR_JAR_TIME, jarTime); |
|
||||||
consumingMap.put(ATTR_VERSION, version); |
|
||||||
|
|
||||||
return consumingMap; |
|
||||||
} |
|
||||||
|
|
||||||
private HashMap<String, Object> getProcessMap(String templateID, JTemplate jt) { |
|
||||||
HashMap<String, Object> processMap = new HashMap<>(); |
|
||||||
|
|
||||||
processMap.put(ATTR_TEMPLATE_ID, templateID); |
|
||||||
processMap.put(ATTR_PROCESS, jt.getProcess()); |
|
||||||
|
|
||||||
TemplateProcessInfo info = jt.getProcessInfo(); |
|
||||||
processMap.put(ATTR_REPORT_TYPE, info.getReportType()); |
|
||||||
processMap.put(ATTR_CELL_COUNT, info.getCellCount()); |
|
||||||
processMap.put(ATTR_FLOAT_COUNT, info.getFloatCount()); |
|
||||||
processMap.put(ATTR_BLOCK_COUNT, info.getBlockCount()); |
|
||||||
processMap.put(ATTR_WIDGET_COUNT, info.getWidgetCount()); |
|
||||||
|
|
||||||
return processMap; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 发送本地模板信息到服务器 |
|
||||||
*/ |
|
||||||
public void sendTemplateInfo() { |
|
||||||
addDayCount(); |
|
||||||
String consumingUrl = CloudCenter.getInstance().acquireUrlByKind("tempinfo.consuming") + "/single"; |
|
||||||
String processUrl = CloudCenter.getInstance().acquireUrlByKind("tempinfo.process") + "/single"; |
|
||||||
ArrayList<HashMap<String, String>> completeTemplatesInfo = getCompleteTemplatesInfo(); |
|
||||||
for (HashMap<String, String> templateInfo : completeTemplatesInfo) { |
|
||||||
String jsonConsumingMap = templateInfo.get(JSON_CONSUMING_MAP); |
|
||||||
String jsonProcessMap = templateInfo.get(JSON_PROCESS_MAP); |
|
||||||
if (sendSingleTemplateInfo(consumingUrl, jsonConsumingMap) && sendSingleTemplateInfo(processUrl, jsonProcessMap)) { |
|
||||||
// 清空记录
|
|
||||||
removeFromTemplateInfoList(templateInfo.get(ATTR_TEMPLATE_ID)); |
|
||||||
} |
|
||||||
} |
|
||||||
saveInfo(); |
|
||||||
} |
|
||||||
|
|
||||||
private boolean sendSingleTemplateInfo(String url, String content) { |
|
||||||
HashMap<String, String> para = new HashMap<>(); |
|
||||||
para.put("token", SiteCenterToken.generateToken()); |
|
||||||
para.put("content", content); |
|
||||||
HttpClient httpClient = new HttpClient(url, para, true); |
|
||||||
httpClient.setTimeout(5000); |
|
||||||
httpClient.asGet(); |
|
||||||
|
|
||||||
if (!httpClient.isServerAlive()) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
String res = httpClient.getResponseText(); |
|
||||||
boolean success; |
|
||||||
try { |
|
||||||
success = ComparatorUtils.equals(new JSONObject(res).get("status"), "success"); |
|
||||||
} catch (Exception ex) { |
|
||||||
success = false; |
|
||||||
} |
|
||||||
return success; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 返回已完成的模板信息 |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
private ArrayList<HashMap<String, String>> getCompleteTemplatesInfo() { |
|
||||||
ArrayList<HashMap<String, String>> completeTemplatesInfo = new ArrayList<>(); |
|
||||||
ArrayList<String> testTemplateKeys = new ArrayList<>(); // 保存测试模板的key
|
|
||||||
for (String key : templateInfoList.keySet()) { |
|
||||||
HashMap<String, Object> templateInfo = templateInfoList.get(key); |
|
||||||
if ((int) templateInfo.get(ATTR_DAY_COUNT) <= COMPLETE_DAY_COUNT) { // 未完成模板
|
|
||||||
continue; |
|
||||||
} |
|
||||||
if (isTestTemplate(templateInfo)) { |
|
||||||
testTemplateKeys.add(key); |
|
||||||
continue; |
|
||||||
} |
|
||||||
HashMap<String, Object> consumingMap = (HashMap<String, Object>) templateInfo.get(XML_CONSUMING_MAP); |
|
||||||
HashMap<String, Object> processMap = (HashMap<String, Object>) templateInfo.get(XML_PROCESS_MAP); |
|
||||||
String jsonConsumingMap = new JSONObject(consumingMap).toString(); |
|
||||||
String jsonProcessMap = new JSONObject(processMap).toString(); |
|
||||||
HashMap<String, String> jsonTemplateInfo = new HashMap<>(); |
|
||||||
jsonTemplateInfo.put(JSON_CONSUMING_MAP, jsonConsumingMap); |
|
||||||
jsonTemplateInfo.put(JSON_PROCESS_MAP, jsonProcessMap); |
|
||||||
jsonTemplateInfo.put(ATTR_TEMPLATE_ID, key); |
|
||||||
completeTemplatesInfo.add(jsonTemplateInfo); |
|
||||||
} |
|
||||||
// 删除测试模板
|
|
||||||
for (String key : testTemplateKeys) { |
|
||||||
removeFromTemplateInfoList(key); |
|
||||||
} |
|
||||||
return completeTemplatesInfo; |
|
||||||
} |
|
||||||
|
|
||||||
private void removeFromTemplateInfoList(String key) { |
|
||||||
templateInfoList.remove(key); |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
private boolean isTestTemplate(HashMap<String, Object> templateInfo) { |
|
||||||
HashMap<String, Object> processMap = (HashMap<String, Object>) templateInfo.get(XML_PROCESS_MAP); |
|
||||||
int reportType = (int) processMap.get(ATTR_REPORT_TYPE); |
|
||||||
int cellCount = (int) processMap.get(ATTR_CELL_COUNT); |
|
||||||
int floatCount = (int) processMap.get(ATTR_FLOAT_COUNT); |
|
||||||
int blockCount = (int) processMap.get(ATTR_BLOCK_COUNT); |
|
||||||
int widgetCount = (int) processMap.get(ATTR_WIDGET_COUNT); |
|
||||||
boolean isTestTemplate = false; |
|
||||||
if (reportType == 0) { // 普通报表
|
|
||||||
isTestTemplate = cellCount <= VALID_CELL_COUNT && floatCount <= 1 && widgetCount <= VALID_WIDGET_COUNT; |
|
||||||
} else if (reportType == 1) { // 聚合报表
|
|
||||||
isTestTemplate = blockCount <= 1 && widgetCount <= VALID_WIDGET_COUNT; |
|
||||||
} else { // 表单(reportType == 2)
|
|
||||||
isTestTemplate = widgetCount <= 1; |
|
||||||
} |
|
||||||
return isTestTemplate; |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
@Override |
|
||||||
public void readXML(XMLableReader reader) { |
|
||||||
if (reader.isChildNode()) { |
|
||||||
try { |
|
||||||
String name = reader.getTagName(); |
|
||||||
if (XML_DESIGNER_OPEN_DATE.equals(name)) { |
|
||||||
this.designerOpenDate = reader.getElementValue(); |
|
||||||
} else if (XML_TEMPLATE_INFO_LIST.equals(name)) { |
|
||||||
readTemplateInfoList(reader); |
|
||||||
} |
|
||||||
} catch (Exception ex) { |
|
||||||
// 什么也不做,使用默认值
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void readTemplateInfoList(XMLableReader reader) { |
|
||||||
reader.readXMLObject(new XMLReadable() { |
|
||||||
public void readXML(XMLableReader reader) { |
|
||||||
if (XML_TEMPLATE_INFO.equals(reader.getTagName())) { |
|
||||||
TemplateInfo templateInfo = new TemplateInfo(); |
|
||||||
reader.readXMLObject(templateInfo); |
|
||||||
templateInfoList.put(templateInfo.getTemplateID(), templateInfo.getTemplateInfo()); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void writeXML(XMLPrintWriter writer) { |
|
||||||
writer.startTAG("TplInfo"); |
|
||||||
|
|
||||||
writer.startTAG(XML_DESIGNER_OPEN_DATE); |
|
||||||
writer.textNode(designerOpenDate); |
|
||||||
writer.end(); |
|
||||||
|
|
||||||
writeTemplateInfoList(writer); |
|
||||||
|
|
||||||
writer.end(); |
|
||||||
} |
|
||||||
|
|
||||||
private void writeTemplateInfoList(XMLPrintWriter writer) { |
|
||||||
//启停
|
|
||||||
writer.startTAG(XML_TEMPLATE_INFO_LIST); |
|
||||||
for (String templateID : templateInfoList.keySet()) { |
|
||||||
new TemplateInfo(templateInfoList.get(templateID)).writeXML(writer); |
|
||||||
} |
|
||||||
writer.end(); |
|
||||||
} |
|
||||||
|
|
||||||
private class TemplateInfo implements XMLReadable, XMLWriter { |
|
||||||
|
|
||||||
private int dayCount; |
|
||||||
private String templateID; |
|
||||||
private HashMap<String, Object> processMap = new HashMap<>(); |
|
||||||
private HashMap<String, Object> consumingMap = new HashMap<>(); |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public TemplateInfo(HashMap<String, Object> templateInfo) { |
|
||||||
this.dayCount = (int) templateInfo.get(ATTR_DAY_COUNT); |
|
||||||
this.processMap = (HashMap<String, Object>) templateInfo.get(XML_PROCESS_MAP); |
|
||||||
this.consumingMap = (HashMap<String, Object>) templateInfo.get(XML_CONSUMING_MAP); |
|
||||||
this.templateID = (String) processMap.get(ATTR_TEMPLATE_ID); |
|
||||||
} |
|
||||||
|
|
||||||
public TemplateInfo() { |
|
||||||
} |
|
||||||
|
|
||||||
public String getTemplateID() { |
|
||||||
return templateID; |
|
||||||
} |
|
||||||
|
|
||||||
public HashMap<String, Object> getTemplateInfo() { |
|
||||||
HashMap<String, Object> templateInfo = new HashMap<>(); |
|
||||||
templateInfo.put(XML_PROCESS_MAP, processMap); |
|
||||||
templateInfo.put(XML_CONSUMING_MAP, consumingMap); |
|
||||||
templateInfo.put(ATTR_DAY_COUNT, dayCount); |
|
||||||
return templateInfo; |
|
||||||
} |
|
||||||
|
|
||||||
public void writeXML(XMLPrintWriter writer) { |
|
||||||
writer.startTAG(XML_TEMPLATE_INFO); |
|
||||||
if (StringUtils.isNotEmpty(templateID)) { |
|
||||||
writer.attr(ATTR_TEMPLATE_ID, this.templateID); |
|
||||||
} |
|
||||||
if (dayCount >= 0) { |
|
||||||
writer.attr(ATTR_DAY_COUNT, this.dayCount); |
|
||||||
} |
|
||||||
writeProcessMap(writer); |
|
||||||
writeConsumingMap(writer); |
|
||||||
|
|
||||||
writer.end(); |
|
||||||
} |
|
||||||
|
|
||||||
private void writeProcessMap(XMLPrintWriter writer) { |
|
||||||
writer.startTAG(XML_PROCESS_MAP); |
|
||||||
writer.attr(ATTR_PROCESS, (String) processMap.get(ATTR_PROCESS)); |
|
||||||
writer.attr(ATTR_FLOAT_COUNT, (int) processMap.get(ATTR_FLOAT_COUNT)); |
|
||||||
writer.attr(ATTR_WIDGET_COUNT, (int) processMap.get(ATTR_WIDGET_COUNT)); |
|
||||||
writer.attr(ATTR_CELL_COUNT, (int) processMap.get(ATTR_CELL_COUNT)); |
|
||||||
writer.attr(ATTR_BLOCK_COUNT, (int) processMap.get(ATTR_BLOCK_COUNT)); |
|
||||||
writer.attr(ATTR_REPORT_TYPE, (int) processMap.get(ATTR_REPORT_TYPE)); |
|
||||||
writer.end(); |
|
||||||
} |
|
||||||
|
|
||||||
private void writeConsumingMap(XMLPrintWriter writer) { |
|
||||||
writer.startTAG(XML_CONSUMING_MAP); |
|
||||||
writer.attr(ATTR_ACTIVITYKEY, (String) consumingMap.get(ATTR_ACTIVITYKEY)); |
|
||||||
writer.attr(ATTR_JAR_TIME, (String) consumingMap.get(ATTR_JAR_TIME)); |
|
||||||
writer.attr(ATTR_CREATE_TIME, (String) consumingMap.get(ATTR_CREATE_TIME)); |
|
||||||
writer.attr(ATTR_UUID, (String) consumingMap.get(ATTR_UUID)); |
|
||||||
writer.attr(ATTR_TIME_CONSUME, (long) consumingMap.get(ATTR_TIME_CONSUME)); |
|
||||||
writer.attr(ATTR_VERSION, (String) consumingMap.get(ATTR_VERSION)); |
|
||||||
writer.attr(ATTR_USERNAME, (String) consumingMap.get(ATTR_USERNAME)); |
|
||||||
writer.end(); |
|
||||||
} |
|
||||||
|
|
||||||
public void readXML(XMLableReader reader) { |
|
||||||
if (!reader.isChildNode()) { |
|
||||||
dayCount = reader.getAttrAsInt(ATTR_DAY_COUNT, 0); |
|
||||||
templateID = reader.getAttrAsString(ATTR_TEMPLATE_ID, StringUtils.EMPTY); |
|
||||||
} else { |
|
||||||
try { |
|
||||||
String name = reader.getTagName(); |
|
||||||
if (XML_PROCESS_MAP.equals(name)) { |
|
||||||
processMap.put(ATTR_PROCESS, reader.getAttrAsString(ATTR_PROCESS, StringUtils.EMPTY)); |
|
||||||
processMap.put(ATTR_FLOAT_COUNT, reader.getAttrAsInt(ATTR_FLOAT_COUNT, 0)); |
|
||||||
processMap.put(ATTR_WIDGET_COUNT, reader.getAttrAsInt(ATTR_WIDGET_COUNT, 0)); |
|
||||||
processMap.put(ATTR_CELL_COUNT, reader.getAttrAsInt(ATTR_CELL_COUNT, 0)); |
|
||||||
processMap.put(ATTR_BLOCK_COUNT, reader.getAttrAsInt(ATTR_BLOCK_COUNT, 0)); |
|
||||||
processMap.put(ATTR_REPORT_TYPE, reader.getAttrAsInt(ATTR_REPORT_TYPE, 0)); |
|
||||||
processMap.put(ATTR_TEMPLATE_ID, templateID); |
|
||||||
} else if (XML_CONSUMING_MAP.equals(name)) { |
|
||||||
consumingMap.put(ATTR_ACTIVITYKEY, reader.getAttrAsString(ATTR_ACTIVITYKEY, StringUtils.EMPTY)); |
|
||||||
consumingMap.put(ATTR_JAR_TIME, reader.getAttrAsString(ATTR_JAR_TIME, StringUtils.EMPTY)); |
|
||||||
consumingMap.put(ATTR_CREATE_TIME, reader.getAttrAsString(ATTR_CREATE_TIME, StringUtils.EMPTY)); |
|
||||||
consumingMap.put(ATTR_TEMPLATE_ID, templateID); |
|
||||||
consumingMap.put(ATTR_UUID, reader.getAttrAsString(ATTR_UUID, StringUtils.EMPTY)); |
|
||||||
consumingMap.put(ATTR_TIME_CONSUME, reader.getAttrAsLong(ATTR_TIME_CONSUME, 0)); |
|
||||||
consumingMap.put(ATTR_VERSION, reader.getAttrAsString(ATTR_VERSION, "8.0")); |
|
||||||
consumingMap.put(ATTR_USERNAME, reader.getAttrAsString(ATTR_USERNAME, StringUtils.EMPTY)); |
|
||||||
} |
|
||||||
} catch (Exception ex) { |
|
||||||
// 什么也不做,使用默认值
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,58 +0,0 @@ |
|||||||
package com.fr.aspectj.designerbase; |
|
||||||
|
|
||||||
/** |
|
||||||
* 记录模板过程 |
|
||||||
* Created by plough on 2017/3/3. |
|
||||||
*/ |
|
||||||
|
|
||||||
import org.aspectj.lang.reflect.SourceLocation; |
|
||||||
|
|
||||||
import java.awt.event.ActionEvent; |
|
||||||
import java.awt.event.MouseEvent; |
|
||||||
|
|
||||||
public aspect TemplateProcessTracker { |
|
||||||
//声明一个pointcut,匹配你需要的方法 |
|
||||||
pointcut onMouseClicked(MouseEvent e): |
|
||||||
execution(* mouseClicked(MouseEvent)) && args(e); |
|
||||||
pointcut onMousePressed(MouseEvent e): |
|
||||||
execution(* mousePressed(MouseEvent)) && args(e); |
|
||||||
pointcut onMouseReleased(MouseEvent e): |
|
||||||
execution(* mouseReleased(MouseEvent)) && args(e); |
|
||||||
pointcut onActionPerformed(ActionEvent e): |
|
||||||
execution(* actionPerformed(ActionEvent)) && args(e); |
|
||||||
pointcut onSetValueAt(Object v, int r, int c): |
|
||||||
execution(* setValueAt(java.lang.Object, int, int)) && args(v, r, c); |
|
||||||
|
|
||||||
//before表示之前的意思 |
|
||||||
//这整个表示在MouseAdapter的public void mouseXXX(MouseEvent)方法调用之前,你想要执行的代码 |
|
||||||
before(MouseEvent e): onMouseClicked(e) || onMousePressed(e) || onMouseReleased(e) { |
|
||||||
SourceLocation sl = thisJoinPoint.getSourceLocation();//切面对应的代码位置 |
|
||||||
|
|
||||||
//String log = String.format("%s:\n%s\n%s\n%s\n\n", new Date(), sl, e, e.getSource()); |
|
||||||
String log = ""; |
|
||||||
//TemplateInfoCollector.appendProcess(log); |
|
||||||
} |
|
||||||
//同上 |
|
||||||
before(ActionEvent e): onActionPerformed(e) { |
|
||||||
SourceLocation sl = thisJoinPoint.getSourceLocation(); |
|
||||||
// !within(LogHandlerBar) 没用, 手动过滤 |
|
||||||
if (e != null && e.getSource().toString().contains("javax.swing.Timer")) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
//String log = String.format("%s:\n%s\n%s\n%s\n\n", new Date(), sl, e, e.getSource()); |
|
||||||
String log = ""; |
|
||||||
//TemplateInfoCollector.appendProcess(log); |
|
||||||
|
|
||||||
} |
|
||||||
//同上 |
|
||||||
before(Object v, int r, int c): onSetValueAt(v, r, c) { |
|
||||||
SourceLocation sl = thisJoinPoint.getSourceLocation(); |
|
||||||
|
|
||||||
//String log getSourceLocation= String.format("%s:\n%s\nset value: %s at (%d, %d)\n\n", new Date(), sl, v, r, c); |
|
||||||
String log = ""; |
|
||||||
// TemplateInfoCollector.appendProcess(log); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,42 @@ |
|||||||
|
package com.fr.design.mainframe.template.info; |
||||||
|
|
||||||
|
import com.fr.invoke.Reflect; |
||||||
|
import com.fr.stable.ProductConstants; |
||||||
|
import org.easymock.EasyMock; |
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.runner.RunWith; |
||||||
|
import org.powermock.api.easymock.PowerMock; |
||||||
|
import org.powermock.core.classloader.annotations.PrepareForTest; |
||||||
|
import org.powermock.modules.junit4.PowerMockRunner; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by plough on 2019/4/18. |
||||||
|
*/ |
||||||
|
@RunWith(PowerMockRunner.class) |
||||||
|
@PrepareForTest(ProductConstants.class) |
||||||
|
public class TemplateInfoCollectorTest { |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() { |
||||||
|
PowerMock.mockStatic(ProductConstants.class); |
||||||
|
|
||||||
|
String filePath = getClass().getResource("tpl.info").getPath(); |
||||||
|
String dirPath = filePath.substring(0, filePath.indexOf("tpl.info")); |
||||||
|
EasyMock.expect(ProductConstants.getEnvHome()).andReturn(dirPath).anyTimes(); |
||||||
|
|
||||||
|
EasyMock.replay(); |
||||||
|
PowerMock.replayAll(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testReadXML() { |
||||||
|
TemplateInfoCollector collector = TemplateInfoCollector.getInstance(); |
||||||
|
assertEquals("2019-04-18", Reflect.on(collector).field("designerOpenDate").get()); |
||||||
|
assertEquals(7, ((Map) Reflect.on(collector).field("templateInfoMap").get()).size()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<TplInfo xmlVersion="20170720" releaseVersion="10.0.0"> |
||||||
|
<DesignerOpenDate> |
||||||
|
<![CDATA[2019-04-18]]></DesignerOpenDate> |
||||||
|
<TemplateInfoList> |
||||||
|
<TemplateInfo templateID="16a988ce-8529-42f5-b17c-2ee849355071" day_count="9"> |
||||||
|
<processMap process="" float_count="0" widget_count="0" cell_count="1" block_count="0" report_type="0"/> |
||||||
|
<consumingMap activitykey="2e0ea413-fa9c241e0-9723-4354fce51e81" jar_time="不是安装版本" create_time="2019-03-26 16:13" uuid="476ca2cc-f789-4c5d-8e89-ef146580775c" time_consume="129" version="10.0" username="plough"/> |
||||||
|
</TemplateInfo> |
||||||
|
<TemplateInfo templateID="23817e4f-64b6-438e-b23b-91c1a4d0b254" day_count="9"> |
||||||
|
<processMap process="" float_count="0" widget_count="0" cell_count="231" block_count="0" report_type="0"/> |
||||||
|
<consumingMap activitykey="2e0ea413-fa9c241e0-9723-4354fce51e81" jar_time="不是安装版本" create_time="2019-03-26 16:52" uuid="476ca2cc-f789-4c5d-8e89-ef146580775c" time_consume="91" version="10.0" username="plough"/> |
||||||
|
</TemplateInfo> |
||||||
|
<TemplateInfo templateID="31319947-5ce7-4d82-97e4-3cfea825df9c" day_count="9"> |
||||||
|
<processMap process="" float_count="0" widget_count="0" cell_count="3" block_count="0" report_type="0"/> |
||||||
|
<consumingMap activitykey="2e0ea413-fa9c241e0-9723-4354fce51e81" jar_time="不是安装版本" create_time="2019-03-26 16:49" uuid="476ca2cc-f789-4c5d-8e89-ef146580775c" time_consume="160" version="10.0" username="plough"/> |
||||||
|
</TemplateInfo> |
||||||
|
<TemplateInfo templateID="43bdd914-a3f7-405c-ad96-2feaf28bed74" day_count="8"> |
||||||
|
<processMap process="" float_count="0" widget_count="0" cell_count="1" block_count="0" report_type="0"/> |
||||||
|
<consumingMap activitykey="2e0ea413-fa9c241e0-9723-4354fce51e81" jar_time="2019.01.04.18.06.01.38" create_time="2019-03-27 16:17" uuid="476ca2cc-f789-4c5d-8e89-ef146580775c" time_consume="1426" version="10.0" username="plough"/> |
||||||
|
</TemplateInfo> |
||||||
|
<TemplateInfo templateID="cd527ae5-06e4-48fb-a73e-e9a06c9e7c58" day_count="12"> |
||||||
|
<processMap process="" float_count="0" widget_count="0" cell_count="3" block_count="0" report_type="0"/> |
||||||
|
<consumingMap activitykey="2e0ea413-fa9c241e0-9723-4354fce51e81" jar_time="2019.01.04.18.06.01.38" create_time="2019-03-15 10:02" uuid="476ca2cc-f789-4c5d-8e89-ef146580775c" time_consume="430" version="10.0" username="plough"/> |
||||||
|
</TemplateInfo> |
||||||
|
<TemplateInfo templateID="08f9c404-8124-4615-a34c-735dcabee137" day_count="9"> |
||||||
|
<processMap process="" float_count="0" widget_count="0" cell_count="2" block_count="0" report_type="0"/> |
||||||
|
<consumingMap activitykey="2e0ea413-fa9c241e0-9723-4354fce51e81" jar_time="不是安装版本" create_time="2019-03-25 17:22" uuid="476ca2cc-f789-4c5d-8e89-ef146580775c" time_consume="1497" version="10.0" username="plough"/> |
||||||
|
</TemplateInfo> |
||||||
|
<TemplateInfo templateID="981314a5-9c5b-4831-97d8-15e76735f9e2" day_count="1"> |
||||||
|
<processMap process="" float_count="0" widget_count="0" cell_count="3" block_count="0" report_type="0"/> |
||||||
|
<consumingMap activitykey="2e0ea413-fa9c241e0-9723-4354fce51e81" jar_time="不是安装版本" create_time="2019-04-17 16:24" uuid="476ca2cc-f789-4c5d-8e89-ef146580775c" time_consume="155" version="10.0" username="plough"/> |
||||||
|
</TemplateInfo> |
||||||
|
</TemplateInfoList> |
||||||
|
</TplInfo> |
@ -1,4 +1,4 @@ |
|||||||
package com.fr.design.mainframe.templateinfo; |
package com.fr.design.mainframe.template.info; |
||||||
|
|
||||||
import com.fr.form.main.Form; |
import com.fr.form.main.Form; |
||||||
import com.fr.form.ui.container.WLayout; |
import com.fr.form.ui.container.WLayout; |
@ -1,4 +1,4 @@ |
|||||||
package com.fr.design.mainframe.templateinfo; |
package com.fr.design.mainframe.template.info; |
||||||
|
|
||||||
import com.fr.base.parameter.ParameterUI; |
import com.fr.base.parameter.ParameterUI; |
||||||
import com.fr.main.impl.WorkBook; |
import com.fr.main.impl.WorkBook; |
Loading…
Reference in new issue