From e93edf3bbbdf2f6e5e4073dfca09f14c699b6572 Mon Sep 17 00:00:00 2001
From: super_liu <396572590@qq.com>
Date: Wed, 11 Aug 2021 17:19:57 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20convert=20?=
=?UTF-8?q?=E8=BD=AC=E6=8D=A2pdf=E5=AD=90=E9=A1=B9=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../service/ActSarItemsEOService.java | 2 +-
adc-da-convert/pom.xml | 260 +++++++++++++++++
.../da/convert/common/ConvertStateEnum.java | 19 ++
.../adc/da/convert/common/DocConverter.java | 265 ++++++++++++++++++
.../da/convert/common/DocConverterPdf.java | 243 ++++++++++++++++
.../da/convert/common/DocConverterPdfOld.java | 225 +++++++++++++++
.../adc/da/convert/common/PDFEditUtils.java | 34 +++
.../com/adc/da/convert/common/SplitPdf.java | 169 +++++++++++
.../src/main/lib/jodconverter-2.2.2.jar | Bin 0 -> 32054 bytes
pom.xml | 3 +-
10 files changed, 1218 insertions(+), 2 deletions(-)
create mode 100644 adc-da-convert/pom.xml
create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/ConvertStateEnum.java
create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverter.java
create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdf.java
create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdfOld.java
create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/PDFEditUtils.java
create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/SplitPdf.java
create mode 100644 adc-da-convert/src/main/lib/jodconverter-2.2.2.jar
diff --git a/adc-da-activiti/src/main/java/com/adc/da/workFlow/service/ActSarItemsEOService.java b/adc-da-activiti/src/main/java/com/adc/da/workFlow/service/ActSarItemsEOService.java
index 670dde45..57af35b3 100644
--- a/adc-da-activiti/src/main/java/com/adc/da/workFlow/service/ActSarItemsEOService.java
+++ b/adc-da-activiti/src/main/java/com/adc/da/workFlow/service/ActSarItemsEOService.java
@@ -121,7 +121,7 @@ public class ActSarItemsEOService {
}
/***
- * @Description: 标准解读流程入库"
+ * @Description: 国内外标准流程入库"
* @Author: yangxuenan
* @Date: 2020/12/7 13:48
* @Param: [standJson]
diff --git a/adc-da-convert/pom.xml b/adc-da-convert/pom.xml
new file mode 100644
index 00000000..43028d98
--- /dev/null
+++ b/adc-da-convert/pom.xml
@@ -0,0 +1,260 @@
+
+
+
+ foton-slrs-system-rest
+ com.adc
+ 3.0.0
+
+ 4.0.0
+
+ adc-da-convert
+
+ UTF-8
+ UTF-8
+ 1.7
+ 1.7
+ 1.7
+ 4.3.9.RELEASE
+ 3.4.0
+ 1.4.0-RC2
+ 4.1.2
+
+
+
+
+ adc
+ http://60.247.58.121:8182/nexus/content/groups/public
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+ thirdparty
+ Nexus Thirdparty Repository
+ http://60.247.58.121:8182/nexus/content/repositories/thirdparty/
+
+
+
+
+
+
+ com.adc
+ adc-da-swagger
+ 2.0.0
+
+
+ com.adc
+ adc-da-base
+ 2.0.0
+
+
+ com.adc
+ adc-da-sys
+ 3.0.0
+
+
+ com.adc
+ adc-da-util
+ 2.2.4
+
+
+ org.bouncycastle
+ bcprov-jdk14
+
+
+
+
+ org.springframework
+ spring-tx
+ ${spring.version}
+
+
+ org.springframework
+ spring-web
+ ${spring.version}
+
+
+ org.mybatis
+ mybatis
+ ${mybatis.version}
+
+
+ javax.validation
+ validation-api
+ 2.0.1.Final
+
+
+
+ org.apache.shiro
+ shiro-core
+ ${shiro.version}
+
+
+
+ com.adc
+ adc-da-excel
+ 2.0.0
+
+
+
+ org.apache.poi
+ poi
+ ${poi.version}
+
+
+ org.apache.poi
+ poi-ooxml
+ ${poi.version}
+
+
+ org.apache.poi
+ poi-ooxml-schemas
+ ${poi.version}
+
+
+ org.apache.poi
+ poi-scratchpad
+ ${poi.version}
+ true
+
+
+
+
+
+ com.adc
+ adc-da-file
+ RELEASE
+
+
+ com.adc
+ adc-da-file
+ 2.0.0
+
+
+
+
+ com.servlets
+ cos
+ 05Nov2002
+
+
+
+ com.artofsolving
+ jodconverter
+ system
+ 2.2.2
+ ${basedir}/src/main/lib/jodconverter-2.2.2.jar
+
+
+ org.openoffice
+ juh
+ 3.0.1
+
+
+ org.openoffice
+ jurt
+ 3.0.1
+
+
+ org.openoffice
+ ridl
+ 3.0.1
+
+
+ org.slf4j
+ slf4j-jdk14
+ 1.7.21
+ test
+
+
+ org.openoffice
+ unoil
+ 3.0.1
+
+
+ com.thoughtworks.xstream
+ xstream
+ 1.3.1
+
+
+
+
+
+ com.itextpdf
+ kernel
+ 7.0.4
+
+
+ com.itextpdf
+ io
+ 7.0.4
+
+
+ com.itextpdf
+ layout
+ 7.0.4
+
+
+ com.itextpdf
+ forms
+ 7.0.4
+
+
+ com.itextpdf
+ pdfa
+ 7.0.4
+
+
+ com.itextpdf
+ pdftest
+ 7.0.4
+
+
+ org.slf4j
+ slf4j-log4j12
+ 1.7.18
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java.version}
+ ${java.version}
+ ${java.version}
+ ${project.build.sourceEncoding}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/ConvertStateEnum.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/ConvertStateEnum.java
new file mode 100644
index 00000000..9f573722
--- /dev/null
+++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/ConvertStateEnum.java
@@ -0,0 +1,19 @@
+package com.adc.da.convert.common;
+
+public enum ConvertStateEnum {
+ NO_CONVERT(0,"未转换"),CONVERING(1,"转换中"),CONVERT_SUCCESS(2,"转换成功"),CONVERT_ERROR(3,"转换失败");
+
+ private int value;
+ private String lable;
+
+ private ConvertStateEnum(int value, String lable) {
+ this.value = value;
+ this.lable = lable;
+ }
+ public int getValue() {
+ return value;
+ }
+ public String getLable() {
+ return lable;
+ }
+}
diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverter.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverter.java
new file mode 100644
index 00000000..30d1d95e
--- /dev/null
+++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverter.java
@@ -0,0 +1,265 @@
+package com.adc.da.convert.common;
+
+import com.artofsolving.jodconverter.DocumentConverter;
+import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
+import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
+import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
+import com.itextpdf.kernel.pdf.PdfReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.io.*;
+
+/**
+ * @Author yangxuenan
+ * @Description 文档转换
+ * Date 2018/8/24 13:44
+ * @Param
+ * @return
+ **/
+public class DocConverter {
+
+ private static final Logger logger = LoggerFactory.getLogger(DocConverter.class);
+ // 环境 1:windows 2:linux
+ private static final int ENVIRONMENT = 1;
+ // (只涉及pdf2swf路径问题)
+ private String fileString;
+ // 输入路径 ,如果不设置就输出在默认的位置
+ private String outputPath = "";
+ //转化文件名称
+ private String fileName;
+ //转换pdf文件
+ private File pdfFile;
+ //转换成swf文件
+ private File swfFile;
+ //待转换doc文件
+ private File docFile;
+ //为文件加水印后文件路径
+ String waterPdfPath;
+
+ @Value("${convert.host}")
+ private String convertHost;
+
+ public DocConverter(String fileString,String fileType) {
+ ini(fileString,fileType);
+ }
+
+ /**
+ * @Author yangxuenan
+ * @Description 重新设置file
+ * Date 2018/8/24 13:50
+ * @Param [fileString, fileType]
+ * @return void
+ **/
+ public void setFile(String fileString,String fileType) {
+ ini(fileString,fileType);
+ }
+
+ /**
+ * @Author yangxuenan
+ * @Description 初始化
+ * Date 2018/8/24 13:50
+ * @Param [fileString, fileType]
+ * @return void
+ **/
+ private void ini(String fileString,String fileType) {
+ this.fileString = fileString;
+ fileName = fileString.substring(0, fileString.lastIndexOf("."));
+ //判断文件类型,进行不同操作
+ if(".doc".equals(fileType) || ".docx".equals(fileType)){
+ docFile = new File(fileString);
+ pdfFile = new File(fileName + ".pdf");
+ swfFile = new File(fileName + ".swf");
+ } else if (".pdf".equals(fileType)){
+ pdfFile = new File(fileName + ".pdf");
+ swfFile = new File(fileName + ".swf");
+ }
+ }
+
+ /**
+ * @Author yangxuenan
+ * @Description 转为PDF
+ * Date 2018/8/24 13:50
+ * @Param []
+ * @return void
+ **/
+ private void doc2pdf() throws Exception {
+ if (docFile.exists()) {
+ if (!pdfFile.exists()) {
+ logger.info("转换服务地址接口:"+convertHost);
+ //连接openOffice
+ OpenOfficeConnection connection = new SocketOpenOfficeConnection(convertHost,8100);
+ try {
+ connection.connect();
+ //使用openOffice将doc文件转换问pdf文件
+ DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
+ converter.convert(docFile, pdfFile);
+ // 关闭连接
+ connection.disconnect();
+ logger.info("****pdf转换成功,PDF输出:" + pdfFile.getPath()+ "****");
+ } catch (java.net.ConnectException e) {
+ logger.error(e.getMessage(),e);
+ logger.info("****swf转换器异常,openoffice服务未启动!****");
+ throw e;
+ } catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) {
+ logger.error(e.getMessage(),e);
+ logger.info("****swf转换器异常,读取转换文件失败****");
+ throw e;
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ } else {
+ logger.info("****已经转换为pdf,不需要再进行转化****");
+ }
+ } else {
+ logger.info("****swf转换器异常,需要转换的文档不存在,无法转换****");
+ }
+ }
+
+ /**
+ * @Author yangxuenan
+ * @Description 转换成 swf
+ * Date 2018/8/24 13:51
+ * @Param [fileType]
+ * @return void
+ **/
+ /*private void pdf2swf(String fileType) throws Exception {
+ Runtime r = Runtime.getRuntime();
+ if (!swfFile.exists()) {
+ if (pdfFile.exists()) {
+ // windows环境处理
+ if (ENVIRONMENT == 1) {
+ try {
+ //使用swfTools工具将pdf文件转换为swf文件
+ //String paperSwfFile = swfFile.getPath().replace(".swf","%.swf");
+ Process p = r.exec("G:/swftTools/pdf2swf.exe "+ waterPdfPath + " -o "+ swfFile.getPath() + " -f -T 9 -t -s languagedir=G:/xpdf/xpdf-chinese-simplified");
+ logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****");
+ //如果源文件为doc类文件,将过渡的pdf文件删除
+ if(".doc".equals(fileType) || ".docx".equals(fileType)){
+ if (pdfFile.exists()) {
+ if(!pdfFile.delete()){
+ logger.error("文件删除失败!!!");
+ }
+ }
+ }
+ } catch (IOException e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ } else if (ENVIRONMENT == 2) {// linux环境处理
+ try {
+ Process p = r.exec("pdf2swf " + pdfFile.getPath()
+ + " -o " + swfFile.getPath() + " -f -T 9 -t -s storeallcharacters");
+ logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****");
+ if (pdfFile.exists()) {
+ if(!pdfFile.delete()){
+ logger.error("文件删除失败!!!");
+ }
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ }
+ } else {
+ logger.info("****pdf不存在,无法转换****");
+ }
+ } else {
+ logger.info("****swf已经存在不需要转换****");
+ }
+ }*/
+
+ static String loadStream(InputStream in) throws IOException {
+
+ int ptr = 0;
+ in = new BufferedInputStream(in);
+ StringBuilder buffer = new StringBuilder();
+
+ while ((ptr = in.read()) != -1) {
+ buffer.append((char) ptr);
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * @Author yangxuenan
+ * @Description 转换主方法
+ * Date 2018/8/24 13:51
+ * @Param [fileType]
+ * @return boolean
+ **/
+ public boolean conver(String fileType) {
+
+ if (swfFile.exists()) {
+ logger.info("****swf转换器开始工作,该文件已经转换为swf****");
+ return true;
+ }
+
+ if (ENVIRONMENT == 1) {
+ logger.info("****swf转换器开始工作,当前设置运行环境windows****");
+ } else {
+ logger.info("****swf转换器开始工作,当前设置运行环境linux****");
+ }
+ try {
+ //判断待转换文件类型,如果为doc文件需要先转为pdf类型文件
+ if(".doc".equals(fileType) || ".docx".equals(fileType)){
+ doc2pdf();
+// pdf2swf(fileType);
+ } else if (".pdf".equals(fileType)){
+// pdf2swf(fileType);
+ }
+
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ return false;
+ }
+
+ if (swfFile.exists()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @Author yangxuenan
+ * @Description 返回文件路径
+ * Date 2018/8/24 13:52
+ * @Param []
+ * @return java.lang.String
+ **/
+ public String getswfPath() {
+ if (swfFile.exists()) {
+ //获取转换后的swf文件路径
+ String tempString = swfFile.getPath();
+ tempString = tempString.replaceAll("\\\\", "/");
+ return tempString;
+ } else {
+ return "";
+ }
+
+ }
+
+ /**
+ * @Author yangxuenan
+ * @Description 设置输出路径
+ * Date 2018/8/24 13:52
+ * @Param [outputPath]
+ * @return void
+ **/
+ public void setOutputPath(String outputPath) {
+ this.outputPath = outputPath;
+ if (!outputPath.equals("")) {
+ String realName = fileName.substring(fileName.lastIndexOf("/"),
+ fileName.lastIndexOf("."));
+ if (outputPath.charAt(outputPath.length()) == '/') {
+ swfFile = new File(outputPath + realName + ".swf");
+ }
+ }
+ }
+
+
+}
diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdf.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdf.java
new file mode 100644
index 00000000..6294d314
--- /dev/null
+++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdf.java
@@ -0,0 +1,243 @@
+package com.adc.da.convert.common;
+
+import com.artofsolving.jodconverter.DocumentConverter;
+import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
+import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
+import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
+import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.*;
+
+public class DocConverterPdf {
+
+ private static final Logger logger = LoggerFactory.getLogger(DocConverterPdf.class);
+
+ private static final int ENVIRONMENT = 1;// 环境 1:windows 2:linux
+ private String fileString;// (只涉及pdf2swf路径问题)
+ private String outputPath = "";// 输入路径 ,如果不设置就输出在默认的位置
+ private String fileName;
+ private File pdfFile;
+ private File convertPdfFile;
+ private File swfFile;
+ private File docFile;
+ String waterPdfPath;
+
+ private String convertHost;
+
+ public DocConverterPdf(String fileString, String fileType) {
+ ini(fileString,fileType);
+ }
+
+ /**
+ * 重新设置file
+ *
+ * @param fileString
+ */
+ public void setFile(String fileString,String fileType) {
+ ini(fileString,fileType);
+ }
+
+ /**
+ * 初始化
+ *
+ * @param fileString
+ */
+ private void ini(String fileString,String fileType) {
+ this.fileString = fileString;
+ fileName = fileString.substring(0, fileString.lastIndexOf("."));
+ if(".doc".equals(fileType.toLowerCase()) || ".docx".equals(fileType.toLowerCase()) || ".xlsx".equals(fileType.toLowerCase()) || ".xls".equals(fileType.toLowerCase()) || ".ppt".equals(fileType.toLowerCase()) || ".pptx".equals(fileType.toLowerCase())){
+ docFile = new File(fileString);
+ convertPdfFile=new File(fileName+"_C"+ ".pdf");
+ pdfFile = new File(fileName + ".pdf");
+ swfFile = new File(fileName + ".swf");
+ } else if (".pdf".equals(fileType)){
+ pdfFile = new File(fileName + ".pdf");
+ swfFile = new File(fileName + ".swf");
+ }
+ }
+
+ /**
+ * 转为PDF
+ *
+ * @param
+ */
+ private void doc2pdf() throws Exception {
+ if (!pdfFile.exists()) {
+ OpenOfficeConnection connection = null;
+ logger.info("转换服务地址接口:"+convertHost);
+ try {
+ if(StringUtils.isNotBlank(convertHost)){
+ connection = new SocketOpenOfficeConnection(convertHost,8100);
+ }else{
+ connection = new SocketOpenOfficeConnection(8100);
+ }
+ connection.connect();
+ DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
+ converter.convert(docFile, convertPdfFile);
+
+ //addWaterToPdf(pdfFile,userId);
+
+ // close the connection
+ connection.disconnect();
+ // 开始设置PDF文档相关属性保证其安全性
+ logger.info("开始设置转换后的PDF文件安全性相关设置");
+ PDFEditUtils.setPDFFileSecurity(pdfFile.getAbsolutePath(),convertPdfFile.getAbsolutePath());
+ logger.info("****pdf转换成功,PDF输出:" + pdfFile.getPath()+ "****");
+ } catch (java.net.ConnectException e) {
+ logger.error(e.getMessage(),e);
+ logger.info("****pdf转换器异常,openoffice服务未启动!****");
+ throw e;
+ } catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) {
+ logger.error(e.getMessage(),e);
+ logger.info("****pdf转换器异常,读取转换文件失败****");
+ throw e;
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ } else {
+ logger.info("****已经转换为pdf,不需要再进行转化****");
+ }
+ }
+
+ /**
+ * 转换成 swf
+ */
+ @SuppressWarnings("unused")
+ /*private void pdf2swf(String fileType) throws Exception {
+ Runtime r = Runtime.getRuntime();
+ if (!swfFile.exists()) {
+ if (pdfFile.exists()) {
+ if (ENVIRONMENT == 1) {// windows环境处理
+ try {
+ //String paperSwfFile = swfFile.getPath().replace(".swf","%.swf");
+ Process p = r.exec("G:/swftTools/pdf2swf.exe "+ waterPdfPath + " -o "+ swfFile.getPath() + " -f -T 9 -t -s languagedir=G:/xpdf/xpdf-chinese-simplified");
+ logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****");
+ if(".doc".equals(fileType) || ".docx".equals(fileType)){
+ *//*if (pdfFile.exists()) {
+ pdfFile.delete();
+ }*//*
+ }
+ } catch (IOException e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ } else if (ENVIRONMENT == 2) {// linux环境处理
+ try {
+ Process p = r.exec("pdf2swf " + pdfFile.getPath()
+ + " -o " + swfFile.getPath() + " -f -T 9 -t -s storeallcharacters");
+ logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****");
+ if (pdfFile.exists()) {
+ if(!pdfFile.delete()){
+ logger.error("文件删除失败!!!");
+ }
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ }
+ } else {
+ logger.info("****pdf不存在,无法转换****");
+ }
+ } else {
+ logger.info("****swf已经存在不需要转换****");
+ }
+ }*/
+
+ static String loadStream(InputStream in) throws IOException {
+
+ int ptr = 0;
+ in = new BufferedInputStream(in);
+ StringBuilder buffer = new StringBuilder();
+ while ((ptr = in.read()) != -1) {
+ buffer.append((char) ptr);
+ }
+
+ return buffer.toString();
+ }
+ /**
+ * 转换主方法
+ */
+ @SuppressWarnings("unused")
+ public File conver(String fileType) {
+ if (ENVIRONMENT == 1) {
+ logger.info("****swf转换器开始工作,当前设置运行环境windows****");
+ } else {
+ logger.info("****swf转换器开始工作,当前设置运行环境linux****");
+ }
+ try {
+ if(StringUtils.isNotBlank(fileType)){
+ fileType = fileType.toUpperCase();
+ if(".DOC".equals(fileType) || ".DOCX".equals(fileType) || ".XLSX".equals(fileType) || ".XLS".equals(fileType) || ".PPT".equals(fileType) || ".PPTX".equals(fileType)){
+ doc2pdf();
+ /*pdf2swf(fileType);*/
+ } else if (".PDF".equals(fileType)){
+ /*pdf2swf(fileType);*/
+ }
+ }else{
+ logger.error("文件类型后缀获取失败,请检查文件名称格式是否正确");
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ return new File("");
+ }
+
+ return pdfFile;
+
+ }
+
+ /**
+ * 返回文件路径
+ *
+ * @param
+ */
+ public String getswfPath() {
+ if (swfFile.exists()) {
+ String tempString = swfFile.getPath();
+ tempString = tempString.replaceAll("\\\\", "/");
+ return tempString;
+ } else {
+ return "";
+ }
+
+ }
+
+ public String getpdfPath() {
+ if (pdfFile!= null && !pdfFile.getPath().isEmpty()) {
+ String tempString = pdfFile.getPath();
+ tempString = tempString.replaceAll("\\\\", "/");
+ return tempString;
+ } else {
+ return "";
+ }
+
+ }
+
+ /**
+ * 设置输出路径
+ */
+ public void setOutputPath(String outputPath) {
+ this.outputPath = outputPath;
+ if (!outputPath.equals("")) {
+ String realName = fileName.substring(fileName.lastIndexOf("/"), fileName.lastIndexOf("."));
+ //TODO 此处的if判断执行的代码逻辑完全一样, 因此将其判断注释掉,直接执行
+/* if (outputPath.charAt(outputPath.length()) == '/') {
+ swfFile = new File(outputPath + realName + ".swf");
+ } else {
+ swfFile = new File(outputPath + realName + ".swf");
+ }*/
+ swfFile = new File(outputPath + realName + ".swf");
+ }
+ }
+
+ public String getConvertHost() {
+ return convertHost;
+ }
+
+ public void setConvertHost(String convertHost) {
+ this.convertHost = convertHost;
+ }
+}
diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdfOld.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdfOld.java
new file mode 100644
index 00000000..d9887b21
--- /dev/null
+++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdfOld.java
@@ -0,0 +1,225 @@
+package com.adc.da.convert.common;
+
+import com.artofsolving.jodconverter.DocumentConverter;
+import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
+import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
+import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class DocConverterPdfOld {
+
+ private static final Logger logger = LoggerFactory.getLogger(DocConverterPdf.class);
+
+ private static final int ENVIRONMENT = 1;// 环境 1:windows 2:linux
+ private String fileString;// (只涉及pdf2swf路径问题)
+ private String outputPath = "";// 输入路径 ,如果不设置就输出在默认的位置
+ private String fileName;
+ private File pdfFile;
+ private File convertPdfFile;
+ private File swfFile;
+ private File docFile;
+ String waterPdfPath;
+
+ public DocConverterPdfOld(String fileString, String fileType) {
+ ini(fileString,fileType);
+ }
+
+ /**
+ * 重新设置file
+ *
+ * @param fileString
+ */
+ public void setFile(String fileString,String fileType) {
+ ini(fileString,fileType);
+ }
+
+ /**
+ * 初始化
+ *
+ * @param fileString
+ */
+ private void ini(String fileString,String fileType) {
+ this.fileString = fileString;
+ fileName = fileString.substring(0, fileString.lastIndexOf("."));
+ if(".doc".equals(fileType) || ".docx".equals(fileType) || ".xlsx".equals(fileType) || ".xls".equals(fileType) || ".ppt".equals(fileType) || ".pptx".equals(fileType)){
+ docFile = new File(fileString);
+ convertPdfFile=new File(fileName+"_C"+ ".pdf");
+ pdfFile = new File(fileName + ".pdf");
+ swfFile = new File(fileName + ".swf");
+ } else if (".pdf".equals(fileType)){
+ pdfFile = new File(fileName + ".pdf");
+ swfFile = new File(fileName + ".swf");
+ }
+ }
+
+ /**
+ * 转为PDF
+ *
+ * @param
+ */
+ private void doc2pdf() throws Exception {
+ if (!pdfFile.exists()) {
+ OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
+ try {
+ connection.connect();
+ DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
+ converter.convert(docFile, convertPdfFile);
+
+ //addWaterToPdf(pdfFile,userId);
+
+ // close the connection
+ connection.disconnect();
+ // 开始设置PDF文档相关属性保证其安全性
+ logger.info("开始设置转换后的PDF文件安全性相关设置");
+ logger.info("****pdf转换成功,PDF输出:" + pdfFile.getPath()+ "****");
+ } catch (java.net.ConnectException e) {
+ logger.error(e.getMessage(),e);
+ logger.info("****pdf转换器异常,openoffice服务未启动!****");
+ throw e;
+ } catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) {
+ logger.error(e.getMessage(),e);
+ logger.info("****pdf转换器异常,读取转换文件失败****");
+ throw e;
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ } else {
+ logger.info("****已经转换为pdf,不需要再进行转化****");
+ }
+ }
+
+ /**
+ * 转换成 swf
+ */
+ @SuppressWarnings("unused")
+ /*private void pdf2swf(String fileType) throws Exception {
+ Runtime r = Runtime.getRuntime();
+ if (!swfFile.exists()) {
+ if (pdfFile.exists()) {
+ if (ENVIRONMENT == 1) {// windows环境处理
+ try {
+ //String paperSwfFile = swfFile.getPath().replace(".swf","%.swf");
+ Process p = r.exec("G:/swftTools/pdf2swf.exe "+ waterPdfPath + " -o "+ swfFile.getPath() + " -f -T 9 -t -s languagedir=G:/xpdf/xpdf-chinese-simplified");
+ logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****");
+ if(".doc".equals(fileType) || ".docx".equals(fileType)){
+ *//*if (pdfFile.exists()) {
+ pdfFile.delete();
+ }*//*
+ }
+ } catch (IOException e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ } else if (ENVIRONMENT == 2) {// linux环境处理
+ try {
+ Process p = r.exec("pdf2swf " + pdfFile.getPath()
+ + " -o " + swfFile.getPath() + " -f -T 9 -t -s storeallcharacters");
+ logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****");
+ if (pdfFile.exists()) {
+ if(!pdfFile.delete()){
+ logger.error("文件删除失败!!!");
+ }
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ throw e;
+ }
+ }
+ } else {
+ logger.info("****pdf不存在,无法转换****");
+ }
+ } else {
+ logger.info("****swf已经存在不需要转换****");
+ }
+ }*/
+
+ static String loadStream(InputStream in) throws IOException {
+
+ int ptr = 0;
+ in = new BufferedInputStream(in);
+ StringBuilder buffer = new StringBuilder();
+ while ((ptr = in.read()) != -1) {
+ buffer.append((char) ptr);
+ }
+
+ return buffer.toString();
+ }
+ /**
+ * 转换主方法
+ */
+ @SuppressWarnings("unused")
+ public File conver(String fileType) {
+ if (ENVIRONMENT == 1) {
+ logger.info("****swf转换器开始工作,当前设置运行环境windows****");
+ } else {
+ logger.info("****swf转换器开始工作,当前设置运行环境linux****");
+ }
+ try {
+ if(".doc".equals(fileType) || ".docx".equals(fileType) || ".xlsx".equals(fileType) || ".xls".equals(fileType) || ".ppt".equals(fileType) || ".pptx".equals(fileType)){
+ doc2pdf();
+ /*pdf2swf(fileType);*/
+ } else if (".pdf".equals(fileType)){
+ /*pdf2swf(fileType);*/
+ }
+
+ } catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ return new File("");
+ }
+
+ return pdfFile;
+
+ }
+
+ /**
+ * 返回文件路径
+ *
+ * @param
+ */
+ public String getswfPath() {
+ if (swfFile.exists()) {
+ String tempString = swfFile.getPath();
+ tempString = tempString.replaceAll("\\\\", "/");
+ return tempString;
+ } else {
+ return "";
+ }
+
+ }
+
+ public String getpdfPath() {
+ if (!pdfFile.getPath().isEmpty()) {
+ String tempString = pdfFile.getPath();
+ tempString = tempString.replaceAll("\\\\", "/");
+ return tempString;
+ } else {
+ return "";
+ }
+
+ }
+
+ /**
+ * 设置输出路径
+ */
+ public void setOutputPath(String outputPath) {
+ this.outputPath = outputPath;
+ if (!outputPath.equals("")) {
+ String realName = fileName.substring(fileName.lastIndexOf("/"), fileName.lastIndexOf("."));
+ //TODO 此处的if判断执行的代码逻辑完全一样, 因此将其判断注释掉,直接执行
+/* if (outputPath.charAt(outputPath.length()) == '/') {
+ swfFile = new File(outputPath + realName + ".swf");
+ } else {
+ swfFile = new File(outputPath + realName + ".swf");
+ }*/
+ swfFile = new File(outputPath + realName + ".swf");
+ }
+ }
+
+}
diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/PDFEditUtils.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/PDFEditUtils.java
new file mode 100644
index 00000000..515b6106
--- /dev/null
+++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/PDFEditUtils.java
@@ -0,0 +1,34 @@
+package com.adc.da.convert.common;
+
+
+import com.itextpdf.kernel.pdf.*;
+
+import java.io.File;
+import java.io.IOException;
+
+/***
+ *
+ * @MethodName:PDF编辑工具类
+ * @author: zhangyanduan
+ * @param:
+ * @return:
+ * date: 2019/3/6 18:36
+ */
+public class PDFEditUtils {
+
+ //设置安全性
+ public static void setPDFFileSecurity(String descFilePath,String srcFilePath) throws IOException {
+ checkOutFile(descFilePath);
+ PdfReader reader = new PdfReader(srcFilePath, new ReaderProperties());
+ PdfWriter writer = new PdfWriter(descFilePath, new WriterProperties()
+ .setStandardEncryption(null, "1234qwer".getBytes(), EncryptionConstants.ALLOW_SCREENREADERS,
+ EncryptionConstants.ENCRYPTION_AES_128 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA));
+ PdfDocument pdfDoc = new PdfDocument(reader, writer);
+ pdfDoc.close();
+ }
+
+ private static void checkOutFile(String descFilePath){
+ File desc=new File(descFilePath);
+ desc.getParentFile().mkdirs();
+ }
+}
diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/SplitPdf.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/SplitPdf.java
new file mode 100644
index 00000000..7160d5c5
--- /dev/null
+++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/SplitPdf.java
@@ -0,0 +1,169 @@
+package com.adc.da.convert.common;
+
+import com.adc.da.util.utils.UUID;
+import com.itextpdf.text.*;
+import com.itextpdf.text.log.Logger;
+import com.itextpdf.text.log.LoggerFactory;
+import com.itextpdf.text.pdf.*;
+import org.apache.commons.lang.StringUtils;
+import sun.misc.BASE64Encoder;
+
+import java.io.*;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SplitPdf {
+
+ private static final Logger logger = LoggerFactory.getLogger(SplitPdf.class);
+
+ public static String splitPDFFile(String inputPath,
+ String outputPath, int fromPage, int toPage) {
+ Document document = new Document();
+ InputStream inputStream = null;
+ OutputStream outputStream = null;
+ String allPassword = "";
+ try {
+ logger.info("*********开始拆分pdf**********");
+ inputStream = new FileInputStream(inputPath);
+ outputStream = new FileOutputStream(outputPath);
+ PdfReader inputPDF = new PdfReader(inputStream);
+ int totalPages = inputPDF.getNumberOfPages();
+ //make fromPage equals to toPage if it is greater
+ if(fromPage > toPage ) {
+ fromPage = toPage;
+ }
+ if(toPage > totalPages) {
+ toPage = totalPages;
+ }
+
+ // Create a writer for the outputstream
+ PdfWriter writer = PdfWriter.getInstance(document, outputStream);
+ Map pwdMap = setFilePassword();
+ allPassword = pwdMap.get("allPwd");
+ String filepassword = pwdMap.get("filePwd");
+ writer.setEncryption(filepassword.getBytes(), "1234qwer".getBytes(),
+ PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128);
+ document.open();
+ //构造文件,防止初始化文件为空
+ //document.add(new Chunk(""));
+ PdfContentByte cb = writer.getDirectContent(); // Holds the PDF data
+ PdfImportedPage page;
+
+ while(fromPage <= toPage) {
+ Rectangle pageSize = inputPDF.getPageSize(fromPage);
+ document.setPageSize(new Rectangle(pageSize.getWidth(),pageSize.getHeight()));
+ document.newPage();
+ page = writer.getImportedPage(inputPDF, fromPage);
+ // 此处将文档的旋转参数写入新的文档中
+ /* PdfDictionary pageN = inputPDF.getPageN(fromPage);
+ PdfNumber asNumber = pageN.getAsNumber(PdfName.ROTATE);
+ PdfDictionary additional = new PdfDictionary();
+ additional.put(PdfName.ROTATE,asNumber);
+ page.setAdditional(additional);*/
+ cb.addTemplate(page, 0, 0);
+ fromPage++;
+ }
+ outputStream.flush();
+ document.close();
+ inputStream.close();
+ outputStream.close();
+ //加密码
+ /*String path = outputPath.replace("测试文件拆分\\","测试文件拆分\\加密码\\");
+ PDFEditUtils.setPDFFileSecurity(outputPath,outputPath);*/
+ }catch (IllegalArgumentException ie){
+ logger.error("拆分过程中,读取文件失败");
+ logger.error(ie.getMessage(),ie);
+ logger.error(ie.getMessage());
+ } catch (IOException ioe) {
+ logger.error("拆分过程中,读取文件IO失败");
+ logger.error(ioe.getMessage(),ioe);
+ logger.error(ioe.getMessage());
+ }catch (Exception e) {
+ logger.error(e.getMessage(),e);
+ logger.error(e.getMessage());
+ } finally {
+ if(document.isOpen()){
+ document.close();
+ }
+ try {
+ if (inputStream != null){
+ inputStream.close();
+ }
+ if (outputStream != null){
+ outputStream.close();
+ }
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+ return allPassword;
+ }
+
+ /**
+ * 利用libreOffice将office文档转换成pdf
+ * @param inputFile 目标文件地址
+ * @param pdfFile 输出文件夹
+ * @return
+ */
+ public static boolean convertOffice2PDF(String inputFile, String pdfFile){
+ long start = System.currentTimeMillis();
+ String command;
+ boolean flag;
+ String osName = System.getProperty("os.name");
+ if (osName.contains("Windows")) {
+ command = "cmd /c soffice --headless --invisible --convert-to pdf:writer_pdf_Export " + inputFile + " --outdir " + pdfFile;
+ }else {
+ command = "libreoffice --headless --invisible --convert-to pdf:writer_pdf_Export " + inputFile + " --outdir " + pdfFile;
+ }
+ flag = executeLibreOfficeCommand(command);
+ long end = System.currentTimeMillis();
+ logger.debug("用时:{} ms"+(end - start));
+ return flag;
+ }
+
+
+ /**
+ * 执行command指令
+ * @param command
+ * @return
+ */
+ public static boolean executeLibreOfficeCommand(String command) {
+ logger.info("开始进行转化.......");
+ Process process;// Process可以控制该子进程的执行或获取该子进程的信息
+ try {
+ logger.info("convertOffice2PDF cmd : {}"+ command);
+ process = Runtime.getRuntime().exec(command);// exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序,并返回与该子进程对应的Process对象实例。
+ // 下面两个可以获取输入输出流
+// InputStream errorStream = process.getErrorStream();
+// InputStream inputStream = process.getInputStream();
+ } catch (IOException e) {
+ logger.error(" convertOffice2PDF {} error"+command, e);
+ return false;
+ }
+ int exitStatus = 0;
+ try {
+ exitStatus = process.waitFor();// 等待子进程完成再往下执行,返回值是子线程执行完毕的返回值,返回0表示正常结束
+ // 第二种接受返回值的方法
+ int i = process.exitValue(); // 接收执行完毕的返回值
+ logger.debug("返回值:"+i);
+ } catch (InterruptedException e) {
+ logger.info("InterruptedException convertOffice2PDF {}"+ command);
+ return false;
+ }
+ logger.info("convertOffice2PDF cmd exitStatus {}"+ exitStatus);
+ process.destroy(); // 销毁子进程
+ logger.info("转化结束.......");
+ return true;
+ }
+ //设置文件密码
+ public static Map setFilePassword(){
+ String allPwd = UUID.randomUUID(20);
+ String filePwd = allPwd.substring(0,5) + allPwd.substring(15,20);
+ Map map = new HashMap<>();
+ map.put("allPwd",allPwd);
+ map.put("filePwd",filePwd);
+ return map;
+ }
+
+}
diff --git a/adc-da-convert/src/main/lib/jodconverter-2.2.2.jar b/adc-da-convert/src/main/lib/jodconverter-2.2.2.jar
new file mode 100644
index 0000000000000000000000000000000000000000..d033256e8245d18c4340b5559a8a75a8ee7bc349
GIT binary patch
literal 32054
zcmbSy1DGXIl5W}6W!tvhW!tuGS9R%@ZFkwWZQHih#V)*_otb?*v+wQfZhm<)^JYfI
z7a1oq&L2nxX;3g2pua4bMv>hAcJQ|i^q;+~sEQz+q?{Oo!r#cCfH3}$r7E=!n*F)#
z^XG^9AIW3|8PhCXBw0k7g=_XoM@${M`@+$grFb~
z3)Pa)X?jUL+Oi^*P^6WVU9zdGP;p_A6Iqndd{8Eo9{yaBVsV!0-ET`5U3*0gK-H~D
zvWYu0^Mbeoh;{08>Hz&+E+8QEe-a<;k6gy~w*M~qf2KhC8-<~hi@lk%y^Wito%w$t
z|I35^q4@U&|Ig8182$sfmA#3vy`7t>lZ&a-e{nC>zr5Gp!PL&)%*@i*^uJ)k@;_no
z-;s;;f5_0z)Y!$+-tON;g!(tNr5w$2-$P8WbW`|?OAcBjr;ek_uOOp
zGiHJWmod3erO6Gr(5oOHL;=z_N&DX5egV)x{%KQ%olzIv2hLd<6uW
zwBU&k#}!>ZDbW#D!f%qO;lD(@#mG5QU=o4{O7Mo8=+nQQ?@5H03^7z8gtB^^!?zKx
zrYZ{=m_5`bD}=qCuM{J*kS7DFKfbXli1>hSv|sy_DohUqJOefOznC0rl5V;_B)YPo
zjPY%mtwOyk#fsMbBvcQTB>;~RwC6K>y{+Sp!iFN=iwSv>BLCR}r;oAYU8zf?DAB_D93$4I^#YCF5+zi;Z~tGu^F8cR5(L>qCBp8RWAYZ!!KEBa`6w
z581HPsE<>PiIGy!iEO!Z=-)Szk|mV0RAa+1TP%A7XuAr-
zVj*OujOi)hk7gEGLEBxn(ztU17#Q}h5cvApd89x_C*D5aSlYU17rA$J7!lSnJivck
zG0=qY!6qnK?y8*@+An4nqg5GP)cx95r2K7H7;mYXVEV2c}IYD+SSD
zO;Lfpt0z~eX11xZ2pO)*G#A$bN7ZJ})*1Y+_giE>=4UCdn3IGAE}bc48{sPXSnVCBSnL|D3m?
z(n!4qo&KKcPC`MoQW)Bi<;^CPOi-E#USz?el1zpr`+~mQQ-N=1jFY7Z&p^L=P?l
zhOH*lJ=ANkQj?df0o%+ZBlWZ>P_GASaNAl?0
z+(h5j+0k)U(Qn=L`*AqD*GG!aJKE&4Fk3wyXA>b5|J!6w{w9(52G#x{n|&PD3(KDa|@pJwt$WzyDT^Vl{7bgT6leFiw`MiU8i
z3c?9wncdymlGeF)4DKaDb+R0JY50Uog^*Ct!K=`8;K;}l5=3!`N)jX?->HFxCcGP3
z>Zg$gKl22Rw|#EB?T?ew@%Y}3yAVJulwLzH2c}+ILvDflA)&Ql40naWUl{p?UP@)$
z#t+r{M-HD4g5^hVD4=txMX+1lo
z;~fz8q=R*Xw}Kf^=t+G-92oZa`$dC)Ln9#Klj_L4Q14j>*Pzf7`2^h}?kV*T1luDw
zqjZaU1Uq2uZ3N$h-H1cSB6ZX3KSRZ$bj!a0?}Y{vAmtG1$h|P_N%kuT(?AIjy(itW
z?n(8}K+Pcf$+bq@!uB&j^FZ|w^Gd(4?QsNGK=+Wn$J~1Nvjv|(`4hg!JJ9XP2MeI&
zQ0R!i!0v(fM+RR&`;)y#JAm%p1p6a?O18$|*7$TL#ro46RyiEly>W)j28MvbaM9^4
zDpFoJ9LTM#o{CYd+1p1k8M%2N@vs|E=%$Ci13D(Yq2I7R&Z%pOTJQKhrZ`l`Tp%=XjV8KaCR__ZmI7-6Uw^`NnO5=}-Tmr3)=^@2xYziJY@F@y{85=A;DdylJX{NJJb|w(q|8?!xVoAMqWaLnxsT|(?}v|zZl-`)=Fnq
zB8GY_x3gm6Yc&{YlT$mA{YIp(pT|*5fu#?V+y|)N+kCYC&BKFQUauqdfgvk}kfudo
z_Z&UoM>pGC;Gh^
z^x_A8A;)=F#{GB!;PH7|9yyqUn2~EMgNRL^gKOxspYjnHnLzE|FY&e*jpl^cbK>l5
z&6D)bJO>W(^zM+29>U?IfbT{Lv06*NA?eg}<8GRmmrIpSxd+Ve2{Md@4rX0jv$Ey&
z^-uFxePhrcpRSkf7iVRoL#u(Y{-ogD=DsnO;IJ&;Uf@ZKQ1PKi&u)ibM1&hnRFw`{+6brNyc
zxJeh`ruwIRA8O)^gPQg)NAI<{#jt}~+W~$TajSO0>MVJ?cu$r_iIfx2ooc~B;M~%#
z4U&arQ*Y`mZY;-_sHMv*3s%*emvZ83q^WsXrH0hAMtaRQe_dueqiqNBp9<1D-)E8E
zs`No#>wO8+rLXmsfW}Dm$!u37M(fZ|q
zB3D1+d=xd6otFYVN8#hkh2esrukLy+lT)1B?E59f!$*WG?dC__P~VjyfZ`)bNxL2@
zf2V~c{qMznr;%xqwCKF`C@jPu*asHgzUbE?}q)#a_uknE>9+3a{c?*{cc)O
z<8yks!sB;*OOx&_QBBBj+LW2^8L2kM4J@&JyRWbIYJpu;>bU+^hf{5r^^{-dXd_wA
z=(v*H`b@IFDRm?5ssI6txWeYb#`?+`pv`nXQt9Jb`I6T4KpCUAi?Ht?a<~m7u^r7(>b|=!)`w(yZ(^{Z?)QcB|XQI
z40rHLJ6iDb#gxKc6`vxYllZU?M5tx)8qkg~48dY@oYvM6zfyNrgA=<5A
zlky@|ra3Hhm9I;=Vun_1Ic?N1&COI{qMMzj3SCA|IK^Hug-!0d6gh3A+tr$N09$kn
z++U5b3JJrylGTFq5Ia`qG)OuL79TMc#H>{2S&OO36|h7Uh-ZaQuGXejJ-Jd+MZk;>WJ`|>5o|&Se?bZ)u%t)o?4^!d
zLt3vVG{7ZWojX=CL|xVj0q&N$JvwFz#LyHqYiKjVh%w#ceDI(P^9vEFB8$#Zuto!a
zqM1@PgFSglGpf*ls(7p)3TRhNST?IhdL~l~pIo*QlkBy?xDYLEB}^+BbMgN~(^Bi%Ctz4%gg=abde9^$D)`XS3Ohw7=JQj?iS`o>4Cw-$WE
zLM&L(QgxiR94i@k0Lf+)7hNn_m8=12suTvZ+8}dssy|KFdg|M48g95E3%y5^Djkcw
zwi;wq@T(pR)lfy9l}PsdIkwu)koa=%nvdN~FX2S;s34lmH!K1JPKg&+&KrJY29ZFLxe53=y`7NQgK$IA72sv-$kjFRi
zeKcA{h!~~dBCBsHWx{njOZl2ry)aEMBV~TLGu~W+qIFWy1)|xZYE7Wli?SLOZuz=f
z0F)*Atio&Y5-&L2b4iy9bBB5_;I4DiUu7J%)06{03=L<~V&R94vW!>{RE){wINlrp
zb-?CWnT9x)HmuErMmFM$t@tsHuz=_dCZkQz6%U}yDDm1g4-lpU%faZAJuC(y!%l!n
zDOi~T+k9RdCIXugaU*VG-hrdssYwXh;5sqz4tb~LoCR18NpX>#*@Ih}!d+UbGh)|4Wt
z>3(vZ5hb(}1G;K+OLp@-XpUNyDX!AqXxb%*tecfBw*`OTf5eJF?L#DqAV5I9;6OkE
z{}L-|*xLNRaUvU@o>RsXG
z7zvMPn9(?Ri#9w9fp7%%u!&8~U!r}k#Wpavk%$2G{_X5vA8tG(dDQCyEqeDb
zKrX-Lb-pTuzl~YOZQ;PAZ8q6!eiczoqB3bjmu&{r0boPvecm({qL&q=lI@MgW0%f$
zy*`aDd={5{PMg>--cT`?VjnKbv;L#5hu(yWnau$X0Kfumz%)%GuTW}HE!!w>Tp91h
zt+sA8+$FceN*lS-*v%cWG5~hRM32#dhKoev&`GU2_IeR}V*q`ibA`UnzzgWLx$SM9
z{0)D;r=~#yDZbdYfSjxgH}H-G*~e%us+vsVSDl%AaeVS5m*vJm&Lo4Y3)_7&<-gP!myrGP{C`Hvq}!``J*>imam)YCySDPIy3hFHuk@odU8ycUH^B)VDncN1)@2^BXFSs#o0FDfCx&Z
zUGNy=y6JlRf(OH)nv_7u-Msu4(tJ|WW-LoJmYq$0foh->ObSeLOe8a`(5e@uP}hbg
zaQki0j`0YRN&@$`>L%*OiA8>oi+Y!C7A5Mdpe!1y^JS&BtfNWWEO4k9a`e7+Bbw-9_h4q8Go*0oBki)PYLx(#82}f
z8`opk{UGMV@4^4k5qzF5P0syM2Cb6NtA4W6
z<)iW)wX}GV*f;h4aDH>K6S?I*e{&Gox)tfOi0m*U4{LZ-A=)8I+f0tSt(s7nVbo3E
zWrK=U9>2zu5KX7=wMcZVjF6us2y+t3JT1?Q5Izd-ZEy{4Wq6bjsF{iasdQ0*iiWK%
zI66KcJ|G+zOhW?`D-BEI2OQ!QOwrm;Rvra#5>UuE6Qf0|F{0
z00L6^mpb|nsnP$N)0F>{FO~ndeCgk9>z`Cur2(C#JcRW%W0#OR#b2FFqeEYB@I(kK
zQUr{u@m&oAy$y_)V6CMifRy1_L(rR2tEM@kacLP8O<{4J`lq)94L+UL#`-{Wvzph=
z^Va%rfrt7wc3Rk@)E)cnNsgWOlaAv|`}=kO9B=$yIL8>s=Y4+oXKRn%Ag9ZOsUUpX
z5#f5z)#wYh%cq|p9h<8pJ>GmCV6o%d{0R612iQ5c2AuqReTgrHHvC6|EIISHjgSR4
z_kLp@-vQcXI_GO=U*QksvY|
zT?L4>fwq)ubkU`pGb-=J^N<`lY*kMH>5;PJOD>NZzv{c
zv1C<=28m6nV)Ds>IeE4ClDDzy2f4%anBkl%R!%YInvs~uu3Ii%s3FZPYGjFWg);O)
zSWa54a|0sX+2WXyglK3;5tQ@*(gFYxQx{vyptWfDwX;CVidX@wImHG(-I0g?zE!K<
zWGGpCk)vJ|nvtry)_0Y
zi`dh&{~WGmd{DLKN17c7^A^~Ao@~IQQ&6#5eaJ??8S$4*dvdik3Q{_n6IN_W9vJh{
z+Br2K4{5^UNX(J`Tc%{X<|0h`9LPj;E8H%rb8h+!iwM0IrnPQ8n;n_OCRz9A25KK}
zsvxz%ybNh&@T7yMBk?ZHBEKnV3s_3hZegV`-SNH1*Q_$m2}`>+OEX5A3RI283WwHQ
zE80OPTL*
z6a5up+fsqwfuez9t1w~y*H$oUCpD>kr>hzDSFJovgevs*YOFlKkkVaWj=GN0JvU*^
zbf=wF5jtokrFCVZdHPUSm$$Be-%xsDbZSho*%e|b2P49y`qC-4G040rSuR+Hhe8Fx
z0qgAu9sBd=LF}sJ^1+pasWUAN?NH;YO+&hg%7sRxx63=Ue@d5YeOsVro5qFcSu=Y&
zPO$!n{;fK^|H7SnXTbr1hxmYi>pSchI%Z~W?EOPq@JB4*>s$n}of74!-C@@%fa#Uy
zzP|m?@w}gm)vOHpRcANw>t=ge7~8N$%1L3%Od&=sf@U*o6#SBzWUcS#l4!`SMZQuA
zvak!2iiZo64BW~PlwwijfCLNG&RG#gihOWmDC*I0FHy+16`S9f~GF+^;
zKwsbz5e=SYRg7ktRXTRL>V4IPqzyyfb4`BK_0OrnbxM&^Dq_vGnJnK{0F}f~Gbv57Kwgpr+`$
zG8ldV8GVJccr>&94|65e`bP}C(4VkqWkM$McX5d0x*UA^szKsv4As?|tR@KC(nz3oGq1=U~KOQ_*#S7IiH
z`MQEfOb9gN)t$VWr8NdNrN|6fR;=@qPdNAX;cR%&7uc?`iz$W7CefT|7Ia$b`)*_M
zT{C(;hozm1HVsCE)6ZfR1Yrg2Xudiuna$#efrqxUZj+u?pglsCh0^1huNSR{eRUR5{oA~iOVm<+w5-V+>rDBZ6qY>1#OO15$0
zu`450KflHFNg*{xJ$g7NZ;LXwX-$QtGcT!j#UruSg5Ph>G#Q_P>a~b*=Z}}Y*Sm@2
zGTcY(5P^f)$x5P&nV4SDDDp}|a)_ELZqBPSs7d7F%+;#+0BYQ789mIQYZ|PTdAT=ejfr^mq)xi%UqN@70+7Naha(D=kEKYKh!l8EkD42f
z4%bzuq*2sd9-B?Zqt+Rn;#g+2G@d#FC{b@7J;!H;~QhNz}XK
z`Q;v~Bb3lO(?|N#hl+WJodX1u>X{w8ZL^UiCp2=m7!dOiaahSVJ
z;uDIbCKiA}@Pe2<7YM<)t`o~|$0bK9d)L#NsHdRfIfiB{7R-z?--L_*{Bx+T*?}dF
zovpWIIcO(DXD0O$>FQh7km^%nV#BmO)hv;Um#OQHrjAGbq8d-PjuNSC&7zvu=_VT(
zYZby)hO0|@ZY28}PoOG8aJBNEvi|)=5;;&{JDp3{D+fH-)y8+ryu?ko*>w7V@
z%R9V*C*+uEVJ!b271iB1)gPD1hJ4zw`Sd?fVCw?9=GZaV_mx8S`%PQ3Fp)1J;M7pY
zUqKt&-vD+NLk5v;7U3Wj&1>}rS`ac%)q|>sZoR$aIL(uiMATgFDqz{fr{zurLPG#M
zk8p_N2dOX2}^6*()ut%w5`lt7M4
zp4sqvsf979f=)5(yRNRrtf?I(G`#Kz!xEh^OAl(ePu#IT`!6p0SEW0vNjNty61IFT
z;`XC96xg;aT#ftpewKvQ^_%_j`gT)tzQ7oYo~ou_*qz;q#`CfjkbQp9-^B@4^VU6j
zC)iop-5igS*84=9(VUJ;!x-Yo6z!KQ*)wAZHd#`Fe(OyXz21i=*`A;HtuVO
z4i>Lpq}@?z_RMwJb?=v+N@~FNMZZbMg~4+ay-c2RuHY2l=TpM_lTrB(7xSgYH~OqK
zSbeTSmWpE8nQwfqdfej|@zphtRtz`7rnL$B_GG@Q0L>(RDd_x0Z`KRY9+*YS84WlR
zs>idW)|iwW(chEe89DLjJ5n7s2dC?mAIFI_g8Up@!-*WS!O~@h6yEq~(7sO>DsD*S
zE9O0Nrg=_F4Oi-YH*A|DlAC7NP03F*i3m2$^M2@_h5FYj6ixJ}o1trhsc=i(&U1t_
zAs1M)gnl`&mf*uRMr9d>v7OWEjDzGZ#>acySj!Eoa?jlDj%osfYoLTVwy{sjwCUB<
ziZ$JSV3@r)={V<0&t5UM!VLWm%{L@7vWMOH!kEK;HY0GGVV)iWiOW;GFfEQtkZsrW
z#G|*}L0Rqz){x#j4Z{TeE^l_7q2w8Yi9M;M^!HD5&E}S@>dWx%)D+N5i2!ZG?b#r%E{{|cd5ogj
z*n965-jfXK<(>}si5CLl3k*PY>Z-33
z9ujF25`*fIFYOCt8kXB5te7TXnqdT(HZBX+b{agwIbfKrO)eyLohT=}7X<&9_U^TEKYYn+$BW_FwSjaB^_E!G44;-6i-X|eaGyu-;Im}CgZSBCpnWczlX
zPrH&&xx_OKhi82U<7laKVTqVz1O}B{VTXp5TY@w611e(u-{#%SE$m`!GI)KuG*2GO
zDUr%4j7w!6P2iHvNlwtKyCW5?#it`Cn{-uIK<`{0h>{+nxY8!GLeXM^ey5tcxKoY4
zU$R~2R}u`1qc%lg7r$Q7pk5F2rBC=Y_d}B7eou5+3Tdv$NUF&2a+njOjpyj3Tov9m
z9zQ1dBKXJXvygMn6&e-@2!IU)r1QUvtOSkz6f6ymUH)Z+)uaLKfvbx5)iq^jR-aCK
z)eH?k>js-A$&qOj349I_VVg1E$W@C$N6EaFEnB=bX=84l38wNrPFh4kMGIlEyeQ|$
zA^|yIUl8r)cei~fxIOsS&D3RjGWiGN>;3eXZ}(W@4F5ajkL1d^SnoS}=$n*Vd;w~Q
zIE0(zTYdrRS2L9Dn-MeI%KRlF{!NO#T7n4YdtfYr%Kp&XJu8<35@!B!q?p@1KP>cI
zf;hv8(NV_NYe6h;lc<+F#2BfxIL5OPCEO&Yp%Y^tk2Hh@Kia+#&S4Ti-iQ$s+>?g`
zpO@As`Oz2Bp7*3E3Qjt1fdKi3#2J+XNguW0lUA49)H`s$7g2%kU7eycb$F)
z()WZs{%W#CnfYtBrI(_V^m$tCm3cVVu8t*ND^lZ&F^Sxaa}y1T)Zy>Mc_WSV3yh6v
zRhbY2#oK9I$cl6uGKEuz{9Bk2m+S{j3#;OVtTg>~G687eN3+DBrWQ!CfL5%DC<{PW
zU!$0ccO-jZiLG_k-g}~hrapQsCHqi<75A3Ns_a?RTvD@YML5k;qjTh+O8c)`?zBbB
zW1e$zRpQMdCa5N>i&jGf>t=l8(oO{q7jJlB{R!BTn+QC(ZF-h!N9PN`axNCuVx?`2
zNPr$oF}Ztb%JlPf-U|Nm7#Gh8X^?lTTbxY(@MR~ZW`V1zp@gM>Wp4{d=a2E64A8c4
z?D>o?Kd~ew1=bc+58Db`q`B$9#DKo7!Hv55ycnp==^y5|SIUX$3DOwJhI0yB+r+}h
zEtP5UB+DLR;dqU!N>thJvMP1E~$>P=D{N?4ipSXPlWV;yG0(_2q`
z3{_lX)SNW*j*k7a{2VZFEk{RZd)#rMtga?8frk=sP=<2h5bDKRGm+m_>nlw(ODl(~
zf$JsUk4z0)ix+Q8iub76%ci@on4o$U65-e~;-@vVdMuyK6B^Z3tR)N{BP+|s?A$rS
z>kTLiiWY{Fu$Gf3*;))JDm+k#sVf?pG7pg+OPKeNYZ|hQvPF$Fj+4mC&ye&MvKzP7
zOk)aVf`EdHop>R;4`1`f64eZOpwNRN;TUW%g9%HVTrCbR&lQ-a1ZCOg<87Ewipk2&
zrywkHY|-%)na(Y!%0y|Z)8LCTT+C`~i(f}EJJnv>vo+81-fY7Gqcs8#L{*WB5>
zQVhX?7x>(Yw#to3D!`%ZD&dFbGg1o03;GD6!3)z^(^SR}Xr>vh<~C?8R%75HZxAfT
zgB>GATI0Un9>Z!0mD*ELXbV{&Ys`@;YtvNHFUf)W#sc8eW0;DR$AWLNz#{O&!1c5X
zO0}T!R4?#;6SJNPs7~0*ug!gDI%Nhxsni}+%?dr^Jmv)%_~c(yr@{hjE(Q3p)_~w0
zsu#Y`pS!UyC_~Tave5{blEj4ry91?xjygpKaNcC^ntcl%0GZ5{KQ;43z~Z4+ixz6>
zrowr-Yr06FxQubNCip>d3VX)YPj<0=@gSJbz@Ga(dzjA{e+S#ovfX5lq4%9Jbta_>iqhUIUAk6kpTZlHbftqzQV$BN2YzN$ZXyPnVyz*13>4jg8GhTD&L?<7PFFWmf$0V)MPvHWXJ4y
z6U8G``jhi0wl5t%UuS~yfm9V{gVwZ0BCS#3$Z5TtirJ!5B$gSxo)L*hx_6?M0XWrm
zfh(_khZ!Y?@O8_8ys20%+tA`tqUP3xmn{iz-LiUA?s_eLX
zT$nQUUY(WPxLFzPooa}}9+Zcn2j;N=W+7UYY=&@C%{tL}jWX$WoBP_h9x!3CDcNBc
z_%y47VwEj+R4ply7hz<*7U!EkpvAy=V~v()XMds}?K=p2o+?~bbtcs2v1vAEC0B)6tP_CwCg
zF;NGt5rwmUcFo2)go_6g0TEF6k%~7e;Z`Gop+WYNogUG3!a2E8-M2H3Ms4$T=pM?7
zL`YMIY7N+cz)G>Le+P6Hekb87iI3uwfN5tIvp7O>fls}5+dnQ!-yH3?MbXfZ@<7S6
zMGqGKW)S0`8sm^GomL}LC;>EWR5P*vIM^@l>`bY!!yOJ#*lny$LvIQ%tDBoRS$5Da
za0e+l0q4xN0gZ4E&(e~nuc2^fAP;3Iu{Z&7vTnh|25
zN3>o_f*skKkM|9H+ChXTabl4>U%z{u(qRvZ#~Cdq~a@wp{TL+Jm-9=~g0a(gW1>mk*?9$Akgo}ELvuOsBC1^rfw
zGJinMK4mx_e}#SVm
zxwj$dsHgY77>C*!5amk2bwqDPU_U6@igR&iMy+dK1k@EexWjxLwOZWoNHa*<+FGqxJqG9(0I~@oB{rR!G
zirNRpKSJ;X|5X9XKV5@X=s-YP|2qh-?BZl{6r#&2@Pgw!6J36eLZw5HsD7}B+
zHr7t+9VqmLF*IFvbxiu$xeK{!b~9TAx1FVA*W0P#Mq^`lFukGYhNP`VBx&Q~_d?B6
z4k=0j-h_Hc*NrgA+iO-OfNyT_lLAgWafWH;U1K^XyM@F2Wo&wx;a0sXjnTI=Di(YW
zBd_58B>V<=7PPaUjRW!QC&AHde8}S&Q-0O@b7qCVg3?WL?OZ$X!8az;QcmY+g?(mV
zCN2d@=<-egKBF)Q8!6RfC%BeO#_5GQ^_k{unDzeCrqGafx`oI&ts$Lsfvh;IdJ9rk
zZmIkRg|^m%hTfK)-^mSsPZ=^9YGyB^E-7gV^{2;a3;&rTtx133Jk;MsuSSfj4OzO+
z7E&gj?>KW8BeY5CXajYA7ffo4#~xobN_j_ZCnDOFA_OY;>wLcK6{a#IbtMG84FF
z_Lp~VFY(b7Pa}W)inCn9i;>m(g(=Qpj1w-=!A{DGT)ezPIxa{lWzhi>9^$5MSf(I3
zyDNS2cA+bGdD(+B=T9Q{6@B&f}=q*We-7*(D0+O}d$~LwXM*DkH#<$L!DDBZeB4CqCR72rUz_mk`XhVk1xL
zFx|H-B1ABYEW7*z#Z^wS4^Z{)NqGx-EVV8
zlpXg5kzOr>TGcUn?-y)|AMrs%VD7%TO4=9o~b>nY7Y4XY8@Z>1=HaFn$605l8+-yDKm7?jv!gaDO5-S@XFr
ziZ{$&D)6468RbBC*Su&1gU0U;q
z+sn>H7maSTr$fvcH&ncy?sRUi*^o*NyM=m|=xtCP)=lX6SrfvrRRf}7RC>TB)?Zca
zB^{F1>3ky`re!+sq%|&+`CqxbShWZ-#qk#$lT$eq5B!lLwqz#EfIV}bY7rJcqd
zWFA5zZm^L`<7AhkClv)Zqz9Hdlx3QfMq)NB7dH~IDWg!iEp!f78bnCG?ZbS^24aOB
zH9@rK0E=F(Grb8J{4=XWMvto~bF!+HJ&CD&bqeWNZ7;7{GWQKFjP~Ye!nYU@ct=`X
z$#mWHB-^l*reE<aSoMl(?!JEy?cG=JrJW-1_{BK^zxl|8A$j_=I
ze1rU>_XAtj&N10ul{M4A9SVSMGu`ARw?m}iO_F|
z-x=ued$n*6-Uk+W<;d|1kA*8cP)rmj>S~kgI^o67{6SII`Fc6tvJVP|!j+x2&0Z}W
ziRoRpb@)Ll_l6d@S9MB_~d%#&!D5`=iX=nOE
ztjHSr-W)@3^2MA>+WfRHr)XtrEmK((wLoUWkE45qN#R5d8L9K+rnM?{LtiaZopV2(oRw}(GZI;Fq
z6Pp(R*-U=
zV2|x%xvJDTK3tF9ypRxc>KdJpl5zkif@gM0lyB*g#B_S`I`scXeCDAnI_~kOYboMS
zgO1$)5TE`1`?voK&Hi+q{O#mlJ9lgq$K(bW5%C&Wi)=#b9|z&Jpc&omY(UCNp-5F6
zowFs6=Dny#qIXv~Z-ISKjrLQZ(40meqISGqdvb$k3a|&mozaSNRd;hbx1AJ8#B`w@pM5oG927g5
z9^^x<6{xrZz^ExgRHq&K~Zh1AcshvgMI%%{ue&e5deDrUK?@%XZ31NPU&A`hlkLtresKc*TIv0F52QPAGZ_r1?bva%1No$Jk43HjCxY`0D)mD)E2X
zVD$GfR<{4sMolVOO;D&ERbGbqY|DOw
z$TgF0SmVoA-!vhRcS;y`WhGhffPE+r(gP5c$D{9zPJF(m*I3f^dwRaWYC|v}mSr?N
z(t1fyn0VQ1t4*eRQOF)3V5HDx3v1)QQw5a3Er0gyU5_|@Jp8t*nl?zC+3damv-3D#
zG&u|{slin8Ccc#7NP_1$z3Z`xsURo?;0^t_1RuDx7Wj391JLN6H3+*2CpVo*{)kie
zI-%e#@1OuymkmCFfakbR=5rc0-MC@KP33dEZjDE+s)l-F{ozcWkpuOcH-XnlBs4UC
z>7MU8j^!}tm+0wY@N>un^-wu?Gsm~Nm%I0P{1Ou4vAAjZ&wa*iblr$dwz)`Nztf7m
z`h~vCi2gXZ#hy|nSXd3BPt~^$y^0|cG~L1_SGL+h7&ls*{=BB-MU(aQeACpzm9j8j
z{8oMUW;&aL^m5;6h1Z_UJl!u?hvz~Xl9kNBELWaGd*-BSO=rV?woUl0Ip(doU!_Dt
zvjeqpxswG^Ll^68wPH6!qBX`4&knH82CY?eVo$u6b-tn7;L02#<{7*UP4H==nN#Kr
z5NWT)57*QLk_OO{Mzrx}@GN8P@=A&+;z=zcifs^zDK&;BalH{{g`u7#fO%#wZc%Nl
zxpk3(P=L-Iq){$J*ainZQ-@$~_D>RL=mEI|Curv%nd;tEM%m4Eg>14|&*OUm+fnl>
z>P^{|)p{SG|7fI!B)0Lre;knxC=ig+|I!gDSUQ;g|D92l($1eQV#LpsZ@Y$|nfT4MQ@8pA0Qqn!l#ZVSqwwL$Y?uYbZqp3NYdABLkco8I=2wW|-!Bd->1Bz5nFaG(3I&Qq}9$VOh&2
zzj`9>s+Z&-S_|GXqDew8m0h1VN=OOT3+pv;XJ4yNmozsQCV|=yh=AFK32ey+(SotW
zQTWcQ&?(<}19}6C#_;Ren`O;;{;=RP-t+hN?~m@AXTRqOWBHvg!XK{rBtLj=`N410
zZv%kJ9Vz^;VGIPm)?+(BUkLeCVtqNsbG=`jqXeGITN%Qra1nOF~(Q*}TCDCHbUsMn)ZY}@xGz;V^-f4p89^~dC
z7}0h2_H>u-OH+5_4yxa(g6kg?)jXUyqU|W$%6`7mq3x*MWfK~`R0rPN%|ELaYV;FO
zzT^cGP`x+;o$Sh?3GCgKQ2U|xuDx){=Rg^d_~q@U!uX+mNARoK=kR&6SACZoy1_a^
z@Tm|ee?f_rFMnYnxWhp6SN-$ae8~3gc%BhZf0pg*!{n&l+KYZi5<*f1amBJW8LR~t
z@=f7Go-tFx`8M?XaNR5*1bTusIykX;l4wLOlSIZ{B6s!xYYR8L!&+p8)21YmM68C5
z-7Xz)232_`tzmp;GaY4)x8*j5aQGZvL}a~+auz&Sli7|+cs??hJHdIzyYY>0PvfbO
zCaq=JIz7fQSS~8*{zRtY^m}Xs=Y@_UxLWFb$HW~dpA%`n*Uhz<(sv!=+DT64>2gN#
z=As7hE+`jLW-oReqDH7ZQA|3e)z~=1`xa4m9hJgPz2kjn0J*IBqQgA2Kc#wY7)4qM
zNPrrF(r`2`WxbG%8nONmOyeuG!KoR$lR>O)G)^-MmkH-*V8Sp78aBr1FCy8sw=_kO
zP4hF!r+`)h8zW99195KSODSYi?qqhG{v1NZw1Vr+#&ox742^Zgv$X8rU{+pLq?#Rd
z47S*yZFPnN-5LbbnDcumUS_#=C7#!G%bW#gmAyZI!Ed=$sw|JoAgaB`CCg0W;!wz@
zsZonw<1lD&ce`?4tQL-KHFjuUKOJ+7%|?h*D{S>8SYn|Q)|3o6ajT%CvFMF%DwRd%`h(%PNYk`H>n%br8GF
zQ1Aa((iWS#GeXr!MPKVoBah3C(+Du(*8>kcv#}?t9z#T3dlX@`Gd1h-g9VVI3i&2HdR?$C(oS#AhgD
zPkm4;Tsjirvxw4+QM^9iI_fN;2abd;W!`91hZ4}nb5MpC9mVC&9a~TppC)~#+`+8P
z!c&`;LHE{Qigz_hCZaK?fK$T}9WGN6jv_)+tP02O6ei?dfmYFhB}FBcX`GU16KS?x
z!>(`DLTSpED8XKR~^0}k_aG$gEyufDo+4iMXlTK?>JZ4iUmykX{A&P
zOU9OgxVQz*Ec(s?j}(3(ST_%(G)OI5Ieekp>M0rzp!sQCs{uGxigvt?NnUp;8zRv;Lpbz5=YSBxxIW
zcPDsocS(Y~2KV5>-IHJ!cXxMpg1fuBTs*-c0fPPHo1JBcnVp%Pzp?x9oUXT8&NeoH_LAoVD;%VMvV0ubj&sj@IxdXjlo6bqQEoS7TV
z)-kKN?jKcLlSJq(%9b?p#D#Cv`+v3JxZsW*6{%tDXm@`kExeEciU
zbLz00K!Iar4aF4gS=lxJ_t$vrW)cQmoQmo?y}g^+qJSus=DsR|I>cI;V)VK<+KUX0
z)=BPXXCAc+(PX7|in5%)Z-&(N%0=l@n(w0STog{a$E)FC^RkMB&IfPl0vA6B|@4Pq23vFJI1GO(O
z#IksBau7XabR#q-Au5Uy^)lkft6p=8vbe!n1ROV6<+@#C?uT->T|p-(LAM~?1^_*S+cC*5r&TO$+NnSC{bz#0@+h)zd3FS`*@LB2?0TwT
zc5&2+p|QimQHjbd_>75!42cUO)sO`nJhJBmBckGAG#i*eWFYWWuFfyHZ@6v_a{q;>0_6wl`kKJjQ_qj
zUew~7DL>_^eIYRIk0qU*2?r#{yJ^g;l+Sp;!Qv0fj$Y{(bU&
zN_UlirN=tLyV*Qj4NQ(10wHwP5*yqkav>#WQzO)_BAMEWyv6Y^<4JjV%%M9P(j)}@
z04!q*M_f&E19(t>im^p%VN61%ZL+03svjfp1+
z@fDhAPU!maIRTbMWCdJGCHB<7DALup*gW=lV<(?x<@AMW0Hy7cZaZwFMV*8=d+s3k
z$O512k_Zoo#@|~TWR}yI2FdQBUBVVs`G=nUiG90w8G=PK~V5fEZk%kCN06tVA
z`S^0Z;LzhFIYN!!B(c0v!w|j1bzw!HrsLRhZ&>0
z__AJ@IuG7!J{Gx~p&73{GOL-RJh?Q@3NIVT<#hcr$4eSalAtyw4(}x{=F!w1sH&~|
z*Nzp@F9tt|RC-HcBsLghR5ORqEW$o9{IG~naII;Z=fBZ9Hd;F{UW+ji-V@Z6DsxXb
z1IQQ;PJXki;q`Kg3e1I@8aPy=NcCo1jc#*6UVXtD(T;ygDK{yQwS%q^o|z7A+m6`%
z0XN`oV*Chwo-F$$E8B>pB~Ki>)HS&kxBe|DGRs*+FyG5a=k8H+s%~KBI9mMTn&TFRPTRAk&1%r0`Gx-bhZiPXK8N(C2
zD#uduEj(Zm&70+@%Qc=(Pbwok5`*)Vs@6tj>2-d^u*-Ys-|pPjaB@fRpg}RWjE-{PbBprtKTnwmiCprvFx*edbr?$HfL&NrGzE*9ikgbHca#12Wq^2k>c*H{
zJ<7kGdjmRjXXWz9`MBw_>9XZ|?BV`i4rIwz#V4>CtSloVlThS3VWNVl=cSA$O_=$-
zZy!bso2i{fSBb|wjc?Fr20kP)fkADX4T)4&Oe(e?<)&)w;TX4SJ?L<0(?v@^jDvQbPKL>eLdBCXlZnm
zPm{cLnT74i+@XmH7c2SuQ1E%IhVl2K^s%Q5$_y5Iv=N4?IvJV(hq5>n;jDYDof{L8
zEn-!h2uaiy$;o9D762ciyaXBiFj_bxg(Rv^7q*f4nCHv3pQEwtm$Cf3jm|EzG~9f1
z$XeMnv7j<
z+&KR;tCe(oLr61I=%nw4nw=J==rV3_Gw%I&0gRHYU7VSQG8#K)+wT=ZKfeO}Fg+7f1?4;6}I-K+2#4mYJ*p|dsanj}&_4xx7>8o4zCi1=r
z$%6f}#EKo3v4kv<^yu6hN9bv()@<`C3$hCY=xIU(l{uBk<%;0cfqCmSVY-_*LdUi3
zxU-B51F#<_baY^_xWjB54mzzJZn4^?PCb`L+b4NGgwIh=mnJW7V#1|hthOiftag%v
z88QK^eOCj1v#@)VZwAEE1-5w-iwEY
z1p;5w6QPJjm#E>*wovjgTzSlKt>4mDo2r3bSL@Pc
ziluwO11wqQT9`z<%`#3ZvgAwYFK>(ePAF!KE8I0)j))W{DxuZCjE+=)-01VibkIRu^)LE0z+`XQ(u%7NbZT;p#Xf
zM!&$K>Q|fWUqFm&zopd*d0Ql=E#Fdw-;^clcgOh!&|U#>+j*Ie$xyDcQlXD8;!1-g
zPt~U3XWVm;Qc)Pqm=;oXJ=
zE2|w9@I8)Pz}JsTw2Qv{D^#IuDx?}OLgS2cUw#c4=~
zfy~y}54w5_@)oWPv#EjP4^Z1^R$1;w&L@rD8))wi`yEn*#@Z$bHC<7Q^G36G5qKof
zjvE4Ibl=J3v3^etvBR|mySEYzEv~Fh-`r`C)KtU1hMqOaIyH6IA`G5tbh$vYGV6=q
z8!_Fjc;jt_@S5`~10R@#>}H-vyUK0@8_1#2MC}Yk%Mv*>&w}|iSd1a#VX&^crb|bw
zqpjjIUN(W-9{20h1%RXY)PXGdOX5ofEuzc-Ii(WfY*Sv0L^!jQoJ1vz;wg;MbC*vQ
zNN9^6Jp90~7?G}-1^kSBPoch}srZu18AO~-zj1*wI}oGFB+CBAn~CzBi-aJHAU!7p
zK|g_yJG69b4rY6YZ+nA@NEmzLD^3s2hJwzQg`1=rijP}MsBY$D4`ce?tBVqD7}3gc
z1i6*N?s6<~Aqrs7qeuhwmS-cXssjgcl#6`gQ3`hY&9eBR=dL{)NLIYFpyJL`Zp@WM+ikk1oi`;LuAhg0L7`;;o8$+CcqQ1+A4ZyF$F9DV^
z0rhjKU&)unP6`-9H~cX`-+uK|n9e1hdU*CC&NZ@D@_96&Ha^<=W&Xck#3C*RMmGQP
z5>}Lv!)HeEM316_ONRtATYqg$QP|kx({Q2yDH1CD!nvBOW1?47$9l1?2R0D=)hA*<
z9A4CnD6%-dP1iKnbJ6cp=UrrPy4l`IwdvDuBnK%CEQ8M
z6h&tjDK|vDmu&eUgO5awd{uavv(?m0ek4lt4PzpYIKI13)1b1nu*&7QYn3z{&WH;%
zsI>K;kbNz8PjNPDaN}!AUM-Cv*oO=U8;aYwMuN>bd;4v%lPOnt3zt>d#2AG}J9Q2H3?TdBPsQuye-XYo=Q(yQnGJr?&Wpy|gjb0k3E4u|Y
zF85YLd+W04s?U+&DB6-vT|fRTWuY*mH#%n9n?l{fp&iPl%8GOWuK17h~1S4Rq0
z=@!YsPGAd1V8iOBb@rdGy}B{&^Kdn0biS}sd34=-DwiJEqGK+G4wU>V!t
zA)Ce9gDGNwTo20(B*UuC>lCpt8@VYvMrfrv4C|PrI@FnP<-i+Nc$ZLLjb@cj#b(*g
zucuI;)>{djurAfUyr)>8)|e+8sMhi00nRWk`JbF6)Ovdudz!9y`AJuY!d=q?nz+8+
zaN8($LkoLEFuo!Oc99B@0<%d4D1la}RKh73%oIS3-J6C0IhcNNwPP55vUMU@d|Rz{
zX$pZrIf;2+cafCs{u{2HDdh&@^ukV)Q||lgW?%a&um=x?c5t*tTdnT+tA`=2dsShN
zSod{vwAL_d@hi$!3g8mK9UDe>x?pZVpxlQ3s0H_hC4v#yvHUfd`r4=y}%_sG&H4wlg(vtFK>c9W#^e
zHzZa3KwvFX^LZ~VrM|-qaEl+eVhA!+K_Yy#cNXP};LK`=-M-sU9n9%wPh~5d&!S*6
zrxhyvI3ob4vLY*DnMN{&WseCXRvgjajwrL^#6cBV%TK^tGx0K-O^ADEN}R#!bM$}T
z_B`GtacBn(Q#*a}Nx9VTt10yj4YS
zh=av2&-(;1#SS_KmlupxJc962{1MeT3vFNQ<_Cdrs?L!QaluoOO=8pi6G27^2=D|!
zHM#p8_jEB*^20biMIAyQmC4uB2Psqu{9g*9W=pxjY4FX4Fbj>U2?(6@U9Zl|q+zc>
zbF-tn5azD=5xx~9MFnykU8@H~ya~!hpU85NE1?jo7rwCQloAqM3@MO}D@kA#)BJ1-
z`YPs>Y`J%wZB2r__%#}f1?gF$kYN&ldJ{y{@D>Ld?kX_k(LIU9sxu=beG{97luP_O
z2KmL;Mm(hp23F&*J3M(E%BV6LMbweAjtn>PEDjO7*zPg?8AZa%nm#@(AN+LTuR=rC
zfP7s^u30);__)X$`h#rcgJ>rKA#1j@czkdGeF;#W1X(o=EypHVsSw&mEX%=d1N1_s
zqMpf^9^rP(2mT(tR&RYZb}HCHUevjP443f2P~OoipO9BTx#{m&>a3cg)lNrU6`RQ_
z_0}3It!Al*$tFM!+>gDw1s}Tynz6pBMX^Y4ebv_(d~{sum1mUp?!#2Dildw!>PK>QkOpM)VZXYyK>3~QK#K~mfYhtyO3lA%rc2k!(j+KsL
z?!I&F%Dv;x_c2uIG4xU%Dgn&EmB<=@8y3Tsx2c;gjp=7G*Q*^>52wO82iP`6O_JK5
zS~W!FDd?H^JLgpte>XRAR0#rIz*Pjk<%?}Lai-nJD4lDt25c}-aSi%MW({S6t}
zk0J`^;wY6Kpdx-Km&)~mftrc&eC3dP#&2{)yPx&OFcX`8WlEKM?m?srN=QooyKQ5Q
zRNb6Km5VI7w&g|ePKma>VHP;Wy&DByD*v0h>)oc?V4O#%5`1I20`l1Y1U&K`E_N)c
z8h0}g667J&74bsOT=p5DHre_H&aq3>fz!isHEL?5QucmtNQfC*B2OMK{mKreVo~i9
zk@3*&9f7^u6j6Jc1sDTEOG{V?LcX6K+foT<-QaiI@
zX_#W4l|L&|7cE-k&KDZ&GOff*vPj4UtMm68@Hpzidkj)wA1IKD#Uuw~n$%Bx#wZhb4
zS2*7UIo)XUda1AtXF+gIm0{=BK;wZ;6~I8Spya(Umgh#?C-;)Ff%h~IfPopeE#BzD
zH_3%>|eCaV2wZ$=P+U~i#1bR#9MR}^KaEgHNT*#oQe=}o%RQ#$Gtid5`u!KWaL{^;0Tz+5rIpRyZ
zTh`j^;!xq*KrT-7V-?`4;En^DE~ma*fIa?%GpaLZPw^aw9c>{o`DV8KAuB#p5Y8d5
zydSe^oo1&iwr@4VN#t}FmmrV$ZR|Rik0l8#9|ZE4-hMwqT&T3cHJi!-+;qG^OvenU
z?i7Yfno#L+(o}=f7KVy!miG%>HfWDI*DQ}YlariJW5=OdMr7ct{WBbPp`2AcqIGU$
zJ{)$37>itXsXi9fk(OF>xFu9W9EK-b?SUQy8UwoRveQ}VXuF~{`qtoyWg0
zoUPowB}P_sOriR?gH{)}>a!f3Q6tsfKij^tHDIR$&pIz|vceQ0Qy@d8WSTDOZ*32y
zDQNg^7k3=LCfmYx0hiBjLw36UWSawk(D>M~f&eQqZm4MlOeA@$%vShBsta9P@o-w7_|gtfH(95&cs9)g}LZU
zP21LXvkG)@)|V6pgW`v0)lOM9WKva)%JUIB9^1;}++&^9mIcUTm70=eu6*%Heo7zR
zEeX9waUG%$h;*%?JeB4<$m*v8myvkwcv<$w)_WUgdEky2NY4<*seD%QU!>LGi@XUm
z-@n>jkaZW3UGf_%=sd`NK>n@ejMO}|;HSR>*rWCAuhXOn>f4(c{F>iK^bZp1rp7MG
zqAOqk9<=iaO`*rVU&47)9YoT2zrfrgPm`3HHodSi6(g8*a^Mkhg-ZWKb)qPZ;X~QW
zi@w&;O{MU_&yPfo*Swcjds%WlS3jrWetAnj^r9{4Kf93CV;PLkJ+E)9(et
zJ86x0L7YBc0*2xQ1kwQN>!YBWJmnl^EoEl1@zi>|*enIRIQpgnUL!A|L`P2{Ic0+C
zh`|ISDteTL_i@rDDjD=>o-Z@#G+cesjfbNmOEFXtZ@gMH)+Mk7EW
zqzCg@xr-AfE&JRw>frE=&FE{bw(V8Sx+(~}Wa;;eSnIdEKAV&Ip522xPq|@ySNb`
zksa7e3TGgq5;%F91)8-SbO<(POM4dzu*q$69iu$Y>ID4WqiVIe^|odKgCN|7BbY;@
zJ#$_xVBX}4=%erw^vmOh9U)>d*FLW}Zv!q#sp22@vt#+~wkZW>^b<-y-dA4A1Dj56
zPE5;3VSSm_zg#GLn)6KJwZDkPNa>cBVeZKf*@+KYLM;5$#5L``X}ykMKQ$A+Hn}vm
zD}9T9`;NEOr#)zT!H*_F<|s>B559|y2cngftMr1F7ly(q!;)mY+@kIJPKeDXEW>Bh
z^-Kf?Wm5o1F7qOYoRTSs`kpz*bwH}X7AlP8JpVJ99}^juPxUaHKHg1g2X|Su9!~Zb
zm~0rDxeZ
zuqzg_8lT~5L29=kJ{IqIXdf!w>4(G~Y&w;zD+vg>Y!?6{*%ghqG9;nWRCRE4xXP}m
zeKcI7Nqwj`nI@BD@&aVOMJ$IkO+e^UZjeDt3PrX&J7xhzws`t1Vzw!!4h>Gy$Wl*<
zg4020koG)9?m=BkTD?@0@dESE0xYjCeG-LUZ;h`HCt0n1r%pkWy0c!5nSHkUYgk!(-xyxy4^5uoA-Kw{h>==DZi>y*q3Q&
zu?_|IYIGRR9W*Pbu?%7zZ)bk7P>-eLs~8gLB0-x|f(CbtK{v)>H$Sq1+F-*R$<_$9
zNE%J)*OYtz;^mNn8xsX9kF;FUuo-mWZgUMKPKiLZEl(20KrXzuJX75JQSld+BSq4|
z-ZtoxA}7KGjd?p#2eP|2rTxvN>%d6*CRmeUq@@Lxp(9Z4J^vJ%r5@wgxx5f~t%j(Vs-ynh@H>>O*7uLc|!;-UfCu95ZsWXkLZf$?B
zHm3(H@s?(V)G-+eMXW`G6z#Zv`+DA6kzloO^4uJBEF8wBd1s(O`{j6Ma_FAnQ3r7F
zz10P%NQ3_eL@yYTGHg%z6VOA!y^L3IrD{sjJ(n@d>2bP}-dAbpYYdaQ9+9^JPROWv
zm^O-Q{#g%U8iN_=&uOT=yJ(Sw#7m$|F|nE*
z2EIZs)}MUD6vFziQO@nG{FI_Rs~vpC8ags!vkM
zLxFP^^ts3(osv01MKD2FB+{|aHxb07x+dH16`CS
z18rZdl4jk*u-__yFNcJy44<2kgKV+$wDCe13ZQH$We&fn&$XUlQ*sS;A#3*@D=gT3
zi!o=~^W6+dvVa+OrZE39l54owh*&4ze{LUgpVI0&4>Vq13&4L4rL9jlSJbNgiH~C2
z1neT^W*IzGN?vCL>n?vCDK-fHq2-_v)lN%hD8*?_KKctUxzX;5e2dFzf1HzQzh2vaGsgSAY4#JNC>amz;4F!hT&(=AEQnLOel(
zp5~;#ArQZ)x(bb!?W~=0`}TyypM|{WT^k?S*vep_GrxhKcazHC3U5rj-Qls4Eo$?NFCs)
zs1ov7F5p>SuGc%x8N_Mi*mk;NkelY8lB7GQv4ybEK}DG8_3NQF>#(QhT=6rOS-RN4`O*8(8pfZw
z4w+9!UThZZ(NaaSOuANqk*WloML$ZKwDJbEUMf-0*X$fB&S}}KR54rX&zvCZ@+cmD
z;LRU5j+RNMS09PH-K_Gm=_qWXh-5bMW9xxY!~k`@Sxw|XSJNXSDrV*GajO^PlM{&Pn&xE
z(x6rr*Sfy{N{)T}ozKN9=sQ>F?QwDZm}tc_X(c3T+_)R6{pfHn!%u8@+&Byou_QxO
zEkJj@)4=eP7Ufn02d7RslMqs%X%_@T)XdsRZv!wc$?{L&zuOHI!i)kG^pM!LK*tvzHlSO9Bc#7dO7&`Ej7p
z{nfKDkfk%h=TJHvfi12%Cj&buJmNZe%QfhoXd}zeMf&UC1iZgagz-DHiaok2#u6#G
zz1`=RJXUsF6ZlbBf_}X5k*ZC5nlm+>dA%=5kQ6SE;Efx`q&>vGlDIB-q^4d`Cf5i~
zje*Y~VFqFN6zBQ
zQ{*?IY#!Boq+}XVU9n!`K>0YP+hK(4UP#XSeYQhs29Z|9K|JYQ58#MeFDF_$nN&F{
zD)sIgzanv7%G;w!C!AZ-Rl?&Bmjm{<9=djupC+Y)Om@$0obLI!gJ~%^Bk;VXGt*Pc
zLkm?D-cCXZi_<2Rk;D`QtZM0s4A}tUN5yHI7R@>OkDZ!q>TRO1s~7m(oE@*R%H!Dd
z1o3GUZ7$g~&BR(`sM(SFBz(3E(85sIhLRUX=$5}8@V!B|rDk3KSgS)R`-ULY)I_C7
zzN$>eNP=c4f`-hV-nB~@RgAw+lEiJX8XvCgi|7;%;Q`mvyImQqC1y1BcL$C9Ll=G&90~p14n39&g7eHa6D*2!xJ5dsM
z=^ Y8XySBp8$>LO%$;4~-jegaj@Q%rgOIRU8cI$}r`cr+<*ZF&jq;6Kc%T_?Z&m
zx=+xo7wDLd(_h@rr@8g%w%$i;dC%^RN}*)Dq_X~^i9r!xdWAko5vt{TE@YYlAoKMr
z&{nu`BGY-xr)XPK9OCnc&tXY7MS|?!e8Xg8Rp+LXFd@@qY@GX6v
zK~y+sAsGIsD4u1R{MSK^sq}Y9W|ETjgE|DRqAA6x&dgo14(j*#1(FrY*tTqW>eMx2
zkT?EB@5^Q883$FcU6(EgNl5bHcI0s;D(&blpt!JNz62Y+Ko~GqSA;7njD+FDSDnCA
z(v;9~URDTQ&(P5*6xr5aAd))jV>f>y_tKmuX(jRc~(_Mv_cjD&qq?k>N*l2rk=hXFz*vlp0k@
z3D^AfCfXhP1V}e6ipi*>h3s0Bz}@V~IXoJKk7DXOI5hCZdAPc@a2sNKZOKe1Mi}FEXiG0xVJ-AcwuD?2PFjuOSV$q;$mpn?t9t7}
z`kSKK_H+W*mhn%aF%T?Qt|cO@IONmTQ$Q`&?zz|&1h#8y3*DpS_{N)G92CE|9oul1
z%^sH-=oZphDp+IPh`cbk>25VYyx~rakZDPi?ghIH+cflGX9_a9eelV{it=PgiFV}>A@u~H9CcfB@_Ih
z;z+ZFm3mH6qPM|P4ZCI^-^aHXz(?Gv=&do=7d`l&E{+3$I|8U>%=hI`!gFwT9_-#6
zNa+ZBFEey7#v*3!7o-KAtx^1Eqv0$cA1$_zKfM3s5o2R#ZSzQ*XJ%xN7|aaU#e@Lj
z+#(pk-<=16*FVlcA(VdsUQ`MZKMNQ1uK(EFiYLsRC`EmM3wYB_g*iGtZ0NFtkt(zc
zJ%=1mbbJo)Ij5ajaU^lJw**&0)5p=n++R+?uI_Xl7o%Dbg$1XwB=#;s>y?4uD|snU
zFbwej&UpCPl*fVsa`@)w-+wk2|uJ#{%h))uJ&qVl>tMHfd
z6S(d1Eu({E|lp5r`E(f@=a^ypde=Z*Rm=P_*R7uL^THeAmk
zo@cm!f-reZ3-jj?|8avn&EzL{(Z8v|^GuLW8g!8TBMp8ZI`%g;d7cpGNfTklf27IZ
zOpo(?Or8gRKk2c>^}p%y>&^c(D38Oe(pN;1fBL6AOGjj|MfZk$5Z|J5#JM(zRq7k{pEq*
z^L9NymUsfgd-qphzdpWxIavJT#ymI0J;?`{{B8OFVVHZ;|M#2zpZ0}c%Fh)Ks`-Dc
zBY(9vJS~@=vvt4tweJ6|T?Kw$`EiV&TOaEaJpP8X|FT^CV|&D}!gIX(
z{#VievQ9kp<1g#+=i8Ad1R9&)_2cil;y23wM0nbq$V)*!T46yzh#$Wm_b4DIkK#Z;
F{vXwFhfn|j
literal 0
HcmV?d00001
diff --git a/pom.xml b/pom.xml
index ca9ad0c4..4cec972f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,7 +39,8 @@
adc-da-search
adc-da-slrs
adc-da-activiti
-
+ adc-da-convert
+