Bug 553803: [Model2Doc] Misc methods to provide and others

Change-Id: Ib17b422033d6fa76899ddc018fe4bb868864416a
Signed-off-by: Vincent Lorenzo <vincent.lorenzo@cea.fr>
diff --git a/plugins/emf/org.eclipse.papyrus.model2doc.emf.template2structure/META-INF/MANIFEST.MF b/plugins/emf/org.eclipse.papyrus.model2doc.emf.template2structure/META-INF/MANIFEST.MF
index b6c98bc..1575202 100755
--- a/plugins/emf/org.eclipse.papyrus.model2doc.emf.template2structure/META-INF/MANIFEST.MF
+++ b/plugins/emf/org.eclipse.papyrus.model2doc.emf.template2structure/META-INF/MANIFEST.MF
@@ -10,7 +10,6 @@
  org.eclipse.papyrus.infra.core.log;bundle-version="[1.2.0,2.0.0)",
  org.eclipse.papyrus.model2doc.emf.documentstructuretemplate;bundle-version="[0.7.0,1.0.0)",
  org.eclipse.papyrus.model2doc.emf.documentstructure;bundle-version="[0.7.0,1.0.0)",
- org.eclipse.papyrus.model2doc.emf.documentstructuretemplate.editor;bundle-version="[0.7.0,1.0.0)",
  org.eclipse.emf.ecore;bundle-version="[2.17.0,3.0.0)",
  org.eclipse.emf.transaction;bundle-version="[1.9.0,2.0.0)",
  org.eclipse.papyrus.model2doc.core.generatorconfiguration;bundle-version="[0.7.0,1.0.0)",
diff --git a/plugins/integration/ieee/org.eclipse.papyrus.model2doc.integration.ieee.requirements.odt.ui/plugin.xml b/plugins/integration/ieee/org.eclipse.papyrus.model2doc.integration.ieee.requirements.odt.ui/plugin.xml
index 58ffff3..baa4eb0 100755
--- a/plugins/integration/ieee/org.eclipse.papyrus.model2doc.integration.ieee.requirements.odt.ui/plugin.xml
+++ b/plugins/integration/ieee/org.eclipse.papyrus.model2doc.integration.ieee.requirements.odt.ui/plugin.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?eclipse version="3.4"?>
 <plugin>
-   <extension
+   <!--extension
          point="org.eclipse.core.expressions.propertyTesters">
       <propertyTester
             class="org.eclipse.papyrus.model2doc.integration.ieee.requirements.odt.ui.internal.propertytester.IEEERequirementsDocumentTester"
@@ -10,5 +10,5 @@
             properties="isIEEERequirementsDocument"
             type="org.eclipse.jface.viewers.IStructuredSelection">
       </propertyTester>
-   </extension>
+   </extension-->
 </plugin>
\ No newline at end of file
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/META-INF/MANIFEST.MF b/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/META-INF/MANIFEST.MF
index 61fb6c1..035feab 100755
--- a/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/META-INF/MANIFEST.MF
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/META-INF/MANIFEST.MF
@@ -22,3 +22,7 @@
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Automatic-Module-Name: org.eclipse.papyrus.model2doc.emf.stucture2odt
 Bundle-ActivationPolicy: lazy
+Export-Package: org.eclipse.papyrus.model2doc.odt.emf.structure2document.internal.generators,
+ org.eclipse.papyrus.model2doc.odt.emf.structure2document.internal.handler,
+ org.eclipse.papyrus.model2doc.odt.emf.structure2document.internal.transcriber,
+ org.eclipse.papyrus.model2doc.odt.emf.structure2document.internal.utils
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/src/org/eclipse/papyrus/model2doc/odt/emf/structure2document/internal/handler/CreateODTFileFromTextDocumentHelper.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/src/org/eclipse/papyrus/model2doc/odt/emf/structure2document/internal/handler/CreateODTFileFromTextDocumentHelper.java
index 9ab201d..17ef7e3 100755
--- a/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/src/org/eclipse/papyrus/model2doc/odt/emf/structure2document/internal/handler/CreateODTFileFromTextDocumentHelper.java
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/src/org/eclipse/papyrus/model2doc/odt/emf/structure2document/internal/handler/CreateODTFileFromTextDocumentHelper.java
@@ -24,39 +24,66 @@
 import org.eclipse.papyrus.model2doc.odt.internal.transcription.ODTTranscription;
 
 /**
- *
+ * This helper allows to create the ODT file from a {@link TextDocument}
  */
+// TODO : a such class should be API, without dependencies on ODT
 public class CreateODTFileFromTextDocumentHelper {
 
+	/**
+	 * The initial text document
+	 */
 	private TextDocument textDocument;
 
-	protected CreateODTFileFromTextDocumentHelper() {
-		// nothing to do
-	}
-
+	/**
+	 *
+	 * Constructor.
+	 *
+	 * @param textDocument
+	 *            the text document we want to process
+	 */
 	public CreateODTFileFromTextDocumentHelper(final TextDocument textDocument) {
-		setTextDocument(textDocument);
+		this.textDocument = textDocument;
 	}
 
 
-	public void generate() {
+	/**
+	 * This method generate the final odt document
+	 */
+	public void generate() {// TODO : must return the generated file
 		if (this.textDocument == null) {
 			Activator.log.warn("The TextDocument is null"); //$NON-NLS-1$
 			return;
 		}
 		final IDocumentGeneratorConfiguration ddgc = textDocument.getDocumentGeneratorConfiguration();
 
-		DefaultStyleEditor styleEditor = new DefaultStyleEditor();
-		Transcription transcription = new ODTTranscription(styleEditor, ddgc);
+		final Transcription transcription = createTranscription(ddgc);
 
-		Transcriber t = new StructureToODTTranscriber(textDocument, transcription);
+		Transcriber t = createTranscriber(textDocument, transcription);
 		t.transcribe();
 	}
 
+	/**
+	 *
+	 * @param ddgc
+	 *            the document generation configuration
+	 * @return
+	 *         the transcription to use to write the ODT documentF
+	 */
+	protected Transcription createTranscription(final IDocumentGeneratorConfiguration ddgc) {
+		return new ODTTranscription(new DefaultStyleEditor(), ddgc);
+	}
 
-
-	protected void setTextDocument(final TextDocument textDocument) {
-		this.textDocument = textDocument;
+	/**
+	 *
+	 * @param textDocument
+	 *            the text document
+	 * @param transcription
+	 *            the transcription to use
+	 * @return
+	 *         the Transcriber in charge to cross the TextDocument to write the final document using the Transcription element
+	 */
+	protected Transcriber createTranscriber(final TextDocument textDocument, final Transcription transcription) {
+		return new StructureToODTTranscriber(textDocument, transcription);
 	}
 
 }
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/src/org/eclipse/papyrus/model2doc/odt/emf/structure2document/internal/transcriber/StructureToODTTranscriber.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/src/org/eclipse/papyrus/model2doc/odt/emf/structure2document/internal/transcriber/StructureToODTTranscriber.java
index 63b7303..18bdcba 100755
--- a/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/src/org/eclipse/papyrus/model2doc/odt/emf/structure2document/internal/transcriber/StructureToODTTranscriber.java
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt.emf.structure2document/src/org/eclipse/papyrus/model2doc/odt/emf/structure2document/internal/transcriber/StructureToODTTranscriber.java
@@ -34,6 +34,7 @@
 
 /**
  * This class crosses a {@link TextDocument} to fill an odt file
+ * TODO : this class must be moved. it has no dependencies on odt
  */
 public class StructureToODTTranscriber implements Transcriber {
 
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/transcription/ODTTranscription.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/transcription/ODTTranscription.java
index e99ca98..5d0454c 100755
--- a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/transcription/ODTTranscription.java
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/transcription/ODTTranscription.java
@@ -38,6 +38,7 @@
 import org.eclipse.papyrus.model2doc.odt.internal.constants.ParagraphPropertiesConstants;
 import org.eclipse.papyrus.model2doc.odt.internal.constants.ParagraphPropertiesValues;
 import org.eclipse.papyrus.model2doc.odt.internal.editor.ODTEditor;
+import org.eclipse.papyrus.model2doc.odt.internal.util.PropertySetUtil;
 import org.eclipse.papyrus.model2doc.odt.internal.util.WriteUtil;
 import org.eclipse.papyrus.model2doc.odt.service.StyleService;
 import org.eclipse.papyrus.model2doc.odt.service.StyleServiceImpl;
@@ -80,22 +81,22 @@
 	private static final String TABLE_OF_CONTENTS_TYPE = "com.sun.star.text.ContentIndex"; //$NON-NLS-1$
 
 	/** The text interface contains all methods and properties to manipulate the content from a text document. */
-	private XText text = null;
+	protected XText text = null;
 
 	/** The cursor for walking through the model of the text document. */
-	private XTextCursor cursor = null;
+	protected XTextCursor cursor = null;
 
-	private StyleEditor styleEditor = null;
+	protected StyleEditor styleEditor = null;
 
-	private ODTEditor odtEditor = null;
+	protected ODTEditor odtEditor = null;
 
-	private IDocumentGeneratorConfiguration odtGeneratorConfig = null;
+	protected IDocumentGeneratorConfiguration odtGeneratorConfig = null;
 
-	private WriteService writeService = null;
+	protected WriteService writeService = null;
 
-	private StyleService styleService = null;
+	protected StyleService styleService = null;
 
-	private List<XDocumentIndex> tablesOfIndexes = new ArrayList<>();
+	protected List<XDocumentIndex> tablesOfIndexes = new ArrayList<>();
 
 	/**
 	 * Constructor.
@@ -248,7 +249,7 @@
 				xIndex.setPropertyValue("CreateFromOutline", true); //$NON-NLS-1$
 			} else if (TABLE_OF_FIGURE_TYPE.equals(libreOfficePagetype)) {
 				xIndex.setPropertyValue("CreateFromLabels", true); //$NON-NLS-1$
-				xIndex.setPropertyValue("LabelCategory", "Figure"); //$NON-NLS-1$
+				xIndex.setPropertyValue("LabelCategory", "Figure"); //$NON-NLS-1$ //$NON-NLS-2$
 				xIndex.setPropertyValue("LabelDisplayType", ChapterFormat.NAME_NUMBER); //$NON-NLS-1$
 			}
 			xIndex.setPropertyValue("Title", pageTitle); //$NON-NLS-1$
@@ -353,7 +354,7 @@
 
 			XPropertyContainer userDefined = props.getUserDefinedProperties();
 
-			// we need to remove the property if it already exist, in order to be change its value
+			// we need to remove the property if it already exist, in order to be able to change its value
 			try {
 				userDefined.removeProperty(CustomFields.AUTHORS);
 			} catch (UnknownPropertyException e) {
@@ -412,4 +413,47 @@
 		this.writeService.insertTextFile(cursor, path);
 	}
 
+
+
+	/**
+	 * This method should works but has never been tested... here as reminder
+	 *
+	 * @param pageBreak
+	 */
+	private void addPageBreak(final PageBreak pageBreak) {
+		int breakValue = -1;
+		switch (pageBreak) {
+		case BEFORE:
+			breakValue = com.sun.star.style.BreakType.PAGE_BEFORE.getValue();
+			break;
+		case AFTER:
+			breakValue = com.sun.star.style.BreakType.PAGE_AFTER.getValue();
+			break;
+		case BOTH:
+			breakValue = com.sun.star.style.BreakType.PAGE_BOTH.getValue();
+			break;
+		default:
+			breakValue = com.sun.star.style.BreakType.PAGE_BOTH.getValue();
+		}
+		WriteUtil.addControlCharacter(cursor, (short) breakValue);
+	}
+
+	/**
+	 * This method should works but has never been tested... here as reminder
+	 */
+	private void addPageBreak() {
+		WriteUtil.addControlCharacter(cursor, (short) com.sun.star.style.BreakType.PAGE_AFTER.getValue());
+		PropertySetUtil.setProperty(cursor, "BreakType", 4); //$NON-NLS-1$
+		cursor.gotoEnd(false);
+		WriteUtil.addControlCharacter(cursor, (short) com.sun.star.style.BreakType.PAGE_AFTER.getValue());
+	}
+
+	/**
+	 * Kind of PageBreak according to the LibreOffice API
+	 */
+	private enum PageBreak {
+		BEFORE, AFTER, BOTH
+	}
+
+
 }
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/AdaptToPageImageResizer.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/AdaptToPageImageResizer.java
new file mode 100755
index 0000000..05afacb
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/AdaptToPageImageResizer.java
@@ -0,0 +1,44 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.lang.XMultiComponentFactory;
+import com.sun.star.text.XTextContent;
+import com.sun.star.text.XTextDocument;
+import com.sun.star.uno.XComponentContext;
+
+/**
+ * This resizer adapts the image to the page size.
+ * The image will be scaled to fit in the page
+ */
+public class AdaptToPageImageResizer implements IImageResizer {
+
+	/**
+	 * @see org.eclipse.papyrus.model2doc.odt.internal.util.IImageResizer#resizeImage(com.sun.star.text.XTextContent, java.lang.String, com.sun.star.text.XTextDocument, com.sun.star.lang.XMultiComponentFactory, com.sun.star.uno.XComponentContext)
+	 *
+	 * @param graphicContent
+	 * @param imagePath
+	 * @param xTextDocument
+	 * @param xMultiComponentFactory
+	 * @param xComponentContext
+	 * @return
+	 */
+	@Override
+	public XTextContent resizeImage(XTextContent graphicContent, String imagePath, XTextDocument xTextDocument, XMultiComponentFactory xMultiComponentFactory, XComponentContext xComponentContext) {
+		return ImageUtil.resizeImage(graphicContent, imagePath, xTextDocument, xMultiComponentFactory, xComponentContext);
+	}
+
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/CaptionUtils.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/CaptionUtils.java
new file mode 100755
index 0000000..95a7db0
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/CaptionUtils.java
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import org.eclipse.papyrus.model2doc.odt.Activator;
+import org.eclipse.papyrus.model2doc.odt.internal.editor.ODTEditor;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.text.XDependentTextField;
+import com.sun.star.text.XTextCursor;
+import com.sun.star.text.XTextFieldsSupplier;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.NumberFormat;
+
+/**
+ * This class provides methods related to {@link XTextFieldsSupplier} and others to create and insert caption
+ */
+public class CaptionUtils {
+
+	/**
+	 * This string allows to create a master SetExpression for figure
+	 */
+	public static final String TEXT_FIELDMASTER_SET_EXPRESSION_FIGURE = "com.sun.star.text.fieldmaster.SetExpression.Figure"; //$NON-NLS-1$
+
+	/**
+	 * This string allows to create the dependant expression to get the figure number
+	 */
+	public static final String TEXTFIELD_SET_EXPRESSION = "com.sun.star.text.textfield.SetExpression"; //$NON-NLS-1$
+
+	private CaptionUtils() {
+		// to prevent instanciation
+	}
+
+	/**
+	 * This method allows to write the caption of the figure
+	 *
+	 * @param xTextCursor
+	 *            the xTextCursor to use to create the caption
+	 * @param caption
+	 *            the caption text itself
+	 * @param odtEditor
+	 *            the odtEditor to use to get the services
+	 */
+	public static final void writeFigureCaption(final XTextCursor xTextCursor, final String caption, final ODTEditor odtEditor) {
+		try {
+			// managing the caption, we need a text field master
+			XTextFieldsSupplier supplier = UnoRuntime.queryInterface(XTextFieldsSupplier.class, odtEditor.getXTextDocument());
+			XNameAccess masters = supplier.getTextFieldMasters();
+			Object masterSetExpressionForFigure = masters.getByName(TEXT_FIELDMASTER_SET_EXPRESSION_FIGURE);
+
+			// create a dependent SetExpression
+			XMultiServiceFactory xMultiServiceFactory = odtEditor.getXMultiServiceFactory();
+			Object textFieldSetExpression = xMultiServiceFactory.createInstance(TEXTFIELD_SET_EXPRESSION);
+
+			XPropertySet textFieldSetExpressionPropertySet = UnoRuntime.queryInterface(XPropertySet.class, textFieldSetExpression);
+			textFieldSetExpressionPropertySet.setPropertyValue("NumberingType", com.sun.star.style.NumberingType.ARABIC); //$NON-NLS-1$
+			textFieldSetExpressionPropertySet.setPropertyValue("NumberFormat", NumberFormat.NUMBER); //$NON-NLS-1$
+			textFieldSetExpressionPropertySet.setPropertyValue("Content", "Figure + 1"); //$NON-NLS-1$ //$NON-NLS-2$
+			XDependentTextField xDependeantTextField = UnoRuntime.queryInterface(XDependentTextField.class, textFieldSetExpression);
+
+			// attach the dependent SetExpression to its master
+			xDependeantTextField.attachTextFieldMaster(UnoRuntime.queryInterface(XPropertySet.class, masterSetExpressionForFigure));
+
+			xTextCursor.getText().insertString(xTextCursor, "Figure ", false); //$NON-NLS-1$
+
+			// insert the SetExpression
+			xTextCursor.getText().insertTextContent(xTextCursor, xDependeantTextField, true);
+
+
+			if (caption != null && !caption.isEmpty()) {
+				xTextCursor.getText().insertString(xTextCursor, ": " + caption, false); //$NON-NLS-1$
+			}
+		} catch (com.sun.star.uno.Exception e) {
+			Activator.log.error(e);
+		}
+	}
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/CellImageWriter.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/CellImageWriter.java
new file mode 100755
index 0000000..15f04f1
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/CellImageWriter.java
@@ -0,0 +1,72 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import org.eclipse.papyrus.model2doc.odt.internal.editor.ODTEditor;
+
+import com.sun.star.text.TextContentAnchorType;
+
+/**
+ * This Writer allows to write an image in a cell of an XTextTable
+ */
+public class CellImageWriter extends ParagraphImageWriter {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param odtEditor
+	 */
+	public CellImageWriter(final ODTEditor odtEditor) {
+		super(odtEditor);
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param odtEditor
+	 * @param imageResizer
+	 */
+	public CellImageWriter(final ODTEditor odtEditor, final IImageResizer imageResizer) {
+		super(odtEditor, imageResizer);
+	}
+
+
+
+	/**
+	 * Constructor.
+	 *
+	 * @param odtEditor
+	 * @param imageResizer
+	 * @param imageCropper
+	 */
+	public CellImageWriter(final ODTEditor odtEditor, final IImageResizer imageResizer, final IImageCropper imageCropper) {
+		super(odtEditor, imageResizer, imageCropper);
+	}
+
+	/**
+	 * @see org.eclipse.papyrus.model2doc.odt.internal.util.ParagraphImageWriter#configure()
+	 *
+	 */
+	@Override
+	protected void configure() {
+		super.configure();
+		setGenerateCaption(false);
+		setEndParagraph(false);
+		setWrapImageInTextFrame(false);
+		setImageAnchor(TextContentAnchorType.AS_CHARACTER);
+	}
+
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ConstrainedImageResizer.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ConstrainedImageResizer.java
new file mode 100755
index 0000000..d0400d5
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ConstrainedImageResizer.java
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.awt.Size;
+import com.sun.star.lang.XMultiComponentFactory;
+import com.sun.star.text.XTextContent;
+import com.sun.star.text.XTextDocument;
+import com.sun.star.uno.XComponentContext;
+
+/**
+ * This resizer allows to fit an image to display it in a given space.
+ * The resize is done keeping the ratio width/height
+ */
+public class ConstrainedImageResizer implements IImageResizer {
+
+	/**
+	 * the max available width
+	 */
+	private final int maxWidth;
+
+	/**
+	 * the max available height
+	 */
+	private final int maxHeight;
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 * @param maxWidth
+	 * @param maxHeight
+	 */
+	public ConstrainedImageResizer(final int maxWidth, final int maxHeight) {
+		this.maxWidth = maxWidth;
+		this.maxHeight = maxHeight;
+	}
+
+	/**
+	 * @see org.eclipse.papyrus.model2doc.odt.internal.util.IImageResizer#resizeImage(com.sun.star.text.XTextContent, java.lang.String, com.sun.star.text.XTextDocument, com.sun.star.lang.XMultiComponentFactory, com.sun.star.uno.XComponentContext)
+	 *
+	 * @param graphicContent
+	 * @param imagePath
+	 * @param xTextDocument
+	 * @param xMultiComponentFactory
+	 * @param xComponentContext
+	 * @return
+	 */
+	@Override
+	public XTextContent resizeImage(final XTextContent graphicContent, final String imagePath, final XTextDocument xTextDocument, final XMultiComponentFactory xMultiComponentFactory, XComponentContext xComponentContext) {
+		Size realSizeImage = ImageUtil.getSize100mm(imagePath, xMultiComponentFactory, xComponentContext);
+
+		// code for maximize in landscape
+		if (this.maxHeight > 0 && this.maxWidth > 0 && realSizeImage.Width > 0 && realSizeImage.Height > 0) {
+			Size resizeImage = new Size(realSizeImage.Width, realSizeImage.Height);
+			Size writableSize = new Size(maxWidth, maxHeight);
+
+			float width = ((float) realSizeImage.Width) / ((float) writableSize.Width);
+			float height = ((float) realSizeImage.Height) / ((float) writableSize.Height);
+			if (height < width) {
+				resizeImage.Height = Math.round((resizeImage.Height) / width);
+				resizeImage.Width = Math.round((resizeImage.Width) / width);
+
+			}
+			if (width < height) {
+				resizeImage.Height = Math.round((resizeImage.Height) / height);
+				resizeImage.Width = Math.round((resizeImage.Width) / height);
+			}
+
+			PropertySetUtil.setProperty(graphicContent, SizeConstants.WIDTH, resizeImage.Width);
+			PropertySetUtil.setProperty(graphicContent, SizeConstants.HEIGHT, resizeImage.Height);
+
+			// TODO : seem not working...
+			PropertySetUtil.setProperty(graphicContent, "RelativeHeightRelation", "scale"); //$NON-NLS-1$ //$NON-NLS-2$
+			PropertySetUtil.setProperty(graphicContent, "RelativeWidthRelation", "100"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+		return graphicContent;
+	}
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/IImageCropper.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/IImageCropper.java
new file mode 100755
index 0000000..e65eb26
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/IImageCropper.java
@@ -0,0 +1,32 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.text.XTextContent;
+
+/**
+ * This interface provides a method to crop the inserted image
+ */
+public interface IImageCropper {
+
+	/**
+	 * This method allows to resize the xTextContent owning the image, editing its "GraphicCrop" property {@link XTextContentConstants#GRAPHIC_CROP}
+	 *
+	 * @param xTextContent
+	 *            the {@link XTextContent} containing the image
+	 */
+	public void crop(final XTextContent xTextContent);
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/IImageResizer.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/IImageResizer.java
new file mode 100755
index 0000000..ed52259
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/IImageResizer.java
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.lang.XMultiComponentFactory;
+import com.sun.star.text.XTextContent;
+import com.sun.star.text.XTextDocument;
+import com.sun.star.uno.XComponentContext;
+
+/**
+ * Common interface for image resizer
+ */
+public interface IImageResizer {
+
+	/**
+	 * This methods is used to resize inserted image. The edited properties are owned by the {@link XTextContent} and are
+	 * <ul>
+	 * <li>Width</li>
+	 * <li>Height</li>
+	 * <li>RelativeHeightRelation</li>
+	 * <li>RelativeWidthRelation</li>
+	 * </ul>
+	 *
+	 * @param graphicContent
+	 * @param imagePath
+	 * @param xTextDocument
+	 * @param xMultiComponentFactory
+	 * @param xComponentContext
+	 * @return
+	 */
+	public XTextContent resizeImage(XTextContent graphicContent, String imagePath, XTextDocument xTextDocument, XMultiComponentFactory xMultiComponentFactory, XComponentContext xComponentContext);
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ImageCropper.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ImageCropper.java
new file mode 100755
index 0000000..ecd23ff
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ImageCropper.java
@@ -0,0 +1,101 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import org.eclipse.papyrus.model2doc.odt.Activator;
+
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.text.GraphicCrop;
+import com.sun.star.text.XTextContent;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * The cropper must be called AFTER the image insertion in the document. If not the crop property is not found.
+ * TODO -> we can probably bypass this behavior, creating is ourself...
+ */
+public class ImageCropper implements IImageCropper {
+
+	private final int topCrop;
+
+	private final int bottomCrop;
+
+	private final int leftCrop;
+
+	private final int rightCrop;
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 * @param crop
+	 *            the crop value to apply on all sides of the image
+	 */
+	public ImageCropper(final int crop) {
+		this(crop, crop, crop, crop);
+	}
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 * @param topCrop
+	 *            the crop to apply on the top side of the image
+	 * @param bottomCrop
+	 *            the crop to apply on the bottom side of the image
+	 * @param leftCrop
+	 *            the crop to apply on the left side of the image
+	 * @param rightCrop
+	 *            the crop to apply on the right side of the image
+	 *
+	 */
+	public ImageCropper(final int topCrop, final int bottomCrop, final int leftCrop, final int rightCrop) {
+		this.topCrop = topCrop;
+		this.bottomCrop = bottomCrop;
+		this.leftCrop = leftCrop;
+		this.rightCrop = rightCrop;
+	}
+
+	/**
+	 * @see org.eclipse.papyrus.model2doc.odt.internal.util.IImageCropper#crop(com.sun.star.text.XTextContent)
+	 *
+	 * @param xTextContent
+	 */
+	@Override
+	public void crop(final XTextContent xTextContent) {
+		final XPropertySet propertySet = UnoRuntime.queryInterface(XPropertySet.class, xTextContent);
+		try {
+			GraphicCrop crops = (GraphicCrop) propertySet.getPropertyValue(XTextContentConstants.GRAPHIC_CROP);
+			crops.Top = this.topCrop;
+			crops.Bottom = this.bottomCrop;
+			crops.Left = this.leftCrop;
+			crops.Right = this.rightCrop;
+			propertySet.setPropertyValue(XTextContentConstants.GRAPHIC_CROP, crops);
+		} catch (UnknownPropertyException e) {
+			Activator.log.error(e);
+		} catch (WrappedTargetException e) {
+			Activator.log.error(e);
+		} catch (IllegalArgumentException e) {
+			Activator.log.error(e);
+		} catch (PropertyVetoException e) {
+			Activator.log.error(e);
+		}
+	}
+
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PageNumberUtils.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PageNumberUtils.java
new file mode 100755
index 0000000..cd26190
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PageNumberUtils.java
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import org.eclipse.papyrus.model2doc.odt.Activator;
+import org.eclipse.papyrus.model2doc.odt.internal.editor.ODTEditor;
+
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.text.XTextCursor;
+import com.sun.star.text.XTextField;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * This class contains useful methods to add the current page number and the total page number
+ * somewhere in the document
+ */
+public class PageNumberUtils {
+
+	/**
+	 * The string value to create a page number
+	 */
+	public static final String TEXTFIELD_PAGE_NUMBER = "com.sun.star.text.textfield.PageNumber"; //$NON-NLS-1$
+
+	/**
+	 * The string value to create a page count
+	 */
+	public static final String TEXTFIELD_PAGE_COUNT = "com.sun.star.text.textfield.PageCount"; //$NON-NLS-1$
+
+	/**
+	 * The name of the property used to define how must be done the numbering.
+	 * Values are givent by the enumeration {@link com.sun.star.style.NumberingType}
+	 */
+	public static final String NUMBERING_TYPE = "NumberingType"; //$NON-NLS-1$
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 */
+	private PageNumberUtils() {
+		// to prevent instanciation
+	}
+
+	/**
+	 *
+	 * @param xTextCursor
+	 *            the xTextCuror
+	 * @param odtEditor
+	 *            the odtEditor
+	 */
+	public static final void addPageNumberOnTotalPages(final XTextCursor xTextCursor, final ODTEditor odtEditor) {
+		addPageNumberOnTotalPages(xTextCursor, odtEditor, "page: "); //$NON-NLS-1$
+	}
+
+	/**
+	 *
+	 * @param xTextCursor
+	 *            the {@link XTextCursor} to use to set the page number properties
+	 * @param odtEditor
+	 *            the {@link ODTEditor}
+	 * @param pageFieldLabel
+	 *            the label used to insert the page's number The result will be : "pageFieldLabel currentPageNumber/totalPageNumber"
+	 */
+	public static final void addPageNumberOnTotalPages(final XTextCursor xTextCursor, final ODTEditor odtEditor, final String pageFieldLabel) {
+		XMultiServiceFactory xMultiServiceFactory = odtEditor.getXMultiServiceFactory();
+		try {
+			final Object textFieldPageNumber = xMultiServiceFactory.createInstance(TEXTFIELD_PAGE_NUMBER);
+			final XTextField f = UnoRuntime.queryInterface(XTextField.class, textFieldPageNumber);
+			XPropertySet textFieldSetExpressionPropertySet = UnoRuntime.queryInterface(XPropertySet.class, f);
+			textFieldSetExpressionPropertySet.setPropertyValue(NUMBERING_TYPE, com.sun.star.style.NumberingType.ARABIC);
+
+			if (pageFieldLabel != null) {
+				xTextCursor.getText().insertString(xTextCursor, pageFieldLabel, false);
+			}
+			xTextCursor.getText().insertTextContent(xTextCursor, f, false);
+
+			Object textFieldPageCount = xMultiServiceFactory.createInstance(TEXTFIELD_PAGE_COUNT);
+			XTextField pageCount = UnoRuntime.queryInterface(XTextField.class, textFieldPageCount);
+			XPropertySet pageCountExpressionPropertySet = UnoRuntime.queryInterface(XPropertySet.class, pageCount);
+			pageCountExpressionPropertySet.setPropertyValue(NUMBERING_TYPE, com.sun.star.style.NumberingType.ARABIC);
+			xTextCursor.getText().insertString(xTextCursor, "/", false); //$NON-NLS-1$
+			xTextCursor.getText().insertTextContent(xTextCursor, pageCount, false);
+		} catch (IllegalArgumentException | UnknownPropertyException | PropertyVetoException | WrappedTargetException e) {
+			Activator.log.error(e);
+		} catch (Exception e) {
+			Activator.log.error(e);
+		}
+	}
+
+
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PageUtil.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PageUtil.java
index 325cb1b..f400bd3 100755
--- a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PageUtil.java
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PageUtil.java
@@ -15,6 +15,7 @@
 package org.eclipse.papyrus.model2doc.odt.internal.util;
 
 import org.eclipse.papyrus.model2doc.odt.Activator;
+
 import com.sun.star.awt.Size;
 import com.sun.star.beans.UnknownPropertyException;
 import com.sun.star.beans.XPropertySet;
@@ -26,7 +27,7 @@
  *
  */
 public class PageUtil {
-	
+
 	/**
 	 * Constructor.
 	 *
@@ -37,7 +38,7 @@
 
 	/**
 	 * Get writable size.
-	 * 
+	 *
 	 * @param xTextDocument
 	 * @param familyStyleName
 	 * @param propertySetName
@@ -45,16 +46,16 @@
 	 */
 	public static Size getWritableSize(XTextDocument xTextDocument, String familyStyleName, String propertySetName) {
 		XPropertySet propertySet = StyleUtil.getStylePropertySet(xTextDocument, familyStyleName, propertySetName);
-		
+
 		if (propertySet != null) {
 			try {
-				int width = ((Integer)propertySet.getPropertyValue(SizeConstants.WIDTH)).intValue();
-				int height = ((Integer)propertySet.getPropertyValue(SizeConstants.HEIGHT)).intValue();
-				int leftMargin = ((Integer)propertySet.getPropertyValue(SizeConstants.LEFT_MARGIN)).intValue();
-			    int rightMargin = ((Integer)propertySet.getPropertyValue(SizeConstants.RIGHT_MARGIN)).intValue();
-			    int topMargin = ((Integer)propertySet.getPropertyValue(SizeConstants.TOPMARGIN)).intValue();
-			    int bottomMargin = ((Integer)propertySet.getPropertyValue(SizeConstants.BOTTOM_MARGIN)).intValue();
-			    
+				int width = ((Integer) propertySet.getPropertyValue(SizeConstants.WIDTH)).intValue();
+				int height = ((Integer) propertySet.getPropertyValue(SizeConstants.HEIGHT)).intValue();
+				int leftMargin = ((Integer) propertySet.getPropertyValue(SizeConstants.LEFT_MARGIN)).intValue();
+				int rightMargin = ((Integer) propertySet.getPropertyValue(SizeConstants.RIGHT_MARGIN)).intValue();
+				int topMargin = ((Integer) propertySet.getPropertyValue(SizeConstants.TOPMARGIN)).intValue();
+				int bottomMargin = ((Integer) propertySet.getPropertyValue(SizeConstants.BOTTOM_MARGIN)).intValue();
+
 				return new Size(width - (leftMargin + rightMargin), height - (topMargin + bottomMargin));
 			} catch (UnknownPropertyException | WrappedTargetException e) {
 				Activator.log.error(e);
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ParagraphImageWriter.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ParagraphImageWriter.java
new file mode 100755
index 0000000..926f30d
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/ParagraphImageWriter.java
@@ -0,0 +1,305 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.papyrus.model2doc.odt.Activator;
+import org.eclipse.papyrus.model2doc.odt.internal.editor.ODTEditor;
+import org.eclipse.papyrus.model2doc.odt.service.ODTFileIOService;
+import org.eclipse.papyrus.model2doc.odt.service.ODTFileIOServiceImpl;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameContainer;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.text.SizeType;
+import com.sun.star.text.TextContentAnchorType;
+import com.sun.star.text.WrapTextMode;
+import com.sun.star.text.XParagraphCursor;
+import com.sun.star.text.XTextContent;
+import com.sun.star.text.XTextCursor;
+import com.sun.star.text.XTextFrame;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * This Writer is configured to insert an Image in a Paragraph
+ */
+public class ParagraphImageWriter {
+
+	// TODO remove me
+	private static final ODTFileIOService odtFileIOService = new ODTFileIOServiceImpl();
+
+	/**
+	 *
+	 */
+	private ODTEditor odtEditor;
+
+	/**
+	 * if <code>true</code>, we will generate a caption under the image
+	 */
+	private boolean generateCaption;
+
+	/**
+	 * if <code>true</code>, we will end the paragraph (new line) at the end of the insertion
+	 */
+	private boolean endParagraph;
+
+	/**
+	 * The image resize to use
+	 */
+	private IImageResizer imageResizer;
+
+	/**
+	 * if <code>true</code>, the image will be inserted in a TextFrame, itself inserted in the final paragraph
+	 */
+	private boolean wrapImageInTextFrame;
+
+	/**
+	 * The kind of anchor to use to insert the textFrame (if we create one)
+	 */
+	private TextContentAnchorType textFrameAnchor;
+
+	/**
+	 * The kind of anchor to use to insert the image
+	 */
+	private TextContentAnchorType imageAnchor;
+
+	/**
+	 * The image cropper to use
+	 */
+	private IImageCropper imageCropper;
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 * @param odtEditor
+	 */
+	public ParagraphImageWriter(final ODTEditor odtEditor) {
+		this(odtEditor, null);
+	}
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 * @param odtEditor
+	 * @param imageResizer
+	 */
+	public ParagraphImageWriter(final ODTEditor odtEditor, final IImageResizer imageResizer) {
+		this(odtEditor, imageResizer, null);
+	}
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 * @param odtEditor
+	 * @param imageResizer
+	 * @param imageCropper
+	 */
+	public ParagraphImageWriter(final ODTEditor odtEditor, final IImageResizer imageResizer, final IImageCropper imageCropper) {
+		Assert.isNotNull(odtEditor);
+		this.odtEditor = odtEditor;
+		this.imageResizer = imageResizer != null ? imageResizer : new AdaptToPageImageResizer();
+		this.imageCropper = imageCropper != null ? imageCropper : new StubImageCropper();
+		configure();
+	}
+
+	/**
+	 * This method allows to apply default configuration for Parahraph to this IImageWriter
+	 */
+	protected void configure() {
+		this.endParagraph = true;
+		this.wrapImageInTextFrame = true;
+		this.generateCaption = true;
+		this.textFrameAnchor = TextContentAnchorType.AS_CHARACTER;
+		this.imageAnchor = TextContentAnchorType.AT_CHARACTER;
+	}
+
+	/**
+	 * @param textFrameAnchor
+	 *            the textFrameAnchor to set
+	 */
+	public final void setTextFrameAnchor(final TextContentAnchorType textFrameAnchor) {
+		this.textFrameAnchor = textFrameAnchor;
+	}
+
+	/**
+	 * @param imageAnchor
+	 *            the imageAnchor to set
+	 */
+	public final void setImageAnchor(final TextContentAnchorType imageAnchor) {
+		this.imageAnchor = imageAnchor;
+	}
+
+	/**
+	 * @param generateCaption
+	 *            the generateCaption to set
+	 */
+	public final void setGenerateCaption(final boolean generateCaption) {
+		this.generateCaption = generateCaption;
+	}
+
+	/**
+	 * @param endPAragraph
+	 *            if <code>true</code> we will add an empty line after the image insertion
+	 */
+	public final void setEndParagraph(final boolean endParagraph) {
+		this.endParagraph = endParagraph;
+	}
+
+	/**
+	 * @param imageResizer
+	 *            the imageResizer to set
+	 */
+	public final void setImageResizer(final IImageResizer imageResizer) {
+		this.imageResizer = imageResizer != null ? imageResizer : new AdaptToPageImageResizer();
+	}
+
+	/**
+	 * @param wrapImageInTextFrame
+	 *            if <code>true</code>, the image will be wrapped in a TextFrame before to be inserted in the document
+	 */
+	public final void setWrapImageInTextFrame(final boolean wrapImageInTextFrame) {
+		this.wrapImageInTextFrame = wrapImageInTextFrame;
+	}
+
+	/**
+	 *
+	 * @param imageCropper
+	 *            the image cropper to use during the image insertion
+	 */
+	public final void setImageCropper(final IImageCropper imageCropper) {
+		this.imageCropper = imageCropper != null ? imageCropper : new StubImageCropper();
+	}
+
+	/**
+	 *
+	 * @return
+	 *         the {@link XTextFrame} created to insert the image
+	 */
+	private XTextFrame createTextFrameForImage() {
+		XTextFrame textFrame = null;
+		XMultiServiceFactory xMultiServiceFactory = odtEditor.getXMultiServiceFactory();
+		try {
+
+			Object tmp = xMultiServiceFactory.createInstance("com.sun.star.text.TextFrame");//$NON-NLS-1$
+
+			textFrame = UnoRuntime.queryInterface(XTextFrame.class, tmp);
+			XPropertySet framePropertySet = UnoRuntime.queryInterface(XPropertySet.class, textFrame);
+			framePropertySet.setPropertyValue("SizeType", SizeType.VARIABLE); //$NON-NLS-1$
+			framePropertySet.setPropertyValue("AnchorType", this.textFrameAnchor); //$NON-NLS-1$
+			framePropertySet.setPropertyValue("ZOrder", 1);// not really sure //$NON-NLS-1$
+			framePropertySet.setPropertyValue("TextWrap", WrapTextMode.THROUGH); //$NON-NLS-1$
+
+			// remove the margin around the image
+			framePropertySet.setPropertyValue(BaseFramePropertiesConstants.LEFT_BORDER_DISTANCE, 0);
+			framePropertySet.setPropertyValue(BaseFramePropertiesConstants.RIGHT_BORDER_DISTANCE, 0);
+			framePropertySet.setPropertyValue(BaseFramePropertiesConstants.TOP_BORDER_DISTANCE, 0);
+			framePropertySet.setPropertyValue(BaseFramePropertiesConstants.BOTTOM_BORDER_DISTANCE, 0);
+		} catch (com.sun.star.uno.Exception e) {
+			Activator.log.error(e);
+		}
+		return textFrame;
+	}
+
+	/**
+	 *
+	 * @param xTextCursor
+	 *            the {@link XTextCursor}
+	 * @param imageFilePath
+	 *            the path of the image to insert
+	 * @param caption
+	 *            the caption
+	 */
+	public void writeImage(final XTextCursor xTextCursor, String imageFilePath, final String caption) {
+		if (false == imageFilePath.startsWith(odtFileIOService.getODTFilePrefix())) {
+			imageFilePath = odtFileIOService.getODTFilePrefix() + imageFilePath;
+		}
+
+		try {
+			XMultiServiceFactory xMultiServiceFactory = odtEditor.getXMultiServiceFactory();
+
+			// Creating the service GraphicObject
+			Object graphicObject = xMultiServiceFactory.createInstance("com.sun.star.text.TextGraphicObject"); //$NON-NLS-1$
+
+			// Creating TextContent for GraphicObject
+			XTextContent graphicContent = UnoRuntime.queryInterface(XTextContent.class, graphicObject);
+
+			// Creating bitmap container service
+			XNameContainer bitmapContainer = UnoRuntime.queryInterface(XNameContainer.class, xMultiServiceFactory.createInstance("com.sun.star.drawing.BitmapTable")); //$NON-NLS-1$
+
+			// Inserting image to the container
+			bitmapContainer.insertByName(imageFilePath, imageFilePath);
+
+			PropertySetUtil.setProperty(graphicContent, "AnchorType", this.imageAnchor); //$NON-NLS-1$
+			PropertySetUtil.setProperty(graphicContent, "GraphicURL", bitmapContainer.getByName(imageFilePath)); //$NON-NLS-1$
+
+			graphicContent = imageResizer.resizeImage(graphicContent, imageFilePath, odtEditor.getXTextDocument(), odtEditor.getXMultiComponentFactory(), odtEditor.getXComponentContext());
+
+
+			XTextCursor localCursor = xTextCursor;
+			if (this.wrapImageInTextFrame) {
+				final XTextFrame textFrame = createTextFrameForImage();
+				XPropertySet framePropertySet = UnoRuntime.queryInterface(XPropertySet.class, textFrame);
+				XPropertySet graphicPropSet = UnoRuntime.queryInterface(XPropertySet.class, graphicContent);
+				Object heightValue = graphicPropSet.getPropertyValue("Height"); //$NON-NLS-1$
+				Object widthValue = graphicPropSet.getPropertyValue("Width"); //$NON-NLS-1$
+
+				framePropertySet.setPropertyValue("Height", heightValue);// TODO don't work, and should be on the next level... //$NON-NLS-1$
+				framePropertySet.setPropertyValue("Width", widthValue); //$NON-NLS-1$
+				xTextCursor.getText().insertTextContent(xTextCursor, textFrame, false);
+				localCursor = textFrame.getText().createTextCursor();
+			}
+
+			XParagraphCursor paragraphCursor = UnoRuntime.queryInterface(XParagraphCursor.class, localCursor);
+			XPropertySet paraSet = UnoRuntime.queryInterface(XPropertySet.class, paragraphCursor);
+
+			paraSet.setPropertyValue("ParaStyleName", "Figure");// it works!!! in fact we can't push style which have not been declared and which don't exist by default //$NON-NLS-1$ //$NON-NLS-2$
+
+			localCursor.getText().insertTextContent(localCursor, graphicContent, false);
+			localCursor.gotoEnd(true);
+
+			this.imageCropper.crop(graphicContent);
+
+			if (this.generateCaption) {
+				addCaption(localCursor, caption);
+			}
+
+			if (this.endParagraph) {
+				WriteUtil.endParagraph(xTextCursor);
+			}
+		} catch (Exception e) {
+			Activator.log.error(e);
+		}
+	}
+
+	/**
+	 *
+	 * @param xTextCursor
+	 *            the xTextCursor
+	 * @param caption
+	 *            the caption to insert
+	 */
+	protected void addCaption(final XTextCursor xTextCursor, final String caption) {
+		if (!this.generateCaption) {
+			return;
+		}
+		CaptionUtils.writeFigureCaption(xTextCursor, caption, this.odtEditor);
+	}
+
+
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PropertySetUtil.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PropertySetUtil.java
index 30825f9..9b2423f 100755
--- a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PropertySetUtil.java
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/PropertySetUtil.java
@@ -62,7 +62,9 @@
 			try {
 				propertyValue = propertySet.getPropertyValue(propertyName);
 			} catch (Exception e) {
-				Activator.log.error("Could not get property " + propertyName, e); //$NON-NLS-1$
+				// we don't display the expection, because it spam the console when we are debugging
+				propertyValue = "Not available : exception generated"; //$NON-NLS-1$
+				// Activator.log.error("Could not get property " + propertyName, e); //$NON-NLS-1$
 			}
 		}
 		return propertyValue;
@@ -113,6 +115,21 @@
 
 	/**
 	 *
+	 * A method for debug purpose
+	 *
+	 * @param propertySet
+	 *            a property set
+	 * @param relativeObjectName
+	 *            the name of the object for which we want explore the property set
+	 */
+	public static final void displayPropertySet(final Object object, final String relativeObjectName) {
+		XPropertySet propertySet = UnoRuntime.queryInterface(XPropertySet.class, object);
+		displayPropertySet(propertySet, relativeObjectName);
+	}
+
+
+	/**
+	 *
 	 * @param source
 	 *            the source property to copy
 	 * @param target
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/StubImageCropper.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/StubImageCropper.java
new file mode 100755
index 0000000..db88950
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/StubImageCropper.java
@@ -0,0 +1,34 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.text.XTextContent;
+
+/**
+ * This image cropper does nothing
+ */
+public final class StubImageCropper implements IImageCropper {
+
+	/**
+	 * @see org.eclipse.papyrus.model2doc.odt.internal.util.IImageCropper#crop(com.sun.star.text.XTextContent)
+	 *
+	 * @param xTextContent
+	 */
+	@Override
+	public void crop(XTextContent xTextContent) {
+		// do nothing
+	}
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/StubImageResizer.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/StubImageResizer.java
new file mode 100755
index 0000000..f20582c
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/StubImageResizer.java
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.awt.Size;
+import com.sun.star.lang.XMultiComponentFactory;
+import com.sun.star.text.XTextContent;
+import com.sun.star.text.XTextDocument;
+import com.sun.star.uno.XComponentContext;
+
+/**
+ * This image resizer doesn't resize the image
+ */
+public class StubImageResizer implements IImageResizer {
+
+	/**
+	 * @see org.eclipse.papyrus.model2doc.odt.internal.util.IImageResizer#resizeImage(com.sun.star.text.XTextContent, java.lang.String, com.sun.star.text.XTextDocument, com.sun.star.lang.XMultiComponentFactory, com.sun.star.uno.XComponentContext)
+	 *
+	 * @param graphicContent
+	 * @param imagePath
+	 * @param xTextDocument
+	 * @param xMultiComponentFactory
+	 * @param xComponentContext
+	 * @return
+	 */
+	@Override
+	public XTextContent resizeImage(XTextContent graphicContent, String imagePath, XTextDocument xTextDocument, XMultiComponentFactory xMultiComponentFactory, XComponentContext xComponentContext) {
+		Size realSizeImage = ImageUtil.getSize100mm(imagePath, xMultiComponentFactory, xComponentContext);
+
+		PropertySetUtil.setProperty(graphicContent, SizeConstants.WIDTH, realSizeImage.Width);
+		PropertySetUtil.setProperty(graphicContent, SizeConstants.HEIGHT, realSizeImage.Height);
+
+		// TODO : seem not working...
+		PropertySetUtil.setProperty(graphicContent, "RelativeHeightRelation", "100"); //$NON-NLS-1$ //$NON-NLS-2$
+		PropertySetUtil.setProperty(graphicContent, "RelativeWidthRelation", "100"); //$NON-NLS-1$ //$NON-NLS-2$
+		return graphicContent;
+	}
+
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/WriteUtil.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/WriteUtil.java
index 632cf85..bb87720 100755
--- a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/WriteUtil.java
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/WriteUtil.java
@@ -21,7 +21,6 @@
 import java.util.List;
 
 import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.Assert;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.papyrus.model2doc.core.builtintypes.AbstractTable;
 import org.eclipse.papyrus.model2doc.core.builtintypes.Cell;
@@ -34,11 +33,8 @@
 import org.eclipse.papyrus.model2doc.odt.service.ODTFileIOService;
 import org.eclipse.papyrus.model2doc.odt.service.ODTFileIOServiceImpl;
 
-import com.sun.star.beans.Property;
 import com.sun.star.beans.PropertyValue;
 import com.sun.star.beans.XPropertySet;
-import com.sun.star.beans.XPropertySetInfo;
-import com.sun.star.container.XNameAccess;
 import com.sun.star.container.XNameContainer;
 import com.sun.star.document.XDocumentInsertable;
 import com.sun.star.io.IOException;
@@ -48,16 +44,13 @@
 import com.sun.star.text.SizeType;
 import com.sun.star.text.TextContentAnchorType;
 import com.sun.star.text.WrapTextMode;
-import com.sun.star.text.XDependentTextField;
 import com.sun.star.text.XParagraphCursor;
 import com.sun.star.text.XText;
 import com.sun.star.text.XTextContent;
 import com.sun.star.text.XTextCursor;
-import com.sun.star.text.XTextFieldsSupplier;
 import com.sun.star.text.XTextFrame;
 import com.sun.star.text.XTextTable;
 import com.sun.star.uno.UnoRuntime;
-import com.sun.star.util.NumberFormat;
 
 /**
  * Utility class for writing odt documents.
@@ -88,18 +81,41 @@
 	 * Add Paragraph.
 	 *
 	 * @param xTextCursor
+	 *            the {@link XTextCursor} to use to edit the document
 	 * @param text
+	 *            the text to write
 	 * @param processRichText
+	 *            if <code>true</code> the text represents RichText contents
 	 */
 	public static void addParagraph(XTextCursor xTextCursor, String text, boolean processRichText) {
+		addParagraph(xTextCursor, text, processRichText, true);
+	}
+
+
+	/**
+	 * Add Paragraph.
+	 *
+	 * @param xTextCursor
+	 *            the {@link XTextCursor} to use to edit the document
+	 * @param text
+	 *            the text to write
+	 * @param processRichText
+	 *            if <code>true</code> the text represents RichText contents
+	 * @param endParagraph
+	 *            if <code>true</code>, we will add a new line at the end of the paragraph
+	 */
+	public static void addParagraph(final XTextCursor xTextCursor, final String text, final boolean processRichText, final boolean endParagraph) {
 		if (processRichText) {
 			addParagraphWithRichText(xTextCursor, text);
 		} else {
 			addText(xTextCursor, text);
-			endParagraph(xTextCursor);
+			if (endParagraph) {
+				endParagraph(xTextCursor);
+			}
 		}
 	}
 
+
 	/**
 	 * Add control character to end of document.
 	 *
@@ -136,90 +152,8 @@
 	}
 
 	public static void addImageLink(String imageFilePath, String caption, XTextCursor xTextCursor, ODTEditor odtEditor) {
-		if (false == imageFilePath.startsWith(odtFileIOService.getODTFilePrefix())) {
-			imageFilePath = odtFileIOService.getODTFilePrefix() + imageFilePath;
-		}
-		try {
-			XMultiServiceFactory xMultiServiceFactory = odtEditor.getXMultiServiceFactory();
-
-			Object tmp = xMultiServiceFactory.createInstance("com.sun.star.text.TextFrame"); //$NON-NLS-1$
-			XTextFrame textFrame = UnoRuntime.queryInterface(XTextFrame.class, tmp);
-			XPropertySet framePropertySet = createXPropertySet(textFrame);
-			framePropertySet.setPropertyValue("SizeType", SizeType.VARIABLE); //$NON-NLS-1$
-			framePropertySet.setPropertyValue("AnchorType", TextContentAnchorType.AS_CHARACTER); //$NON-NLS-1$
-			framePropertySet.setPropertyValue("ZOrder", 1);// not really sure //$NON-NLS-1$
-			framePropertySet.setPropertyValue("TextWrap", WrapTextMode.THROUGH); //$NON-NLS-1$
-
-			// remove the margin around the image
-			framePropertySet.setPropertyValue(BaseFramePropertiesConstants.LEFT_BORDER_DISTANCE, 0);
-			framePropertySet.setPropertyValue(BaseFramePropertiesConstants.RIGHT_BORDER_DISTANCE, 0);
-			framePropertySet.setPropertyValue(BaseFramePropertiesConstants.TOP_BORDER_DISTANCE, 0);
-			framePropertySet.setPropertyValue(BaseFramePropertiesConstants.BOTTOM_BORDER_DISTANCE, 0);
-
-			// Creating the service GraphicObject
-			Object graphicObject = xMultiServiceFactory.createInstance("com.sun.star.text.TextGraphicObject"); //$NON-NLS-1$
-
-			// Creating TextContent for GraphicObject
-			XTextContent graphicContent = UnoRuntime.queryInterface(XTextContent.class, graphicObject);
-
-			// Creating bitmap container service
-			XNameContainer bitmapContainer = UnoRuntime.queryInterface(XNameContainer.class, xMultiServiceFactory.createInstance("com.sun.star.drawing.BitmapTable")); //$NON-NLS-1$
-
-			// Inserting image to the container
-			bitmapContainer.insertByName(imageFilePath, imageFilePath);
-
-			PropertySetUtil.setProperty(graphicContent, "AnchorType", TextContentAnchorType.AT_CHARACTER); //$NON-NLS-1$
-			PropertySetUtil.setProperty(graphicContent, "GraphicURL", bitmapContainer.getByName(imageFilePath)); //$NON-NLS-1$
-
-			graphicContent = ImageUtil.resizeImage(graphicContent, imageFilePath, odtEditor.getXTextDocument(), odtEditor.getXMultiComponentFactory(), odtEditor.getXComponentContext());
-
-			XPropertySet graphicPropSet = createXPropertySet(graphicContent);
-			Object heightValue = graphicPropSet.getPropertyValue("Height"); //$NON-NLS-1$
-			Object widthValue = graphicPropSet.getPropertyValue("Width"); //$NON-NLS-1$
-			XPropertySet textFrameSet = createXPropertySet(textFrame);
-			textFrameSet.setPropertyValue("Height", heightValue);// TODO don't work, and should be on the next level... //$NON-NLS-1$
-			textFrameSet.setPropertyValue("Width", widthValue); //$NON-NLS-1$
-
-			xTextCursor.getText().insertTextContent(xTextCursor, textFrame, false);
-			XTextCursor localCursor = textFrame.getText().createTextCursor();
-
-			XParagraphCursor paragraphCursor = UnoRuntime.queryInterface(XParagraphCursor.class, localCursor);
-			XPropertySet paraSet = createXPropertySet(paragraphCursor);
-			paraSet.setPropertyValue("ParaStyleName", "Figure");// it works!!! in fact we can't push style which have not been declared and which don't exist by default //$NON-NLS-1$ //$NON-NLS-2$
-			localCursor.getText().insertTextContent(localCursor, graphicContent, false);
-			localCursor.gotoEnd(true);
-
-
-			// managing the caption, we need a text field master
-			XTextFieldsSupplier supplier = UnoRuntime.queryInterface(XTextFieldsSupplier.class, odtEditor.getXTextDocument());
-			XNameAccess masters = supplier.getTextFieldMasters();
-			Object masterSetExpressionForFigure = masters.getByName("com.sun.star.text.fieldmaster.SetExpression.Figure"); //$NON-NLS-1$
-
-			// create a dependent SetExpression
-			Object textFieldSetExpression = xMultiServiceFactory.createInstance("com.sun.star.text.textfield.SetExpression"); //$NON-NLS-1$
-			XPropertySet textFieldSetExpressionPropertySet = UnoRuntime.queryInterface(XPropertySet.class, textFieldSetExpression);
-			textFieldSetExpressionPropertySet.setPropertyValue("NumberingType", com.sun.star.style.NumberingType.ARABIC); //$NON-NLS-1$
-			textFieldSetExpressionPropertySet.setPropertyValue("NumberFormat", NumberFormat.NUMBER); //$NON-NLS-1$
-			textFieldSetExpressionPropertySet.setPropertyValue("Content", "Figure + 1"); //$NON-NLS-1$ //$NON-NLS-2$
-			XDependentTextField xDependeantTextFIeld = UnoRuntime.queryInterface(XDependentTextField.class, textFieldSetExpression);
-
-			// attach the dependent SetExpression to its master
-			xDependeantTextFIeld.attachTextFieldMaster(UnoRuntime.queryInterface(XPropertySet.class, masterSetExpressionForFigure));
-
-			localCursor.getText().insertString(localCursor, "Figure ", false); //$NON-NLS-1$
-
-			// insert the SetExpression
-			localCursor.getText().insertTextContent(localCursor, xDependeantTextFIeld, true);
-
-
-			if (caption != null && !caption.isEmpty()) {
-				localCursor.getText().insertString(localCursor, ": " + caption, false); //$NON-NLS-1$
-			}
-
-			endParagraph(xTextCursor);
-		} catch (Exception e) {
-			Activator.log.error(e);
-		}
+		ParagraphImageWriter writer = new ParagraphImageWriter(odtEditor);
+		writer.writeImage(xTextCursor, imageFilePath, caption);
 	}
 
 	public static void addImageLink(ImageDescription image, String caption, XTextCursor xTextCursor, ODTEditor odtEditor) {
@@ -229,7 +163,7 @@
 			XMultiServiceFactory xMultiServiceFactory = odtEditor.getXMultiServiceFactory();
 
 			Object tmp = xMultiServiceFactory.createInstance("com.sun.star.text.TextFrame"); //$NON-NLS-1$
-			XTextFrame textFrame = UnoRuntime.queryInterface(XTextFrame.class, tmp);
+			final XTextFrame textFrame = UnoRuntime.queryInterface(XTextFrame.class, tmp);
 			XPropertySet framePropertySet = createXPropertySet(textFrame);
 			framePropertySet.setPropertyValue("SizeType", SizeType.VARIABLE); //$NON-NLS-1$
 			framePropertySet.setPropertyValue("AnchorType", TextContentAnchorType.AS_CHARACTER); //$NON-NLS-1$
@@ -319,24 +253,6 @@
 		return UnoRuntime.queryInterface(XPropertySet.class, object);
 	}
 
-	private static final void displayPropertySet(final XPropertySet propertySet, final String relativeObjectName) {
-		Assert.isNotNull(propertySet);
-		Assert.isNotNull(relativeObjectName);
-		System.out.println(NLS.bind("-----------------------properties of {0}--------------------", relativeObjectName)); //$NON-NLS-1$
-		XPropertySetInfo set12 = propertySet.getPropertySetInfo();
-		for (Property tmp : set12.getProperties()) {
-			System.out.println("prop Name " + tmp.Name); //$NON-NLS-1$
-			System.out.println("prop attr " + tmp.Attributes); //$NON-NLS-1$
-			System.out.println("prop type " + tmp.Type); //$NON-NLS-1$
-			System.out.println("\n"); //$NON-NLS-1$
-		}
-	}
-
-
-
-
-	// }
-
 	/**
 	 * End line.
 	 *
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XCellConstants.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XCellConstants.java
new file mode 100755
index 0000000..1a30c73
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XCellConstants.java
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.table.BorderLine;
+import com.sun.star.table.BorderLine2;
+import com.sun.star.table.XCell;
+
+/**
+ * Constants used to manipulate {@link XCell}
+ */
+public interface XCellConstants {
+
+	/**
+	 * The right border property name. The value will be a {@link BorderLine} (or a {@link BorderLine2})
+	 */
+	public static final String RIGHT_BORDER = "RightBorder"; //$NON-NLS-1$
+
+	/**
+	 * The left border property name. The value will be a {@link BorderLine} (or a {@link BorderLine2})
+	 */
+	public static final String LEFT_BORDER = "LeftBorder"; //$NON-NLS-1$
+
+	/**
+	 * The top border property name. The value will be a {@link BorderLine} (or a {@link BorderLine2})
+	 */
+	public static final String TOP_BORDER = "TopBorder"; //$NON-NLS-1$
+
+	/**
+	 * The bottom border property name. The value will be a {@link BorderLine} (or a {@link BorderLine2})
+	 */
+	public static final String BOTTOM_BORDER = "BottomBorder"; //$NON-NLS-1$
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XCellUtils.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XCellUtils.java
new file mode 100755
index 0000000..f7f71fd
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XCellUtils.java
@@ -0,0 +1,97 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.table.BorderLine2;
+import com.sun.star.table.BorderLineStyle;
+import com.sun.star.table.XCell;
+
+/**
+ * Utils methods to manipulate {@link XCell}
+ */
+public final class XCellUtils {
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 */
+	private XCellUtils() {
+		// to prevent instanciation
+	}
+
+	/**
+	 * This method allows to hide the top border
+	 *
+	 * @param cell
+	 *            the edited cell
+	 */
+	public static void hideTopCellBorder(final XCell cell) {
+		hideCellBorder(cell, XCellConstants.TOP_BORDER);
+	}
+
+	/**
+	 * This method allows to hide the bottom border
+	 *
+	 * @param cell
+	 *            the edited cell
+	 */
+	public static void hideBottomCellBorder(final XCell cell) {
+		hideCellBorder(cell, XCellConstants.BOTTOM_BORDER);
+	}
+
+	/**
+	 * This method allows to hide the left border
+	 *
+	 * @param cell
+	 *            the edited cell
+	 */
+	public static void hideLeftCellBorder(final XCell cell) {
+		hideCellBorder(cell, XCellConstants.LEFT_BORDER);
+	}
+
+	/**
+	 * This method allows to hide the right border
+	 *
+	 * @param cell
+	 *            the edited cell
+	 */
+	public static void hideRightCellBorder(final XCell cell) {
+		hideCellBorder(cell, XCellConstants.RIGHT_BORDER);
+	}
+
+	/**
+	 *
+	 * @param cell
+	 *            the edited cell
+	 * @param border
+	 *            the border's name to hide (the name of the border can be
+	 *            <ul>
+	 *            <li>{@link XCellConstants#RIGHT_BORDER}</li>
+	 *            <li>{@link XCellConstants#BOTTOM_BORDER}</li>
+	 *            <li>{@link XCellConstants#LEFT_BORDER}</li>
+	 *            <li>{@link XCellConstants#RIGHT_BORDER}</li>
+	 *            </ul>
+	 */
+	public static void hideCellBorder(final XCell cell, final String border) {
+		BorderLine2 borderLine = (BorderLine2) PropertySetUtil.getPropertyValue(cell, border);
+		borderLine.LineStyle = BorderLineStyle.NONE;
+		borderLine.LineWidth = 0;
+		borderLine.InnerLineWidth = 0;
+		borderLine.OuterLineWidth = 0;
+		PropertySetUtil.setProperty(cell, border, borderLine);
+	}
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextContentConstants.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextContentConstants.java
new file mode 100755
index 0000000..a840194
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextContentConstants.java
@@ -0,0 +1,30 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.text.GraphicCrop;
+import com.sun.star.text.XTextContent;
+
+/**
+ * Constants used for {@link XTextContent}
+ */
+public interface XTextContentConstants {
+
+	/**
+	 * The property name to edit the crop for inserted image. The value is a {@link GraphicCrop}
+	 */
+	public static final String GRAPHIC_CROP = "GraphicCrop"; // $NON-NLS-1$
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextTableConstants.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextTableConstants.java
new file mode 100755
index 0000000..6cb9efb
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextTableConstants.java
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import com.sun.star.table.TableBorder2;
+import com.sun.star.table.TableBorderDistances;
+import com.sun.star.text.TableColumnSeparator;
+import com.sun.star.text.XTextTable;
+
+/**
+ * This interface defines the constants used to edit {@link XTextTable}
+ */
+public interface XTextTableConstants {
+
+	/**
+	 * This string allows to create the LibreOffice TextTable (that we will adapt into {@link XTextTable}
+	 */
+	public static final String TEXT_TABLE = "com.sun.star.text.TextTable"; //$NON-NLS-1$
+
+	/**
+	 * This property allows to define the style of the table boder
+	 * The value is a {@link TableBorder2}
+	 */
+	public static final String TABLE_BORDER2 = "TableBorder2"; //$NON-NLS-1$
+
+	/**
+	 * This property allows to get all column separators of the tables. We use them to define the column width
+	 * The value is a an array of {@link TableColumnSeparator}
+	 */
+	public static final String TABLE_COLUMN_SEPARATOR = "TableColumnSeparators"; //$NON-NLS-1$
+
+	/**
+	 * This property allows to get the sum (size) of all columns width.
+	 * The value is a {@link Short}
+	 */
+	public static final String TABLE_COLUMN_RELATIVE_SUM = "TableColumnRelativeSum"; //$NON-NLS-1$
+
+	/**
+	 * This property allows to define the distance between the border and inserted contents.
+	 * The value of this property is {@link TableBorderDistances}
+	 */
+	public static final String TABLE_BORDER_DISTANCE = "TableBorderDistances"; //$NON-NLS-1$
+}
diff --git a/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextTableUtils.java b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextTableUtils.java
new file mode 100755
index 0000000..5ac477a
--- /dev/null
+++ b/plugins/odt/org.eclipse.papyrus.model2doc.odt/src/org/eclipse/papyrus/model2doc/odt/internal/util/XTextTableUtils.java
@@ -0,0 +1,228 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *	Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.model2doc.odt.internal.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.papyrus.model2doc.odt.Activator;
+
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.table.TableBorder2;
+import com.sun.star.table.TableBorderDistances;
+import com.sun.star.table.XCell;
+import com.sun.star.text.TableColumnSeparator;
+import com.sun.star.text.XTextTable;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * Utils methods to manipulate {@link XTextTable}
+ */
+public class XTextTableUtils {
+
+	/**
+	 *
+	 * Constructor.
+	 *
+	 */
+	private XTextTableUtils() {
+		// to prevent instanciation
+	}
+
+	/**
+	 *
+	 * @param textTable
+	 *            the edited textTable
+	 * @param columnsWitdhInUnit
+	 *            the list of the columns size in a user unit (typically centimeters).
+	 *            This unit is indicative and the final result will be approximatively the wanted result, due to the real width of the table in the page
+	 */
+	public static final void setColumnsWidthInUnit(final XTextTable textTable, final List<Double> columnsWitdhInUnit) {
+		double fullUnit = 0;
+		for (final Double current : columnsWitdhInUnit) {
+			fullUnit += current.doubleValue();
+		}
+		if (fullUnit != 0) {
+			final List<Double> percentage = new ArrayList<>(columnsWitdhInUnit.size());
+			for (int i = 0; i < columnsWitdhInUnit.size(); i++) {
+				percentage.add(Double.valueOf(columnsWitdhInUnit.get(i).doubleValue() / fullUnit));
+			}
+			setColumnsWidth(textTable, percentage);
+		} else {
+			Activator.log.warn("The columns width has not been set, because you don't give us values > 0"); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 *
+	 * @param table
+	 * @param columnsSize
+	 *
+	 * @see https://wiki.openoffice.org/wiki/API/Samples/Java/Writer/TextTable
+	 */
+	public static final void setColumnsWidth(final XTextTable textTable, final List<Double> columnsInPercentage) {
+		try {
+			XPropertySet xPS = UnoRuntime.queryInterface(XPropertySet.class, textTable);
+			Object xObj = xPS.getPropertyValue(XTextTableConstants.TABLE_COLUMN_SEPARATOR);
+
+			short tableWidthRelative = (short) PropertySetUtil.getPropertyValue(textTable, XTextTableConstants.TABLE_COLUMN_RELATIVE_SUM);
+
+			TableColumnSeparator[] colSep1 = UnoRuntime.queryInterface(TableColumnSeparator[].class, xObj);
+			Assert.isTrue(columnsInPercentage.size() == colSep1.length + 1, NLS.bind("There are {0} column's separators for {1} width to set.", colSep1.length, columnsInPercentage.size())); //$NON-NLS-1$
+			double consumedWidth = 0;
+			for (int j = 0; j < colSep1.length; j++) {
+				double result = columnsInPercentage.get(j) * tableWidthRelative;
+				consumedWidth += result;
+				colSep1[j].Position = (short) Math.ceil(consumedWidth);
+			}
+			xPS.setPropertyValue(XTextTableConstants.TABLE_COLUMN_SEPARATOR, colSep1);
+		} catch (IllegalArgumentException | UnknownPropertyException | WrappedTargetException | PropertyVetoException e) {
+			Activator.log.error(e);
+		}
+	}
+
+	/**
+	 *
+	 * @param xTextTable
+	 *            the table for which we want to define the witdh of the border
+	 */
+	public static final void setTableBorderWidth(final XTextTable xTextTable, final int borderWidth) {
+		TableBorder2 tb2 = (TableBorder2) PropertySetUtil.getPropertyValue(xTextTable, XTextTableConstants.TABLE_BORDER2);
+		tb2.LeftLine.LineWidth = borderWidth;
+		tb2.RightLine.LineWidth = borderWidth;
+		tb2.TopLine.LineWidth = borderWidth;
+		tb2.BottomLine.LineWidth = borderWidth;
+
+		PropertySetUtil.setProperty(xTextTable, XTextTableConstants.TABLE_BORDER2, tb2);
+	}
+
+	/**
+	 * This method allows to define the distance between the table's border and the table contents
+	 *
+	 * @param xTextTable
+	 *            the edited {@link XTextTable}
+	 * @param distance
+	 *            the distance between the table's border and the table contents
+	 */
+	public static final void setTableMarginDistance(final XTextTable xTextTable, final short distance) {
+		final TableBorder2 tb2 = (TableBorder2) PropertySetUtil.getPropertyValue(xTextTable, XTextTableConstants.TABLE_BORDER2);
+
+		tb2.LeftLine.LineDistance = distance;
+		tb2.RightLine.LineDistance = distance;
+		tb2.TopLine.LineDistance = distance;
+		tb2.BottomLine.LineDistance = distance;
+
+		PropertySetUtil.setProperty(xTextTable, XTextTableConstants.TABLE_BORDER2, tb2);
+	}
+
+	/**
+	 * This methods allows to remove the margin between the border and the table contents
+	 *
+	 * @param xTextTable
+	 *            the edited {@link XTextTable}
+	 *
+	 */
+	public static final void removeTableMargin(final XTextTable xTextTable) {
+		setTableMarginDistance(xTextTable, (short) 0);
+	}
+
+	/**
+	 *
+	 * @param xTextTable
+	 *            the edited {@link XTextTable}
+	 * @param border
+	 *            the border's name to hide (the name of the border can be
+	 *            <ul>
+	 *            <li>{@link XCellConstants#RIGHT_BORDER}</li>
+	 *            <li>{@link XCellConstants#BOTTOM_BORDER}</li>
+	 *            <li>{@link XCellConstants#LEFT_BORDER}</li>
+	 *            <li>{@link XCellConstants#RIGHT_BORDER}</li>
+	 */
+	public static final void hideTableBorder(final XTextTable xTextTable, final String border) {
+		final List<String> cellNames = Arrays.asList(xTextTable.getCellNames());
+		final Iterator<String> libreOfficeCellNamesIter = cellNames.iterator();
+		while (libreOfficeCellNamesIter.hasNext()) {
+			XCell cell = xTextTable.getCellByName(libreOfficeCellNamesIter.next());
+			XCellUtils.hideCellBorder(cell, border);
+		}
+	}
+
+	/**
+	 * This method hides the top border of the table
+	 *
+	 * @param xTextTable
+	 *            the edited {@link XTextTable}
+	 */
+	public static final void hideTableTopBorder(final XTextTable xTextTable) {
+		hideTableBorder(xTextTable, XCellConstants.TOP_BORDER);
+	}
+
+	/**
+	 * This method hides the bottom border of the table
+	 *
+	 * @param xTextTable
+	 *            the edited {@link XTextTable}
+	 */
+	public static final void hideTableBottomBorder(final XTextTable xTextTable) {
+		hideTableBorder(xTextTable, XCellConstants.BOTTOM_BORDER);
+	}
+
+	/**
+	 * This method hides the left border of the table
+	 *
+	 * @param xTextTable
+	 *            the edited {@link XTextTable}
+	 */
+	public static final void hideTableLeftBorder(final XTextTable xTextTable) {
+		hideTableBorder(xTextTable, XCellConstants.LEFT_BORDER);
+	}
+
+	/**
+	 * This method hides the right border of the table
+	 *
+	 * @param xTextTable
+	 *            the edited {@link XTextTable}
+	 */
+	public static final void hideTableRightBorder(final XTextTable xTextTable) {
+		hideTableBorder(xTextTable, XCellConstants.RIGHT_BORDER);
+	}
+
+	/**
+	 * This method allows to remove the distance between the border and the table contents
+	 *
+	 * @param xTextTable
+	 *            the edited XTextTable
+	 */
+	public static final void removeTableBorderDistance(final XTextTable xTextTable) {
+		TableBorderDistances d = (TableBorderDistances) PropertySetUtil.getPropertyValue(xTextTable, XTextTableConstants.TABLE_BORDER_DISTANCE);
+		d.BottomDistance = 0;
+		d.LeftDistance = 0;
+		d.RightDistance = 0;
+		d.TopDistance = 0;
+
+		PropertySetUtil.setProperty(xTextTable, XTextTableConstants.TABLE_BORDER_DISTANCE, d);
+
+	}
+
+}