Browse Source

Merging in latest from upstream (BA/design:refs/heads/dev)

* commit '513482fa04ffb7007b5ca4d419364787c69afa28':
  调整代码
  调整代码
  REPORT-1916 做模板的过程和耗时收集=》把统计格子数量的功能分离为单独的类;调整代码
  REPORT-1916 做模板的过程和耗时收集=》若未加入产品改良计划,则不收集本地数据
  REPORT-1916 做模板的过程和耗时收集=》把 reportletsid 改成 templateID
  REPORT-1916 做模板的过程和耗时收集=》上传数据前,判断是否为测试模板
  REPORT-1916 做模板的过程和耗时收集=》调整代码
  REPORT-1916 做模板的过程和耗时收集=》上传模板数据前,判断模板是否完成
  REPORT-1916 做模板的过程和耗时收集=》重构代码,将process和consuming分离,暂时不记录模板过程
  REPORT-1916 做模板的过程和耗时收集=》修改获取单元格编辑信息的方式
  REPORT-1916 做模板的过程和耗时收集=》完成所有信息的本地存取
  REPORT-1916 做模板的过程和耗时收集=》完成基本信息的本地存取
master
yaoh.wu 8 years ago
parent
commit
c9e58b9284
  1. 73
      designer/src/com/fr/aspectj/designer/TemplateProcessTracker.aj
  2. 2
      designer/src/com/fr/design/mainframe/InformationCollector.java
  3. 1
      designer/src/com/fr/design/mainframe/JPolyWorkBook.java
  4. 18
      designer/src/com/fr/design/mainframe/JWorkBook.java
  5. 9
      designer/src/com/fr/grid/Grid.java
  6. 60
      designer_base/src/com/fr/aspectj/designerbase/TemplateProcessTracker.aj
  7. 50
      designer_base/src/com/fr/design/mainframe/JTemplate.java
  8. 42
      designer_base/src/com/fr/design/mainframe/templateinfo/JFormProcessInfo.java
  9. 75
      designer_base/src/com/fr/design/mainframe/templateinfo/JWorkBookProcessInfo.java
  10. 309
      designer_base/src/com/fr/design/mainframe/templateinfo/TemplateInfoCollector.java
  11. 26
      designer_base/src/com/fr/design/mainframe/templateinfo/TemplateProcessInfo.java
  12. 59
      designer_chart/src/com/fr/aspectj/designerchart/TemplateProcessTracker.aj
  13. 59
      designer_form/src/com/fr/aspectj/designerform/TemplateProcessTracker.aj
  14. 10
      designer_form/src/com/fr/design/mainframe/JForm.java

73
designer/src/com/fr/aspectj/designer/TemplateProcessTracker.aj

@ -0,0 +1,73 @@
package com.fr.aspectj.designer;
/**
* 记录模板过程
* Created by plough on 2017/3/3.
*/
import com.fr.design.mainframe.templateinfo.TemplateInfoCollector;
import com.fr.grid.Grid;
import org.aspectj.lang.reflect.SourceLocation;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.util.Date;
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);
pointcut onSetValue4EditingElement(Grid g, Object v) :
call(* setValue4EditingElement(java.lang.Object)) && target(g) && args(v);
//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.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 = String.format("%s:\n%s\nset value: %s at (%d, %d)\n\n", new Date(), sl, v, r, c);
String log = "";
TemplateInfoCollector.appendProcess(log);
}
//同上
before(Grid g, Object v) : onSetValue4EditingElement(g, v) {
SourceLocation sl = thisJoinPoint.getSourceLocation();
// String v = "test";
//String log = String.format("%s:\n%s\nset value: %s at %s\n\n", new Date(), sl, v, g.getEditingCellElement());
String log = "";
TemplateInfoCollector.appendProcess(log);
}
}

2
designer/src/com/fr/design/mainframe/InformationCollector.java

@ -10,6 +10,7 @@ import com.fr.data.core.db.dml.Delete;
import com.fr.data.core.db.dml.Select; import com.fr.data.core.db.dml.Select;
import com.fr.data.core.db.dml.Table; import com.fr.data.core.db.dml.Table;
import com.fr.design.DesignerEnvManager; import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.templateinfo.TemplateInfoCollector;
import com.fr.general.*; import com.fr.general.*;
import com.fr.general.http.HttpClient; import com.fr.general.http.HttpClient;
import com.fr.json.JSONArray; import com.fr.json.JSONArray;
@ -315,6 +316,7 @@ public class InformationCollector implements XMLReadable, XMLWriter {
} }
sendFunctionsInfo(); sendFunctionsInfo();
sendUserInfo(); sendUserInfo();
TemplateInfoCollector.getInstance().sendTemplateInfo();
} }
}); });
sendThread.start(); sendThread.start();

1
designer/src/com/fr/design/mainframe/JPolyWorkBook.java

@ -24,7 +24,6 @@ public class JPolyWorkBook extends JWorkBook {
super(new WorkBook(new PolyWorkSheet()), DEFAULT_NAME); super(new WorkBook(new PolyWorkSheet()), DEFAULT_NAME);
populateReportParameterAttr(); populateReportParameterAttr();
} }
/** /**
* 创建sheet名称tab面板 * 创建sheet名称tab面板

18
designer/src/com/fr/design/mainframe/JWorkBook.java

@ -3,6 +3,7 @@ package com.fr.design.mainframe;
import com.fr.base.BaseUtils; import com.fr.base.BaseUtils;
import com.fr.base.FRContext; import com.fr.base.FRContext;
import com.fr.base.Parameter; import com.fr.base.Parameter;
import com.fr.base.parameter.ParameterUI;
import com.fr.design.DesignModelAdapter; import com.fr.design.DesignModelAdapter;
import com.fr.design.ExtraDesignClassManager; import com.fr.design.ExtraDesignClassManager;
import com.fr.design.actions.AllowAuthorityEditAction; import com.fr.design.actions.AllowAuthorityEditAction;
@ -26,6 +27,8 @@ import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIModeControlContainer; import com.fr.design.gui.icontainer.UIModeControlContainer;
import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.gui.imenu.UIMenuItem;
import com.fr.design.mainframe.cell.QuickEditorRegion; import com.fr.design.mainframe.cell.QuickEditorRegion;
import com.fr.design.mainframe.templateinfo.JWorkBookProcessInfo;
import com.fr.design.mainframe.templateinfo.TemplateProcessInfo;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.menu.*; import com.fr.design.menu.*;
import com.fr.design.module.DesignModuleFactory; import com.fr.design.module.DesignModuleFactory;
@ -54,7 +57,10 @@ import com.fr.main.impl.WorkBook;
import com.fr.main.parameter.ReportParameterAttr; import com.fr.main.parameter.ReportParameterAttr;
import com.fr.poly.PolyDesigner; import com.fr.poly.PolyDesigner;
import com.fr.privilege.finegrain.WorkSheetPrivilegeControl; import com.fr.privilege.finegrain.WorkSheetPrivilegeControl;
import com.fr.report.cellcase.CellCase;
import com.fr.report.elementcase.TemplateElementCase; import com.fr.report.elementcase.TemplateElementCase;
import com.fr.report.poly.PolyWorkSheet;
import com.fr.report.report.Report;
import com.fr.report.worksheet.WorkSheet; import com.fr.report.worksheet.WorkSheet;
import com.fr.stable.ArrayUtils; import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils; import com.fr.stable.StableUtils;
@ -66,10 +72,7 @@ import javax.swing.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* JWorkBook used to edit WorkBook. * JWorkBook used to edit WorkBook.
@ -129,6 +132,13 @@ public class JWorkBook extends JTemplate<WorkBook, WorkBookUndoState> {
return centerPane; return centerPane;
} }
public TemplateProcessInfo getProcessInfo() {
if (processInfo == null) {
processInfo = new JWorkBookProcessInfo(template);
}
return processInfo;
}
/** /**
* 判断sheet权限 * 判断sheet权限
* *

9
designer/src/com/fr/grid/Grid.java

@ -10,6 +10,7 @@ import com.fr.design.constants.UIConstants;
import com.fr.design.fun.GridUIProcessor; import com.fr.design.fun.GridUIProcessor;
import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.mainframe.ElementCasePane; import com.fr.design.mainframe.ElementCasePane;
import com.fr.design.mainframe.templateinfo.TemplateInfoCollector;
import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils; import com.fr.general.ComparatorUtils;
import com.fr.grid.event.CellEditorEvent; import com.fr.grid.event.CellEditorEvent;
@ -35,6 +36,7 @@ import javax.swing.plaf.ComponentUI;
import java.awt.*; import java.awt.*;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.Date;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Iterator; import java.util.Iterator;
@ -1065,6 +1067,13 @@ public class Grid extends BaseGridComponent {
} }
/**
* @return editingCellElement 的字符串表示
*/
public String getEditingCellElement() {
return editingCellElement.toString();
}
/** /**
* 将新值赋给editingCellElement * 将新值赋给editingCellElement
* *

60
designer_base/src/com/fr/aspectj/designerbase/TemplateProcessTracker.aj

@ -0,0 +1,60 @@
package com.fr.aspectj.designerbase;
/**
* 记录模板过程
* Created by plough on 2017/3/3.
*/
import com.fr.design.mainframe.templateinfo.TemplateInfoCollector;
import org.aspectj.lang.reflect.SourceLocation;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.util.Date;
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.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 = String.format("%s:\n%s\nset value: %s at (%d, %d)\n\n", new Date(), sl, v, r, c);
String log = "";
TemplateInfoCollector.appendProcess(log);
}
}

50
designer_base/src/com/fr/design/mainframe/JTemplate.java

@ -27,6 +27,8 @@ import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.gui.imenu.UIMenuItem;
import com.fr.design.gui.itree.filetree.TemplateFileTree; import com.fr.design.gui.itree.filetree.TemplateFileTree;
import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.templateinfo.TemplateInfoCollector;
import com.fr.design.mainframe.templateinfo.TemplateProcessInfo;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.menu.MenuDef; import com.fr.design.menu.MenuDef;
import com.fr.design.menu.NameSeparator; import com.fr.design.menu.NameSeparator;
@ -72,16 +74,27 @@ public abstract class JTemplate<T extends IOFile, U extends BaseUndoState<?>> ex
private UndoManager authorityUndoManager; private UndoManager authorityUndoManager;
protected U undoState; protected U undoState;
protected U authorityUndoState = null; protected U authorityUndoState = null;
protected T template; // 当前模板
protected TemplateProcessInfo processInfo; // 模板过程的相关信息
private static short currentIndex = 0;// 此变量用于多次新建模板时,让名字不重复 private static short currentIndex = 0;// 此变量用于多次新建模板时,让名字不重复
private DesignModelAdapter<T, ?> designModel; private DesignModelAdapter<T, ?> designModel;
private PreviewProvider previewType; private PreviewProvider previewType;
private long openTime = 0L; // 打开模板的时间点(包括新建模板)
private TemplateInfoCollector tic = TemplateInfoCollector.getInstance();
private StringBuilder process = new StringBuilder(""); // 制作模板的过程
public JTemplate(T t, String defaultFileName) { public JTemplate(T t, String defaultFileName) {
this(t, new MemFILE(newTemplateNameByIndex(defaultFileName))); this(t, new MemFILE(newTemplateNameByIndex(defaultFileName)), true);
initForCollect();
} }
public JTemplate(T t, FILE file) { public JTemplate(T t, FILE file) {
this(t, file, false);
}
public JTemplate(T t, FILE file, boolean isNewFile) {
super(t); super(t);
this.template = t;
this.previewType = parserPreviewProvider(t.getPreviewType()); this.previewType = parserPreviewProvider(t.getPreviewType());
this.editingFILE = file; this.editingFILE = file;
this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.setLayout(FRGUIPaneFactory.createBorderLayout());
@ -89,6 +102,38 @@ public abstract class JTemplate<T extends IOFile, U extends BaseUndoState<?>> ex
this.add(createCenterPane(), BorderLayout.CENTER); this.add(createCenterPane(), BorderLayout.CENTER);
this.undoState = createUndoState(); this.undoState = createUndoState();
designModel = createDesignModel(); designModel = createDesignModel();
// 如果不是新建模板,并且在收集列表中
if (!isNewFile && tic.inList(t)) {
openTime = System.currentTimeMillis();
process.append(tic.loadProcess(t));
}
}
// 为收集模版信息作准备
private void initForCollect() {
if (template.getTemplateID() == null) {
template.initTemplateID(); // 为新模板设置 templateID 属性
}
if (openTime == 0) {
openTime = System.currentTimeMillis();
}
}
private void collectInfo() { // 执行收集操作
long saveTime = System.currentTimeMillis(); // 保存模板的时间点
tic.collectInfo(template, this, openTime, saveTime);
openTime = saveTime; // 更新 openTime,准备下一次计算
}
public abstract TemplateProcessInfo getProcessInfo();
// 追加过程记录
public void appendProcess(String s) {
process.append(s);
}
// 获取过程记录
public String getProcess() {
return process.toString();
} }
public U getUndoState() { public U getUndoState() {
@ -439,6 +484,7 @@ public abstract class JTemplate<T extends IOFile, U extends BaseUndoState<?>> ex
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("FR-Designer_No-Privilege") + "!", Inter.getLocText("FR-Designer_Message"), JOptionPane.WARNING_MESSAGE); JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("FR-Designer_No-Privilege") + "!", Inter.getLocText("FR-Designer_Message"), JOptionPane.WARNING_MESSAGE);
return false; return false;
} }
collectInfo();
return this.saveFile(); return this.saveFile();
} }
@ -487,6 +533,8 @@ public abstract class JTemplate<T extends IOFile, U extends BaseUndoState<?>> ex
boolean result = this.saveFile(); boolean result = this.saveFile();
if (result) { if (result) {
DesignerFrameFileDealerPane.getInstance().refresh(); DesignerFrameFileDealerPane.getInstance().refresh();
initForCollect(); // 如果是旧模板另存为新模板,则添加 templateID
collectInfo();
} }
//更换最近打开 //更换最近打开
DesignerEnvManager.getEnvManager().replaceRecentOpenedFilePath(oldName, this.getFullPathName()); DesignerEnvManager.getEnvManager().replaceRecentOpenedFilePath(oldName, this.getFullPathName());

42
designer_base/src/com/fr/design/mainframe/templateinfo/JFormProcessInfo.java

@ -0,0 +1,42 @@
package com.fr.design.mainframe.templateinfo;
import com.fr.form.main.Form;
import com.fr.form.ui.container.WFitLayout;
/**
* Created by plough on 2017/3/17.
*/
public class JFormProcessInfo extends TemplateProcessInfo<Form> {
public JFormProcessInfo(Form form) {
super(form);
}
// 获取模板类型
public int getReportType() {
return 2;
}
// 获取模板格子数
public int getCellCount() {
return 0;
}
// 获取模板悬浮元素个数
public int getFloatCount() {
return 0;
}
// 获取模板聚合块个数
public int getBlockCount() {
return 0;
}
// 获取模板控件数
public int getWidgetCount() {
int widgetCount = 0;
for (int i = 0; i < template.getContainer().getWidgetCount(); i++) {
WFitLayout wf = (WFitLayout) template.getContainer().getWidget(i);
widgetCount += wf.getWidgetCount();
}
int a = 1;
int b = 2;
return widgetCount;
}
}

75
designer_base/src/com/fr/design/mainframe/templateinfo/JWorkBookProcessInfo.java

@ -0,0 +1,75 @@
package com.fr.design.mainframe.templateinfo;
import com.fr.base.io.IOFile;
import com.fr.base.parameter.ParameterUI;
import com.fr.main.impl.WorkBook;
import com.fr.report.cellcase.CellCase;
import com.fr.report.poly.PolyWorkSheet;
import com.fr.report.worksheet.WorkSheet;
import java.util.Iterator;
/**
* Created by plough on 2017/3/17.
*/
public class JWorkBookProcessInfo extends TemplateProcessInfo<WorkBook> {
public JWorkBookProcessInfo(WorkBook wb) {
super(wb);
}
// 获取模板类型
public int getReportType() {
return template.isElementCaseBook() ? 0 : 1;
}
// 获取模板格子数
public int getCellCount() {
int cellCount = 0;
if (template.isElementCaseBook()) { // 如果是普通报表
for (int i = 0; i < template.getReportCount(); i++) {
WorkSheet r = (WorkSheet) template.getReport(i);
CellCase cc = r.getBlock().getCellCase();
for (int j = 0; j < cc.getRowCount(); j++) {
Iterator iter = cc.getRow(j);
while (iter.hasNext()) {
cellCount ++;
iter.next();
}
}
}
}
return cellCount;
}
// 获取模板悬浮元素个数
public int getFloatCount() {
int chartCount = 0;
if (template.isElementCaseBook()) { // 如果是普通报表
for (int i = 0; i < template.getReportCount(); i++) {
WorkSheet r = (WorkSheet) template.getReport(i);
Iterator fiter = r.getBlock().floatIterator();
while (fiter.hasNext()) {
chartCount ++;
fiter.next();
}
}
}
return chartCount;
}
// 获取模板聚合块个数
public int getBlockCount() {
int blockCount = 0;
if (!template.isElementCaseBook()) { // 如果是聚合报表
for (int i = 0; i < template.getReportCount(); i++) {
PolyWorkSheet r = (PolyWorkSheet) template.getReport(i);
blockCount += r.getBlockCount();
}
}
return blockCount;
}
// 获取模板控件数
public int getWidgetCount() {
ParameterUI pui = template.getReportParameterAttr().getParameterUI();
return pui == null ? 0 : (pui.getAllWidgets().length - 1);
}
}

309
designer_base/src/com/fr/design/mainframe/templateinfo/TemplateInfoCollector.java

@ -0,0 +1,309 @@
package com.fr.design.mainframe.templateinfo;
import com.fr.base.FRContext;
import com.fr.base.io.IOFile;
import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRLogger;
import com.fr.general.GeneralUtils;
import com.fr.general.SiteCenter;
import com.fr.general.http.HttpClient;
import com.fr.stable.*;
import org.json.JSONObject;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
/**
* 做模板的过程和耗时收集辅助类
* Created by plough on 2017/2/21.
*/
public class TemplateInfoCollector<T extends IOFile> implements Serializable {
private static final String FILE_NAME = "tplInfo.ser";
private static TemplateInfoCollector instance;
private HashMap<String, HashMap<String, Object>> templateInfoList;
private String designerOpenDate; //设计器最近一次打开日期
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;
@SuppressWarnings("unchecked")
private TemplateInfoCollector() {
templateInfoList = new HashMap<>();
setDesignerOpenDate();
}
/**
* 把设计器最近打开日期设定为当前日期
*/
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 static File getInfoFile() {
return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), FILE_NAME));
}
public static TemplateInfoCollector getInstance() {
if (instance == null) {
// 先尝试从文件读取
try{
ObjectInputStream is = new ObjectInputStream(new FileInputStream(getInfoFile()));
instance = (TemplateInfoCollector) is.readObject();
} catch (FileNotFoundException ex) {
// 如果之前没有存储过,则创建新对象
instance = new TemplateInfoCollector();
} catch (Exception ex) {
FRLogger.getLogger().error(ex.getMessage(), ex);
}
}
return instance;
}
private static boolean shouldCollectInfo() {
return DesignerEnvManager.getEnvManager().isJoinProductImprove() && FRContext.isChineseEnv();
}
public static 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("processMap");
return (String)processMap.get("process");
}
/**
* 根据模板ID是否在收集列表中判断是否需要收集当前模板的信息
*/
public boolean inList(T t) {
return templateInfoList.containsKey(t.getTemplateID());
}
/**
* 将包含所有信息的对象保存到文件
*/
private void saveInfo() {
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(getInfoFile()));
FRLogger.getLogger().info("writing: " + instance.templateInfoList);
os.writeObject(instance);
os.close();
} catch (Exception ex) {
FRLogger.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("day_count") + 1;
templateInfo.put("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(t.getTemplateID());
// 更新 conusmingMap
HashMap<String, Object> consumingMap = (HashMap<String, Object>) templateInfo.get("consumingMap");
timeConsume += (long)consumingMap.get("time_consume"); // 加上之前的累计编辑时间
consumingMap.put("time_consume", timeConsume);
}
else { // 新增
templateInfo = new HashMap<>();
templateInfo.put("consumingMap", getNewConsumingMap(templateID, openTime, timeConsume));
}
// 直接覆盖 processMap
templateInfo.put("processMap", getProcessMap(templateID, jt));
// 保存模板时,让 day_count 归零
templateInfo.put("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 = DesignerEnvManager.getEnvManager().getBBSName();
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("username", username);
consumingMap.put("uuid", uuid);
consumingMap.put("activitykey", activitykey);
consumingMap.put("templateID", templateID);
consumingMap.put("create_time", createTime);
consumingMap.put("time_consume", timeConsume);
consumingMap.put("jar_time", jarTime);
consumingMap.put("version", version);
return consumingMap;
}
private HashMap<String, Object> getProcessMap(String templateID, JTemplate jt) {
HashMap<String, Object> processMap = new HashMap<>();
processMap.put("templateID", templateID);
processMap.put("process", jt.getProcess());
TemplateProcessInfo info = jt.getProcessInfo();
processMap.put("report_type", info.getReportType());
processMap.put("cell_count", info.getCellCount());
processMap.put("float_count", info.getFloatCount());
processMap.put("block_count", info.getBlockCount());
processMap.put("widget_count", info.getWidgetCount());
return processMap;
}
/**
* 发送本地模板信息到服务器
*/
public void sendTemplateInfo() {
addDayCount();
String consumingUrl = SiteCenter.getInstance().acquireUrlByKind("tempinfo.consuming") + "/single";
String processUrl = SiteCenter.getInstance().acquireUrlByKind("tempinfo.process") + "/single";
ArrayList<HashMap<String, String>> completeTemplatesInfo = getCompleteTemplatesInfo();
for (HashMap<String, String> templateInfo : completeTemplatesInfo) {
String jsonConsumingMap = templateInfo.get("jsonConsumingMap");
String jsonProcessMap = templateInfo.get("jsonProcessMap");
if (sendSingleTemplateInfo(consumingUrl, jsonConsumingMap) && sendSingleTemplateInfo(processUrl, jsonProcessMap)) {
// 清空记录
FRLogger.getLogger().info("successfully send " + templateInfo.get("templateID"));
templateInfoList.remove(templateInfo.get("templateID"));
}
}
saveInfo();
}
private boolean sendSingleTemplateInfo(String url, String content) {
HashMap<String, String> para = new HashMap<>();
String date = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime());
para.put("token", CodeUtils.md5Encode(date, "", "MD5"));
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 = ComparatorUtils.equals(new JSONObject(res).get("status"), "success");
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("day_count") <= COMPLETE_DAY_COUNT) { // 未完成模板
continue;
}
if (isTestTemplate(templateInfo)) {
testTemplateKeys.add(key);
continue;
}
HashMap<String, Object> consumingMap = (HashMap<String, Object>) templateInfo.get("consumingMap");
HashMap<String, Object> processMap = (HashMap<String, Object>) templateInfo.get("processMap");
String jsonConsumingMap = new JSONObject(consumingMap).toString();
String jsonProcessMap = new JSONObject(processMap).toString();
HashMap<String, String> jsonTemplateInfo = new HashMap<>();
jsonTemplateInfo.put("jsonConsumingMap", jsonConsumingMap);
jsonTemplateInfo.put("jsonProcessMap", jsonProcessMap);
jsonTemplateInfo.put("templateID", key);
completeTemplatesInfo.add(jsonTemplateInfo);
}
// 删除测试模板
for (String key : testTemplateKeys) {
templateInfoList.remove(key);
// System.out.println(key + " is removed...");
}
return completeTemplatesInfo;
}
@SuppressWarnings("unchecked")
private boolean isTestTemplate(HashMap<String, Object> templateInfo) {
HashMap<String, Object> processMap = (HashMap<String, Object>) templateInfo.get("processMap");
int reportType = (int)processMap.get("report_type");
int cellCount = (int)processMap.get("cell_count");
int floatCount = (int)processMap.get("float_count");
int blockCount = (int)processMap.get("block_count");
int widgetCount = (int)processMap.get("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;
}
public static void main(String[] args) {
TemplateInfoCollector tic = TemplateInfoCollector.getInstance();
tic.sendTemplateInfo();
}
}

26
designer_base/src/com/fr/design/mainframe/templateinfo/TemplateProcessInfo.java

@ -0,0 +1,26 @@
package com.fr.design.mainframe.templateinfo;
import com.fr.base.io.IOFile;
/**
* Created by plough on 2017/3/17.
*/
public abstract class TemplateProcessInfo<T extends IOFile> {
protected T template;
public TemplateProcessInfo(T template) {
this.template = template;
}
// 获取模板类型。0 代表普通报表,1 代表聚合报表,2 代表表单
public abstract int getReportType();
// 获取模板格子数
public abstract int getCellCount();
// 获取模板悬浮元素个数
public abstract int getFloatCount();
// 获取模板聚合块个数
public abstract int getBlockCount();
// 获取模板控件数
public abstract int getWidgetCount();
}

59
designer_chart/src/com/fr/aspectj/designerchart/TemplateProcessTracker.aj

@ -0,0 +1,59 @@
package com.fr.aspectj.designerchart;
/**
* Created by plough on 2017/3/3.
*/
import com.fr.chart.chartattr.Chart;
import com.fr.design.mainframe.templateinfo.TemplateInfoCollector;
import org.aspectj.lang.reflect.SourceLocation;
import javax.swing.event.ListSelectionEvent;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.util.Date;
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 onChartUpdate(Chart c) :
execution(* update(Chart)) && args(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.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(Chart c) : onChartUpdate(c) {
SourceLocation sl = thisJoinPoint.getSourceLocation();
//String log = String.format("%s:\n%s\n插入新图表:%s\n\n", new Date(), sl, c.getChartName());
String log = "";
TemplateInfoCollector.appendProcess(log);
}
}

59
designer_form/src/com/fr/aspectj/designerform/TemplateProcessTracker.aj

@ -0,0 +1,59 @@
package com.fr.aspectj.designerform;
/**
* Created by plough on 2017/3/3.
*/
import com.fr.design.mainframe.templateinfo.TemplateInfoCollector;
import org.aspectj.lang.reflect.SourceLocation;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.util.Date;
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.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 = String.format("%s:\n%s\nset value: %s at (%d, %d)\n\n", new Date(), sl, v, r, c);
String log = "";
TemplateInfoCollector.appendProcess(log);
}
}

10
designer_form/src/com/fr/design/mainframe/JForm.java

@ -26,6 +26,8 @@ import com.fr.design.mainframe.actions.FormMobileAttrAction;
import com.fr.design.mainframe.actions.TemplateParameterAction; import com.fr.design.mainframe.actions.TemplateParameterAction;
import com.fr.design.mainframe.form.FormECCompositeProvider; import com.fr.design.mainframe.form.FormECCompositeProvider;
import com.fr.design.mainframe.form.FormECDesignerProvider; import com.fr.design.mainframe.form.FormECDesignerProvider;
import com.fr.design.mainframe.templateinfo.JFormProcessInfo;
import com.fr.design.mainframe.templateinfo.TemplateProcessInfo;
import com.fr.design.mainframe.toolbar.ToolBarMenuDock; import com.fr.design.mainframe.toolbar.ToolBarMenuDock;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.KeySetUtils;
@ -41,6 +43,7 @@ import com.fr.form.FormElementCaseProvider;
import com.fr.form.main.Form; import com.fr.form.main.Form;
import com.fr.form.ui.Widget; import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WBorderLayout; import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.form.ui.container.WLayout; import com.fr.form.ui.container.WLayout;
import com.fr.general.ComparatorUtils; import com.fr.general.ComparatorUtils;
import com.fr.general.FRLogger; import com.fr.general.FRLogger;
@ -91,6 +94,13 @@ public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm {
return DesignState.JFORM; return DesignState.JFORM;
} }
public TemplateProcessInfo getProcessInfo() {
if (processInfo == null) {
processInfo = new JFormProcessInfo(template);
}
return processInfo;
}
@Override @Override
protected boolean accept(Object o) { protected boolean accept(Object o) {
return !(o instanceof FloatElementsProvider); return !(o instanceof FloatElementsProvider);

Loading…
Cancel
Save