<commit_before>package com.haulmont.cuba.report.formatters;

import com.haulmont.cuba.core.app.ServerConfig;
import com.haulmont.cuba.core.entity.FileDescriptor;
import com.haulmont.cuba.core.global.ConfigProvider;
import com.haulmont.cuba.report.Band;
import com.haulmont.cuba.report.ReportOutputType;
import com.haulmont.cuba.report.exception.ReportFormatterException;
import com.haulmont.cuba.report.formatters.tools.ClipBoardHelper;
import com.haulmont.cuba.report.formatters.tools.OOOConnection;
import com.haulmont.cuba.report.formatters.tools.OOOConnector;
import com.haulmont.cuba.report.formatters.tools.OOOutputStream;
import com.sun.star.container.NoSuchElementException;
import com.sun.star.container.XEnumeration;
import com.sun.star.container.XIndexAccess;
import com.sun.star.frame.XDispatchHelper;
import com.sun.star.io.IOException;
import com.sun.star.io.XInputStream;
import com.sun.star.lang.WrappedTargetException;
import com.sun.star.lang.XComponent;
import com.sun.star.table.XCell;
import com.sun.star.text.XText;
import com.sun.star.text.XTextDocument;
import com.sun.star.text.XTextRange;
import com.sun.star.text.XTextTable;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.util.XReplaceable;
import com.sun.star.util.XSearchDescriptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import static com.haulmont.cuba.report.formatters.tools.ODTHelper.*;
import static com.haulmont.cuba.report.formatters.tools.ODTTableHelper.*;
import static com.haulmont.cuba.report.formatters.tools.ODTUnoConverter.*;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

/*
 * Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
 * Haulmont Technology proprietary and confidential.
 * Use is subject to license terms.

 * Author: <NAME>
 * Created: 12.10.2010 19:21:36
 *
 * $Id$
 */

public class DocFormatter extends AbstractFormatter {
    private OOOConnection connection;
    private Band rootBand;
    private FileDescriptor templateFileDescriptor;
    private ReportOutputType reportOutputType;
    private XComponent xComponent;

    private Log log = LogFactory.getLog(DocFormatter.class);

    public DocFormatter(FileDescriptor templateFileDescriptor, ReportOutputType reportOutputType) {
        String openOfficePath = ConfigProvider.getConfig(ServerConfig.class).getOpenOfficePath();
        try {
            connection = OOOConnector.createConnection(openOfficePath);
        } catch (Exception ex) {
            throw new RuntimeException("Please check OpenOffice path: " + openOfficePath);
        }
        this.templateFileDescriptor = templateFileDescriptor;
        this.reportOutputType = reportOutputType;
    }

    public byte[] createDocument(Band rootBand) {
        this.rootBand = rootBand;
        /* What is it?
        String bands = "";
        for (Band b : rootBand.getChildren())
            bands += b.getName() + "|";
        if (rootBand.getChildren().size() == 0)
            log.info("RootBand is empty");
        */
        try {
            XInputStream xis = getXInputStream(templateFileDescriptor);
            xComponent = loadXComponent(connection.createXComponentLoader(), xis);
            // Handling tables
            fillTables();
            // Handling text
            replaceAllAliasesInDocument();
            // Saving document to output stream and closing
            return saveAndClose(xComponent);
        } catch (java.lang.Exception ex) {
            throw new java.lang.RuntimeException(ex);
        }
    }

    private byte[] saveAndClose(XComponent xComponent) throws IOException {
        OOOutputStream ooos = new OOOutputStream();
        String filterName;
        if (ReportOutputType.PDF.equals(reportOutputType)) {
            filterName = "writer_pdf_Export";
        } else {
            filterName = "writer8";
        }
        saveXComponent(xComponent, ooos, filterName);
        closeXComponent(xComponent);
        return ooos.toByteArray();
    }

    private void fillTables() throws com.sun.star.uno.Exception {
        String[] tablesNames = getTablesNames(xComponent);
        XDispatchHelper xDispatchHelper = connection.createXDispatchHelper();
        for (String tableName : tablesNames) {
            Band band = findBand(rootBand, tableName);
            if (band != null) {
                XTextTable xTextTable = getTableByName(xComponent, tableName);
                // todo remove this hack!
                // try to select one cell without it workaround
                int columnCount = xTextTable.getColumns().getCount();
                if (columnCount < 2)
                    xTextTable.getColumns().insertByIndex(columnCount,1);
                fillTable(tableName, band.getParentBand(), xTextTable, xDispatchHelper);
                // end workaround
                if (columnCount < 2)
                    xTextTable.getColumns().removeByIndex(columnCount,1);    
            }
        }
    }

    private void fillTable(String name, Band parentBand, XTextTable xTextTable, XDispatchHelper xDispatchHelper) throws com.sun.star.uno.Exception {
        ClipBoardHelper.clear();
        for (int i = 0; i < parentBand.getChildren().size(); i++) {
            if (name.equals(parentBand.getChildren().get(i).getName()))
                duplicateLastRow(xDispatchHelper, asXTextDocument(xComponent).getCurrentController(), xTextTable);
        }
        int i = 0;
        for (Band child : parentBand.getChildren()) {
            if (name.equals(child.getName())){
                fillRow(child, xTextTable, i);
                i++;
            }
        }
        deleteLastRow(xTextTable);
    }

    private void fillRow(Band band, XTextTable xTextTable, int row) throws com.sun.star.lang.IndexOutOfBoundsException, NoSuchElementException, WrappedTargetException {<commit_msg>#457 (Удаление шаблонных таблиц, для которых нет данных)<commit_after>package com.haulmont.cuba.report.formatters;

import com.haulmont.cuba.core.app.ServerConfig;
import com.haulmont.cuba.core.entity.FileDescriptor;
import com.haulmont.cuba.core.global.ConfigProvider;
import com.haulmont.cuba.report.Band;
import com.haulmont.cuba.report.ReportOutputType;
import com.haulmont.cuba.report.exception.ReportFormatterException;
import com.haulmont.cuba.report.formatters.tools.*;
import com.sun.star.container.NoSuchElementException;
import com.sun.star.container.XEnumeration;
import com.sun.star.container.XIndexAccess;
import com.sun.star.frame.XDispatchHelper;
import com.sun.star.io.IOException;
import com.sun.star.io.XInputStream;
import com.sun.star.lang.*;
import com.sun.star.table.XCell;
import com.sun.star.text.XText;
import com.sun.star.text.XTextDocument;
import com.sun.star.text.XTextRange;
import com.sun.star.text.XTextTable;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.util.XReplaceable;
import com.sun.star.util.XSearchDescriptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import static com.haulmont.cuba.report.formatters.tools.ODTHelper.*;
import static com.haulmont.cuba.report.formatters.tools.ODTTableHelper.*;
import static com.haulmont.cuba.report.formatters.tools.ODTUnoConverter.*;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

/*
 * Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
 * Haulmont Technology proprietary and confidential.
 * Use is subject to license terms.

 * Author: <NAME>
 * Created: 12.10.2010 19:21:36
 *
 * $Id$
 */

public class DocFormatter extends AbstractFormatter {
    private OOOConnection connection;
    private Band rootBand;
    private FileDescriptor templateFileDescriptor;
    private ReportOutputType reportOutputType;
    private XComponent xComponent;

    private Log log = LogFactory.getLog(DocFormatter.class);

    public DocFormatter(FileDescriptor templateFileDescriptor, ReportOutputType reportOutputType) {
        String openOfficePath = ConfigProvider.getConfig(ServerConfig.class).getOpenOfficePath();
        try {
            connection = OOOConnector.createConnection(openOfficePath);
        } catch (Exception ex) {
            throw new RuntimeException("Please check OpenOffice path: " + openOfficePath);
        }
        this.templateFileDescriptor = templateFileDescriptor;
        this.reportOutputType = reportOutputType;
    }

    public byte[] createDocument(Band rootBand) {
        this.rootBand = rootBand;
        /* What is it?
        String bands = "";
        for (Band b : rootBand.getChildren())
            bands += b.getName() + "|";
        if (rootBand.getChildren().size() == 0)
            log.info("RootBand is empty");
        */
        try {
            XInputStream xis = getXInputStream(templateFileDescriptor);
            xComponent = loadXComponent(connection.createXComponentLoader(), xis);
            // Handling tables
            fillTables();
            // Handling text
            replaceAllAliasesInDocument();
            // Saving document to output stream and closing
            return saveAndClose(xComponent);
        } catch (java.lang.Exception ex) {
            throw new java.lang.RuntimeException(ex);
        }
    }

    private byte[] saveAndClose(XComponent xComponent) throws IOException {
        OOOutputStream ooos = new OOOutputStream();
        String filterName;
        if (ReportOutputType.PDF.equals(reportOutputType)) {
            filterName = "writer_pdf_Export";
        } else {
            filterName = "writer8";
        }
        saveXComponent(xComponent, ooos, filterName);
        closeXComponent(xComponent);
        return ooos.toByteArray();
    }

    private void fillTables() throws com.sun.star.uno.Exception {
        String[] tablesNames = getTablesNames(xComponent);
        XDispatchHelper xDispatchHelper = connection.createXDispatchHelper();
        for (String tableName : tablesNames) {
            Band band = findBand(rootBand, tableName);
            XTextTable xTextTable = getTableByName(xComponent, tableName);
            if (band != null) {
                // todo remove this hack!
                // try to select one cell without it workaround
                int columnCount = xTextTable.getColumns().getCount();
                if (columnCount < 2)
                    xTextTable.getColumns().insertByIndex(columnCount, 1);
                fillTable(tableName, band.getParentBand(), xTextTable, xDispatchHelper);
                // end of workaround ->
                if (columnCount < 2)
                    xTextTable.getColumns().removeByIndex(columnCount, 1);
            } else {
                if (haveValueExpressions(xTextTable))
                    deleteLastRow(xTextTable);
            }
        }
    }

    public boolean haveValueExpressions(XTextTable xTextTable) {
        int lastrow = xTextTable.getRows().getCount() - 1;
        try {
            for (int i = 0; i < xTextTable.getRows().getCount(); i++) {
                String templateText = asXText(ODTTableHelper.getXCell(xTextTable, i, lastrow)).getString();
                if (Pattern.compile("\\$\\{[^\\.]+?\\}").matcher(templateText).find()) {
                    return true;
                }
            }
        } catch (Exception e) {
            throw new ReportFormatterException(e);
        }
        return false;
    }

    private void fillTable(String name, Band parentBand, XTextTable xTextTable, XDispatchHelper xDispatchHelper) throws com.sun.star.uno.Exception {
        ClipBoardHelper.clear();
        int count = 0;
        for (int i = 0; i < parentBand.getChildren().size(); i++) {
            if (name.equals(parentBand.getChildren().get(i).getName())) {
                duplicateLastRow(xDispatchHelper, asXTextDocument(xComponent).getCurrentController(), xTextTable);
                count++;
            }
        }
        int i = 0;
        for (Band child : parentBand.getChildren()) {
            if (name.equals(child.getName())) {
                fillRow(child, xTextTable, i);
                i++;
            }
        }
        deleteLastRow(xTextTable);
    }

    private void fillRow(Band band, XTextTable xTextTable, int row) throws com.sun.star.lang.IndexOutOfBoundsException, NoSuchElementException, WrappedTargetException {
{'fraction_non_alphanumeric': 0.10195121951219512, 'fraction_numerical': 0.004715447154471545, 'mean_word_length': 2.7977770916949676, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1117134', 'n_tokens_mistral': 3462, 'n_tokens_neox': 3335, 'n_words': 699}