com.haulmont.yarg.formatters.impl.inline.AbstractInliner.java Source code

Java tutorial

Introduction

Here is the source code for com.haulmont.yarg.formatters.impl.inline.AbstractInliner.java

Source

/*
 * Copyright 2013 Haulmont
 *
 * 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.
 */

/**
 * @author degtyarjov
 * @version $Id$
 */
package com.haulmont.yarg.formatters.impl.inline;

import com.haulmont.yarg.exception.ReportFormattingException;
import com.haulmont.yarg.formatters.impl.doc.OfficeComponent;
import com.haulmont.yarg.formatters.impl.doc.connector.OfficeResourceProvider;
import com.haulmont.yarg.formatters.impl.xlsx.CellReference;
import com.haulmont.yarg.formatters.impl.xlsx.XlsxUtils;
import com.sun.star.awt.Size;
import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.XPropertySet;
import com.sun.star.drawing.XShape;
import com.sun.star.graphic.XGraphic;
import com.sun.star.graphic.XGraphicProvider;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter;
import com.sun.star.text.HoriOrientation;
import com.sun.star.text.XText;
import com.sun.star.text.XTextContent;
import com.sun.star.text.XTextRange;
import com.sun.star.uno.XComponentContext;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.ImageUtils;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.docx4j.dml.*;
import org.docx4j.dml.spreadsheetdrawing.*;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.SpreadsheetMLPackage;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.DrawingML.Drawing;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.SpreadsheetML.WorksheetPart;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.R;
import org.docx4j.wml.Text;
import org.xlsx4j.sml.Cell;

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

import static com.haulmont.yarg.formatters.impl.doc.UnoConverter.as;
import static org.apache.poi.util.Units.EMU_PER_PIXEL;

public abstract class AbstractInliner implements ContentInliner {
    private static final String TEXT_GRAPHIC_OBJECT = "com.sun.star.text.TextGraphicObject";
    private static final String GRAPHIC_PROVIDER_OBJECT = "com.sun.star.graphic.GraphicProvider";
    private static final int IMAGE_FACTOR = 27;

    protected Pattern tagPattern;
    protected int docxUniqueId1, docxUniqueId2;

    protected abstract byte[] getContent(Object paramValue);

    public void inlineToXlsx(SpreadsheetMLPackage pkg, WorksheetPart worksheetPart, Cell newCell, Object paramValue,
            Matcher matcher) {
        try {
            Image image = new Image(paramValue, matcher);
            if (image.isValid()) {
                BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(pkg, worksheetPart,
                        image.imageContent);
                CTOneCellAnchor anchor = new CTOneCellAnchor();
                anchor.setFrom(new CTMarker());
                CellReference cellReference = new CellReference("", newCell.getR());
                anchor.getFrom().setCol(cellReference.getColumn() - 1);
                anchor.getFrom().setRow(cellReference.getRow() - 1);
                anchor.setExt(new CTPositiveSize2D());
                anchor.getExt().setCx(XlsxUtils.convertPxToEmu(image.width));
                anchor.getExt().setCy(XlsxUtils.convertPxToEmu(image.height));
                putImage(worksheetPart, pkg, imagePart, anchor);
            }
        } catch (Exception e) {
            throw new ReportFormattingException("An error occurred while inserting bitmap to xlsx file", e);
        }
    }

    private void putImage(WorksheetPart worksheetPart, SpreadsheetMLPackage pkg, BinaryPartAbstractImage imagePart,
            CTOneCellAnchor anchor) throws Docx4JException {
        PartName drawingPart = new PartName(
                worksheetPart.getPartName().getName().replace("worksheets/sheet", "drawings/drawing"));
        String imagePartName = imagePart.getPartName().getName();
        Drawing drawing = (Drawing) pkg.getParts().get(drawingPart);
        int currentId = 0;
        if (drawing == null) {
            drawing = new Drawing(drawingPart);
            drawing.setContents(new org.docx4j.dml.spreadsheetdrawing.CTDrawing());
            Relationship relationship = worksheetPart.addTargetPart(drawing);
            org.xlsx4j.sml.CTDrawing smlDrawing = new org.xlsx4j.sml.CTDrawing();
            smlDrawing.setId(relationship.getId());
            smlDrawing.setParent(worksheetPart.getContents());
            worksheetPart.getContents().setDrawing(smlDrawing);
        } else {
            currentId = drawing.getContents().getEGAnchor().size();
        }

        CTPicture picture = new CTPicture();

        CTBlipFillProperties blipFillProperties = new CTBlipFillProperties();
        blipFillProperties.setStretch(new CTStretchInfoProperties());
        blipFillProperties.getStretch().setFillRect(new CTRelativeRect());
        blipFillProperties.setBlip(new CTBlip());
        blipFillProperties.getBlip().setEmbed("rId" + (currentId + 1));
        blipFillProperties.getBlip().setCstate(STBlipCompression.PRINT);

        picture.setBlipFill(blipFillProperties);

        CTNonVisualDrawingProps nonVisualDrawingProps = new CTNonVisualDrawingProps();
        nonVisualDrawingProps.setId(currentId + 2);
        nonVisualDrawingProps.setName(imagePartName.substring(imagePartName.lastIndexOf("/") + 1));
        nonVisualDrawingProps.setDescr(nonVisualDrawingProps.getName());

        CTNonVisualPictureProperties nonVisualPictureProperties = new CTNonVisualPictureProperties();
        nonVisualPictureProperties.setPicLocks(new CTPictureLocking());
        nonVisualPictureProperties.getPicLocks().setNoChangeAspect(true);
        CTPictureNonVisual nonVisualPicture = new CTPictureNonVisual();

        nonVisualPicture.setCNvPr(nonVisualDrawingProps);
        nonVisualPicture.setCNvPicPr(nonVisualPictureProperties);

        picture.setNvPicPr(nonVisualPicture);

        CTShapeProperties shapeProperties = new CTShapeProperties();
        CTTransform2D transform2D = new CTTransform2D();
        transform2D.setOff(new CTPoint2D());
        transform2D.setExt(new CTPositiveSize2D());
        shapeProperties.setXfrm(transform2D);
        shapeProperties.setPrstGeom(new CTPresetGeometry2D());
        shapeProperties.getPrstGeom().setPrst(STShapeType.RECT);
        shapeProperties.getPrstGeom().setAvLst(new CTGeomGuideList());

        picture.setSpPr(shapeProperties);

        anchor.setPic(picture);
        anchor.setClientData(new CTAnchorClientData());

        drawing.getContents().getEGAnchor().add(anchor);

        Relationship rel = new Relationship();
        rel.setId("rId" + (currentId + 1));
        rel.setType(Namespaces.IMAGE);
        rel.setTarget(imagePartName);

        drawing.getRelationshipsPart().addRelationship(rel);
        RelationshipsPart relPart = drawing.getRelationshipsPart();
        pkg.getParts().remove(relPart.getPartName());
        pkg.getParts().put(relPart);
        pkg.getParts().remove(drawing.getPartName());
        pkg.getParts().put(drawing);
    }

    @Override
    public void inlineToDocx(WordprocessingMLPackage wordPackage, Text text, Object paramValue,
            Matcher paramsMatcher) {
        try {
            Image image = new Image(paramValue, paramsMatcher);
            if (image.isValid()) {
                BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordPackage,
                        image.imageContent);
                Inline inline = imagePart.createImageInline("", "", docxUniqueId1++, docxUniqueId2++, false);
                ImageSize oldSize = imagePart.getImageInfo().getSize();
                double widthExtent = (double) image.width / oldSize.getWidthPx();
                double heightExtent = (double) image.height / oldSize.getHeightPx();
                inline.getExtent().setCx((long) (inline.getExtent().getCx() * widthExtent));
                inline.getExtent().setCy((long) (inline.getExtent().getCy() * heightExtent));
                org.docx4j.wml.Drawing drawing = new org.docx4j.wml.ObjectFactory().createDrawing();
                R run = (R) text.getParent();
                run.getContent().add(drawing);
                drawing.getAnchorOrInline().add(inline);
                text.setValue("");
            }
        } catch (Exception e) {
            throw new ReportFormattingException("An error occurred while inserting bitmap to docx file", e);
        }
    }

    @Override
    public void inlineToXls(HSSFPatriarch patriarch, HSSFCell resultCell, Object paramValue,
            Matcher paramsMatcher) {
        try {
            Image image = new Image(paramValue, paramsMatcher);
            if (image.isValid()) {
                HSSFSheet sheet = resultCell.getSheet();
                HSSFWorkbook workbook = sheet.getWorkbook();

                int pictureIdx = workbook.addPicture(image.imageContent, Workbook.PICTURE_TYPE_JPEG);

                CreationHelper helper = workbook.getCreationHelper();
                ClientAnchor anchor = helper.createClientAnchor();
                anchor.setCol1(resultCell.getColumnIndex());
                anchor.setRow1(resultCell.getRowIndex());
                anchor.setCol2(resultCell.getColumnIndex());
                anchor.setRow2(resultCell.getRowIndex());
                if (patriarch == null) {
                    throw new IllegalArgumentException(String.format(
                            "No HSSFPatriarch object provided. Charts on this sheet could cause this effect. Please check sheet %s",
                            resultCell.getSheet().getSheetName()));
                }
                HSSFPicture picture = patriarch.createPicture(anchor, pictureIdx);
                Dimension size = ImageUtils.getDimensionFromAnchor(picture);
                double actualHeight = size.getHeight() / EMU_PER_PIXEL;
                double actualWidth = size.getWidth() / EMU_PER_PIXEL;
                picture.resize((double) image.width / actualWidth, (double) image.height / actualHeight);
            }
        } catch (IllegalArgumentException e) {
            throw new ReportFormattingException("An error occurred while inserting bitmap to xls file", e);
        }
    }

    @Override
    public void inlineToDoc(OfficeComponent officeComponent, XTextRange textRange, XText destination,
            Object paramValue, Matcher paramsMatcher) throws Exception {
        try {
            if (paramValue != null) {
                Image image = new Image(paramValue, paramsMatcher);

                if (image.isValid()) {
                    XComponent xComponent = officeComponent.getOfficeComponent();
                    insertImage(xComponent, officeComponent.getOfficeResourceProvider(), destination, textRange,
                            image);
                }
            }
        } catch (Exception e) {
            throw new ReportFormattingException("An error occurred while inserting bitmap to doc file", e);
        }
    }

    protected void insertImage(XComponent document, OfficeResourceProvider officeResourceProvider,
            XText destination, XTextRange textRange, Image image) throws Exception {
        XMultiServiceFactory xFactory = as(XMultiServiceFactory.class, document);
        XComponentContext xComponentContext = officeResourceProvider.getXComponentContext();
        XMultiComponentFactory serviceManager = xComponentContext.getServiceManager();

        Object oImage = xFactory.createInstance(TEXT_GRAPHIC_OBJECT);
        Object oGraphicProvider = serviceManager.createInstanceWithContext(GRAPHIC_PROVIDER_OBJECT,
                xComponentContext);

        XGraphicProvider xGraphicProvider = as(XGraphicProvider.class, oGraphicProvider);

        XPropertySet imageProperties = buildImageProperties(xGraphicProvider, oImage, image.imageContent);
        XTextContent xTextContent = as(XTextContent.class, oImage);
        destination.insertTextContent(textRange, xTextContent, true);
        setImageSize(image.width, image.height, oImage, imageProperties);
    }

    protected void setImageSize(int width, int height, Object oImage, XPropertySet imageProperties)
            throws Exception {
        Size aActualSize = (Size) imageProperties.getPropertyValue("ActualSize");
        aActualSize.Height = height * IMAGE_FACTOR;
        aActualSize.Width = width * IMAGE_FACTOR;
        XShape xShape = as(XShape.class, oImage);
        xShape.setSize(aActualSize);
    }

    protected XPropertySet buildImageProperties(XGraphicProvider xGraphicProvider, Object oImage,
            byte[] imageContent) throws Exception {
        XPropertySet imageProperties = as(XPropertySet.class, oImage);

        PropertyValue[] propValues = new PropertyValue[] { new PropertyValue() };
        propValues[0].Name = "InputStream";
        propValues[0].Value = new ByteArrayToXInputStreamAdapter(imageContent);

        XGraphic graphic = xGraphicProvider.queryGraphic(propValues);
        if (graphic != null) {
            imageProperties.setPropertyValue("Graphic", graphic);

            imageProperties.setPropertyValue("HoriOrient", HoriOrientation.NONE);
            imageProperties.setPropertyValue("VertOrient", HoriOrientation.NONE);

            imageProperties.setPropertyValue("HoriOrientPosition", 0);
            imageProperties.setPropertyValue("VertOrientPosition", 0);
        }

        return imageProperties;
    }

    protected class Image {
        byte[] imageContent = null;
        int width = 0;
        int height = 0;

        public Image(Object paramValue, Matcher paramsMatcher) {
            if (paramValue == null) {
                return;
            }

            imageContent = getContent(paramValue);
            if (imageContent.length == 0) {
                imageContent = null;
                return;
            }

            width = Integer.parseInt(paramsMatcher.group(1));
            height = Integer.parseInt(paramsMatcher.group(2));
        }

        boolean isValid() {
            return imageContent != null;
        }
    }

}