Browse Source

Merge branch 'feature-replace-view' into dev

# Conflicts:
#	pom.xml
sunyj 7 years ago
parent
commit
282c5c6d45
38 changed files with 778 additions and 465 deletions
  1. 0 1
      .gitignore
  2. 10 0
      crystal-replace-view/README.md
  3. BIN
      crystal-replace-view/lib/com/azalea/ufl/barcode/1.0.0/barcode-1.0.0.jar
  4. 7 0
      crystal-replace-view/lib/com/azalea/ufl/barcode/1.0.0/barcode-1.0.0.pom
  5. BIN
      crystal-replace-view/lib/com/businessobjects/foundation/logging/1.0.0/logging-1.0.0.jar
  6. 7 0
      crystal-replace-view/lib/com/businessobjects/foundation/logging/1.0.0/logging-1.0.0.pom
  7. BIN
      crystal-replace-view/lib/com/businessobjects/reports/JDBInterface/1.0.0/JDBInterface-1.0.0.jar
  8. 7 0
      crystal-replace-view/lib/com/businessobjects/reports/JDBInterface/1.0.0/JDBInterface-1.0.0.pom
  9. BIN
      crystal-replace-view/lib/com/crystaldecisions/CrystalCommon2/1.0.0/CrystalCommon2-1.0.0.jar
  10. 7 0
      crystal-replace-view/lib/com/crystaldecisions/CrystalCommon2/1.0.0/CrystalCommon2-1.0.0.pom
  11. BIN
      crystal-replace-view/lib/com/crystaldecisions/CrystalReportsRuntime/1.0.0/CrystalReportsRuntime-1.0.0.jar
  12. 7 0
      crystal-replace-view/lib/com/crystaldecisions/CrystalReportsRuntime/1.0.0/CrystalReportsRuntime-1.0.0.pom
  13. BIN
      crystal-replace-view/lib/com/crystaldecisions/DatabaseConnectors/1.0.0/DatabaseConnectors-1.0.0.jar
  14. 7 0
      crystal-replace-view/lib/com/crystaldecisions/DatabaseConnectors/1.0.0/DatabaseConnectors-1.0.0.pom
  15. BIN
      crystal-replace-view/lib/com/crystaldecisions/keycodeDecoder/1.0.0/keycodeDecoder-1.0.0.jar
  16. 7 0
      crystal-replace-view/lib/com/crystaldecisions/keycodeDecoder/1.0.0/keycodeDecoder-1.0.0.pom
  17. 106 0
      crystal-replace-view/pom.xml
  18. 159 0
      crystal-replace-view/src/main/java/com/uas/report/crystal/CrystalReplaceView.java
  19. 45 0
      crystal-replace-view/src/main/resources/logback.xml
  20. 21 0
      crystal-replace-view/src/test/java/com/uas/report/crystal/CrystalReplaceViewTest.java
  21. BIN
      crystal-replace-view/src/test/resources/out/bjd_price.rpt
  22. BIN
      crystal-replace-view/src/test/resources/rpts/BankLestMoney_E_Shine_DigitGroup.rpt
  23. BIN
      crystal-replace-view/src/test/resources/rpts/PROFITCUSTOMER_E_Shine_DigitGroup.rpt
  24. BIN
      crystal-replace-view/src/test/resources/rpts/PROFITChampion_Eshine_Group.rpt
  25. BIN
      crystal-replace-view/src/test/resources/rpts/PROFITTOTAL_E_Shine_DigitGroup.rpt
  26. BIN
      crystal-replace-view/src/test/resources/rpts/PURCLIST.rpt
  27. BIN
      crystal-replace-view/src/test/resources/rpts/ProductwhSystem_E_Shine_DigitGroup.rpt
  28. BIN
      crystal-replace-view/src/test/resources/rpts/bjd_price.rpt
  29. BIN
      crystal-replace-view/src/test/resources/rpts/overdate_arbill_customer_group.rpt
  30. BIN
      crystal-replace-view/src/test/resources/rpts/overdate_arbill_depart_group.rpt
  31. BIN
      crystal-replace-view/src/test/resources/rpts/profitdetail_eshinegroup.rpt
  32. BIN
      crystal-replace-view/src/test/resources/rpts/profitsyb_sum_e_shine_digitgroup.rpt
  33. 4 8
      crystal2jasper/src/main/java/com/uas/report/crystal2jasper/CrystalToJasper.java
  34. 14 1
      pom.xml
  35. 5 0
      report-common/pom.xml
  36. 365 59
      report-common/src/main/java/com/uas/report/util/ObjectUtils.java
  37. 0 4
      report/pom.xml
  38. 0 392
      report/src/main/java/com/uas/report/util/ObjectUtils.java

+ 0 - 1
.gitignore

@@ -24,7 +24,6 @@
 .mtj.tmp/
 .mtj.tmp/
 
 
 # Package Files #
 # Package Files #
-*.jar
 *.war
 *.war
 *.ear
 *.ear
 *.zip
 *.zip

+ 10 - 0
crystal-replace-view/README.md

@@ -0,0 +1,10 @@
+## 运行方式
+`
+java -jar target/crystal-replace-view-0.0.1.jar src/test/resources/rpts HUASL_
+`
+## 参数说明
+| 选项 | 说明 |
+| - | - |
+| target/crystal-replace-view-0.0.1.jar | 程序主体 | 必填 |
+| src/test/resources/rpts | 水晶报表相对路径(文件或文件夹) | 是 |
+| HUASL_ | 前缀 | 是 |

BIN
crystal-replace-view/lib/com/azalea/ufl/barcode/1.0.0/barcode-1.0.0.jar


+ 7 - 0
crystal-replace-view/lib/com/azalea/ufl/barcode/1.0.0/barcode-1.0.0.pom

@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.azalea.ufl</groupId>
+    <artifactId>barcode</artifactId>
+    <version>1.0.0</version>
+</project>

BIN
crystal-replace-view/lib/com/businessobjects/foundation/logging/1.0.0/logging-1.0.0.jar


+ 7 - 0
crystal-replace-view/lib/com/businessobjects/foundation/logging/1.0.0/logging-1.0.0.pom

@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.businessobjects.foundation</groupId>
+    <artifactId>logging</artifactId>
+    <version>1.0.0</version>
+</project>

BIN
crystal-replace-view/lib/com/businessobjects/reports/JDBInterface/1.0.0/JDBInterface-1.0.0.jar


+ 7 - 0
crystal-replace-view/lib/com/businessobjects/reports/JDBInterface/1.0.0/JDBInterface-1.0.0.pom

@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.businessobjects.reports</groupId>
+    <artifactId>JDBInterface</artifactId>
+    <version>1.0.0</version>
+</project>

BIN
crystal-replace-view/lib/com/crystaldecisions/CrystalCommon2/1.0.0/CrystalCommon2-1.0.0.jar


+ 7 - 0
crystal-replace-view/lib/com/crystaldecisions/CrystalCommon2/1.0.0/CrystalCommon2-1.0.0.pom

@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.crystaldecisions</groupId>
+    <artifactId>CrystalCommon2</artifactId>
+    <version>1.0.0</version>
+</project>

BIN
crystal-replace-view/lib/com/crystaldecisions/CrystalReportsRuntime/1.0.0/CrystalReportsRuntime-1.0.0.jar


+ 7 - 0
crystal-replace-view/lib/com/crystaldecisions/CrystalReportsRuntime/1.0.0/CrystalReportsRuntime-1.0.0.pom

@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.crystaldecisions</groupId>
+    <artifactId>CrystalReportsRuntime</artifactId>
+    <version>1.0.0</version>
+</project>

BIN
crystal-replace-view/lib/com/crystaldecisions/DatabaseConnectors/1.0.0/DatabaseConnectors-1.0.0.jar


+ 7 - 0
crystal-replace-view/lib/com/crystaldecisions/DatabaseConnectors/1.0.0/DatabaseConnectors-1.0.0.pom

@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.crystaldecisions</groupId>
+    <artifactId>DatabaseConnectors</artifactId>
+    <version>1.0.0</version>
+</project>

BIN
crystal-replace-view/lib/com/crystaldecisions/keycodeDecoder/1.0.0/keycodeDecoder-1.0.0.jar


+ 7 - 0
crystal-replace-view/lib/com/crystaldecisions/keycodeDecoder/1.0.0/keycodeDecoder-1.0.0.pom

@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.crystaldecisions</groupId>
+    <artifactId>keycodeDecoder</artifactId>
+    <version>1.0.0</version>
+</project>

+ 106 - 0
crystal-replace-view/pom.xml

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>report-parent</artifactId>
+        <groupId>com.uas.report</groupId>
+        <version>0.0.1</version>
+    </parent>
+    <artifactId>crystal-replace-view</artifactId>
+    <packaging>jar</packaging>
+
+    <repositories>
+        <repository>
+            <id>lib</id>
+            <url>file://${project.basedir}/lib</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.uas.report</groupId>
+            <artifactId>report-common</artifactId>
+        </dependency>
+
+        <!-- crystal reports dependencies -->
+        <dependency>
+            <groupId>com.crystaldecisions</groupId>
+            <artifactId>CrystalReportsRuntime</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.crystaldecisions</groupId>
+            <artifactId>CrystalCommon2</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.crystaldecisions</groupId>
+            <artifactId>DatabaseConnectors</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.businessobjects.foundation</groupId>
+            <artifactId>logging</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.crystaldecisions</groupId>
+            <artifactId>keycodeDecoder</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.businessobjects.reports</groupId>
+            <artifactId>JDBInterface</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-configuration</groupId>
+            <artifactId>commons-configuration</artifactId>
+            <version>1.10</version>
+        </dependency>
+        <dependency>
+            <groupId>com.ibm.icu</groupId>
+            <artifactId>icu4j</artifactId>
+            <version>60.2</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.2.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.azalea.ufl</groupId>
+            <artifactId>barcode</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.lowagie</groupId>
+            <artifactId>itext</artifactId>
+            <version>2.1.7.js5</version>
+        </dependency>
+        <dependency>
+            <groupId>com.oracle</groupId>
+            <artifactId>ojdbc6</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 159 - 0
crystal-replace-view/src/main/java/com/uas/report/crystal/CrystalReplaceView.java

@@ -0,0 +1,159 @@
+package com.uas.report.crystal;
+
+import com.crystaldecisions.sdk.occa.report.application.DatabaseController;
+import com.crystaldecisions.sdk.occa.report.application.OpenReportOptions;
+import com.crystaldecisions.sdk.occa.report.application.ReportClientDocument;
+import com.crystaldecisions.sdk.occa.report.application.ReportSaveAsOptions;
+import com.crystaldecisions.sdk.occa.report.data.IDatabase;
+import com.crystaldecisions.sdk.occa.report.data.ITable;
+import com.crystaldecisions.sdk.occa.report.data.Tables;
+import com.crystaldecisions.sdk.occa.report.lib.ReportSDKException;
+import com.uas.report.util.ArrayUtils;
+import com.uas.report.util.FileUtils;
+import com.uas.report.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+
+/**
+ * 在报表的视图名称前添加前缀
+ *
+ * @author sunyj
+ * @since 2017/12/22 10:42
+ */
+public class CrystalReplaceView {
+    private static Logger logger = LoggerFactory.getLogger(CrystalReplaceView.class);
+
+    public static void main(String[] args) {
+        int length = args != null ? args.length : 0;
+        if (length < 2) {
+            logger.error("参数缺失\neg. java -jar target/crystal-replace-view-0.0.1.jar src/test/resources/rpts HUASL_");
+            return;
+        }
+        // 命令行接收两个参数:报表路径、需添加的前缀
+        File src = new File(args[0]);
+        String prefix = args[1];
+        try {
+            CrystalReplaceView.replaceReports(src, prefix);
+        } catch (IOException e) {
+            logger.error("替换失败", e);
+        }
+    }
+
+    /**
+     * 替换报表的视图名称
+     *
+     * @param src    报表文件(夹)
+     * @param prefix 需添加的视图前缀
+     * @throws IOException
+     */
+    public static void replaceReports(File src, String prefix) throws IOException {
+        logger.info("start...");
+        if (src == null || StringUtils.isEmpty(prefix)) {
+            throw new IllegalArgumentException("需指定参数 src, prefix");
+        }
+        FileUtils.checkFile(src);
+        if (src.isDirectory()) {
+            replaceReports(src, new File(src, "success"), prefix);
+        } else {
+            replaceReport(src, new File(src.getParentFile(), "success"), prefix);
+        }
+        logger.info("completed...");
+    }
+
+    /**
+     * 替换指定文件夹下报表的视图名称
+     *
+     * @param reportDir  报表文件夹
+     * @param successDir 报表替换成功后,新报表的路径
+     * @param prefix     需添加的视图前缀
+     * @throws IOException
+     */
+    private static void replaceReports(File reportDir, File successDir, String prefix) throws IOException {
+        FileUtils.checkDir(reportDir);
+        File[] files = reportDir.listFiles(new FileFilter() {
+            @Override
+            public boolean accept(File file) {
+                if (file == null || !file.exists()) {
+                    return false;
+                }
+                // success路径下的文件不进行转换
+                String filePath = file.getAbsolutePath();
+                if (filePath.endsWith("success") || filePath.contains("\\success\\")
+                        || filePath.contains("/success/")) {
+                    return false;
+                }
+                // 文件必须是 rpt 格式
+                return !file.isFile() || filePath.endsWith(".rpt");
+            }
+        });
+        if (ArrayUtils.isEmpty(files)) {
+            return;
+        }
+        for (File file : files) {
+            try {
+                String fileName = file.getName();
+                // 是文件夹的话,递归处理
+                if (file.isDirectory()) {
+                    // 不可直接修改 successDir,否则会造成其他文件的路径有问题
+                    File successDirCopy = new File(successDir, fileName);
+                    replaceReports(file, successDirCopy, prefix);
+                } else {
+                    replaceReport(file, successDir, prefix);
+                }
+            } catch (Throwable e) {
+                logger.error(file.getName(), e);
+            }
+        }
+    }
+
+    /**
+     * 替换单个报表的视图名称
+     *
+     * @param reportFile 报表文件
+     * @param successDir 报表替换成功后,新报表的路径
+     * @param prefix     需添加的视图前缀
+     * @throws IOException
+     */
+    private static void replaceReport(File reportFile, File successDir, String prefix) throws IOException {
+        logger.info("replacing... " + reportFile.getName());
+        FileUtils.initDir(successDir);
+        ReportClientDocument client = new ReportClientDocument();
+        try {
+            // 打开报表
+            client.setReportAppServer(ReportClientDocument.inprocConnectionString);
+            client.open(reportFile.getPath(), OpenReportOptions._retrieveNoReportDefinition);
+            DatabaseController databaseController = client.getDatabaseController();
+            IDatabase database = databaseController.getDatabase();
+            Tables tables = database.getTables();
+            for (ITable iTable : tables) {
+                String alias = iTable.getAlias();
+                // 只替换以 '_VIEW' 结尾的视图,不替换表
+                if (alias.toUpperCase().endsWith("_VIEW")) {
+                    logger.info("replacing table: name=" + iTable.getName() + ", alias=" + alias);
+                    // 修改视图名称
+                    databaseController.modifyTableAlias(iTable, prefix + alias);
+                }
+            }
+
+            client.saveAs(reportFile.getName(), successDir.getAbsolutePath(), ReportSaveAsOptions._overwriteExisting);
+            if (!reportFile.delete()) {
+                logger.info("文件删除失败:" + reportFile);
+            }
+            System.out.println();
+        } catch (ReportSDKException e) {
+            logger.error("报表读取失败", e);
+        } catch (IOException e) {
+            logger.error("报表写入失败", e);
+        } finally {
+            try {
+                client.close();
+            } catch (ReportSDKException e) {
+                throw new IllegalStateException("报表关闭失败:", e);
+            }
+        }
+    }
+}

+ 45 - 0
crystal-replace-view/src/main/resources/logback.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <appender name="FILE"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <File>logs/log.log</File>
+        <encoder>
+            <pattern>
+                %date{yyyy-MM-dd HH:mm:ss:SSS} [%relative ms] %-5level [%50.50(%logger{36}.%method:%line)] ---- %msg%n
+            </pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- daily rollover -->
+            <FileNamePattern>logs/log.%d{yyyy-MM-dd}.log</FileNamePattern>
+            <!-- keep 10 days' worth of history -->
+            <maxHistory>10</maxHistory>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+    </appender>
+
+    <!-- Console output -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
+        <encoder>
+            <pattern>
+                %date{yyyy-MM-dd HH:mm:ss:SSS} [%relative ms] %-5level [%50.50(%logger{36}.%method:%line)] ---- %msg%n
+            </pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- Only log level WARN and above -->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+    </appender>
+
+    <!-- Enable FILE and STDOUT appenders for all log messages. By default,
+        only log at level INFO and above. -->
+    <root level="ERROR">
+        <appender-ref ref="FILE"/>
+        <appender-ref ref="STDOUT"/>
+    </root>
+    <logger name="com.uas" level="INFO"/>
+</configuration>

+ 21 - 0
crystal-replace-view/src/test/java/com/uas/report/crystal/CrystalReplaceViewTest.java

@@ -0,0 +1,21 @@
+package com.uas.report.crystal;
+
+import com.uas.report.util.ResourceUtils;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author sunyj
+ * @since 2017/12/29 18:04
+ */
+public class CrystalReplaceViewTest {
+
+    @Test
+    public void test() throws IOException {
+        File src = ResourceUtils.getFile("rpts");
+        String prefix = "YITOA_";
+        CrystalReplaceView.replaceReports(src, prefix);
+    }
+}

BIN
crystal-replace-view/src/test/resources/out/bjd_price.rpt


BIN
crystal-replace-view/src/test/resources/rpts/BankLestMoney_E_Shine_DigitGroup.rpt


BIN
crystal-replace-view/src/test/resources/rpts/PROFITCUSTOMER_E_Shine_DigitGroup.rpt


BIN
crystal-replace-view/src/test/resources/rpts/PROFITChampion_Eshine_Group.rpt


BIN
crystal-replace-view/src/test/resources/rpts/PROFITTOTAL_E_Shine_DigitGroup.rpt


BIN
crystal-replace-view/src/test/resources/rpts/PURCLIST.rpt


BIN
crystal-replace-view/src/test/resources/rpts/ProductwhSystem_E_Shine_DigitGroup.rpt


BIN
crystal-replace-view/src/test/resources/rpts/bjd_price.rpt


BIN
crystal-replace-view/src/test/resources/rpts/overdate_arbill_customer_group.rpt


BIN
crystal-replace-view/src/test/resources/rpts/overdate_arbill_depart_group.rpt


BIN
crystal-replace-view/src/test/resources/rpts/profitdetail_eshinegroup.rpt


BIN
crystal-replace-view/src/test/resources/rpts/profitsyb_sum_e_shine_digitgroup.rpt


+ 4 - 8
crystal2jasper/src/main/java/com/uas/report/crystal2jasper/CrystalToJasper.java

@@ -24,20 +24,16 @@ public class CrystalToJasper {
 
 
 	public static void main(String[] args) throws IOException, DocumentException, TransformerException {
 	public static void main(String[] args) throws IOException, DocumentException, TransformerException {
 		int length = args != null ? args.length : 0;
 		int length = args != null ? args.length : 0;
-        File rptZipFile = null;
-        File outDir = null;
+        File rptZipFile;
+        File outDir;
         File styleFile = ResourceUtils.getFile("crystal2jasper.xsl");
         File styleFile = ResourceUtils.getFile("crystal2jasper.xsl");
         boolean remainHierarchy = false;
         boolean remainHierarchy = false;
         if(length < 2){
         if(length < 2){
             logger.error("参数缺失\neg. java -jar target/crystal2jasper-0.0.1.jar src/test/resources/formatted-rpts src/test/resources/out src/main/resources/crystal2jasper.xsl false");
             logger.error("参数缺失\neg. java -jar target/crystal2jasper-0.0.1.jar src/test/resources/formatted-rpts src/test/resources/out src/main/resources/crystal2jasper.xsl false");
             return;
             return;
         }
         }
-		if (length >= 1) {
-			rptZipFile = new File(args[0]);
-		}
-		if (length >= 2) {
-			outDir = new File(args[1]);
-		}
+        rptZipFile = new File(args[0]);
+        outDir = new File(args[1]);
 		if (length >= 3) {
 		if (length >= 3) {
 			styleFile = new File(args[2]);
 			styleFile = new File(args[2]);
 		}
 		}

+ 14 - 1
pom.xml

@@ -12,23 +12,36 @@
     <version>0.0.1</version>
     <version>0.0.1</version>
 
 
     <modules>
     <modules>
-        <module>report</module>
         <module>report-common</module>
         <module>report-common</module>
+        <module>report</module>
         <module>crystal2jasper</module>
         <module>crystal2jasper</module>
+        <module>crystal-replace-view</module>
     </modules>
     </modules>
 
 
     <properties>
     <properties>
+        <oracle.jdbc.version>11.2.0</oracle.jdbc.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <report.common.version>0.0.1</report.common.version>
         <report.common.version>0.0.1</report.common.version>
+        <fastjson.version>1.2.15</fastjson.version>
     </properties>
     </properties>
 
 
     <dependencyManagement>
     <dependencyManagement>
         <dependencies>
         <dependencies>
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
             <dependency>
             <dependency>
                 <groupId>com.uas.report</groupId>
                 <groupId>com.uas.report</groupId>
                 <artifactId>report-common</artifactId>
                 <artifactId>report-common</artifactId>
                 <version>${report.common.version}</version>
                 <version>${report.common.version}</version>
             </dependency>
             </dependency>
+            <dependency>
+                <groupId>com.oracle</groupId>
+                <artifactId>ojdbc6</artifactId>
+                <version>${oracle.jdbc.version}</version>
+            </dependency>
         </dependencies>
         </dependencies>
     </dependencyManagement>
     </dependencyManagement>
 
 

+ 5 - 0
report-common/pom.xml

@@ -14,5 +14,10 @@
             <groupId>ch.qos.logback</groupId>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
             <artifactId>logback-classic</artifactId>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
     </dependencies>
 </project>
 </project>

+ 365 - 59
report-common/src/main/java/com/uas/report/util/ObjectUtils.java

@@ -1,8 +1,13 @@
 package com.uas.report.util;
 package com.uas.report.util;
 
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.*;
+import java.util.Map.Entry;
 
 
 /**
 /**
  * 对象工具类
  * 对象工具类
@@ -12,75 +17,376 @@ import java.util.Map;
  */
  */
 public class ObjectUtils {
 public class ObjectUtils {
 
 
+	/**
+	 * 判断是否为 null、空数组、空串或者空集合
+	 *
+	 * @param obj
+	 *            对象
+	 * @return 是否为 null、空数组、空串或者空集合
+	 */
+	public static boolean isEmpty(Object obj) {
+		if (obj == null) {
+			return true;
+		}
+		if (obj.getClass().isArray()) {
+			if (obj instanceof long[]) {
+				return ArrayUtils.isEmpty((long[]) obj);
+			} else if (obj instanceof int[]) {
+				return ArrayUtils.isEmpty((int[]) obj);
+			} else if (obj instanceof short[]) {
+				return ArrayUtils.isEmpty((short[]) obj);
+			} else if (obj instanceof byte[]) {
+				return ArrayUtils.isEmpty((byte[]) obj);
+			} else if (obj instanceof char[]) {
+				return ArrayUtils.isEmpty((char[]) obj);
+			} else if (obj instanceof boolean[]) {
+				return ArrayUtils.isEmpty((boolean[]) obj);
+			} else if (obj instanceof float[]) {
+				return ArrayUtils.isEmpty((float[]) obj);
+			} else if (obj instanceof double[]) {
+				return ArrayUtils.isEmpty((double[]) obj);
+			}
+			return ArrayUtils.isEmpty((Object[]) obj);
+		}
+		return (obj instanceof String && StringUtils.isEmpty(obj))
+				|| (obj instanceof Collection && CollectionUtils.isEmpty((Collection<?>) obj))
+				|| (obj instanceof Map && CollectionUtils.isEmpty((Map<?, ?>) obj));
+	}
+
+	/**
+	 * 将对象转为 String
+	 *
+	 * @param obj
+	 *            对象
+	 * @return 转换的 String
+	 */
+	public static String toString(Object obj) {
+		if (obj == null) {
+			return "";
+		}
+		if (obj instanceof String) {
+			return (String) obj;
+		}
+		if (obj.getClass().isArray()) {
+			if (obj instanceof long[]) {
+				return Arrays.toString((long[]) obj);
+			} else if (obj instanceof int[]) {
+				return Arrays.toString((int[]) obj);
+			} else if (obj instanceof short[]) {
+				return Arrays.toString((short[]) obj);
+			} else if (obj instanceof byte[]) {
+				return Arrays.toString((byte[]) obj);
+			} else if (obj instanceof char[]) {
+				return Arrays.toString((char[]) obj);
+			} else if (obj instanceof boolean[]) {
+				return Arrays.toString((boolean[]) obj);
+			} else if (obj instanceof float[]) {
+				return Arrays.toString((float[]) obj);
+			} else if (obj instanceof double[]) {
+				return Arrays.toString((double[]) obj);
+			}
+			return Arrays.toString((Object[]) obj);
+		}
+		return obj.toString();
+	}
+
+	/**
+	 * 深克隆对象
+	 *
+	 * @param t
+	 *            要克隆的对象
+	 * @return 克隆得到的对象
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T extends Serializable> T clone(T t)
+			throws IOException, ClassNotFoundException, NotSerializableException {
+		if (t == null) {
+			return null;
+		}
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		new ObjectOutputStream(out).writeObject(t);
+		ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+		return (T) in.readObject();
+	}
+
+	/**
+	 * 深克隆集合对象
+	 *
+	 * @param collection
+	 *            要克隆的对象
+	 * @return 克隆得到的对象
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> Collection<T> clone(Collection<T> collection) throws InstantiationException,
+			IllegalAccessException, NotSerializableException, ClassNotFoundException, IOException {
+		if (collection == null) {
+			return null;
+		}
+		Collection<T> result = collection.getClass().newInstance();
+		for (T t : collection) {
+			if (t instanceof Serializable) {
+				result.add((T) clone((Serializable) t));
+			} else if (t instanceof Collection) {
+				result.add((T) clone((Collection<?>) t));
+			} else if (t instanceof Map) {
+				result.add((T) clone((Map<String, ?>) t));
+			} else {
+				throw new IllegalArgumentException("未实现 Serializable 接口");
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 深克隆 Map 对象
+	 *
+	 * @param map
+	 *            要克隆的对象
+	 * @return 克隆得到的对象
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> Map<String, T> clone(Map<String, T> map) throws InstantiationException, IllegalAccessException,
+			NotSerializableException, ClassNotFoundException, IOException {
+		if (map == null) {
+			return null;
+		}
+		Map<String, T> result = map.getClass().newInstance();
+		Set<Entry<String, T>> entrySet = map.entrySet();
+		for (Entry<String, T> entry : entrySet) {
+			T value = entry.getValue();
+			if (value instanceof Serializable) {
+				result.put(entry.getKey(), (T) clone((Serializable) value));
+			} else if (value instanceof Collection) {
+				result.put(entry.getKey(), (T) clone((Collection<?>) value));
+			} else if (value instanceof Map) {
+				result.put(entry.getKey(), (T) clone((Map<String, ?>) value));
+			} else {
+				throw new IllegalArgumentException("未实现 Serializable 接口");
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * JSONArray 转为指定类型的 List
+	 *
+	 * @param array
+	 *            JSONArray
+	 * @param clazz
+	 *            指定的类型
+	 * @param <T>
+	 *            指定的类型
+	 * @return 指定类型的 List
+	 */
+	public static <T> List<T> toList(JSONArray array, Class<T> clazz) {
+		if (array == null) {
+			return null;
+		}
+		List<T> list = new ArrayList<>();
+		for (int i = 0; i < array.size(); i++) {
+			list.add(array.getObject(i, clazz));
+		}
+		return list;
+	}
+
+	/**
+	 * 利用反射获取指定对象的指定字段的值
+	 *
+	 * @param field
+	 *            指定字段
+	 * @param k
+	 *            指定对象
+	 * @return 指定字段的值
+	 */
+	public static <K> Object getValue(Field field, K k) throws IllegalStateException {
+		Object value;
+		try {
+			if (!field.isAccessible()) {
+				field.setAccessible(true);
+				value = field.get(k);
+				field.setAccessible(false);
+			} else {
+				value = field.get(k);
+			}
+		} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
+			throw new IllegalStateException("通过反射取值失败", e);
+		}
+		return value;
+	}
+
+	/**
+	 * 利用反射递归获取指定对象的指定字段的值
+	 *
+	 * @param field
+	 *            指定字段
+	 * @param k
+	 *            指定对象
+	 * @return 指定字段的值
+	 */
+	public static <K> Object recursivelyGetValue(String field, K k) {
+		return getValue(recursivelyGetField(field, k.getClass()), k);
+	}
+
+	/**
+	 * 递归获取指定类的指定字段(包括父类的私有字段)
+	 *
+	 * @param field
+	 *            指定字段
+	 * @param clazz
+	 *            指定类
+	 * @return 指定字段
+	 * @throws IllegalArgumentException
+	 */
+	public static Field recursivelyGetField(String field, Class<?> clazz) throws IllegalArgumentException {
+		try {
+			return clazz.getDeclaredField(field);
+		} catch (NoSuchFieldException e) {
+			Class<?> superclass = clazz.getSuperclass();
+			if (superclass != null) {
+				return recursivelyGetField(field, superclass);
+			}
+			throw new IllegalArgumentException(clazz + "中不存在字段:" + field);
+		}
+	}
+
+	/**
+	 * 获取指定类的指定字段
+	 *
+	 * @param field
+	 *            指定字段
+	 * @param clazz
+	 *            指定类
+	 * @return 指定字段
+	 * @throws IllegalArgumentException
+	 */
+	public static Field getField(String field, Class<?> clazz) throws IllegalArgumentException {
+		try {
+			return clazz.getDeclaredField(field);
+		} catch (NoSuchFieldException e) {
+			throw new IllegalArgumentException(clazz + "中不存在字段:" + field);
+		}
+	}
+
+	/**
+	 * 递归获取父类(包括私有字段)的所有字段
+	 *
+	 * @param clazz
+	 *            指定类
+	 * @return 所有字段
+	 */
+	public static List<Field> recursivelyGetParentField(Class<?> clazz) {
+		List<Field> fields = new ArrayList<>();
+		Class<?> superclass = clazz.getSuperclass();
+		if (superclass != null) {
+			fields.addAll(recursivelyGetField(superclass));
+		}
+		return fields;
+	}
+
+	/**
+	 * 递归获取所有字段(包括父类的私有字段)
+	 *
+	 * @param clazz
+	 *            指定类
+	 * @return 所有字段
+	 */
+	private static List<Field> recursivelyGetField(Class<?> clazz) {
+		List<Field> fields = new ArrayList<>();
+		Field[] declaredFields = clazz.getDeclaredFields();
+		if (!ArrayUtils.isEmpty(declaredFields)) {
+			fields.addAll(Arrays.asList(declaredFields));
+		}
+		Class<?> superclass = clazz.getSuperclass();
+		if (superclass != null) {
+			fields.addAll(recursivelyGetField(superclass));
+		}
+		return fields;
+	}
+
     /**
     /**
-     * 判断是否为 null、空数组、空串或者空集合
+     * 通过反射为指定的字段赋值
      *
      *
-     * @param obj 对象
-     * @return 是否为 null、空数组、空串或者空集合
+     * @param object 对象
+     * @param field  字段
+     * @param value  值
+     * @throws IllegalAccessException
      */
      */
-    public static boolean isEmpty(Object obj) {
-        if (obj == null) {
-            return true;
+    public static void setValue(Object object, Field field, Object value) throws IllegalAccessException {
+        if (object == null || field == null) {
+            throw new IllegalArgumentException("object 或 field 为空");
         }
         }
-        if (obj.getClass().isArray()) {
-            if (obj instanceof long[]) {
-                return ArrayUtils.isEmpty((long[]) obj);
-            } else if (obj instanceof int[]) {
-                return ArrayUtils.isEmpty((int[]) obj);
-            } else if (obj instanceof short[]) {
-                return ArrayUtils.isEmpty((short[]) obj);
-            } else if (obj instanceof byte[]) {
-                return ArrayUtils.isEmpty((byte[]) obj);
-            } else if (obj instanceof char[]) {
-                return ArrayUtils.isEmpty((char[]) obj);
-            } else if (obj instanceof boolean[]) {
-                return ArrayUtils.isEmpty((boolean[]) obj);
-            } else if (obj instanceof float[]) {
-                return ArrayUtils.isEmpty((float[]) obj);
-            } else if (obj instanceof double[]) {
-                return ArrayUtils.isEmpty((double[]) obj);
+        if (value != null) {
+            Type type = field.getGenericType();
+            String typeString = type.toString();
+            if (typeString.equals("class java.lang.String")) {
+            } else if (typeString.equals("class java.lang.Long") || typeString.equals("long")) {
+                value = Long.valueOf(value.toString());
+            } else if (typeString.equals("class java.lang.Integer") || typeString.equals("int")) {
+                value = Integer.valueOf(value.toString());
+            } else if (typeString.equals("class java.lang.Short") || typeString.equals("short")) {
+                value = Short.valueOf(value.toString());
+            } else if (typeString.equals("class java.lang.Double") || typeString.equals("double")) {
+                value = Double.valueOf(value.toString());
+            } else if (typeString.equals("class java.lang.Float") || typeString.equals("float")) {
+                value = Float.valueOf(value.toString());
+            } else if (typeString.equals("class java.lang.Byte") || typeString.equals("byte")) {
+                value = Byte.valueOf(value.toString());
+            } else if (typeString.equals("class java.lang.Boolean") || typeString.equals("boolean")) {
+                value = Boolean.valueOf(value.toString());
+            } else if (typeString.equals("class com.alibaba.fastjson.JSONObject")) {
+                value = JSONObject.parseObject(value.toString());
+            } else if (typeString.startsWith("java.util.List")) {
+                Class<?> clazz = Object.class;
+                if (typeString.matches("^java.util.List<[\\s\\S]+?>$")) {
+                    try {
+                        clazz = Class.forName(typeString.substring(typeString.indexOf("<") + 1, typeString.length() - 1));
+                    } catch (ClassNotFoundException e) {
+                        throw new IllegalStateException("无法转换为 " + typeString, e);
+                    }
+                }
+                String[] strs = value.toString().split(",[ ]*");
+                value = castList(strs, clazz);
+            } else {
+                throw new IllegalArgumentException("不支持的类型:type=" + type + ", value=" + value);
             }
             }
-            return ArrayUtils.isEmpty((Object[]) obj);
         }
         }
-        return (obj instanceof String && StringUtils.isEmpty(obj))
-                || (obj instanceof Collection && CollectionUtils.isEmpty((Collection<?>) obj))
-                || (obj instanceof Map && CollectionUtils.isEmpty((Map<?, ?>) obj));
+        if (!field.isAccessible()) {
+            field.setAccessible(true);
+            field.set(object, value);
+            field.setAccessible(false);
+        } else {
+            field.set(object, value);
+        }
     }
     }
 
 
     /**
     /**
-     * 将对象转为 String
+     * 转换 String 数组为指定对象列表
      *
      *
-     * @param obj 对象
-     * @return 转换的 String
+     * @param strs  String 数组
+     * @param clazz 目标类型
+     * @param <T>   目标类型
+     * @return 对象列表
      */
      */
-    public static String toString(Object obj) {
-        if (obj == null) {
-            return "";
-        }
-        if (obj instanceof String) {
-            return (String) obj;
+    private static <T> List<T> castList(String[] strs, Class<T> clazz) {
+        if (ArrayUtils.isEmpty(strs)) {
+            return null;
         }
         }
-        if (obj.getClass().isArray()) {
-            if (obj instanceof long[]) {
-                return Arrays.toString((long[]) obj);
-            } else if (obj instanceof int[]) {
-                return Arrays.toString((int[]) obj);
-            } else if (obj instanceof short[]) {
-                return Arrays.toString((short[]) obj);
-            } else if (obj instanceof byte[]) {
-                return Arrays.toString((byte[]) obj);
-            } else if (obj instanceof char[]) {
-                return Arrays.toString((char[]) obj);
-            } else if (obj instanceof boolean[]) {
-                return Arrays.toString((boolean[]) obj);
-            } else if (obj instanceof float[]) {
-                return Arrays.toString((float[]) obj);
-            } else if (obj instanceof double[]) {
-                return Arrays.toString((double[]) obj);
-            }
-            return Arrays.toString((Object[]) obj);
+        List<T> list = new ArrayList<>();
+        for (String str : strs) {
+            list.add(cast(str, clazz));
         }
         }
-        return obj.toString();
+        return list;
     }
     }
 
 
+    /**
+     * 转换对象为指定类型
+     *
+     * @param object 对象
+     * @param clazz  目标类型
+     * @param <T>    目标类型
+     * @return 目标
+     */
+    private static <T> T cast(Object object, Class<T> clazz) {
+        return object == null ? null : (T) object;
+    }
 }
 }

+ 0 - 4
report/pom.xml

@@ -10,13 +10,11 @@
 	<packaging>war</packaging>
 	<packaging>war</packaging>
 
 
 	<properties>
 	<properties>
-		<oracle.jdbc.version>11.2.0</oracle.jdbc.version>
 		<druid.version>1.0.24</druid.version>
 		<druid.version>1.0.24</druid.version>
 		<jasperreports.version>6.4.0</jasperreports.version>
 		<jasperreports.version>6.4.0</jasperreports.version>
 		<jasperreports-functions.version>6.3.0</jasperreports-functions.version>
 		<jasperreports-functions.version>6.3.0</jasperreports-functions.version>
 		<poi.version>3.10.1</poi.version>
 		<poi.version>3.10.1</poi.version>
 		<commons.fileupload.version>1.3.2</commons.fileupload.version>
 		<commons.fileupload.version>1.3.2</commons.fileupload.version>
-		<fastjson.version>1.2.15</fastjson.version>
 		<axis.version>1.4</axis.version>
 		<axis.version>1.4</axis.version>
 		<commons.discovery.version>0.2</commons.discovery.version>
 		<commons.discovery.version>0.2</commons.discovery.version>
 		<javax.activation.version>1.1.1</javax.activation.version>
 		<javax.activation.version>1.1.1</javax.activation.version>
@@ -80,12 +78,10 @@
 		<dependency>
 		<dependency>
 			<groupId>com.alibaba</groupId>
 			<groupId>com.alibaba</groupId>
 			<artifactId>fastjson</artifactId>
 			<artifactId>fastjson</artifactId>
-			<version>${fastjson.version}</version>
 		</dependency>
 		</dependency>
 		<dependency>
 		<dependency>
 			<groupId>com.oracle</groupId>
 			<groupId>com.oracle</groupId>
 			<artifactId>ojdbc6</artifactId>
 			<artifactId>ojdbc6</artifactId>
-			<version>${oracle.jdbc.version}</version>
 		</dependency>
 		</dependency>
 		<dependency>
 		<dependency>
 			<groupId>mysql</groupId>
 			<groupId>mysql</groupId>

+ 0 - 392
report/src/main/java/com/uas/report/util/ObjectUtils.java

@@ -1,392 +0,0 @@
-package com.uas.report.util;
-
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-
-import java.io.*;
-import java.lang.reflect.Field;
-import java.lang.reflect.Type;
-import java.util.*;
-import java.util.Map.Entry;
-
-/**
- * 对象工具类
- *
- * @author sunyj
- * @since 2017年9月1日 下午3:54:26
- */
-public class ObjectUtils {
-
-	/**
-	 * 判断是否为 null、空数组、空串或者空集合
-	 *
-	 * @param obj
-	 *            对象
-	 * @return 是否为 null、空数组、空串或者空集合
-	 */
-	public static boolean isEmpty(Object obj) {
-		if (obj == null) {
-			return true;
-		}
-		if (obj.getClass().isArray()) {
-			if (obj instanceof long[]) {
-				return ArrayUtils.isEmpty((long[]) obj);
-			} else if (obj instanceof int[]) {
-				return ArrayUtils.isEmpty((int[]) obj);
-			} else if (obj instanceof short[]) {
-				return ArrayUtils.isEmpty((short[]) obj);
-			} else if (obj instanceof byte[]) {
-				return ArrayUtils.isEmpty((byte[]) obj);
-			} else if (obj instanceof char[]) {
-				return ArrayUtils.isEmpty((char[]) obj);
-			} else if (obj instanceof boolean[]) {
-				return ArrayUtils.isEmpty((boolean[]) obj);
-			} else if (obj instanceof float[]) {
-				return ArrayUtils.isEmpty((float[]) obj);
-			} else if (obj instanceof double[]) {
-				return ArrayUtils.isEmpty((double[]) obj);
-			}
-			return ArrayUtils.isEmpty((Object[]) obj);
-		}
-		return (obj instanceof String && StringUtils.isEmpty(obj))
-				|| (obj instanceof Collection && CollectionUtils.isEmpty((Collection<?>) obj))
-				|| (obj instanceof Map && CollectionUtils.isEmpty((Map<?, ?>) obj));
-	}
-
-	/**
-	 * 将对象转为 String
-	 *
-	 * @param obj
-	 *            对象
-	 * @return 转换的 String
-	 */
-	public static String toString(Object obj) {
-		if (obj == null) {
-			return "";
-		}
-		if (obj instanceof String) {
-			return (String) obj;
-		}
-		if (obj.getClass().isArray()) {
-			if (obj instanceof long[]) {
-				return Arrays.toString((long[]) obj);
-			} else if (obj instanceof int[]) {
-				return Arrays.toString((int[]) obj);
-			} else if (obj instanceof short[]) {
-				return Arrays.toString((short[]) obj);
-			} else if (obj instanceof byte[]) {
-				return Arrays.toString((byte[]) obj);
-			} else if (obj instanceof char[]) {
-				return Arrays.toString((char[]) obj);
-			} else if (obj instanceof boolean[]) {
-				return Arrays.toString((boolean[]) obj);
-			} else if (obj instanceof float[]) {
-				return Arrays.toString((float[]) obj);
-			} else if (obj instanceof double[]) {
-				return Arrays.toString((double[]) obj);
-			}
-			return Arrays.toString((Object[]) obj);
-		}
-		return obj.toString();
-	}
-
-	/**
-	 * 深克隆对象
-	 *
-	 * @param t
-	 *            要克隆的对象
-	 * @return 克隆得到的对象
-	 */
-	@SuppressWarnings("unchecked")
-	public static <T extends Serializable> T clone(T t)
-			throws IOException, ClassNotFoundException, NotSerializableException {
-		if (t == null) {
-			return null;
-		}
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		new ObjectOutputStream(out).writeObject(t);
-		ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
-		return (T) in.readObject();
-	}
-
-	/**
-	 * 深克隆集合对象
-	 *
-	 * @param collection
-	 *            要克隆的对象
-	 * @return 克隆得到的对象
-	 */
-	@SuppressWarnings("unchecked")
-	public static <T> Collection<T> clone(Collection<T> collection) throws InstantiationException,
-			IllegalAccessException, NotSerializableException, ClassNotFoundException, IOException {
-		if (collection == null) {
-			return null;
-		}
-		Collection<T> result = collection.getClass().newInstance();
-		for (T t : collection) {
-			if (t instanceof Serializable) {
-				result.add((T) clone((Serializable) t));
-			} else if (t instanceof Collection) {
-				result.add((T) clone((Collection<?>) t));
-			} else if (t instanceof Map) {
-				result.add((T) clone((Map<String, ?>) t));
-			} else {
-				throw new IllegalArgumentException("未实现 Serializable 接口");
-			}
-		}
-		return result;
-	}
-
-	/**
-	 * 深克隆 Map 对象
-	 *
-	 * @param map
-	 *            要克隆的对象
-	 * @return 克隆得到的对象
-	 */
-	@SuppressWarnings("unchecked")
-	public static <T> Map<String, T> clone(Map<String, T> map) throws InstantiationException, IllegalAccessException,
-			NotSerializableException, ClassNotFoundException, IOException {
-		if (map == null) {
-			return null;
-		}
-		Map<String, T> result = map.getClass().newInstance();
-		Set<Entry<String, T>> entrySet = map.entrySet();
-		for (Entry<String, T> entry : entrySet) {
-			T value = entry.getValue();
-			if (value instanceof Serializable) {
-				result.put(entry.getKey(), (T) clone((Serializable) value));
-			} else if (value instanceof Collection) {
-				result.put(entry.getKey(), (T) clone((Collection<?>) value));
-			} else if (value instanceof Map) {
-				result.put(entry.getKey(), (T) clone((Map<String, ?>) value));
-			} else {
-				throw new IllegalArgumentException("未实现 Serializable 接口");
-			}
-		}
-		return result;
-	}
-
-	/**
-	 * JSONArray 转为指定类型的 List
-	 *
-	 * @param array
-	 *            JSONArray
-	 * @param clazz
-	 *            指定的类型
-	 * @param <T>
-	 *            指定的类型
-	 * @return 指定类型的 List
-	 */
-	public static <T> List<T> toList(JSONArray array, Class<T> clazz) {
-		if (array == null) {
-			return null;
-		}
-		List<T> list = new ArrayList<>();
-		for (int i = 0; i < array.size(); i++) {
-			list.add(array.getObject(i, clazz));
-		}
-		return list;
-	}
-
-	/**
-	 * 利用反射获取指定对象的指定字段的值
-	 *
-	 * @param field
-	 *            指定字段
-	 * @param k
-	 *            指定对象
-	 * @return 指定字段的值
-	 */
-	public static <K> Object getValue(Field field, K k) throws IllegalStateException {
-		Object value;
-		try {
-			if (!field.isAccessible()) {
-				field.setAccessible(true);
-				value = field.get(k);
-				field.setAccessible(false);
-			} else {
-				value = field.get(k);
-			}
-		} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
-			throw new IllegalStateException("通过反射取值失败", e);
-		}
-		return value;
-	}
-
-	/**
-	 * 利用反射递归获取指定对象的指定字段的值
-	 *
-	 * @param field
-	 *            指定字段
-	 * @param k
-	 *            指定对象
-	 * @return 指定字段的值
-	 */
-	public static <K> Object recursivelyGetValue(String field, K k) {
-		return getValue(recursivelyGetField(field, k.getClass()), k);
-	}
-
-	/**
-	 * 递归获取指定类的指定字段(包括父类的私有字段)
-	 *
-	 * @param field
-	 *            指定字段
-	 * @param clazz
-	 *            指定类
-	 * @return 指定字段
-	 * @throws IllegalArgumentException
-	 */
-	public static Field recursivelyGetField(String field, Class<?> clazz) throws IllegalArgumentException {
-		try {
-			return clazz.getDeclaredField(field);
-		} catch (NoSuchFieldException e) {
-			Class<?> superclass = clazz.getSuperclass();
-			if (superclass != null) {
-				return recursivelyGetField(field, superclass);
-			}
-			throw new IllegalArgumentException(clazz + "中不存在字段:" + field);
-		}
-	}
-
-	/**
-	 * 获取指定类的指定字段
-	 *
-	 * @param field
-	 *            指定字段
-	 * @param clazz
-	 *            指定类
-	 * @return 指定字段
-	 * @throws IllegalArgumentException
-	 */
-	public static Field getField(String field, Class<?> clazz) throws IllegalArgumentException {
-		try {
-			return clazz.getDeclaredField(field);
-		} catch (NoSuchFieldException e) {
-			throw new IllegalArgumentException(clazz + "中不存在字段:" + field);
-		}
-	}
-
-	/**
-	 * 递归获取父类(包括私有字段)的所有字段
-	 *
-	 * @param clazz
-	 *            指定类
-	 * @return 所有字段
-	 */
-	public static List<Field> recursivelyGetParentField(Class<?> clazz) {
-		List<Field> fields = new ArrayList<>();
-		Class<?> superclass = clazz.getSuperclass();
-		if (superclass != null) {
-			fields.addAll(recursivelyGetField(superclass));
-		}
-		return fields;
-	}
-
-	/**
-	 * 递归获取所有字段(包括父类的私有字段)
-	 *
-	 * @param clazz
-	 *            指定类
-	 * @return 所有字段
-	 */
-	private static List<Field> recursivelyGetField(Class<?> clazz) {
-		List<Field> fields = new ArrayList<>();
-		Field[] declaredFields = clazz.getDeclaredFields();
-		if (!ArrayUtils.isEmpty(declaredFields)) {
-			fields.addAll(Arrays.asList(declaredFields));
-		}
-		Class<?> superclass = clazz.getSuperclass();
-		if (superclass != null) {
-			fields.addAll(recursivelyGetField(superclass));
-		}
-		return fields;
-	}
-
-    /**
-     * 通过反射为指定的字段赋值
-     *
-     * @param object 对象
-     * @param field  字段
-     * @param value  值
-     * @throws IllegalAccessException
-     */
-    public static void setValue(Object object, Field field, Object value) throws IllegalAccessException {
-        if (object == null || field == null) {
-            throw new IllegalArgumentException("object 或 field 为空");
-        }
-        if (value != null) {
-            Type type = field.getGenericType();
-            String typeString = type.toString();
-            if (typeString.equals("class java.lang.String")) {
-            } else if (typeString.equals("class java.lang.Long") || typeString.equals("long")) {
-                value = Long.valueOf(value.toString());
-            } else if (typeString.equals("class java.lang.Integer") || typeString.equals("int")) {
-                value = Integer.valueOf(value.toString());
-            } else if (typeString.equals("class java.lang.Short") || typeString.equals("short")) {
-                value = Short.valueOf(value.toString());
-            } else if (typeString.equals("class java.lang.Double") || typeString.equals("double")) {
-                value = Double.valueOf(value.toString());
-            } else if (typeString.equals("class java.lang.Float") || typeString.equals("float")) {
-                value = Float.valueOf(value.toString());
-            } else if (typeString.equals("class java.lang.Byte") || typeString.equals("byte")) {
-                value = Byte.valueOf(value.toString());
-            } else if (typeString.equals("class java.lang.Boolean") || typeString.equals("boolean")) {
-                value = Boolean.valueOf(value.toString());
-            } else if (typeString.equals("class com.alibaba.fastjson.JSONObject")) {
-                value = JSONObject.parseObject(value.toString());
-            } else if (typeString.startsWith("java.util.List")) {
-                Class<?> clazz = Object.class;
-                if (typeString.matches("^java.util.List<[\\s\\S]+?>$")) {
-                    try {
-                        clazz = Class.forName(typeString.substring(typeString.indexOf("<") + 1, typeString.length() - 1));
-                    } catch (ClassNotFoundException e) {
-                        throw new IllegalStateException("无法转换为 " + typeString, e);
-                    }
-                }
-                String[] strs = value.toString().split(",[ ]*");
-                value = castList(strs, clazz);
-            } else {
-                throw new IllegalArgumentException("不支持的类型:type=" + type + ", value=" + value);
-            }
-        }
-        if (!field.isAccessible()) {
-            field.setAccessible(true);
-            field.set(object, value);
-            field.setAccessible(false);
-        } else {
-            field.set(object, value);
-        }
-    }
-
-    /**
-     * 转换 String 数组为指定对象列表
-     *
-     * @param strs  String 数组
-     * @param clazz 目标类型
-     * @param <T>   目标类型
-     * @return 对象列表
-     */
-    private static <T> List<T> castList(String[] strs, Class<T> clazz) {
-        if (ArrayUtils.isEmpty(strs)) {
-            return null;
-        }
-        List<T> list = new ArrayList<>();
-        for (String str : strs) {
-            list.add(cast(str, clazz));
-        }
-        return list;
-    }
-
-    /**
-     * 转换对象为指定类型
-     *
-     * @param object 对象
-     * @param clazz  目标类型
-     * @param <T>    目标类型
-     * @return 目标
-     */
-    private static <T> T cast(Object object, Class<T> clazz) {
-        return object == null ? null : (T) object;
-    }
-}