Browse Source

Merging in latest from upstream (DESIGN/design:refs/heads/feature/x)

* commit 'ff5784311ad6d8d0a5c2f07d098d8a0808a37cce':
  CHART-18176  钻取地图标记点默认值修改
  REPORT-46779 报表预览第一行显示不全
  REPORT-47101 海外设计器通行证相关链接替换
  REPORT-46916 修复单元测试
  REPORT-46916 调整包名,兼容性调整
  REPORT-46916 调整包名
  REPORT-46916 新引擎内置,调整代码结构,适配代码调用方式
  REPORT-46916 新引擎内置,添加模块
  REPORT-46916 新引擎内置,添加模块
  REPORT-47632 远程锁定-从远程切换到本地后,数据集窗口的锁定图标不消失 【问题原因】之前的逻辑不完善,如果处于远程状态下是锁定的,isLock变量为true,然后切回本地了,这个变量没有被置为false,会导致数据集窗口图标一直为锁定状态 【改动思路】加个判断,如果不是远程设计状态且isLock为true,将其置为false,再通知观察者们
  REPORT-47606 聚合报表拖拽时停止编辑会回退到原位置
persist/11.0
rinoux 4 years ago
parent
commit
db43d776c7
  1. 1
      build.gradle
  2. 47
      designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java
  3. 49
      designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java
  4. 18
      designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java
  5. 10
      designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java
  6. 15
      designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java
  7. 2
      designer-base/src/main/java/com/fr/design/gui/icontainer/UIModeControlContainer.java
  8. 12
      designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java
  9. 38
      designer-base/src/main/java/com/fr/design/locale/impl/BbsRegisterMark.java
  10. 38
      designer-base/src/main/java/com/fr/design/locale/impl/BbsResetMark.java
  11. 39
      designer-base/src/main/java/com/fr/design/locale/impl/BbsSpaceMark.java
  12. 22
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  13. 41
      designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java
  14. 15
      designer-base/src/main/java/com/fr/design/upm/UpmBridge.java
  15. 1
      designer-base/src/main/java/com/fr/file/FILEChooserPane.java
  16. 60
      designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java
  17. 97
      designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java
  18. 116
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java
  19. 221
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java
  20. 55
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java
  21. 64
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java
  22. 25
      designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java
  23. 25
      designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java
  24. 71
      designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java
  25. 22
      designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java
  26. 61
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java
  27. 223
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java
  28. 79
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java
  29. 204
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java
  30. 130
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java
  31. 70
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java
  32. 110
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java
  33. 86
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java
  34. 70
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java
  35. 72
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java
  36. 55
      designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java
  37. 79
      designer-base/src/main/java/com/fr/nx/app/designer/utils/DesignerCptxFileUtils.java
  38. 239
      designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java
  39. 85
      designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java
  40. 32
      designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java
  41. 27
      designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java
  42. 35
      designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java
  43. 124
      designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java
  44. 58
      designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java
  45. 2
      designer-chart/src/main/java/com/fr/van/chart/map/designer/style/series/VanChartMapAnchorMarkerPane.java
  46. 4
      designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java
  47. 3
      designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppActivator.java
  48. 12
      designer-realize/src/main/java/com/fr/design/mainframe/bbs/BBSLoginDialog.java
  49. 7
      designer-realize/src/main/java/com/fr/design/mainframe/bbs/UserInfoLabel.java
  50. 10
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandExtraAttrPane.java
  51. 53
      designer-realize/src/main/java/com/fr/nx/app/designer/CptxApp.java
  52. 117
      designer-realize/src/main/java/com/fr/nx/app/designer/JStreamBook.java
  53. 75
      designer-realize/src/main/java/com/fr/nx/app/designer/StartupAssist.java
  54. 109
      designer-realize/src/main/java/com/fr/nx/app/designer/cell/CellTreeAttrPanel.java
  55. 30
      designer-realize/src/main/java/com/fr/nx/app/designer/cell/CellTreeAttrPanelProvider.java
  56. 76
      designer-realize/src/main/java/com/fr/nx/app/designer/menu/CalculateAttrAction.java
  57. 200
      designer-realize/src/main/java/com/fr/nx/app/designer/menu/CalculateAttrPane.java
  58. 73
      designer-realize/src/main/java/com/fr/nx/app/designer/menu/FeatureFlagsPanel.java
  59. 36
      designer-realize/src/main/java/com/fr/nx/app/designer/menu/bean/FeatureFlagBean.java
  60. 2
      designer-realize/src/main/java/com/fr/poly/PolyBlockProperPane.java
  61. 19
      designer-realize/src/main/java/com/fr/poly/PolyBlockProperTable.java
  62. 2
      designer-realize/src/main/java/com/fr/start/MainDesigner.java
  63. 54
      designer-realize/src/test/java/com/fr/nx/app/designer/CptxAppTest.java
  64. 121
      designer-realize/src/test/java/com/fr/nx/app/designer/JStreamBookTest.java
  65. 79
      designer-realize/src/test/resources/cpt/read-write-expand-order.cpt
  66. 78
      designer-realize/src/test/resources/cpt/read-write-image-ref.cpt

1
build.gradle

@ -73,6 +73,7 @@ allprojects {
implementation 'com.fr.decision:fine-decision:' + frVersion
implementation 'com.fr.schedule:fine-schedule:' + frVersion
implementation 'com.fr.report:engine-report:' + frDevVersion
implementation 'com.fr.report:engine-x:' + frDevVersion
implementation 'com.fr.report:engine-chart:' + frDevVersion
implementation 'com.fr.report:engine-i18n:' + frDevVersion
implementation 'com.fr.design:design-i18n:' + frDevVersion

47
designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java

@ -0,0 +1,47 @@
package com.fr.design.actions.file;
import com.fr.base.BaseUtils;
import com.fr.design.actions.UpdateAction;
import com.fr.design.menu.MenuKeySet;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.transform.ui.BatchTransformPane;
import javax.swing.KeyStroke;
import java.awt.Dialog;
import java.awt.event.ActionEvent;
/**
* Created by kerry on 2019-12-10
*/
public class BatchCompileAction extends UpdateAction {
public BatchCompileAction() {
this.setMenuKeySet(COMPILE);
this.setName(getMenuKeySet().getMenuKeySetName() + "...");
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/batch_transform.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
BatchTransformPane batchTransformPane = new BatchTransformPane();
Dialog dialog = batchTransformPane.showDialog();
dialog.setVisible(true);
}
private static final MenuKeySet COMPILE = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'C';
}
@Override
public String getMenuName() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform");
}
@Override
public KeyStroke getKeyStroke() {
return null;
}
};
}

49
designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java

@ -0,0 +1,49 @@
package com.fr.design.actions.server;
import com.fr.base.BaseUtils;
import com.fr.design.actions.UpdateAction;
import com.fr.design.menu.MenuKeySet;
import com.fr.design.utils.DesignUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.web.URLConstants;
import com.fr.stable.StableUtils;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
/**
* @author Maksim
* Created in 2020/11/5 11:44 上午
*/
public class LocalAnalyzerAction extends UpdateAction {
public LocalAnalyzerAction() {
this.setMenuKeySet(ANALYZER);
this.setName(getMenuKeySet().getMenuKeySetName());
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/analyzer.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
String path = StableUtils.pathJoin("/url", URLConstants.ANALYZE_VIEW);
DesignUtils.visitEnvServerByParameters(path, new String[]{}, new String[]{});
}
private static final MenuKeySet ANALYZER = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'R';
}
@Override
public String getMenuName() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Analyzer_Menu_Name");
}
@Override
public KeyStroke getKeyStroke() {
return null;
}
};
}

18
designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java

@ -40,13 +40,17 @@ public abstract class EditLockChangeChecker {
try {
EditLockOperator operator = WorkContext.getCurrent().get(EditLockOperator.class);
boolean locked = operator.isLocked(lockItem);
if (isLocked != locked) {
isLocked = locked;
if (isLocked() != locked) {
setLocked(locked);
fireChange();
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
} else if (isLocked()){
// 如果不是远程环境,且此前的远程状态下为锁定的话,切换回来后需要将其修改为不锁定
setLocked(false);
fireChange();
}
}
}, 0, INTERVAL, TimeUnit.MILLISECONDS);
@ -65,9 +69,17 @@ public abstract class EditLockChangeChecker {
@Override
public void run() {
for (EditLockChangeListener listener : EditLockChangeChecker.this.listeners) {
listener.updateLockedState(new EditLockChangeEvent(isLocked));
listener.updateLockedState(new EditLockChangeEvent(isLocked()));
}
}
});
}
public boolean isLocked() {
return this.isLocked;
}
public void setLocked(boolean locked) {
this.isLocked = locked;
}
}

10
designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java

@ -6,8 +6,12 @@ import com.fr.config.MarketConfig;
import com.fr.design.dialog.UIDialog;
import com.fr.design.extra.exe.PluginLoginExecutor;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.locale.impl.BbsRegisterMark;
import com.fr.design.locale.impl.BbsResetMark;
import com.fr.general.CloudCenter;
import com.fr.general.http.HttpClient;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import javafx.concurrent.Task;
@ -118,7 +122,8 @@ public class LoginWebBridge {
*/
public void registerHref() {
try {
Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind("bbs.register")));
LocaleMark<String> registerMark = LocaleCenter.getMark(BbsRegisterMark.class);
Desktop.getDesktop().browse(new URI(registerMark.getValue()));
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
@ -129,7 +134,8 @@ public class LoginWebBridge {
*/
public void forgetHref() {
try {
Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind("bbs.reset")));
LocaleMark<String> resetMark = LocaleCenter.getMark(BbsResetMark.class);
Desktop.getDesktop().browse(new URI(resetMark.getValue()));
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}

15
designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java

@ -13,8 +13,13 @@ import com.fr.design.extra.exe.PluginLoginExecutor;
import com.fr.design.extra.exe.ReadUpdateOnlineExecutor;
import com.fr.design.extra.exe.SearchOnlineExecutor;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.locale.impl.BbsRegisterMark;
import com.fr.design.locale.impl.BbsResetMark;
import com.fr.design.locale.impl.BbsSpaceMark;
import com.fr.design.utils.concurrent.ThreadFactoryBuilder;
import com.fr.general.CloudCenter;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginMarker;
@ -434,8 +439,8 @@ public class PluginWebBridge {
*/
public void getPriviteMessage() {
try {
String loginUrl = CloudCenter.getInstance().acquireUrlByKind("bbs.default");
Desktop.getDesktop().browse(new URI(loginUrl));
LocaleMark<String> spaceMark = LocaleCenter.getMark(BbsSpaceMark.class);
Desktop.getDesktop().browse(new URI(spaceMark.getValue()));
} catch (Exception exp) {
FineLoggerFactory.getLogger().info(exp.getMessage());
}
@ -497,7 +502,8 @@ public class PluginWebBridge {
*/
public void registerHref() {
try {
Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind("bbs.register")));
LocaleMark<String> registerMark = LocaleCenter.getMark(BbsRegisterMark.class);
Desktop.getDesktop().browse(new URI(registerMark.getValue()));
} catch (Exception e) {
FineLoggerFactory.getLogger().info(e.getMessage());
}
@ -511,7 +517,8 @@ public class PluginWebBridge {
*/
public void forgetHref() {
try {
Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind("bbs.reset")));
LocaleMark<String> resetMark = LocaleCenter.getMark(BbsResetMark.class);
Desktop.getDesktop().browse(new URI(resetMark.getValue()));
} catch (Exception e) {
FineLoggerFactory.getLogger().info(e.getMessage());
}

2
designer-base/src/main/java/com/fr/design/gui/icontainer/UIModeControlContainer.java

@ -166,10 +166,10 @@ public class UIModeControlContainer extends JLayeredPane {
}
// 拖动的距离,为正值表示往下拖动,为负值表示往上拖动
int deltaY = e.getY();
toolPaneY += deltaY;
if (toolPaneY < 0) {
toolPaneY = 0;
}
toolPaneY += deltaY;
onResize(toolPaneY);
refreshContainer();
}

12
designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java

@ -48,6 +48,9 @@ public class FileTreeIcon {
public static final Icon MODERN_CHT_FILE_IMAGE_ICON =
BaseUtils.readIcon("/com/fr/design/images/gui/modern_style_cht_file_icon_16x16.png");
public static final Icon CPTX_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/cptx_file_icon.png");
public static final Icon CPTX_LOCKED_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/cptx_file_icon_locked.png");
public static final LockIcon FOLDER_LOCK_ICON =
new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/fold.png"));
public static final LockIcon FILE_LOCK_ICON =
@ -108,6 +111,7 @@ public class FileTreeIcon {
public final static int CPT_FILE = 11; //.cpt
public final static int FRM_FILE = 12; //.form .frm
public final static int CHT_FILE = 13; //.chart .cht
public final static int CPTX_FILE = 14; //.cptx
public static Icon getIcon(File file) {
return FileTreeIcon.getIcon(file, false);
@ -252,6 +256,12 @@ public class FileTreeIcon {
} else {
return FileTreeIcon.MODERN_CPT_FILE_IMAGE_ICON;
}
} else if (fileType == CPTX_FILE) {
if (isLocked) {
return FileTreeIcon.CPTX_LOCKED_ICON;
} else {
return FileTreeIcon.CPTX_ICON;
}
} else if (fileType == FRM_FILE) { //form frm
if (isLocked) {
return FileTreeIcon.FRM_FILE_LOCK_ICON;
@ -314,6 +324,8 @@ public class FileTreeIcon {
return BMP_FILE;
} else if (fileName.endsWith(".cpt")) {
return CPT_FILE;
} else if (fileName.endsWith(".cptx")) {
return CPTX_FILE;
} else if (fileName.endsWith(".frm") || fileName.endsWith(".form")) {
return FRM_FILE;
} else if (fileName.endsWith(".cht") || fileName.endsWith(".chart")) {

38
designer-base/src/main/java/com/fr/design/locale/impl/BbsRegisterMark.java

@ -0,0 +1,38 @@
package com.fr.design.locale.impl;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralContext;
import com.fr.general.locale.LocaleMark;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/1/29
*/
public class BbsRegisterMark implements LocaleMark<String> {
private final Map<Locale, String> map = new HashMap<>();
private static final String BBS_REGISTER_CN = CloudCenter.getInstance().acquireUrlByKind("bbs.register");
private static final String BBS_REGISTER_TW = CloudCenter.getInstance().acquireUrlByKind("bbs.register");
private static final String BBS_REGISTER_EN = CloudCenter.getInstance().acquireUrlByKind("bbs.register.en_US");
private static final String BBS_REGISTER_KR = CloudCenter.getInstance().acquireUrlByKind("bbs.register.en_US");
private static final String BBS_REGISTER_JP = CloudCenter.getInstance().acquireUrlByKind("bbs.register.en_US");
public BbsRegisterMark() {
map.put(Locale.CHINA, BBS_REGISTER_CN);
map.put(Locale.KOREA, BBS_REGISTER_KR);
map.put(Locale.JAPAN, BBS_REGISTER_JP);
map.put(Locale.US, BBS_REGISTER_EN);
map.put(Locale.TAIWAN, BBS_REGISTER_TW);
}
@Override
public String getValue() {
String result = map.get(GeneralContext.getLocale());
return result == null ? BBS_REGISTER_EN : result;
}
}

38
designer-base/src/main/java/com/fr/design/locale/impl/BbsResetMark.java

@ -0,0 +1,38 @@
package com.fr.design.locale.impl;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralContext;
import com.fr.general.locale.LocaleMark;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/1/29
*/
public class BbsResetMark implements LocaleMark<String> {
private final Map<Locale, String> map = new HashMap<>();
private static final String BBS_RESET_CN = CloudCenter.getInstance().acquireUrlByKind("bbs.reset");
private static final String BBS_RESET_TW = CloudCenter.getInstance().acquireUrlByKind("bbs.reset");
private static final String BBS_RESET_EN = CloudCenter.getInstance().acquireUrlByKind("bbs.reset.en_US");
private static final String BBS_RESET_KR = CloudCenter.getInstance().acquireUrlByKind("bbs.reset.en_US");
private static final String BBS_RESET_JP = CloudCenter.getInstance().acquireUrlByKind("bbs.reset.en_US");
public BbsResetMark() {
map.put(Locale.CHINA, BBS_RESET_CN);
map.put(Locale.KOREA, BBS_RESET_KR);
map.put(Locale.JAPAN, BBS_RESET_JP);
map.put(Locale.US, BBS_RESET_EN);
map.put(Locale.TAIWAN, BBS_RESET_TW);
}
@Override
public String getValue() {
String result = map.get(GeneralContext.getLocale());
return result == null ? BBS_RESET_EN : result;
}
}

39
designer-base/src/main/java/com/fr/design/locale/impl/BbsSpaceMark.java

@ -0,0 +1,39 @@
package com.fr.design.locale.impl;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralContext;
import com.fr.general.locale.LocaleMark;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/1/29
*/
public class BbsSpaceMark implements LocaleMark<String> {
private final Map<Locale, String> map = new HashMap<>();
private static final String BBS_SPACE_CN = CloudCenter.getInstance().acquireUrlByKind("bbs.default");
private static final String BBS_SPACE_TW = CloudCenter.getInstance().acquireUrlByKind("bbs.default");
private static final String BBS_SPACE_EN = CloudCenter.getInstance().acquireUrlByKind("bbs.default.en_US");
private static final String BBS_SPACE_KR = CloudCenter.getInstance().acquireUrlByKind("bbs.default.en_US");
private static final String BBS_SPACE_JP = CloudCenter.getInstance().acquireUrlByKind("bbs.default.en_US");
public BbsSpaceMark() {
map.put(Locale.CHINA, BBS_SPACE_CN);
map.put(Locale.KOREA, BBS_SPACE_KR);
map.put(Locale.JAPAN, BBS_SPACE_JP);
map.put(Locale.US, BBS_SPACE_EN);
map.put(Locale.TAIWAN, BBS_SPACE_TW);
}
@Override
public String getValue() {
String result = map.get(GeneralContext.getLocale());
return result == null ? BBS_SPACE_EN : result;
}
}

22
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -3,6 +3,7 @@ package com.fr.design.mainframe;
import com.fr.base.BaseUtils;
import com.fr.base.FRContext;
import com.fr.base.Parameter;
import com.fr.base.extension.FileExtension;
import com.fr.base.io.BaseBook;
import com.fr.base.iofile.attr.DesignBanCopyAttrMark;
import com.fr.base.iofile.attr.TemplateIdAttrMark;
@ -14,6 +15,7 @@ import com.fr.design.ExtraDesignClassManager;
import com.fr.design.actions.TableDataSourceAction;
import com.fr.design.actions.edit.RedoAction;
import com.fr.design.actions.edit.UndoAction;
import com.fr.design.actions.file.BatchCompileAction;
import com.fr.design.actions.file.SaveAsTemplateAction;
import com.fr.design.actions.file.SaveTemplateAction;
import com.fr.design.actions.file.WebPreviewUtils;
@ -60,6 +62,8 @@ import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.context.PluginRuntime;
import com.fr.nx.app.designer.toolbar.CompileAction;
import com.fr.nx.app.designer.toolbar.TemplateTransformer;
import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.manage.PluginFilter;
import com.fr.plugin.observer.PluginEvent;
@ -781,10 +785,12 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
protected boolean saveToNewFile(String oldName) {
boolean result = false;
String path = this.editingFILE.getPath();
Set<ReportSupportedFileUIProvider> providers = ExtraDesignClassManager.getInstance().getArray(ReportSupportedFileUIProvider.XML_TAG);
for (ReportSupportedFileUIProvider provider : providers) {
result = result || provider.saveToNewFile(this.editingFILE.getPath(), this);
result = result || provider.saveToNewFile(path, this);
}
result = result || saveToNewFile4Cptx(path);
if (!result) {
result = result || this.saveFile();
//更换最近打开
@ -794,6 +800,14 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
return result;
}
private boolean saveToNewFile4Cptx(String targetPath) {
if (FileExtension.CPTX.matchExtension(targetPath)) {
TemplateTransformer.TO_CPTX.transform(this);
return true;
}
return false;
}
protected void mkNewFile(FILE file) {
try {
file.mkfile();
@ -887,7 +901,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
} else if (DesignerMode.isAuthorityEditing()) {
return new ShortCut[]{new SaveTemplateAction(this), new UndoAction(this), new RedoAction(this)};
} else {
return new ShortCut[]{new SaveTemplateAction(this), new SaveAsTemplateAction(this), new UndoAction(this), new RedoAction(this)};
return new ShortCut[]{new SaveTemplateAction(this), new SaveAsTemplateAction(this), new BatchCompileAction(), new UndoAction(this), new RedoAction(this)};
}
}
@ -1323,8 +1337,10 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
* @return 按钮组
*/
public UIButton[] createExtraButtons() {
UIButton[] uiButtons = new UIButton[] {
(UIButton) new CompileAction().createToolBarComponent()
};
Set<DesignerFrameUpButtonProvider> providers = ExtraDesignClassManager.getInstance().getArray(DesignerFrameUpButtonProvider.XML_TAG);
UIButton[] uiButtons = new UIButton[0];
for (DesignerFrameUpButtonProvider provider : providers) {
uiButtons = ArrayUtils.addAll(uiButtons, provider.getUpButtons(getMenuState()));
}

41
designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java

@ -0,0 +1,41 @@
package com.fr.design.preview;
import com.fr.design.fun.impl.AbstractPreviewProvider;
import com.fr.general.web.ParameterConstants;
import com.fr.locale.InterProviderFactory;
import java.util.HashMap;
import java.util.Map;
import static com.fr.nx.app.web.v9.PagePlusActor.TYPE;
public class PagePlusPreview extends AbstractPreviewProvider {
private static final int CODE = 100;
@Override
public String nameForPopupItem() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Page-Plus");
}
@Override
public String iconPathForPopupItem() {
return "com/fr/design/images/buttonicon/pages.png";
}
@Override
public String iconPathForLarge() {
return "com/fr/design/images/buttonicon/pageb24.png";
}
@Override
public int previewTypeCode() {
return CODE;
}
@Override
public Map<String, Object> parametersForPreview() {
Map<String, Object> map = new HashMap<String, Object>();
map.put(ParameterConstants.OP, TYPE);
return map;
}
}

15
designer-base/src/main/java/com/fr/design/upm/UpmBridge.java

@ -16,6 +16,9 @@ import com.fr.design.extra.exe.PluginLoginExecutor;
import com.fr.design.extra.exe.ReadUpdateOnlineExecutor;
import com.fr.design.extra.exe.SearchOnlineExecutor;
import com.fr.design.i18n.Toolkit;
import com.fr.design.locale.impl.BbsRegisterMark;
import com.fr.design.locale.impl.BbsResetMark;
import com.fr.design.locale.impl.BbsSpaceMark;
import com.fr.design.upm.event.CertificateEvent;
import com.fr.design.upm.event.DownloadEvent;
import com.fr.design.upm.exec.UpmBrowserExecutor;
@ -23,6 +26,8 @@ import com.fr.design.upm.task.UpmTaskWorker;
import com.fr.event.EventDispatcher;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralUtils;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginMarker;
@ -424,8 +429,8 @@ public class UpmBridge {
@JSBridge
public void getPriviteMessage() {
try {
String loginUrl = CloudCenter.getInstance().acquireUrlByKind("bbs.default");
Desktop.getDesktop().browse(new URI(loginUrl));
LocaleMark<String> spaceMark = LocaleCenter.getMark(BbsSpaceMark.class);
Desktop.getDesktop().browse(new URI(spaceMark.getValue()));
} catch (Exception exp) {
FineLoggerFactory.getLogger().info(exp.getMessage());
}
@ -437,7 +442,8 @@ public class UpmBridge {
@JSBridge
public void forgetHref() {
try {
Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind("bbs.reset")));
LocaleMark<String> resetMark = LocaleCenter.getMark(BbsResetMark.class);
Desktop.getDesktop().browse(new URI(resetMark.getValue()));
} catch (Exception e) {
FineLoggerFactory.getLogger().info(e.getMessage());
}
@ -449,7 +455,8 @@ public class UpmBridge {
@JSBridge
public void registerHref() {
try {
Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind("bbs.register")));
LocaleMark<String> registerMark = LocaleCenter.getMark(BbsRegisterMark.class);
Desktop.getDesktop().browse(new URI(registerMark.getValue()));
} catch (Exception e) {
FineLoggerFactory.getLogger().info(e.getMessage());
}

1
designer-base/src/main/java/com/fr/file/FILEChooserPane.java

@ -770,6 +770,7 @@ public class FILEChooserPane extends BasicPane {
// ben:filefilter设置初值为cpt过滤
this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPT, appName + Toolkit.i18nText("Fine-Design_Report_Template_File")));
this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPTX, appName + Toolkit.i18nText("Fine-Design_Report_Template_File")));
// richer:form文件 daniel 改成三个字
this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.FRM, appName + Toolkit.i18nText("Fine-Design_Report_Template_File")));

60
designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java

@ -0,0 +1,60 @@
package com.fr.nx.app.designer.cptx.io;
import com.fr.common.annotations.Negative;
import com.fr.file.FILE;
import com.fr.nx.app.designer.utils.DesignerCptxFileUtils;
import com.fr.nx.cptx.io.handle.impl.AbstractCptxIOProvider;
import com.fr.nx.cptx.pack.util.CompiledReportInputStream;
import com.fr.nx.cptx.pack.util.CompiledReportOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 用于设计器保存编译后的结果并缓存可web预览模版
* 没有可观的内存实现内存实现方式复杂赶发布先提供简单的内存实现方式
*
* @author: Maksim
* @Date: Created in 2020/4/10
* @Description: 用于cptx写操作的Provider
*/
@Negative(until = "2020-05-10")
public class DesignReadWritableProvider extends AbstractCptxIOProvider {
/**
* 原文件
*/
private final FILE file;
/**
* 编译文件夹
*/
private final String compileDir;
private CompiledReportOutputStream outputStream;
public DesignReadWritableProvider(FILE file) {
this.file = file;
this.compileDir = DesignerCptxFileUtils.generateCompileDir(file);
}
@Override
public InputStream open() throws Exception {
if (outputStream == null) {
throw new IOException("can not read cptx template before compile");
}
return new CompiledReportInputStream(outputStream.toByteArray());
}
/**
* 对于写操作用到的只有这个方法以流形式来操作
*
* @return 保存的目标输出流
* @throws Exception e
*/
@Override
public OutputStream createTemp() throws Exception {
outputStream = new CompiledReportOutputStream(file.asOutputStream(), compileDir);
return outputStream;
}
}

97
designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java

@ -0,0 +1,97 @@
package com.fr.nx.app.designer.monitor;
import com.fr.design.mainframe.errorinfo.ErrorInfo;
import com.fr.intelli.record.MetricRegistry;
import com.fr.json.JSON;
import com.fr.json.JSONFactory;
import com.fr.json.JSONObject;
import com.fr.message.ErrorMessage;
import com.fr.nx.app.designer.toolbar.TransformResult;
/**
* Created by loy on 2021/1/18.
*
* <p>设计器埋点记录相关
*/
public class DesignerMetricRecorder {
private static final String ATTR_TEMPLATE_ID = "templateid";
private static final String ATTR_USERNAME = "username";
private static final String ATTR_UUID = "uuid";
private static final String ATTR_ACTIVE_KEY = "activekey";
private static final String ATTR_TEST_LOG = "testlog";
private static final String ATTR_REPORT_CONTENT = "reportcontent";
private static final String ATTR_ERROR_STACK = "errorstack";
private static final String IDENTIFICATION = "view_plus";
private DesignerMetricRecorder() {
}
/**
* 模板转换失败的埋点
*/
public static void submitFailedTransform(TransformResult result, String templateID, String name, Exception e) {
if (isPressureTesting()) {
return;
}
saveAsJSON(result, templateID, name, e);
}
/**
* 记录在设计器的错误信息收集中
*/
private static void saveToErrorInfo(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) {
JSONObject jo = JSONFactory.createJSON(JSON.OBJECT);
jo.put(ATTR_USERNAME, IDENTIFICATION);
jo.put(ATTR_UUID, IDENTIFICATION);
jo.put(ATTR_ACTIVE_KEY, IDENTIFICATION);
jo.put(ATTR_TEMPLATE_ID, templateID);
jo.put(ATTR_REPORT_CONTENT, name);
if (result == TransformResult.FAILED) {
jo.put(ATTR_TEST_LOG, e);
jo.put(ATTR_ERROR_STACK, e.getMessage());
} else {
jo.put(ATTR_TEST_LOG, unsupportMessage);
}
new ErrorInfo().saveFileToCache(jo);
}
/**
* 记录在fine_record_error表中
*/
private static void saveToErrorMessage(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) {
String errorMessage = unsupportMessage;
if (result == TransformResult.FAILED) {
errorMessage = e.getStackTrace()[0].toString();
}
ErrorMessage message = ErrorMessage.build(e == null ? errorMessage : e.getMessage(), errorMessage);
message.setTname(name);
message.setDisplayName(name);
MetricRegistry.getMetric().submit(message);
}
private static void saveAsJSON(TransformResult result, String templateID, String name, Exception e) {
saveToErrorInfo(result, templateID, name, e, null);
saveToErrorMessage(result, templateID, name, e, null);
}
/**
* 预编译中不支持的功能的埋点
*/
public static void submitUnSupportTransform(TransformResult result, String templateID, String name, String unsupportMessage) {
if (isPressureTesting()) {
return;
}
saveToErrorInfo(result, templateID, name, null, unsupportMessage);
saveToErrorMessage(result, templateID, name, null, unsupportMessage);
}
/**
* 埋点对压测性能的影响控制参数
*
* @return 是否压测
*/
public static boolean isPressureTesting() {
return Boolean.parseBoolean(System.getProperty("monitorDebug"));
}
}

116
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java

@ -0,0 +1,116 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.base.extension.FileExtension;
import com.fr.design.actions.UpdateAction;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.menu.MenuKeySet;
import com.fr.file.FILE;
import com.fr.file.FileNodeFILE;
import com.fr.general.IOUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.utils.CompileTransformUtil;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog;
import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER;
import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
import static javax.swing.JOptionPane.OK_OPTION;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
/**
* Created by kerry on 2019-10-14
*/
public class CompileAction extends UpdateAction {
public static final Icon TRANS_ICON = IOUtils.readIcon("/com/fr/nx/app/designer/transform.png");
private static final MenuKeySet COMPILE_ATTR = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'C';
}
@Override
public String getMenuName() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip");
}
@Override
public KeyStroke getKeyStroke() {
return KeyStroke.getKeyStroke(KeyEvent.VK_T, DEFAULT_MODIFIER);
}
};
public CompileAction() {
initMenuStyle();
}
private void initMenuStyle() {
this.setMenuKeySet(COMPILE_ATTR);
this.setName(getMenuKeySet().getMenuKeySetName());
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(TRANS_ICON);
this.setAccelerator(getMenuKeySet().getKeyStroke());
}
@Override
public void actionPerformed(ActionEvent e) {
JTemplate jtemplate = DesignerContext.getDesignerFrame().getSelectedJTemplate();
if (jtemplate == null || jtemplate.getEditingFILE() == null) {
return;
}
FILE currentTemplate = jtemplate.getEditingFILE();
if(currentTemplate instanceof FileNodeFILE){
transformAndDisplay(jtemplate);
}else {
//模板不在报表环境下,提示保存
int selVal = showConfirmDialog(
DesignerContext.getDesignerFrame(),
InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Preview_Message"),
InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Transformer_Tips"),
OK_CANCEL_OPTION,
WARNING_MESSAGE);
if (OK_OPTION == selVal) {
//保存成功才会执行编译
if (jtemplate.saveAsTemplate2Env()) {
transformAndDisplay(jtemplate);
}
}
}
}
//编译模板并展示
private void transformAndDisplay(JTemplate jtemplate){
String path = jtemplate.getEditingFILE().getPath();
TemplateTransformer transformer = TemplateTransformer.parse(path);
FILE targetFile = CompileTransformUtil.getTargetFile(jtemplate, transformer);
TransformResult result = transformer.transform(jtemplate, targetFile);
jtemplate.fireJTemplateSaved();
result.display();
}
@Override
public boolean isEnabled() {
JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
String path = jt.getEditingFILE().getPath();
return FileExtension.CPTX.matchExtension(path) || FileExtension.CPT.matchExtension(path);
}
@Override
public JComponent createToolBarComponent() {
UIButton transBtn = (UIButton) super.createToolBarComponent();
transBtn.set4ToolbarButton();
transBtn.setToolTipText(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip"));
return transBtn;
}
}

221
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java

@ -0,0 +1,221 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.base.extension.FileExtension;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.MutilTempalteTabPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.file.FILE;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.monitor.DesignerMetricRecorder;
import com.fr.nx.compile.CompileStatus;
import com.fr.nx.compile.ReportCompiler;
import com.fr.nx.compile.adapter.LegacyWorkBookAdapter;
import com.fr.nx.compile.util.ReportCompileUtils;
import com.fr.nx.cptx.CptxIOManager;
import com.fr.nx.cptx.cache.CptxTemplatePool;
import com.fr.nx.cptx.entry.CptxTemplate;
import com.fr.nx.cptx.io.handle.CptxTemplateHandle;
import com.fr.nx.app.designer.cptx.io.DesignReadWritableProvider;
import com.fr.nx.cptx.monitor.CompileMonitorHandler;
import com.fr.nx.cptx.utils.CptxFileUtils;
import com.fr.nx.data.layer.LayerItem;
import com.fr.nx.data.layer.LayerProps;
import com.fr.nx.template.compile.CompiledReport;
import com.fr.stable.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.io.OutputStream;
import static com.fr.base.extension.FileExtension.ALL;
import static com.fr.base.extension.FileExtension.CPT;
import static com.fr.base.extension.FileExtension.CPTX;
/**
* 模板转换器, 可以把cptx模板转为cpt, 或者cpt模板转为cptx.
* 以后可以扩展支持frm frmx互相转换
*/
public enum TemplateTransformer {
TO_CPTX(CPT) {
@Override
public TransformResult transform(JTemplate jtemplate, FILE file) {
WorkBook workbook = (WorkBook) jtemplate.getTarget();
TransformResultInfo resultInfo = compileCPTX(workbook, file);
if (needDoAfterTransformed(resultInfo.getResult())) {
doAfterTransformed(file, jtemplate);
}
return resultInfo.getResult();
}
},
TO_CPT(CPTX) {
@Override
public TransformResult transform(JTemplate jtemplate, FILE file) {
WorkBook workbook = (WorkBook) jtemplate.getTarget();
try {
workbook.export(file.asOutputStream());
doAfterTransformed(file, jtemplate);
return TransformResult.SUCCESS;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return TransformResult.FAILED;
}
}
},
OTHER(ALL);
private FileExtension extension;
TemplateTransformer(FileExtension extension) {
this.extension = extension;
}
public TransformResult transform(JTemplate jtemplate) {
return transform(jtemplate, jtemplate.getEditingFILE());
}
public TransformResult transform(JTemplate jtemplate, FILE newFile) {
return TransformResult.UNSUPPORT;
}
public static TemplateTransformer parse(String path) {
for (TemplateTransformer transformer : values()) {
if (transformer.extension.matchExtension(path)) {
return transformer;
}
}
return OTHER;
}
private static boolean needDoAfterTransformed(TransformResult result) {
return ComparatorUtils.equals(TransformResult.SUCCESS, result)
|| ComparatorUtils.equals(TransformResult.UNSUPPORT, result);
}
private static void doAfterTransformed(FILE file, JTemplate jtemplate) {
JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (ComparatorUtils.equals(file.getPath(), jt.getPath())) {
HistoryTemplateListCache.getInstance().closeSelectedReport(jt);
DesignerContext.getDesignerFrame().openTemplate(file);
return;
}
MutilTempalteTabPane.getInstance().setIsCloseCurrent(true);
MutilTempalteTabPane.getInstance().closeFormat(jt);
MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(jt);
DesignerContext.getDesignerFrame().openTemplate(file);
}
public static FILE createOutputFile(String oldPath, String oldSuffix, String newSuffix) {
String newPath = generateNewPath(oldPath, oldSuffix, newSuffix);
return new FileNodeFILE(new FileNode(newPath, false));
}
private static String generateNewPath(String oldPath, String oldSuffix, String newSuffix) {
if (StringUtils.isEmpty(oldPath) || StringUtils.isEmpty(oldSuffix) || StringUtils.isEmpty(newSuffix)) {
return oldPath;
}
if (oldPath.endsWith(oldSuffix)) {
return StringUtils.cutStringEndWith(oldPath, oldSuffix) + newSuffix;
}
return oldPath;
}
/**
* 编译和保存
*
* @param workbook work
* @param file file
* @return 编译保存结果
*/
@NotNull
public static TransformResultInfo compileCPTX(WorkBook workbook, FILE file) {
//对于非工作目录的cptx,修改无需执行编译
if(!(file instanceof FileNodeFILE)){
try {
OutputStream outputStream = file.asOutputStream();
workbook.export(outputStream);
return TransformResultInfo.generateResult(TransformResult.SUCCESS).saved(true);
}catch (Exception e){
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return TransformResultInfo.generateResult(TransformResult.FAILED).saved(false);
}
}
boolean saved;
CompiledReport report = null;
CompileStatus compileStatus = CompileStatus.SUCCEED;
if (workbook == null || file == null) {
return TransformResultInfo
.generateResult(TransformResult.FAILED, "work and file must not be null")
.saved(false);
}
String failMessage = null;
// 编译
ReportCompiler compiler;
try {
compiler = new ReportCompiler(new LegacyWorkBookAdapter(workbook));
long startTime = System.currentTimeMillis();
compiler.compile();
report = compiler.getCompiledReport();
// 折叠树埋点
LayerProps props = ReportCompileUtils.getLayerProps(report);
LayerItem[] items;
if (props != null && (items = props.getLayerItems()) != null) {
CompileMonitorHandler.submitTreeCompileFocusPoint(
startTime, file.getPath(), items.length,
props.getExpandLayer(), true
);
}
compileStatus = compiler.getStatus();
failMessage = compiler.getFailMessage();
long endTime = System.currentTimeMillis();
CompileMonitorHandler.submitCompileMessage(startTime, endTime, file.getPath(), "");
if (compileStatus != CompileStatus.SUCCEED) {
DesignerMetricRecorder.submitUnSupportTransform(
TransformResult.UNSUPPORT,
workbook.getTemplateID(),
file.getName(),
compileStatus == CompileStatus.FAILED_UNSUPPORT ? failMessage : null
);
}
} catch (Exception exception) {
String templateID = workbook.getTemplateID();
String fileName = file.getName();
DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, templateID, fileName, exception);
FineLoggerFactory.getLogger().error(exception.getMessage(), exception);
}
// 构建编译结果,当前的 cptx template 是未经反序列化钩子处理过的 cptx 模版对象,不能直接用于模版预览
CptxTemplate template = CptxIOManager.createCptxTemplate(workbook, report, compileStatus, failMessage);
// 保存
DesignReadWritableProvider cptx = new DesignReadWritableProvider(file);
CptxTemplateHandle handle = CptxIOManager.create(template, cptx);
try {
saved = handle.save();
} catch (Exception exception) {
// 存储cptx格式报错或者失败
FineLoggerFactory.getLogger().error(exception.getMessage(), exception);
DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, workbook.getTemplateID(), file.getName(), exception);
return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(false);
}
// 读取可 web 预览模版并缓存
try {
// todo 是否考虑异步
String timestampedPath = CptxFileUtils.getTimestampedPath(file.getPath());
CptxTemplate previewCptxTemplate = CptxIOManager.open(cptx).getTemplate();
CptxTemplatePool.getInstance().addCptxTemplate(timestampedPath, previewCptxTemplate);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (report == null) {
// 编译报错或者失败
return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(saved);
}
return TransformResultInfo.generateResult(TransformResult.parse(compileStatus), failMessage).saved(saved);
}
}

55
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java

@ -0,0 +1,55 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.design.file.TemplateTreePane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.compile.CompileStatus;
import javax.swing.JOptionPane;
public enum TransformResult {
SUCCESS(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Success")) {
@Override
public void display() {
// 转换成功后, 刷新下目录树
TemplateTreePane.getInstance().refresh();
super.display();
}
},
FAILED(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Failed")),
UNSUPPORT(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Unsupport")){
@Override
public void display() {
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), TransformResult.SUCCESS.toString());
}
};
private String msg;
private TransformResult(String msg) {
this.msg = msg;
}
// 展示结果
public void display() {
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), this.toString());
}
@Override
public String toString() {
return this.msg;
}
public static TransformResult parse(CompileStatus status) {
switch (status) {
case SUCCEED:
return TransformResult.SUCCESS;
case FAILED_UNSUPPORT:
return TransformResult.UNSUPPORT;
default:
return TransformResult.FAILED;
}
}
}

64
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java

@ -0,0 +1,64 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.locale.InterProviderFactory;
import com.fr.stable.StringUtils;
/**
* Created by kerry on 2020-01-15
*/
public class TransformResultInfo {
private boolean saved;
private TransformResult result;
private final String transformLog;
public static TransformResultInfo generateResult(TransformResult result, String transformLog) {
return new TransformResultInfo(result, transformLog);
}
public static TransformResultInfo generateResult(TransformResult result) {
return new TransformResultInfo(result, StringUtils.EMPTY);
}
private TransformResultInfo(TransformResult result, String transformLog) {
this.result = result;
this.transformLog = transformLog;
this.saved = false;
}
public boolean isSaved() {
return saved;
}
public void setSaved(boolean saved) {
this.saved = saved;
}
public TransformResultInfo saved(boolean saved) {
setSaved(saved);
return this;
}
public TransformResult getResult() {
return result;
}
public void setResult(TransformResult result) {
this.result = result;
}
public String getTransformLog() {
switch (this.result) {
case FAILED:
return transformLog + "\n"
+ InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip");
case SUCCESS:
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip");
case UNSUPPORT:
return transformLog + "\n"
+ InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip");
}
return transformLog;
}
}

25
designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java

@ -0,0 +1,25 @@
package com.fr.nx.app.designer.transform;
/**
* Created by kerry on 2019-12-10
*/
public class BatchTransformProgress {
private double progress = 0.0D;
private int total = 0;
private int complete = 0;
public BatchTransformProgress(int total) {
this.total = total;
}
public double getProgress() {
return this.progress;
}
public void updateProgress() {
this.complete++;
this.progress = this.complete * 1D / this.total;
}
}

25
designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java

@ -0,0 +1,25 @@
package com.fr.nx.app.designer.transform;
import com.fr.file.filetree.FileNode;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2020-02-14
*/
public class BatchTransformUtil {
private BatchTransformUtil() {
}
public static FileNode[] filterTransformedFile(FileNode[] fileNodes, List<FileNode> transformedList){
List<FileNode> list = new ArrayList<FileNode>();
for (FileNode fileNode : fileNodes) {
if (!transformedList.contains(fileNode)) {
list.add(fileNode);
}
}
return list.toArray(new FileNode[list.size()]);
}
}

71
designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java

@ -0,0 +1,71 @@
package com.fr.nx.app.designer.transform;
import com.fr.design.utils.concurrent.ThreadFactoryBuilder;
import com.fr.file.filetree.FileNode;
import com.fr.plugin.context.PluginContexts;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import com.fr.nx.app.designer.utils.CompileTransformUtil;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
/**
* Created by kerry on 2019-12-10
*/
public class BatchTransformer {
private BatchTransformProgress progress = new BatchTransformProgress(0);
private Map<FileNode, TransformResultInfo> transformResults = new ConcurrentHashMap<FileNode, TransformResultInfo>();
private UpdateCallBack updateCallBack;
private static final int MAXPOOLSIZE = 5;
private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s";
private ExecutorService threadPoolExecutor =
PluginContexts.currentContext().newFixedThreadPool(MAXPOOLSIZE,
new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build());
public BatchTransformer(UpdateCallBack updateCallBack) {
this.updateCallBack = updateCallBack;
}
public void batchTransform(List<FileNode> fileNodes) {
//先清理下
transformResults.clear();
progress = new BatchTransformProgress(fileNodes.size());
for (FileNode fileNode : fileNodes) {
transform(fileNode);
}
}
private void transform(final FileNode fileNode) {
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
TransformResultInfo transformResult = CompileTransformUtil.compileFile(fileNode);
transformResults.put(fileNode, transformResult);
updateTransformProgress();
}
});
}
private synchronized void updateTransformProgress() {
progress.updateProgress();
updateCallBack.updateProgress(progress.getProgress());
}
public void shutDown() {
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdownNow();
}
threadPoolExecutor = PluginContexts.currentContext().newFixedThreadPool(MAXPOOLSIZE,
new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build());
updateCallBack.shutDown();
}
public Map<FileNode, TransformResultInfo> getResults() {
return transformResults;
}
}

22
designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java

@ -0,0 +1,22 @@
package com.fr.nx.app.designer.transform;
/**
* Created by kerry on 2019-12-10
*/
public interface UpdateCallBack {
/**
* 更新进度
* @param progress 进度
*/
void updateProgress(double progress);
/**
* 进度中断
*/
void shutDown();
/**
* 进度重置
*/
void reset();
}

61
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java

@ -0,0 +1,61 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.locale.InterProviderFactory;
import javax.swing.JDialog;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* Created by kerry on 2019-12-19
*/
public class BatchTransformDialog extends JDialog implements ActionListener {
private UIButton closeBtn;
public BatchTransformDialog(Frame parent, JPanel contentPane) {
super(parent, true);
this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"));
this.setResizable(false);
JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane();
this.setContentPane(defaultPane);
closeBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Close"));
closeBtn.addActionListener(this);
JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
buttonPanel.add(closeBtn);
defaultPane.add(contentPane, BorderLayout.CENTER);
defaultPane.add(buttonPanel, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dialogExit();
}
});
this.getRootPane().setDefaultButton(closeBtn);
this.setSize(new Dimension(900, 600));
GUICoreUtils.centerWindow(this);
}
@Override
public void actionPerformed(ActionEvent e) {
dialogExit();
}
private void dialogExit() {
this.dispose();
}
}

223
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java

@ -0,0 +1,223 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.extension.FileExtension;
import com.fr.design.dialog.BasicPane;
import com.fr.design.file.NodeAuthProcessor;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.itree.filetree.FileNodeComparator;
import com.fr.design.gui.itree.filetree.FileNodeConstants;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.file.filetree.FileNode;
import com.fr.file.filetree.IOFileNodeFilter;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.tree.DefaultTreeModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Created by kerry on 2019-12-10
*/
public class BatchTransformPane extends BasicPane {
private UITextField searchField;
private TransformFileTree tree;
private Dialog showDialog;
private TransformPreparePane preparePane;
private TransformResultPane resultPane;
public BatchTransformPane() {
DesignerFrame designerFrame = DesignerContext.getDesignerFrame();
this.showDialog = new BatchTransformDialog(designerFrame, this);
initPane();
}
private void initPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
initNorthPane();
initSouthPane();
}
private void initNorthPane() {
UILabel northTip = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Tip"));
northTip.setForeground(Color.decode("#8F8F92"));
northTip.setBorder(BorderFactory.createEmptyBorder(0, 550, 10, 10));
this.add(northTip, BorderLayout.NORTH);
}
private void initSouthPane() {
preparePane = new TransformPreparePane(this.showDialog, this);
tree = new TransformFileTree(preparePane);
this.add(preparePane, BorderLayout.CENTER);
initLeftPane();
initRightPane();
}
private void initLeftPane() {
IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{FileExtension.CPT.getSuffix()});
tree.setDigIn(true);
tree.setFileNodeFilter(filter);
UIScrollPane scrollPane = new UIScrollPane(tree);
scrollPane.setPreferredSize(new Dimension(320, 442));
scrollPane.setBorder(BorderFactory.createEmptyBorder(12, 0, 0, 0));
tree.refreshEnv();
JPanel selectPane = FRGUIPaneFactory.createTitledBorderPaneCenter(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Select_Template"));
JPanel searchPane = initSearchPane();
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.add(searchPane, BorderLayout.NORTH);
jPanel.add(scrollPane, BorderLayout.WEST);
jPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
selectPane.add(jPanel);
selectPane.setPreferredSize(new Dimension(330, 501));
this.add(selectPane, BorderLayout.WEST);
}
private void initRightPane() {
resultPane = new TransformResultPane();
this.add(resultPane, BorderLayout.EAST);
}
private JPanel initSearchPane() {
JPanel jPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane();
jPanel.setBorder(BorderFactory.createEmptyBorder());
searchField = new UITextField();
searchField.requestFocus();
searchField.addKeyListener(keyFieldKeyListener);
searchField.setPreferredSize(new Dimension(261, 20));
jPanel.add(searchField);
UIButton searchBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Search"));
searchBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
search();
}
});
searchBtn.setPreferredSize(new Dimension(44, 20));
jPanel.add(searchBtn);
return jPanel;
}
private KeyAdapter keyFieldKeyListener = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
search();
e.consume();
}
}
};
private void search() {
//重新构建TreeModel
filter(searchField.getText());
ExpandMutableTreeNode rootNode = (ExpandMutableTreeNode) tree.getModel().getRoot();
((DefaultTreeModel) tree.getModel()).reload(rootNode);
// 展开所有isExpanded为true的TreeNode
rootNode.expandCurrentTreeNode(tree);
}
public void filter(String filterString) {
NodeAuthProcessor.getInstance().refresh();
DefaultTreeModel defaultTreeModel = (DefaultTreeModel) tree.getModel();
ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot();
NodeAuthProcessor.getInstance().fixTreeNodeAuth(rootTreeNode);
filter(rootTreeNode, filterString);
defaultTreeModel.reload(rootTreeNode);
}
private void filter(ExpandMutableTreeNode rootTreeNode, String filterString) {
rootTreeNode.removeAllChildren();
FileNode[] fns;
fns = listFileNodes(rootTreeNode);
ExpandMutableTreeNode[] subTreeNodes = NodeAuthProcessor.getInstance().parser2TreeNodeArray(fns);
for (ExpandMutableTreeNode node : subTreeNodes) {
filter(node, filterString);
if (node.getChildCount() > 0 || (node.getChildCount() == 0 && node.toString().contains(filterString))) {
node.setExpanded(true);
rootTreeNode.add(node);
}
}
}
private FileNode[] listFileNodes(ExpandMutableTreeNode rootTreeNode) {
if (rootTreeNode == null) {
return new FileNode[0];
}
Object object = rootTreeNode.getUserObject();
if (!(object instanceof FileNode)) {
return new FileNode[0];
}
FileNode[] fileNodes = null;
try {
fileNodes = tree.listFile(((FileNode) object).getEnvPath());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (fileNodes == null) {
fileNodes = new FileNode[0];
}
Arrays.sort(fileNodes, new FileNodeComparator(FileNodeConstants.getSupportFileTypes()));
return fileNodes;
}
public void resetFilePaths(Map<FileNode, TransformResultInfo> resultMap) {
this.tree.resetSelectedPaths();
Iterator<FileNode> iterator = resultMap.keySet().iterator();
List<FileNode> list = new ArrayList<FileNode>();
while (iterator.hasNext()){
FileNode node = iterator.next();
list.add(node);
}
this.tree.addTransformedList(list);
this.tree.refresh();
resultPane.populate(resultMap);
}
public void removeSelectedNode(FileNode fileNode) {
String path = fileNode.getEnvPath();
this.tree.removeSelectedPath(path);
}
@Override
protected String title4PopupWindow() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform");
}
public Dialog showDialog() {
return this.showDialog;
}
}

79
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java

@ -0,0 +1,79 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.BaseUtils;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ilist.UIList;
import com.fr.design.gui.itree.filetree.FileTreeIcon;
import com.fr.file.filetree.FileNode;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/**
* Created by kerry on 2020-01-13
*/
public class PrepareTransformFileList extends UIList {
private TransformPreparePane transformingPane;
private static final int DELETE_RANGE = 20;
public PrepareTransformFileList(final TransformPreparePane transformingPane) {
super();
this.transformingPane = transformingPane;
this.setBackground(UIConstants.TREE_BACKGROUND);
this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
DefaultListModel listModel = new DefaultListModel();
this.setModel(listModel);
this.setCellRenderer(new UIListControlCellRenderer() {
@Override
protected Icon getLeftLabelIcon(Object value) {
if (value instanceof FileNode) {
return FileTreeIcon.getIcon((FileNode) value);
}
return null;
}
@Override
protected Icon getRightLabelIcon(Object value) {
return BaseUtils.readIcon("/com/fr/nx/app/designer/transform/tab_close.png");
}
});
this.addMouseListener(getListMouseListener());
}
private MouseListener getListMouseListener() {
return new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent evt) {
JList list = (JList) evt.getSource();
int selectedIndex = list.getSelectedIndex();
Rectangle rectangle = list.getCellBounds(selectedIndex, selectedIndex);
if (SwingUtilities.isLeftMouseButton(evt)
&& pointInSelected(rectangle, evt.getX(), evt.getY())) {
Object value = PrepareTransformFileList.this.getSelectedValue();
if (value != null) {
transformingPane.removeSelectedNode((FileNode) value);
}
}
}
};
}
private boolean pointInSelected(Rectangle rectangle, int x, int y) {
if (rectangle == null) {
return false;
}
return x >= rectangle.x + rectangle.width - DELETE_RANGE &&
x <= rectangle.x + rectangle.width &&
y >= rectangle.y && y <= rectangle.y + rectangle.height;
}
}

204
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java

@ -0,0 +1,204 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.FRContext;
import com.fr.base.extension.FileExtension;
import com.fr.design.gui.itree.checkboxtree.CheckBoxTree;
import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeCellRenderer;
import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeSelectionModel;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.remote.ui.tree.FileAuthorityTree;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.nx.app.designer.transform.BatchTransformUtil;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Created by kerry on 2020-01-13
*/
public class TransformFileTree extends FileAuthorityTree {
private TransformPreparePane preparePane;
private static final float CHECKBOX_ENABLE_OPACITY = 0.4f;
private List<FileNode> transformedList = new ArrayList<FileNode>();
public TransformFileTree(TransformPreparePane preparePane) {
this.preparePane = preparePane;
}
public void addTransformedList(List<FileNode> removeList) {
this.transformedList.addAll(removeList);
}
@Override
protected CheckBoxTree.Handler createHandler() {
return new CheckBoxTree.Handler(this) {
@Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
TreePath treePath = this.getTreePathForMouseEvent(e);
if (treePath == null) {
return;
}
CheckBoxTreeSelectionModel selectionModel = _tree.getCheckBoxTreeSelectionModel();
boolean selected = selectionModel.isPathSelected(treePath, selectionModel.isDigIn());
ExpandMutableTreeNode lastPathComponent = (ExpandMutableTreeNode) treePath.getLastPathComponent();
List<FileNode> selectedFileNodes = filterBatchFileNode(lastPathComponent);
preparePane.removeTransformNode(selectedFileNodes);
if (selected) {
preparePane.addTransformNode(selectedFileNodes);
}
}
};
}
private List<FileNode> filterBatchFileNode(ExpandMutableTreeNode treeNode) {
List<FileNode> fileNodeList = new ArrayList<>();
int childCount = treeNode.getChildCount();
if (childCount > 0) {
loadPendingChildTreeNode(treeNode);
int expandChildCount = treeNode.getChildCount();
for (int i = 0; i < expandChildCount; i++) {
fileNodeList.addAll(filterBatchFileNode((ExpandMutableTreeNode) treeNode.getChildAt(i)));
}
} else {
FileNode fileNode = (FileNode) treeNode.getUserObject();
boolean locked = fileNodeLocked(treeNode);
if (!fileNode.isDirectory() && !locked) {
fileNodeList.add((FileNode) treeNode.getUserObject());
}
}
return fileNodeList;
}
private boolean fileNodeLocked(ExpandMutableTreeNode treeNode) {
Object userObj = treeNode.getUserObject();
if (userObj instanceof FileNode) {
FileNode node = (FileNode) userObj;
String lock = node.getLock();
if (lock != null && !node.getUserID().equals(lock)) {
return true;
}
}
return false;
}
public void resetSelectedPaths() {
CheckBoxTreeSelectionModel selectionModel = this.getCheckBoxTreeSelectionModel();
selectionModel.clearSelection();
}
@Override
public void selectCheckBoxPaths(String[] paths) {
if (paths == null || paths.length == 0) {
return;
}
DefaultTreeModel model = (DefaultTreeModel) this.getModel();
ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot();
List<TreePath> res = new ArrayList<>();
for (String path : paths) {
TreePath treePath = getSelectedPath(treeNode, path);
if (treePath != null) {
res.add(treePath);
}
}
// 勾选中这些结点
this.getCheckBoxTreeSelectionModel().setSelectionPaths(res.toArray(new TreePath[0]));
}
private TreePath getSelectedPath(ExpandMutableTreeNode treeNode, String path) {
//可以只在选中的path中选择
for (int i = 0, len = treeNode.getChildCount(); i < len; i++) {
ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) treeNode.getChildAt(i);
if (childTreeNode.getChildCount() > 0) {
loadPendingChildTreeNode(childTreeNode);
TreePath treePath = getSelectedPath(childTreeNode, path);
if (treePath != null) {
return treePath;
}
}
if (!(childTreeNode.getUserObject() instanceof FileNode)) {
continue;
}
FileNode fileNode = (FileNode) childTreeNode.getUserObject();
if (ComparatorUtils.equals(path, fileNode.getEnvPath())) {
DefaultTreeModel model = (DefaultTreeModel) this.getModel();
return new TreePath(model.getPathToRoot(childTreeNode));
}
}
return null;
}
public void removeSelectedPath(String path) {
if (path == null) {
return;
}
DefaultTreeModel model = (DefaultTreeModel) this.getModel();
ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot();
TreePath selectedPath = getSelectedPath(treeNode, path);
if (selectedPath != null) {
this.getCheckBoxTreeSelectionModel().removeSelectionPath(selectedPath);
}
}
@Override
public FileNode[] listFile(String path) {
// 支持插件扩展, 先从env的filter拿, 再从插件拿
Set<FileExtension> supportTypes = new HashSet<FileExtension>();
for (String temp : this.filter.getSupportedTypes()) {
supportTypes.add(FileExtension.parse(temp));
}
FileNode[] fileNodes = FRContext.getFileNodes().list(
path,
supportTypes.toArray(new FileExtension[supportTypes.size()])
);
return BatchTransformUtil.filterTransformedFile(fileNodes, transformedList);
}
@Override
public boolean isCheckBoxEnabled(TreePath path) {
ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) path.getLastPathComponent();
return !fileNodeLocked(treeNode);
}
@Override
protected CheckBoxTreeCellRenderer createCellRenderer(TreeCellRenderer renderer) {
final CheckBoxTreeCellRenderer checkBoxTreeCellRenderer = new CheckBoxTreeCellRenderer(renderer) {
@Override
public void paint(Graphics g) {
if (!_checkBox.isEnabled()) {
AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, CHECKBOX_ENABLE_OPACITY);
((Graphics2D) g).setComposite(composite);
}
super.paint(g);
}
};
addPropertyChangeListener(CELL_RENDERER_PROPERTY, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
checkBoxTreeCellRenderer.setActualTreeRenderer((TreeCellRenderer) evt.getNewValue());
}
});
return checkBoxTreeCellRenderer;
}
}

130
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java

@ -0,0 +1,130 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.file.filetree.FileNode;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import com.fr.nx.app.designer.transform.BatchTransformer;
import com.fr.nx.app.designer.transform.UpdateCallBack;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by kerry on 2020-01-13
*/
public class TransformPreparePane extends JPanel {
private static final String INITIAL_DISPLAY_TEXT = "0";
private PrepareTransformFileList fileList;
private List<FileNode> selectedFileNodes;
private UpdateProgressDialog dialog;
private BatchTransformer transformer;
private UpdateCallBack updateProgressPane;
private Dialog parentDialog;
private UILabel transCountLabel;
private BatchTransformPane batchTransformPane;
private UIButton startTransform;
public TransformPreparePane(Dialog parentDialog, BatchTransformPane batchTransformPane) {
this.batchTransformPane = batchTransformPane;
this.parentDialog = parentDialog;
this.setLayout(FRGUIPaneFactory.createBorderLayout());
updateProgressPane = new UpdateProgressPane(this);
transformer = new BatchTransformer(updateProgressPane);
fileList = new PrepareTransformFileList(this);
selectedFileNodes = new ArrayList<>();
initPane();
}
private void initPane() {
JPanel transformPane = FRGUIPaneFactory.createTitledBorderPaneCenter(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Template_To_Transform"));
transformPane.setPreferredSize(new Dimension(270, 501));
startTransform = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Start"));
startTransform.setEnabled(false);
addStartTransformListener(startTransform);
transCountLabel = new UILabel(INITIAL_DISPLAY_TEXT);
JPanel northPane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane();
northPane.add(startTransform);
northPane.add(Box.createHorizontalStrut(160));
northPane.add(transCountLabel);
transformPane.add(northPane, BorderLayout.NORTH);
UIScrollPane scrollPane = new UIScrollPane(fileList);
scrollPane.setPreferredSize(new Dimension(260, 442));
scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
transformPane.add(scrollPane, BorderLayout.CENTER);
this.add(transformPane, BorderLayout.CENTER);
}
private void addStartTransformListener(UIButton startTransform) {
startTransform.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//开始转换
transformer.batchTransform(selectedFileNodes);
displayProgressPane();
}
private void displayProgressPane() {
dialog = new UpdateProgressDialog(transformer, parentDialog, (JPanel) updateProgressPane);
dialog.setVisible(true);
}
});
}
public void addTransformNode(List<FileNode> fileNodeList) {
selectedFileNodes.addAll(fileNodeList);
buildFileList();
}
public void removeTransformNode(List<FileNode> fileNodeList) {
selectedFileNodes.removeAll(fileNodeList);
buildFileList();
}
public void removeSelectedNode(FileNode fileNode) {
selectedFileNodes.remove(fileNode);
buildFileList();
this.batchTransformPane.removeSelectedNode(fileNode);
}
private void buildFileList() {
DefaultListModel listModel = new DefaultListModel();
int count = selectedFileNodes.size();
for (int i = count - 1; i >= 0; i--) {
listModel.addElement(selectedFileNodes.get(i));
}
this.fileList.setModel(listModel);
startTransform.setEnabled(selectedFileNodes.size() > 0);
transCountLabel.setText(String.valueOf(selectedFileNodes.size()));
}
public void complete() {
dialog.dialogExit();
updateProgressPane.reset();
Map<FileNode, TransformResultInfo> resultMap = transformer.getResults();
resetFileNodeList();
this.batchTransformPane.resetFilePaths(resultMap);
}
private void resetFileNodeList(){
this.selectedFileNodes.clear();
buildFileList();
}
}

70
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java

@ -0,0 +1,70 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.BaseUtils;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ilist.UIList;
import com.fr.design.gui.itree.filetree.FileTreeIcon;
import com.fr.file.filetree.FileNode;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ListSelectionModel;
import java.util.Iterator;
import java.util.Map;
/**
* Created by kerry on 2020-01-13
*/
public class TransformResultList extends UIList {
private Map<FileNode, TransformResultInfo> resultMap;
private static final Icon FAILED_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_failed.png");
private static final Icon SUCCESS_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_success.png");
private static final Icon UNSUPPORT_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_unsupport.png");
public TransformResultList() {
super();
this.setBackground(UIConstants.TREE_BACKGROUND);
this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
DefaultListModel listModel = new DefaultListModel();
this.setModel(listModel);
this.setCellRenderer(new UIListControlCellRenderer() {
@Override
protected Icon getLeftLabelIcon(Object value) {
if (value instanceof FileNode) {
return FileTreeIcon.getIcon((FileNode) value);
}
return null;
}
@Override
protected Icon getRightLabelIcon(Object value) {
if (value != null) {
TransformResultInfo resultInfo = resultMap.get(value);
switch (resultInfo.getResult()) {
case FAILED:
return FAILED_ICON;
case SUCCESS:
return SUCCESS_ICON;
case UNSUPPORT:
return UNSUPPORT_ICON;
}
}
return null;
}
});
}
public void populate(Map<FileNode, TransformResultInfo> resultMap) {
this.resultMap = resultMap;
DefaultListModel listModel = new DefaultListModel();
Iterator<Map.Entry<FileNode, TransformResultInfo>> iterator = resultMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<FileNode, TransformResultInfo> entry = iterator.next();
FileNode key = entry.getKey();
listModel.addElement(key);
}
this.setModel(listModel);
}
}

110
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java

@ -0,0 +1,110 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextarea.UITextArea;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.toolbar.TransformResult;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.Iterator;
import java.util.Map;
/**
* Created by kerry on 2020-01-10
*/
public class TransformResultPane extends JPanel {
private TransformResultList resultList;
private UITextArea resultInfo;
private Map<FileNode, TransformResultInfo> resultMap;
private UILabel successTip;
public TransformResultPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
initPane();
}
private void initPane() {
JPanel resultPane = FRGUIPaneFactory.createTitledBorderPaneCenter(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Result"));
JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
resultList = new TransformResultList();
addValueChangeListener();
UIScrollPane scrollPane = new UIScrollPane(resultList);
scrollPane.setPreferredSize(new Dimension(260, 260));
scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
successTip = new UILabel("");
successTip.setBorder(BorderFactory.createEmptyBorder(5, 150, 5, 10));
northPane.add(successTip, BorderLayout.NORTH);
northPane.add(scrollPane, BorderLayout.CENTER);
resultPane.add(northPane);
JPanel resultInfoPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
resultInfoPane.setPreferredSize(new Dimension(270, 165));
resultInfoPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5));
UILabel transformLogLabel = new UILabel(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Logs"));
transformLogLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
resultInfoPane.add(transformLogLabel, BorderLayout.NORTH);
resultInfo = new UITextArea();
resultInfo.setBackground(Color.white);
resultInfo.setLineWrap(true);
resultInfo.setWrapStyleWord(true);
resultInfo.setEditable(false);
UIScrollPane resultScrollPane = new UIScrollPane(resultInfo);
resultInfoPane.add(resultScrollPane, BorderLayout.CENTER);
this.add(resultPane, BorderLayout.NORTH);
this.add(resultInfoPane, BorderLayout.CENTER);
}
private void addValueChangeListener() {
resultList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
FileNode selectedValue = (FileNode) resultList.getSelectedValue();
if (resultInfo != null && selectedValue != null) {
TransformResultInfo result = resultMap.get(selectedValue);
resultInfo.setText(result.getTransformLog());
}
}
});
}
public void populate(Map<FileNode, TransformResultInfo> resultMap) {
int count = getSuccessCount(resultMap);
String tip = InterProviderFactory.getProvider().getLocText(
"Fine-Plugin_Engine_Transform_Result_Tip", String.valueOf(count));
successTip.setText(tip);
this.resultMap = resultMap;
resultList.populate(resultMap);
if (resultList.getModel().getSize() > 0) {
resultList.setSelectedIndex(0);
FileNode firstResult = (FileNode) resultList.getModel().getElementAt(0);
resultInfo.setText(resultMap.get(firstResult).getTransformLog());
}
}
private int getSuccessCount(Map<FileNode, TransformResultInfo> resultMap) {
int count = 0;
Iterator<Map.Entry<FileNode, TransformResultInfo>> iterator = resultMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<FileNode, TransformResultInfo> entry = iterator.next();
TransformResultInfo resultInfo = entry.getValue();
if (ComparatorUtils.equals(TransformResult.SUCCESS, resultInfo.getResult())) {
count++;
}
}
return count;
}
}

86
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java

@ -0,0 +1,86 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.stable.StringUtils;
import sun.swing.DefaultLookup;
import javax.swing.Icon;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
/**
* Created by kerry on 2020-01-14
*/
public class UIListControlCellRenderer extends JPanel implements ListCellRenderer {
private UILabel content;
private UILabel controlLabel;
private Color initialLabelForeground;
public UIListControlCellRenderer() {
initPane();
}
private void initPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
content = new UILabel();
initialLabelForeground = content.getForeground();
controlLabel = new UILabel();
controlLabel.setPreferredSize(new Dimension(16, 20));
this.add(content, BorderLayout.CENTER);
this.add(controlLabel, BorderLayout.EAST);
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setComponentOrientation(list.getComponentOrientation());
Color bg = null;
Color fg = null;
JList.DropLocation dropLocation = list.getDropLocation();
if (dropLocation != null
&& !dropLocation.isInsert()
&& dropLocation.getIndex() == index) {
bg = DefaultLookup.getColor(this, ui, "List.dropCellBackground");
fg = DefaultLookup.getColor(this, ui, "List.dropCellForeground");
isSelected = true;
}
if (isSelected) {
setBackground(bg == null ? list.getSelectionBackground() : bg);
setForeground(fg == null ? list.getSelectionForeground() : fg);
content.setForeground(Color.WHITE);
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
content.setForeground(initialLabelForeground);
}
content.setText((value == null) ? StringUtils.EMPTY : value.toString());
Icon leftLabelIcon = getLeftLabelIcon(value);
if (leftLabelIcon != null) {
content.setIcon(leftLabelIcon);
}
Icon rightLabelIcon = getRightLabelIcon(value);
if (rightLabelIcon != null) {
controlLabel.setIcon(rightLabelIcon);
}
return this;
}
protected Icon getLeftLabelIcon(Object value) {
return null;
}
protected Icon getRightLabelIcon(Object value) {
return null;
}
}

70
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java

@ -0,0 +1,70 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.transform.BatchTransformer;
import javax.swing.JDialog;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* Created by kerry on 2019-12-19
*/
public class UpdateProgressDialog extends JDialog implements ActionListener {
private UIButton pauseBtn;
private BatchTransformer transformer;
public UpdateProgressDialog(BatchTransformer transformer, Dialog parent, JPanel contentPane) {
super(parent, true);
this.transformer = transformer;
initPane(contentPane);
}
private void initPane(JPanel contentPane) {
this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Format_Transform"));
this.setResizable(false);
JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane();
this.setContentPane(defaultPane);
pauseBtn = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend"));
pauseBtn.addActionListener(this);
JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
buttonPanel.add(pauseBtn);
defaultPane.add(contentPane, BorderLayout.CENTER);
defaultPane.add(buttonPanel, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
transformer.shutDown();
dialogExit();
}
});
this.getRootPane().setDefaultButton(pauseBtn);
this.setSize(new Dimension(262, 122));
GUICoreUtils.centerWindow(this);
}
@Override
public void actionPerformed(ActionEvent e) {
transformer.shutDown();
dialogExit();
}
public void dialogExit() {
this.dispose();
}
}

72
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java

@ -0,0 +1,72 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.BaseUtils;
import com.fr.decision.update.data.UpdateConstants;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.ComparatorUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.transform.UpdateCallBack;
import com.sun.java.swing.plaf.motif.MotifProgressBarUI;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import java.awt.BorderLayout;
import java.awt.Dimension;
/**
* Created by kerry on 2019-12-11
*/
public class UpdateProgressPane extends BasicPane implements UpdateCallBack {
private TransformPreparePane contentPane;
private JProgressBar progressBar;
public UpdateProgressPane(TransformPreparePane contentPane) {
this.contentPane = contentPane;
initPane();
}
private void initPane() {
this.setPreferredSize(new Dimension(262, 60));
UILabel icon = new UILabel(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transforming.png"));
icon.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
this.add(icon, BorderLayout.WEST);
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
UILabel title = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transforming"));
title.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0));
centerPane.add(title, BorderLayout.NORTH);
progressBar = new JProgressBar();
progressBar.setUI(new MotifProgressBarUI());
progressBar.setForeground(UpdateConstants.BAR_COLOR);
centerPane.add(progressBar, BorderLayout.CENTER);
this.add(centerPane, BorderLayout.CENTER);
}
@Override
public void updateProgress(double progress) {
progressBar.setValue((int) (progress * 100));
if (ComparatorUtils.equals(progress, 1D)) {
contentPane.complete();
}
}
@Override
public void shutDown() {
contentPane.complete();
}
@Override
public void reset() {
progressBar.setValue(0);
}
@Override
protected String title4PopupWindow() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend");
}
}

55
designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java

@ -0,0 +1,55 @@
package com.fr.nx.app.designer.utils;
import com.fr.design.mainframe.JTemplate;
import com.fr.file.FILE;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.toolbar.TemplateTransformer;
import com.fr.nx.app.designer.toolbar.TransformResult;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import com.fr.workspace.WorkContext;
import java.io.InputStream;
import static com.fr.base.extension.FileExtension.CPT;
import static com.fr.base.extension.FileExtension.CPTX;
/**
* Created by kerry on 2019-12-04
*/
public class CompileTransformUtil {
public static TransformResultInfo compileFile(FileNode fileNode) {
long start = System.currentTimeMillis();
InputStream in = WorkContext.getWorkResource().openStream(fileNode.getEnvPath());
WorkBook workBook = new WorkBook();
TransformResultInfo result = null;
try {
workBook.readStream(in);
FILE file = TemplateTransformer.createOutputFile(fileNode.getEnvPath(), CPT.getSuffix(), CPTX.getSuffix());
result = TemplateTransformer.compileCPTX(workBook, file);
} catch (Exception ignore) {
result = TransformResultInfo.generateResult(TransformResult.FAILED);
}
long end = System.currentTimeMillis();
FineLoggerFactory.getLogger().debug(fileNode.getName() + " compile cost : " + (end - start) +" ms ");
return result;
}
public static FILE getTargetFile(JTemplate jTemplate, TemplateTransformer transformer) {
FILE file = null;
if (ComparatorUtils.equals(TemplateTransformer.TO_CPTX, transformer)) {
file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(),
CPT.getSuffix(), CPTX.getSuffix());
} else if (ComparatorUtils.equals(TemplateTransformer.TO_CPT, transformer)) {
file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(),
CPTX.getSuffix(), CPT.getSuffix());
}
return file;
}
}

79
designer-base/src/main/java/com/fr/nx/app/designer/utils/DesignerCptxFileUtils.java

@ -0,0 +1,79 @@
package com.fr.nx.app.designer.utils;
import com.fr.file.FILE;
import com.fr.general.CommonIOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.marshal.impl.xml.DefaultXMLObjectUnmarshaler;
import com.fr.nx.marshal.util.MarshalUtil;
import com.fr.nx.cptx.entry.metadata.CptxMetadata;
import com.fr.nx.cptx.io.handle.impl.OriginCptProvider;
import com.fr.nx.cptx.marshal.util.CptxMarshalUtil;
import com.fr.nx.cptx.utils.CptxFileUtils;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.xml.XMLableReader;
import com.fr.workspace.WorkContext;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Created by loy on 2021/1/18.
*
* <p>用于设计器的cptx的一些工具类
* <p>
*/
public class DesignerCptxFileUtils {
/**
* 根据file来获取cptx中的cpt
* @param file
* @return
*/
public static WorkBook getWorkBook(final FILE file){
try (InputStream input = file.asInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
CommonIOUtils.copyBinaryTo(input, outputStream);
OriginCptProvider provider = new OriginCptProvider(outputStream.toByteArray());
return CptxFileUtils.getWorkBook(provider);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
/**
* 获取模板的元数据
* @param file
* @return
*/
public static CptxMetadata getMetadata(FILE file){
try {
String metadataPath = StableUtils.pathJoin(generateCompileDir(file), CptxMarshalUtil.NAME_METADATA);
if(!WorkContext.getWorkResource().exist(metadataPath)){
return null;
}
InputStream metadataInput = WorkContext.getWorkResource().openStream(metadataPath);
XMLableReader reader = XMLableReader.createXMLableReader(
new InputStreamReader(metadataInput, EncodeConstants.ENCODING_UTF_8));
CptxMetadata metadata = (CptxMetadata) new DefaultXMLObjectUnmarshaler().unmarshal(
MarshalUtil.createMarshalableExtra(CptxMetadata.class), reader);
return metadata;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
/**
* 根据文件获取编译后的文件夹绝对路径比如原文件位于reportlets/test/merge.cptx转化后为evn://assets/engine/test/merge文件夹
* @param file
* @return
*/
public static String generateCompileDir(FILE file){
String filePath = file.getPath();
return CptxFileUtils.generateCompileDir(filePath);
}
}

239
designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java

@ -0,0 +1,239 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.base.Parameter;
import com.fr.base.chart.BaseChartCollection;
import com.fr.base.io.XMLEncryptKey;
import com.fr.base.io.XMLEncryptUtils;
import com.fr.base.iofile.IOFileAttrMarkManager;
import com.fr.base.parameter.ParameterUI;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.config.dao.DaoContext;
import com.fr.config.dao.impl.LocalClassHelperDao;
import com.fr.config.dao.impl.LocalEntityDao;
import com.fr.config.dao.impl.LocalXmlEntityDao;
import com.fr.file.MemFILE;
import com.fr.form.DefaultFormOperator;
import com.fr.form.FormOperator;
import com.fr.form.main.ExtraFormClassManager;
import com.fr.form.main.Form;
import com.fr.form.main.FormHyperlink;
import com.fr.form.main.parameter.FormParameterUI;
import com.fr.form.parameter.FormSubmitButton;
import com.fr.form.plugin.DefaultSwitcherImpl;
import com.fr.general.xml.GeneralXMLTools;
import com.fr.io.EncryptUtils;
import com.fr.js.FormHyperlinkProvider;
import com.fr.main.impl.WorkBook;
import com.fr.nx.calculable.Calculable;
import com.fr.nx.calculable.type.ConstantCalculable;
import com.fr.nx.cell.CellKey;
import com.fr.nx.cell.CellTemplate;
import com.fr.nx.cptx.cache.CptxTemplatePool;
import com.fr.nx.cptx.entry.CptxTemplate;
import com.fr.nx.cptx.resource.ImageResourceRef;
import com.fr.page.BaseSinglePagePrintable;
import com.fr.page.BaseSingleReportCache;
import com.fr.page.ClippedChartPage;
import com.fr.page.ClippedECPage;
import com.fr.page.ClippedPageProvider;
import com.fr.page.PDF2Painter;
import com.fr.page.PageGeneratorProvider;
import com.fr.page.PagePainter;
import com.fr.page.PagePainterProvider;
import com.fr.page.PageSetChainProvider;
import com.fr.page.PageSetProvider;
import com.fr.page.PageXmlOperator;
import com.fr.page.PageXmlProvider;
import com.fr.page.PaperSettingProvider;
import com.fr.page.ReportPage;
import com.fr.page.ReportPageAttrProvider;
import com.fr.page.ReportPageProvider;
import com.fr.page.SheetPage;
import com.fr.page.SinglePagePrintable;
import com.fr.page.SingleReportCache;
import com.fr.page.generator.PaginateReportPageGenerator;
import com.fr.page.generator.PolyReportPageGenerator;
import com.fr.page.generator.SheetPageGenerator;
import com.fr.page.pageset.ArrayPageSet;
import com.fr.page.pageset.PageSetChain;
import com.fr.page.stable.PaperSetting;
import com.fr.page.stable.ReportPageAttr;
import com.fr.plugin.attr.CalculatorAttrMark;
import com.fr.runtime.FineRuntime;
import com.fr.stable.EssentialUtils;
import com.fr.stable.bridge.BridgeMark;
import com.fr.stable.bridge.StableFactory;
import com.fr.stable.fun.WidgetSwitcher;
import com.fr.stable.module.Module;
import com.fr.stable.plugin.ExtraFormClassManagerProvider;
import com.fr.transaction.Configurations;
import com.fr.transaction.LocalConfigurationHelper;
import com.fr.xml.ReportXMLUtils;
import org.easymock.EasyMock;
import org.easymock.IArgumentMatcher;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import java.io.InputStream;
@RunWith(PowerMockRunner.class)
@PrepareForTest({CptxTemplatePool.class, XMLEncryptUtils.class})
@SuppressStaticInitializationFor({"com.fr.nx.cptx.cache.CptxTemplatePool", "com.fr.base.io.XMLEncryptUtils"})
@PowerMockIgnore({"com.sun.tools.attach.*", "sun.tools.attach.*"})
public class TemplateTransformerDebugTest {
@BeforeClass
public static void beforeClass() {
System.setProperty("apple.awt.UIElement", "true");
StableFactory.registerXMLDescription(ReportPageAttrProvider.XML_TAG, new ReportPageAttr());
StableFactory.registerMarkedClass(ReportPageProvider.XML_TAG, ReportPage.class);
StableFactory.registerMarkedClass(PaperSettingProvider.XML_TAG, PaperSetting.class);
StableFactory.registerMarkedClass(ReportPageProvider.XML_TAG_4_SHEET, SheetPage.class);
StableFactory.registerMarkedClass(PagePainterProvider.XML_TAG, PagePainter.class);
StableFactory.registerMarkedClass(PageSetChainProvider.XML_TAG, PageSetChain.class);
StableFactory.registerMarkedClass(PageXmlProvider.XML_TAG, PageXmlOperator.class);
StableFactory.registerMarkedClass(BaseSinglePagePrintable.XML_TAG, SinglePagePrintable.class);
StableFactory.registerMarkedClass(BaseSingleReportCache.XML_TAG, SingleReportCache.class);
StableFactory.registerMarkedClass(PageSetProvider.XML_TAG_4_ARRAY, ArrayPageSet.class);
StableFactory.registerMarkedClass(ClippedPageProvider.XML_TAG_EC, ClippedECPage.class);
StableFactory.registerMarkedClass(ClippedPageProvider.XML_TAG_CHART, ClippedChartPage.class);
StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_PAGE, PaginateReportPageGenerator.class);
StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_POLY, PolyReportPageGenerator.class);
StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_SHEET, SheetPageGenerator.class);
StableFactory.registerMarkedClass(PagePainterProvider.XML_TAG_4_PDF, PDF2Painter.class);
StableFactory.registerMarkedClass(BridgeMark.SUBMIT_BUTTON, FormSubmitButton.class);
StableFactory.registerMarkedClass(FormOperator.MARK_STRING, DefaultFormOperator.class);
StableFactory.registerMarkedClass(Module.FORM_MODULE, Form.class);
StableFactory.registerMarkedClass(ParameterUI.FORM_XML_TAG, FormParameterUI.class);
StableFactory.registerMarkedClass(FormHyperlinkProvider.XML_TAG, FormHyperlink.class);
StableFactory.registerMarkedObject(WidgetSwitcher.XML_TAG, new DefaultSwitcherImpl());
StableFactory.registerMarkedClass(ExtraFormClassManagerProvider.XML_TAG, ExtraFormClassManager.class);
StableFactory.registerXMLDescription(BaseChartCollection.XML_TAG, new ChartCollection());
StableFactory.registerXMLDescription(Parameter.XML_TAG, new Parameter());
FineRuntime.start();
GeneralXMLTools.Object_Tokenizer = new ReportXMLUtils.ReportObjectTokenizer();
GeneralXMLTools.Object_XML_Writer_Finder = new ReportXMLUtils.ReportObjectXMLWriterFinder();
DaoContext.setEntityDao(new LocalEntityDao());
DaoContext.setClassHelperDao(new LocalClassHelperDao());
DaoContext.setXmlEntityDao(new LocalXmlEntityDao());
Configurations.setHelper(new LocalConfigurationHelper());
IOFileAttrMarkManager.register(new CalculatorAttrMark());
}
@Before
public void before() {
Whitebox.setInternalState(XMLEncryptUtils.class, "KEY", new XMLEncryptKey());
}
@Test
public void testUnsupportedCompile() {
WorkBook workbook = readCpt("read-write-expand-order.cpt");
CptxTemplatePool pool = EasyMock.mock(CptxTemplatePool.class);
PowerMock.mockStatic(CptxTemplatePool.class);
EasyMock.expect(CptxTemplatePool.getInstance()).andReturn(pool).anyTimes();
PowerMock.replay(CptxTemplatePool.class);
pool.addCptxTemplate(EasyMock.anyString(), matchUnsupportedWebPreviewCptxTemplate());
EasyMock.expectLastCall().once();
EasyMock.replay(pool);
TemplateTransformer.compileCPTX(workbook, new MemFILE("read-write-expand-order.cpt"));
EasyMock.verify(pool);
PowerMock.verify(CptxTemplatePool.class);
}
@Test
public void testImageRefCompile() {
WorkBook workbook = readCpt("read-write-image-ref.cpt");
CptxTemplatePool pool = EasyMock.mock(CptxTemplatePool.class);
PowerMock.mockStatic(CptxTemplatePool.class);
EasyMock.expect(CptxTemplatePool.getInstance()).andReturn(pool).anyTimes();
PowerMock.replay(CptxTemplatePool.class);
pool.addCptxTemplate(EasyMock.anyString(), matchImageRefWebPreviewCptxTemplate());
EasyMock.expectLastCall().once();
EasyMock.replay(pool);
TemplateTransformer.compileCPTX(workbook, new MemFILE("read-write-image-ref.cpt"));
EasyMock.verify(pool);
PowerMock.verify(CptxTemplatePool.class);
}
private CptxTemplate matchImageRefWebPreviewCptxTemplate() {
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object argument) {
if (argument instanceof CptxTemplate) {
CptxTemplate cptxTemplate = (CptxTemplate) argument;
Assert.assertNotNull(cptxTemplate.getTemplate());
Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult());
Assert.assertEquals(1, cptxTemplate.getTemplate().getCompileResult().getCellBlocks().length);
Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure());
Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure().getCells());
CellTemplate cellTemplate = cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure().getCells().get(CellKey.fromString("A2"));
Assert.assertNotNull(cellTemplate);
Calculable calculable = cellTemplate.getCalculable();
ConstantCalculable constantCalculable = calculable.unWrap(ConstantCalculable.KEY);
Assert.assertNotNull(constantCalculable);
Assert.assertTrue(constantCalculable.get() instanceof ImageResourceRef);
return true;
}
return false;
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("cptx template should be previewed on the web side but not.");
}
});
return null;
}
private CptxTemplate matchUnsupportedWebPreviewCptxTemplate() {
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object argument) {
if (argument instanceof CptxTemplate) {
CptxTemplate cptxTemplate = (CptxTemplate) argument;
Assert.assertEquals("unsupported feature: sort after expand",
cptxTemplate.getMetadata().getFailMessage());
return true;
}
return false;
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("should find unsupported error message but not");
}
});
return null;
}
private static WorkBook readCpt(String subPath) {
InputStream is = TemplateTransformerDebugTest.class.getClassLoader().getResourceAsStream("cpt/" + subPath);
WorkBook wb = new WorkBook();
try {
wb.readStream(EncryptUtils.decodeInputStream(is));
} catch (Exception e) {
throw new RuntimeException(e);
}
return wb;
}
}

85
designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java

@ -0,0 +1,85 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.base.FRContext;
import com.fr.base.operator.common.CommonOperator;
import com.fr.file.FILE;
import com.fr.file.filetree.FileNodes;
import com.fr.invoke.Reflect;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static com.fr.nx.app.designer.toolbar.TemplateTransformer.OTHER;
import static com.fr.nx.app.designer.toolbar.TemplateTransformer.TO_CPT;
import static com.fr.nx.app.designer.toolbar.TemplateTransformer.TO_CPTX;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@RunWith(PowerMockRunner.class)
@PrepareForTest({FRContext.class})
@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*", "com.fr.license.*"})
public class TemplateTransformerTest {
@Test
public void testParse() {
assertEquals(TO_CPTX, TemplateTransformer.parse("/sdf/abc.cpt"));
assertEquals(TO_CPT, TemplateTransformer.parse("/sdf/abc.cptx"));
assertEquals(OTHER, TemplateTransformer.parse("/sdf/abc.frm"));
assertEquals(OTHER, TemplateTransformer.parse(null));
assertEquals(OTHER, TemplateTransformer.parse("abc"));
}
@Test
public void testCompileFailed() {
TransformResultInfo result = TemplateTransformer.compileCPTX(null, null);
assertEquals(result.getResult(), TransformResult.FAILED);
}
@Test
public void testGenerateNewPath() {
assertEquals(generateNewPath("/abc/dd.cpt", ".cpt", ".cptx"), "/abc/dd.cptx");
assertEquals(generateNewPath("/abc/dd.cptx", ".cpt", ".cptx"), "/abc/dd.cptx");
assertEquals(generateNewPath("/abc/dd.cptx", ".cptx", ".cpt"), "/abc/dd.cpt");
assertEquals(generateNewPath("/abc/dd.frm", ".cpt", ".cptx"), "/abc/dd.frm");
assertNull(generateNewPath(null, null, null));
assertEquals(generateNewPath("abc", null, null), "abc");
}
private String generateNewPath(String oldPath, String oldSuffix, String newSuffix) {
return Reflect.on(TemplateTransformer.class).call("generateNewPath", oldPath, oldSuffix, newSuffix).get();
}
@Test
public void testCreateOutputFile() {
CommonOperator commonOperator = EasyMock.mock(CommonOperator.class);
FileNodes fileNodes = EasyMock.mock(FileNodes.class);
EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes();
PowerMock.mockStatic(FRContext.class);
EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes();
EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes();
EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes();
EasyMock.replay(commonOperator, fileNodes);
PowerMock.replayAll();
FILE file1 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cpt", ".cptx");
FILE file2 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cptx", ".cpt");
assertEquals("WorkBook1.cptx", file1.getPath());
assertEquals("WorkBook1.cpt", file2.getPath());
}
@Test
public void testNeedDoAfterTransformed() {
Assert.assertTrue(needDoAfterTransformed(TransformResult.SUCCESS));
Assert.assertTrue(needDoAfterTransformed(TransformResult.UNSUPPORT));
Assert.assertFalse(needDoAfterTransformed(TransformResult.FAILED));
}
private boolean needDoAfterTransformed(TransformResult result) {
return Reflect.on(TemplateTransformer.class).call("needDoAfterTransformed", result).get();
}
}

32
designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java

@ -0,0 +1,32 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.locale.InterProviderFactory;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by kerry on 2020-01-15
*/
public class TransformResultInfoTest {
@Test
public void testGetTransformLog() {
TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed");
Assert.assertEquals("failed\n" +
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip"),
resultInfo1.getTransformLog());
TransformResultInfo resultInfo2 = TransformResultInfo.generateResult(TransformResult.SUCCESS);
Assert.assertEquals(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip"),
resultInfo2.getTransformLog());
TransformResultInfo resultInfo3 = TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "unsupport");
Assert.assertEquals("unsupport\n" +
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip"),
resultInfo3.getTransformLog());
}
@Test
public void testSaved() {
TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed").saved(false);
Assert.assertFalse(resultInfo1.isSaved());
}
}

27
designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java

@ -0,0 +1,27 @@
package com.fr.nx.app.designer.transform;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by kerry on 2020-01-15
*/
public class BatchTransformProgressTest {
@Test
public void testGetProgress(){
BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100);
Assert.assertEquals(0.0D, batchTransformProgress.getProgress(), 0.0D);
}
@Test
public void testUpdateProgress(){
BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100);
for (int i = 0; i < 80; i++) {
batchTransformProgress.updateProgress();
}
Assert.assertEquals(0.8D, batchTransformProgress.getProgress(), 0.0D);
batchTransformProgress.updateProgress();
Assert.assertEquals(0.81D, batchTransformProgress.getProgress(), 0.0D);
}
}

35
designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java

@ -0,0 +1,35 @@
package com.fr.nx.app.designer.transform;
import com.fr.file.filetree.FileNode;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2020-02-14
*/
public class BatchTransformUtilTest {
@Test
public void testFilterTransformedFile(){
FileNode[] fileNodes = new FileNode[]{
new FileNode("test1", false), new FileNode("test2", false)
};
List<FileNode> transformedFileNodes = new ArrayList<FileNode>();
FileNode[] result1 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes);
Assert.assertEquals(2, result1.length);
transformedFileNodes.add( new FileNode("test1", false));
FileNode[] result2 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes);
Assert.assertEquals(1, result2.length);
transformedFileNodes.add( new FileNode("test2", false));
FileNode[] result3 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes);
Assert.assertEquals(0, result3.length);
transformedFileNodes.add( new FileNode("test3", false));
FileNode[] result4 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes);
Assert.assertEquals(0, result4.length);
}
}

124
designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java

@ -0,0 +1,124 @@
package com.fr.nx.app.designer.transform;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
/**
* Created by kerry on 2020-01-15
*/
// FIXME @kerry 打包失败,暂时先注释
//@RunWith(value = PowerMockRunner.class)
//@PrepareForTest({CompileTransformUtil.class, PluginContexts.class})
//@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"})
public class BatchTransformerTest {
private static final int MAXPOOLSIZE = 5;
private static final int COREPOOLSIZE = 3;
private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s";
@Before
public void setUp() {
// FineRuntime.start();
// ExecutorService threadPoolExecutor = new ThreadPoolExecutor(COREPOOLSIZE, MAXPOOLSIZE,
// 0L, TimeUnit.MILLISECONDS,
// new LinkedBlockingQueue<Runnable>(),
// new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build());
// PowerMock.mockStatic(PluginContexts.class);
// PluginContext pluginContext = EasyMock.mock(PluginContext.class);
// EasyMock.expect(pluginContext.newFixedThreadPool(
// EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class)))
// .andReturn(threadPoolExecutor).anyTimes();
// EasyMock.expect(PluginContexts.currentContext()).andReturn(pluginContext).anyTimes();
//
// PowerMock.mockStatic(CompileTransformUtil.class);
// TransformResultInfo resultInfo = TransformResultInfo.generateResult(TransformResult.SUCCESS);
// EasyMock.expect(CompileTransformUtil.compileFile(EasyMock.anyObject(FileNode.class)))
// .andReturn(resultInfo).anyTimes();
// EasyMock.replay(pluginContext);
// PowerMock.replayAll();
}
@Test
public void testBatchTransform() {
// final CountDownLatch countDownLatch = new CountDownLatch(2);
// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch));
// List<FileNode> nodeList = new ArrayList<>();
// FileNode test1 = new FileNode("path1", false);
// FileNode test2 = new FileNode("path2", false);
// nodeList.add(test1);
// nodeList.add(test2);
// transformer.batchTransform(nodeList);
// try {
// countDownLatch.await(5, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// Assert.fail();
// }
// Map<FileNode, TransformResultInfo> transformResults = transformer.getResults();
// Assert.assertEquals(2, transformResults.size());
// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test1).getResult());
// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test2).getResult());
}
@Test
public void testTransform() {
// final CountDownLatch countDownLatch = new CountDownLatch(1);
// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch));
// FileNode test = new FileNode("path", false);
// Reflect.on(transformer).call("transform", test);
// try {
// countDownLatch.await(5, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// Assert.fail();
// }
// Map<FileNode, TransformResultInfo> transformResults = transformer.getResults();
// Assert.assertEquals(1, transformResults.size());
// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult());
}
@Test
public void testShutDown() {
// final CountDownLatch countDownLatch = new CountDownLatch(1);
// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch));
// List<FileNode> nodeList = new ArrayList<>();
// FileNode test = new FileNode("path", false);
// nodeList.add(test);
// transformer.batchTransform(nodeList);
// transformer.shutDown();
// try {
// countDownLatch.await(3, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// Assert.fail();
// }
// Map<FileNode, TransformResultInfo> transformResults = transformer.getResults();
// Assert.assertEquals(1, transformResults.size());
// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult());
}
private class MockUpdateCallBack implements UpdateCallBack {
private CountDownLatch countDownLatch;
public MockUpdateCallBack(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void updateProgress(double progress) {
countDownLatch.countDown();
}
@Override
public void shutDown() {
}
@Override
public void reset() {
}
}
}

58
designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java

@ -0,0 +1,58 @@
package com.fr.nx.app.designer.utils;
import com.fr.base.FRContext;
import com.fr.base.operator.common.CommonOperator;
import com.fr.design.mainframe.JTemplate;
import com.fr.file.FILE;
import com.fr.file.filetree.FileNodes;
import com.fr.nx.app.designer.toolbar.TemplateTransformer;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
/**
* Created by kerry on 2019-12-04
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({FRContext.class})
@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"})
public class CompileTransformUtilTest {
@Test
public void testGetTargetFile() {
CommonOperator commonOperator = EasyMock.mock(CommonOperator.class);
FileNodes fileNodes = EasyMock.mock(FileNodes.class);
EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes();
PowerMock.mockStatic(FRContext.class);
EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes();
EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes();
EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes();
EasyMock.replay(commonOperator, fileNodes);
PowerMock.replayAll();
JTemplate jTemplate1 = EasyMock.mock(JTemplate.class);
FILE file1 = EasyMock.mock(FILE.class);
EasyMock.expect(jTemplate1.getEditingFILE()).andReturn(file1).anyTimes();
EasyMock.expect(file1.getPath()).andReturn("WorkBook1.cpt").anyTimes();
EasyMock.replay(jTemplate1, file1);
FILE targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPTX);
Assert.assertEquals("WorkBook1.cptx", targetFile.getPath());
targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPT);
Assert.assertEquals("WorkBook1.cpt", targetFile.getPath());
JTemplate jTemplate2 = EasyMock.mock(JTemplate.class);
FILE file2 = EasyMock.mock(FILE.class);
EasyMock.expect(jTemplate2.getEditingFILE()).andReturn(file2).anyTimes();
EasyMock.expect(file2.getPath()).andReturn("WorkBook1.cpt").anyTimes();
EasyMock.replay(jTemplate2, file2);
targetFile = CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPTX);
Assert.assertEquals("WorkBook1.cptx", targetFile.getPath());
targetFile =CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPT);
Assert.assertEquals("WorkBook1.cpt", targetFile.getPath());
}
}

2
designer-chart/src/main/java/com/fr/van/chart/map/designer/style/series/VanChartMapAnchorMarkerPane.java

@ -21,7 +21,7 @@ public class VanChartMapAnchorMarkerPane extends BasicBeanPane<VanChartAttrMarke
private UISpinner anchorSize;
public VanChartMapAnchorMarkerPane() {
anchorSize = new UISpinnerWithPx(0, Double.MAX_VALUE, 0.5, 28);
anchorSize = new UISpinnerWithPx(0, Double.MAX_VALUE, 0.5, 22);
Component[][] components = new Component[][]{
new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Height")), anchorSize}

4
designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java

@ -55,6 +55,7 @@ import com.fr.design.module.DesignModuleFactory;
import com.fr.design.parameter.ParameterDefinitePane;
import com.fr.design.parameter.ParameterInputPane;
import com.fr.design.preview.MobilePreview;
import com.fr.design.preview.PagePlusPreview;
import com.fr.design.preview.PagePreview;
import com.fr.design.preview.ViewPreview;
import com.fr.design.preview.WriteEnhancePreview;
@ -918,7 +919,7 @@ public class JWorkBook extends JTemplate<WorkBook, WorkBookUndoState> {
public PreviewProvider[] supportPreview() {
PreviewProvider[] templatePreviews = super.supportPreview();
return ArrayUtils.addAll(new PreviewProvider[]{
new PagePreview(), new WritePreview(), new ViewPreview(), new WriteEnhancePreview(), new MobilePreview()
new PagePreview(), new WritePreview(), new ViewPreview(), new WriteEnhancePreview(), new MobilePreview(), new PagePlusPreview()
}, templatePreviews);
}
@ -1194,6 +1195,7 @@ public class JWorkBook extends JTemplate<WorkBook, WorkBookUndoState> {
protected void addChooseFILEFilter(FILEChooserPane fileChooser) {
String appName = ProductConstants.APP_NAME;
fileChooser.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPT, appName + Toolkit.i18nText("Fine-Design_Report_Template_File")));
fileChooser.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPTX, appName + Toolkit.i18nText("Fine-Design_Report_Template_File")));
addExtraChooseFILEFilter(fileChooser);
}

3
designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppActivator.java

@ -4,6 +4,7 @@ import com.fr.design.mainframe.App;
import com.fr.design.mainframe.JTemplateFactory;
import com.fr.module.Activator;
import com.fr.module.extension.Prepare;
import com.fr.nx.app.designer.CptxApp;
import java.util.List;
@ -33,7 +34,7 @@ public class DesignerAppActivator extends Activator implements Prepare {
@Override
public void prepare() {
addMutable(App.KEY, new CptApp(), new FormApp(), new XlsApp(), new XlsxApp());
addMutable(App.KEY, new CptApp(), new CptxApp(), new FormApp(), new XlsApp(), new XlsxApp());
}
}

12
designer-realize/src/main/java/com/fr/design/mainframe/bbs/BBSLoginDialog.java

@ -8,11 +8,15 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ipasswordfield.UIPassWordField;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.locale.impl.BbsRegisterMark;
import com.fr.design.locale.impl.BbsResetMark;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.CloudCenter;
import com.fr.general.ComparatorUtils;
import com.fr.general.http.HttpClient;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StringUtils;
@ -65,6 +69,8 @@ public class BBSLoginDialog extends UIDialog {
private UILabel tipLabel;
private BoxCenterAligmentPane passwordReset;
private BoxCenterAligmentPane registerLabel;
private LocaleMark<String> resetMark = LocaleCenter.getMark(BbsResetMark.class);
private LocaleMark<String> registerMark = LocaleCenter.getMark(BbsRegisterMark.class);
private KeyListener keyListener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
@ -113,8 +119,8 @@ public class BBSLoginDialog extends UIDialog {
nameField = new UITextField();
passField = new UIPassWordField();
loginButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_BBSLogin_Login"));
passwordReset = getURLActionLabel(CloudCenter.getInstance().acquireUrlByKind("bbs.reset"));
registerLabel = getURLActionLabel(CloudCenter.getInstance().acquireUrlByKind("bbs.register"));
passwordReset = getURLActionLabel(resetMark.getValue());
registerLabel = getURLActionLabel(registerMark.getValue());
loginButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
@ -311,7 +317,7 @@ public class BBSLoginDialog extends UIDialog {
private BoxCenterAligmentPane getURLActionLabel(final String url) {
ActionLabel actionLabel = new ActionLabel(url);
if (ComparatorUtils.equals(url, CloudCenter.getInstance().acquireUrlByKind("bbs.reset"))) {
if (ComparatorUtils.equals(url, resetMark.getValue())) {
actionLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_BBSLogin_Forgot-Password"));
} else {
actionLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_BBSLogin_Register_Account"));

7
designer-realize/src/main/java/com/fr/design/mainframe/bbs/UserInfoLabel.java

@ -15,6 +15,7 @@ import com.fr.design.extra.WebViewDlgHelper;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.imenu.UIMenuItem;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.locale.impl.BbsSpaceMark;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.upm.event.CertificateEvent;
@ -27,6 +28,8 @@ import com.fr.general.CloudCenter;
import com.fr.general.ComparatorUtils;
import com.fr.general.DateUtils;
import com.fr.general.http.HttpClient;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StableUtils;
@ -96,8 +99,8 @@ public class UserInfoLabel extends UILabel {
public void mousePressed(MouseEvent e) {
if (StringUtils.isNotEmpty(userName)) {
try {
String loginUrl = CloudCenter.getInstance().acquireUrlByKind("bbs.default");
Desktop.getDesktop().browse(new URI(loginUrl));
LocaleMark<String> spaceMark = LocaleCenter.getMark(BbsSpaceMark.class);
Desktop.getDesktop().browse(new URI(spaceMark.getValue()));
} catch (Exception exp) {
FineLoggerFactory.getLogger().info(exp.getMessage());
}

10
designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandExtraAttrPane.java

@ -7,6 +7,7 @@ import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.ui.util.UIUtil;
import com.fr.event.EventDispatcher;
import com.fr.nx.app.designer.cell.CellTreeAttrPanelProvider;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.manage.PluginFilter;
@ -19,7 +20,10 @@ import java.awt.BorderLayout;
import java.awt.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import static com.fr.plugin.observer.PluginEventType.AfterRun;
@ -114,8 +118,9 @@ public class CellExpandExtraAttrPane extends JPanel {
extras = new ArrayList<>();
}
extras.clear();
Set<CellExpandAttrPanelProvider> attrProviders = ExtraDesignClassManager.getInstance().getArray(CellExpandAttrPanelProvider.MARK_STRING);
if (attrProviders != null) {
Set<CellExpandAttrPanelProvider> attrProviders = new LinkedHashSet<>(Collections.singletonList(new CellTreeAttrPanelProvider()));
Optional.<Set<CellExpandAttrPanelProvider>>of(ExtraDesignClassManager.getInstance().getArray(CellExpandAttrPanelProvider.MARK_STRING))
.ifPresent(attrProviders::addAll);
for (CellExpandAttrPanelProvider attrProvider : attrProviders) {
if (attrProvider.isDisplayable()) {
BasicBeanPane<TemplateCellElement> extra = attrProvider.createPanel();
@ -124,7 +129,6 @@ public class CellExpandExtraAttrPane extends JPanel {
}
}
}
}
Component[][] components = new Component[extras.size()][DEFAULT_COMPONENT_SIZE];
for (int i = 0; i < extras.size(); i++) {

53
designer-realize/src/main/java/com/fr/nx/app/designer/CptxApp.java

@ -0,0 +1,53 @@
package com.fr.nx.app.designer;
import com.fr.base.extension.FileExtension;
import com.fr.design.mainframe.AbstractAppProvider;
import com.fr.design.mainframe.JTemplate;
import com.fr.file.FILE;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.utils.DesignerCptxFileUtils;
/**
* 支持设计器打开cptx文件
*/
public class CptxApp extends AbstractAppProvider<WorkBook> {
public CptxApp() {
StartupAssist.initDesignModule();
}
@Override
public String[] defaultExtensions() {
return new String[]{FileExtension.CPTX.getExtension()};
}
@Override
public void process() {
super.process();
StartupAssist.reloadTemplate();
}
/**
* 该方法只是为了读到cptx中的cpt
*
* @param tplFile file
* @return template
*/
@Override
public JTemplate<WorkBook, ?> openTemplate(FILE tplFile) {
WorkBook workBook = DesignerCptxFileUtils.getWorkBook(tplFile);
if (workBook == null) {
workBook = new WorkBook();
}
return new JStreamBook(workBook, tplFile);
}
@Override
public WorkBook asIOFile(FILE file) {
WorkBook workBook = DesignerCptxFileUtils.getWorkBook(file);
if (workBook == null) {
workBook = new WorkBook();
}
return workBook;
}
}

117
designer-realize/src/main/java/com/fr/nx/app/designer/JStreamBook.java

@ -0,0 +1,117 @@
package com.fr.nx.app.designer;
import com.fr.base.extension.FileExtension;
import com.fr.design.actions.file.export.CSVExportAction;
import com.fr.design.actions.file.export.PDFExportAction;
import com.fr.design.actions.file.export.SVGExportAction;
import com.fr.design.actions.file.export.TextExportAction;
import com.fr.design.actions.file.export.WordExportAction;
import com.fr.design.mainframe.JWorkBook;
import com.fr.design.menu.MenuDef;
import com.fr.design.menu.ShortCut;
import com.fr.file.FILE;
import com.fr.general.ComparatorUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.utils.DesignerCptxFileUtils;
import com.fr.nx.cptx.entry.metadata.CptxMetadata;
import com.fr.nx.app.designer.menu.CalculateAttrAction;
import com.fr.nx.app.designer.toolbar.TemplateTransformer;
import com.fr.nx.app.designer.toolbar.TransformResult;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.third.jodd.util.ArraysUtil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class JStreamBook extends JWorkBook {
public JStreamBook(WorkBook workBook, FILE file) {
super(workBook, file);
}
@Override
protected boolean saveFile() {
boolean saved;
TransformResultInfo resultInfo = TemplateTransformer.compileCPTX(getTarget(), getEditingFILE());
saved = resultInfo.isSaved();
this.setSaved(saved);
if (saved) {
this.fireJTemplateSaved();
}
return saved;
}
@Override
protected boolean saveToNewFile(String oldName) {
String path = this.getEditingFILE().getPath();
try {
if (!path.startsWith(ProjectConstants.REPORTLETS_NAME)) {
File file = new File(path);
if (file.getParentFile() != null && !file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
this.getTarget().export(outputStream);
return true;
}else {
TransformResult result;
if (FileExtension.CPT.matchExtension(path)) {
result = TemplateTransformer.TO_CPT.transform(this);
} else {
result = TemplateTransformer.TO_CPTX.transform(this);
}
return ComparatorUtils.equals(TransformResult.SUCCESS, result);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
/**
* 保存文件的后缀名
*
* @return 后缀的字符串
*/
@Override
public String suffix() {
return ".cptx";
}
@Override
protected void addShortCut(MenuDef exportMenuDef, MenuDef excelExportMenuDef) {
exportMenuDef.addShortCut(excelExportMenuDef, new PDFExportAction(this), new WordExportAction(this), new SVGExportAction(this),
new CSVExportAction(this), new TextExportAction(this));
}
@Override
public String getPath() {
return getEditingFILE().getPath() + getSuffix();
}
public String getTemplateName() {
return getEditingFILE().getName() + getSuffix();
}
private String getSuffix() {
CptxMetadata metadata = DesignerCptxFileUtils.getMetadata(this.getEditingFILE());
if (metadata != null && metadata.isForceCpt()) {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Compatibility_Mode");
}
return StringUtils.EMPTY;
}
@Override
public ShortCut[] shortcut4TemplateMenu() {
return ArraysUtil.insert(super.shortcut4TemplateMenu(), new CalculateAttrAction(this), 5);
}
}

75
designer-realize/src/main/java/com/fr/nx/app/designer/StartupAssist.java

@ -0,0 +1,75 @@
package com.fr.nx.app.designer;
import com.fr.base.Parameter;
import com.fr.base.extension.FileExtension;
import com.fr.common.annotations.Negative;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.JTemplateFactory;
import com.fr.design.module.DesignModuleFactory;
import com.fr.design.parameter.AbstractParameterReader;
import com.fr.design.ui.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.cptx.CptxIOManager;
import com.fr.nx.cptx.io.handle.CptxTemplateHandle;
/**
* 保证设计器默认 cptx 启动正常
*
* @author yaohwu
* created by yaohwu at 2020/6/5 16:28
*/
public class StartupAssist {
public static void initDesignModule() {
DesignModuleFactory.registerParameterReader(new AbstractParameterReader() {
@Override
public Parameter[] readParameterFromPath(String tplPath) {
if (accept(tplPath, FileExtension.CPTX.getSuffix())) {
try {
CptxTemplateHandle handle = CptxIOManager.open(tplPath);
WorkBook book = handle.getTemplate().getLegacyWorkBook();
return book.getParameters();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return new Parameter[0];
}
}
return null;
}
});
}
private static void reload() {
JTemplate<?, ?> old = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
JTemplate<?, ?> template = JTemplateFactory.createJTemplate(old.getEditingFILE());
DesignerContext.getDesignerFrame().addAndActivateJTemplate(template);
HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(template);
}
/**
* 主代码修复后就可以删除了
*
* <a href="https://work.fineres.com/browse/REPORT-33552">主代码任务链接</>
*/
@Negative(until = "2021-09-01")
public static void reloadTemplate() {
if (isCptxJTemplate()) {
UIUtil.invokeLaterIfNeeded(() -> {
reload();
DesignerContext.getDesignerFrame().setVisible(true);
DesignerContext.getDesignerFrame().resizeFrame();
});
}
}
private static boolean isCptxJTemplate() {
JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
String path;
return jTemplate != null &&
(path = jTemplate.getPath()) != null
&& path.endsWith(FileExtension.CPTX.getExtension());
}
}

109
designer-realize/src/main/java/com/fr/nx/app/designer/cell/CellTreeAttrPanel.java

@ -0,0 +1,109 @@
package com.fr.nx.app.designer.cell;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.event.UIObserverListener;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.MultilineLabel;
import com.fr.design.mainframe.CellWidgetPropertyPane;
import com.fr.design.mainframe.ElementCasePane;
import com.fr.design.mainframe.JTemplate;
import com.fr.form.ui.Widget;
import com.fr.locale.InterProviderFactory;
import com.fr.report.cell.TemplateCellElement;
import com.fr.report.web.button.form.TreeNodeToggleButton;
import java.awt.BorderLayout;
import java.awt.Color;
/**
* @author yaohwu
* created by yaohwu at 2020/4/26 16:33
*/
public class CellTreeAttrPanel extends BasicBeanPane<TemplateCellElement> {
private static final Color TIP_COLOR = new Color(0x8f8f92);
private TemplateCellElement cellElement = null;
private final UICheckBox showAsTreeNodeCheckBox;
private final UIObserverListener listener = new UIObserverListener() {
@Override
public void doChange() {
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (template != null) {
if (CellTreeAttrPanel.this.cellElement != null) {
CellTreeAttrPanel.this.updateBean();
}
template.fireTargetModified();
CellWidgetPropertyPane.getInstance().populate((ElementCasePane<?>) template.getCurrentElementCasePane());
}
}
};
private static final class Holder {
private static final CellTreeAttrPanel INSTANCE = new CellTreeAttrPanel();
}
public static CellTreeAttrPanel getInstance() {
return Holder.INSTANCE;
}
private CellTreeAttrPanel() {
this.setLayout(new BorderLayout());
showAsTreeNodeCheckBox =
new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Cell_Show_As_Tree_Node"));
this.add(showAsTreeNodeCheckBox, BorderLayout.NORTH);
MultilineLabel multilineLabel =
new MultilineLabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Cell_Show_As_Tree_Node_TIP"));
multilineLabel.setForeground(TIP_COLOR);
this.add(multilineLabel, BorderLayout.CENTER);
}
/**
* 展示数据
*
* @param ob 待展示的对象
*/
@Override
public void populateBean(TemplateCellElement ob) {
this.cellElement = ob;
Widget widget = cellElement.getWidget();
showAsTreeNodeCheckBox.registerChangeListener(null);
showAsTreeNodeCheckBox.setSelected(widget instanceof TreeNodeToggleButton);
showAsTreeNodeCheckBox.registerChangeListener(listener);
}
/**
* 保存数据
*
* @return 待保存的对象
*/
@Override
public TemplateCellElement updateBean() {
if (this.cellElement == null) {
return null;
}
if (showAsTreeNodeCheckBox.isSelected()) {
cellElement.setWidget(createTreeToggleButton());
} else {
cellElement.setWidget(null);
}
return this.cellElement;
}
@Override
public void updateBean(TemplateCellElement ob) {
this.cellElement = ob;
updateBean();
}
@Override
protected String title4PopupWindow() {
return "";
}
private TreeNodeToggleButton createTreeToggleButton() {
return new TreeNodeToggleButton();
}
}

30
designer-realize/src/main/java/com/fr/nx/app/designer/cell/CellTreeAttrPanelProvider.java

@ -0,0 +1,30 @@
package com.fr.nx.app.designer.cell;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fun.impl.AbstractCellExpandAttrPanelProvider;
import com.fr.design.mainframe.JTemplate;
import com.fr.nx.app.designer.JStreamBook;
import com.fr.report.cell.TemplateCellElement;
/**
* @author yaohwu
* created by yaohwu at 2020/4/26 16:32
*/
public class CellTreeAttrPanelProvider extends AbstractCellExpandAttrPanelProvider {
@Override
public BasicBeanPane<TemplateCellElement> createPanel() {
return CellTreeAttrPanel.getInstance();
}
/**
* 只有新引擎 cptx 模版才展示
* 先注释掉Override适配老的主jar保留这个方法是为了在新主jar下支持这个功能
*/
// @Override
public boolean isDisplayable() {
JTemplate<?, ?> current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
return current instanceof JStreamBook;
}
}

76
designer-realize/src/main/java/com/fr/nx/app/designer/menu/CalculateAttrAction.java

@ -0,0 +1,76 @@
package com.fr.nx.app.designer.menu;
import com.fr.base.BaseUtils;
import com.fr.design.actions.JTemplateAction;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.UIDialog;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.MenuKeySet;
import com.fr.locale.InterProviderFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.JStreamBook;
import com.fr.plugin.attr.CalculatorAttrMark;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
public class CalculateAttrAction extends JTemplateAction<JStreamBook> {
public CalculateAttrAction(JStreamBook jTemplate) {
super(jTemplate);
initMenuStyle();
}
private void initMenuStyle() {
this.setMenuKeySet(CALCULATE_FIT_ATTR);
this.setName(getMenuKeySet().getMenuKeySetName() + "...");
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/bbs/center.png"));
}
/**
* Action触发事件
*
* @param e 事件
*/
public void actionPerformed(ActionEvent e) {
final JStreamBook jwb = getEditingComponent();
if (jwb == null) {
return;
}
WorkBook workBook = jwb.getTarget();
CalculatorAttrMark mark = workBook.getAttrMark(CalculatorAttrMark.MARK);
CalculateAttrPane attrPane = new CalculateAttrPane();
showReportFitDialog(mark, jwb, workBook, attrPane);
}
private void showReportFitDialog(CalculatorAttrMark mark, final JStreamBook jwb, final WorkBook workBook, final BasicBeanPane<CalculatorAttrMark> attrPane) {
attrPane.populateBean(mark);
UIDialog dialog = attrPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() {
@Override
public void doOk() {
workBook.addAttrMark(attrPane.updateBean());
jwb.fireTargetModified();
}
});
dialog.setVisible(true);
}
private static final MenuKeySet CALCULATE_FIT_ATTR = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'C';
}
@Override
public String getMenuName() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Attr");
}
@Override
public KeyStroke getKeyStroke() {
return null;
}
};
}

200
designer-realize/src/main/java/com/fr/nx/app/designer/menu/CalculateAttrPane.java

@ -0,0 +1,200 @@
package com.fr.nx.app.designer.menu;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ispinner.UISpinner;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.menu.bean.FeatureFlagBean;
import com.fr.nx.feature.FeatureFlags;
import com.fr.nx.feature.FeatureManager;
import com.fr.plugin.attr.CalculatorAttrMark;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
public class CalculateAttrPane extends BasicBeanPane<CalculatorAttrMark> {
private static final Color TIPS_FONT_COLOR = new Color(0x8f8f92);
// private UICheckBox calculateEnd;
private UICheckBox queryCache;
private UICheckBox treeAsyncQuery;
private UICheckBox multiSourceMode;
private UISpinner treeExpandLayer;
private JPanel treeConfigPanel;
/**
* 当前模版从未设置过模版计算属性
*/
private boolean isEmptyAttr = false;
public CalculateAttrPane() {
initComponents();
}
private void initComponents() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JPanel featureFlagPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
ActionLabel featureLabel = new ActionLabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Experimental_Feature"));
featureLabel.setFont(new Font(null, Font.PLAIN, 10));
featureLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JDialog wDialog = createJDialog();
wDialog.setVisible(true);
}
});
featureFlagPanel.add(featureLabel);
JPanel calculateAttrPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane();
calculateAttrPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0));
// JPanel calculatedEndPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
// calculateEnd = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Calculate-End"));
// calculatedEndPanel.add(calculateEnd);
JPanel queryCachePanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
queryCache = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Calculate_Query_Cache"));
queryCachePanel.add(queryCache);
JPanel multiSourcePanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
multiSourceMode = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Feature_Multi_Source"));
multiSourcePanel.add(multiSourceMode);
// calculateAttrPanel.add(calculatedEndPanel);
calculateAttrPanel.add(queryCachePanel);
calculateAttrPanel.add(multiSourcePanel);
treeConfigPanel = FRGUIPaneFactory.createTitledBorderPane(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Config")
);
treeConfigPanel.setVisible(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE));
treeConfigPanel.setLayout(new BoxLayout(treeConfigPanel, BoxLayout.Y_AXIS));
JPanel treeAsyncQueryPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
treeAsyncQuery = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Async_Query"));
treeAsyncQueryPanel.add(treeAsyncQuery);
JPanel treeExpandLayerPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
UILabel treeExpandLayerLabel = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Expand_Layer"));
treeExpandLayer = new UISpinner(1, Integer.MAX_VALUE, 1, 1);
// 功能不支持,设置先禁用
treeExpandLayer.setEnabled(false);
treeExpandLayerPanel.add(treeExpandLayerLabel);
treeExpandLayerPanel.add(treeExpandLayer);
JPanel treeExpandLayerLabelPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
UILabel multilineLabel = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Expand_Layer_Label"));
multilineLabel.setForeground(TIPS_FONT_COLOR);
treeExpandLayerLabelPanel.add(multilineLabel);
treeConfigPanel.add(treeAsyncQueryPanel);
treeConfigPanel.add(treeExpandLayerPanel);
treeConfigPanel.add(treeExpandLayerLabelPanel);
List<Component[]> components = new ArrayList<>();
components.add(new Component[]{featureFlagPanel});
components.add(new Component[]{calculateAttrPanel});
components.add(new Component[]{treeConfigPanel});
JPanel content =
TableLayoutHelper.createGapTableLayoutPane(
components.toArray(new Component[0][]),
TableLayoutHelper.FILL_LASTCOLUMN,
5,
5
);
this.add(content, BorderLayout.CENTER);
}
@Override
public void populateBean(CalculatorAttrMark attrMark) {
if (attrMark == null) {
isEmptyAttr = true;
// 默认折叠树配置
treeAsyncQuery.setSelected(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE_ASYNC));
return;
}
// calculateEnd.setSelected(attrMark.isCalculateEnd());
queryCache.setSelected(attrMark.isQueryCache());
treeAsyncQuery.setSelected(attrMark.isTreeAsyncQuery());
treeExpandLayer.setValue(attrMark.getTreeExpandLayer());
multiSourceMode.setSelected(attrMark.isUseMultiSourceMode());
isEmptyAttr = false;
}
/**
* 提交数据
*
* @return 界面上的更新数据
*/
@Override
public CalculatorAttrMark updateBean() {
return new CalculatorAttrMark(false, queryCache.isSelected())
.treeAsyncQuery(treeAsyncQuery.isSelected())
.treeExpandLayer((int) treeExpandLayer.getValue())
.useMultiSourceMode(multiSourceMode.isSelected());
}
/**
* 标题
*
* @return 标题
*/
@Override
protected String title4PopupWindow() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Attr");
}
private void showFeatureConfigPane() {
treeConfigPanel.setVisible(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE));
}
private void resetTreeAsyncConfigPane() {
if (isEmptyAttr) {
treeAsyncQuery.setSelected(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE_ASYNC));
}
}
private JDialog createJDialog() {
final FeatureFlagsPanel panel = new FeatureFlagsPanel();
panel.populateBean(new FeatureFlagBean());
return panel.showSmallWindow(SwingUtilities.getWindowAncestor(CalculateAttrPane.this), new DialogActionAdapter() {
@Override
public void doOk() {
panel.updateBean().saveModification();
super.doOk();
CalculateAttrPane.this.resetTreeAsyncConfigPane();
CalculateAttrPane.this.showFeatureConfigPane();
CalculateAttrPane.this.revalidate();
CalculateAttrPane.this.repaint();
}
});
}
}

73
designer-realize/src/main/java/com/fr/nx/app/designer/menu/FeatureFlagsPanel.java

@ -0,0 +1,73 @@
package com.fr.nx.app.designer.menu;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.menu.bean.FeatureFlagBean;
import com.fr.nx.feature.FeatureFlag;
import com.fr.stable.collections.combination.Pair;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created by loy on 2020/4/14.
*/
public class FeatureFlagsPanel extends BasicBeanPane<FeatureFlagBean> {
private FeatureFlagBean bean;
private JPanel mainPanel;
public FeatureFlagsPanel() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane();
mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0));
JPanel content =
TableLayoutHelper.createGapTableLayoutPane(
new Component[][]{new Component[]{mainPanel}},
TableLayoutHelper.FILL_LASTCOLUMN,
5,
5
);
this.add(content, BorderLayout.CENTER);
}
@Override
public void populateBean(FeatureFlagBean featureFlagBean) {
this.bean = featureFlagBean;
mainPanel.removeAll();
for (Pair<FeatureFlag, Boolean> entry : featureFlagBean.getAllFlags()) {
final FeatureFlag flag = entry.getFirst();
Boolean selected = entry.getSecond();
JPanel itemPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
final UICheckBox cb = new UICheckBox(flag.getDisplayName());
cb.setSelected(selected);
cb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
bean.modifyFlag(flag, cb.isSelected());
}
});
itemPanel.add(cb);
mainPanel.add(itemPanel);
}
}
@Override
public FeatureFlagBean updateBean() {
return bean;
}
@Override
protected String title4PopupWindow() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Experimental_Feature");
}
}

36
designer-realize/src/main/java/com/fr/nx/app/designer/menu/bean/FeatureFlagBean.java

@ -0,0 +1,36 @@
package com.fr.nx.app.designer.menu.bean;
import com.fr.nx.feature.FeatureFlag;
import com.fr.nx.feature.FeatureManager;
import com.fr.stable.collections.combination.Pair;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by loy on 2020/4/14.
*/
public class FeatureFlagBean {
private Map<FeatureFlag, Boolean> modifyMap = new HashMap<>();
public List<Pair<FeatureFlag, Boolean>> getAllFlags() {
List<Pair<FeatureFlag, Boolean>> flagList = new ArrayList<>();
for (FeatureFlag flag : FeatureManager.getSupportFlags()) {
flagList.add(new Pair<>(flag, FeatureManager.getInstance().isFlagEnable(flag)));
}
return flagList;
}
public void modifyFlag(FeatureFlag flag, boolean value) {
modifyMap.put(flag, value);
}
public void saveModification() {
for (Map.Entry<FeatureFlag, Boolean> entry : modifyMap.entrySet()) {
FeatureManager.getInstance().setFlagEnable(entry.getKey(), entry.getValue());
}
}
}

2
designer-realize/src/main/java/com/fr/poly/PolyBlockProperPane.java

@ -41,7 +41,7 @@ public class PolyBlockProperPane extends DockingView {
}
public void update(){
polyBlockProperTable.update();
polyBlockProperTable.setBlockName(this.designer.getEditingTarget());
}
@Override

19
designer-realize/src/main/java/com/fr/poly/PolyBlockProperTable.java

@ -111,12 +111,7 @@ public class PolyBlockProperTable extends JPanel {
if (isPopulating || block == null) {
return;
}
if (blockPropertyPane.getWidgetNameField() != null) {
String toSetWidgetName = blockPropertyPane.getWidgetNameField().getText();
if (isBlockNameValid(toSetWidgetName, block.getBlockName())) {
block.setBlockName(toSetWidgetName);
}
}
setBlockName(block);
PolyBoundsGroup boundsgroup = new PolyBoundsGroup(block, designer.getTarget());
boundsgroup.setValue(x.getValue(), 0, 1);
boundsgroup.setValue(y.getValue(), 1, 1);
@ -125,6 +120,18 @@ public class PolyBlockProperTable extends JPanel {
firePropertyEdit();
}
public void setBlockName(TemplateBlock block){
if (isPopulating || block == null || blockPropertyPane == null) {
return;
}
if (blockPropertyPane.getWidgetNameField() != null) {
String toSetWidgetName = blockPropertyPane.getWidgetNameField().getText();
if (isBlockNameValid(toSetWidgetName, block.getBlockName())) {
block.setBlockName(toSetWidgetName);
}
}
}
/**
*校验一下要设置的名称不能为空不能重名
*

2
designer-realize/src/main/java/com/fr/start/MainDesigner.java

@ -6,6 +6,7 @@ import com.fr.design.DesignerEnvManager;
import com.fr.design.actions.file.WebPreviewUtils;
import com.fr.design.actions.file.newReport.NewPolyReportAction;
import com.fr.design.actions.file.newReport.NewWorkBookAction;
import com.fr.design.actions.server.LocalAnalyzerAction;
import com.fr.design.actions.server.ServerConfigManagerAction;
import com.fr.design.actions.server.StyleListAction;
import com.fr.design.actions.server.WidgetManagerAction;
@ -165,6 +166,7 @@ public class MainDesigner extends BaseDesigner {
if (WorkContext.getCurrent().isRoot()) {
menuDef.addShortCut(new ServerConfigManagerAction(), new StyleListAction(), new WidgetManagerAction());
menuDef.addShortCut(new ChartPreStyleAction(), new ChartEmptyDataStyleAction(),new ChartMapEditorAction());
menuDef.addShortCut(new LocalAnalyzerAction());
}
insertMenu(menuDef, MenuHandler.SERVER);

54
designer-realize/src/test/java/com/fr/nx/app/designer/CptxAppTest.java

@ -0,0 +1,54 @@
package com.fr.nx.app.designer;
import com.fr.file.AbstractFILE;
import com.fr.file.FILE;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.utils.DesignerCptxFileUtils;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.runners.MethodSorters;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(JUnit4.class)
@PrepareForTest({
DesignerCptxFileUtils.class
})
public class CptxAppTest {
@Test
public void testDefaultExtensions() {
CptxApp app = new CptxApp();
String[] extendsions = app.defaultExtensions();
Assert.assertEquals("cptx", extendsions[0]);
}
@Test
public void testAsIOFile() {
PowerMock.mockStatic(DesignerCptxFileUtils.class);
FILE file = new AbstractFILE() {
};
WorkBook workBook = new WorkBook();
EasyMock.expect(DesignerCptxFileUtils.getWorkBook(file))
.andReturn(workBook).once()
.andReturn(null).once();
PowerMock.replay(DesignerCptxFileUtils.class);
Assert.assertSame(workBook, new CptxApp().asIOFile(file));
Assert.assertNotNull(new CptxApp().asIOFile(file));
PowerMock.verify(DesignerCptxFileUtils.class);
}
}

121
designer-realize/src/test/java/com/fr/nx/app/designer/JStreamBookTest.java

@ -0,0 +1,121 @@
package com.fr.nx.app.designer;
import com.fr.file.FILE;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.toolbar.TemplateTransformer;
import com.fr.nx.app.designer.toolbar.TransformResult;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest({TemplateTransformer.class, JStreamBook.class})
@PowerMockIgnore({"com.fr.license.*"})
@SuppressStaticInitializationFor({"com.fr.plugin.designer.JStreamBook"})
public class JStreamBookTest {
@Test
public void saveFile() {
PowerMock.mockStatic(TemplateTransformer.class);
final boolean[] fireSave = {false};
JStreamBook workbook =
EasyMock.partialMockBuilder(VirtualJStreamBook.class)
.addMockedMethod("fireJTemplateSaved")
.addMockedMethod("getTarget")
.addMockedMethod("getEditingFILE")
.createMock();
// 保存成功
EasyMock.expect(TemplateTransformer.compileCPTX(null, null))
.andReturn(TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "fake Unsupported").saved(true))
.once();
PowerMock.replay(TemplateTransformer.class);
workbook.fireJTemplateSaved();
EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
@Override
public Void answer() throws Throwable {
fireSave[0] = true;
return null;
}
}).once();
EasyMock.expect(workbook.getTarget()).andAnswer(new IAnswer<WorkBook>() {
@Override
public WorkBook answer() throws Throwable {
return null;
}
}).once();
EasyMock.expect(workbook.getEditingFILE()).andAnswer(new IAnswer<FILE>() {
@Override
public FILE answer() throws Throwable {
return null;
}
}).once();
EasyMock.replay(workbook);
boolean saved = workbook.saveFile();
Assert.assertTrue(saved);
Assert.assertTrue(fireSave[0]);
PowerMock.verify(TemplateTransformer.class);
EasyMock.verify(workbook);
fireSave[0] = false;
// 保存失败
PowerMock.reset(TemplateTransformer.class);
EasyMock.expect(TemplateTransformer.compileCPTX(null, null))
.andReturn(TransformResultInfo.generateResult(TransformResult.FAILED, "fake Unsupported").saved(false))
.once();
PowerMock.replay(TemplateTransformer.class);
EasyMock.reset(workbook);
EasyMock.expect(workbook.getTarget()).andAnswer(new IAnswer<WorkBook>() {
@Override
public WorkBook answer() throws Throwable {
return null;
}
}).once();
EasyMock.expect(workbook.getEditingFILE()).andAnswer(new IAnswer<FILE>() {
@Override
public FILE answer() throws Throwable {
return null;
}
}).once();
EasyMock.replay(workbook);
saved = workbook.saveFile();
Assert.assertFalse(saved);
Assert.assertFalse(fireSave[0]);
PowerMock.verify(TemplateTransformer.class);
EasyMock.verify(workbook);
}
private static final class VirtualJStreamBook extends JStreamBook {
public VirtualJStreamBook(WorkBook workBook, FILE file) {
super(workBook, file);
}
@Override
public String toString() {
return this.getClass().getName() + "fake to string";
}
}
}

79
designer-realize/src/test/resources/cpt/read-write-expand-order.cpt

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<WorkBook xmlVersion="20170720" releaseVersion="10.0.0">
<Report class="com.fr.report.worksheet.WorkSheet" name="sheet1">
<ReportPageAttr>
<HR/>
<FR/>
<HC/>
<FC/>
</ReportPageAttr>
<ColumnPrivilegeControl/>
<RowPrivilegeControl/>
<RowHeight defaultValue="723900">
<![CDATA[723900,4295838,723900,723900,723900,723900,723900,723900,723900,723900,723900]]></RowHeight>
<ColumnWidth defaultValue="2743200">
<![CDATA[6627865,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200]]></ColumnWidth>
<CellElementList>
<C c="0" r="0">
<PrivilegeControl/>
<Expand order="1"/>
</C>
<C c="1" r="0">
<O t="I">
<![CDATA[1]]></O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="0" r="1">
<O t="XMLable" class="com.fr.general.ImageWithSuffix">
<FineImage fm="png">
<IM>
<![CDATA[!T4)&qh\-E7h#eD$31&+%7s)Y;?-[s;?-[s;@!I,!!(%jK:;i@"K+gZ5u`*!m@D"-'L<GRe"
s8V+^efB0"$1Z>tC;K&-B[7`5WK?,Xelf@&8+0+s;]Ad+gFe2#R^R0KRcH9&1(_,Q&m?CF2#j
L2g`#\[sRl3^"LL;I*q<:m`bRtAnUh^m(8[R[\Qdap[PoDZI+D(a6:V.`2I<j@73SOmdDs,A
+uOS3sXroCYL"=N7$79<fLEF.)_okG>2?>R^Sd'MY!@@k@GfZiTaUt[[X*Qn(Vqi1,QX!S[g
X8cV#:o/U(RN!]A[-MCK!$>RYIs_SOW[_9PE1L2Q+u4)L'*_+9GA>FbhqkF3><ITQR#Z&\t@r
[!>rH*rsS)m6q"c>/>qr/Vjd(?R(*:-.oLG%<9eZ1]Al^J"e-:(+>+Q1NPOaSJo+/S+i4n&T%
\/J4IBcE%5,_GkC[%jH'kh$2]A+l)FI""N?9]AXFHef&/Q\Pm:q*oGRR,WL<dta:sa5g[sEC!i
2BKX\fS\?I`Sr$qqD4,Rq:A1qgre[HWS.AXA,T'5S3(`gh<4:2'QhJ%3fl9"m:'tu8Ts:@U:
VVh>M]A._;-d'aOX+8Xcia>YISk1g?.bi%E?!"e!Dq4AIRE5*J06XZ"l9<VXc0CmdGqRCY\[V
jH,m1GSaXbIcEJA8MVlg3npt"ps&Q#K6#N$Oa+4nH=;+F`U)c]A/o/l[6`,^T3Lkh5?3_]A^#?
kP/@Wf,h'#E=eI>/,[%5lSYHM*Gsc;De0X(/o,#On+F;om!UF7s$[mR(>_*`AIpT;n1NSp*r
5Md*5kOL1RpseeaT5!G,kk_1&F%\@jJs#W%4nbD$X(dC(\O+&KX.Vp>]AY-Lo<Zfr&,N4U<l3
\c3%i!rXB<7Y--5>L^V=LM7!$S/!&hR'nH_0hm_H,f=2p+p`R&".Le>"lHKmKAHnSIm69U'g
LYG,>[,VlJ&!5>PutHqRJ4XG^$7ZL6(YG+-e=+b;LUuH3Zrc58GNFlF?j1-+QXQ(%S6.V?:G
1jf/GeC6q@_Q>S5"##8tiN'(`qU.T7U?<]A'i8Uhe/g^>U%!HX@Al,.N83)TcC)q$'k_OQ-?:
_D-F="?_k3O8O[DbknE3?fn3U+EJ3:q;#Xc<us;VN0E_,#[5<%bWR/m"YJ/$/ncCA7S?[j0O
"7eDS"!*;F5*3mL`XuV$==.VthfIr!KbMS$iZjA,/%hUoiVc!Y-RGQBegW]AOdq1#1ZcM-7T7
!1]AKjAoOfF;#;YX8dknF7"f0r)k@UaJen54dIPZFo<,FG*kET--FlL!4pNhXJWUmu)gmTe=%
;EIA(U#04L!G6;`dfD5U#?b(9UAV,ZsGPK90Bb9k\<VBG[>cA+E^R:k_hA7K7g.e*(3U#a[&
%V(jo6,q3)+CL/"I32M"cKPBGLn2M%"r'=faV2lDBHCm%MHBI]AOIZj%Z*1+*FVK8J!g'*3c#
"WMR3*Y&1h_H@PEJC*H;"Y@nbp:f4UB61F[-H4phL"^(VI"gQST8h*)bt+Jo(MXVpo+u.k@X
tpaqkFs9$<?s@QH[Num^)V"=AgaN!FkbtEsHE-B`J,5!(fUS7'8jaJc~
]]></IM>
</FineImage>
</O>
<PrivilegeControl/>
<Expand/>
</C>
</CellElementList>
<ReportAttrSet>
<ReportSettings headerHeight="0" footerHeight="0">
<PaperSetting/>
<Background name="ColorBackground" color="-1"/>
</ReportSettings>
</ReportAttrSet>
<PrivilegeControl/>
</Report>
<ReportParameterAttr>
<Attributes showWindow="true" delayPlaying="true" windowPosition="1" align="0" useParamsTemplate="true"/>
<PWTitle>
<![CDATA[参数]]></PWTitle>
</ReportParameterAttr>
<StyleList/>
<DesignerVersion DesignerVersion="KAA"/>
<PreviewType PreviewType="0"/>
<TemplateIdAttMark class="com.fr.base.iofile.attr.TemplateIdAttrMark">
<TemplateIdAttMark TemplateId="2c82bd1f-e4a5-4d56-bc03-789dfd00971d"/>
</TemplateIdAttMark>
</WorkBook>

78
designer-realize/src/test/resources/cpt/read-write-image-ref.cpt

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<WorkBook xmlVersion="20170720" releaseVersion="10.0.0">
<Report class="com.fr.report.worksheet.WorkSheet" name="sheet1">
<ReportPageAttr>
<HR/>
<FR/>
<HC/>
<FC/>
</ReportPageAttr>
<ColumnPrivilegeControl/>
<RowPrivilegeControl/>
<RowHeight defaultValue="723900">
<![CDATA[723900,4295838,723900,723900,723900,723900,723900,723900,723900,723900,723900]]></RowHeight>
<ColumnWidth defaultValue="2743200">
<![CDATA[6627865,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200]]></ColumnWidth>
<CellElementList>
<C c="0" r="0">
<PrivilegeControl/>
</C>
<C c="1" r="0">
<O t="I">
<![CDATA[1]]></O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="0" r="1">
<O t="XMLable" class="com.fr.general.ImageWithSuffix">
<FineImage fm="png">
<IM>
<![CDATA[!T4)&qh\-E7h#eD$31&+%7s)Y;?-[s;?-[s;@!I,!!(%jK:;i@"K+gZ5u`*!m@D"-'L<GRe"
s8V+^efB0"$1Z>tC;K&-B[7`5WK?,Xelf@&8+0+s;]Ad+gFe2#R^R0KRcH9&1(_,Q&m?CF2#j
L2g`#\[sRl3^"LL;I*q<:m`bRtAnUh^m(8[R[\Qdap[PoDZI+D(a6:V.`2I<j@73SOmdDs,A
+uOS3sXroCYL"=N7$79<fLEF.)_okG>2?>R^Sd'MY!@@k@GfZiTaUt[[X*Qn(Vqi1,QX!S[g
X8cV#:o/U(RN!]A[-MCK!$>RYIs_SOW[_9PE1L2Q+u4)L'*_+9GA>FbhqkF3><ITQR#Z&\t@r
[!>rH*rsS)m6q"c>/>qr/Vjd(?R(*:-.oLG%<9eZ1]Al^J"e-:(+>+Q1NPOaSJo+/S+i4n&T%
\/J4IBcE%5,_GkC[%jH'kh$2]A+l)FI""N?9]AXFHef&/Q\Pm:q*oGRR,WL<dta:sa5g[sEC!i
2BKX\fS\?I`Sr$qqD4,Rq:A1qgre[HWS.AXA,T'5S3(`gh<4:2'QhJ%3fl9"m:'tu8Ts:@U:
VVh>M]A._;-d'aOX+8Xcia>YISk1g?.bi%E?!"e!Dq4AIRE5*J06XZ"l9<VXc0CmdGqRCY\[V
jH,m1GSaXbIcEJA8MVlg3npt"ps&Q#K6#N$Oa+4nH=;+F`U)c]A/o/l[6`,^T3Lkh5?3_]A^#?
kP/@Wf,h'#E=eI>/,[%5lSYHM*Gsc;De0X(/o,#On+F;om!UF7s$[mR(>_*`AIpT;n1NSp*r
5Md*5kOL1RpseeaT5!G,kk_1&F%\@jJs#W%4nbD$X(dC(\O+&KX.Vp>]AY-Lo<Zfr&,N4U<l3
\c3%i!rXB<7Y--5>L^V=LM7!$S/!&hR'nH_0hm_H,f=2p+p`R&".Le>"lHKmKAHnSIm69U'g
LYG,>[,VlJ&!5>PutHqRJ4XG^$7ZL6(YG+-e=+b;LUuH3Zrc58GNFlF?j1-+QXQ(%S6.V?:G
1jf/GeC6q@_Q>S5"##8tiN'(`qU.T7U?<]A'i8Uhe/g^>U%!HX@Al,.N83)TcC)q$'k_OQ-?:
_D-F="?_k3O8O[DbknE3?fn3U+EJ3:q;#Xc<us;VN0E_,#[5<%bWR/m"YJ/$/ncCA7S?[j0O
"7eDS"!*;F5*3mL`XuV$==.VthfIr!KbMS$iZjA,/%hUoiVc!Y-RGQBegW]AOdq1#1ZcM-7T7
!1]AKjAoOfF;#;YX8dknF7"f0r)k@UaJen54dIPZFo<,FG*kET--FlL!4pNhXJWUmu)gmTe=%
;EIA(U#04L!G6;`dfD5U#?b(9UAV,ZsGPK90Bb9k\<VBG[>cA+E^R:k_hA7K7g.e*(3U#a[&
%V(jo6,q3)+CL/"I32M"cKPBGLn2M%"r'=faV2lDBHCm%MHBI]AOIZj%Z*1+*FVK8J!g'*3c#
"WMR3*Y&1h_H@PEJC*H;"Y@nbp:f4UB61F[-H4phL"^(VI"gQST8h*)bt+Jo(MXVpo+u.k@X
tpaqkFs9$<?s@QH[Num^)V"=AgaN!FkbtEsHE-B`J,5!(fUS7'8jaJc~
]]></IM>
</FineImage>
</O>
<PrivilegeControl/>
<Expand/>
</C>
</CellElementList>
<ReportAttrSet>
<ReportSettings headerHeight="0" footerHeight="0">
<PaperSetting/>
<Background name="ColorBackground" color="-1"/>
</ReportSettings>
</ReportAttrSet>
<PrivilegeControl/>
</Report>
<ReportParameterAttr>
<Attributes showWindow="true" delayPlaying="true" windowPosition="1" align="0" useParamsTemplate="true"/>
<PWTitle>
<![CDATA[参数]]></PWTitle>
</ReportParameterAttr>
<StyleList/>
<DesignerVersion DesignerVersion="KAA"/>
<PreviewType PreviewType="0"/>
<TemplateIdAttMark class="com.fr.base.iofile.attr.TemplateIdAttrMark">
<TemplateIdAttMark TemplateId="2c82bd1f-e4a5-4d56-bc03-789dfd00971d"/>
</TemplateIdAttMark>
</WorkBook>
Loading…
Cancel
Save