sfx2: move DocumentProperties from Java to CppUnittest

Change-Id: I007ff75fb63a20304726a22fa3d949eb3616069e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173820
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Xisco Fauli 2024-09-23 16:32:16 +02:00
parent 5ceff2c65c
commit 5aea0dd59c
4 changed files with 406 additions and 553 deletions

View file

@ -31,11 +31,9 @@ $(eval $(call gb_JunitTest_use_jars,sfx2_complex,\
))
$(eval $(call gb_JunitTest_add_sourcefiles,sfx2_complex,\
sfx2/qa/complex/sfx2/DocumentProperties \
sfx2/qa/complex/sfx2/GlobalEventBroadcaster \
sfx2/qa/complex/sfx2/UndoManager \
sfx2/qa/complex/sfx2/DocumentEvents \
sfx2/qa/complex/sfx2/tools/TestDocument \
sfx2/qa/complex/sfx2/tools/WriterHelper \
sfx2/qa/complex/sfx2/undo/CalcDocumentTest \
sfx2/qa/complex/sfx2/undo/ChartDocumentTest \
@ -48,7 +46,6 @@ $(eval $(call gb_JunitTest_add_sourcefiles,sfx2_complex,\
))
$(eval $(call gb_JunitTest_add_classes,sfx2_complex,\
complex.sfx2.DocumentProperties \
complex.sfx2.DocumentEvents \
complex.sfx2.UndoManager \
))

View file

@ -1,516 +0,0 @@
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
package complex.sfx2;
import complex.sfx2.tools.TestDocument;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.lang.XInitialization;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lang.Locale;
import com.sun.star.lang.EventObject;
import com.sun.star.util.Date;
import com.sun.star.util.DateTime;
import com.sun.star.util.Time;
import com.sun.star.util.Duration;
import com.sun.star.util.XModifyListener;
import com.sun.star.util.XModifyBroadcaster;
import com.sun.star.beans.XPropertyContainer;
import com.sun.star.beans.XPropertySet;
import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.NamedValue;
import com.sun.star.beans.PropertyAttribute;
import com.sun.star.beans.UnknownPropertyException;
import com.sun.star.beans.IllegalTypeException;
import com.sun.star.document.XDocumentProperties;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openoffice.test.OfficeConnection;
import static org.junit.Assert.*;
/**
* Test case for the service com.sun.star.document.DocumentProperties.
* Currently, this service is implemented in
* sfx2/source/doc/SfxDocumentMetaData.cxx.
*
*/
public class DocumentProperties
{
@After public void cleanup() {
// nothing to do
}
// for testing modifications
private class Listener implements XModifyListener {
private boolean m_Called;
Listener() {
m_Called = false;
}
private boolean reset() {
boolean oldCalled = m_Called;
m_Called = false;
return oldCalled;
}
public void modified(EventObject e) {
m_Called = true;
}
public void disposing(EventObject e) {
}
}
@Test public void check() throws Exception
{
XMultiServiceFactory xMSF = getMSF();
assertNotNull("could not create MultiServiceFactory.", xMSF);
XPropertySet xPropertySet = UnoRuntime.queryInterface(XPropertySet.class, xMSF);
Object defaultCtx = xPropertySet.getPropertyValue("DefaultContext");
XComponentContext xContext = UnoRuntime.queryInterface(XComponentContext.class, defaultCtx);
assertNotNull("could not get component context.", xContext);
// TODO: Path to temp
String temp = util.utils.getOfficeTemp/*Dir*/(xMSF);
System.out.println("tempdir: " + temp);
PropertyValue[] noArgs = { };
PropertyValue mimetype = new PropertyValue();
mimetype.Name = "MediaType";
mimetype.Value = "application/vnd.oasis.opendocument.text";
PropertyValue[] mimeArgs = { mimetype };
PropertyValue cfile = new PropertyValue();
cfile.Name = "URL";
cfile.Value = temp + "EMPTY.odt";
PropertyValue[] mimeEmptyArgs = { mimetype, cfile };
System.out.println("Creating service DocumentProperties...");
Object oDP =
xMSF.createInstance("com.sun.star.document.DocumentProperties");
XDocumentProperties xDP = UnoRuntime.queryInterface(XDocumentProperties.class, oDP);
System.out.println("...done");
System.out.println("Checking initialize ...");
XDocumentProperties xDP2 = UnoRuntime.queryInterface(XDocumentProperties.class, xMSF.createInstance("com.sun.star.document.DocumentProperties"));
XInitialization xInit = UnoRuntime.queryInterface(XInitialization.class, xDP2);
xInit.initialize(new Object[] { });
System.out.println("...done");
System.out.println("Checking storing default-initialized meta data ...");
xDP2.storeToMedium("", mimeEmptyArgs);
System.out.println("...done");
System.out.println("Checking loading default-initialized meta data ...");
xDP2.loadFromMedium("", mimeEmptyArgs);
assertEquals("Author", "", xDP2.getAuthor());
System.out.println("...done");
System.out.println("Checking loading from test document...");
String file = TestDocument.getUrl("TEST.odt");
xDP.loadFromMedium(file, noArgs);
/* XInputStream xStream =
new StreamSimulator("./testdocuments/TEST.odt", true, param);
Object oSF =
xMSF.createInstance("com.sun.star.embed.StorageFactory");
XSingleServiceFactory xSF = (XSingleServiceFactory)
UnoRuntime.queryInterface(XSingleServiceFactory.class, oSF);
Object oStor = xSF.createInstanceWithArguments(
new Object[] { xStream });
XStorage xStor = (XStorage) UnoRuntime.queryInterface(
XStorage.class, oStor);
xDP.loadFromStorage(xStor);*/
System.out.println("...done");
System.out.println("Checking meta-data import...");
assertEquals("Author", "Karl-Heinz Mustermann", xDP.getAuthor());
assertEquals(
"Generator",
"StarOffice/8$Solaris_x86 OpenOffice.org_project/680m232$Build-9227",
xDP.getGenerator());
assertEquals("CreationDate", 2007, xDP.getCreationDate().Year);
assertEquals("Title", "Urgent Memo", xDP.getTitle());
assertEquals("Subject", "Wichtige Mitteilung", xDP.getSubject());
assertEquals(
"Description",
"Modern internal company memorandum in full-blocked style",
xDP.getDescription());
assertEquals(
"ModifiedBy", "Karl-Heinz Mustermann", xDP.getModifiedBy());
assertEquals(
"ModificationDate", 10, xDP.getModificationDate().Month);
assertEquals(
"PrintedBy", "Karl-Heinz Mustermann", xDP.getPrintedBy());
assertEquals("PrintDate", 29, xDP.getPrintDate().Day);
assertEquals("TemplateName", "Modern Memo", xDP.getTemplateName());
assertTrue("TemplateURL",
xDP.getTemplateURL().endsWith("memmodern.ott"));
assertEquals("TemplateDate", 17, xDP.getTemplateDate().Hours);
assertTrue(
"AutoloadURL", xDP.getAutoloadURL().endsWith("/TEST.odt"));
assertEquals("AutoloadSecs", 0, xDP.getAutoloadSecs());
assertEquals("DefaultTarget", "_blank", xDP.getDefaultTarget());
assertEquals("EditingCycles", 3, xDP.getEditingCycles());
assertEquals("EditingDuration", 320, xDP.getEditingDuration());
String[] kws = xDP.getKeywords();
assertTrue("Keywords", fromArray(kws).containsAll(
fromArray(new Object[] { "Asien", "Memo", "Reis" })));
NamedValue[] ds = xDP.getDocumentStatistics();
assertTrue("DocumentStatistics:WordCount", containsNV(ds,
new NamedValue("WordCount", Integer.valueOf(23))));
assertTrue("DocumentStatistics:PageCount", containsNV(ds,
new NamedValue("PageCount", Integer.valueOf(1))));
XPropertyContainer udpc = xDP.getUserDefinedProperties();
XPropertySet udps = UnoRuntime.queryInterface( XPropertySet.class, udpc );
assertEquals(
"UserDefined 1", "Dies ist ein wichtiger Hinweis",
udps.getPropertyValue("Hinweis"));
assertEquals(
"UserDefined 2", "Kann Spuren von N\u00FCssen enthalten",
udps.getPropertyValue("Warnung"));
System.out.println("...done");
System.out.println("Checking meta-data updates...");
String str;
DateTime dt = new DateTime();
Locale l = new Locale();
int i;
str = "me";
xDP.setAuthor(str);
assertEquals("setAuthor", str, xDP.getAuthor());
str = "the computa";
xDP.setGenerator(str);
assertEquals("setGenerator", str, xDP.getGenerator());
dt.Year = 2038;
dt.Month = 1;
dt.Day = 1;
xDP.setCreationDate(dt);
assertEquals(
"setCreationDate", dt.Year, xDP.getCreationDate().Year);
str = "El t'itulo";
xDP.setTitle(str);
assertEquals("setTitle", str, xDP.getTitle());
str = "Ein verkommenes Subjekt";
xDP.setSubject(str);
assertEquals("setSubject", str, xDP.getSubject());
str = "Este descripci'on no es importante";
xDP.setDescription(str);
assertEquals("setDescription", str, xDP.getDescription());
l.Language = "en";
l.Country = "GB";
xDP.setLanguage(l);
Locale l2 = xDP.getLanguage();
assertEquals("setLanguage Lang", l.Language, l2.Language);
assertEquals("setLanguage Cty", l.Country, l2.Country);
str = "myself";
xDP.setModifiedBy(str);
assertEquals("setModifiedBy", str, xDP.getModifiedBy());
dt.Year = 2042;
xDP.setModificationDate(dt);
assertEquals(
"setModificationDate", dt.Year, xDP.getModificationDate().Year);
str = "i did not do it";
xDP.setPrintedBy(str);
assertEquals("setPrintedBy", str, xDP.getPrintedBy());
dt.Year = 2024;
xDP.setPrintDate(dt);
assertEquals("setPrintDate", dt.Year, xDP.getPrintDate().Year);
str = "blah";
xDP.setTemplateName(str);
assertEquals("setTemplateName", str, xDP.getTemplateName());
str = "gopher://some-hole-in-the-ground/";
xDP.setTemplateURL(str);
assertEquals("setTemplateURL", str, xDP.getTemplateURL());
dt.Year = 2043;
xDP.setTemplateDate(dt);
assertEquals(
"setTemplateDate", dt.Year, xDP.getTemplateDate().Year);
str = "http://nowhere/";
xDP.setAutoloadURL(str);
assertEquals("setAutoloadURL", str, xDP.getAutoloadURL());
i = 3661; // this might not work (due to conversion via double...)
xDP.setAutoloadSecs(i);
assertEquals("setAutoloadSecs", i, xDP.getAutoloadSecs());
str = "_blank";
xDP.setDefaultTarget(str);
assertEquals("setDefaultTarget", str, xDP.getDefaultTarget());
i = 42;
xDP.setEditingCycles((short) i);
assertEquals("setEditingCycles", i, xDP.getEditingCycles());
i = 84;
xDP.setEditingDuration(i);
assertEquals("setEditingDuration", i, xDP.getEditingDuration());
str = "";
String[] kws2 = new String[] {
"keywordly", "keywordlike", "keywordalicious" };
xDP.setKeywords(kws2);
kws = xDP.getKeywords();
assertTrue("setKeywords", fromArray(kws).containsAll(fromArray(kws2)));
NamedValue[] ds2 = new NamedValue[] {
new NamedValue("SyllableCount", Integer.valueOf(9)),
new NamedValue("FrameCount", Integer.valueOf(2)),
new NamedValue("SentenceCount", Integer.valueOf(7)) };
xDP.setDocumentStatistics(ds2);
ds = xDP.getDocumentStatistics();
assertTrue("setDocumentStatistics:SyllableCount", containsNV(ds,
new NamedValue("SyllableCount", Integer.valueOf(9))));
assertTrue("setDocumentStatistics:FrameCount", containsNV(ds,
new NamedValue("FrameCount", Integer.valueOf(2))));
assertTrue("setDocumentStatistics:SentenceCount", containsNV(ds,
new NamedValue("SentenceCount", Integer.valueOf(7))));
System.out.println("...done");
System.out.println("Checking user-defined meta-data updates...");
// actually, this tests the PropertyBag service
// but maybe the DocumentProperties service will be implemented
// differently some day...
boolean b = true;
double d = 3.1415;
// note that Time is only supported for backward compatibility!
Time t = new Time();
t.Hours = 1;
t.Minutes = 16;
Date date = new Date();
date.Year = 2071;
date.Month = 2;
date.Day = 3;
dt.Year = 2065;
Duration dur = new Duration();
dur.Negative = true;
dur.Years = 1001;
dur.Months = 999;
dur.Days = 888;
dur.Hours = 777;
dur.Minutes = 666;
dur.Seconds = 555;
dur.NanoSeconds = 444444444;
udpc.addProperty("Frobnicate", PropertyAttribute.REMOVABLE, b);
udpc.addProperty("FrobDuration", PropertyAttribute.REMOVABLE, dur);
udpc.addProperty("FrobDuration2", PropertyAttribute.REMOVABLE, t);
udpc.addProperty("FrobEndDate", PropertyAttribute.REMOVABLE, date);
udpc.addProperty("FrobStartTime", PropertyAttribute.REMOVABLE, dt);
udpc.addProperty("Pi", PropertyAttribute.REMOVABLE, Double.valueOf(d));
udpc.addProperty("Foo", PropertyAttribute.REMOVABLE, "bar");
udpc.addProperty("Removed", PropertyAttribute.REMOVABLE, "bar");
// #i94175#: empty property name is valid ODF 1.1
udpc.addProperty("", PropertyAttribute.REMOVABLE, "eeeeek");
try {
udpc.removeProperty("Info 1");
udpc.removeProperty("Removed");
} catch (UnknownPropertyException e) {
fail("removeProperty failed");
}
try {
udpc.addProperty("Forbidden", PropertyAttribute.REMOVABLE,
new String[] { "foo", "bar" });
fail("inserting value of non-supported type did not fail");
} catch (IllegalTypeException e) {
// ignore
}
assertEquals(
"UserDefined bool", b, udps.getPropertyValue("Frobnicate"));
assertTrue("UserDefined duration", eqDuration(dur, (Duration)
udps.getPropertyValue("FrobDuration")));
assertTrue("UserDefined time", eqTime(t, (Time)
udps.getPropertyValue("FrobDuration2")));
assertTrue("UserDefined date", eqDate(date, (Date)
udps.getPropertyValue("FrobEndDate")));
assertTrue("UserDefined datetime", eqDateTime(dt, (DateTime)
udps.getPropertyValue("FrobStartTime")));
assertEquals("UserDefined float", d, udps.getPropertyValue("Pi"));
assertEquals(
"UserDefined string", "bar", udps.getPropertyValue("Foo"));
assertEquals(
"UserDefined empty name", "eeeeek", udps.getPropertyValue(""));
try {
udps.getPropertyValue("Removed");
fail("UserDefined remove didn't");
} catch (UnknownPropertyException e) {
// ok
}
System.out.println("...done");
System.out.println("Checking storing meta-data to file...");
xDP.storeToMedium(temp + "TEST.odt", mimeArgs);
System.out.println("...done");
System.out.println("Checking loading meta-data from stored file...");
xDP.loadFromMedium(temp + "TEST.odt", noArgs);
System.out.println("...done");
System.out.println("Checking user-defined meta-data from stored file...");
udpc = xDP.getUserDefinedProperties();
udps = UnoRuntime.queryInterface( XPropertySet.class, udpc );
assertEquals(
"UserDefined bool", b, udps.getPropertyValue("Frobnicate"));
assertTrue("UserDefined duration", eqDuration(dur, (Duration)
udps.getPropertyValue("FrobDuration")));
// this is now a Duration!
Duration t_dur = new Duration(false, (short)0, (short)0, (short)0,
t.Hours, t.Minutes, t.Seconds,
t.NanoSeconds);
assertTrue("UserDefined time", eqDuration(t_dur, (Duration)
udps.getPropertyValue("FrobDuration2")));
assertTrue("UserDefined date", eqDate(date, (Date)
udps.getPropertyValue("FrobEndDate")));
assertTrue("UserDefined datetime", eqDateTime(dt, (DateTime)
udps.getPropertyValue("FrobStartTime")));
assertEquals("UserDefined float", d, udps.getPropertyValue("Pi"));
assertEquals(
"UserDefined string", "bar", udps.getPropertyValue("Foo"));
try {
udps.getPropertyValue("Removed");
fail("UserDefined remove didn't");
} catch (UnknownPropertyException e) {
// ok
}
System.out.println("...done");
System.out.println("Checking notification listener interface...");
Listener listener = new Listener();
XModifyBroadcaster xMB = UnoRuntime.queryInterface( XModifyBroadcaster.class, xDP );
xMB.addModifyListener(listener);
xDP.setAuthor("not me");
assertTrue("Listener Author", listener.reset());
udpc.addProperty("Listener", PropertyAttribute.REMOVABLE, "foo");
assertTrue("Listener UserDefined Add", listener.reset());
udps.setPropertyValue("Listener", "bar");
assertTrue("Listener UserDefined Set", listener.reset());
udpc.removeProperty("Listener");
assertTrue("Listener UserDefined Remove", listener.reset());
xMB.removeModifyListener(listener);
udpc.addProperty("Listener2", PropertyAttribute.REMOVABLE, "foo");
assertTrue("Removed Listener UserDefined Add", !listener.reset());
System.out.println("...done");
}
// grrr...
boolean eqDateTime(DateTime a, DateTime b) {
return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day
&& a.Hours == b.Hours && a.Minutes == b.Minutes
&& a.Seconds == b.Seconds
&& a.NanoSeconds == b.NanoSeconds;
}
boolean eqDate(Date a, Date b) {
return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day;
}
boolean eqTime(Time a, Time b) {
return a.Hours == b.Hours && a.Minutes == b.Minutes
&& a.Seconds == b.Seconds
&& a.NanoSeconds == b.NanoSeconds;
}
boolean eqDuration(Duration a, Duration b) {
return a.Years == b.Years && a.Months == b.Months && a.Days == b.Days
&& a.Hours == b.Hours && a.Minutes == b.Minutes
&& a.Seconds == b.Seconds
&& a.NanoSeconds == b.NanoSeconds
&& a.Negative == b.Negative;
}
java.util.Collection<Object> fromArray(Object[] os) {
java.util.Collection<Object> ret = new java.util.HashSet<Object>();
for (int i = 0; i < os.length; ++i) {
ret.add(os[i]);
}
return ret;
}
// bah, structs do not have proper equals(), and uno.Type is not comparable
public static boolean containsNV (NamedValue[] nvs, NamedValue nv) {
for (int i = 0; i < nvs.length; ++i) {
if (nvs[i].Name.equals(nv.Name) && nvs[i].Value.equals(nv.Value)) {
return true;
}
}
return false;
}
private XMultiServiceFactory getMSF()
{
final XMultiServiceFactory xMSF1 = UnoRuntime.queryInterface( XMultiServiceFactory.class, connection.getComponentContext().getServiceManager() );
return xMSF1;
}
// setup and close connections
@BeforeClass public static void setUpConnection() throws Exception {
System.out.println( "------------------------------------------------------------" );
System.out.println( "starting class: " + DocumentProperties.class.getName() );
System.out.println( "------------------------------------------------------------" );
connection.setUp();
}
@AfterClass public static void tearDownConnection()
throws InterruptedException, com.sun.star.uno.Exception
{
System.out.println( "------------------------------------------------------------" );
System.out.println( "finishing class: " + DocumentProperties.class.getName() );
System.out.println( "------------------------------------------------------------" );
connection.tearDown();
}
private static final OfficeConnection connection = new OfficeConnection();
}

View file

@ -1,34 +0,0 @@
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
package complex.sfx2.tools;
import java.io.File;
import org.openoffice.test.OfficeFileUrl;
import org.openoffice.test.Argument;
public final class TestDocument {
public static String getUrl(String name) {
return OfficeFileUrl.getAbsolute(new File(Argument.get("tdoc"), name));
}
public static String getPath(String name) {
return new File(Argument.get("tdoc"), name).toString();
}
private TestDocument() {}
}

View file

@ -16,6 +16,9 @@
#include <memory>
#include <com/sun/star/beans/Pair.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/IllegalTypeException.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/beans/PropertyState.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/document/DocumentProperties.hpp>
@ -24,6 +27,13 @@
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/util/Duration.hpp>
#include <com/sun/star/util/Time.hpp>
#include <com/sun/star/util/XModifyListener.hpp>
#include <com/sun/star/util/XModifyBroadcaster.hpp>
#include <test/unoapixml_test.hxx>
@ -59,6 +69,28 @@ public:
}
};
class Listener : public ::cppu::WeakImplHelper<css::util::XModifyListener>
{
public:
Listener()
: bCalled(false)
{
}
bool reset()
{
bool bOld = bCalled;
bCalled = false;
return bOld;
}
private:
bool bCalled;
virtual void SAL_CALL disposing(const lang::EventObject&) noexcept override {}
virtual void SAL_CALL modified(const lang::EventObject&) noexcept override { bCalled = true; }
};
CPPUNIT_TEST_FIXTURE(MiscTest, testODFCustomMetadata)
{
uno::Reference<document::XDocumentProperties> const xProps(
@ -81,6 +113,380 @@ CPPUNIT_TEST_FIXTURE(MiscTest, testODFCustomMetadata)
assertXPathContent(pXmlDoc, "/office:document-meta/office:meta/foo:bar/foo:baz"_ostr, u"bar"_ustr);
}
/**
* Test case for the service com.sun.star.document.DocumentProperties.
* Currently, this service is implemented in
* sfx2/source/doc/SfxDocumentMetaData.cxx.
*
*/
CPPUNIT_TEST_FIXTURE(MiscTest, testDocumentProperties)
{
uno::Reference<document::XDocumentProperties> const xProps(
::com::sun::star::document::DocumentProperties::create(m_xContext));
OUString const url(
m_directories.getURLFromSrc(u"/sfx2/qa/complex/sfx2/testdocuments/TEST.odt"));
xProps->loadFromMedium(url, uno::Sequence<beans::PropertyValue>());
CPPUNIT_ASSERT_EQUAL(u"Karl-Heinz Mustermann"_ustr, xProps->getAuthor());
CPPUNIT_ASSERT_EQUAL(u"StarOffice/8$Solaris_x86 OpenOffice.org_project/680m232$Build-9227"_ustr,
xProps->getGenerator());
CPPUNIT_ASSERT_EQUAL(sal_Int16(2007), xProps->getCreationDate().Year);
CPPUNIT_ASSERT_EQUAL(u"Urgent Memo"_ustr, xProps->getTitle());
CPPUNIT_ASSERT_EQUAL(u"Wichtige Mitteilung"_ustr, xProps->getSubject());
CPPUNIT_ASSERT_EQUAL(u"Modern internal company memorandum in full-blocked style"_ustr,
xProps->getDescription());
CPPUNIT_ASSERT_EQUAL(u"Karl-Heinz Mustermann"_ustr, xProps->getModifiedBy());
CPPUNIT_ASSERT_EQUAL(sal_uInt16(10), xProps->getModificationDate().Month);
CPPUNIT_ASSERT_EQUAL(u"Karl-Heinz Mustermann"_ustr, xProps->getPrintedBy());
CPPUNIT_ASSERT_EQUAL(sal_uInt16(29), xProps->getPrintDate().Day);
CPPUNIT_ASSERT_EQUAL(u"Modern Memo"_ustr, xProps->getTemplateName());
CPPUNIT_ASSERT(xProps->getTemplateURL().endsWith("memmodern.ott"));
CPPUNIT_ASSERT_EQUAL(sal_uInt16(17), xProps->getTemplateDate().Hours);
CPPUNIT_ASSERT(xProps->getAutoloadURL().endsWith("/TEST.odt"));
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xProps->getAutoloadSecs());
CPPUNIT_ASSERT_EQUAL(u"_blank"_ustr, xProps->getDefaultTarget());
CPPUNIT_ASSERT_EQUAL(sal_Int16(3), xProps->getEditingCycles());
CPPUNIT_ASSERT_EQUAL(sal_Int32(320), xProps->getEditingDuration());
uno::Sequence<OUString> aKeywords(xProps->getKeywords());
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aKeywords.getLength());
CPPUNIT_ASSERT_EQUAL(u"Memo"_ustr, aKeywords[0]);
CPPUNIT_ASSERT_EQUAL(u"Asien"_ustr, aKeywords[1]);
CPPUNIT_ASSERT_EQUAL(u"Reis"_ustr, aKeywords[2]);
uno::Sequence<beans::NamedValue> aDocStats = xProps->getDocumentStatistics();
auto it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats),
[](const css::beans::NamedValue& val) {
return val.Name == "WordCount" && val.Value.get<sal_uInt32>() == 23;
});
CPPUNIT_ASSERT(it != std::cend(aDocStats));
it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats),
[](const css::beans::NamedValue& val) {
return val.Name == "PageCount" && val.Value.get<sal_uInt32>() == 1;
});
CPPUNIT_ASSERT(it != std::cend(aDocStats));
uno::Reference<beans::XPropertyContainer> xUDP = xProps->getUserDefinedProperties();
uno::Reference<beans::XPropertySet> xPropertySet(xUDP, uno::UNO_QUERY);
uno::Any aAny = xPropertySet->getPropertyValue(u"Hinweis"_ustr);
CPPUNIT_ASSERT_EQUAL(u"Dies ist ein wichtiger Hinweis"_ustr, aAny.get<OUString>());
aAny = xPropertySet->getPropertyValue(u"Warnung"_ustr);
CPPUNIT_ASSERT_EQUAL(u"Kann Spuren von N\u00FCssen enthalten"_ustr, aAny.get<OUString>());
xProps->setAuthor(u"me"_ustr);
CPPUNIT_ASSERT_EQUAL(u"me"_ustr, xProps->getAuthor());
xProps->setGenerator(u"the computa"_ustr);
CPPUNIT_ASSERT_EQUAL(u"the computa"_ustr, xProps->getGenerator());
css::util::DateTime aDateTime;
aDateTime.Day = 1;
aDateTime.Month = 1;
aDateTime.Year = 2038;
xProps->setCreationDate(aDateTime);
CPPUNIT_ASSERT_EQUAL(sal_Int16(2038), xProps->getCreationDate().Year);
xProps->setTitle(u"El t'itulo"_ustr);
CPPUNIT_ASSERT_EQUAL(u"El t'itulo"_ustr, xProps->getTitle());
xProps->setSubject(u"Ein verkommenes Subjekt"_ustr);
CPPUNIT_ASSERT_EQUAL(u"Ein verkommenes Subjekt"_ustr, xProps->getSubject());
xProps->setDescription(u"Este descripci'on no es importante"_ustr);
CPPUNIT_ASSERT_EQUAL(u"Este descripci'on no es importante"_ustr, xProps->getDescription());
lang::Locale aLang;
aLang.Language = u"en"_ustr;
aLang.Country = u"GB"_ustr;
xProps->setLanguage(aLang);
CPPUNIT_ASSERT_EQUAL(aLang.Language, xProps->getLanguage().Language);
CPPUNIT_ASSERT_EQUAL(aLang.Country, xProps->getLanguage().Country);
xProps->setModifiedBy(u"myself"_ustr);
CPPUNIT_ASSERT_EQUAL(u"myself"_ustr, xProps->getModifiedBy());
aDateTime.Year = 2042;
xProps->setModificationDate(aDateTime);
CPPUNIT_ASSERT_EQUAL(sal_Int16(2042), xProps->getModificationDate().Year);
xProps->setPrintedBy(u"i did not do it"_ustr);
CPPUNIT_ASSERT_EQUAL(u"i did not do it"_ustr, xProps->getPrintedBy());
aDateTime.Year = 2024;
xProps->setPrintDate(aDateTime);
CPPUNIT_ASSERT_EQUAL(sal_Int16(2024), xProps->getPrintDate().Year);
xProps->setTemplateName(u"blah"_ustr);
CPPUNIT_ASSERT_EQUAL(u"blah"_ustr, xProps->getTemplateName());
xProps->setTemplateURL(u"gopher://some-hole-in-the-ground/"_ustr);
CPPUNIT_ASSERT_EQUAL(u"gopher://some-hole-in-the-ground/"_ustr, xProps->getTemplateURL());
aDateTime.Year = 2043;
xProps->setTemplateDate(aDateTime);
CPPUNIT_ASSERT_EQUAL(sal_Int16(2043), xProps->getTemplateDate().Year);
xProps->setAutoloadURL(u"http://nowhere/"_ustr);
CPPUNIT_ASSERT_EQUAL(u"http://nowhere/"_ustr, xProps->getAutoloadURL());
xProps->setAutoloadSecs(3661);
CPPUNIT_ASSERT_EQUAL(sal_Int32(3661), xProps->getAutoloadSecs());
xProps->setDefaultTarget(u"_blank"_ustr);
CPPUNIT_ASSERT_EQUAL(u"_blank"_ustr, xProps->getDefaultTarget());
xProps->setEditingCycles(42);
CPPUNIT_ASSERT_EQUAL(sal_Int16(42), xProps->getEditingCycles());
xProps->setEditingDuration(84);
CPPUNIT_ASSERT_EQUAL(sal_Int32(84), xProps->getEditingDuration());
uno::Sequence<OUString> aKeywords2{ u"keywordly"_ustr, u"keywordlike"_ustr,
u"keywordalicious"_ustr };
xProps->setKeywords(aKeywords2);
aKeywords = xProps->getKeywords();
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aKeywords.getLength());
CPPUNIT_ASSERT_EQUAL(u"keywordly"_ustr, aKeywords[0]);
CPPUNIT_ASSERT_EQUAL(u"keywordlike"_ustr, aKeywords[1]);
CPPUNIT_ASSERT_EQUAL(u"keywordalicious"_ustr, aKeywords[2]);
uno::Sequence<beans::NamedValue> aDocStats2{ { u"SyllableCount"_ustr, uno::Any(sal_Int16(9)) },
{ u"FrameCount"_ustr, uno::Any(sal_Int16(2)) },
{ u"SentenceCount"_ustr,
uno::Any(sal_Int16(7)) } };
xProps->setDocumentStatistics(aDocStats2);
aDocStats = xProps->getDocumentStatistics();
it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats),
[](const css::beans::NamedValue& val) {
return val.Name == "SyllableCount" && val.Value.get<sal_uInt32>() == 9;
});
CPPUNIT_ASSERT(it != std::cend(aDocStats));
it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats),
[](const css::beans::NamedValue& val) {
return val.Name == "FrameCount" && val.Value.get<sal_uInt32>() == 2;
});
CPPUNIT_ASSERT(it != std::cend(aDocStats));
it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats),
[](const css::beans::NamedValue& val) {
return val.Name == "SentenceCount" && val.Value.get<sal_uInt32>() == 7;
});
CPPUNIT_ASSERT(it != std::cend(aDocStats));
// actually, this tests the PropertyBag service
// but maybe the DocumentProperties service will be implemented
// differently some day...
// note that Time is only supported for backward compatibility!
css::util::Time aTime;
aTime.Hours = 1;
aTime.Minutes = 16;
css::util::Date aDate;
aDate.Year = 2071;
aDate.Month = 2;
aDate.Day = 3;
aDateTime.Year = 2065;
css::util::Duration aDur;
aDur.Negative = true;
aDur.Years = 1001;
aDur.Months = 999;
aDur.Days = 888;
aDur.Hours = 777;
aDur.Minutes = 666;
aDur.Seconds = 555;
aDur.NanoSeconds = 444444444;
xUDP->addProperty("Frobnicate", beans::PropertyAttribute::REMOVABLE, uno::Any(true));
xUDP->addProperty("FrobDuration", beans::PropertyAttribute::REMOVABLE, uno::Any(aDur));
xUDP->addProperty("FrobDuration2", beans::PropertyAttribute::REMOVABLE, uno::Any(aTime));
xUDP->addProperty("FrobEndDate", beans::PropertyAttribute::REMOVABLE, uno::Any(aDate));
xUDP->addProperty("FrobStartTime", beans::PropertyAttribute::REMOVABLE, uno::Any(aDateTime));
xUDP->addProperty("Pi", beans::PropertyAttribute::REMOVABLE, uno::Any(3.1415));
xUDP->addProperty("Foo", beans::PropertyAttribute::REMOVABLE, uno::Any(u"bar"_ustr));
xUDP->addProperty("Removed", beans::PropertyAttribute::REMOVABLE, uno::Any(u"bar"_ustr));
// #i94175#: empty property name is valid ODF 1.1
xUDP->addProperty("", beans::PropertyAttribute::REMOVABLE, uno::Any(u"eeeeek"_ustr));
try
{
xUDP->removeProperty(u"Info 1"_ustr);
xUDP->removeProperty(u"Removed"_ustr);
}
catch (beans::UnknownPropertyException&)
{
CPPUNIT_FAIL("removeProperty failed");
}
try
{
xUDP->addProperty("Forbidden", beans::PropertyAttribute::REMOVABLE,
uno::Any(uno::Sequence<OUString>{ u"foo"_ustr, u"bar"_ustr }));
CPPUNIT_FAIL("inserting value of non-supported type did not fail");
}
catch (beans::IllegalTypeException&)
{
}
aAny = xPropertySet->getPropertyValue(u"Frobnicate"_ustr);
CPPUNIT_ASSERT_EQUAL(true, aAny.get<bool>());
aAny = xPropertySet->getPropertyValue(u"FrobDuration"_ustr);
css::util::Duration aDur2 = aAny.get<css::util::Duration>();
CPPUNIT_ASSERT_EQUAL(aDur.Negative, aDur2.Negative);
CPPUNIT_ASSERT_EQUAL(aDur.Years, aDur2.Years);
CPPUNIT_ASSERT_EQUAL(aDur.Months, aDur2.Months);
CPPUNIT_ASSERT_EQUAL(aDur.Days, aDur2.Days);
CPPUNIT_ASSERT_EQUAL(aDur.Hours, aDur2.Hours);
CPPUNIT_ASSERT_EQUAL(aDur.Minutes, aDur2.Minutes);
CPPUNIT_ASSERT_EQUAL(aDur.Seconds, aDur2.Seconds);
CPPUNIT_ASSERT_EQUAL(aDur.NanoSeconds, aDur2.NanoSeconds);
aAny = xPropertySet->getPropertyValue(u"FrobDuration2"_ustr);
css::util::Time aTime2 = aAny.get<css::util::Time>();
CPPUNIT_ASSERT_EQUAL(aTime.Hours, aTime2.Hours);
CPPUNIT_ASSERT_EQUAL(aTime.Minutes, aTime2.Minutes);
CPPUNIT_ASSERT_EQUAL(aTime.Seconds, aTime2.Seconds);
CPPUNIT_ASSERT_EQUAL(aTime.NanoSeconds, aTime2.NanoSeconds);
aAny = xPropertySet->getPropertyValue(u"FrobEndDate"_ustr);
css::util::Date aDate2 = aAny.get<css::util::Date>();
CPPUNIT_ASSERT_EQUAL(aDate.Day, aDate2.Day);
CPPUNIT_ASSERT_EQUAL(aDate.Month, aDate2.Month);
CPPUNIT_ASSERT_EQUAL(aDate.Year, aDate2.Year);
aAny = xPropertySet->getPropertyValue(u"FrobStartTime"_ustr);
css::util::DateTime aDateTime2 = aAny.get<css::util::DateTime>();
CPPUNIT_ASSERT_EQUAL(aDateTime.Year, aDateTime2.Year);
CPPUNIT_ASSERT_EQUAL(aDateTime.Month, aDateTime2.Month);
CPPUNIT_ASSERT_EQUAL(aDateTime.Day, aDateTime2.Day);
CPPUNIT_ASSERT_EQUAL(aDateTime.Hours, aDateTime2.Hours);
CPPUNIT_ASSERT_EQUAL(aDateTime.Minutes, aDateTime2.Minutes);
CPPUNIT_ASSERT_EQUAL(aDateTime.Seconds, aDateTime2.Seconds);
CPPUNIT_ASSERT_EQUAL(aDateTime.NanoSeconds, aDateTime2.NanoSeconds);
aAny = xPropertySet->getPropertyValue(u"Pi"_ustr);
double aPi = aAny.get<double>();
CPPUNIT_ASSERT_EQUAL(3.1415, aPi);
aAny = xPropertySet->getPropertyValue(u"Foo"_ustr);
OUString aFoo = aAny.get<OUString>();
CPPUNIT_ASSERT_EQUAL(u"bar"_ustr, aFoo);
aAny = xPropertySet->getPropertyValue(u""_ustr);
OUString aEmpty = aAny.get<OUString>();
CPPUNIT_ASSERT_EQUAL(u"eeeeek"_ustr, aEmpty);
try
{
xPropertySet->getPropertyValue(u"Removed"_ustr);
CPPUNIT_FAIL("UserDefined remove didn't");
}
catch (beans::UnknownPropertyException&)
{
}
uno::Sequence<beans::PropertyValue> mimeArgs({ beans::PropertyValue(
u"MediaType"_ustr, -1, uno::Any(u"application/vnd.oasis.opendocument.text"_ustr),
beans::PropertyState_DIRECT_VALUE) });
xProps->storeToMedium(maTempFile.GetURL(), mimeArgs);
xProps->loadFromMedium(maTempFile.GetURL(), uno::Sequence<beans::PropertyValue>());
xUDP = xProps->getUserDefinedProperties();
xPropertySet.set(xUDP, uno::UNO_QUERY);
aAny = xPropertySet->getPropertyValue(u"Frobnicate"_ustr);
CPPUNIT_ASSERT_EQUAL(true, aAny.get<bool>());
aAny = xPropertySet->getPropertyValue(u"FrobDuration"_ustr);
aDur2 = aAny.get<css::util::Duration>();
CPPUNIT_ASSERT_EQUAL(aDur.Negative, aDur2.Negative);
CPPUNIT_ASSERT_EQUAL(aDur.Years, aDur2.Years);
CPPUNIT_ASSERT_EQUAL(aDur.Months, aDur2.Months);
CPPUNIT_ASSERT_EQUAL(aDur.Days, aDur2.Days);
CPPUNIT_ASSERT_EQUAL(aDur.Hours, aDur2.Hours);
CPPUNIT_ASSERT_EQUAL(aDur.Minutes, aDur2.Minutes);
CPPUNIT_ASSERT_EQUAL(aDur.Seconds, aDur2.Seconds);
CPPUNIT_ASSERT_EQUAL(aDur.NanoSeconds, aDur2.NanoSeconds);
css::util::Duration aDur3(false, 0, 0, 0, aTime.Hours, aTime.Minutes, aTime.Seconds,
aTime.NanoSeconds);
// this is now a Duration!
aAny = xPropertySet->getPropertyValue(u"FrobDuration2"_ustr);
aDur2 = aAny.get<css::util::Duration>();
CPPUNIT_ASSERT_EQUAL(aDur3.Negative, aDur2.Negative);
CPPUNIT_ASSERT_EQUAL(aDur3.Years, aDur2.Years);
CPPUNIT_ASSERT_EQUAL(aDur3.Months, aDur2.Months);
CPPUNIT_ASSERT_EQUAL(aDur3.Days, aDur2.Days);
CPPUNIT_ASSERT_EQUAL(aDur3.Hours, aDur2.Hours);
CPPUNIT_ASSERT_EQUAL(aDur3.Minutes, aDur2.Minutes);
CPPUNIT_ASSERT_EQUAL(aDur3.Seconds, aDur2.Seconds);
CPPUNIT_ASSERT_EQUAL(aDur3.NanoSeconds, aDur2.NanoSeconds);
aAny = xPropertySet->getPropertyValue(u"FrobEndDate"_ustr);
aDate2 = aAny.get<css::util::Date>();
CPPUNIT_ASSERT_EQUAL(aDate.Day, aDate2.Day);
CPPUNIT_ASSERT_EQUAL(aDate.Month, aDate2.Month);
CPPUNIT_ASSERT_EQUAL(aDate.Year, aDate2.Year);
aAny = xPropertySet->getPropertyValue(u"FrobStartTime"_ustr);
aDateTime2 = aAny.get<css::util::DateTime>();
CPPUNIT_ASSERT_EQUAL(aDateTime.Year, aDateTime2.Year);
CPPUNIT_ASSERT_EQUAL(aDateTime.Month, aDateTime2.Month);
CPPUNIT_ASSERT_EQUAL(aDateTime.Day, aDateTime2.Day);
CPPUNIT_ASSERT_EQUAL(aDateTime.Hours, aDateTime2.Hours);
CPPUNIT_ASSERT_EQUAL(aDateTime.Minutes, aDateTime2.Minutes);
CPPUNIT_ASSERT_EQUAL(aDateTime.Seconds, aDateTime2.Seconds);
CPPUNIT_ASSERT_EQUAL(aDateTime.NanoSeconds, aDateTime2.NanoSeconds);
aAny = xPropertySet->getPropertyValue(u"Pi"_ustr);
aPi = aAny.get<double>();
CPPUNIT_ASSERT_EQUAL(3.1415, aPi);
aAny = xPropertySet->getPropertyValue(u"Foo"_ustr);
aFoo = aAny.get<OUString>();
CPPUNIT_ASSERT_EQUAL(u"bar"_ustr, aFoo);
aAny = xPropertySet->getPropertyValue(u""_ustr);
aEmpty = aAny.get<OUString>();
CPPUNIT_ASSERT_EQUAL(u"eeeeek"_ustr, aEmpty);
try
{
xPropertySet->getPropertyValue(u"Removed"_ustr);
CPPUNIT_FAIL("UserDefined remove didn't");
}
catch (beans::UnknownPropertyException&)
{
}
rtl::Reference<Listener> xListener = new Listener();
css::uno::Reference<css::util::XModifyBroadcaster> xBroadcaster(xProps, css::uno::UNO_QUERY);
xBroadcaster->addModifyListener(xListener);
xProps->setAuthor(u"not me"_ustr);
CPPUNIT_ASSERT(xListener->reset());
xUDP->addProperty(u"Listener"_ustr, beans::PropertyAttribute::REMOVABLE, uno::Any(u"foo"_ustr));
CPPUNIT_ASSERT(xListener->reset());
xPropertySet->setPropertyValue(u"Listener"_ustr, uno::Any(u"bar"_ustr));
CPPUNIT_ASSERT(xListener->reset());
xUDP->removeProperty(u"Listener"_ustr);
CPPUNIT_ASSERT(xListener->reset());
xBroadcaster->removeModifyListener(xListener);
xUDP->addProperty(u"Listener2"_ustr, beans::PropertyAttribute::REMOVABLE,
uno::Any(u"foo"_ustr));
CPPUNIT_ASSERT(!xListener->reset());
}
CPPUNIT_TEST_FIXTURE(MiscTest, testNoThumbnail)
{
// Load a document.