Issue 92831 - Serializing the selected text in Writer and preserving its formatting (in Java)
Summary: Serializing the selected text in Writer and preserving its formatting (in Java)
Status: UNCONFIRMED
Alias: None
Product: Writer
Classification: Application
Component: code (show other issues)
Version: OOo 2.4.1
Hardware: PC Windows XP
: P3 Trivial (vote)
Target Milestone: ---
Assignee: AOO issues mailing list
QA Contact:
URL:
Keywords: needhelp
Depends on:
Blocks:
 
Reported: 2008-08-16 15:25 UTC by anestikas
Modified: 2017-05-20 10:44 UTC (History)
2 users (show)

See Also:
Issue Type: DEFECT
Latest Confirmation in: ---
Developer Difficulty: ---


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description anestikas 2008-08-16 15:25:12 UTC
I was trying to create a serializable class that would hold the XTransferable
data of the current selection in a Writer document. I need this in order to be
able to store the selection to the database (preserving the formatting) and
later retrieve it and insert it in some other document.

I created the following class:

package test;

import java.io.Serializable;

import com.sun.star.datatransfer.DataFlavor;
import com.sun.star.datatransfer.UnsupportedFlavorException;
import com.sun.star.datatransfer.XTransferable;
import com.sun.star.io.IOException;
import com.sun.star.uno.Type;

public class FormattedText implements Serializable, XTransferable {

	private static final long serialVersionUID = 1L;
	
	public static final DataFlavor textFlavor = new
DataFlavor("text/plain;charset=utf-16", "Text", new Type(String.class));
	public static final DataFlavor htmlFlavor = new DataFlavor("text/html", "HTML
(HyperText Markup Language)", new Type(byte[].class));
	public static final DataFlavor richtextFlavor = new DataFlavor("text/richtext",
"Rich Text Format", new Type(byte[].class));
	public static final DataFlavor starObjectFlavor = new
DataFlavor("application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star
Object Descriptor (XML)\"", "Star Object Descriptor (XML)", new Type(byte[].class));
	public static final DataFlavor starEmbededSourceFlavor = new
DataFlavor("application/x-openoffice-embed-source-xml;windows_formatname=\"Star
Embed Source (XML)\"", "Star Embed Source (XML)", new Type(byte[].class));
	public static final DataFlavor starLinkFlavor = new
DataFlavor("application/x-openoffice-link;windows_formatname=\"Link\"", "Link",
 new Type(byte[].class));
	
	private static final DataFlavor[] SUPPORTED_DATA_FLAVORS = {
		starEmbededSourceFlavor, starObjectFlavor, richtextFlavor, htmlFlavor,
textFlavor, starLinkFlavor
	};
	
	private String text;
	private byte[] html;
	private byte[] richtext;
	private byte[] starObject;
	private byte[] starEmbededSource;
	private byte[] starLink;

	public FormattedText(XTransferable transferable) throws IOException {
		try {
			if(transferable.isDataFlavorSupported(textFlavor)) {
				text = (String)transferable.getTransferData(textFlavor);
			}
			if(transferable.isDataFlavorSupported(htmlFlavor)) {
				html = (byte[])transferable.getTransferData(htmlFlavor);;
			}
			if(transferable.isDataFlavorSupported(richtextFlavor)) {
				richtext = (byte[])transferable.getTransferData(richtextFlavor);
			}
			if(transferable.isDataFlavorSupported(starObjectFlavor)) {
				starObject = (byte[])transferable.getTransferData(starObjectFlavor);
			}
			if(transferable.isDataFlavorSupported(starEmbededSourceFlavor)) {
				starEmbededSource =
(byte[])transferable.getTransferData(starEmbededSourceFlavor);
			}
			if(transferable.isDataFlavorSupported(starLinkFlavor)) {
				starLink = (byte[])transferable.getTransferData(starLinkFlavor);
			}
		} catch (UnsupportedFlavorException e) {
			e.printStackTrace();
		}
	}
	public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException,
IOException {
		if(df.MimeType.toString().equals(textFlavor.MimeType.toString())) {
			return text;
		} else if(df.MimeType.toString().equals(htmlFlavor.MimeType.toString())) {
			return html;
		} else if(df.MimeType.toString().equals(richtextFlavor.MimeType.toString())) {
			return richtext;
		} else if(df.MimeType.toString().equals(starObjectFlavor.MimeType.toString())) {
			return starObject;
		} else
if(df.MimeType.toString().equals(starEmbededSourceFlavor.MimeType.toString())) {
			return starEmbededSource;
		} else if(df.MimeType.toString().equals(starLinkFlavor.MimeType.toString())) {
			return starLink;
		}
		throw new UnsupportedFlavorException(df.HumanPresentableName);
	}

	public DataFlavor[] getTransferDataFlavors() {
		return SUPPORTED_DATA_FLAVORS;
	}

	public boolean isDataFlavorSupported(DataFlavor df) {
		for(int i = 0; i < SUPPORTED_DATA_FLAVORS.length; i++) {
			if(SUPPORTED_DATA_FLAVORS[i].equals(df)) return true;
		}
		return false;
	}

}


I use this class like this:

        XTextViewCursorSupplier svc =
(XTextViewCursorSupplier)UnoRuntime.queryInterface(XTextViewCursorSupplier.class,
xTextDocument.getCurrentController());
        
        XTransferableSupplier sts = (XTransferableSupplier)
UnoRuntime.queryInterface( XTransferableSupplier.class, svc);

		XTransferable transferable = sts.getTransferable();

		FormattedText ft = new FormattedText(transferable);

		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		ObjectOutputStream out = new ObjectOutputStream(bout);
		out.writeObject(ft);
		byte[] result = bout.toByteArray();

Later, I'm recreating the FormattedText object like this and insert (paste) it
in the document like this:

		ByteArrayInputStream bin = new ByteArrayInputStream(result);
		ObjectInputStream in = new ObjectInputStream(bin);

		transferable = (XTransferable)in.readObject();

		XTextViewCursorSupplier vcs =
(XTextViewCursorSupplier)UnoRuntime.queryInterface(XTextViewCursorSupplier.class,
xTextDocument.getCurrentController());
		
        XTransferableSupplier ts = (XTransferableSupplier)
UnoRuntime.queryInterface(XTransferableSupplier.class, vcs);
        
        ts.insertTransferable(transferable); 

The problem is that some information is lost in the process and the following
bug occurs:

When i paste the serialized (and unformatted) text in a location where some
sentence (or a paragraph) is formatted (e.g. it is red), the formatting of the
rest of the sentence becomes the same as the formatting of the serialized text
(unformatted).

Here is an example:

Imagine that the following numbers are some formatted (ones) and unformatted
(zeros) letters. The brackets show the current selection.

State 1. This is our document

00000000000000000000000000000000000000
0001111111111111111111111111
111111111111111111111111111
00000000000000000000000000000000

State 2. I mark some text and copy (serialize) it with the code above

000[0000000000]0000000000000000000000000
0001111111111111111111111111
111111111111111111111111111
00000000000000000000000000000000

State 3. I place the cursor in the middle of some formatted text

00000000000000000000000000000000000000
00011111111[]11111111111111111
111111111111111111111111111
00000000000000000000000000000000

State 4. I paste the serialized text with the code above

00000000000000000000000000000000000000
00011111111[0000000000]11111111111111111
111111111111111111111111111
00000000000000000000000000000000

State 5. This is the bug. The formatted text which should not be affected, loses
its formatting.

00000000000000000000000000000000000000
00011111111[0000000000]00000000000000000
000000000000000000000000000
00000000000000000000000000000000

I have done some hacking and i believe that this is a bug in the implementation
because some data in the original transferable is not accessible through the UNO
interface.

The bug does not occur when the transferable is not serialized, but it is pasted
as it is in its original state.

Also, i have found that the 'oid' of the IQueryInterface that the XTransferable
implements has something to do with the bug. I had the FormattedText class
implement the IQueryInterface and override the getOid() method, and i had the
oid serialized too. Sometimes, when the oid of the serialized text was the same
with the oid of the document where i pasted the text, the bug did not occur.
However,  this behavior is not acceptable because the oid will always be
different when the text is serialized and stored in the database for a long time.

It is VERY important to me to find a solution fast. I will gladly assist you
anyway i can. Please don't hesitate to ask me anything.

If there is some other way of serializing an XTransferable, please let me know.

Thank you
Comment 1 anestikas 2008-08-25 09:54:56 UTC
The same problem occurs in versions older than 3.0 so I'm changing the version
attribute to 2.4.1 which is the current stable version.

If it helps, I can send you an eclipse project so that you can easily test. Is
there anyone interested in resolving this issue?

If not, then how can I resolve the issue myself? Where should I look?

It is really important for me to fix this problem so I am willing to help as
much as I can.

Thanks
Comment 2 michael.ruess 2008-08-25 16:09:16 UTC
MRU->JSC: is this something for you?
Comment 3 anestikas 2008-08-25 18:36:50 UTC
I have found a workaround that works in my case only. When I paste the text, I
have some text selected so that the pasted text overwrites the selected text
(this is a requirement in my case). The workaround is to clear the formatting of
the selected text before pasting. This way, the rest of the sentence does not
lose its formatting.

The problem remains when there is no text selected when pasting.

I think that this bug report should be converted to a feature request,
requesting that the XTransferable interface becomes Serializable so that it can
be stored in some database.

Thanks
Comment 4 jsc 2008-08-26 05:12:36 UTC
jsc -> os can you take a look on it and comment
Comment 5 jsc 2008-08-26 05:13:01 UTC
.
Comment 6 Marcus 2017-05-20 10:44:31 UTC
Reset the assignee to the default "issues@openoffice.apache.org".