<commit_before>/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.officeimporter.internal;

import groovy.lang.GroovyClassLoader;

import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.xwiki.bridge.DocumentAccessBridge;
import org.xwiki.model.reference.AttachmentReference;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.Requirement;
import org.xwiki.component.logging.AbstractLogEnabled;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.model.reference.DocumentReferenceResolver;
import org.xwiki.officeimporter.OfficeImporter;
import org.xwiki.officeimporter.OfficeImporterException;
import org.xwiki.officeimporter.OfficeImporterFilter;
import org.xwiki.officeimporter.builder.PresentationBuilder;
import org.xwiki.officeimporter.builder.XDOMOfficeDocumentBuilder;
import org.xwiki.officeimporter.builder.XHTMLOfficeDocumentBuilder;
import org.xwiki.officeimporter.document.XDOMOfficeDocument;
import org.xwiki.officeimporter.document.XHTMLOfficeDocument;
import org.xwiki.officeimporter.splitter.TargetDocumentDescriptor;
import org.xwiki.officeimporter.splitter.XDOMOfficeDocumentSplitter;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.xml.html.HTMLUtils;

/**
 * Default implementation of the office importer component.
 * 
 * @version $Id$
 * @since 1.8M1
 * @deprecated use individual document builder components instead since 2.2M1
 */
@Component
@Deprecated
public class DefaultOfficeImporter extends AbstractLogEnabled implements OfficeImporter
{
    /**
     * File extensions corresponding to slide presentations.
     */
    public static final List<String> PRESENTATION_FORMAT_EXTENSIONS = Arrays.asList("ppt", "odp");

    /**
     * Error message to be used for indicating invalid splitting criterion.
     */
    private static final String ERROR_INVALID_SPLITTING_CRITERION = "Unable to determine splitting criterion.";

    /**
     * Document access bridge used to access wiki documents.
     */
    @Requirement
    private DocumentAccessBridge docBridge;

    /**
     * Used to dynamically lookup for components.
     */
    @Requirement
    private ComponentManager componentManager;

    /**
     * Used for parsing document name strings.
     */
    @Requirement("currentmixed")
    private DocumentReferenceResolver currentMixedDocumentReferenceResolver;

    /**
     * Used for importing office documents.
     */
    @Requirement
    private XHTMLOfficeDocumentBuilder xhtmlOfficeDocumentBuilder;

    /**
     * Used for importing office documents.
     */
    @Requirement
    private XDOMOfficeDocumentBuilder xdomOfficeDocumentBuilder;

    /**
     * Used for importing (presentation) office documents.
     */
    @Requirement
    private PresentationBuilder presentationBuilder;

    /**
     * Used for splitting office imports.
     */
    @Requirement
    private XDOMOfficeDocumentSplitter xdomOfficeDocumentSplitter;

    /**
     * {@inheritDoc}
     */
    @Deprecated
    public void importStream(InputStream documentStream, String documentFormat, String targetWikiDocument,
        Map<String, String> params) throws OfficeImporterException
    {
        // Deduct an office file name from documentFormat argument.
        String extension = documentFormat.substring(documentFormat.lastIndexOf('.') + 1);
        String officeFileName = "input." + extension;

        DocumentReference baseDocument = this.currentMixedDocumentReferenceResolver.resolve(targetWikiDocument);
        if (isPresentation(documentFormat)) {
            XDOMOfficeDocument presentation = presentationBuilder.build(documentStream, officeFileName, baseDocument);
            saveDocument(presentation, new TargetDocumentDescriptor(baseDocument, this.componentManager), null,
                isAppendRequest(params), false);
        } else {
            OfficeImporterFilter importerFilter = getImporterFilter(params);
            XHTMLOfficeDocument xhtmlDoc =
                xhtmlOfficeDocumentBuilder.build(documentStream, officeFileName, baseDocument,
                    shouldFilterStyles(params));
            importerFilter.filter(targetWikiDocument, xhtmlDoc.getContentDocument());
            XDOMOfficeDocument xdomDoc = xdomOfficeDocumentBuilder.build(xhtmlDoc);
            importerFilter.filter(targetWikiDocument, xdomDoc.getContentDocument(), false);
            if (!isSplitRequest(params)) {
                saveDocument(xdomDoc, new TargetDocumentDescriptor(baseDocument, this.componentManager),
                    importerFilter, isAppendRequest(params), false);
            } else {
                int[] headingLevels = getHeadingLevelsToSplit(params);
                String namingCriterionHint = params.get("childPagesNamingMethod");
                Map<TargetDocumentDescriptor, XDOMOfficeDocument> results =
                    xdomOfficeDocumentSplitter.split(xdomDoc, headingLevels, namingCriterionHint, baseDocument);
                for (Map.Entry<TargetDocumentDescriptor, XDOMOfficeDocument> result : results.entrySet()) {
                    boolean append = result.getKey().getDocumentReference().equals(baseDocument);
                    saveDocument(result.getValue(), result.getKey(), importerFilter, append, true);
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Deprecated
    public String importAttachment(String strDocumentName, String strAttachmentFileName, Map<String, String> params)
        throws OfficeImporterException
    {
        DocumentReference documentReference = this.currentMixedDocumentReferenceResolver.resolve(strDocumentName);
        AttachmentReference attachmentReference = new AttachmentReference(strAttachmentFileName, documentReference);

        InputStream attachmentStream;
        try {
            attachmentStream = this.docBridge.getAttachmentContent(attachmentReference);
        } catch (Exception ex) {
            throw new OfficeImporterException("Error while reading attachment", ex);
        }

        String result = null;
        if (isPresentation(strAttachmentFileName)) {
            XDOMOfficeDocument presentation =
                presentationBuilder.build(attachmentStream, strAttachmentFileName, documentReference);
            // Annotated xhtml renderer is required here because WYSIWYG needs these annotations to interpret the macros
            // used in the presentation XDOM. Fortunately WYSIWYG module is the only module which depends on this
            // OfficeImporter#importAttachment() deprecated API so we don't have any side effects of this. However we
            // need to update xwiki-web-gwt-wysiwyg-server module so that it does not depend on this deprecated API
            // anymore and instead directly use PresentaionBuilder component.
            result = presentation.getContentAsString("annotatedxhtml/1.0");
            attachArtifacts(strDocumentName, presentation.getArtifacts());
        } else {
            XHTMLOfficeDocument xhtmlDoc =
                xhtmlOfficeDocumentBuilder.build(attachmentStream, strAttachmentFileName, documentReference,
                    shouldFilterStyles(params));
            HTMLUtils.stripHTMLEnvelope(xhtmlDoc.getContentDocument());
            result = xhtmlDoc.getContentAsString();
            attachArtifacts(strDocumentName, xhtmlDoc.getArtifacts());
        }
        return result;
    }

    /**
     * Utility method for saving an {@link XDOMOfficeDocument} into a wiki page.
     * 
     * @param document the xdom office document.
     * @param targetDescriptor where to save the office document.
     * @param importerFilter filter to be used on the final content just before saving.
     * @param append whether content should be appended if the target document already exists.
     * @param isSplit if this document is a newly split one.
     * @throws OfficeImporterException if an error occurs while saving into the xwiki page.
     */
    private void saveDocument(XDOMOfficeDocument document, TargetDocumentDescriptor targetDescriptor,
        OfficeImporterFilter importerFilter, boolean append, boolean isSplit) throws OfficeImporterException
    {
        String target = targetDescriptor.getDocumentReferenceAsString();
        String parent = targetDescriptor.getParentReferenceAsString();
        String title = document.getTitle();
        String content = document.getContentAsString();
        content = (null != importerFilter) ? importerFilter.filter(target, content, isSplit) : content;
        try {
            if (docBridge.exists(target) && append) {
                // Must make sure that the target document is in xwiki 2.0 syntax.
                if (!docBridge.getDocumentSyntaxId(target).equals(Syntax.XWIKI_2_0.toIdString())) {
                    throw new OfficeImporterException("Target document is not an xwiki/2.0 document.");
                }
                String oldContent = docBridge.getDocumentContent(target);<commit_msg>XWIKI-5249: Omit XML declaration and document type when importing office file<commit_after>/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.officeimporter.internal;

import groovy.lang.GroovyClassLoader;

import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.xwiki.bridge.DocumentAccessBridge;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.Requirement;
import org.xwiki.component.logging.AbstractLogEnabled;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.model.reference.AttachmentReference;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.DocumentReferenceResolver;
import org.xwiki.officeimporter.OfficeImporter;
import org.xwiki.officeimporter.OfficeImporterException;
import org.xwiki.officeimporter.OfficeImporterFilter;
import org.xwiki.officeimporter.builder.PresentationBuilder;
import org.xwiki.officeimporter.builder.XDOMOfficeDocumentBuilder;
import org.xwiki.officeimporter.builder.XHTMLOfficeDocumentBuilder;
import org.xwiki.officeimporter.document.XDOMOfficeDocument;
import org.xwiki.officeimporter.document.XHTMLOfficeDocument;
import org.xwiki.officeimporter.splitter.TargetDocumentDescriptor;
import org.xwiki.officeimporter.splitter.XDOMOfficeDocumentSplitter;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.xml.html.HTMLUtils;

/**
 * Default implementation of the office importer component.
 * 
 * @version $Id$
 * @since 1.8M1
 * @deprecated use individual document builder components instead since 2.2M1
 */
@Component
@Deprecated
public class DefaultOfficeImporter extends AbstractLogEnabled implements OfficeImporter
{
    /**
     * File extensions corresponding to slide presentations.
     */
    public static final List<String> PRESENTATION_FORMAT_EXTENSIONS = Arrays.asList("ppt", "odp");

    /**
     * Error message to be used for indicating invalid splitting criterion.
     */
    private static final String ERROR_INVALID_SPLITTING_CRITERION = "Unable to determine splitting criterion.";

    /**
     * Document access bridge used to access wiki documents.
     */
    @Requirement
    private DocumentAccessBridge docBridge;

    /**
     * Used to dynamically lookup for components.
     */
    @Requirement
    private ComponentManager componentManager;

    /**
     * Used for parsing document name strings.
     */
    @Requirement("currentmixed")
    private DocumentReferenceResolver currentMixedDocumentReferenceResolver;

    /**
     * Used for importing office documents.
     */
    @Requirement
    private XHTMLOfficeDocumentBuilder xhtmlOfficeDocumentBuilder;

    /**
     * Used for importing office documents.
     */
    @Requirement
    private XDOMOfficeDocumentBuilder xdomOfficeDocumentBuilder;

    /**
     * Used for importing (presentation) office documents.
     */
    @Requirement
    private PresentationBuilder presentationBuilder;

    /**
     * Used for splitting office imports.
     */
    @Requirement
    private XDOMOfficeDocumentSplitter xdomOfficeDocumentSplitter;

    /**
     * {@inheritDoc}
     */
    @Deprecated
    public void importStream(InputStream documentStream, String documentFormat, String targetWikiDocument,
        Map<String, String> params) throws OfficeImporterException
    {
        // Deduct an office file name from documentFormat argument.
        String extension = documentFormat.substring(documentFormat.lastIndexOf('.') + 1);
        String officeFileName = "input." + extension;

        DocumentReference baseDocument = this.currentMixedDocumentReferenceResolver.resolve(targetWikiDocument);
        if (isPresentation(documentFormat)) {
            XDOMOfficeDocument presentation = presentationBuilder.build(documentStream, officeFileName, baseDocument);
            saveDocument(presentation, new TargetDocumentDescriptor(baseDocument, this.componentManager), null,
                isAppendRequest(params), false);
        } else {
            OfficeImporterFilter importerFilter = getImporterFilter(params);
            XHTMLOfficeDocument xhtmlDoc =
                xhtmlOfficeDocumentBuilder.build(documentStream, officeFileName, baseDocument,
                    shouldFilterStyles(params));
            importerFilter.filter(targetWikiDocument, xhtmlDoc.getContentDocument());
            XDOMOfficeDocument xdomDoc = xdomOfficeDocumentBuilder.build(xhtmlDoc);
            importerFilter.filter(targetWikiDocument, xdomDoc.getContentDocument(), false);
            if (!isSplitRequest(params)) {
                saveDocument(xdomDoc, new TargetDocumentDescriptor(baseDocument, this.componentManager),
                    importerFilter, isAppendRequest(params), false);
            } else {
                int[] headingLevels = getHeadingLevelsToSplit(params);
                String namingCriterionHint = params.get("childPagesNamingMethod");
                Map<TargetDocumentDescriptor, XDOMOfficeDocument> results =
                    xdomOfficeDocumentSplitter.split(xdomDoc, headingLevels, namingCriterionHint, baseDocument);
                for (Map.Entry<TargetDocumentDescriptor, XDOMOfficeDocument> result : results.entrySet()) {
                    boolean append = result.getKey().getDocumentReference().equals(baseDocument);
                    saveDocument(result.getValue(), result.getKey(), importerFilter, append, true);
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Deprecated
    public String importAttachment(String strDocumentName, String strAttachmentFileName, Map<String, String> params)
        throws OfficeImporterException
    {
        DocumentReference documentReference = this.currentMixedDocumentReferenceResolver.resolve(strDocumentName);
        AttachmentReference attachmentReference = new AttachmentReference(strAttachmentFileName, documentReference);

        InputStream attachmentStream;
        try {
            attachmentStream = this.docBridge.getAttachmentContent(attachmentReference);
        } catch (Exception ex) {
            throw new OfficeImporterException("Error while reading attachment", ex);
        }

        String result = null;
        if (isPresentation(strAttachmentFileName)) {
            XDOMOfficeDocument presentation =
                presentationBuilder.build(attachmentStream, strAttachmentFileName, documentReference);
            // Annotated xhtml renderer is required here because WYSIWYG needs these annotations to interpret the macros
            // used in the presentation XDOM. Fortunately WYSIWYG module is the only module which depends on this
            // OfficeImporter#importAttachment() deprecated API so we don't have any side effects of this. However we
            // need to update xwiki-web-gwt-wysiwyg-server module so that it does not depend on this deprecated API
            // anymore and instead directly use PresentaionBuilder component.
            result = presentation.getContentAsString("annotatedxhtml/1.0");
            attachArtifacts(strDocumentName, presentation.getArtifacts());
        } else {
            XHTMLOfficeDocument xhtmlDoc =
                xhtmlOfficeDocumentBuilder.build(attachmentStream, strAttachmentFileName, documentReference,
                    shouldFilterStyles(params));
            HTMLUtils.stripHTMLEnvelope(xhtmlDoc.getContentDocument());
            boolean omitXMLDeclaration = Boolean.valueOf(params.get("omitXMLDeclaration"));
            boolean omitDocumentType = Boolean.valueOf(params.get("omitDocumentType"));
            // We can't use xhtmlDoc.getContentAsString() because it includes the XML declaration and the document type.
            result = HTMLUtils.toString(xhtmlDoc.getContentDocument(), omitXMLDeclaration, omitDocumentType);
            attachArtifacts(strDocumentName, xhtmlDoc.getArtifacts());
        }
        return result;
    }

    /**
     * Utility method for saving an {@link XDOMOfficeDocument} into a wiki page.
     * 
     * @param document the xdom office document.
     * @param targetDescriptor where to save the office document.
     * @param importerFilter filter to be used on the final content just before saving.
     * @param append whether content should be appended if the target document already exists.
     * @param isSplit if this document is a newly split one.
     * @throws OfficeImporterException if an error occurs while saving into the xwiki page.
     */
    private void saveDocument(XDOMOfficeDocument document, TargetDocumentDescriptor targetDescriptor,
        OfficeImporterFilter importerFilter, boolean append, boolean isSplit) throws OfficeImporterException
    {
        String target = targetDescriptor.getDocumentReferenceAsString();
        String parent = targetDescriptor.getParentReferenceAsString();
        String title = document.getTitle();
        String content = document.getContentAsString();
        content = (null != importerFilter) ? importerFilter.filter(target, content, isSplit) : content;
        try {
            if (docBridge.exists(target) && append) {
                // Must make sure that the target document is in xwiki 2.0 syntax.
                if (!docBridge.getDocumentSyntaxId(target).equals(Syntax.XWIKI_2_0.toIdString())) {
                    throw new OfficeImporterException("Target document is not an xwiki/2.0 document.");
                }
                String oldContent = docBridge.getDocumentContent(target);
{'fraction_non_alphanumeric': 0.07313352035041094, 'fraction_numerical': 0.0029529012254540087, 'mean_word_length': 3.373654756780026, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, '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': '1094673', 'n_tokens_mistral': 5066, 'n_tokens_neox': 4792, 'n_words': 1407}