Bug Hunting Session
Bug 42073 - Writer input fields are not populated using the Java UNO API
Summary: Writer input fields are not populated using the Java UNO API
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Writer (show other bugs)
Version:
(earliest affected)
3.4.3 release
Hardware: x86 (IA32) Windows (All)
: high critical
Assignee: Michael Stahl (CIB)
URL:
Whiteboard: target:3.6.0 target:3.5.2 target:3.4.6
Keywords: regression
Depends on:
Blocks:
 
Reported: 2011-10-20 12:02 UTC by John Manko
Modified: 2012-03-07 03:38 UTC (History)
6 users (show)

See Also:
Crash report or crash signature:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description John Manko 2011-10-20 12:02:33 UTC
I've been using OpenOffice and LibreOffice to batch process documents using the Java UNO interface.  Upon updating to LibreOffice 3.4.3, LibreOffice is ignoring the Java UNO calls to populate the input fields with data.  Running the same code with LibreOffice 3.3 works flawlessly.  Below is sample code, which I've stepped through in debug mode, and everything is running correctly.  The fields are found, but calling xPropertySet.setPropertyValue("Content", newValue) leaves the document unchanged. Updating table cells with 3.4.3, however, is working as expected.  Has something changed with the API that is not documented?

CODE:
String file = "/path/to/SomeFile.ott";

/* Initialize some variables */
// xRemoteServiceManager initialized previously
Object desktop = xRemoteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xRemoteContext);
XComponentLoader xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktop);

// createPropertyValueArray and createPropertyValue are simply utility methods.
PropertyValue[] xComponentLoadProps = createPropertyValueArray(
                createPropertyValue("AsTemplate", new Any(Type.BOOLEAN, Boolean.TRUE)),
                createPropertyValue("Hidden", new Any(Type.BOOLEAN, Boolean.TRUE)));

XComponent xTemplateComponent = (XComponent) xComponentLoader.loadComponentFromURL("file:///" + file, "_blank", 0, properties);
XTextDocument comp = (XTextDocument) UnoRuntime.queryInterface(XTextDocument.class, xTemplateComponent);
XBookmarksSupplier bookmarksSupplier = (XBookmarksSupplier) UnoRuntime.queryInterface(XBookmarksSupplier.class, comp);
XNameAccess namedBookmarks = bookmarksSupplier.getBookmarks();
XTextTablesSupplier xTablesSupplier = (XTextTablesSupplier) UnoRuntime.queryInterface(XTextTablesSupplier.class, comp);
XNameAccess namedTables = xTablesSupplier.getTextTables();
XDrawPageSupplier xSuppPage = (XDrawPageSupplier) UnoRuntime.queryInterface(XDrawPageSupplier.class, comp);
XDrawPage xDrawPage = xSuppPage.getDrawPage();


/* Create a HashMap to reference all the text fields */
XTextFieldsSupplier supplier = (XTextFieldsSupplier) UnoRuntime.queryInterface(XTextFieldsSupplier.class, comp);
XEnumerationAccess enumAccess = supplier.getTextFields();
XEnumeration xEnum = enumAccess.createEnumeration();

Map textFields = new HashMap();

while (xEnum.hasMoreElements()) {
    Object o = xEnum.nextElement();
    XTextField text = (XTextField) UnoRuntime.queryInterface(XTextField.class, o);
    XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, text);
    XServiceInfo xServiceInfo = (XServiceInfo) UnoRuntime.queryInterface(XServiceInfo.class, text);
    if (xServiceInfo.supportsService("com.sun.star.text.TextField.Input")) {
        textFields.put(((String) xPropertySet.getPropertyValue("Hint")), text);
    }
}


/* Set some input fields */
setInputField("FirstName", "John");
setInputField("LastName", "Doe");
setInputField("Phone", "123-456-7890");


/* defined methods */
public void setInputField(String name, String value) {
        String newValue = (value == null) ? "" : value.replaceAll("\\u0000", "");
        newValue = (newValue.contains("\r\n")) ? newValue.replace("\r", "") : newValue.replace("\r", "\n");
        Object o = textFields.get(name);
        XTextField text = (XTextField) UnoRuntime.queryInterface(XTextField.class, o);
        XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, text);
	xPropertySet.setPropertyValue("Content", newValue);
}
Comment 1 John Manko 2012-01-04 08:17:45 UTC
I just tested with version 3.4.4, and the same problem exists.  This is a show stopper.
Comment 2 Petr Mladek 2012-01-05 01:30:56 UTC
I add some experts into CC. Does it trigger any bell?
Comment 3 Michael Stahl (CIB) 2012-01-18 11:07:11 UTC
cannot reproduce a regression here, what am i missing?

the following runs successfully against LO 3.3.4, LO 3.4.3, LO master, OOo 3.3, OOo 3.2.1, OOo 3.0.1:

    @Test public void test_fdo42073() throws Exception
    {
        XMultiServiceFactory xDocFactory = (XMultiServiceFactory)
            UnoRuntime.queryInterface(XMultiServiceFactory.class, m_xDoc);
        Object xField =
            xDocFactory.createInstance("com.sun.star.text.TextField.Input");
        XText xBodyText = m_xDoc.getText();
        XTextCursor xCursor = xBodyText.createTextCursor();
        XTextContent xContent = (XTextContent)
            UnoRuntime.queryInterface(XTextContent.class, xField);
        xBodyText.insertTextContent(xCursor, xContent, true);
        XPropertySet xPropSet = (XPropertySet)
            UnoRuntime.queryInterface(XPropertySet.class, xField);
        String content = "this is not surprising";
        xPropSet.setPropertyValue("Content", content);
        Object readContent = xPropSet.getPropertyValue("Content");
        assertEquals(content, readContent);
    }
Comment 4 John Manko 2012-01-18 13:07:02 UTC
I tried your code (and mine), and it does work (sort of).  When running the code (with the document visible), the input fields do not show the newly set text.  ie, they are collapsed.  In order to view the text, I have to enable "Field Names" from the View menu, then disable them again.  Only after doing that does the text show.  More so, if I export the document to a file (through code) prior to the enable/disable workaround, the data in the fields does not get saved.  Only after performing the enable/disable function does the export include the field data.  Obviously is wrong/bad, because I can't sit here for automated system.  The latest test is running LO 3.4.4 on Ubuntu Linux 11.10, but the same thing occurs on my Windows installation.

@Test
    public void test_fdo42073() throws Exception {
        initializeOpenOffice();

        PropertyValue[] loadProps = createPropertyValueArray(
                createPropertyValue("AsTemplate", new Any(Type.BOOLEAN, Boolean.TRUE)),
                createPropertyValue("Hidden", new Any(Type.BOOLEAN, Boolean.FALSE)));

        XComponent component = componentImport("/home/jmanko/VirtualBox VMs/PCID_042_LO_3.4.3/shared/templates/0198.OTT", loadProps);
        XTextDocument document = (XTextDocument) UnoRuntime.queryInterface(XTextDocument.class, component);

        XMultiServiceFactory xDocFactory = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, document);
        Object xField = xDocFactory.createInstance("com.sun.star.text.TextField.Input");
        XText xBodyText = document.getText();
        XTextCursor xCursor = xBodyText.createTextCursor();
        XTextContent xContent = (XTextContent) UnoRuntime.queryInterface(XTextContent.class, xField);
        xBodyText.insertTextContent(xCursor, xContent, true);
        XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xField);
        String content = "this is not surprising";
        xPropSet.setPropertyValue("Content", content);


        XTextFieldsSupplier supplier = (XTextFieldsSupplier) UnoRuntime.queryInterface(XTextFieldsSupplier.class, document);
        XEnumerationAccess enumAccess = supplier.getTextFields();
        XEnumeration xEnum = enumAccess.createEnumeration();
        Map textFields = new HashMap();
        while (xEnum.hasMoreElements()) {
            Object o = xEnum.nextElement();
            XTextField text = (XTextField) UnoRuntime.queryInterface(XTextField.class, o);
            XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, text);
            XServiceInfo xServiceInfo = (XServiceInfo) UnoRuntime.queryInterface(XServiceInfo.class, text);
            if (xServiceInfo.supportsService("com.sun.star.text.TextField.Input")) {
                textFields.put(((String) xPropertySet.getPropertyValue("Hint")), text);
            }
        }
        Object o = textFields.get("POLICY_NO");
        XTextField text = text = (XTextField) UnoRuntime.queryInterface(XTextField.class, o);
        XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, text);
        xPropertySet.setPropertyValue("Content", "123456789");

        PropertyValue[] saveProps = createPropertyValueArray(
                createPropertyValue("FilterName", new Any(Type.STRING, DocumentType.WRITER_OPENDOCUMENT_TEXT)),
                createPropertyValue("CompressionMode", new Any(Type.STRING, "1")),
                createPropertyValue("Pages", new Any(Type.STRING, "All")),
                createPropertyValue("Overwrite", new Any(Type.BOOLEAN, Boolean.TRUE)));
        
        /** BREAKPOINT PRIOR TO SAVING TO VIEW THE DOCUMENT. **/
        componentExport(component, saveProps, "/home/jmanko/VirtualBox VMs/PCID_042_LO_3.4.3/shared/templates/0198_AFTER.ODT");
        closeComponent(component);

    }
Comment 5 John Manko 2012-02-01 11:42:03 UTC
How did my last test code work?
Comment 6 John Manko 2012-02-02 13:57:18 UTC
I just tried this with versions 3.4.5 and 3.5.0 RC1, and neither worked correctly.  So, this is an ongoing bug that was introduced with 3.4.3 and is unresolved.  Let me know if you have any suggestions on how to provide more details for this bug.
Comment 7 Michael Stahl (CIB) 2012-03-02 13:19:38 UTC
ok, the problem here is that following a setPropertyValue,
the getPresentation method will return stale values.

this is a regression in OOo 3.4, from CWS sw34bf01
(8485708f3001fca132c3353c464fe7187ef62bed),
related to fix for issue 112425, issue 85766.

what confused me is that setPropertyValue also does not
cause the text in the document view to be refreshed,
which is a pre-existing condition (see comment #3).

bug 39694 is a different regression from the same change.
Comment 8 John Manko 2012-03-02 13:26:38 UTC
Great find, Michael!  If there any way this can be targeted for 3.5.1?
Comment 9 Not Assigned 2012-03-02 15:16:45 UTC
Michael Stahl committed a patch related to this issue.
It has been pushed to "master":

http://cgit.freedesktop.org/libreoffice/core/commit/?id=e3dfae0741aae8581cd3fc713ba1b4459bb22d88

fdo#42073: sw: expand all text fields when setting properties:
Comment 10 Michael Stahl (CIB) 2012-03-02 15:18:54 UTC
fixed on master

probably too late for 3.5.1 now, with rc2 scheduled for Monday
Comment 11 Korrawit Pruegsanusak 2012-03-06 08:43:37 UTC
Now in -3-5 branch => will be in 3.5.2 => set target accordingly

http://cgit.freedesktop.org/libreoffice/core/commit/?h=libreoffice-3-5&id=be999f1bc692a122e36add37f23312edad8f81d2
Comment 12 Michael Stahl (CIB) 2012-03-07 03:38:27 UTC
added unit test for this:
http://cgit.freedesktop.org/libreoffice/core/commit/?id=870e5a8e8251967b513b4255231ee9665b085431

because of the bugzilla outage it wasn't picked up automatically, so:

fixed in libreoffice-3-4 as well:

http://cgit.freedesktop.org/libreoffice/writer/commit/?h=libreoffice-3-4&id=ea137eef21554dfc7b8420b1f40e7a26eaaa5210