public class UIDocument extends UIComponentBase implements FacesAjaxComponent {

	public static final String COMPONENT_TYPE = "biz.webgate.dominoext.poi.Document"; //$NON-NLS-1$
	public static final String COMPONENT_FAMILY = "biz.webgate.dominoext.poi.Document"; //$NON-NLS-1$
	public static final String RENDERER_TYPE = "biz.webgate.dominoext.poi.Document"; //$NON-NLS-1$

	private List<IDocumentBookmark> m_Bookmarks;
	private List<DocumentTable> m_Tables;
	private String m_pathInfo;
	private String m_DownloadFileName;
	private ITemplateSource m_TemplateSource;
	private MethodBinding m_PostGenerationProcess;
	private Boolean m_PdfOutput;

	public UIDocument() {

		super();
		setRendererType(RENDERER_TYPE);
	}

	public List<IDocumentBookmark> getBookmarks() {
		return m_Bookmarks;
	}

	public void setBookmarks(List<IDocumentBookmark> bookmarks) {
		m_Bookmarks = bookmarks;
	}

	public void addBookmark(IDocumentBookmark myBookmark) {
		if (m_Bookmarks == null) {
			m_Bookmarks = new ArrayList<>();
		}
		m_Bookmarks.add(myBookmark);
	}

	public List<DocumentTable> getTables() {
		return m_Tables;
	}

	public void setTables(List<DocumentTable> tables) {
		m_Tables = tables;
	}

	public void addTables(DocumentTable myTable) {
		if (m_Tables == null) {
			m_Tables = new ArrayList<>();
		}
		m_Tables.add(myTable);
	}

	public String getPathInfo() {
		if (null != m_pathInfo) {
			return m_pathInfo;
		}
		ValueBinding _vb = getValueBinding("pathInfo"); //$NON-NLS-1$
		if (_vb != null) {
			return (java.lang.String) _vb.getValue(FacesContext.getCurrentInstance());
		} else {
			return null;
		}
	}

	public void setPathInfo(String linkName) {
		m_pathInfo = linkName;
	}

	public String getDownloadFileName() {
		if (null != m_DownloadFileName) {
			return m_DownloadFileName;
		}
		ValueBinding _vb = getValueBinding("downloadFileName"); //$NON-NLS-1$
		if (_vb != null) {
			return (java.lang.String) _vb.getValue(FacesContext.getCurrentInstance());
		} else {
			return null;
		}
	}

	public void setDownloadFileName(String downloadFileName) {
		m_DownloadFileName = downloadFileName;
	}

	public ITemplateSource getTemplateSource() {
		return m_TemplateSource;
	}

	public void setTemplateSource(ITemplateSource templateSource) {
		m_TemplateSource = templateSource;
	}

	@Override
	public String getFamily() {
		return COMPONENT_FAMILY;
	}

	public boolean getPdfOutput() {
		if (null != m_PdfOutput) {
			return m_PdfOutput;
		}
		ValueBinding _vb = getValueBinding("pdfOutput"); //$NON-NLS-1$
		if (_vb != null) {
			return (Boolean) _vb.getValue(FacesContext.getCurrentInstance());
		} else {
			return false;
		}
	}

	public void setPdfOutput(boolean pdfOutput) {
		m_PdfOutput = pdfOutput;
	}

	@Override
	public boolean handles(FacesContext context) {
		String reqPathInfo = context.getExternalContext().getRequestPathInfo();
		if (StringUtil.isNotEmpty(reqPathInfo)) {
			String pathInfo = getPathInfo();
			if (StringUtil.isEmpty(pathInfo)) {
				return false;
			}
			if (!pathInfo.startsWith("/")) {
				pathInfo = "/" + pathInfo;
			}
			if (!pathInfo.endsWith("/")) {
				pathInfo += "/";
			}
			if (!reqPathInfo.startsWith("/")) {
				reqPathInfo = "/" + reqPathInfo;
			}
			if (!reqPathInfo.endsWith("/")) {
				reqPathInfo += "/";
			}
			if (reqPathInfo.startsWith(pathInfo)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void processAjaxRequest(FacesContext context) throws IOException {
		DocumentProcessor.INSTANCE.processCall(context, this, false, null);
	}

	// SAVING AND RESTORING
	@Override
	public Object saveState(FacesContext context) {
		try {
			Object[] state = new Object[8];
			state[0] = super.saveState(context);
			state[1] = m_DownloadFileName;
			state[2] = m_pathInfo;
			state[3] = FacesUtil.objectToSerializable(context, m_TemplateSource);
			state[4] = StateHolderUtil.saveList(context, m_Bookmarks);
			state[5] = StateHolderUtil.saveMethodBinding(context, m_PostGenerationProcess);
			state[6] = m_PdfOutput;
			state[7] = StateHolderUtil.saveList(context, m_Tables);
			return state;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void restoreState(FacesContext context, Object value) {
		Object[] state = (Object[]) value;
		super.restoreState(context, state[0]);
		m_DownloadFileName = (String) state[1];
		m_pathInfo = (String) state[2];
		m_TemplateSource = (ITemplateSource) FacesUtil.objectFromSerializable(context, this, state[3]);
		m_Bookmarks = StateHolderUtil.restoreList(context, this, state[4]);
		m_PostGenerationProcess = StateHolderUtil.restoreMethodBinding(context, this, state[5]);
		m_PdfOutput = (Boolean) state[6];
		m_Tables = StateHolderUtil.restoreList(context, this, state[7]);

	}

	public MethodBinding getPostGenerationProcess() {
		return m_PostGenerationProcess;
	}

	public void setPostGenerationProcess(MethodBinding postGenerationProcess) {
		m_PostGenerationProcess = postGenerationProcess;
	}

	public boolean postGenerationProcess(FacesContext context, XWPFDocument document) {
		if (m_PostGenerationProcess != null) {
			Object[] params = null;
			if (m_PostGenerationProcess instanceof MethodBindingEx) {
				params = new Object[] { document };
				((MethodBindingEx) m_PostGenerationProcess).setComponent(this);
				((MethodBindingEx) m_PostGenerationProcess).setParamNames(s_postGenParamNames);
			}
			/*
			 * if (FacesUtil.isCancelled(m_PostGenerationProcess.invoke(context,
			 * params))) { return false; }
			 */
			doPostGenerationProcessPrivileged(context, params);
			return true;
		}
		return true;
	}

	public void doPostGenerationProcessPrivileged(final FacesContext context, final Object[] params) {
		try {
			AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
				m_PostGenerationProcess.invoke(context, params);
				return null;
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
	}

	private static final String[] s_postGenParamNames = { "xwpfdocument" }; // $NON-NLS-1$
} public interface ITemplateSource {

	public InputStream getFileStream();

	public int accessTemplate();

	public void cleanUP();
} public interface IDocumentBookmark {
	public String getName();
	public String getValue();
} public class DocumentTable extends AbstractDataExporter {

	/*
	 * private String m_Var; private String m_Index; private Integer m_StepSize;
	 * private IExportSource m_DataSource; private String m_DataSourceVar;
	 */
	private Integer m_StartRow;
	private List<DocColumnDefinition> m_DocColumns;
	private Integer m_MaxRow;
	private Integer m_TableNr;
	private List<DocCellValue> m_DocCellValues;
	private Boolean m_IncludeHeader;

	public List<DocCellValue> getDocCellValues() {
		return m_DocCellValues;
	}

	public void setDocCellValues(List<DocCellValue> docCellValues) {
		m_DocCellValues = docCellValues;
	}

	public void addDocCellValue(DocCellValue icvCurrent) {
		if (m_DocCellValues == null) {
			m_DocCellValues = new ArrayList<>();
		}
		m_DocCellValues.add(icvCurrent);
	}

	public int getStartRow() {
		if (m_StartRow != null) {
			return m_StartRow;
		}
		ValueBinding vb = getValueBinding("startRow");
		if (vb != null) {
			Integer intValue = (Integer) vb.getValue(getFacesContext());
			if (intValue != null)
				return intValue;
		}
		return 0;

	}

	public void setStartRow(int startRow) {
		m_StartRow = startRow;
	}


	public List<DocColumnDefinition> getDocColumns() {
		return m_DocColumns;
	}

	public void setDocColumns(List<DocColumnDefinition> docColumns) {
		m_DocColumns = docColumns;
	}

	public void addDocColumn(DocColumnDefinition cdCurrent) {
		if (m_DocColumns == null) {
			m_DocColumns = new ArrayList<>();
		}
		m_DocColumns.add(cdCurrent);
	}

	public int getMaxRow() {
		if (m_MaxRow != null) {
			return m_MaxRow;
		}
		ValueBinding vb = getValueBinding("maxRow");
		if (vb != null) {
			Integer intValue = (Integer) vb.getValue(getFacesContext());
			if (intValue != null)
				return intValue;
		}
		return 100;

	}

	public void setMaxRow(int maxRow) {
		m_MaxRow = maxRow;
	}

	public int getTableNr() {
		return m_TableNr;
	}

	public void setTableNr(int tableNr) {
		m_TableNr = tableNr;
	}
	/*
	 * public IExportSource getDataSource() { return m_DataSource; }
	 *
	 * public void setDataSource(IExportSource dataSource) { m_DataSource =
	 * dataSource; }
	 *
	 * public int getStepSize() { if (m_StepSize != null) { return m_StepSize; }
	 * ValueBinding vb = getValueBinding("stepSize"); if (vb != null) { Integer
	 * intValue = (Integer) vb.getValue(getFacesContext()); if (intValue !=
	 * null) return intValue; } return 1; }
	 *
	 * public void setStepSize(int stepSize) { m_StepSize = stepSize; }
	 *
	 * public String getVar() { return m_Var; }
	 *
	 * public void setVar(String var) { m_Var = var; }
	 *
	 * public String getIndex() { return m_Index; }
	 *
	 * public void setIndex(String index) { m_Index = index; }
	 *
	 * public String getDataSourceVar() { if (m_DataSourceVar != null) { return
	 * m_DataSourceVar; } ValueBinding vb = getValueBinding("dataSourceVar"); if
	 * (vb != null) { String strValue = (String) vb.getValue(getFacesContext());
	 * if (strValue != null) return strValue; } return null;
	 *
	 * }
	 *
	 * public void setDataSourceVar(String dataSourceVar) { m_DataSourceVar =
	 * dataSourceVar; }
	 *
	 * public DataSource getPageDataSource() { String strName =
	 * getDataSourceVar(); System.out.println(strName); if
	 * (StringUtil.isNotEmpty(strName)) {
	 *
	 * UIViewRoot vrCurrent = getFacesContext().getViewRoot(); if (vrCurrent
	 * instanceof UIViewRootEx) { for (DataSource dsCurrent : ((UIViewRootEx)
	 * vrCurrent).getData()) { if (strName.equals(dsCurrent.getVar())) { return
	 * dsCurrent; } } } } System.out.println("Datasource name:" +
	 * m_DataSourceVar); return null;
	 *
	 * }
	 */





	public boolean getIncludeHeader() {
		if (null != m_IncludeHeader) {
			return m_IncludeHeader;
		}
		ValueBinding _vb = getValueBinding("includeHeader"); //$NON-NLS-1$
		if (_vb != null) {
			return (Boolean) _vb.getValue(FacesContext.getCurrentInstance());
		} else {
			return false;
		}
	}

	public void setIncludeHeader(boolean includeHeader) {
		m_IncludeHeader = includeHeader;
	}

	@Override
	public Object saveState(FacesContext context) {
		try {

			Object[] state = new Object[7];
			state[0] = super.saveState(context);
			state[1] = StateHolderUtil.saveList(context, m_DocCellValues);
			state[2] = m_StartRow;
			state[3] = StateHolderUtil.saveList(context, m_DocColumns);
			state[4] = m_MaxRow;
			state[5] = m_TableNr;
			state[6] = m_IncludeHeader;
			/*
			 * state[5] = m_StepSize; state[6] =
			 * FacesUtil.objectToSerializable(getFacesContext(), m_DataSource);
			 * state[7] = m_DataSourceVar; state[8] = m_Var; state[9] = m_Index;
			 */
			return state;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void restoreState(FacesContext context, Object arg1) {
		Object[] state = (Object[]) arg1;
		super.restoreState(context, state[0]);
		m_DocCellValues = StateHolderUtil.restoreList(context, getComponent(), state[1]);
		m_StartRow = (Integer) state[2];
		m_DocColumns = StateHolderUtil.restoreList(context, getComponent(), state[3]);
		m_MaxRow = (Integer) state[4];
		m_TableNr = (Integer) state[5];
		m_IncludeHeader = (Boolean) state[6];
	}


} public class DocCellValue extends ValueBindingObjectImpl implements ICellValue {

	private Object m_Value;
	private Integer m_ColumnNumber;
	private Integer m_RowNumber;

	// private PoiCellStyle m_PoiCellStyle;

	public int getRowNumber() {
		if (m_RowNumber != null) {
			return m_RowNumber;
		}
		ValueBinding vb = getValueBinding("rowNumber");
		if (vb != null) {
			Integer intValue = (Integer) vb.getValue(getFacesContext());
			if (intValue != null) {
				return intValue;
			}
		}
		return 0;

	}

	public void setRowNumber(int rowNumber) {
		m_RowNumber = rowNumber;
	}

	@Override
	public Object getValue() {
		if (m_Value != null) {
			return m_Value;
		}
		ValueBinding vb = getValueBinding("value");
		if (vb != null) {
			return vb.getValue(getFacesContext());
		}
		return null;
	}

	public void setValue(Object value) {
		m_Value = value;
	}

	public int getColumnNumber() {
		if (m_ColumnNumber != null) {
			return m_ColumnNumber;
		}
		ValueBinding vb = getValueBinding("columnNumber");
		if (vb != null) {
			Integer intValue = (Integer) vb.getValue(getFacesContext());
			if (intValue != null) {
				return intValue;
			}
		}
		return 0;
	}

	public void setColumnNumber(int columnNumber) {
		m_ColumnNumber = columnNumber;
	}



	@Override
	public Object saveState(FacesContext context) {
		Object[] state = new Object[4];
		state[0] = super.saveState(context);
		state[1] = m_ColumnNumber;
		state[2] = m_RowNumber;
		state[3] = m_Value;
		return state;
	}

	@Override
	public void restoreState(FacesContext context, Object arg1) {
		Object[] state = (Object[]) arg1;
		super.restoreState(context, state[0]);
		m_ColumnNumber = (Integer)state[1];
		m_RowNumber = (Integer)state[2];
		m_Value = state[3];
	}
} public interface ICellValue {

	public Object getValue();
} public enum EmbeddedDataSourceExportProcessor implements IDataSourceExportProcessor {
	INSTANCE;

	@Override
	public XWPFTable processExportTable(DocumentTable lstExport, XWPFDocument dxDocument, FacesContext context, String strVar, String strIndex) throws POIException {

		Logger logCurrent = LoggerFactory.getLogger(this.getClass().getCanonicalName());

		try {
			logCurrent.finer("Proccess Export Row");
			IExportSource is = lstExport.getDataSource();

			logCurrent.finer("Load Access Source");
			int nAccess = is.accessSource();
			if (nAccess < 1) {
				throw new POIException("Error accessing Source: " + is.getClass() + " Error: " + nAccess);
			}
			int currentOutputRow = lstExport.getStartRow();
			int nStepSize = lstExport.getStepSize();

			int dataRowCount = 0;

			logCurrent.finer("Strart Creating Table");

			XWPFTable dxTable = dxDocument.getTables().get(lstExport.getTableNr() - 1);

			logCurrent.finer("Proccess Create Table - DONE");

			logCurrent.finer("Start Processing Columns");
			currentOutputRow = buildHeaderIfNeeded(lstExport, currentOutputRow, dxTable);
			List<ShadowedObject> controlData = RequestVarsHandler.INSTANCE.publishControlData(context, strVar, strIndex);

			while (is.accessNextRow() == 1 && currentOutputRow < lstExport.getMaxRow() + (lstExport.getIncludeHeader() ? 1 : 0)) {
				dataRowCount++;
				RequestVarsHandler.INSTANCE.pushVars(context, strVar, strIndex, is.getDataRow(), dataRowCount);

				processRow(lstExport, context, is, currentOutputRow, dxTable);
				currentOutputRow = currentOutputRow + nStepSize;
				RequestVarsHandler.INSTANCE.removeVars(context, strVar, strIndex);

			}
			RequestVarsHandler.INSTANCE.revokeControlData(controlData, context);

			is.closeSource();
			logCurrent.finer("Proccess Export Cells - DONE");
			return dxTable;
		} catch (Exception e) {
			throw new POIException("Error in processExportTable", e);
		}
	}

	private void processRow(DocumentTable lstExport, FacesContext context, IExportSource is, int currentOutputRow, XWPFTable dxTable) {
		for (DocColumnDefinition clDef : lstExport.getDocColumns()) {
			int nCol = clDef.getColumnNumber();
			int nMyRow = clDef.getRowShift() + currentOutputRow;
			Object objCurrent = is.getValue(clDef, context);
			setDocCellValue(dxTable, nMyRow, nCol, objCurrent, lstExport.getMaxRow(), false);
		}
	}

	private int buildHeaderIfNeeded(DocumentTable lstExport, int nRow, XWPFTable dxTable) {
		if (lstExport.getIncludeHeader()) {
			nRow++;
			for (DocColumnDefinition clDef : lstExport.getDocColumns()) {
				setDocCellValue(dxTable, 0, clDef.getColumnNumber(), clDef.getColumnHeader(), lstExport.getMaxRow(), true);
			}
		}
		return nRow;
	}

	public void setDocCellValue(XWPFTable dxTable, int nRow, int nCol, Object objValue, int maxRow, boolean isHeader) {

		try {
			if (dxTable.getRow(nRow) == null) {
				// DEFINIE MAX VALUE!
				while (dxTable.getRow(nRow) == null && dxTable.getRows().size() < maxRow) {
					dxTable.createRow();
					// rowHasChanged = true;
				}
			}
			if (dxTable.getRow(nRow) != null) {
				if (dxTable.getRow(nRow).getCell(nCol) == null) {
					// CHECK MAX COL
					while (dxTable.getRow(nRow).getCell(nCol) == null && dxTable.getRow(nRow).getTableCells().size() < 50) {
						dxTable.getRow(nRow).addNewTableCell();
					}
				}

				for (XWPFParagraph paraCurrent : dxTable.getRow(nRow).getCell(nCol).getParagraphs()) {
					if (paraCurrent.getRuns().size() == 0) {
						XWPFRun runCurrent = paraCurrent.createRun();
						if (isHeader)
							runCurrent.setBold(true);
						runCurrent.setText("" + objValue.toString());
					} else {
						for (XWPFRun runCurrent : paraCurrent.getRuns()) {
							if (isHeader)
								runCurrent.setBold(true);
							runCurrent.setText("" + objValue.toString());
						}
					}
				}

			} else {
				System.out.println("Still null: " + nRow + " MaxRow = " + maxRow);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

} public enum MethodExecutor {
	INSTANCE;

	public void execute(MethodBinding method, UIComponent comp, FacesContext context, Object bo) throws PrivilegedActionException {
		if (method != null) {
			Object[] params = null;
			if (method instanceof MethodBindingEx) {
				params = new Object[] { bo };
				((MethodBindingEx) method).setComponent(comp);
				((MethodBindingEx) method).setParamNames(new String[] { "result" });
			}

			executePrivileged(method, context, params);
		}
	}

	private void executePrivileged(final MethodBinding method, final FacesContext context, final Object[] params) throws PrivilegedActionException {
		AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
			method.invoke(context, params);
			return null;
		});
	}
} public interface IPDFService {

	public void buildPDF(InputStream isDocument, OutputStream osTarget) throws PDFException;
	public String getName();
} public class PDFConversionService {

	private static final String PDF_SERVICE_KEY = "poi.pdfservice"; //$NON-NLS-1$

	private static final String PDF_DATAPROVIDER_SERVICE = "biz.webgate.poi.pdf.service"; //$NON-NLS-1$

	private static final String PREF_PROVIDER = "poi.pdfservice.provider"; //$NON-NLS-1$

	private IPDFService m_PdfService;

	private PDFConversionService() {

	}

	public static PDFConversionService getInstance() {
		PDFConversionService f = (PDFConversionService) Application.get()
				.getObject(PDF_SERVICE_KEY);
		if (f == null) {
			synchronized (PDFConversionService.class) {
				f = (PDFConversionService) Application.get().getObject(
						PDF_SERVICE_KEY);
				if (f == null) {
					f = new PDFConversionService();
					Application.get().putObject(PDF_SERVICE_KEY, f);
				}
			}
		}
		return f;
	}

	public IPDFService getPDFService() {
		final Logger logCurrent = LoggerFactory.getLogger(this.getClass().getCanonicalName());
		if (m_PdfService == null) {
			AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
				String providersProp = ApplicationEx.getInstance()
						.getApplicationProperty(PREF_PROVIDER, null);
				logCurrent.info(PREF_PROVIDER +" = "+ providersProp);
				@SuppressWarnings("unchecked")
				List<IPDFService> allPDFProviders = ApplicationEx
						.getInstance().findServices(
								PDF_DATAPROVIDER_SERVICE);
				for (IPDFService p : allPDFProviders) {
					logCurrent.info( "TEST of "+ p.getName());
					if (p.getName().equalsIgnoreCase(providersProp)) {
						m_PdfService = p;
						break;
					}
				}
				if (m_PdfService == null) {
					logCurrent.info("No PDF Service found. Assign FOP Service!");
					m_PdfService = new FOPService();
				}

				return null;
			});
		}
		return m_PdfService;
	}

} public class POIException extends Exception {


	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	public POIException() {
		super();
	}
	public POIException(String strMessage) {
		super(strMessage);
	}
	public POIException(Throwable t) {
		super(t);
	}
	public POIException(String strMessage,Throwable t) {
		super(strMessage,t);
	}
} public class ErrorPageBuilder {

	private static ErrorPageBuilder m_Builder;

	private ErrorPageBuilder() {

	}

	public static ErrorPageBuilder getInstance() {
		if (m_Builder == null) {
			m_Builder = new ErrorPageBuilder();
		}
		return m_Builder;
	}

	public void processError(HttpServletResponse httpResponse,
			String strErrorMessage, Throwable t) {
		try {
			httpResponse.setContentType("text/plain");
			PrintWriter pw = httpResponse.getWriter();
			pw.println("POI 4 XPages -> ERROR");
			pw.println("--------------------------------------------------------------");
			pw.println("Error    : " + strErrorMessage);
			pw.println("POI LIB  : " + LibUtil.getPOILibUtilVersion());
			if (t != null) {
				pw.println("StackTrace:");
				t.printStackTrace(pw);
			}
			pw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
} public class LoggerFactory {
	private static HashMap<String, Logger> m_RegistredLoggers = new HashMap<>();

	private static int m_logLevel = -1;
	private static int m_logLevelPDF = -1;
	private static int m_logLevelFOP = -1;

	public static Logger getLogger(String strName) {
		try {
			if (m_RegistredLoggers.containsKey(strName)) {
				return m_RegistredLoggers.get(strName);
			}
			Logger logRC = java.util.logging.Logger.getAnonymousLogger();
			if (m_logLevel == -1) {
				checkLogLevel();
			}
			logRC.setLevel(getLogLevel(getLogLevelForClass(strName)));
			ConsoleHandler ch = new ConsoleHandler(strName,
					getLogLevel(m_logLevel));
			logRC.addHandler(ch);
			m_RegistredLoggers.put(strName, logRC);
			return logRC;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Level getLogLevel(int nLevel) {
		switch (nLevel) {
		case 0:
			return Level.OFF;
		case 1:
			return Level.SEVERE;
		case 2:
			return Level.WARNING;
		case 3:
			return Level.INFO;
		case 4:
			return Level.FINE;
		case 5:
			return Level.FINER;
		case 6:
			return Level.FINEST;

		}
		return Level.ALL;

	}

	private static void checkLogLevel() {
		try {
			String strPOI = LibUtil.getCurrentSession().getEnvironmentString(
					"DEBUG_POI", true);
			if (strPOI == null || "".equals(strPOI)) {
				m_logLevel = 1;
			}
			String strPOIPDF = LibUtil.getCurrentSession()
					.getEnvironmentString("DEBUG_POI_PDF", true);
			if (strPOIPDF == null || "".equals(strPOIPDF)) {
				m_logLevelPDF = 1;
			}
			String strPOIFOP = LibUtil.getCurrentSession()
					.getEnvironmentString("DEBUG_POI_FOP", true);
			if (strPOIFOP == null || "".equals(strPOIFOP)) {
				m_logLevelFOP = 1;
			}

			try {
				if (strPOI != null && !"".equals(strPOI)) {
					m_logLevel = Integer.parseInt(strPOI);
				}
				if (strPOIPDF != null && !"".equals(strPOIPDF)) {
					m_logLevelPDF = Integer.parseInt(strPOIPDF);
				}
				if (strPOIFOP != null && !"".equals(strPOIFOP)) {
					m_logLevelFOP = Integer.parseInt(strPOIFOP);
				}
			} catch (Exception e) {
				m_logLevel = 0;
			}
			System.out.println("POI     LOG-LEVEL is set to: " + strPOI +" / "+ m_logLevel);
			System.out.println("POI PDF LOG-LEVEL is set to: " + strPOIPDF+" / "+ m_logLevelPDF);
			System.out.println("POI FOP LOG-LEVEL is set to: " + strPOIFOP+" / "+ m_logLevelFOP);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static int getLogLevelForClass(String strClass) {
		if (strClass == null) {
			return m_logLevel;
		}
		if (strClass.toLowerCase().startsWith(
				"biz.webgate.dominoext.poi.pdf.fopdocx4j")) {
			return m_logLevelFOP;
		}
		if (strClass.toLowerCase().startsWith("biz.webgate.dominoext.poi.pdf")) {
			return m_logLevelPDF;
		}
		return m_logLevel;
	}
}
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import com.ibm.xsp.webapp.XspHttpServletResponse;
import biz.webgate.dominoext.poi.component.containers.UIDocument;
import biz.webgate.dominoext.poi.component.data.ITemplateSource;
import biz.webgate.dominoext.poi.component.data.document.IDocumentBookmark;
import biz.webgate.dominoext.poi.component.data.document.table.DocumentTable;
import biz.webgate.dominoext.poi.component.data.document.table.cell.DocCellValue;
import biz.webgate.dominoext.poi.component.data.ss.cell.ICellValue;
import biz.webgate.dominoext.poi.component.kernel.document.EmbeddedDataSourceExportProcessor;
import biz.webgate.dominoext.poi.component.kernel.util.MethodExecutor;
import biz.webgate.dominoext.poi.pdf.IPDFService;
import biz.webgate.dominoext.poi.pdf.PDFConversionService;
import biz.webgate.dominoext.poi.utils.exceptions.POIException;
import biz.webgate.dominoext.poi.utils.logging.ErrorPageBuilder;
import biz.webgate.dominoext.poi.utils.logging.LoggerFactory;
/**
 * Copyright (c) 2012-2021 WebGate Consulting AG and others
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package biz.webgate.dominoext.poi.component.kernel;






public enum DocumentProcessor {
	INSTANCE;

	/**
	 * gets the Instance of the DocumentProcessor.
	 *
	 * @deprecated -> Use DocumentProcessor.INSTANCE instead
	 *
	 * @return Instance of the DocumentProcessor
	 */
	@Deprecated
	public static DocumentProcessor getInstance() {
		return DocumentProcessor.INSTANCE;
	}

	public XWPFDocument getDocument(InputStream inDocument) {

		try {
			Logger log = LoggerFactory.getLogger(getClass().getCanonicalName());
			log.info("inDocument -> " + inDocument);
			XWPFDocument dxReturn = new XWPFDocument(inDocument);
			return dxReturn;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	public int processBookmarks2Document(XWPFDocument dxProcess, List<IDocumentBookmark> arrBookmarks) {
		// First Prozessing all paragraphs.
		for (XWPFParagraph paraCurrent : dxProcess.getParagraphs()) {
			processBookmarks2Paragraph(arrBookmarks, paraCurrent);
		}

		for (XWPFTable tabCurrent : dxProcess.getTables()) {
			processBookmarks2Table(arrBookmarks, tabCurrent);
		}
		for (XWPFHeader headCurrent : dxProcess.getHeaderList()) {
			for (XWPFParagraph paraCurrent : headCurrent.getParagraphs()) {
				processBookmarks2Paragraph(arrBookmarks, paraCurrent);
			}
			for (XWPFTable tabCurrent : headCurrent.getTables()) {
				processBookmarks2Table(arrBookmarks, tabCurrent);
			}
		}
		for (XWPFFooter footCurrent : dxProcess.getFooterList()) {
			for (XWPFParagraph paraCurrent : footCurrent.getParagraphs()) {
				processBookmarks2Paragraph(arrBookmarks, paraCurrent);
			}
			for (XWPFTable tabCurrent : footCurrent.getTables()) {
				processBookmarks2Table(arrBookmarks, tabCurrent);
			}
		}

		return 1;
	}

	private void processBookmarks2Table(List<IDocumentBookmark> arrBookmarks, XWPFTable tabCurrent) {
		for (XWPFTableRow tabRow : tabCurrent.getRows()) {
			for (XWPFTableCell tabCell : tabRow.getTableCells()) {
				for (XWPFParagraph paraCurrent : tabCell.getParagraphs()) {
					processBookmarks2Paragraph(arrBookmarks, paraCurrent);
				}
			}
		}
	}

	private void processBookmarks2Paragraph(List<IDocumentBookmark> arrBookmarks, XWPFParagraph paraCurrent) {
		for (XWPFRun runCurrent : paraCurrent.getRuns()) {
			processBookmarks2Run(runCurrent, arrBookmarks);
		}
	}

	public int processBookmarks2Run(XWPFRun runCurrent, List<IDocumentBookmark> arrBookmarks) {
		String strText = runCurrent.getText(0);
		if (strText != null) {
			boolean found = false;
			for (IDocumentBookmark bmCurrent : arrBookmarks) {
				String strValue = bmCurrent.getValue();
				strValue = strValue == null ? "" : strValue;
				if (bmCurrent.getName() != null && strText.contains("<<" + bmCurrent.getName() + ">>")) {
					found = true;
					strText = strText.replace("<<" + bmCurrent.getName() + ">>", strValue);
				}
			}
			if (found) {
				String lines[] = strText.split("\\r?\\n");
				for (int i = 0; i < lines.length; i++) {
					String line = lines[i];
					if (i == 0) {
						runCurrent.setText(line, 0);
					} else {
						runCurrent.setText(line);
					}
					if (i + 1 < lines.length) {
						runCurrent.addBreak(BreakType.TEXT_WRAPPING);
					}
				}
			}
		}
		return 1;
	}

	public void generateNewFile(ITemplateSource itsCurrent, HttpServletResponse httpResponse, FacesContext context, UIDocument uiDoc, boolean noDownload, MethodBinding preDownload)
			throws IOException {
		Logger logCurrent = LoggerFactory.getLogger(this.getClass().getCanonicalName());
		List<IDocumentBookmark> bookmarks = uiDoc.getBookmarks();
		List<DocumentTable> tables = uiDoc.getTables();
		String strFileName = uiDoc.getDownloadFileName();
		try {
			int nTemplateAccess = itsCurrent.accessTemplate();
			if (nTemplateAccess == 1) {
				XWPFDocument dxDocument = processDocument(itsCurrent, bookmarks, tables, context, uiDoc);
				if (uiDoc.getPdfOutput()) {

					logCurrent.info("Build PDF");
					ByteArrayOutputStream bosDoc = new ByteArrayOutputStream();
					dxDocument.write(bosDoc);
					bosDoc.flush();
					logCurrent.info("Size of worddocument ByteArrayOutputStream: " + bosDoc.size());
					ByteArrayInputStream is = new ByteArrayInputStream(bosDoc.toByteArray());
					ByteArrayOutputStream bos = new ByteArrayOutputStream();
					IPDFService isCurrent = PDFConversionService.getInstance().getPDFService();