summaryrefslogtreecommitdiff
path: root/sfx2
diff options
context:
space:
mode:
authorRelease Engineers <releng@openoffice.org>2009-07-02 09:05:03 +0000
committerRelease Engineers <releng@openoffice.org>2009-07-02 09:05:03 +0000
commite68b9caf08facdd99054e61f1242c7a5c5929ab9 (patch)
tree2d139861ef5c381fe46305e7adf064c5ba1f8524 /sfx2
parentb53dc9550dbff91f84714e673ba24b60f5d36cfb (diff)
CWS-TOOLING: integrate CWS odfmetadata2
2009-06-22 11:48:36 +0200 mst r273206 : - connectivity/source/drivers/mozab/mozillasrc/MNSInclude.hxx: + add "include ustrbuf.hxx" to work around warning caused by solaris <sys/kstat.h> declaring a global "long l ;" 2009-06-19 14:25:25 +0200 mst r273159 : - scp2/source/ooo/file_library_ooo.scp: + fix MinGW build 2009-06-08 12:52:33 +0200 mst r272727 : - redland/raptor-1.4.18.patch.mingw, redland/raptor/makefile.mk: + disable parsers that do not build on MinGW (thanks for patch by tono) 2009-05-15 17:31:07 +0200 mst r271957 : fix typos 2009-05-15 17:28:57 +0200 mst r271956 : #i101965# - offapi/com/sun/star/text/TextPortion: + add missing properties: SoftPageBreak, DocumentIndexMark, ReferenceMark, Footnote, TextField + fix read-only status of properties: Bookmark, IsStart, IsCollapsed - offapi/type_reference/{typelibrary_history.txt,types.rdb}: + update reference types.rdb 2009-05-07 14:41:38 +0200 mst r271669 : - sw/inc/{fmtftn.hxx,unocoll.hxx,doc.hxx,editsh.hxx,ftninfo.hxx}, sw/source/core/layout/{flowfrm.cxx,ftnfrm.cxx}, sw/source/core/doc/docftn.cxx, sw/source/core/edit/edattr.cxx, sw/source/core/txtnode/atrftn.cxx, sw/source/core/unocore/unocoll.cxx, sw/source/ui/fldui/fldref.cxx: + fix warning ... the hard way + also fix signature of SwDoc::SetCurFtn 2009-05-05 19:52:55 +0200 mst r271556 : - sw/inc/undobj.hxx: + make some members const 2009-05-05 19:34:40 +0200 mst r271555 : - sw/inc/rolbck.hxx, sw/source/core/undo/rolbck.cxx: + make some members const 2009-05-05 19:13:14 +0200 mst r271553 : - sw/inc/{undobj.hxx,rolbck.hxx}, sw/source/core/undo/{unbkmk.cxx,rolbck.cxx}: + fix rebase merge error + rename SwHstryBookmark to SwHistoryBookmark + clean up SwUndoBookmark 2009-05-05 19:05:53 +0200 mst r271552 : - sw/source/core/unocore/unoportenum.cxx: + fix annoying assertion 2009-05-05 15:34:48 +0200 mst r271522 : CWS-TOOLING: rebase CWS odfmetadata2 to trunk@271427 (milestone: DEV300:m47) 2009-05-04 12:37:01 +0200 mst r271444 : trivial 2009-04-22 13:30:37 +0200 mst r271102 : - sfx2/inc/sfx2/dinfdlg.hxx: + trivial change 2009-04-21 16:46:58 +0200 mst r271043 : - sw/inc/hintids.hxx: + introduce some predicates for the various hints, and use them 2009-04-21 16:19:03 +0200 mst r271041 : - sw/inc/undobj.hxx, sw/source/core/doc/{docfly.cxx,docfmt.cxx,docftn.cxx,doctxm.cxx}, sw/source/core/undo/{unattr.cxx,unins.cxx}: + clean up unattr.cxx: remove/fix casts, prefix members, use auto_ptr, etc. 2009-04-21 15:34:23 +0200 mst r271039 : - sw/inc/{rolbck.hxx,undobj.hxx}, sw/source/core/doc/docfmt.cxx, sw/source/core/txtnode/{thints.cxx,txtedt.cxx}, sw/source/core/undo/{rolbck.cxx,undel.cxx,undobj.cxx,unins.cxx,unmove.cxx, unovwr.cxx,unsect.cxx,unspnd.cxx,untbl.cxx,untblk.cxx,unattr.cxx}: + clean up SwHistory, SwRegHistory and SwHistoryHint etc.: remove/fix casts, prefix members, remove wrong const annotations, use auto_ptr, remove unused members, etc. 2009-04-20 19:17:36 +0200 mst r271013 : - sw/inc/ndhints.hxx, sw/source/core/text/{itrtxt.cxx,txtftn.cxx,itratr.cxx,porfly.cxx, txtfrm.cxx,txtdrop.cxx,frmform.cxx}, sw/source/core/txtnode/{ndtxt.cxx,ndhints.cxx,thints.cxx,txtedt.cxx}, sw/source/core/edit/acorrect.cxx, sw/source/core/doc/{docedt.cxx,docfmt.cxx}, sw/source/filter/html/swhtml.cxx: + clean up SwHintsArray and its subclasses: remove/fix casts, prefix members 2009-04-20 18:42:07 +0200 mst r271007 : - sw/source/core/text/txtio.cxx, sw/source/core/edit/edattr.cxx, sw/source/core/undo/rolbck.cxx: + remove JP_NEWCORE dead code 2009-04-20 18:38:09 +0200 mst r271006 : - sw/source/core/unocore/unochart.cxx: + silence unxlngi warning (debug=t) 2009-04-20 16:36:13 +0200 mst r270991 : - sfx2/inc/sfx2/dinfdlg.hxx, sfx2/source/dialog/dinfdlg.cxx, sfx2/source/doc/objserv.cxx, sw/source/ui/fldui/flddinf.hxx: + trivial cleanups 2009-04-20 15:28:52 +0200 mst r270990 : - sfx2/inc/sfx2/dinfdlg.hxx, sfx2/source/dialog/dinfdlg.cxx, sfx2/source/doc/objserv.cxx: + fix bug: replaying a macro with a DocumentInfoItem removes all user-defined properties 2009-03-10 15:08:20 +0100 mst r269273 : - sfx2/source/doc/Metadatable.cxx: + add missing SolarMutex guards 2009-03-10 14:46:29 +0100 mst r269272 : - unoxml/source/rdf/librdf_repository.cxx: + never free rdf_world because that would call libxm2 xmlCleanupParser (and, to add insult to injury, other libxml2 functions later...) 2009-03-06 19:02:44 +0100 mst r269041 : argh! undo... 2009-03-06 19:00:58 +0100 mst r269040 : fix #i99931# - sw/source/ui/uno/unomod.cxx: + SwXViewSettings::_getSingleValue returns uninitialized memory for the ZoomType property if the value is PAGE_WIDTH_EXACT 2009-03-06 18:59:28 +0100 mst r269039 : - sw/inc/ndtxt.hxx, sw/source/core/txtnode/ndtxt.cxx, sw/source/core/unocore/unoportenum.cxx: + fix some more wntmsci12 warnings... 2009-03-06 18:56:46 +0100 mst r269038 : - sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx: + work around spurious warning on unxsoli4 debug=t 2009-03-05 14:02:01 +0100 mst r268902 : - sw/inc/txatbase.hxx: + back to c-style casts, they also compile on wntmsci12... 2009-03-05 10:23:25 +0100 mst r268882 : - comphelper/inc/comphelper/processfactory.hxx, comphelper/source/processfactory/processfactory.cxx: + revert change of return type of comphelper_getProcessComponentContext to Reference: does not build on wntmsci12 2009-03-04 19:08:09 +0100 mst r268861 : - sw/source/core/txtnode/{atrtox.cxx,ndtxt.cxx}: + fix initialization 2009-03-04 14:37:30 +0100 mst r268831 : - solenv/inc/target.mk: + fix CLASSPATH so complex tests run (fix by sb) 2009-03-04 14:36:30 +0100 mst r268830 : - sw/inc/unoobj.hxx, sw/source/core/unocore/{unoparagraph.cxx,unoobj.cxx,unoobj2.cxx}: + SwXParaFrameEnumeration constructor now takes SwPaM, not SwUnoCrsr + move SwParaSelection into unoparagraph.cxx, as it is only used there + bugfix: replace SwUnoCrsrs on stack with SwCursors 2009-03-04 14:34:46 +0100 mst r268829 : - sw/inc/pam.hxx, sw/source/core/crsr/pam.cxx, sw/source/core/edit/eddel.cxx, sw/source/core/doc/docredln.cxx, sw/source/core/undo/{untbl.cxx,undel.cxx}, sw/source/filter/rtf/swparrtf.cxx: + clean up SwPaM: prefix members + new constructor SwPosition(SwCntntNode&, xub_StrLen) + fix several broken SwPosition and SwPaM constructors + SwPam::DeleteMark now actually resets the unused position to default 2009-03-02 12:07:09 +0100 mst r268646 : - sw/inc/fmtcol.hxx: + fix annoying warning (gcc 4) 2009-03-02 12:06:27 +0100 mst r268645 : - odk/util/check.pl, odk/examples/DevelopersGuide/Text/TextDocuments.java: + rename module from FieldMaster to fieldmaster 2009-02-27 19:49:56 +0100 mst r268614 : - sfx2/inc/sfx2/Metadatable.hxx, sfx2/prj/d.lst, sfx2/source/doc/{Metadatable.cxx,makefile.mk}, sw/inc/{SwMetadatable.hxx,unoobj.hxx,undobj.hxx,ndtxt.hxx}, sw/source/core/doc/{SwMetadatable.cxx,makefile.mk,docnew.cxx}, sw/source/core/undo/{untbl.cxx,unins.cxx}, sw/source/core/unocore/unoparagraph.cxx, sw/source/ui/app/docsh.cxx: + move Metadatable implementation from sw to sfx2 2009-02-27 17:58:55 +0100 mst r268608 : - sw/inc/{SwMetadatable.hxx,undobj.hxx}, sw/source/core/doc/SwMetadatable.cxx, sw/source/core/undo/{untbl.cxx,unins.cxx,undel.cxx}: + CreateUndo now returns an opaque MetadatableUndo object 2009-02-27 13:15:44 +0100 mst r268587 : - sw/inc/ndtxt.hxx, sw/source/core/doc/docfmt.cxx, sw/source/core/text/{itratr.cxx,porlay.cxx}, sw/source/core/txtnode/{txtedt.cxx,ndtxt.cxx,thints.cxx}: + clean up SwTxtNode: fix casts, prefix members + factor out inline function SwTxtNode::TryDeleteSwpHints() 2009-02-27 13:14:30 +0100 mst r268586 : - svx/inc/svx/emphitem.hxx: + fix borken header guard 2009-02-27 13:13:56 +0100 mst r268585 : - sfx2/source/bastyp/progress.cxx: + fix use of compiler specific macro 2009-02-27 11:00:32 +0100 mst r268564 : - sw/inc/{txatbase.hxx,txtatr.hxx,txtinet.hxx,txtfld.hxx,txtftn.hxx, txtflcnt.hxx,txttxmrk.hxx,txtrfmrk.hxx}, sw/source/core/txtnode/{atrtox.cxx,atrref.cxx,atrflyin.cxx,atrftn.cxx, txtatr2.cxx,txatbase.cxx,atrfld.cxx,txtedt.cxx}, sw/source/core/text/atrstck.cxx, sw/source/core/access/acchyperlink.cxx, sw/source/core/doc/visiturl.cxx, sw/source/ui/wrtsh/wrtsh2.cxx: + clean up SwTxtAttr and its subclasses: remove/fix casts, prefix members + SwTxtINetFmt: remove unused member bColor - sw/source/core/text/txtfld.cxx: + move SwTxtFld methods to atrfld.cxx 2009-02-27 10:58:44 +0100 mst r268563 : - sfx2/inc/sfx2/sfxbasemodel.hxx: + don't privately inherit BaseMutex, ScModelObj wants to access it 2009-02-27 10:58:02 +0100 mst r268562 : - xmloff/source/core/{RDFaExportHelper.cxx,RDFaImportHelper.cxx}: + arrrgh!!! someone thought it would be a good idea to have 2 different versions of boost in external! and they're NOT compatible!!! insert an ugly fragile hack that maybe works with both... 2009-02-26 17:42:26 +0100 mst r268544 : - comphelper/inc/comphelper/storagehelper.hxx. sfx2/source/doc/DocumentMetadataAccess.cxx: + someone made IsValidZipEntryFileName a static method and didn't tell me 2009-02-26 15:52:56 +0100 mst r268529 : redland: split up patches 2009-02-26 13:17:56 +0100 mst r268509 : migration of cws odfmetadata2 from CVS (resync to m42): module sw #i95863# - sw/inc/segdefs{,_}.hxx: + remove obsolete files - sw/source/ui/inc/itemdef.hxx: + remove itemdef.hxx - sw/source/ui/app/[apphdl.cxx,docsh.cxx}, sw/source/ui/misc/glshell.cxx, sw/source/ui/shells/*.cxx, sw/source/ui/uiview/*.cxx, sw/source/ui/web/*.cxx: + use sfx2/msg.hxx instead of itemdef.hxx - sw/source/core/edit/eddel.cxx: + @ JP: SwEditShell::Replace: you're right, deleting the text to be replaced first, and then inserting a space, and then replacing that space is unnecessary. whew, i'm so happy that we finally answered that question after 11 years. - sw/inc/edimp.hxx: + remove FOREACHCURSOR_START, FOREACHCURSOR_END - sw/inc/{swcrsr.hxx,unocrsr.hxx,viscrs.hxx}, sw/source/core/crsr/{crsrsh.cxx,swcrsr.cxx,trvlreg.cxx,trvltbl.cxx, unocrsr.cxx,viscrs.cxx}, sw/source/core/doc/{docbm.cxx,doccorr.cxx}, sw/source/core/docnode/{ndtbl.cxx,ndtbl1.cxx}, sw/source/core/edit/editsh.cxx, sw/source/core/frmedt/{fefly1.cxx,fetab.cxx,tblsel.cxx}, sw/source/core/layout/trvlfrm.cxx, sw/source/core/unocore/{unochart.cxx,unoobj2.cxx,unoparagraph.cxx, unoportenum.cxx,unotbl.cxx}, sw/source/core/view/vprint.cxx: + remove the hideous virtual operator SwFooCursor* + make SwCursor::IsReadOnlyAvailable() virtual + make SwUnoCrsr::Clone() virtual + refactor SwCursor methods IsSelOver(), LeftRight(), UpDown(), GotoTable(): replace dynamic_cast<...>(this) with new virtual methods 2009-02-26 13:14:58 +0100 mst r268508 : migration of cws odfmetadata2 from CVS (resync to m42): module sw - sw/source/filter/xml/swxml.cxx: + XMLReader::Read: load RDF metadata of the ODF document - sw/source/filter/xml/wrtxml.cxx: + SwXMLWriter::_Write: write RDF metadata of the ODF document if ODF >= 1.2 #i90620#: import xml:id in text tables (does not actually work yet) - sw/source/filter/xml/xmltbli{.hxx,.cxx}: + SwXMLTableCellAttrTokens,aTableCellAttrTokenMap: add XML_TOK_TABLE_XMLID + SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl: attribute xml:id + SwXMLTableCellContext_Impl::CreateChildContext: attribute xml:id + SwXMLTableColContext_Impl::SwXMLTableColContext_Impl: attribute xml:id + SwXMLTableContext::SwXMLTableContext: attribute xml:id fix #i98530# - sw/inc/unoport.hxx, sw/source/core/unocore/unoport.cxx: + SwXTextPortion: make constructor params const& - sw/source/core/unocore/unoportenum.cxx: + refactor to remove some code duplication + fix bug: paragraph w/out hints: bookmark before frame gets lost #i97274# handle invalid tables - sw/source/core/layout/tabfrm.cxx, sw/source/filter/xml/xmltbli.cxx: + SwXMLTableContext::MakeTable(): check that the table actually contains cells, and abort (removing the inserted table nodes) if not 2009-02-26 13:11:48 +0100 mst r268507 : migration of cws odfmetadata2 from CVS (resync to m42): module sw refactor SwXTextRange and SwXParagraph - sw/inc/unoobj.hxx, sw/source/core/unocore/unoobj2.cxx: + remove 3 constructors of SwXTextRange + new method SwXTextRange::CreateParentXText + refactor SwXTextRange::CreateTextRangeFromPosition and SwXTextRange::getText - sw/inc/unoobj.hxx, sw/source/core/unocore/unoparagraph.cxx: + SwXParagraph no longer uses a cursor; it registers directly at SwTxtNode + replace SwXParagraph::GetCrsr with SwXParagraph::GetTxtNode - sw/source/core/unocore/unotext.cxx, sw/source/ui/uno/unotxvw.cxx: + adapt to new SwXParagraph #i90620# - sw/inc/SwMetadatable.hxx, sw/source/core/doc/SwMetadatable.cxx: + new files: base classes sw::Metadatable and sw::MetadatableMixin; also, 2 implementations of IXmlIdRegistry: sw::XmlIdRegistryDocument and sw::XmlIdRegistryClipboard + setMetadataReference: handle empty stream name as auto-detect - sw/source/core/doc/makefile.mk: + add SwMetadatable add a XmlIdRegistry to SwDoc - sw/inc/doc.hxx: + SwDoc: add member m_pXmlIdRegistry, method GetXmlIdRegistry() - sw/source/core/doc/docnew.cxx: + initialize XmlIdRegistry in SwDoc::GetXmlIdRegistry, not in constructor, because the constructor is not told whether the SwDoc is a clipboard - sw/inc/docsh.hxx, sw/source/ui/app/docsh.cxx: + SwDocShell: override GetXmlIdRegistry() #i91563#: make the SwTxtNode metadatable - sw/inc/ndtxt.hxx + SwTxtNode inherits sw::Metadatable - sw/inc/unoobj.hxx, sw/source/core/unocore/unoparagraph.cxx: + SwXParagraph inherits sw::MetadatableMixin #i91563#: handle SwTxtNode's metadata for delete - sw/source/core/txtnode/ndtxt.cxx: + SwTxtNode::SplitCntntNode: handle XmlId + SwTxtNode::JoinNext: merge XmlIds - sw/source/core/doc/docedt.cxx: + lcl_GetJoinFlags: document postcondition + SwDoc::Delete: remove XmlId only if SwTxtNode _becomes_ empty #i91563#: handle SwTxtNode's metadata for delete with undo - sw/inc/undobj.hxx + SwUndoDelete: new members m_pMetadataUndoStart, m_pMetadataUndoEnd - sw/source/core/undo/undel.cxx: + SwUndoDelete::SaveCntnt: save XmlIds for start and end SwTxtNode + SwUndoDelete::SaveCntnt: remove XmlId only if SwTxtNode _becomes_ empty + SwUndoDelete::Undo: restore saved XmlIds for start and end SwTxtNode - sw/source/core/docnode/ndcopy.cxx: + SwTxtNode::MakeCopy: register copy at XmlIdRegistry #i91563#: handle SwTxtNode's metadata for find/replace with undo - sw/source/core/undo/unins.cxx: + _UnReplaceData: rename members: add prefix m_ + _UnReplaceData: new members m_pMetadataUndoStart, m_pMetadataUndoEnd + _UnReplaceData::_UnReplaceData: save XmlIds for start and end SwTxtNode + _UnReplaceData::Undo: restore saved XmlIds for start and end SwTxtNode #i91563#: handle SwTxtNode's metadata for table-to-text with undo - sw/source/core/undo/untbl.cxx: + SwTblToTxtSave: rename members: add prefix m_ + SwTblToTxtSave: new members m_pMetadataUndoStart, m_pMetadataUndoEnd + SwTblToTxtSave::SwTblToTxtSave: save XmlIds for start and end SwTxtNode + SwTblToTxtSave::SwTblToTxtSave, SwNodes::UndoTableToText: always store the index of the first SwTxtNode in the cell, instead of the index of the first SwTxtNode in case of the first cell in a row, and the cell start node in other cases + SwNodes::UndoTableToText: restore saved XmlIds for start and end SwTxtNode - sw/source/core/docnode/ndtbl.cxx: + lcl_DelBox: simplify for refactored start index handling in SwTblToTxtSave 2009-02-26 13:02:28 +0100 mst r268505 : migration of cws odfmetadata2 from CVS (resync to m42): module sd - sd/source/ui/table/tableobjectbar.cxx,sd/source/ui/view/*.cxx: + remove invocations of SFX_DECL_TYPE - sd/source/ui/slideshow/SlideShowRestarter.cxx, sd/source/ui/toolpanel/LayoutMenu.cxx, sd/source/ui/unoidl/DrawController.cxx, sd/source/ui/view/{ViewShellBase.cxx,ViewTabBar.cxx,frmview.cxx}: + fix abuses of comphelper_getProcessComponentContext (missing release) 2009-02-26 13:01:24 +0100 mst r268504 : migration of cws odfmetadata2 from CVS (resync to m42): module starmath - starmath/source/document.cxx: + don't touch SfxObjectShell's privates 2009-02-26 13:00:37 +0100 mst r268503 : migration of cws odfmetadata2 from CVS (resync to m42): module sfx2 #i90620# - sfx2/inc/sfx2/XmlIdRegistry.hxx: + new file: interfaces sfx2::IXmlIdRegistry and sfx2::IXmlIdRegistrySupplier and a couple of utility functions - sfx2/inc/sfx2/DocumentMetadataAccess.hxx, sfx2/source/doc/DocumentMetadataAccess.cxx: + new class sfx2::DocumentMetadataAccess, implements XDocumentMetadataAccess + the URI of the DocumentMetadataAccess is now the URI from which the document was loaded; for a new document, use a vnd.sun.star.tdoc URI + add new function sfx2::createBaseURI() + prevent using reserved file names + try not to recurse into embedded subdocuments - sfx2/source/doc/makefile.mk: + add DocumentMetadataAccess - sfx2/util/makefile.mk: + link libsfx2 against libxml2 (needed for xmlValidateNCName) - sfx2/source/doc/makefile.mk: + add LIBXML_CFLAGS to CFLAGS - sfx2/prj/build.lst: + add dependence on libxml2 - sfx2/prj/d.lst: + add XmlIdRegistry.hxx, DocumentMetadataAccess.hxx - sfx2/inc/sfx2/objsh.hxx, sfx2/source/doc/objxtor.cxx: + make SfxObjectShell's members private + new method SfxObjectShell::GetAutoStyleFilterIndex + SfxObjectShell inherits sfx2::IXmlIdRegistrySupplier - sfx2/source/dialog/templdlg.cxx, sfx2/source/doc/sfxbasemodel.cxx: + don't touch SfxObjectShell's privates - sfx2/inc/sfx2/sfxbasemodel.hxx, sfx2/source/doc/sfxbasemodel.cxx: + SfxBaseModel inherits BaseMutex instead of IMPL_SfxBaseModel_MutexContainer + SfxBaseModel implements additional interface XDocumentMetadataAccess + IMPL_SfxBaseModel_DataContainer has new member: a sfx2::DocumentMetadataAccess + implementation of XDocumentMetadataAccess forwards to the sfx2::DocumentMetadataAccess member - sfx2/qa/complex/DocumentMetadataAccessTest.java, sfx2/qa/complex/{tests.sce,makefile.mk}, sfx2/qa/complex/testdocuments/TESTRDFA.odt: + add complex test: DocumentMetadataAccessTest + add RDFa test document #i95863# - sfx2/inc/sfx2/dinfdlg.hxx, sfx2/source/dialog/dinfdlg.cxx: + refactor SfxDocumentItem so it no longer requires a XDocumentInfo + move struct CustomProperty to implementation file + remove class SfxDocumentUserPage + QueryValue,PutValue: remove MID_DOCINFO_FIELD* - sfx2/source/doc/objserv.cxx: + adapt to SfxDocumentItem change - sfx2/inc/sfx2/sfx.hrc, sfx2/sdi/sfxslots.sdi, sfx2/inc/sfx2/msg.hxx: + remove MID_DOCINFO_FIELD* + put all invocations of SFX_DECL_TYPE in msg.hxx, and undef SFX_DECL_TYPE - sfx2/source/doc/objxtor.cxx: + fix abuses of comphelper_getProcessComponentContext (missing release) - sfx2/source/doc/docfile.cxx: + SfxMedium::SfxMedium: don't dereference NULL, throw exception instead - sfx2/source/doc/objstor.cxx: + SfxObjectShell::DoLoad: fix bug: DocumentBaseURI is not initialized 2009-02-26 12:58:07 +0100 mst r268502 : migration of cws odfmetadata2 from CVS (resync to m42): module xmloff #i90620#: implement RDFa import (interface change) - xmloff/inc/xmloff/xmlimp.hxx. xmloff/source/core/xmlimp.cxx: + make SvXMLImport::GetAbsoluteReference() const + add SvXMLImport::GetComponentContext() + SvXMLImport::_InitCtor(): add RDFa namespace + add SvXMLImport::AddRDFa() + SvXMLImport::endDocument() inserts RDFa into document repository - xmloff/inc/xmloff/xmltoken.hxx, xmloff/source/core/xmltoken.cxx: + new tokens for RDFa: XML_ABOUT, XML_DATATYPE - xmloff/inc/RDFaImportHelper.hxx, xmloff/source/core/RDFaImportHelper.cxx: + new class RDFaImportHelper + adapt the code to the bleak reality of broken C++ implementations + handle empty xhtml:about attributes properly, which are actually valid relative URIs + work around broken SvXMLImport::GetAbsoluteReference - xmloff/source/core/makefile.mk: + add RDFaImportHelper.cxx #i90620#: implement RDFa export - xmloff/inc/xmloff/xmlexp.hxx, xmloff/source/core/xmlexp.cxx: + add SvXMLExport::EnsureNamespace(), and a stack of namespace maps + add SvXMLExport::GetComponentContext() + add SvXMLExport::AddAttributesRDFa() - xmloff/inc/RDFaExportHelper.hxx, xmloff/source/core/RDFaExportHelper.cxx: + new class RDFaExportHelper + don't use std::map::data_type, which is actually called std::map::mapped_type by libstdc++ - xmloff/source/core/makefile.mk: + add RDFaExportHelper.cxx #i91563# - xmloff/inc/xmloff/txtimp.hxx, xmloff/source/text/txtimp.cxx: + XMLTextPAttrTokens: add RDFa tokens - xmloff/source/text/txtparai{.hxx,.cxx}: + import RDFa for text:p - xmloff/source/text/txtparae.cxx: + export RDFa for text:p interface change: use XHTML namespace instead of RDFA - xmloff/inc/xmlnmspe.hxx, xmloff/inc/xmloff/xmltoken.hxx, xmloff/source/core/{xmltoken.cxx,xmlimp.cxx,xmlexp.cxx,RDFaExportHelper.cxx}, xmloff/source/text/txtimp.cxx: + use XHTML namespace instead of RDFA #i91565#, #i91566#: (preliminary) import for text:meta, text:meta-field - xmloff/source/text/txtparai.cxx: + new class XMLMetaImportContextBase with subclasses to import text:meta and text:meta-field - xmloff/source/text/XMLTextMarkImportContext.cxx: + change XMLTextMarkImportContext::CreateAndInsertMark to handle marks with no name (text:meta) #i91565#, #i91566#: (preliminary) export for text:meta, text:meta-field - xmloff/inc/txtflde.hxx, xmloff/source/text/txtflde.cxx: + add FIELD_ID_META to FieldIdEnum + new method XMLTextFieldExport::ExportMetaField() + change XMLTextFieldExport::ExportField{,AutoStyle,Helper} to take additional parameter for progress bar - xmloff/inc/xmloff/txtparae.hxx, xmloff/source/text/txtparae.cxx: + make XMLTextParagraphExport::exportTextRangeEnumeration() public + new method XMLTextParagraphExport::exportMeta() #i90620# - xmloff/inc/xmloff/xmlimp.hxx, xmloff/source/core/xmlimp.cxx, xmloff/inc/xmloff/xmlexp.hxx, xmloff/source/core/xmlexp.cxx: + rename SvXML{Im,Ex}port::GetStreamPath() to GetStreamName() + fix xml:id {im,ex}port for embedded documents and non-packages + adapt to API change: XMetadatable #i90620# GRDDL - xmloff/inc/xmlnmspe.hxx, xmloff/inc/xmloff/xmltoken.hxx, xmloff/source/core/{xmltoken.cxx,xmlexp.cxx}: + add GRDDL namespace + add token XML_TRANSFORMATION + add grddl:transformation attribute to root elements for meta.xml, content.xml and styles.xml 2009-02-26 12:54:40 +0100 mst r268501 : migration of cws odfmetadata2 from CVS (resync to m42): module unoxml #i90620# - unoxml/source/rdf/librdf_repository.cxx: + librdf_Repository::importGraph: allocate buffer sized length of stream + switch from one librdf_world per repository to a single static world because redland has global variables with a brain-damaged life-cycle... + exportGraph: use new raptor 1.4.18 feature to disable writing an xml:base attribute in RDF/XML files - unoxml/source/rdf/librdf_repository.cxx: unoxml/qa/complex/RDFRepositoryTest.java: + adapt to predicate is URI change + adapt to RDFa API change + adapt to API change: RDFa has multiple predicates... + adapt to API change: XMetadatable derives from XURI + allow xhtml:datatype without xhtml:content + adapt to API change: attribute MetadataReference is StringPair - unoxml/source/rdf/CURI.cxx: + add some more URI constants 2009-02-26 12:53:32 +0100 mst r268500 : migration of cws odfmetadata2 from CVS (resync to m42): module package - package/inc/ImplValidCharacters.hxx: + remove (moved to comphelper) 2009-02-26 12:52:49 +0100 mst r268499 : migration of cws odfmetadata2 from CVS (resync to m42): module comphelper - comphelper/inc/comphelper/processfactory.hxx, comphelper/source/processfactory/processfactory.cxx: + add getProcessComponentContext() + change return type of comphelper_getProcessComponentContext to Reference - comphelper/inc/comphelper/stl_types.hxx: + add OUStringBufferAppender + add algorithm intersperse - comphelper/source/misc/string.cxx: + rewrite convertCommaSeparated with intersperse and OUStringBufferAppender - comphelper/inc/comphelper/stlunosequence.hxx: + fix bug: begin() on empty sequence != end() 2009-02-26 12:50:47 +0100 mst r268498 : migration of cws odfmetadata2 from CVS (resync to m42): module offapi #i96209# - offapi/com/sun/star/text/fieldmaster/*.idl: + rename module from FieldMaster to fieldmaster - offapi/type_reference/{typelibrary_history.txt,types.rdb}: + update reference types.rdb #i90620# - offapi/com/sun/star/rdf/{XMetadatable.idl,XDocumentMetadataAccess.idl}: + API change: XMetadatable derives from XURI + API change: replace XmlId (string) with MetadataReference (StringPair) - offapi/com/sun/star/rdf/{Statement.idl,XDocumentRepository.idl, XNamedGraph.idl,XRepository.idl}: + the predicate of a statement is a URI, not a Resource - offapi/com/sun/star/rdf/XDocumentMetadataAccess.idl: + rename: s/Package/Document/ + remove uuid + remove everything related to mapping + graph names are now generated from base URI and file names + load methods: improve error handling with XInteractionHandler - offapi/com/sun/star/rdf/XDocumentRepository.idl: + change: RDFa permits using multiple predicates in one attribute + setStatementRDFa: subject is now XResource, object is now XMetadatable - offapi/com/sun/star/rdf/URIs.idl: + add some more URI constants - offapi/com/sun/star/rdf: + fix @since tags and replace <method> with <member> 2009-02-26 12:47:24 +0100 mst r268497 : migration of cws odfmetadata2 from CVS (resync to m42): module redland fix #i93768# - redland/raptor-1.4.17.patch, redland/raptor/makefile.mk: + disable GRDDL parser to prevent call to libxslt xsltSetDefaultSecurityPrefs, which breaks xmlhelp - redland/raptor/makefile.mk, redland/raptor-1.4.17.patch, redland/raptor-1.4.18.patch: + upgrade raptor to 1.4.18 + deactivate serializer for RSS/Atom (does not build) - redland/rasqal/makefile.mk, redland/rasqal-0.9.15.patch, redland/rasqal-0.9.16.patch, + upgrade rasqal to 0.9.16 - redland/redland/makefile.mk, redland/redland-1.0.7.patch, redland/redland-1.0.8.patch: + upgrade redland to 1.0.8 - redland/redlandversion.mk: + the librasqal SONAME has changed
Diffstat (limited to 'sfx2')
-rw-r--r--sfx2/inc/sfx2/DocumentMetadataAccess.hxx218
-rw-r--r--sfx2/inc/sfx2/Metadatable.hxx190
-rw-r--r--sfx2/inc/sfx2/XmlIdRegistry.hxx101
-rw-r--r--sfx2/inc/sfx2/dinfdlg.hxx75
-rw-r--r--sfx2/inc/sfx2/msg.hxx12
-rw-r--r--sfx2/inc/sfx2/objsh.hxx8
-rw-r--r--sfx2/inc/sfx2/sfx.hrc8
-rw-r--r--sfx2/inc/sfx2/sfxbasemodel.hxx138
-rw-r--r--sfx2/prj/build.lst2
-rw-r--r--sfx2/prj/d.lst3
-rw-r--r--sfx2/qa/complex/DocumentMetadataAccessTest.java1270
-rw-r--r--sfx2/qa/complex/makefile.mk4
-rw-r--r--sfx2/qa/complex/testdocuments/TESTRDFA.odtbin0 -> 7540 bytes
-rw-r--r--sfx2/qa/complex/tests.sce1
-rw-r--r--sfx2/sdi/sfxslots.sdi8
-rw-r--r--sfx2/source/bastyp/progress.cxx2
-rw-r--r--sfx2/source/dialog/dinfdlg.cxx331
-rw-r--r--sfx2/source/dialog/templdlg.cxx7
-rw-r--r--sfx2/source/doc/DocumentMetadataAccess.cxx1414
-rw-r--r--sfx2/source/doc/Metadatable.cxx1860
-rw-r--r--sfx2/source/doc/docfile.cxx2
-rw-r--r--sfx2/source/doc/makefile.mk7
-rw-r--r--sfx2/source/doc/objserv.cxx4
-rw-r--r--sfx2/source/doc/objstor.cxx1
-rw-r--r--sfx2/source/doc/objxtor.cxx20
-rw-r--r--sfx2/source/doc/sfxbasemodel.cxx394
-rw-r--r--sfx2/util/makefile.mk4
27 files changed, 5668 insertions, 416 deletions
diff --git a/sfx2/inc/sfx2/DocumentMetadataAccess.hxx b/sfx2/inc/sfx2/DocumentMetadataAccess.hxx
new file mode 100644
index 000000000000..1f0d3d38e44e
--- /dev/null
+++ b/sfx2/inc/sfx2/DocumentMetadataAccess.hxx
@@ -0,0 +1,218 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DocumentMetadataAccess.hxx,v $
+ * $Revision: 1.1.2.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SFX_DOCUMENTMETADATAACCESS_HXX_
+#define _SFX_DOCUMENTMETADATAACCESS_HXX_
+
+#include <sal/config.h>
+
+#include <sfx2/dllapi.h>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
+#include <com/sun/star/rdf/XRepositorySupplier.hpp>
+
+#include <cppuhelper/implbase1.hxx>
+
+#include <boost/utility.hpp>
+
+#include <memory>
+
+
+/** Implementation of the interface com.sun.star.rdf.XDocumentMetadataAccess
+
+ This is not a service only because it needs some kind of XML ID registry
+ from the document, and i do not like defining an API for that.
+ Also, the implementation does _no_ locking, so make sure access is
+ protected externally.
+
+ @author mst
+ */
+
+namespace com { namespace sun { namespace star { namespace embed {
+ class XStorage;
+} } } }
+
+namespace sfx2 {
+
+
+/** create a base URI for loading metadata from an ODF (sub)document.
+
+ @param i_xContext component context
+ @param i_xStorage storage for the document; FileSystemStorage is allowed
+ @param i_rPkgURI the URI for the package
+ @param i_rSubDocument (optional) path of the subdocument in package
+
+ @return a base URI suitable for XDocumentMetadataAccess::loadFromStorage
+ */
+::com::sun::star::uno::Reference< ::com::sun::star::rdf::XURI> SFX2_DLLPUBLIC
+createBaseURI(
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext>
+ const & i_xContext,
+ ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage>
+ const & i_xStorage,
+ ::rtl::OUString const & i_rPkgURI,
+ ::rtl::OUString const & i_rSubDocument = ::rtl::OUString());
+
+
+class IXmlIdRegistrySupplier;
+struct DocumentMetadataAccess_Impl;
+
+
+class SFX2_DLLPUBLIC DocumentMetadataAccess :
+ private boost::noncopyable,
+ public ::cppu::WeakImplHelper1<
+ ::com::sun::star::rdf::XDocumentMetadataAccess>
+{
+public:
+ explicit DocumentMetadataAccess(::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext > const & i_xContext,
+ IXmlIdRegistrySupplier const & i_rRegistrySupplier,
+ ::rtl::OUString const & i_rBaseURI);
+ // N.B.: in contrast to previous, this constructor does _not_ initialize!
+ // caller must immediately call loadFromStorage/Medium!
+ explicit DocumentMetadataAccess(::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext > const & i_xContext,
+ IXmlIdRegistrySupplier const & i_rRegistrySupplier);
+ virtual ~DocumentMetadataAccess();
+
+ // ::com::sun::star::rdf::XNode:
+ virtual ::rtl::OUString SAL_CALL getStringValue()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::rdf::XURI:
+ virtual ::rtl::OUString SAL_CALL getNamespace()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getLocalName()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::rdf::XRepositorySupplier:
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XRepository > SAL_CALL getRDFRepository()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::rdf::XDocumentMetadataAccess:
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > SAL_CALL
+ getElementByMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rReference)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > SAL_CALL
+ getElementByURI(const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xURI)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > > SAL_CALL getMetadataGraphsWithType(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xType)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI> SAL_CALL
+ addMetadataFile(const ::rtl::OUString & i_rFileName,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XURI >
+ > & i_rTypes)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::ElementExistException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI> SAL_CALL
+ importMetadataFile(::sal_Int16 i_Format,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::io::XInputStream > & i_xInStream,
+ const ::rtl::OUString & i_rFileName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xBaseURI,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XURI >
+ > & i_rTypes)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::datatransfer::UnsupportedFlavorException,
+ ::com::sun::star::container::ElementExistException,
+ ::com::sun::star::rdf::ParseException,
+ ::com::sun::star::io::IOException);
+ virtual void SAL_CALL removeMetadataFile(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xGraphName)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::NoSuchElementException);
+ virtual void SAL_CALL addContentOrStylesFile(
+ const ::rtl::OUString & i_rFileName)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::ElementExistException);
+ virtual void SAL_CALL removeContentOrStylesFile(
+ const ::rtl::OUString & i_rFileName)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::NoSuchElementException);
+
+ virtual void SAL_CALL loadMetadataFromStorage(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::embed::XStorage > & i_xStorage,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xBaseURI,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::task::XInteractionHandler> & i_xHandler)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException);
+ virtual void SAL_CALL storeMetadataToStorage(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::embed::XStorage > & i_xStorage)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException);
+ virtual void SAL_CALL loadMetadataFromMedium(
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::PropertyValue > & i_rMedium)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException);
+ virtual void SAL_CALL storeMetadataToMedium(
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::PropertyValue > & i_rMedium)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException);
+
+private:
+ std::auto_ptr<DocumentMetadataAccess_Impl> m_pImpl;
+};
+
+} // namespace sfx2
+
+#endif // _SFX_DOCUMENTMETADATAACCESS_HXX_
+
diff --git a/sfx2/inc/sfx2/Metadatable.hxx b/sfx2/inc/sfx2/Metadatable.hxx
new file mode 100644
index 000000000000..c190abd0471b
--- /dev/null
+++ b/sfx2/inc/sfx2/Metadatable.hxx
@@ -0,0 +1,190 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SwMetadatable.hxx,v $
+ * $Revision: 1.1.2.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef METADATABLE_HXX
+#define METADATABLE_HXX
+
+#include <sal/config.h>
+
+#include <sfx2/dllapi.h>
+
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/rdf/XMetadatable.hpp>
+
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+
+
+namespace com { namespace sun { namespace star {
+ namespace frame { class XModel; }
+} } }
+
+namespace sfx2 {
+ class IXmlIdRegistry;
+}
+
+namespace sfx2 {
+
+class XmlIdRegistry;
+class MetadatableUndo;
+
+
+// XML ID handling ---------------------------------------------------
+
+
+/// create a sfx2::XmlIdRegistryDocument or a sfx2::XmlIdRegistryClipboard
+SFX2_DLLPUBLIC ::sfx2::IXmlIdRegistry *
+createXmlIdRegistry(const bool i_DocIsClipboard);
+
+
+/** base class for core objects that may have xml:id.
+
+ <p>The interface of this class consists of 3 parts:
+ <ul><li>implementations that are used by the <type>MetadatableMixin</type>
+ below</li>
+ <li>hooks to be called by the sw core whenever actions that are
+ relevant to the uniqueness of xml:ids are taken (copying,
+ splitting, merging, deletion, undo, etc.)</li>
+ <li>abstract methods that are called by the implementation of the
+ previous hooks</li></ul>
+ </p>
+ */
+class SFX2_DLLPUBLIC Metadatable : private boost::noncopyable
+{
+
+public:
+ Metadatable() : m_pReg(0) {}
+
+ // destructor calls RemoveMetadataReference
+ virtual ~Metadatable();
+
+ // for MetadatableMixin ----------------------------------------------
+
+ ::com::sun::star::beans::StringPair GetMetadataReference() const;
+ void SetMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rReference);
+ void EnsureMetadataReference();
+
+ // hooks -------------------------------------------------------------
+
+ // called from dtor!
+ void RemoveMetadataReference();
+
+ /** register this as a copy of i_rSource */
+ void RegisterAsCopyOf(Metadatable const & i_rSource,
+ const bool i_bCopyPrecedesSource = false);
+
+ /** create an Undo Metadatable, which remembers this' reference */
+ ::boost::shared_ptr<MetadatableUndo> CreateUndo(
+ const bool i_isDelete = false);
+
+ /** restore this from Undo Metadatable */
+ void RestoreMetadata(::boost::shared_ptr<MetadatableUndo> const& i_pUndo);
+
+ /** merge this and i_rOther into this */
+ void JoinMetadatable(Metadatable const & i_rOther,
+ const bool i_isMergedEmpty, const bool i_isOtherEmpty);
+
+ // abstract methods --------------------------------------------------
+
+ /** get the registry from the SwDoc */
+ virtual ::sfx2::IXmlIdRegistry& GetRegistry() = 0;
+
+ /** is this in a clipboard document? */
+ virtual bool IsInClipboard() const = 0;
+
+ /** is this in undo array? */
+ virtual bool IsInUndo() const = 0;
+
+ /** which stream is this in? true: content.xml; false: styles.xml */
+ virtual bool IsInContent() const = 0;
+
+ /** create XMetadatable from this.
+ note: if IsInUndo or IsInClipboard return true,
+ MakeUnoObject <em>must not</em> be called!
+ */
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > MakeUnoObject() = 0;
+
+private:
+ friend class MetadatableClipboard;
+ friend class MetadatableUndo;
+
+ // note that Reg may be a XmlIdRegistryDocument or a XmlIdRegistryClipboard
+ XmlIdRegistry* m_pReg; // null => no XmlId
+};
+
+
+/** base class for UNO objects that implement <type>XMetadatable</type>.
+
+ <p>An instance of this base class is associated with an instance of
+ <type>Metadatable</type>.</p>
+ */
+class SFX2_DLLPUBLIC MetadatableMixin :
+ public ::cppu::WeakImplHelper1<
+ ::com::sun::star::rdf::XMetadatable>
+{
+
+public:
+ MetadatableMixin() {};
+
+ virtual ~MetadatableMixin() {}
+
+ // ::com::sun::star::rdf::XNode:
+ virtual ::rtl::OUString SAL_CALL getStringValue()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::rdf::XURI:
+ virtual ::rtl::OUString SAL_CALL getLocalName()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getNamespace()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::rdf::XMetadatable:
+ virtual ::com::sun::star::beans::StringPair SAL_CALL getMetadataReference()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rReference)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException);
+ virtual void SAL_CALL ensureMetadataReference()
+ throw (::com::sun::star::uno::RuntimeException);
+
+protected:
+ /// get the core object corresponding to this UNO object.
+ virtual Metadatable * GetCoreObject() = 0;
+ /// get the <type>XModel</type> for the document
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >
+ GetModel() = 0;
+
+};
+
+} // namespace sfx2
+
+#endif // METADATABLE_HXX
diff --git a/sfx2/inc/sfx2/XmlIdRegistry.hxx b/sfx2/inc/sfx2/XmlIdRegistry.hxx
new file mode 100644
index 000000000000..0ae6fbb75193
--- /dev/null
+++ b/sfx2/inc/sfx2/XmlIdRegistry.hxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: XmlIdRegistry.hxx,v $
+ * $Revision: 1.1.2.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SFX_XMLIDREGISTRY_HXX_
+#define _SFX_XMLIDREGISTRY_HXX_
+
+#include <sal/config.h>
+
+#include <sfx2/dllapi.h>
+
+#include <com/sun/star/beans/StringPair.hpp>
+
+
+namespace com { namespace sun { namespace star { namespace rdf {
+ class XMetadatable;
+} } } }
+
+namespace sfx2 {
+
+// XML ID utilities --------------------------------------------------
+
+/** is i_rIdref a valid NCName ? */
+bool SFX2_DLLPUBLIC isValidNCName(::rtl::OUString const & i_rIdref);
+
+extern inline bool
+isValidXmlId(::rtl::OUString const & i_rStreamName,
+ ::rtl::OUString const & i_rIdref)
+{
+ return isValidNCName(i_rIdref) &&
+ (i_rStreamName.equalsAscii("content.xml") ||
+ i_rStreamName.equalsAscii("styles.xml"));
+}
+
+
+// XML ID handling ---------------------------------------------------
+
+/** interface for getElementByMetadataReference;
+ for use by sfx2::DocumentMetadataAccess
+ */
+class SFX2_DLLPUBLIC IXmlIdRegistry
+{
+
+public:
+ virtual ~IXmlIdRegistry() { }
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > SAL_CALL
+ GetElementByMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rXmlId) const = 0;
+
+};
+
+/** supplier interface for the registry.
+
+ This indirection is unfortunately necessary, because the SwDocShell
+ is not always connected to a SwDoc, so we cannot guarantee that a
+ registry given to a SfxBaseModel/DocumentMetadataAccess remains valid;
+ it has to be retrieved from this supplier interface on access.
+ */
+class SFX2_DLLPUBLIC IXmlIdRegistrySupplier
+{
+
+public:
+ virtual ~IXmlIdRegistrySupplier() { }
+
+ /** override this if you have a XmlIdRegistry. */
+ virtual const IXmlIdRegistry* GetXmlIdRegistry() const { return 0; }
+
+};
+
+} // namespace sfx2
+
+#endif // _SFX_XMLIDREGISTRY_HXX_
+
diff --git a/sfx2/inc/sfx2/dinfdlg.hxx b/sfx2/inc/sfx2/dinfdlg.hxx
index ae7439bcde44..1873c6e6c88e 100644
--- a/sfx2/inc/sfx2/dinfdlg.hxx
+++ b/sfx2/inc/sfx2/dinfdlg.hxx
@@ -50,9 +50,6 @@
#include "tabdlg.hxx"
namespace com { namespace sun { namespace star {
- namespace beans {
- class XPropertyContainer;
- }
namespace document {
class XDocumentProperties;
}
@@ -75,7 +72,7 @@ private:
::com::sun::star::util::DateTime m_CreationDate;
::rtl::OUString m_ModifiedBy;
::com::sun::star::util::DateTime m_ModificationDate;
- String m_PrintedBy;
+ ::rtl::OUString m_PrintedBy;
::com::sun::star::util::DateTime m_PrintDate;
sal_Int16 m_EditingCycles;
sal_Int32 m_EditingDuration;
@@ -83,11 +80,9 @@ private:
::rtl::OUString m_Keywords;
::rtl::OUString m_Subject;
::rtl::OUString m_Title;
- ::rtl::OUString m_UserDefinedFieldTitles[4];
- ::rtl::OUString m_UserDefinedFieldValues[4];
- sal_Bool bHasTemplate;
- sal_Bool bDeleteUserData;
- sal_Bool bIsUseUserData;
+ sal_Bool m_bHasTemplate;
+ sal_Bool m_bDeleteUserData;
+ sal_Bool m_bUseUserData;
std::vector< CustomProperty* > m_aCustomProperties;
public:
@@ -101,9 +96,10 @@ public:
virtual ~SfxDocumentInfoItem();
/// update i_xDocProps with the data in this object
- void updateDocumentInfo(
+ void UpdateDocumentInfo(
const ::com::sun::star::uno::Reference<
- ::com::sun::star::document::XDocumentProperties> & i_xDocProps)
+ ::com::sun::star::document::XDocumentProperties> & i_xDocProps,
+ bool i_bDoNotUpdateUserDefined = false)
const;
sal_Bool isAutoloadEnabled() const { return m_isAutoloadEnabled; }
@@ -151,25 +147,21 @@ public:
void setSubject(::rtl::OUString i_val) { m_Subject = i_val; }
::rtl::OUString getTitle() const { return m_Title; }
void setTitle(::rtl::OUString i_val) { m_Title = i_val; }
- ::rtl::OUString getUserDefinedFieldTitle(size_t i_ix) const;
- void setUserDefinedFieldTitle(size_t i_ix, ::rtl::OUString i_val);
- ::rtl::OUString getUserDefinedFieldValue(size_t i_ix) const;
- void setUserDefinedFieldValue(size_t i_ix, ::rtl::OUString i_val);
/// reset user-specific data (author, modified-by, ...)
void resetUserData(const ::rtl::OUString & i_rAuthor);
- void SetTemplate( BOOL b ) { bHasTemplate = b; }
- FASTBOOL HasTemplate() const { return bHasTemplate; }
- void SetDeleteUserData( BOOL bSet );
- void SetUseUserData( BOOL bSet );
- BOOL IsDeleteUserData() const;
- BOOL IsUseUserData() const;
+ void SetTemplate( sal_Bool b ) { m_bHasTemplate = b; }
+ sal_Bool HasTemplate() const { return m_bHasTemplate; }
+ void SetDeleteUserData( sal_Bool bSet );
+ void SetUseUserData( sal_Bool bSet );
+ sal_Bool IsDeleteUserData() const;
+ sal_Bool IsUseUserData() const;
std::vector< CustomProperty* > GetCustomProperties() const;
- void ClearCustomProperties();
- void AddCustomProperty( const ::rtl::OUString& sName,
- const com::sun::star::uno::Any& rValue );
+ void ClearCustomProperties();
+ void AddCustomProperty( const ::rtl::OUString& sName,
+ const com::sun::star::uno::Any& rValue );
virtual SfxPoolItem* Clone( SfxItemPool* pPool = NULL ) const;
virtual int operator==( const SfxPoolItem& ) const;
@@ -262,41 +254,6 @@ public:
static SfxTabPage* Create( Window* pParent, const SfxItemSet& );
};
-// class SfxDocumentUserPage ---------------------------------------------
-
-class SfxDocumentUserPage : public SfxTabPage
-{
-private:
- BOOL bLabelModified;
-
- FixedText aInfo1Ft;
- Edit aInfo1Ed;
- FixedText aInfo2Ft;
- Edit aInfo2Ed;
- FixedText aInfo3Ft;
- Edit aInfo3Ed;
- FixedText aInfo4Ft;
- Edit aInfo4Ed;
- PushButton aEditLabelBtn;
- SfxDocumentInfoItem* pInfoItem;
-
-#if _SOLAR__PRIVATE
- DECL_LINK( EditLabelHdl, PushButton * );
-
- String GetLabelText_Impl( FixedText* pLabel );
- void SetLabelText_Impl( FixedText* pLabel, const String& rNewLabel );
-#endif
-
-protected:
- SfxDocumentUserPage( Window* pParent, const SfxItemSet& );
-
- virtual BOOL FillItemSet( SfxItemSet& );
- virtual void Reset( const SfxItemSet& );
-
-public:
- static SfxTabPage* Create( Window* pParent, const SfxItemSet& );
-};
-
// class SfxInternetPage -------------------------------------------------
class TargetList;
diff --git a/sfx2/inc/sfx2/msg.hxx b/sfx2/inc/sfx2/msg.hxx
index 8147a9f67df1..66e8c07ba357 100644
--- a/sfx2/inc/sfx2/msg.hxx
+++ b/sfx2/inc/sfx2/msg.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: msg.hxx,v $
- * $Revision: 1.4 $
+ * $Revision: 1.4.82.2 $
*
* This file is part of OpenOffice.org.
*
@@ -155,11 +155,17 @@ SFX_DECL_TYPE(5);
SFX_DECL_TYPE(6);
SFX_DECL_TYPE(7);
SFX_DECL_TYPE(8);
+SFX_DECL_TYPE(10); // for SfxDocInfoItem
SFX_DECL_TYPE(11);
+SFX_DECL_TYPE(13); // for SwAddPrinterItem, Sd...
SFX_DECL_TYPE(14);
-SFX_DECL_TYPE(17); // fuer SvxAddressItem, SvxSearchItem
-SFX_DECL_TYPE(18); // fuer SfxDocInfoItem
+SFX_DECL_TYPE(16); // for SwDocDisplayItem
+SFX_DECL_TYPE(17); // for SvxAddressItem
+SFX_DECL_TYPE(18); // for SvxSearchItem
+
+// all SfxTypes must be in this header
+#undef SFX_DECL_TYPE
#define SFX_SLOT_ARG( aShellClass, id, GroupId, ExecMethodPtr, StateMethodPtr, Flags, ItemClass, nArg0, nArgs, Name, Prop ) \
{ id, GroupId, id, Flags | Prop, \
diff --git a/sfx2/inc/sfx2/objsh.hxx b/sfx2/inc/sfx2/objsh.hxx
index 53b074aa8829..71f1729840c0 100644
--- a/sfx2/inc/sfx2/objsh.hxx
+++ b/sfx2/inc/sfx2/objsh.hxx
@@ -63,6 +63,7 @@
#include <sot/storage.hxx>
#include <rsc/rscsfx.hxx>
+#include <sfx2/XmlIdRegistry.hxx>
#include <sfx2/shell.hxx>
#include <comphelper/embeddedobjectcontainer.hxx>
#include <com/sun/star/frame/XModel.hpp>
@@ -207,11 +208,13 @@ enum SfxTitleQuery
class SfxToolBoxConfig;
struct TransferableObjectDescriptor;
-class SFX2_DLLPUBLIC SfxObjectShell: public SfxShell, virtual public SotObject, public ::comphelper::IEmbeddedHelper
+class SFX2_DLLPUBLIC SfxObjectShell :
+ public SfxShell, virtual public SotObject,
+ public ::comphelper::IEmbeddedHelper, public ::sfx2::IXmlIdRegistrySupplier
{
friend struct ModifyBlocker_Impl;
-public:
+private:
struct SfxObjectShell_Impl* pImp; // interne Daten
SfxMedium * pMedium; // Beschreibung der Datei bzw. des Storage, in dem sich das Objekt befindet
@@ -524,6 +527,7 @@ public:
//determine the position of the "Automatic" filter in the stylist
void SetAutoStyleFilterIndex(sal_uInt16 nSet);
+ sal_uInt16 GetAutoStyleFilterIndex();
virtual sal_Bool HasBasic() const;
BasicManager* GetBasicManager() const;
com::sun::star::uno::Reference< com::sun::star::script::XLibraryContainer >
diff --git a/sfx2/inc/sfx2/sfx.hrc b/sfx2/inc/sfx2/sfx.hrc
index c29d0797bf81..fbc5e6f58d1c 100644
--- a/sfx2/inc/sfx2/sfx.hrc
+++ b/sfx2/inc/sfx2/sfx.hrc
@@ -367,14 +367,6 @@
#define MID_DOCINFO_KEYWORDS 0x17
#define MID_DOCINFO_SUBJECT 0x1b
#define MID_DOCINFO_TITLE 0x1d
-#define MID_DOCINFO_FIELD1TITLE 0x20
-#define MID_DOCINFO_FIELD2TITLE 0x21
-#define MID_DOCINFO_FIELD3TITLE 0x22
-#define MID_DOCINFO_FIELD4TITLE 0x23
-#define MID_DOCINFO_FIELD1 0x24
-#define MID_DOCINFO_FIELD2 0x25
-#define MID_DOCINFO_FIELD3 0x26
-#define MID_DOCINFO_FIELD4 0x27
#define MID_DOCINFO_AUTOLOADENABLED 0x2d
#define MID_DOCINFO_AUTOLOADURL 0x2e
#define MID_DOCINFO_AUTOLOADSECS 0x2f
diff --git a/sfx2/inc/sfx2/sfxbasemodel.hxx b/sfx2/inc/sfx2/sfxbasemodel.hxx
index 7cbd6e069d66..324080484c81 100644
--- a/sfx2/inc/sfx2/sfxbasemodel.hxx
+++ b/sfx2/inc/sfx2/sfxbasemodel.hxx
@@ -47,6 +47,9 @@
#include <com/sun/star/document/XDocumentInfo.hpp>
#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
+#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
+
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/document/XEventListener.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
@@ -79,13 +82,12 @@
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <cppuhelper/weak.hxx>
+#include <cppuhelper/basemutex.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <com/sun/star/script/XStarBasicAccess.hpp>
#include <osl/mutex.hxx>
-#ifndef _LINK_HXX_
#include <tools/link.hxx>
-#endif
#include <com/sun/star/document/XViewDataSupplier.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
@@ -93,9 +95,9 @@
#include <com/sun/star/task/XInteractionHandler.hpp>
//________________________________________________________________________________________________________
-#if ! defined(INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_28)
-#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_28
-#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 28
+#if ! defined(INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_29)
+#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_29
+#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 29
#include <comphelper/implbase_var.hxx>
#endif
@@ -204,11 +206,6 @@ struct IMPL_SfxBaseModel_DataContainer ; // impl. struct to hold member o
// class declarations
//________________________________________________________________________________________________________
-struct IMPL_SfxBaseModel_MutexContainer
-{
- MUTEX m_aMutex ;
-} ;
-
/**_______________________________________________________________________________________________________
@short -
@@ -217,7 +214,8 @@ struct IMPL_SfxBaseModel_MutexContainer
@implements XChild
XComponent
XDocumentInfoSupplier
- XDocumentPropertiesSupplier
+ document::XDocumentPropertiesSupplier
+ rdf::XDocumentMetadataAccess
XEventListener
XModel
XModifiable2
@@ -230,13 +228,14 @@ struct IMPL_SfxBaseModel_MutexContainer
XCloseable
XCloseBroadcaster
- @base IMPL_MutexContainer
+ @base cppu::BaseMutex
SfxListener
*/
-typedef ::comphelper::WeakImplHelper28 < XCHILD
+typedef ::comphelper::WeakImplHelper29 < XCHILD
, XDOCUMENTINFOSUPPLIER
, ::com::sun::star::document::XDocumentPropertiesSupplier
+ , ::com::sun::star::rdf::XDocumentMetadataAccess
, XEVENTBROADCASTER
, XEVENTLISTENER
, XEVENTSSUPPLIER
@@ -264,8 +263,8 @@ typedef ::comphelper::WeakImplHelper28 < XCHILD
, XUNTITLEDNUMBERS
> SfxBaseModel_Base;
-class SFX2_DLLPUBLIC SfxBaseModel : public SfxBaseModel_Base
- , public IMPL_SfxBaseModel_MutexContainer
+class SFX2_DLLPUBLIC SfxBaseModel : protected ::cppu::BaseMutex
+ , public SfxBaseModel_Base
, public SfxListener
{
@@ -1290,6 +1289,114 @@ public:
throw (css::uno::RuntimeException);
//____________________________________________________________________________________________________
+
+ // ::com::sun::star::rdf::XNode:
+ virtual ::rtl::OUString SAL_CALL getStringValue()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::rdf::XURI:
+ virtual ::rtl::OUString SAL_CALL getNamespace()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getLocalName()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::rdf::XRepositorySupplier:
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XRepository > SAL_CALL getRDFRepository()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::rdf::XDocumentMetadataAccess:
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > SAL_CALL
+ getElementByMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rReference)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > SAL_CALL
+ getElementByURI(const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xURI)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > > SAL_CALL getMetadataGraphsWithType(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xType)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI> SAL_CALL
+ addMetadataFile(const ::rtl::OUString & i_rFileName,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XURI >
+ > & i_rTypes)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::ElementExistException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI> SAL_CALL
+ importMetadataFile(::sal_Int16 i_Format,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::io::XInputStream > & i_xInStream,
+ const ::rtl::OUString & i_rFileName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xBaseURI,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XURI >
+ > & i_rTypes)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::datatransfer::UnsupportedFlavorException,
+ ::com::sun::star::container::ElementExistException,
+ ::com::sun::star::rdf::ParseException,
+ ::com::sun::star::io::IOException);
+ virtual void SAL_CALL removeMetadataFile(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xGraphName)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::NoSuchElementException);
+ virtual void SAL_CALL addContentOrStylesFile(
+ const ::rtl::OUString & i_rFileName)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::ElementExistException);
+ virtual void SAL_CALL removeContentOrStylesFile(
+ const ::rtl::OUString & i_rFileName)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::NoSuchElementException);
+
+ virtual void SAL_CALL loadMetadataFromStorage(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::embed::XStorage > & i_xStorage,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XURI > & i_xBaseURI,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::task::XInteractionHandler> & i_xHandler)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException);
+ virtual void SAL_CALL storeMetadataToStorage(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::embed::XStorage > & i_xStorage)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException);
+ virtual void SAL_CALL loadMetadataFromMedium(
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::PropertyValue > & i_rMedium)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException);
+ virtual void SAL_CALL storeMetadataToMedium(
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::PropertyValue > & i_rMedium)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException);
+
+
+ //____________________________________________________________________________________________________
// SfxListener
//____________________________________________________________________________________________________
@@ -1370,6 +1477,7 @@ public:
/** returns true if someone added a XEventListener to this XEventBroadcaster */
sal_Bool hasEventListeners() const;
+
protected:
/* returns a unique id for the model that is valid as long as the document
diff --git a/sfx2/prj/build.lst b/sfx2/prj/build.lst
index fc6984c17ada..89e618e8fc12 100644
--- a/sfx2/prj/build.lst
+++ b/sfx2/prj/build.lst
@@ -1,4 +1,4 @@
-sf sfx2 : l10n idl basic xmlscript framework shell setup_native sax SYSTRAY_GTK:libegg NULL
+sf sfx2 : l10n idl basic xmlscript framework shell setup_native sax SYSTRAY_GTK:libegg LIBXML2:libxml2 NULL
sf sfx2 usr1 - all sf_mkout NULL
sf sfx2\inc nmake - all sf_inc NULL
sf sfx2\prj get - all sf_prj NULL
diff --git a/sfx2/prj/d.lst b/sfx2/prj/d.lst
index 03ae35e5c3d7..77acce9a7be9 100644
--- a/sfx2/prj/d.lst
+++ b/sfx2/prj/d.lst
@@ -128,3 +128,6 @@ mkdir: %_DEST%\inc%_EXT%\sfx2
..\inc\sfx2\layout-tabdlg.hxx %_DEST%\inc%_EXT%\sfx2\layout-tabdlg.hxx
..\inc\sfx2\layout-post.hxx %_DEST%\inc%_EXT%\sfx2\layout-post.hxx
..\inc\sfx2\layout-pre.hxx %_DEST%\inc%_EXT%\sfx2\layout-pre.hxx
+..\inc\sfx2\XmlIdRegistry.hxx %_DEST%\inc%_EXT%\sfx2\XmlIdRegistry.hxx
+..\inc\sfx2\DocumentMetadataAccess.hxx %_DEST%\inc%_EXT%\sfx2\DocumentMetadataAccess.hxx
+..\inc\sfx2\Metadatable.hxx %_DEST%\inc%_EXT%\sfx2\Metadatable.hxx
diff --git a/sfx2/qa/complex/DocumentMetadataAccessTest.java b/sfx2/qa/complex/DocumentMetadataAccessTest.java
new file mode 100644
index 000000000000..0983aec1bd37
--- /dev/null
+++ b/sfx2/qa/complex/DocumentMetadataAccessTest.java
@@ -0,0 +1,1270 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DocumentMetadataAccessTest.java,v $
+ *
+ * $Revision: 1.1.2.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ ************************************************************************/
+
+package complex.framework;
+
+import complexlib.ComplexTestCase;
+import helper.StreamSimulator;
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.uno.Any;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XInitialization;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.WrappedTargetRuntimeException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.StringPair;
+import com.sun.star.container.XEnumerationAccess;
+import com.sun.star.container.XEnumeration;
+import com.sun.star.container.ElementExistException;
+import com.sun.star.container.NoSuchElementException;
+import com.sun.star.io.XInputStream;
+import com.sun.star.io.XOutputStream;
+import com.sun.star.util.XCloseable;
+import com.sun.star.frame.XStorable;
+import com.sun.star.frame.XLoadable;
+import com.sun.star.text.XTextDocument;
+import com.sun.star.text.XTextRange;
+import com.sun.star.text.XText;
+import com.sun.star.rdf.*;
+
+/**
+ * Test case for interface com.sun.star.rdf.XDocumentMetadataAccess
+ * Currently, this service is implemented in
+ * sfx2/source/doc/DocumentMetadataAccess.cxx
+ *
+ * Actually, this is not a service, so we need to create a document and
+ * go from there...
+ *
+ * @author mst
+ */
+public class DocumentMetadataAccessTest extends ComplexTestCase
+{
+ XMultiServiceFactory xMSF;
+ XComponentContext xContext;
+ String tempDir;
+
+ String nsRDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+ String nsRDFS = "http://www.w3.org/2000/01/rdf-schema#";
+ String nsPkg="http://docs.oasis-open.org/opendocument/meta/package/common#";
+ String nsODF ="http://docs.oasis-open.org/opendocument/meta/package/odf#";
+
+ XURI foo;
+ XURI bar;
+ XURI baz;
+
+ static XURI rdf_type;
+ static XURI rdfs_label;
+ static XURI pkg_Document;
+ static XURI pkg_hasPart;
+ static XURI pkg_MetadataFile;
+ static XURI odf_ContentFile;
+ static XURI odf_StylesFile;
+ static XURI odf_Element;
+ static XBlankNode blank1;
+ static XBlankNode blank2;
+ static XBlankNode blank3;
+ static XBlankNode blank4;
+ static String manifestPath = "manifest.rdf";
+ static String contentPath = "content.xml";
+ static String stylesPath = "styles.xml";
+ static String fooPath = "foo.rdf";
+ static String fooBarPath = "meta/foo/bar.rdf";
+
+ XRepository xRep;
+ XRepositorySupplier xRS;
+ XDocumentMetadataAccess xDMA;
+
+ public String[] getTestMethodNames ()
+ {
+ return new String[] { "check", "checkRDFa" };
+ }
+
+ public void before()
+ {
+ try {
+
+ xMSF = (XMultiServiceFactory) param.getMSF();
+ assure("could not create MultiServiceFactory.", xMSF != null);
+ XPropertySet xPropertySet = (XPropertySet)
+ UnoRuntime.queryInterface(XPropertySet.class, xMSF);
+ Object defaultCtx = xPropertySet.getPropertyValue("DefaultContext");
+ xContext = (XComponentContext)
+ UnoRuntime.queryInterface(XComponentContext.class, defaultCtx);
+ assure("could not get component context.", xContext != null);
+
+ tempDir = util.utils.getOfficeTemp/*Dir*/(xMSF);
+ log.println("tempdir: " + tempDir);
+
+ foo = URI.create(xContext, "uri:foo");
+ assure("foo", null != foo);
+ bar = URI.create(xContext, "uri:bar");
+ assure("bar", null != bar);
+ baz = URI.create(xContext, "uri:baz");
+ assure("baz", null != baz);
+
+ blank1 = BlankNode.create(xContext, "_:1");
+ assure("blank1", null != blank1);
+ blank2 = BlankNode.create(xContext, "_:2");
+ assure("blank2", null != blank2);
+ blank3 = BlankNode.create(xContext, "_:3");
+ assure("blank3", null != blank3);
+ blank4 = BlankNode.create(xContext, "_:4");
+ assure("blank4", null != blank4);
+ rdf_type = URI.createKnown(xContext, URIs.RDF_TYPE);
+ assure("rdf_type", null != rdf_type);
+ rdfs_label = URI.createKnown(xContext, URIs.RDFS_LABEL);
+ assure("rdfs_label", null != rdfs_label);
+ pkg_Document = URI.createKnown(xContext, URIs.PKG_DOCUMENT);
+ assure("pkg_Document", null != pkg_Document);
+ pkg_hasPart = URI.createKnown(xContext, URIs.PKG_HASPART);
+ assure("pkg_hasPart", null != pkg_hasPart);
+ pkg_MetadataFile = URI.createKnown(xContext, URIs.PKG_METADATAFILE);
+ assure("pkg_MetadataFile", null != pkg_MetadataFile);
+ odf_ContentFile = URI.createKnown(xContext, URIs.ODF_CONTENTFILE);
+ assure("odf_ContentFile", null != odf_ContentFile);
+ odf_StylesFile = URI.createKnown(xContext, URIs.ODF_STYLESFILE);
+ assure("odf_StylesFile", null != odf_StylesFile);
+ odf_Element = URI.createKnown(xContext, URIs.ODF_ELEMENT);
+ assure("odf_Element", null != odf_Element);
+
+ } catch (Exception e) {
+ report(e);
+ }
+ }
+
+ public void after()
+ {
+ xRep = null;
+ xRS = null;
+ xDMA = null;
+ }
+
+ public void check()
+ {
+ XComponent xComp = null;
+ XComponent xComp2 = null;
+ try {
+ XEnumeration xStmtsEnum;
+ XNamedGraph xManifest;
+
+ log.println("Creating document with Repository...");
+
+ // we cannot create a XDMA directly, we must create
+ // a document and get it from there :(
+ // create document
+ PropertyValue[] loadProps = new PropertyValue[1];
+ loadProps[0] = new PropertyValue();
+ loadProps[0].Name = "Hidden";
+ loadProps[0].Value = new Boolean(true);
+ xComp = util.DesktopTools.openNewDoc(xMSF, "swriter", loadProps);
+ XTextDocument xText = (XTextDocument) UnoRuntime.queryInterface(
+ XTextDocument.class, xComp);
+
+ XRepositorySupplier xRS = (XRepositorySupplier)
+ UnoRuntime.queryInterface(XRepositorySupplier.class, xComp);
+ assure("xRS null", null != xRS);
+ XDocumentMetadataAccess xDMA = (XDocumentMetadataAccess)
+ UnoRuntime.queryInterface(XDocumentMetadataAccess.class, xRS);
+ assure("xDMA null", null != xDMA);
+ xRep = xRS.getRDFRepository();
+ assure("xRep null", null != xRep);
+
+ log.println("...done");
+
+ log.println("Checking that new repository is initialized...");
+
+ XURI xBaseURI = (XURI) xDMA;
+ String baseURI = xBaseURI.getStringValue();
+ assure("new: baseURI",
+ null != xBaseURI && !xBaseURI.getStringValue().equals(""));
+
+ assure("new: # graphs", 1 == xRep.getGraphNames().length);
+ XURI manifest = URI.createNS(xContext, xBaseURI.getStringValue(),
+ manifestPath);
+ xManifest = xRep.getGraph(manifest);
+ assure("new: manifest graph", null != xManifest);
+
+ Statement[] manifestStmts = getManifestStmts(xBaseURI);
+ xStmtsEnum = xRep.getStatements(null, null, null);
+ assure("new: manifest graph", eq(xStmtsEnum, manifestStmts));
+
+ log.println("...done");
+
+ log.println("Checking some invalid args...");
+
+ String content = "behold, for i am the content.";
+ XTextRange xTR = new TestRange(content);
+ XMetadatable xM = (XMetadatable) xTR;
+
+ try {
+ xDMA.getElementByURI(null);
+ assure("getElementByURI: null allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.getMetadataGraphsWithType(null);
+ assure("getMetadataGraphsWithType: null URI allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("", new XURI[0]);
+ assure("addMetadataFile: empty filename allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("/foo", new XURI[0]);
+ assure("addMetadataFile: absolute filename allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("fo\"o", new XURI[0]);
+ assure("addMetadataFile: invalid filename allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("../foo", new XURI[0]);
+ assure("addMetadataFile: filename with .. allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("foo/../../bar", new XURI[0]);
+ assure("addMetadataFile: filename with nest .. allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("foo/././bar", new XURI[0]);
+ assure("addMetadataFile: filename with nest . allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("content.xml", new XURI[0]);
+ assure("addMetadataFile: content.xml allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("styles.xml", new XURI[0]);
+ assure("addMetadataFile: styles.xml allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("meta.xml", new XURI[0]);
+ assure("addMetadataFile: meta.xml allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addMetadataFile("settings.xml", new XURI[0]);
+ assure("addMetadataFile: settings.xml allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.importMetadataFile(FileFormat.RDF_XML, null, "foo",
+ foo, new XURI[0]);
+ assure("importMetadataFile: null stream allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ XInputStream xFooIn =
+ new StreamSimulator(tempDir + "empty.rdf", true, param);
+ xDMA.importMetadataFile(FileFormat.RDF_XML, xFooIn, "",
+ foo, new XURI[0]);
+ assure("importMetadataFile: empty filename allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ XInputStream xFooIn =
+ new StreamSimulator(tempDir + "empty.rdf", true, param);
+ xDMA.importMetadataFile(FileFormat.RDF_XML, xFooIn, "meta.xml",
+ foo, new XURI[0]);
+ assure("importMetadataFile: meta.xml filename allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ XInputStream xFooIn =
+ new StreamSimulator(tempDir + "empty.rdf", true, param);
+ xDMA.importMetadataFile(FileFormat.RDF_XML,
+ xFooIn, "foo", null, new XURI[0]);
+ assure("importMetadataFile: null base URI allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ XInputStream xFooIn =
+ new StreamSimulator(tempDir + "empty.rdf", true, param);
+ xDMA.importMetadataFile(FileFormat.RDF_XML,
+ xFooIn, "foo", rdf_type, new XURI[0]);
+ assure("importMetadataFile: non-absolute base URI allowed",
+ false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.removeMetadataFile(null);
+ assure("removeMetadataFile: null URI allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addContentOrStylesFile("");
+ assure("addContentOrStylesFile: empty filename allowed",
+ false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addContentOrStylesFile("/content.xml");
+ assure("addContentOrStylesFile: absolute filename allowed",
+ false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.addContentOrStylesFile("foo.rdf");
+ assure("addContentOrStylesFile: invalid filename allowed",
+ false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.removeContentOrStylesFile("");
+ assure("removeContentOrStylesFile: empty filename allowed",
+ false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.loadMetadataFromStorage(null, foo, null);
+ assure("loadMetadataFromStorage: null storage allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.storeMetadataToStorage(null/*, base*/);
+ assure("storeMetadataToStorage: null storage allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.loadMetadataFromMedium(new PropertyValue[0]);
+ assure("loadMetadataFromMedium: empty medium allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ try {
+ xDMA.storeMetadataToMedium(new PropertyValue[0]);
+ assure("storeMetadataToMedium: empty medium allowed", false);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+
+ log.println("...done");
+
+ log.println("Checking file addition/removal...");
+
+ xDMA.removeContentOrStylesFile(contentPath);
+ xStmtsEnum = xManifest.getStatements(null, null, null);
+ assure("removeContentOrStylesFile (content)",
+ eq(xStmtsEnum, new Statement[] {
+ manifestStmts[0], manifestStmts[2], manifestStmts[4]
+ }));
+
+ xDMA.addContentOrStylesFile(contentPath);
+ xStmtsEnum = xManifest.getStatements(null, null, null);
+ assure("addContentOrStylesFile (content)",
+ eq(xStmtsEnum, manifestStmts));
+
+ xDMA.removeContentOrStylesFile(stylesPath);
+ xStmtsEnum = xManifest.getStatements(null, null, null);
+ assure("removeContentOrStylesFile (styles)",
+ eq(xStmtsEnum, new Statement[] {
+ manifestStmts[0], manifestStmts[1], manifestStmts[3]
+ }));
+
+ xDMA.addContentOrStylesFile(stylesPath);
+ xStmtsEnum = xManifest.getStatements(null, null, null);
+ assure("addContentOrStylesFile (styles)",
+ eq(xStmtsEnum, manifestStmts));
+
+ XURI xFoo = URI.createNS(xContext, xBaseURI.getStringValue(),
+ fooPath);
+ Statement xM_BaseHaspartFoo =
+ new Statement(xBaseURI, pkg_hasPart, xFoo, manifest);
+ Statement xM_FooTypeMetadata =
+ new Statement(xFoo, rdf_type, pkg_MetadataFile, manifest);
+ Statement xM_FooTypeBar =
+ new Statement(xFoo, rdf_type, bar, manifest);
+ xDMA.addMetadataFile(fooPath, new XURI[] { bar });
+ xStmtsEnum = xManifest.getStatements(null, null, null);
+ assure("addMetadataFile",
+ eq(xStmtsEnum, merge(manifestStmts, new Statement[] {
+ xM_BaseHaspartFoo, xM_FooTypeMetadata, xM_FooTypeBar
+ })));
+
+ XURI[] graphsBar = xDMA.getMetadataGraphsWithType(bar);
+ assure("getMetadataGraphsWithType",
+ graphsBar.length == 1 && eq(graphsBar[0], xFoo));
+
+
+ xDMA.removeMetadataFile(xFoo);
+ xStmtsEnum = xManifest.getStatements(null, null, null);
+ assure("removeMetadataFile",
+ eq(xStmtsEnum, manifestStmts));
+
+ log.println("...done");
+
+ log.println("Checking mapping...");
+
+ XEnumerationAccess xTextEnum = (XEnumerationAccess)
+ UnoRuntime.queryInterface(XEnumerationAccess.class,
+ xText.getText());
+ Object o = xTextEnum.createEnumeration().nextElement();
+ XMetadatable xMeta1 = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, o);
+
+ XURI uri;
+ XMetadatable xMeta;
+ xMeta = xDMA.getElementByURI(xMeta1);
+ assure("getElementByURI: null", null != xMeta);
+ String XmlId = xMeta.getMetadataReference().Second;
+ String XmlId1 = xMeta1.getMetadataReference().Second;
+ assure("getElementByURI: no xml id", !XmlId.equals(""));
+ assure("getElementByURI: different xml id", XmlId.equals(XmlId1));
+
+ log.println("...done");
+
+ log.println("Checking storing and loading...");
+
+ XURI xFoobar = URI.createNS(xContext, xBaseURI.getStringValue(),
+ fooBarPath);
+ Statement[] metadataStmts = getMetadataFileStmts(xBaseURI,
+ fooBarPath);
+ xDMA.addMetadataFile(fooBarPath, new XURI[0]);
+ xStmtsEnum = xRep.getStatements(null, null, null);
+ assure("addMetadataFile",
+ eq(xStmtsEnum, merge(manifestStmts, metadataStmts )));
+
+ Statement xFoobar_FooBarFoo =
+ new Statement(foo, bar, foo, xFoobar);
+ xRep.getGraph(xFoobar).addStatement(foo, bar, foo);
+ xStmtsEnum = xRep.getStatements(null, null, null);
+ assure("addStatement",
+ eq(xStmtsEnum, merge(manifestStmts, merge(metadataStmts,
+ new Statement[] { xFoobar_FooBarFoo }))));
+
+ PropertyValue noMDNoContentFile = new PropertyValue();
+ noMDNoContentFile.Name = "URL";
+ noMDNoContentFile.Value = util.utils.getFullTestURL("CUSTOM.odt");
+ PropertyValue noMDFile = new PropertyValue();
+ noMDFile.Name = "URL";
+ noMDFile.Value = util.utils.getFullTestURL("TEST.odt");
+ PropertyValue file = new PropertyValue();
+ file.Name = "URL";
+ file.Value = tempDir + "TESTDMA.odt";
+ /*
+ PropertyValue baseURL = new PropertyValue();
+ baseURL.Name = "DocumentBaseURL";
+ baseURL.Value = tempDir + "TMP.odt";
+ */
+ PropertyValue mimetype = new PropertyValue();
+ mimetype.Name = "MediaType";
+ mimetype.Value = "application/vnd.oasis.opendocument.text";
+ PropertyValue[] argsEmptyNoContent = { mimetype, noMDNoContentFile};
+ PropertyValue[] argsEmpty = { mimetype, noMDFile };
+ PropertyValue[] args = { mimetype, file };
+
+ xStmtsEnum = xRep.getStatements(null, null, null);
+ XURI[] graphs = xRep.getGraphNames();
+
+ xDMA.storeMetadataToMedium(args);
+
+ // this should re-init
+ xDMA.loadMetadataFromMedium(argsEmptyNoContent);
+ xRep = xRS.getRDFRepository();
+ assure("xRep null", null != xRep);
+ assure("baseURI still tdoc?",
+ !baseURI.equals(xDMA.getStringValue()));
+ Statement[] manifestStmts2 = getManifestStmts((XURI) xDMA);
+ xStmtsEnum = xRep.getStatements(null, null, null);
+ // there is no content or styles file in here, so we have just
+ // the package stmt
+ assure("loadMetadataFromMedium (no metadata, no content)",
+ eq(xStmtsEnum, new Statement[] { manifestStmts2[0] }));
+
+ // this should re-init
+ xDMA.loadMetadataFromMedium(argsEmpty);
+ xRep = xRS.getRDFRepository();
+ assure("xRep null", null != xRep);
+ assure("baseURI still tdoc?",
+ !baseURI.equals(xDMA.getStringValue()));
+ Statement[] manifestStmts3 = getManifestStmts((XURI) xDMA);
+
+ xStmtsEnum = xRep.getStatements(null, null, null);
+ assure("loadMetadataFromMedium (no metadata)",
+ eq(xStmtsEnum, manifestStmts3));
+
+ xDMA.loadMetadataFromMedium(args);
+ xRep = xRS.getRDFRepository();
+ assure("xRep null", null != xRep);
+ Statement[] manifestStmts4 = getManifestStmts((XURI) xDMA);
+ Statement[] metadataStmts4 = getMetadataFileStmts((XURI) xDMA,
+ fooBarPath);
+
+ xStmtsEnum = xRep.getStatements(null, null, null);
+ assure("some graph(s) not reloaded",
+ graphs.length == xRep.getGraphNames().length);
+
+ XURI xFoobar4 = URI.createNS(xContext, xDMA.getStringValue(),
+ fooBarPath);
+ Statement xFoobar_FooBarFoo4 =
+ new Statement(foo, bar, foo, xFoobar4);
+ assure("loadMetadataFromMedium (re-load)",
+ eq(xStmtsEnum, merge(manifestStmts4, merge(metadataStmts4,
+ new Statement[] { xFoobar_FooBarFoo4 }))));
+
+ log.println("...done");
+
+ log.println("Checking storing and loading via model...");
+
+ String f = tempDir + "TESTPARA.odt";
+
+ XStorable xStor = (XStorable) UnoRuntime.queryInterface(
+ XStorable.class, xRS);
+
+ xStor.storeToURL(f, new PropertyValue[0]);
+
+ xComp2 = util.DesktopTools.loadDoc(xMSF, f, loadProps);
+
+ XDocumentMetadataAccess xDMA2 = (XDocumentMetadataAccess)
+ UnoRuntime.queryInterface(XDocumentMetadataAccess.class,
+ xComp2);
+ assure("xDMA2 null", null != xDMA2);
+
+ XRepositorySupplier xRS2 = (XRepositorySupplier)
+ UnoRuntime.queryInterface(XRepositorySupplier.class, xComp2);
+ assure("xRS2 null", null != xRS2);
+
+ XRepository xRep2 = xRS2.getRDFRepository();
+ assure("xRep2 null", null != xRep2);
+
+ Statement[] manifestStmts5 = getManifestStmts((XURI) xDMA2);
+ Statement[] metadataStmts5 = getMetadataFileStmts((XURI) xDMA2,
+ fooBarPath);
+ XURI xFoobar5 = URI.createNS(xContext, xDMA2.getStringValue(),
+ fooBarPath);
+ Statement xFoobar_FooBarFoo5 =
+ new Statement(foo, bar, foo, xFoobar5);
+ xStmtsEnum = xRep.getStatements(null, null, null);
+ XEnumeration xStmtsEnum2 = xRep2.getStatements(null, null, null);
+ assure("load: repository differs",
+ eq(xStmtsEnum2, merge(manifestStmts5, merge(metadataStmts5,
+ new Statement[] { xFoobar_FooBarFoo5 }))));
+
+ log.println("...done");
+
+ } catch (Exception e) {
+ report(e);
+ } finally {
+ close(xComp);
+ close(xComp2);
+ }
+ }
+
+ public void checkRDFa()
+ {
+ XComponent xComp = null;
+ String file;
+ try {
+ file = util.utils.getFullTestURL("TESTRDFA.odt");
+ xComp = loadRDFa(file);
+ if (xComp != null)
+ {
+ file = tempDir + "TESTRDFA.odt";
+ storeRDFa(xComp, file);
+ close(xComp);
+ xComp = loadRDFa(file);
+ }
+ } finally {
+ close(xComp);
+ }
+ }
+
+ public void storeRDFa(XComponent xComp, String file)
+ {
+ try {
+
+ log.println("Storing test document...");
+
+ XStorable xStor = (XStorable) UnoRuntime.queryInterface(
+ XStorable.class, xComp);
+
+ xStor.storeToURL(file, new PropertyValue[0]);
+
+ log.println("...done");
+
+ } catch (Exception e) {
+ report(e);
+ }
+ }
+
+ public XComponent loadRDFa(String file)
+ {
+ XComponent xComp = null;
+ try {
+
+ log.println("Loading test document...");
+
+ PropertyValue[] loadProps = new PropertyValue[1];
+ loadProps[0] = new PropertyValue();
+ loadProps[0].Name = "Hidden";
+ loadProps[0].Value = new Boolean(true);
+
+
+
+ xComp = util.DesktopTools.loadDoc(xMSF, file, loadProps);
+
+ XRepositorySupplier xRS = (XRepositorySupplier)
+ UnoRuntime.queryInterface(XRepositorySupplier.class, xComp);
+ assure("xRS null", null != xRS);
+
+ XDocumentRepository xRep = (XDocumentRepository)
+ UnoRuntime.queryInterface(XDocumentRepository.class,
+ xRS.getRDFRepository());
+ assure("xRep null", null != xRep);
+
+ XTextDocument xTextDoc = (XTextDocument)
+ UnoRuntime.queryInterface(XTextDocument.class, xComp);
+
+ XText xText = xTextDoc.getText();
+
+ XEnumerationAccess xEA = (XEnumerationAccess)
+ UnoRuntime.queryInterface(XEnumerationAccess.class, xText);
+ XEnumeration xEnum = xEA.createEnumeration();
+
+ log.println("...done");
+
+ log.println("Checking RDFa in loaded test document...");
+
+ XMetadatable xPara;
+ Statement[] stmts;
+
+ Statement x_FooBarLit1 = new Statement(foo, bar, mkLit("1"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 1",
+ eq(stmts, new Statement[] {
+ x_FooBarLit1
+ }));
+
+ Statement x_FooBarLit2 = new Statement(foo, bar, mkLit("2"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 2",
+ eq(stmts, new Statement[] {
+ x_FooBarLit2
+ }));
+
+ Statement x_BlankBarLit3 =
+ new Statement(blank1, bar, mkLit("3"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 3",
+ eq(stmts, new Statement[] {
+ x_BlankBarLit3
+ }));
+ XBlankNode b3 = (XBlankNode) UnoRuntime.queryInterface(
+ XBlankNode.class, stmts[0].Subject);
+
+ Statement x_BlankBarLit4 =
+ new Statement(blank2, bar, mkLit("4"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 4",
+ eq(stmts, new Statement[] {
+ x_BlankBarLit4
+ }));
+ XBlankNode b4 = (XBlankNode) UnoRuntime.queryInterface(
+ XBlankNode.class, stmts[0].Subject);
+
+ Statement x_BlankBarLit5 =
+ new Statement(blank1, bar, mkLit("5"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 5",
+ eq(stmts, new Statement[] {
+ x_BlankBarLit5
+ }));
+ XBlankNode b5 = (XBlankNode) UnoRuntime.queryInterface(
+ XBlankNode.class, stmts[0].Subject);
+
+ assure("RDFa: 3 != 4",
+ !b3.getStringValue().equals(b4.getStringValue()));
+ assure("RDFa: 3 == 5",
+ b3.getStringValue().equals(b5.getStringValue()));
+
+ Statement x_FooBarLit6 = new Statement(foo, bar, mkLit("6"), null);
+ Statement x_FooBazLit6 = new Statement(foo, baz, mkLit("6"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 6",
+ eq(stmts, new Statement[] {
+ x_FooBarLit6, x_FooBazLit6
+ }));
+
+ Statement x_FooBarLit7 = new Statement(foo, bar, mkLit("7"), null);
+ Statement x_FooBazLit7 = new Statement(foo, baz, mkLit("7"), null);
+ Statement x_FooFooLit7 = new Statement(foo, foo, mkLit("7"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 7",
+ eq(stmts, new Statement[] {
+ x_FooBarLit7, x_FooBazLit7, x_FooFooLit7
+ }));
+
+ XNode lit = mkLit("a fooish bar");
+ XNode lit_type= mkLit("a fooish bar", bar);
+ Statement x_FooBarLit = new Statement(foo, bar, lit, null);
+ Statement x_FooBarLittype = new Statement(foo, bar, lit_type, null);
+
+ Statement x_FooLabelLit8 =
+ new Statement(foo, rdfs_label, mkLit("8"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 8",
+ eq(stmts, new Statement[] {
+ x_FooBarLit, x_FooLabelLit8
+ }));
+
+ Statement x_FooLabelLit9 =
+ new Statement(foo, rdfs_label, mkLit("9"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 9",
+ eq(stmts, new Statement[] {
+ x_FooBarLit, x_FooLabelLit9
+ }));
+
+ Statement x_FooLabelLit10 =
+ new Statement(foo, rdfs_label, mkLit("10"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 10",
+ eq(stmts, new Statement[] {
+ x_FooBarLittype, x_FooLabelLit10
+ }));
+
+ Statement x_FooBarLit11
+ = new Statement(foo, bar, mkLit("11", bar), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 11",
+ eq(stmts, new Statement[] {
+ x_FooBarLit11
+ }));
+
+ XURI xFile = URI.createNS(xContext, file, "/" + contentPath);
+ Statement x_FileBarLit12 =
+ new Statement(xFile, bar, mkLit("12"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 12",
+ eq(stmts, new Statement[] {
+ x_FileBarLit12
+ }));
+
+ Statement x_FooLabelLit13 =
+ new Statement(foo, rdfs_label, mkLit("13"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 13",
+ eq(stmts, new Statement[] {
+ x_FooBarLit, x_FooLabelLit13
+ }));
+
+ Statement x_FooLabelLit14 =
+ new Statement(foo, rdfs_label, mkLit("14"), null);
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 14",
+ eq(stmts, new Statement[] {
+ x_FooBarLit, x_FooLabelLit14
+ }));
+
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 15", eq(stmts, new Statement[] { } ));
+
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 16", eq(stmts, new Statement[] { } ));
+
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 17", eq(stmts, new Statement[] { } ));
+
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 18", eq(stmts, new Statement[] { } ));
+
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 19", eq(stmts, new Statement[] { } ));
+
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 20", eq(stmts, new Statement[] { } ));
+
+ xPara = (XMetadatable) UnoRuntime.queryInterface(
+ XMetadatable.class, xEnum.nextElement());
+ stmts = xRep.getStatementRDFa(xPara);
+ assure("RDFa: 21", eq(stmts, new Statement[] { } ));
+
+ log.println("...done");
+
+ } catch (Exception e) {
+ report(e);
+ close(xComp);
+ }
+ return xComp;
+ }
+
+
+// utilities -------------------------------------------------------------
+
+ public void report2(Exception e)
+ {
+ if (e instanceof WrappedTargetException)
+ {
+ log.println("Cause:");
+ Exception cause = (Exception)
+ (((WrappedTargetException)e).TargetException);
+ log.println(cause.toString());
+ report2(cause);
+ } else if (e instanceof WrappedTargetRuntimeException) {
+ log.println("Cause:");
+ Exception cause = (Exception)
+ (((WrappedTargetRuntimeException)e).TargetException);
+ log.println(cause.toString());
+ report2(cause);
+ }
+ }
+
+ public void report(Exception e) {
+ log.println("Exception occurred:");
+ e.printStackTrace((java.io.PrintWriter) log);
+ report2(e);
+ failed();
+ }
+
+ static void close(XComponent i_comp)
+ {
+ try {
+ XCloseable xClos = (XCloseable) UnoRuntime.queryInterface(
+ XCloseable.class, i_comp);
+ if (xClos != null) xClos.close(true);
+ } catch (Exception e) {
+ }
+ }
+
+ XLiteral mkLit(String i_content)
+ {
+ return Literal.create(xContext, i_content);
+ }
+
+ XLiteral mkLit(String i_content, XURI i_uri)
+ {
+ return Literal.createWithType(xContext, i_content, i_uri);
+ }
+
+ static Statement[] merge(Statement[] i_A1, Statement[] i_A2)
+ {
+ // bah, java sucks...
+ Statement[] ret = new Statement[i_A1.length + i_A2.length];
+ for (int i = 0; i < i_A1.length; ++i) {
+ ret[i] = i_A1[i];
+ }
+ for (int i = 0; i < i_A2.length; ++i) {
+ ret[i+i_A1.length] = i_A2[i];
+ }
+ return ret;
+ }
+
+ public static String toS(XNode n) {
+ if (null == n) return "< null >";
+ return n.getStringValue();
+ }
+
+ static boolean isBlank(XNode i_node)
+ {
+ XBlankNode blank = (XBlankNode) UnoRuntime.queryInterface(
+ XBlankNode.class, i_node);
+ return blank != null;
+ }
+
+/*
+ static class Statement implements XStatement
+ {
+ XResource m_Subject;
+ XResource m_Predicate;
+ XNode m_Object;
+ XURI m_Graph;
+
+ Statement(XResource i_Subject, XResource i_Predicate, XNode i_Object,
+ XURI i_Graph)
+ {
+ m_Subject = i_Subject;
+ m_Predicate = i_Predicate;
+ m_Object = i_Object;
+ m_Graph = i_Graph;
+ }
+
+ public XResource getSubject() { return m_Subject; }
+ public XResource getPredicate() { return m_Predicate; }
+ public XNode getObject() { return m_Object; }
+ public XURI getGraph() { return m_Graph; }
+ }
+*/
+
+ static Statement[] toSeq(XEnumeration i_Enum) throws Exception
+ {
+ java.util.Collection c = new java.util.Vector();
+ while (i_Enum.hasMoreElements()) {
+ Statement s = (Statement) i_Enum.nextElement();
+//log.println("toSeq: " + s.getSubject().getStringValue() + " " + s.getPredicate().getStringValue() + " " + s.getObject().getStringValue() + ".");
+ c.add(s);
+ }
+// return (Statement[]) c.toArray();
+ // java sucks
+ Object[] arr = c.toArray();
+ Statement[] ret = new Statement[arr.length];
+ for (int i = 0; i < arr.length; ++i) {
+ ret[i] = (Statement) arr[i];
+ }
+ return ret;
+ }
+
+ static XNode[][] toSeqs(XEnumeration i_Enum) throws Exception
+ {
+ java.util.Collection c = new java.util.Vector();
+ while (i_Enum.hasMoreElements()) {
+ XNode[] s = (XNode[]) i_Enum.nextElement();
+ c.add(s);
+ }
+// return (XNode[][]) c.toArray();
+ Object[] arr = c.toArray();
+ XNode[][] ret = new XNode[arr.length][];
+ for (int i = 0; i < arr.length; ++i) {
+ ret[i] = (XNode[]) arr[i];
+ }
+ return ret;
+ }
+
+ static class BindingComp implements java.util.Comparator
+ {
+ public int compare(Object i_Left, Object i_Right)
+ {
+ XNode[] left = (XNode[]) i_Left;
+ XNode[] right = (XNode[]) i_Right;
+ if (left.length != right.length) throw new RuntimeException();
+ for (int i = 0; i < left.length; ++i) {
+ int eq = (left[i].getStringValue().compareTo(
+ right[i].getStringValue()));
+ if (eq != 0) return eq;
+ }
+ return 0;
+ }
+ }
+
+ static class StmtComp implements java.util.Comparator
+ {
+ public int compare(Object i_Left, Object i_Right)
+ {
+ int eq;
+ Statement left = (Statement) i_Left;
+ Statement right = (Statement) i_Right;
+ if ((eq = cmp(left.Graph, right.Graph )) != 0) return eq;
+ if ((eq = cmp(left.Subject, right.Subject )) != 0) return eq;
+ if ((eq = cmp(left.Predicate, right.Predicate)) != 0) return eq;
+ if ((eq = cmp(left.Object, right.Object )) != 0) return eq;
+ return 0;
+ }
+
+ public int cmp(XNode i_Left, XNode i_Right)
+ {
+ if (isBlank(i_Left)) {
+ return isBlank(i_Right) ? 0 : 1;
+ } else {
+ if (isBlank(i_Right)) {
+ return -1;
+ } else {
+ return toS(i_Left).compareTo(toS(i_Right));
+ }
+ }
+ }
+ }
+
+ static boolean eq(Statement i_Left, Statement i_Right)
+ {
+ XURI lG = i_Left.Graph;
+ XURI rG = i_Right.Graph;
+ if (!eq(lG, rG)) {
+ log.println("Graphs differ: " + toS(lG) + " != " + toS(rG));
+ return false;
+ }
+ if (!eq(i_Left.Subject, i_Right.Subject)) {
+ log.println("Subjects differ: " +
+ i_Left.Subject.getStringValue() + " != " +
+ i_Right.Subject.getStringValue());
+ return false;
+ }
+ if (!eq(i_Left.Predicate, i_Right.Predicate)) {
+ log.println("Predicates differ: " +
+ i_Left.Predicate.getStringValue() + " != " +
+ i_Right.Predicate.getStringValue());
+ return false;
+ }
+ if (!eq(i_Left.Object, i_Right.Object)) {
+ log.println("Objects differ: " +
+ i_Left.Object.getStringValue() + " != " +
+ i_Right.Object.getStringValue());
+ return false;
+ }
+ return true;
+ }
+
+ static boolean eq(Statement[] i_Result, Statement[] i_Expected)
+ {
+ if (i_Result.length != i_Expected.length) {
+ log.println("eq: different lengths: " + i_Result.length + " " +
+ i_Expected.length);
+ return false;
+ }
+ Statement[] expected = (Statement[])
+ java.util.Arrays.asList(i_Expected).toArray();
+ java.util.Arrays.sort(i_Result, new StmtComp());
+ java.util.Arrays.sort(expected, new StmtComp());
+ for (int i = 0; i < expected.length; ++i) {
+ if (!eq(i_Result[i], expected[i])) return false;
+ }
+ return true;
+ }
+
+ static boolean eq(XEnumeration i_Enum, Statement[] i_Expected)
+ throws Exception
+ {
+ Statement[] current = toSeq(i_Enum);
+ return eq(current, i_Expected);
+ }
+
+ static boolean eq(XNode i_Left, XNode i_Right)
+ {
+ if (i_Left == null) {
+ return (i_Right == null);
+ } else {
+ return (i_Right != null) &&
+ (i_Left.getStringValue().equals(i_Right.getStringValue())
+ // FIXME: hack: blank nodes considered equal
+ || (isBlank(i_Left) && isBlank(i_Right)));
+ }
+ }
+
+ static boolean eq(XQuerySelectResult i_Result,
+ String[] i_Vars, XNode[][] i_Bindings) throws Exception
+ {
+ String[] vars = (String[]) i_Result.getBindingNames();
+ XEnumeration iter = (XEnumeration) i_Result;
+ XNode[][] bindings = toSeqs(iter);
+ if (vars.length != i_Vars.length) {
+ log.println("var lengths differ");
+ return false;
+ }
+ if (bindings.length != i_Bindings.length) {
+ log.println("binding lengths differ: " + i_Bindings.length +
+ " vs " + bindings.length );
+ return false;
+ }
+ java.util.Arrays.sort(bindings, new BindingComp());
+ java.util.Arrays.sort(i_Bindings, new BindingComp());
+ for (int i = 0; i < i_Bindings.length; ++i) {
+ if (i_Bindings[i].length != i_Vars.length) {
+ log.println("TEST ERROR!");
+ throw new Exception();
+ }
+ if (bindings[i].length != i_Vars.length) {
+ log.println("binding length and var length differ");
+ return false;
+ }
+ for (int j = 0; j < i_Vars.length; ++j) {
+ if (!eq(bindings[i][j], i_Bindings[i][j])) {
+ log.println("bindings differ: " +
+ toS(bindings[i][j]) + " != " + toS(i_Bindings[i][j]));
+ return false;
+ }
+ }
+ }
+ for (int i = 0; i < i_Vars.length; ++i) {
+ if (!vars[i].equals(i_Vars[i])) {
+ log.println("variable names differ: " +
+ vars[i] + " != " + i_Vars[i]);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static boolean eq(StringPair i_Left, StringPair i_Right)
+ {
+ return ((i_Left.First).equals(i_Right.First)) &&
+ ((i_Left.Second).equals(i_Right.Second));
+ }
+
+ static String mkNamespace(String i_prefix, String i_namespace)
+ {
+ return "PREFIX " + i_prefix + ": <" + i_namespace + ">\n";
+ }
+
+ static String mkNss()
+ {
+ String namespaces = mkNamespace("rdf",
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
+ namespaces += mkNamespace("pkg",
+ "http://docs.oasis-open.org/opendocument/meta/package/common#");
+ namespaces += mkNamespace("odf",
+ "http://docs.oasis-open.org/opendocument/meta/package/odf#");
+ return namespaces;
+ }
+
+ Statement[] getManifestStmts(XURI xBaseURI) throws Exception
+ {
+ XURI xManifest = URI.createNS(xContext, xBaseURI.getStringValue(),
+ manifestPath);
+ XURI xContent = URI.createNS(xContext, xBaseURI.getStringValue(),
+ contentPath);
+ XURI xStyles = URI.createNS(xContext, xBaseURI.getStringValue(),
+ stylesPath);
+ Statement xM_BaseTypeDoc =
+ new Statement(xBaseURI, rdf_type, pkg_Document, xManifest);
+ Statement xM_BaseHaspartContent =
+ new Statement(xBaseURI, pkg_hasPart, xContent, xManifest);
+ Statement xM_BaseHaspartStyles =
+ new Statement(xBaseURI, pkg_hasPart, xStyles, xManifest);
+ Statement xM_ContentTypeContent =
+ new Statement(xContent, rdf_type, odf_ContentFile, xManifest);
+ Statement xM_StylesTypeStyles =
+ new Statement(xStyles, rdf_type, odf_StylesFile, xManifest);
+ return new Statement[] {
+ xM_BaseTypeDoc, xM_BaseHaspartContent, xM_BaseHaspartStyles,
+ xM_ContentTypeContent, xM_StylesTypeStyles
+ };
+ }
+
+ Statement[] getMetadataFileStmts(XURI xBaseURI, String Path)
+ throws Exception
+ {
+ XURI xManifest = URI.createNS(xContext, xBaseURI.getStringValue(),
+ manifestPath);
+ XURI xGraph = URI.createNS(xContext, xBaseURI.getStringValue(), Path);
+ Statement xM_BaseHaspartGraph =
+ new Statement(xBaseURI, pkg_hasPart, xGraph, xManifest);
+ Statement xM_GraphTypeMetadata =
+ new Statement(xGraph, rdf_type, pkg_MetadataFile, xManifest);
+ return new Statement[] { xM_BaseHaspartGraph, xM_GraphTypeMetadata };
+ }
+
+ class TestRange implements XTextRange, XMetadatable, XServiceInfo
+ {
+ String m_Stream;
+ String m_XmlId;
+ String m_Text;
+ TestRange(String i_Str) { m_Text = i_Str; }
+
+ public String getStringValue() { return ""; }
+ public String getNamespace() { return ""; }
+ public String getLocalName() { return ""; }
+
+ public StringPair getMetadataReference()
+ { return new StringPair(m_Stream, m_XmlId); }
+ public void setMetadataReference(StringPair i_Ref)
+ throws IllegalArgumentException
+ { m_Stream = (String)i_Ref.First; m_XmlId = (String)i_Ref.Second; }
+ public void ensureMetadataReference()
+ { m_Stream = "content.xml"; m_XmlId = "42"; }
+
+ public String getImplementationName() { return null; }
+ public String[] getSupportedServiceNames() { return null; }
+ public boolean supportsService(String i_Svc)
+ { return i_Svc.equals("com.sun.star.text.Paragraph"); }
+
+ public XText getText() { return null; }
+ public XTextRange getStart() { return null; }
+ public XTextRange getEnd() { return null; }
+ public String getString() { return m_Text; }
+ public void setString(String i_Str) { m_Text = i_Str; }
+ }
+}
+
diff --git a/sfx2/qa/complex/makefile.mk b/sfx2/qa/complex/makefile.mk
index 102c641f2732..5c0006df9e04 100644
--- a/sfx2/qa/complex/makefile.mk
+++ b/sfx2/qa/complex/makefile.mk
@@ -42,7 +42,9 @@ PACKAGE = complex$/framework
JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar
JAVAFILES = CheckGlobalEventBroadcaster_writer1.java \
- DocumentMetaData.java
+ DocumentMetaData.java \
+ DocumentMetadataAccessTest.java
+
JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class)
SUBDIRS = DocHelper
diff --git a/sfx2/qa/complex/testdocuments/TESTRDFA.odt b/sfx2/qa/complex/testdocuments/TESTRDFA.odt
new file mode 100644
index 000000000000..d59739142df6
--- /dev/null
+++ b/sfx2/qa/complex/testdocuments/TESTRDFA.odt
Binary files differ
diff --git a/sfx2/qa/complex/tests.sce b/sfx2/qa/complex/tests.sce
index e95f6db8848d..c38852927ede 100644
--- a/sfx2/qa/complex/tests.sce
+++ b/sfx2/qa/complex/tests.sce
@@ -1,2 +1,3 @@
-o complex.framework.DocumentMetaData
+-o complex.framework.DocumentMetadataAccessTest
#-o complex.framework.CheckGlobalEventBroadcaster_writer1
diff --git a/sfx2/sdi/sfxslots.sdi b/sfx2/sdi/sfxslots.sdi
index c7667f36c02e..27336865be73 100644
--- a/sfx2/sdi/sfxslots.sdi
+++ b/sfx2/sdi/sfxslots.sdi
@@ -88,14 +88,6 @@ TypeLibFile( "sfxslots.tlb" )
INT32 AutoReloadTime MID_DOCINFO_AUTOLOADSECS;
String AutoReloadURL MID_DOCINFO_AUTOLOADURL;
String AutoReloadFrame MID_DOCINFO_DEFAULTTARGET;
- String Field1Title MID_DOCINFO_FIELD1TITLE;
- String Field2Title MID_DOCINFO_FIELD2TITLE;
- String Field3Title MID_DOCINFO_FIELD3TITLE;
- String Field4Title MID_DOCINFO_FIELD4TITLE;
- String Field1 MID_DOCINFO_FIELD1;
- String Field2 MID_DOCINFO_FIELD2;
- String Field3 MID_DOCINFO_FIELD3;
- String Field4 MID_DOCINFO_FIELD4;
};
item DocInfo SfxDocumentInfoItem;
diff --git a/sfx2/source/bastyp/progress.cxx b/sfx2/source/bastyp/progress.cxx
index 22a3be63dc19..62bc5533e1a9 100644
--- a/sfx2/source/bastyp/progress.cxx
+++ b/sfx2/source/bastyp/progress.cxx
@@ -117,7 +117,7 @@ struct SfxProgress_Impl : public SfxCancellable
#define aTypeLibInfo aProgressTypeLibImpl
//========================================================================
-#if (_MSC_VER < 1300)
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
inline ULONG Get10ThSec()
{
#if defined (MSC) && defined (WIN)
diff --git a/sfx2/source/dialog/dinfdlg.cxx b/sfx2/source/dialog/dinfdlg.cxx
index cb442caa6f1f..6de52384a90c 100644
--- a/sfx2/source/dialog/dinfdlg.cxx
+++ b/sfx2/source/dialog/dinfdlg.cxx
@@ -223,9 +223,9 @@ SfxDocumentInfoItem::SfxDocumentInfoItem()
, m_Keywords()
, m_Subject()
, m_Title()
- , bHasTemplate( sal_True )
- , bDeleteUserData( sal_False )
- , bIsUseUserData( sal_True )
+ , m_bHasTemplate( sal_True )
+ , m_bDeleteUserData( sal_False )
+ , m_bUseUserData( sal_True )
{
}
@@ -253,9 +253,9 @@ SfxDocumentInfoItem::SfxDocumentInfoItem( const String& rFile,
i_xDocProps->getKeywords()) )
, m_Subject( i_xDocProps->getSubject() )
, m_Title( i_xDocProps->getTitle() )
- , bHasTemplate( TRUE )
- , bDeleteUserData( sal_False )
- , bIsUseUserData( bIs )
+ , m_bHasTemplate( sal_True )
+ , m_bDeleteUserData( sal_False )
+ , m_bUseUserData( bIs )
{
try
{
@@ -302,15 +302,10 @@ SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem& rItem )
, m_Keywords( rItem.getKeywords() )
, m_Subject( rItem.getSubject() )
, m_Title( rItem.getTitle() )
- , bHasTemplate( rItem.bHasTemplate )
- , bDeleteUserData( rItem.bDeleteUserData )
- , bIsUseUserData( rItem.bIsUseUserData )
+ , m_bHasTemplate( rItem.m_bHasTemplate )
+ , m_bDeleteUserData( rItem.m_bDeleteUserData )
+ , m_bUseUserData( rItem.m_bUseUserData )
{
- for (size_t i = 0; i < 4; ++i) {
- m_UserDefinedFieldTitles[i] = rItem.getUserDefinedFieldTitle(i);
- m_UserDefinedFieldValues[i] = rItem.getUserDefinedFieldValue(i);
- }
-
for ( sal_uInt32 i = 0; i < rItem.m_aCustomProperties.size(); i++ )
{
CustomProperty* pProp = new CustomProperty( rItem.m_aCustomProperties[i]->m_sName,
@@ -384,8 +379,9 @@ void SfxDocumentInfoItem::resetUserData(const ::rtl::OUString & i_rAuthor)
//------------------------------------------------------------------------
-void SfxDocumentInfoItem::updateDocumentInfo(
- const uno::Reference<document::XDocumentProperties>& i_xDocProps) const
+void SfxDocumentInfoItem::UpdateDocumentInfo(
+ const uno::Reference<document::XDocumentProperties>& i_xDocProps,
+ bool i_bDoNotUpdateUserDefined) const
{
if (isAutoloadEnabled()) {
i_xDocProps->setAutoloadSecs(getAutoloadDelay());
@@ -410,6 +406,15 @@ void SfxDocumentInfoItem::updateDocumentInfo(
i_xDocProps->setSubject(getSubject());
i_xDocProps->setTitle(getTitle());
+ // this is necessary in case of replaying a recorded macro:
+ // in this case, the macro may contain the 4 old user-defined DocumentInfo
+ // fields, but not any of the DocumentInfo properties;
+ // as a consequence, most of the UserDefined properties of the
+ // DocumentProperties would be summarily deleted here, which does not
+ // seem like a good idea.
+ if (i_bDoNotUpdateUserDefined)
+ return;
+
try
{
Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties();
@@ -442,24 +447,24 @@ void SfxDocumentInfoItem::updateDocumentInfo(
//------------------------------------------------------------------------
-BOOL SfxDocumentInfoItem::IsDeleteUserData() const
+sal_Bool SfxDocumentInfoItem::IsDeleteUserData() const
{
- return bDeleteUserData;
+ return m_bDeleteUserData;
}
-void SfxDocumentInfoItem::SetDeleteUserData( BOOL bSet )
+void SfxDocumentInfoItem::SetDeleteUserData( sal_Bool bSet )
{
- bDeleteUserData = bSet;
+ m_bDeleteUserData = bSet;
}
-BOOL SfxDocumentInfoItem::IsUseUserData() const
+sal_Bool SfxDocumentInfoItem::IsUseUserData() const
{
- return bIsUseUserData;
+ return m_bUseUserData;
}
-void SfxDocumentInfoItem::SetUseUserData( BOOL bSet )
+void SfxDocumentInfoItem::SetUseUserData( sal_Bool bSet )
{
- bIsUseUserData = bSet;
+ m_bUseUserData = bSet;
}
std::vector< CustomProperty* > SfxDocumentInfoItem::GetCustomProperties() const
@@ -488,38 +493,11 @@ void SfxDocumentInfoItem::AddCustomProperty( const ::rtl::OUString& sName, const
m_aCustomProperties.push_back( pProp );
}
-::rtl::OUString SfxDocumentInfoItem::getUserDefinedFieldTitle(size_t i_ix) const
-{
- DBG_ASSERT(i_ix < 4, "SfxDocumentInfoItem: invalid index");
- return m_UserDefinedFieldTitles[i_ix];
-}
-
-::rtl::OUString SfxDocumentInfoItem::getUserDefinedFieldValue(size_t i_ix) const
-{
- DBG_ASSERT(i_ix < 4, "SfxDocumentInfoItem: invalid index");
- return m_UserDefinedFieldValues[i_ix];
-}
-
-void SfxDocumentInfoItem::setUserDefinedFieldTitle(size_t i_ix,
- ::rtl::OUString i_val)
-{
- DBG_ASSERT(i_ix < 4, "SfxDocumentInfoItem: invalid index");
- m_UserDefinedFieldTitles[i_ix] = i_val;
-}
-
-void SfxDocumentInfoItem::setUserDefinedFieldValue(size_t i_ix,
- ::rtl::OUString i_val)
-{
- DBG_ASSERT(i_ix < 4, "SfxDocumentInfoItem: invalid index");
- m_UserDefinedFieldValues[i_ix] = i_val;
-}
-
sal_Bool SfxDocumentInfoItem::QueryValue( Any& rVal, BYTE nMemberId ) const
{
String aValue;
sal_Int32 nValue = 0;
sal_Bool bValue = sal_False;
- BOOL bField = FALSE;
BOOL bIsInt = FALSE;
BOOL bIsString = FALSE;
nMemberId &= ~CONVERT_TWIPS;
@@ -562,43 +540,6 @@ sal_Bool SfxDocumentInfoItem::QueryValue( Any& rVal, BYTE nMemberId ) const
bIsString = TRUE;
aValue = getTitle();
break;
- case MID_DOCINFO_FIELD1:
- case MID_DOCINFO_FIELD2:
- case MID_DOCINFO_FIELD3:
- case MID_DOCINFO_FIELD4:
- bField = TRUE;
- // no break here
- case MID_DOCINFO_FIELD1TITLE:
- case MID_DOCINFO_FIELD2TITLE:
- case MID_DOCINFO_FIELD3TITLE:
- case MID_DOCINFO_FIELD4TITLE:
- {
- bIsString = TRUE;
- USHORT nSub = MID_DOCINFO_FIELD1TITLE;
- if ( bField )
- {
- nSub = MID_DOCINFO_FIELD1;
- }
- if ( bField )
- {
- DBG_ASSERT( nMemberId == MID_DOCINFO_FIELD1 ||
- nMemberId == MID_DOCINFO_FIELD2 ||
- nMemberId == MID_DOCINFO_FIELD3 ||
- nMemberId == MID_DOCINFO_FIELD4,
- "SfxDocumentInfoItem:Anpassungsfehler" );
- aValue = getUserDefinedFieldValue( nMemberId - nSub );
- }
- else
- {
- DBG_ASSERT( nMemberId == MID_DOCINFO_FIELD1TITLE ||
- nMemberId == MID_DOCINFO_FIELD2TITLE ||
- nMemberId == MID_DOCINFO_FIELD3TITLE ||
- nMemberId == MID_DOCINFO_FIELD4TITLE,
- "SfxDocumentInfoItem:Anpassungsfehler" );
- aValue = getUserDefinedFieldTitle( nMemberId - nSub );
- }
- break;
- }
default:
DBG_ERROR("Wrong MemberId!");
return sal_False;
@@ -673,28 +614,6 @@ sal_Bool SfxDocumentInfoItem::PutValue( const Any& rVal, BYTE nMemberId )
if ( bRet )
setTitle(aValue);
break;
- case MID_DOCINFO_FIELD1TITLE:
- case MID_DOCINFO_FIELD2TITLE:
- case MID_DOCINFO_FIELD3TITLE:
- case MID_DOCINFO_FIELD4TITLE:
- {
- bRet = (rVal >>= aValue);
- if ( bRet )
- setUserDefinedFieldTitle(
- nMemberId - MID_DOCINFO_FIELD1TITLE, String(aValue));
- break;
- }
- case MID_DOCINFO_FIELD1:
- case MID_DOCINFO_FIELD2:
- case MID_DOCINFO_FIELD3:
- case MID_DOCINFO_FIELD4:
- {
- bRet = (rVal >>= aValue);
- if ( bRet )
- setUserDefinedFieldValue(
- nMemberId - MID_DOCINFO_FIELD1, String(aValue));
- break;
- }
default:
DBG_ERROR("Wrong MemberId!");
return sal_False;
@@ -1178,7 +1097,7 @@ void SfxDocumentPage::Reset( const SfxItemSet& rSet )
aFileValFt.SetText( aURL.GetPartBeforeLastName() );
// handle access data
- BOOL bIsUseUserData = pInfoItem->IsUseUserData();
+ sal_Bool m_bUseUserData = pInfoItem->IsUseUserData();
LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() );
aCreateValFt.SetText( ConvertDateTime_Impl( pInfoItem->getAuthor(),
pInfoItem->getCreationDate(), aLocaleWrapper ) );
@@ -1193,7 +1112,7 @@ void SfxDocumentPage::Reset( const SfxItemSet& rSet )
aPrintValFt.SetText( ConvertDateTime_Impl( pInfoItem->getPrintedBy(),
aTime, aLocaleWrapper ) );
const long nTime = pInfoItem->getEditingDuration();
- if( bIsUseUserData )
+ if ( m_bUseUserData )
{
const Time aT( nTime/3600, (nTime%3600)/60, nTime%60 );
aTimeLogValFt.SetText( aLocaleWrapper.getDuration( aT ) );
@@ -1201,7 +1120,7 @@ void SfxDocumentPage::Reset( const SfxItemSet& rSet )
pInfoItem->getEditingCycles() ) );
}
- TriState eState = (TriState)bIsUseUserData;
+ TriState eState = (TriState)m_bUseUserData;
if ( STATE_DONTKNOW == eState )
aUseUserDataCB.EnableTriState( TRUE );
@@ -1558,192 +1477,6 @@ int SfxInternetPage::DeactivatePage( SfxItemSet* /*pSet*/ )
//------------------------------------------------------------------------
-SfxDocumentUserPage::SfxDocumentUserPage( Window* pParent,
- const SfxItemSet& rItemSet ) :
-
- SfxTabPage( pParent, SfxResId( TP_DOCINFOUSER ), rItemSet ),
-
- bLabelModified ( FALSE ),
- aInfo1Ft ( this, SfxResId( FT_INFO1 ) ),
- aInfo1Ed ( this, SfxResId( ED_INFO1 ) ),
- aInfo2Ft ( this, SfxResId( FT_INFO2 ) ),
- aInfo2Ed ( this, SfxResId( ED_INFO2 ) ),
- aInfo3Ft ( this, SfxResId( FT_INFO3 ) ),
- aInfo3Ed ( this, SfxResId( ED_INFO3 ) ),
- aInfo4Ft ( this, SfxResId( FT_INFO4 ) ),
- aInfo4Ed ( this, SfxResId( ED_INFO4 ) ),
- aEditLabelBtn ( this, SfxResId( BTN_EDITLABEL ) ),
-
- pInfoItem ( NULL )
-
-{
- FreeResource();
- //increase button width in case of long labels
- Size aButtonSize = aEditLabelBtn.GetOutputSizePixel();
- sal_Int32 nTextWidth = aEditLabelBtn.GetTextWidth(aEditLabelBtn.GetText());
- //add some additional space
- sal_Int32 nDiff = nTextWidth + 4 - aButtonSize.Width();
- if( nDiff > 0)
- {
- Point aPos(aEditLabelBtn.GetPosPixel());
- aPos.X() -= nDiff;
- aButtonSize.Width() += nDiff;
- aEditLabelBtn.SetPosSizePixel(aPos, aButtonSize);
- }
-
- aEditLabelBtn.SetClickHdl( LINK( this, SfxDocumentUserPage, EditLabelHdl ) );
-}
-
-//------------------------------------------------------------------------
-
-IMPL_LINK( SfxDocumentUserPage, EditLabelHdl, PushButton *, pPushButton )
-{
- (void)pPushButton; //unused
- SfxDocInfoEditDlg* pDlg = new SfxDocInfoEditDlg( this );
- pDlg->SetText1( GetLabelText_Impl( &aInfo1Ft ) );
- pDlg->SetText2( GetLabelText_Impl( &aInfo2Ft ) );
- pDlg->SetText3( GetLabelText_Impl( &aInfo3Ft ) );
- pDlg->SetText4( GetLabelText_Impl( &aInfo4Ft ) );
-
- if ( RET_OK == pDlg->Execute() )
- {
- SetLabelText_Impl( &aInfo1Ft, pDlg->GetText1() );
- SetLabelText_Impl( &aInfo2Ft, pDlg->GetText2() );
- SetLabelText_Impl( &aInfo3Ft, pDlg->GetText3() );
- SetLabelText_Impl( &aInfo4Ft, pDlg->GetText4() );
- bLabelModified = TRUE;
- }
- delete pDlg;
- return 0;
-}
-
-//------------------------------------------------------------------------
-
-String SfxDocumentUserPage::GetLabelText_Impl( FixedText* pLabel )
-{
- DBG_ASSERT( pLabel, "SfxDocumentUserPage::SetLabelText_Impl(): invalid label" );
- String aLabel = pLabel->GetText();
- aLabel.Erase( 0, aLabel.Search( ' ' ) + 1 );
- return aLabel;
-}
-
-//------------------------------------------------------------------------
-
-void SfxDocumentUserPage::SetLabelText_Impl( FixedText* pLabel, const String& rNewLabel )
-{
- String aLabel( '~' );
- sal_Int32 nNumber = 0;
- if ( &aInfo1Ft == pLabel )
- nNumber = 1;
- else if ( &aInfo2Ft == pLabel )
- nNumber = 2;
- else if ( &aInfo3Ft == pLabel )
- nNumber = 3;
- else if ( &aInfo4Ft == pLabel )
- nNumber = 4;
- DBG_ASSERT( nNumber > 0, "SfxDocumentUserPage::SetLabelText_Impl(): wrong label" );
- aLabel += String::CreateFromInt32( nNumber );
- aLabel += String( DEFINE_CONST_UNICODE(": ") );
- aLabel += rNewLabel;
- DBG_ASSERT( pLabel, "SfxDocumentUserPage::SetLabelText_Impl(): invalid label" );
- pLabel->SetText( aLabel );
-}
-
-//------------------------------------------------------------------------
-
-SfxTabPage* SfxDocumentUserPage::Create( Window* pParent, const SfxItemSet& rItemSet )
-{
- return new SfxDocumentUserPage(pParent, rItemSet);
-}
-
-//------------------------------------------------------------------------
-
-BOOL SfxDocumentUserPage::FillItemSet( SfxItemSet& rSet )
-{
- const BOOL bMod = bLabelModified ||
- aInfo1Ed.IsModified() || aInfo2Ed.IsModified() ||
- aInfo3Ed.IsModified() || aInfo4Ed.IsModified();
- if ( !bMod )
- return FALSE;
-
- const SfxPoolItem* pItem = NULL;
- SfxDocumentInfoItem* pInfo = NULL;
- SfxTabDialog* pDlg = GetTabDialog();
- const SfxItemSet* pExSet = NULL;
-
- if ( pDlg )
- pExSet = pDlg->GetExampleSet();
-
- if ( pExSet && SFX_ITEM_SET != pExSet->GetItemState( SID_DOCINFO, TRUE, &pItem ) )
- pInfo = pInfoItem;
- else if ( pItem )
- pInfo = new SfxDocumentInfoItem( *(const SfxDocumentInfoItem*)pItem );
-
- if ( !pInfo )
- {
- DBG_ERRORFILE( "SfxDocumentUserPage::FillItemSet(): no item found" );
- return FALSE;
- }
-
- if ( bLabelModified || aInfo1Ed.IsModified() )
- {
- XubString aTitle = GetLabelText_Impl( &aInfo1Ft );
- pInfo->setUserDefinedFieldTitle( 0, aTitle );
- pInfo->setUserDefinedFieldValue( 0, aInfo1Ed.GetText() );
- }
- if ( bLabelModified || aInfo2Ed.IsModified() )
- {
- XubString aTitle = GetLabelText_Impl( &aInfo2Ft );
- pInfo->setUserDefinedFieldTitle( 1, aTitle );
- pInfo->setUserDefinedFieldValue( 1, aInfo2Ed.GetText() );
- }
- if ( bLabelModified || aInfo3Ed.IsModified() )
- {
- XubString aTitle = GetLabelText_Impl( &aInfo3Ft );
- pInfo->setUserDefinedFieldTitle( 2, aTitle );
- pInfo->setUserDefinedFieldValue( 2, aInfo3Ed.GetText() );
- }
- if ( bLabelModified || aInfo4Ed.IsModified() )
- {
- XubString aTitle = GetLabelText_Impl( &aInfo4Ft );
- pInfo->setUserDefinedFieldTitle( 3, aTitle );
- pInfo->setUserDefinedFieldValue( 3, aInfo4Ed.GetText() );
- }
- rSet.Put( *pInfo );
- if ( pInfo != pInfoItem )
- delete pInfo;
- return bMod;
-}
-
-//------------------------------------------------------------------------
-
-void SfxDocumentUserPage::Reset(const SfxItemSet &rSet)
-{
- pInfoItem = &(SfxDocumentInfoItem&)rSet.Get( SID_DOCINFO );
-
- SetLabelText_Impl( &aInfo1Ft, pInfoItem->getUserDefinedFieldTitle(0) );
- aInfo1Ed.SetText( pInfoItem->getUserDefinedFieldValue(0) );
- SetLabelText_Impl( &aInfo2Ft, pInfoItem->getUserDefinedFieldTitle(1) );
- aInfo2Ed.SetText( pInfoItem->getUserDefinedFieldValue(1) );
- SetLabelText_Impl( &aInfo3Ft, pInfoItem->getUserDefinedFieldTitle(2) );
- aInfo3Ed.SetText( pInfoItem->getUserDefinedFieldValue(2) );
- SetLabelText_Impl( &aInfo4Ft, pInfoItem->getUserDefinedFieldTitle(3) );
- aInfo4Ed.SetText( pInfoItem->getUserDefinedFieldValue(3) );
- bLabelModified = FALSE;
-
- SFX_ITEMSET_ARG( &rSet, pROItem, SfxBoolItem, SID_DOC_READONLY, FALSE );
- if ( pROItem && pROItem->GetValue() )
- {
- aInfo1Ed.SetReadOnly( TRUE );
- aInfo2Ed.SetReadOnly( TRUE );
- aInfo3Ed.SetReadOnly( TRUE );
- aInfo4Ed.SetReadOnly( TRUE );
- aEditLabelBtn.Disable();
- }
-}
-
-//------------------------------------------------------------------------
-
SfxDocumentInfoDialog::SfxDocumentInfoDialog( Window* pParent,
const SfxItemSet& rItemSet ) :
diff --git a/sfx2/source/dialog/templdlg.cxx b/sfx2/source/dialog/templdlg.cxx
index c0ee288eb882..7dfe5e4b6855 100644
--- a/sfx2/source/dialog/templdlg.cxx
+++ b/sfx2/source/dialog/templdlg.cxx
@@ -79,7 +79,6 @@
#include "imgmgr.hxx"
#include "helpid.hrc"
#include "appdata.hxx"
-#include "objshimp.hxx"
#include <sfx2/viewfrm.hxx>
#include <comphelper/configurationhelper.hxx>
@@ -883,7 +882,7 @@ void SfxCommonTemplateDialog_Impl::ReadResource()
nActFilter = pCurObjShell ? static_cast< USHORT >( LoadFactoryStyleFilter( pCurObjShell ) ) : 0xFFFF;
if ( pCurObjShell && 0xFFFF == nActFilter )
- nActFilter = pCurObjShell->pImp->nStyleFilter;
+ nActFilter = pCurObjShell->GetAutoStyleFilterIndex();
// Einfuegen in die Toolbox
// umgekehrte Reihenfolge, da immer vorne eingefuegt wird.
@@ -1504,7 +1503,7 @@ void SfxCommonTemplateDialog_Impl::Update_Impl()
CheckItem( nActFamily, TRUE );
nActFilter = static_cast< USHORT >( LoadFactoryStyleFilter( pDocShell ) );
if ( 0xFFFF == nActFilter )
- nActFilter = pDocShell->pImp->nStyleFilter;
+ nActFilter = pDocShell->GetAutoStyleFilterIndex();
nAppFilter = pItem->GetValue();
if(!pTreeBox)
@@ -1674,7 +1673,7 @@ void SfxCommonTemplateDialog_Impl::FilterSelect(
SfxObjectShell *pDocShell = pViewFrame->GetObjectShell();
if (pDocShell)
{
- pDocShell->Get_Impl()->nStyleFilter = nActFilter;
+ pDocShell->SetAutoStyleFilterIndex(nActFilter);
SaveFactoryStyleFilter( pDocShell, nActFilter );
}
diff --git a/sfx2/source/doc/DocumentMetadataAccess.cxx b/sfx2/source/doc/DocumentMetadataAccess.cxx
new file mode 100644
index 000000000000..112183a4efbe
--- /dev/null
+++ b/sfx2/source/doc/DocumentMetadataAccess.cxx
@@ -0,0 +1,1414 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DocumentMetadataAccess.cxx,v $
+ * $Revision: 1.1.2.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sfx2.hxx"
+
+#include <sfx2/DocumentMetadataAccess.hxx>
+
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/task/ErrorCodeIOException.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/rdf/FileFormat.hpp>
+#include <com/sun/star/rdf/URIs.hpp>
+#include <com/sun/star/rdf/Statement.hpp>
+#include <com/sun/star/rdf/Literal.hpp>
+#include <com/sun/star/rdf/URI.hpp>
+#include <com/sun/star/rdf/Repository.hpp>
+
+#include <rtl/uuid.h>
+#include <rtl/ustrbuf.hxx>
+
+#include <comphelper/interaction.hxx>
+#include <comphelper/makesequence.hxx>
+#include <comphelper/mediadescriptor.hxx>
+#include <comphelper/sequenceasvector.hxx>
+#include <comphelper/storagehelper.hxx>
+
+#include <sfx2/docfile.hxx>
+#include <sfx2/XmlIdRegistry.hxx>
+
+#include <libxml/tree.h> // for xmlValidateNCName
+
+#include <boost/bind.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#include <vector>
+#include <set>
+#include <map>
+#include <functional>
+#include <algorithm>
+
+#include <unotools/ucbhelper.hxx>
+#include <com/sun/star/uri/XUriReference.hpp>
+#include <com/sun/star/uri/XUriReferenceFactory.hpp>
+#include <com/sun/star/uri/XVndSunStarPkgUrlReferenceFactory.hpp>
+
+
+/*
+ Note: in the context of this implementation, all rdf.QueryExceptions and
+ rdf.RepositoryExceptions are RuntimeExceptions, and will be reported as such.
+
+ This implementation assumes that it is only used with ODF documents, not mere
+ ODF packages. In other words, we enforce that metadata files must not be
+ called reserved names.
+ */
+
+using namespace ::com::sun::star;
+
+namespace sfx2 {
+
+
+bool isValidNCName(::rtl::OUString const & i_rIdref)
+{
+ const ::rtl::OString id(
+ ::rtl::OUStringToOString(i_rIdref, RTL_TEXTENCODING_UTF8) );
+ return !(xmlValidateNCName(
+ reinterpret_cast<const unsigned char*>(id.getStr()), 0));
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+static const char s_content [] = "content.xml";
+static const char s_styles [] = "styles.xml";
+static const char s_meta [] = "meta.xml";
+static const char s_settings[] = "settings.xml";
+static const char s_manifest[] = "manifest.rdf";
+static const char s_rdfxml [] = "application/rdf+xml";
+static const char s_odfmime [] = "application/vnd.oasis.opendocument.";
+
+////////////////////////////////////////////////////////////////////////////
+
+static bool isContentFile(::rtl::OUString const & i_rPath)
+{
+ return i_rPath.equalsAscii(s_content);
+}
+
+static bool isStylesFile (::rtl::OUString const & i_rPath)
+{
+ return i_rPath.equalsAscii(s_styles);
+}
+
+static bool isReservedFile(::rtl::OUString const & i_rPath)
+{
+ return isContentFile(i_rPath)
+ || isStylesFile(i_rPath)
+ || i_rPath.equalsAscii(s_meta)
+ || i_rPath.equalsAscii(s_settings);
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+uno::Reference<rdf::XURI> createBaseURI(
+ uno::Reference<uno::XComponentContext> const & i_xContext,
+ uno::Reference<embed::XStorage> const & i_xStorage,
+ ::rtl::OUString const & i_rPkgURI, ::rtl::OUString const & i_rSubDocument)
+{
+ if (!i_xContext.is() || !i_xStorage.is() || !i_rPkgURI.getLength()) {
+ throw uno::RuntimeException();
+ }
+
+ const uno::Reference<lang::XMultiComponentFactory> xServiceFactory(
+ i_xContext->getServiceManager(), uno::UNO_SET_THROW);
+ const uno::Reference<uri::XUriReferenceFactory> xUriFactory(
+ xServiceFactory->createInstanceWithContext(
+ ::rtl::OUString::createFromAscii(
+ "com.sun.star.uri.UriReferenceFactory"), i_xContext),
+ uno::UNO_QUERY_THROW);
+ uno::Reference< uri::XUriReference > xBaseURI;
+
+ const uno::Reference< uri::XUriReference > xPkgURI(
+ xUriFactory->parse(i_rPkgURI), uno::UNO_SET_THROW );
+ xPkgURI->clearFragment();
+ // need to know whether the storage is a FileSystemStorage
+ // XServiceInfo would be better, but it is not implemented
+// if ( i_rPkgURI.getLength() && ::utl::UCBContentHelper::IsFolder(i_rPkgURI) )
+ if (true) {
+ xBaseURI.set( xPkgURI, uno::UNO_SET_THROW );
+#if 0
+ } else {
+ const uno::Reference<uri::XVndSunStarPkgUrlReferenceFactory>
+ xPkgUriFactory( xServiceFactory->createInstanceWithContext(
+ ::rtl::OUString::createFromAscii(
+ "com.sun.star.uri.VndSunStarPkgUrlReferenceFactory"),
+ i_xContext),
+ uno::UNO_QUERY_THROW);
+ xBaseURI.set( xPkgUriFactory->createVndSunStarPkgUrlReference(xPkgURI),
+ uno::UNO_SET_THROW );
+#endif
+ }
+ ::rtl::OUStringBuffer buf;
+ if (!xBaseURI->getUriReference().endsWithAsciiL("/", 1))
+ {
+ const sal_Int32 count( xBaseURI->getPathSegmentCount() );
+ if (count > 0)
+ {
+ const ::rtl::OUString last( xBaseURI->getPathSegment(count - 1) );
+ buf.append(last);
+ }
+ buf.append(static_cast<sal_Unicode>('/'));
+ }
+ if (i_rSubDocument.getLength())
+ {
+ buf.append(i_rSubDocument);
+ buf.append(static_cast<sal_Unicode>('/'));
+ }
+ const ::rtl::OUString Path(buf.makeStringAndClear());
+ if (Path.getLength())
+ {
+ const uno::Reference< uri::XUriReference > xPathURI(
+ xUriFactory->parse(Path), uno::UNO_SET_THROW );
+ xBaseURI.set(
+ xUriFactory->makeAbsolute(xBaseURI, xPathURI,
+ true, uri::RelativeUriExcessParentSegments_ERROR),
+ uno::UNO_SET_THROW);
+ }
+
+ return rdf::URI::create(i_xContext, xBaseURI->getUriReference());
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+struct DocumentMetadataAccess_Impl
+{
+ // note: these are all initialized in constructor, and loadFromStorage
+ const uno::Reference<uno::XComponentContext> m_xContext;
+ const IXmlIdRegistrySupplier & m_rXmlIdRegistrySupplier;
+ uno::Reference<rdf::XURI> m_xBaseURI;
+ uno::Reference<rdf::XRepository> m_xRepository;
+ uno::Reference<rdf::XNamedGraph> m_xManifest;
+ DocumentMetadataAccess_Impl(
+ uno::Reference<uno::XComponentContext> const& i_xContext,
+ IXmlIdRegistrySupplier const & i_rRegistrySupplier)
+ : m_xContext(i_xContext)
+ , m_rXmlIdRegistrySupplier(i_rRegistrySupplier)
+ , m_xBaseURI()
+ , m_xRepository()
+ , m_xManifest()
+ {
+ OSL_ENSURE(m_xContext.is(), "context null");
+ }
+};
+
+// this is... a hack.
+template<sal_Int16 Constant>
+/*static*/ uno::Reference<rdf::XURI>
+getURI(uno::Reference< uno::XComponentContext > const & i_xContext)
+{
+ static uno::Reference< rdf::XURI > xURI(
+ rdf::URI::createKnown(i_xContext, Constant), uno::UNO_QUERY_THROW);
+ return xURI;
+}
+
+
+/** would storing the file to a XStorage succeed? */
+static bool isFileNameValid(const ::rtl::OUString & i_rFileName)
+{
+ if (i_rFileName.getLength() <= 0) return false;
+ if (i_rFileName[0] == '/') return false; // no absolute paths!
+ sal_Int32 idx(0);
+ do {
+ const ::rtl::OUString segment(
+ i_rFileName.getToken(0, static_cast<sal_Unicode> ('/'), idx) );
+ if (!segment.getLength() || // no empty segments
+ segment.equalsAscii(".") || // no . segments
+ segment.equalsAscii("..") || // no .. segments
+ !::comphelper::OStorageHelper::IsValidZipEntryFileName(
+ segment, sal_False)) // no invalid characters
+ return false;
+ } while (idx >= 0);
+ return true;
+}
+
+/** split a uri hierarchy into first segment and rest */
+static bool
+splitPath(::rtl::OUString const & i_rPath,
+ ::rtl::OUString & o_rDir, ::rtl::OUString& o_rRest)
+{
+ const sal_Int32 idx(i_rPath.indexOf(static_cast<sal_Unicode>('/')));
+ if (idx < 0 || idx >= i_rPath.getLength()) {
+ o_rDir = ::rtl::OUString();
+ o_rRest = i_rPath;
+ return true;
+ } else if (idx == 0 || idx == i_rPath.getLength() - 1) {
+ // input must not start or end with '/'
+ return false;
+ } else {
+ o_rDir = (i_rPath.copy(0, idx));
+ o_rRest = (i_rPath.copy(idx+1));
+ return true;
+ }
+}
+
+static bool
+splitXmlId(::rtl::OUString const & i_XmlId,
+ ::rtl::OUString & o_StreamName, ::rtl::OUString& o_Idref )
+{
+ const sal_Int32 idx(i_XmlId.indexOf(static_cast<sal_Unicode>('#')));
+ if ((idx <= 0) || (idx >= i_XmlId.getLength() - 1)) {
+ return false;
+ } else {
+ o_StreamName = (i_XmlId.copy(0, idx));
+ o_Idref = (i_XmlId.copy(idx+1));
+ return isValidXmlId(o_StreamName, o_Idref);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+static uno::Reference<rdf::XURI>
+getURIForStream(struct DocumentMetadataAccess_Impl& i_rImpl,
+ ::rtl::OUString const& i_rPath)
+{
+ const uno::Reference<rdf::XURI> xURI(
+ rdf::URI::createNS( i_rImpl.m_xContext,
+ i_rImpl.m_xBaseURI->getStringValue(), i_rPath),
+ uno::UNO_SET_THROW);
+ return xURI;
+}
+
+/** add statements declaring i_xResource to be a file of type i_xType with
+ path i_rPath to manifest, with optional additional types i_pTypes */
+static void
+addFile(struct DocumentMetadataAccess_Impl & i_rImpl,
+ uno::Reference<rdf::XURI> const& i_xType,
+ ::rtl::OUString const & i_rPath,
+ const uno::Sequence < uno::Reference< rdf::XURI > > * i_pTypes = 0)
+{
+ try {
+ const uno::Reference<rdf::XURI> xURI( getURIForStream(
+ i_rImpl, i_rPath) );
+
+ i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
+ getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext),
+ xURI.get());
+ i_rImpl.m_xManifest->addStatement(xURI.get(),
+ getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
+ i_xType.get());
+ if (i_pTypes) {
+ for (sal_Int32 i = 0; i < i_pTypes->getLength(); ++i) {
+ i_rImpl.m_xManifest->addStatement(xURI.get(),
+ getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
+ (*i_pTypes)[i].get());
+ }
+ }
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "addFile: exception"), /*this*/0, uno::makeAny(e));
+ }
+}
+
+/** add content.xml or styles.xml to manifest */
+static bool
+addContentOrStylesFileImpl(struct DocumentMetadataAccess_Impl & i_rImpl,
+ const ::rtl::OUString & i_rPath)
+{
+ uno::Reference<rdf::XURI> xType;
+ if (isContentFile(i_rPath)) {
+ xType.set(getURI<rdf::URIs::ODF_CONTENTFILE>(i_rImpl.m_xContext));
+ } else if (isStylesFile(i_rPath)) {
+ xType.set(getURI<rdf::URIs::ODF_STYLESFILE>(i_rImpl.m_xContext));
+ } else {
+ return false;
+ }
+ addFile(i_rImpl, xType.get(), i_rPath);
+ return true;
+}
+
+/** add metadata file to manifest */
+static void
+addMetadataFileImpl(struct DocumentMetadataAccess_Impl & i_rImpl,
+ const ::rtl::OUString & i_rPath,
+ const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
+{
+ addFile(i_rImpl,
+ getURI<rdf::URIs::PKG_METADATAFILE>(i_rImpl.m_xContext),
+ i_rPath, &i_rTypes);
+}
+
+/** remove a file from the manifest */
+static void
+removeFile(struct DocumentMetadataAccess_Impl & i_rImpl,
+ uno::Reference<rdf::XURI> const& i_xPart)
+{
+ if (!i_xPart.is()) throw uno::RuntimeException();
+ try {
+ i_rImpl.m_xManifest->removeStatements(i_rImpl.m_xBaseURI.get(),
+ getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext),
+ i_xPart.get());
+ i_rImpl.m_xManifest->removeStatements(i_xPart.get(),
+ getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext), 0);
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii("removeFile: exception"),
+ 0, uno::makeAny(e));
+ }
+}
+
+static ::std::vector< uno::Reference< rdf::XURI > >
+getAllParts(struct DocumentMetadataAccess_Impl & i_rImpl)
+{
+ ::std::vector< uno::Reference< rdf::XURI > > ret;
+ try {
+ const uno::Reference<container::XEnumeration> xEnum(
+ i_rImpl.m_xManifest->getStatements( i_rImpl.m_xBaseURI.get(),
+ getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext), 0),
+ uno::UNO_SET_THROW);
+ while (xEnum->hasMoreElements()) {
+ rdf::Statement stmt;
+ if (!(xEnum->nextElement() >>= stmt)) {
+ throw uno::RuntimeException();
+ }
+ const uno::Reference<rdf::XURI> xPart(stmt.Object,
+ uno::UNO_QUERY);
+ if (!xPart.is()) continue;
+ ret.push_back(xPart);
+ }
+ return ret;
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii("getAllParts: exception"),
+ 0, uno::makeAny(e));
+ }
+}
+
+static bool
+isPartOfType(struct DocumentMetadataAccess_Impl & i_rImpl,
+ uno::Reference<rdf::XURI> const & i_xPart,
+ uno::Reference<rdf::XURI> const & i_xType)
+{
+ if (!i_xPart.is() || !i_xType.is()) throw uno::RuntimeException();
+ try {
+ const uno::Reference<container::XEnumeration> xEnum(
+ i_rImpl.m_xManifest->getStatements(i_xPart.get(),
+ getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
+ i_xType.get()),
+ uno::UNO_SET_THROW);
+ return (xEnum->hasMoreElements());
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii("isPartOfType: exception"),
+ 0, uno::makeAny(e));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+static ucb::InteractiveAugmentedIOException
+mkException( ::rtl::OUString const & i_rMessage,
+ ucb::IOErrorCode const i_ErrorCode,
+ ::rtl::OUString const & i_rUri, ::rtl::OUString const & i_rResource)
+{
+ ucb::InteractiveAugmentedIOException iaioe;
+ iaioe.Message = i_rMessage;
+ iaioe.Classification = task::InteractionClassification_ERROR;
+ iaioe.Code = i_ErrorCode;
+
+ const beans::PropertyValue uriProp(::rtl::OUString::createFromAscii("Uri"),
+ -1, uno::makeAny(i_rUri), static_cast<beans::PropertyState>(0));
+ const beans::PropertyValue rnProp(
+ ::rtl::OUString::createFromAscii("ResourceName"),
+ -1, uno::makeAny(i_rResource), static_cast<beans::PropertyState>(0));
+ iaioe.Arguments = ::comphelper::makeSequence(
+ uno::makeAny(uriProp), uno::makeAny(rnProp));
+ return iaioe;
+}
+
+/** error handling policy.
+ <p>If a handler is given, ask it how to proceed:
+ <ul><li>(default:) cancel import, raise exception</li>
+ <li>ignore the error and continue</li>
+ <li>retry the action that led to the error</li></ul></p>
+ N.B.: must not be called before DMA is fully initalized!
+ @returns true iff caller should retry
+ */
+static bool
+handleError( ucb::InteractiveAugmentedIOException const & i_rException,
+ const uno::Reference<task::XInteractionHandler> & i_xHandler)
+{
+ if (!i_xHandler.is()) {
+ throw lang::WrappedTargetException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromStorage: exception"),
+ /* *this*/ 0, uno::makeAny(i_rException));
+ }
+
+ ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest(
+ new ::comphelper::OInteractionRequest(uno::makeAny(i_rException)) );
+ ::rtl::Reference< ::comphelper::OInteractionRetry > pRetry(
+ new ::comphelper::OInteractionRetry );
+ ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove(
+ new ::comphelper::OInteractionApprove );
+ ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort(
+ new ::comphelper::OInteractionAbort );
+ /* this does not seem to work
+ if (i_rException.Code != ucb::IOErrorCode_WRONG_FORMAT) {
+ pRequest->addContinuation( pRetry.get() );
+ }
+ */
+ pRequest->addContinuation( pApprove.get() );
+ pRequest->addContinuation( pAbort.get() );
+ // actually call the handler
+ i_xHandler->handle( pRequest.get() );
+ if (pRetry->wasSelected()) {
+ return true;
+ } else if (pApprove->wasSelected()) {
+ return false;
+ } else {
+ OSL_ENSURE(pAbort->wasSelected(), "no continuation selected?");
+ throw lang::WrappedTargetException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromStorage: exception"),
+ /* *this*/ 0, uno::makeAny(i_rException));
+ }
+}
+
+/** check if storage has content.xml/styles.xml;
+ e.g. ODB files seem to only have content.xml */
+static void
+collectFilesFromStorage(uno::Reference<embed::XStorage> const& i_xStorage,
+ ::rtl::OUString i_Path,
+ std::set< ::rtl::OUString > & o_rFiles)
+{
+ static ::rtl::OUString content(::rtl::OUString::createFromAscii(s_content));
+ static ::rtl::OUString styles (::rtl::OUString::createFromAscii(s_styles ));
+ try {
+ if (i_xStorage->hasByName(content) &&
+ i_xStorage->isStreamElement(content))
+ {
+ o_rFiles.insert(i_Path + content);
+ }
+ if (i_xStorage->hasByName(styles) &&
+ i_xStorage->isStreamElement(styles))
+ {
+ o_rFiles.insert(i_Path + styles);
+ }
+ } catch (uno::Exception &) {
+ OSL_TRACE("collectFilesFromStorage: exception?");
+ }
+}
+
+/** import a metadata file into repository */
+static void
+readStream(struct DocumentMetadataAccess_Impl & i_rImpl,
+ uno::Reference< embed::XStorage > const & i_xStorage,
+ ::rtl::OUString const & i_rPath,
+ ::rtl::OUString const & i_rBaseURI)
+{
+ ::rtl::OUString dir;
+ ::rtl::OUString rest;
+ try {
+ if (!splitPath(i_rPath, dir, rest)) throw uno::RuntimeException();
+ if (dir.equalsAscii("")) {
+ if (i_xStorage->isStreamElement(i_rPath)) {
+ const uno::Reference<io::XStream> xStream(
+ i_xStorage->openStreamElement(i_rPath,
+ embed::ElementModes::READ), uno::UNO_SET_THROW);
+ const uno::Reference<io::XInputStream> xInStream(
+ xStream->getInputStream(), uno::UNO_SET_THROW );
+ const uno::Reference<rdf::XURI> xBaseURI(
+ rdf::URI::create(i_rImpl.m_xContext, i_rBaseURI));
+ const uno::Reference<rdf::XURI> xURI(
+ rdf::URI::createNS(i_rImpl.m_xContext,
+ i_rBaseURI, i_rPath));
+ i_rImpl.m_xRepository->importGraph(rdf::FileFormat::RDF_XML,
+ xInStream, xURI, xBaseURI);
+ } else {
+ throw mkException(::rtl::OUString::createFromAscii(
+ "readStream: is not a stream"),
+ ucb::IOErrorCode_NO_FILE, i_rBaseURI + i_rPath, i_rPath);
+ }
+ } else {
+ if (i_xStorage->isStorageElement(dir)) {
+ const uno::Reference<embed::XStorage> xDir(
+ i_xStorage->openStorageElement(dir,
+ embed::ElementModes::READ));
+ const uno::Reference< beans::XPropertySet > xDirProps(xDir,
+ uno::UNO_QUERY_THROW);
+ try {
+ ::rtl::OUString mimeType;
+ xDirProps->getPropertyValue(
+ ::comphelper::MediaDescriptor::PROP_MEDIATYPE() )
+ >>= mimeType;
+ if (mimeType.matchAsciiL(s_odfmime, sizeof(s_odfmime) - 1))
+ {
+ OSL_TRACE("readStream: "
+ "refusing to recurse into embedded document");
+ return;
+ }
+ } catch (uno::Exception &) { }
+ ::rtl::OUStringBuffer buf(i_rBaseURI);
+ buf.append(dir).append(static_cast<sal_Unicode>('/'));
+ readStream(i_rImpl, xDir, rest, buf.makeStringAndClear() );
+ } else {
+ throw mkException(::rtl::OUString::createFromAscii(
+ "readStream: is not a directory"),
+ ucb::IOErrorCode_NO_DIRECTORY, i_rBaseURI + dir, dir);
+ }
+ }
+ } catch (container::NoSuchElementException & e) {
+ throw mkException(e.Message, ucb::IOErrorCode_NOT_EXISTING_PATH,
+ i_rBaseURI + i_rPath, i_rPath);
+ } catch (io::IOException & e) {
+ throw mkException(e.Message, ucb::IOErrorCode_CANT_READ,
+ i_rBaseURI + i_rPath, i_rPath);
+ } catch (rdf::ParseException & e) {
+ throw mkException(e.Message, ucb::IOErrorCode_WRONG_FORMAT,
+ i_rBaseURI + i_rPath, i_rPath);
+ }
+}
+
+/** import a metadata file into repository */
+static void
+importFile(struct DocumentMetadataAccess_Impl & i_rImpl,
+ uno::Reference<embed::XStorage> const & i_xStorage,
+ ::rtl::OUString const & i_rBaseURI,
+ uno::Reference<task::XInteractionHandler> const & i_xHandler,
+ ::rtl::OUString i_rPath)
+{
+retry:
+ try {
+ readStream(i_rImpl, i_xStorage, i_rPath, i_rBaseURI);
+ } catch (ucb::InteractiveAugmentedIOException & e) {
+ if (handleError(e, i_xHandler)) goto retry;
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii("importFile: exception"),
+ 0, uno::makeAny(e));
+ }
+}
+
+/** actually write a metadata file to the storage */
+static void
+exportStream(struct DocumentMetadataAccess_Impl & i_rImpl,
+ uno::Reference< embed::XStorage > const & i_xStorage,
+ uno::Reference<rdf::XURI> const & i_xGraphName,
+ ::rtl::OUString const & i_rFileName,
+ ::rtl::OUString const & i_rBaseURI)
+{
+ const uno::Reference<io::XStream> xStream(
+ i_xStorage->openStreamElement(i_rFileName,
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE),
+ uno::UNO_SET_THROW);
+ const uno::Reference< beans::XPropertySet > xStreamProps(xStream,
+ uno::UNO_QUERY);
+ if (xStreamProps.is()) { // this is NOT supported in FileSystemStorage
+ xStreamProps->setPropertyValue(
+ ::rtl::OUString::createFromAscii("MediaType"),
+ uno::makeAny(::rtl::OUString::createFromAscii(s_rdfxml)));
+ }
+ const uno::Reference<io::XOutputStream> xOutStream(
+ xStream->getOutputStream(), uno::UNO_SET_THROW );
+ const uno::Reference<rdf::XURI> xBaseURI(
+ rdf::URI::create(i_rImpl.m_xContext, i_rBaseURI));
+ i_rImpl.m_xRepository->exportGraph(rdf::FileFormat::RDF_XML,
+ xOutStream, i_xGraphName, xBaseURI);
+}
+
+/** write a metadata file to the storage */
+static void
+writeStream(struct DocumentMetadataAccess_Impl & i_rImpl,
+ uno::Reference< embed::XStorage > const & i_xStorage,
+ uno::Reference<rdf::XURI> const & i_xGraphName,
+ ::rtl::OUString const & i_rPath,
+ ::rtl::OUString const & i_rBaseURI)
+{
+ ::rtl::OUString dir;
+ ::rtl::OUString rest;
+ if (!splitPath(i_rPath, dir, rest)) throw uno::RuntimeException();
+ try {
+ if (dir.equalsAscii("")) {
+ exportStream(i_rImpl, i_xStorage, i_xGraphName, i_rPath,
+ i_rBaseURI);
+ } else {
+ const uno::Reference<embed::XStorage> xDir(
+ i_xStorage->openStorageElement(dir,
+ embed::ElementModes::WRITE));
+ const uno::Reference< beans::XPropertySet > xDirProps(xDir,
+ uno::UNO_QUERY_THROW);
+ try {
+ ::rtl::OUString mimeType;
+ xDirProps->getPropertyValue(
+ ::comphelper::MediaDescriptor::PROP_MEDIATYPE() )
+ >>= mimeType;
+ if (mimeType.matchAsciiL(s_odfmime, sizeof(s_odfmime) - 1)) {
+ OSL_TRACE("writeStream: "
+ "refusing to recurse into embedded document");
+ return;
+ }
+ } catch (uno::Exception &) { }
+ ::rtl::OUStringBuffer buf(i_rBaseURI);
+ buf.append(dir).append(static_cast<sal_Unicode>('/'));
+ writeStream(i_rImpl, xDir, i_xGraphName, rest,
+ buf.makeStringAndClear());
+ }
+ const uno::Reference<embed::XTransactedObject> xTransaction(
+ i_xStorage, uno::UNO_QUERY);
+ if (xTransaction.is()) {
+ xTransaction->commit();
+ }
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (io::IOException &) {
+ throw;
+ }
+}
+
+static void
+initLoading(struct DocumentMetadataAccess_Impl & i_rImpl,
+ const uno::Reference< embed::XStorage > & i_xStorage,
+ const uno::Reference<rdf::XURI> & i_xBaseURI,
+ const uno::Reference<task::XInteractionHandler> & i_xHandler)
+{
+retry:
+ // clear old data
+ i_rImpl.m_xManifest.clear();
+ // init BaseURI
+ i_rImpl.m_xBaseURI = i_xBaseURI;
+
+ // create repository
+ i_rImpl.m_xRepository.clear();
+ i_rImpl.m_xRepository.set(rdf::Repository::create(i_rImpl.m_xContext),
+ uno::UNO_SET_THROW);
+
+ const ::rtl::OUString manifest (
+ ::rtl::OUString::createFromAscii(s_manifest));
+ const ::rtl::OUString baseURI( i_xBaseURI->getStringValue() );
+ // try to delay raising errors until after initialization is done
+ uno::Any rterr;
+ ucb::InteractiveAugmentedIOException iaioe;
+ bool err(false);
+
+ const uno::Reference <rdf::XURI> xManifest(
+ getURIForStream(i_rImpl, manifest));
+ try {
+ readStream(i_rImpl, i_xStorage, manifest, baseURI);
+ } catch (ucb::InteractiveAugmentedIOException & e) {
+ // no manifest.rdf: this is not an error in ODF < 1.2
+ if (!(ucb::IOErrorCode_NOT_EXISTING_PATH == e.Code)) {
+ iaioe = e;
+ err = true;
+ }
+ } catch (uno::Exception & e) {
+ rterr <<= e;
+ }
+
+ // init manifest graph
+ const uno::Reference<rdf::XNamedGraph> xManifestGraph(
+ i_rImpl.m_xRepository->getGraph(xManifest));
+ i_rImpl.m_xManifest.set(xManifestGraph.is() ? xManifestGraph :
+ i_rImpl.m_xRepository->createGraph(xManifest), uno::UNO_SET_THROW);
+ const uno::Reference<container::XEnumeration> xEnum(
+ i_rImpl.m_xManifest->getStatements(0,
+ getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
+ getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get()));
+
+ // document statement
+ i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
+ getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
+ getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get());
+
+ OSL_ENSURE(i_rImpl.m_xBaseURI.is(), "base URI is null");
+ OSL_ENSURE(i_rImpl.m_xRepository.is(), "repository is null");
+ OSL_ENSURE(i_rImpl.m_xManifest.is(), "manifest is null");
+
+ if (rterr.hasValue()) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromStorage: "
+ "exception"), 0, rterr);
+ }
+
+ if (err) {
+ if (handleError(iaioe, i_xHandler)) goto retry;
+ }
+}
+
+/** init Impl struct */
+static void init(struct DocumentMetadataAccess_Impl & i_rImpl)
+{
+ try {
+
+ i_rImpl.m_xManifest.set(i_rImpl.m_xRepository->createGraph(
+ getURIForStream(i_rImpl,
+ ::rtl::OUString::createFromAscii(s_manifest))),
+ uno::UNO_SET_THROW);
+
+ // insert the document statement
+ i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
+ getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
+ getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get());
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii("init: unexpected exception"), 0,
+ uno::makeAny(e));
+ }
+
+ // add top-level content files
+ if (!addContentOrStylesFileImpl(i_rImpl,
+ ::rtl::OUString::createFromAscii(s_content))) {
+ throw uno::RuntimeException();
+ }
+ if (!addContentOrStylesFileImpl(i_rImpl,
+ ::rtl::OUString::createFromAscii(s_styles))) {
+ throw uno::RuntimeException();
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+DocumentMetadataAccess::DocumentMetadataAccess(
+ uno::Reference< uno::XComponentContext > const & i_xContext,
+ const IXmlIdRegistrySupplier & i_rRegistrySupplier)
+ : m_pImpl(new DocumentMetadataAccess_Impl(i_xContext, i_rRegistrySupplier))
+{
+ // no initalization: must call loadFrom...
+}
+
+DocumentMetadataAccess::DocumentMetadataAccess(
+ uno::Reference< uno::XComponentContext > const & i_xContext,
+ const IXmlIdRegistrySupplier & i_rRegistrySupplier,
+ ::rtl::OUString const & i_rURI)
+ : m_pImpl(new DocumentMetadataAccess_Impl(i_xContext, i_rRegistrySupplier))
+{
+ OSL_ENSURE(i_rURI.getLength(), "DMA::DMA: no URI given!");
+ OSL_ENSURE(i_rURI.endsWithAsciiL("/", 1), "DMA::DMA: URI without / given!");
+ if (!i_rURI.endsWithAsciiL("/", 1)) throw uno::RuntimeException();
+ m_pImpl->m_xBaseURI.set(rdf::URI::create(m_pImpl->m_xContext, i_rURI));
+ m_pImpl->m_xRepository.set(rdf::Repository::create(m_pImpl->m_xContext),
+ uno::UNO_SET_THROW);
+
+ // init repository
+ init(*m_pImpl);
+
+ OSL_ENSURE(m_pImpl->m_xBaseURI.is(), "base URI is null");
+ OSL_ENSURE(m_pImpl->m_xRepository.is(), "repository is null");
+ OSL_ENSURE(m_pImpl->m_xManifest.is(), "manifest is null");
+}
+
+DocumentMetadataAccess::~DocumentMetadataAccess()
+{
+}
+
+
+// ::com::sun::star::rdf::XRepositorySupplier:
+uno::Reference< rdf::XRepository > SAL_CALL
+DocumentMetadataAccess::getRDFRepository() throw (uno::RuntimeException)
+{
+ OSL_ENSURE(m_pImpl->m_xRepository.is(), "repository not initialized");
+ return m_pImpl->m_xRepository;
+}
+
+// ::com::sun::star::rdf::XNode:
+::rtl::OUString SAL_CALL
+DocumentMetadataAccess::getStringValue() throw (uno::RuntimeException)
+{
+ return m_pImpl->m_xBaseURI->getStringValue();
+}
+
+// ::com::sun::star::rdf::XURI:
+::rtl::OUString SAL_CALL
+DocumentMetadataAccess::getNamespace() throw (uno::RuntimeException)
+{
+ return m_pImpl->m_xBaseURI->getNamespace();
+}
+
+::rtl::OUString SAL_CALL
+DocumentMetadataAccess::getLocalName() throw (uno::RuntimeException)
+{
+ return m_pImpl->m_xBaseURI->getLocalName();
+}
+
+// ::com::sun::star::rdf::XDocumentMetadataAccess:
+uno::Reference< rdf::XMetadatable > SAL_CALL
+DocumentMetadataAccess::getElementByMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rReference)
+throw (uno::RuntimeException)
+{
+ const IXmlIdRegistry * pReg(
+ m_pImpl->m_rXmlIdRegistrySupplier.GetXmlIdRegistry() );
+ if (!pReg) {
+ throw uno::RuntimeException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::getElementByXmlId: no registry"), *this);
+ }
+ return pReg->GetElementByMetadataReference(i_rReference);
+}
+
+uno::Reference< rdf::XMetadatable > SAL_CALL
+DocumentMetadataAccess::getElementByURI(
+ const uno::Reference< rdf::XURI > & i_xURI )
+throw (uno::RuntimeException, lang::IllegalArgumentException)
+{
+ if (!i_xURI.is()) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::getElementByURI: URI is null"), *this, 0);
+ }
+
+ const ::rtl::OUString baseURI( m_pImpl->m_xBaseURI->getStringValue() );
+ const ::rtl::OUString name( i_xURI->getStringValue() );
+ if (!name.match(baseURI)) {
+ return 0;
+ }
+ const ::rtl::OUString relName( name.copy(baseURI.getLength()) );
+ ::rtl::OUString path;
+ ::rtl::OUString idref;
+ if (!splitXmlId(relName, path, idref)) {
+ return 0;
+ }
+
+ return getElementByMetadataReference( beans::StringPair(path, idref) );
+}
+
+
+uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
+DocumentMetadataAccess::getMetadataGraphsWithType(
+ const uno::Reference<rdf::XURI> & i_xType)
+throw (uno::RuntimeException, lang::IllegalArgumentException)
+{
+ if (!i_xType.is()) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::getMetadataGraphsWithType: "
+ "type is null"), *this, 0);
+ }
+
+ ::comphelper::SequenceAsVector< uno::Reference< rdf::XURI > > ret;
+ const ::std::vector< uno::Reference< rdf::XURI > > parts(
+ getAllParts(*m_pImpl) );
+ ::std::remove_copy_if(parts.begin(), parts.end(),
+ ::std::back_inserter(ret),
+ ::boost::bind(
+ ::std::logical_not<bool>(),
+ ::boost::bind(&isPartOfType, ::boost::ref(*m_pImpl), _1, i_xType) ));
+ return ret.getAsConstList();
+}
+
+uno::Reference<rdf::XURI> SAL_CALL
+DocumentMetadataAccess::addMetadataFile(const ::rtl::OUString & i_rFileName,
+ const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ container::ElementExistException)
+{
+ if (!isFileNameValid(i_rFileName)) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::addMetadataFile: invalid FileName"),
+ *this, 0);
+ }
+ if (isReservedFile(i_rFileName)) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::addMetadataFile:"
+ "invalid FileName: reserved"), *this, 0);
+ }
+ for (sal_Int32 i = 0; i < i_rTypes.getLength(); ++i) {
+ if (!i_rTypes[i].is()) {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::addMetadataFile: "
+ "null type"), *this, 2);
+ }
+ }
+
+ const uno::Reference<rdf::XURI> xGraphName(
+ getURIForStream(*m_pImpl, i_rFileName) );
+
+ try {
+ m_pImpl->m_xRepository->createGraph(xGraphName);
+ } catch (rdf::RepositoryException & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::addMetadataFile: exception"),
+ *this, uno::makeAny(e));
+ // note: all other exceptions are propagated
+ }
+
+ addMetadataFileImpl(*m_pImpl, i_rFileName, i_rTypes);
+ return xGraphName;
+}
+
+uno::Reference<rdf::XURI> SAL_CALL
+DocumentMetadataAccess::importMetadataFile(::sal_Int16 i_Format,
+ const uno::Reference< io::XInputStream > & i_xInStream,
+ const ::rtl::OUString & i_rFileName,
+ const uno::Reference< rdf::XURI > & i_xBaseURI,
+ const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ datatransfer::UnsupportedFlavorException,
+ container::ElementExistException, rdf::ParseException, io::IOException)
+{
+ if (!isFileNameValid(i_rFileName)) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::importMetadataFile: invalid FileName"),
+ *this, 0);
+ }
+ if (isReservedFile(i_rFileName)) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::importMetadataFile:"
+ "invalid FileName: reserved"), *this, 0);
+ }
+ for (sal_Int32 i = 0; i < i_rTypes.getLength(); ++i) {
+ if (!i_rTypes[i].is()) {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::importMetadataFile: null type"),
+ *this, 5);
+ }
+ }
+
+ const uno::Reference<rdf::XURI> xGraphName(
+ getURIForStream(*m_pImpl, i_rFileName) );
+
+ try {
+ m_pImpl->m_xRepository->importGraph(
+ i_Format, i_xInStream, xGraphName, i_xBaseURI);
+ } catch (rdf::RepositoryException & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::importMetadataFile: "
+ "RepositoryException"), *this, uno::makeAny(e));
+ // note: all other exceptions are propagated
+ }
+
+ // add to manifest
+ addMetadataFileImpl(*m_pImpl, i_rFileName, i_rTypes);
+ return xGraphName;
+}
+
+void SAL_CALL
+DocumentMetadataAccess::removeMetadataFile(
+ const uno::Reference< rdf::XURI > & i_xGraphName)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ container::NoSuchElementException)
+{
+ try {
+ m_pImpl->m_xRepository->destroyGraph(i_xGraphName);
+ } catch (rdf::RepositoryException & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::removeMetadataFile: "
+ "RepositoryException"), *this, uno::makeAny(e));
+ // note: all other exceptions are propagated
+ }
+
+ // remove file from manifest
+ removeFile(*m_pImpl, i_xGraphName.get());
+}
+
+void SAL_CALL
+DocumentMetadataAccess::addContentOrStylesFile(
+ const ::rtl::OUString & i_rFileName)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ container::ElementExistException)
+{
+ if (!isFileNameValid(i_rFileName)) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::addContentOrStylesFile: "
+ "invalid FileName"), *this, 0);
+ }
+
+ if (!addContentOrStylesFileImpl(*m_pImpl, i_rFileName)) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::addContentOrStylesFile: "
+ "invalid FileName: must end with content.xml or styles.xml"),
+ *this, 0);
+ }
+}
+
+void SAL_CALL
+DocumentMetadataAccess::removeContentOrStylesFile(
+ const ::rtl::OUString & i_rFileName)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ container::NoSuchElementException)
+{
+ if (!isFileNameValid(i_rFileName)) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::removeContentOrStylesFile: "
+ "invalid FileName"), *this, 0);
+ }
+
+ try {
+ const uno::Reference<rdf::XURI> xPart(
+ getURIForStream(*m_pImpl, i_rFileName) );
+ const uno::Reference<container::XEnumeration> xEnum(
+ m_pImpl->m_xManifest->getStatements( m_pImpl->m_xBaseURI.get(),
+ getURI<rdf::URIs::PKG_HASPART>(m_pImpl->m_xContext),
+ xPart.get()),
+ uno::UNO_SET_THROW);
+ if (!xEnum->hasMoreElements()) {
+ throw container::NoSuchElementException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::removeContentOrStylesFile: "
+ "cannot find stream in manifest graph: ") + i_rFileName,
+ *this);
+ }
+
+ // remove file from manifest
+ removeFile(*m_pImpl, xPart);
+
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::removeContentOrStylesFile: exception"),
+ *this, uno::makeAny(e));
+ }
+}
+
+void SAL_CALL DocumentMetadataAccess::loadMetadataFromStorage(
+ const uno::Reference< embed::XStorage > & i_xStorage,
+ const uno::Reference<rdf::XURI> & i_xBaseURI,
+ const uno::Reference<task::XInteractionHandler> & i_xHandler)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ lang::WrappedTargetException)
+{
+ if (!i_xStorage.is()) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromStorage: "
+ "storage is null"), *this, 0);
+ }
+ if (!i_xBaseURI.is()) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromStorage: "
+ "base URI is null"), *this, 1);
+ }
+ const ::rtl::OUString baseURI( i_xBaseURI->getStringValue());
+ if (baseURI.indexOf('#') >= 0) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromStorage: "
+ "base URI not absolute"), *this, 1);
+ }
+ if (!baseURI.getLength() || !baseURI.endsWithAsciiL("/", 1)) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromStorage: "
+ "base URI does not end with slash"), *this, 1);
+ }
+
+ initLoading(*m_pImpl, i_xStorage, i_xBaseURI, i_xHandler);
+
+ std::set< ::rtl::OUString > StgFiles;
+ collectFilesFromStorage(i_xStorage,
+ ::rtl::OUString::createFromAscii(""), StgFiles);
+
+ std::vector< ::rtl::OUString > MfstMetadataFiles;
+
+ try {
+ const ::std::vector< uno::Reference< rdf::XURI > > parts(
+ getAllParts(*m_pImpl) );
+ const uno::Reference<rdf::XURI> xContentFile(
+ getURI<rdf::URIs::ODF_CONTENTFILE>(m_pImpl->m_xContext));
+ const uno::Reference<rdf::XURI> xStylesFile(
+ getURI<rdf::URIs::ODF_STYLESFILE>(m_pImpl->m_xContext));
+ const uno::Reference<rdf::XURI> xMetadataFile(
+ getURI<rdf::URIs::PKG_METADATAFILE>(m_pImpl->m_xContext));
+ const sal_Int32 len( baseURI.getLength() );
+ const ::rtl::OUString manifest (
+ ::rtl::OUString::createFromAscii(s_manifest));
+ for (::std::vector< uno::Reference< rdf::XURI > >::const_iterator it
+ = parts.begin();
+ it != parts.end(); ++it) {
+ const ::rtl::OUString name((*it)->getStringValue());
+ if (!name.match(baseURI)) {
+ OSL_TRACE("loadMetadataFromStorage: graph not in document: %s",
+ ::rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)
+ .getStr());
+ continue;
+ }
+ const ::rtl::OUString relName( name.copy(len) );
+ if (relName == manifest) {
+ OSL_TRACE("loadMetadataFromStorage: "
+ "found ourselves a recursive manifest!");
+ continue;
+ }
+ // remove found items from StgFiles
+ StgFiles.erase(relName);
+ if (isContentFile(relName)) {
+ if (!isPartOfType(*m_pImpl, *it, xContentFile)) {
+ const uno::Reference <rdf::XURI> xName(
+ getURIForStream(*m_pImpl, relName) );
+ // add missing type statement
+ m_pImpl->m_xManifest->addStatement(xName.get(),
+ getURI<rdf::URIs::RDF_TYPE>(m_pImpl->m_xContext),
+ xContentFile.get());
+ }
+ } else if (isStylesFile(relName)) {
+ if (!isPartOfType(*m_pImpl, *it, xStylesFile)) {
+ const uno::Reference <rdf::XURI> xName(
+ getURIForStream(*m_pImpl, relName) );
+ // add missing type statement
+ m_pImpl->m_xManifest->addStatement(xName.get(),
+ getURI<rdf::URIs::RDF_TYPE>(m_pImpl->m_xContext),
+ xStylesFile.get());
+ }
+ } else if (isReservedFile(relName)) {
+ OSL_TRACE("loadMetadataFromStorage: "
+ "reserved file name in manifest");
+ } else {
+ if (isPartOfType(*m_pImpl, *it, xMetadataFile)) {
+ MfstMetadataFiles.push_back(relName);
+ }
+ // do not add statement for MetadataFile; it could be
+ // something else! just ignore it...
+ }
+ }
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromStorage: "
+ "exception"), *this, uno::makeAny(e));
+ }
+
+ std::for_each(StgFiles.begin(), StgFiles.end(),
+ boost::bind(addContentOrStylesFileImpl, boost::ref(*m_pImpl), _1));
+
+ std::for_each(MfstMetadataFiles.begin(), MfstMetadataFiles.end(),
+ boost::bind(importFile, boost::ref(*m_pImpl),
+ i_xStorage, baseURI, i_xHandler, _1));
+}
+
+void SAL_CALL DocumentMetadataAccess::storeMetadataToStorage(
+ const uno::Reference< embed::XStorage > & i_xStorage)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ lang::WrappedTargetException)
+{
+ if (!i_xStorage.is()) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::storeMetadataToStorage: "
+ "storage is null"), *this, 0);
+ }
+
+ // export manifest
+ const ::rtl::OUString manifest (
+ ::rtl::OUString::createFromAscii(s_manifest));
+ const uno::Reference <rdf::XURI> xManifest(
+ getURIForStream(*m_pImpl, manifest) );
+ const ::rtl::OUString baseURI( m_pImpl->m_xBaseURI->getStringValue() );
+ try {
+ writeStream(*m_pImpl, i_xStorage, xManifest, manifest, baseURI);
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (io::IOException & e) {
+ throw lang::WrappedTargetException( ::rtl::OUString::createFromAscii(
+ "storeMetadataToStorage: IO exception"), *this, uno::makeAny(e));
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "storeMetadataToStorage: exception"), *this, uno::makeAny(e));
+ }
+
+ // export metadata streams
+ try {
+ const uno::Sequence<uno::Reference<rdf::XURI> > graphs(
+ m_pImpl->m_xRepository->getGraphNames());
+ const sal_Int32 len( baseURI.getLength() );
+ for (sal_Int32 i = 0; i < graphs.getLength(); ++i) {
+ const uno::Reference<rdf::XURI> xName(graphs[i]);
+ const ::rtl::OUString name(xName->getStringValue());
+ if (!name.match(baseURI)) {
+ OSL_TRACE("storeMetadataToStorage: graph not in document: %s",
+ ::rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)
+ .getStr());
+ continue;
+ }
+ const ::rtl::OUString relName( name.copy(len) );
+ if (relName == manifest) {
+ continue;
+ }
+ if (!isFileNameValid(relName) || isReservedFile(relName)) {
+ OSL_TRACE("storeMetadataToStorage: invalid file name: %s",
+ ::rtl::OUStringToOString(relName, RTL_TEXTENCODING_UTF8)
+ .getStr());
+ continue;
+ }
+ try {
+ writeStream(*m_pImpl, i_xStorage, xName, relName, baseURI);
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (io::IOException & e) {
+ throw lang::WrappedTargetException(
+ ::rtl::OUString::createFromAscii(
+ "storeMetadataToStorage: IO exception"),
+ *this, uno::makeAny(e));
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "storeMetadataToStorage: exception"),
+ *this, uno::makeAny(e));
+ }
+ }
+ } catch (rdf::RepositoryException & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString::createFromAscii(
+ "storeMetadataToStorage: exception"), *this, uno::makeAny(e));
+ }
+}
+
+void SAL_CALL
+DocumentMetadataAccess::loadMetadataFromMedium(
+ const uno::Sequence< beans::PropertyValue > & i_rMedium)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ lang::WrappedTargetException)
+{
+ uno::Reference<io::XInputStream> xIn;
+ ::comphelper::MediaDescriptor md(i_rMedium);
+ ::rtl::OUString URL;
+ md[ ::comphelper::MediaDescriptor::PROP_URL() ] >>= URL;
+ ::rtl::OUString BaseURL;
+ md[ ::comphelper::MediaDescriptor::PROP_DOCUMENTBASEURL() ] >>= BaseURL;
+ if (md.addInputStream()) {
+ md[ ::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] >>= xIn;
+ }
+ if (!xIn.is() && URL.equalsAscii("")) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromMedium: "
+ "inalid medium: no URL, no input stream"), *this, 0);
+ }
+ uno::Reference<embed::XStorage> xStorage;
+ try {
+ const uno::Reference<lang::XMultiServiceFactory> xMsf (
+ m_pImpl->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
+ if (xIn.is()) {
+ xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream(
+ xIn, xMsf);
+ } else { // fallback to url
+ xStorage = ::comphelper::OStorageHelper::GetStorageFromURL2(
+ URL, embed::ElementModes::READ, xMsf);
+ }
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (io::IOException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetException(
+ ::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromMedium: "
+ "exception"), *this, uno::makeAny(e));
+ }
+ if (!xStorage.is()) {
+ throw uno::RuntimeException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::loadMetadataFromMedium: "
+ "cannot get Storage"), *this);
+ }
+ uno::Reference<rdf::XURI> xBaseURI;
+ try {
+ xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, BaseURL);
+ } catch (uno::Exception &) {
+ // fall back to URL
+ try {
+ xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, URL);
+ } catch (uno::Exception &) {
+ OSL_ENSURE(false, "cannot create base URI");
+ }
+ }
+ uno::Reference<task::XInteractionHandler> xIH;
+ md[ ::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER() ] >>= xIH;
+ loadMetadataFromStorage(xStorage, xBaseURI, xIH);
+}
+
+void SAL_CALL
+DocumentMetadataAccess::storeMetadataToMedium(
+ const uno::Sequence< beans::PropertyValue > & i_rMedium)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ lang::WrappedTargetException)
+{
+ ::comphelper::MediaDescriptor md(i_rMedium);
+ ::rtl::OUString URL;
+ md[ ::comphelper::MediaDescriptor::PROP_URL() ] >>= URL;
+ if (URL.equalsAscii("")) {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::storeMetadataToMedium: "
+ "invalid medium: no URL"), *this, 0);
+ }
+
+ SfxMedium aMedium(i_rMedium);
+ uno::Reference<embed::XStorage> xStorage(aMedium.GetOutputStorage());
+
+ bool sfx(false);
+ if (xStorage.is()) {
+ sfx = true;
+ } else {
+ const uno::Reference<lang::XMultiServiceFactory> xMsf (
+ m_pImpl->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
+ xStorage = ::comphelper::OStorageHelper::GetStorageFromURL2(
+ URL, embed::ElementModes::WRITE, xMsf);
+ }
+
+ if (!xStorage.is()) {
+ throw uno::RuntimeException(::rtl::OUString::createFromAscii(
+ "DocumentMetadataAccess::storeMetadataToMedium: "
+ "cannot get Storage"), *this);
+ }
+ // set MIME type of the storage
+ ::comphelper::MediaDescriptor::const_iterator iter
+ = md.find(::comphelper::MediaDescriptor::PROP_MEDIATYPE());
+ if (iter != md.end()) {
+ uno::Reference< beans::XPropertySet > xProps(xStorage,
+ uno::UNO_QUERY_THROW);
+ try {
+ // this is NOT supported in FileSystemStorage
+ xProps->setPropertyValue(
+ ::comphelper::MediaDescriptor::PROP_MEDIATYPE(),
+ iter->second);
+ } catch (uno::Exception &) { }
+ }
+ storeMetadataToStorage(xStorage);
+
+ if (sfx) {
+ const sal_Bool bOk = aMedium.Commit();
+ aMedium.Close();
+ if ( !bOk ) {
+ sal_uInt32 nError = aMedium.GetError();
+ if ( nError == ERRCODE_NONE ) {
+ nError = ERRCODE_IO_GENERAL;
+ }
+ task::ErrorCodeIOException ex( ::rtl::OUString(),
+ uno::Reference< uno::XInterface >(), nError);
+ throw lang::WrappedTargetException(::rtl::OUString(), *this,
+ uno::makeAny(ex));
+ }
+ }
+}
+
+} // namespace sfx2
+
diff --git a/sfx2/source/doc/Metadatable.cxx b/sfx2/source/doc/Metadatable.cxx
new file mode 100644
index 000000000000..2ad27856c7cc
--- /dev/null
+++ b/sfx2/source/doc/Metadatable.cxx
@@ -0,0 +1,1860 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SwMetadatable.cxx,v $
+ * $Revision: 1.1.2.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sfx2.hxx"
+
+#include <sfx2/Metadatable.hxx>
+#include <sfx2/XmlIdRegistry.hxx>
+
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx> // solarmutex
+
+#include <boost/bind.hpp>
+
+#include <memory>
+#include <hash_map>
+#include <list>
+#include <algorithm>
+#if OSL_DEBUG_LEVEL > 0
+#include <typeinfo>
+#endif
+
+
+/** XML ID handling.
+
+ There is an abstract base class <type>XmlIdRegistry</type>, with
+ 2 subclasses <type>XmlIdRegistryDocument</type> for "normal" documents,
+ and <type>XmlIdRegistryClipboard</type> for clipboard documents.
+ These classes are responsible for managing XML IDs for all elements
+ of the model. Only the implementation of the <type>Metadatable</type>
+ base class needs to know the registries, so they are not in the header.
+
+ The handling of XML IDs differs between clipboard and non-clipboard
+ documents in several aspects. Most importantly, non-clipboard documents
+ can have several elements associated with one XML ID.
+ This is necessary because of the weird undo implementation:
+ deleting a text node moves the deleted node to the undo array, but
+ executing undo will then create a <em>copy</em> of that node in the
+ document array. These 2 nodes must have the same XML ID, because
+ we cannot know whether the user will do a redo next, or something else.
+
+ Because we need to have a mechanism for several objects per XML ID anyway,
+ we use that also to enable some usability features:
+ The document registry has a list of Metadatables per XML ID.
+ This list is sorted by priority, i.e., the first element has highest
+ priority. When inserting copies, care must be taken that they are inserted
+ at the right position: either before or after the source.
+ This is done by <method>Metadatable::RegisterAsCopyOf</method>.
+ When a text node is split, then both resulting text nodes are inserted
+ into the list. If the user then deletes one text node, the other one
+ will have the XML ID.
+ Also, when a Metadatable is copied to the clipboard and then pasted,
+ the copy is inserted into the list. If the user then deletes the source,
+ the XML ID is not lost.
+ The goal is that it should be hard to lose an XML ID by accident, which
+ is especially important as long as we do not have an UI that displays them.
+
+ There are two subclasses of <type>Metadatable</type>:
+ <ul><li><type>MetadatableClipboard</type>: for copies in the clipboard</li>
+ <li><type>MetadatableUndo</type>: for undo, because a Metadatable
+ may be destroyed on delete and a new one created on undo.</li></ul>
+ These serve only to track the position in an XML ID list in a document
+ registry, so that future actions can insert objects at the right position.
+ Unfortunately, inserting dummy objects seems to be necessary:
+ <ul><li>it is not sufficent to just remember the saved id, because then
+ the relative priorities might change when executing the undo</li>
+ <li>it is not sufficient to record the position as an integer, because
+ if we delete a text node and then undo, the node will be copied(!),
+ and we will have one more node in the list.<li>
+ <li>it is not sufficient to record the pointer of the previous/next
+ Metadatable, because if we delete a text node, undo, and then
+ do something to clear the redo array, the original text node is
+ destroyed, and is replaced by the copy created by undo</li></ul>
+
+ If content from a non-clipboard document is copied into a clipboard
+ document, a dummy <type>MetadatableClipboard</type> is inserted into the
+ non-clipboard document registry in order to track the position of the
+ source element. When the clipboard content is pasted back into the source
+ document, this dummy object is used to associate the pasted element with
+ that same XML ID.
+
+ If a <type>Metadatable</type> is deleted or merged,
+ <method>Metadatable::CreateUndo</method> is called, and returns a
+ <type>MetadatableUndo<type> instance, which can be used to undo the action
+ by passing it to <method>Metadatable::RestoreMetadata</method>.
+
+ @author mst
+ */
+
+
+using namespace ::com::sun::star;
+
+using ::sfx2::isValidXmlId;
+
+
+namespace sfx2 {
+
+static const char s_content [] = "content.xml";
+static const char s_styles [] = "styles.xml";
+static const char s_prefix [] = "id"; // prefix for generated xml:id
+
+static bool isContentFile(::rtl::OUString const & i_rPath)
+{
+ return i_rPath.equalsAscii(s_content);
+}
+
+static bool isStylesFile (::rtl::OUString const & i_rPath)
+{
+ return i_rPath.equalsAscii(s_styles);
+}
+
+
+//=============================================================================
+// XML ID handling ---------------------------------------------------
+
+/** handles registration of XMetadatable.
+
+ This class is responsible for guaranteeing that XMetadatable objects
+ always have XML IDs that are unique within a stream.
+
+ This is an abstract base class; see subclasses XmlIdRegistryDocument and
+ XmlIdRegistryClipboard.
+
+ @see SwDoc::GetXmlIdRegistry
+ @see SwDocShell::GetXmlIdRegistry
+ */
+class XmlIdRegistry : public sfx2::IXmlIdRegistry
+{
+
+public:
+ XmlIdRegistry();
+
+ virtual ~XmlIdRegistry();
+
+ /** get the ODF element with the given metadata reference. */
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > SAL_CALL
+ GetElementByMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rReference) const;
+
+ /** register an ODF element at a newly generated, unique metadata reference.
+
+ <p>
+ Find a fresh XML ID, and register it for the element.
+ The generated ID does not occur in any stream of the document.
+ </p>
+ */
+ virtual void RegisterMetadatableAndCreateID(Metadatable& i_xObject) = 0;
+
+ /** try to register an ODF element at a given XML ID, or update its
+ registation to a different XML ID.
+
+ <p>
+ If the given new metadata reference is not already occupied in the
+ document, unregister the element at its old metadata reference if
+ it has one, and register the new metadata reference for the element.
+ Note that this method only ensures that XML IDs are unique per stream,
+ so using the same XML ID in both content.xml and styles.xml is allowed.
+ </p>
+
+ @returns
+ true iff the element has successfully been registered
+ */
+ virtual bool TryRegisterMetadatable(Metadatable& i_xObject,
+ ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref)
+ = 0;
+
+ /** unregister an ODF element.
+
+ <p>
+ Unregister the element at its metadata reference.
+ Does not remove the metadata reference from the element.
+ </p>
+
+ @see RemoveXmlIdForElement
+ */
+ virtual void UnregisterMetadatable(Metadatable const&) = 0;
+
+ /** get the metadata reference for the given element. */
+ ::com::sun::star::beans::StringPair
+ GetXmlIdForElement(Metadatable const&) const;
+
+ /** remove the metadata reference for the given element. */
+ virtual void RemoveXmlIdForElement(Metadatable const&) = 0;
+
+protected:
+
+ virtual bool LookupXmlId(const Metadatable& i_xObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const = 0;
+
+ virtual Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const = 0;
+};
+
+// XmlIdRegistryDocument ---------------------------------------------
+
+/** non-clipboard documents */
+class XmlIdRegistryDocument : public XmlIdRegistry
+{
+
+public:
+ XmlIdRegistryDocument();
+
+ virtual ~XmlIdRegistryDocument();
+
+ virtual void RegisterMetadatableAndCreateID(Metadatable& i_xObject);
+
+ virtual bool TryRegisterMetadatable(Metadatable& i_xObject,
+ ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref);
+
+ virtual void UnregisterMetadatable(Metadatable const&);
+
+ virtual void RemoveXmlIdForElement(Metadatable const&);
+
+ /** register i_rCopy as a copy of i_rSource,
+ with precedence iff i_bCopyPrecedesSource is true */
+ void RegisterCopy(Metadatable const& i_rSource, Metadatable & i_rCopy,
+ const bool i_bCopyPrecedesSource);
+
+ /** create a Undo Metadatable for i_rObject. */
+ ::boost::shared_ptr<MetadatableUndo> CreateUndo(
+ Metadatable const& i_rObject);
+
+ /** merge i_rMerged and i_rOther into i_rMerged. */
+ void JoinMetadatables(Metadatable & i_rMerged, Metadatable const& i_rOther);
+
+ // unfortunately public, Metadatable::RegisterAsCopyOf needs this
+ virtual bool LookupXmlId(const Metadatable& i_xObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const;
+
+private:
+
+ virtual Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const;
+
+ struct XmlIdRegistry_Impl;
+ ::std::auto_ptr<XmlIdRegistry_Impl> m_pImpl;
+};
+
+// MetadatableUndo ---------------------------------------------------
+
+/** the horrible Undo Metadatable: is inserted into lists to track position */
+class MetadatableUndo : public Metadatable
+{
+ /// as determined by the stream of the source in original document
+ const bool m_isInContent;
+public:
+ MetadatableUndo(const bool i_isInContent)
+ : m_isInContent(i_isInContent) { }
+ virtual ::sfx2::XmlIdRegistry& GetRegistry()
+ {
+ // N.B. for Undo, m_pReg is initialized by registering this as copy in
+ // CreateUndo; it is never cleared
+ OSL_ENSURE(m_pReg, "no m_pReg in MetadatableUndo ?");
+ return *m_pReg;
+ }
+ virtual bool IsInClipboard() const { return false; }
+ virtual bool IsInUndo() const { return true; }
+ virtual bool IsInContent() const { return m_isInContent; }
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > MakeUnoObject()
+ { OSL_ENSURE(false, "MetadatableUndo::MakeUnoObject"); throw; }
+};
+
+// MetadatableClipboard ----------------------------------------------
+
+/** the horrible Clipboard Metadatable: inserted into lists to track position */
+class MetadatableClipboard : public Metadatable
+{
+ /// as determined by the stream of the source in original document
+ const bool m_isInContent;
+public:
+ MetadatableClipboard(const bool i_isInContent)
+ : m_isInContent(i_isInContent) { }
+ virtual ::sfx2::XmlIdRegistry& GetRegistry()
+ {
+ // N.B. for Clipboard, m_pReg is initialized by registering this as copy in
+ // RegisterAsCopyOf; it is only cleared by OriginNoLongerInBusinessAnymore
+ OSL_ENSURE(m_pReg, "no m_pReg in MetadatableClipboard ?");
+ return *m_pReg;
+ }
+ virtual bool IsInClipboard() const { return true; }
+ virtual bool IsInUndo() const { return false; }
+ virtual bool IsInContent() const { return m_isInContent; }
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > MakeUnoObject()
+ { OSL_ENSURE(false, "MetadatableClipboard::MakeUnoObject"); throw; }
+ void OriginNoLongerInBusinessAnymore() { m_pReg = 0; }
+};
+
+// XmlIdRegistryClipboard --------------------------------------------
+
+class XmlIdRegistryClipboard : public XmlIdRegistry
+{
+
+public:
+ XmlIdRegistryClipboard();
+ virtual ~XmlIdRegistryClipboard();
+
+ virtual void RegisterMetadatableAndCreateID(Metadatable& i_xObject);
+
+ virtual bool TryRegisterMetadatable(Metadatable& i_xObject,
+ ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref);
+
+ virtual void UnregisterMetadatable(Metadatable const&);
+
+ virtual void RemoveXmlIdForElement(Metadatable const&);
+
+ /** register i_rCopy as a copy of i_rSource */
+ MetadatableClipboard & RegisterCopyClipboard(Metadatable & i_rCopy,
+ beans::StringPair const & i_rReference,
+ const bool i_isLatent);
+
+ /** get the Metadatable that links i_rObject to its origin registry */
+ MetadatableClipboard const* SourceLink(Metadatable const& i_rObject);
+
+private:
+ virtual bool LookupXmlId(const Metadatable& i_xObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const;
+
+ virtual Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const;
+
+ /** create a Clipboard Metadatable for i_rObject. */
+ ::boost::shared_ptr<MetadatableClipboard> CreateClipboard(
+ const bool i_isInContent);
+
+ struct XmlIdRegistry_Impl;
+ ::std::auto_ptr<XmlIdRegistry_Impl> m_pImpl;
+};
+
+
+//=============================================================================
+// XmlIdRegistry
+
+::sfx2::IXmlIdRegistry * createXmlIdRegistry(const bool i_DocIsClipboard)
+{
+ return i_DocIsClipboard
+ ? static_cast<XmlIdRegistry*>( new XmlIdRegistryClipboard )
+ : static_cast<XmlIdRegistry*>( new XmlIdRegistryDocument );
+}
+
+XmlIdRegistry::XmlIdRegistry()
+{
+}
+
+XmlIdRegistry::~XmlIdRegistry()
+{
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::rdf::XMetadatable > SAL_CALL
+XmlIdRegistry::GetElementByMetadataReference(
+ const beans::StringPair & i_rReference) const
+{
+ Metadatable* pObject( LookupElement(i_rReference.First,
+ i_rReference.Second) );
+ return pObject ? pObject->MakeUnoObject() : 0;
+}
+
+beans::StringPair
+XmlIdRegistry::GetXmlIdForElement(const Metadatable& i_rObject) const
+{
+ ::rtl::OUString path;
+ ::rtl::OUString idref;
+ if (LookupXmlId(i_rObject, path, idref))
+ {
+ if (LookupElement(path, idref) == &i_rObject)
+ {
+ return beans::StringPair(path, idref);
+ }
+ }
+ return beans::StringPair();
+}
+
+
+/// generate unique xml:id
+template< typename T >
+/*static*/ ::rtl::OUString create_id(const
+ ::std::hash_map< ::rtl::OUString, T, ::rtl::OUStringHash > & i_rXmlIdMap)
+{
+ const ::rtl::OUString prefix( ::rtl::OUString::createFromAscii(s_prefix) );
+ typename ::std::hash_map< ::rtl::OUString, T, ::rtl::OUStringHash >
+ ::const_iterator iter;
+ ::rtl::OUString id;
+ do
+ {
+ const int n( rand() );
+ id = prefix + ::rtl::OUString::valueOf(static_cast<sal_Int64>(n));
+ iter = i_rXmlIdMap.find(id);
+ }
+ while (iter != i_rXmlIdMap.end());
+ return id;
+}
+
+//=============================================================================
+// Document XML ID Registry (_Impl)
+
+/// element list
+typedef ::std::list< Metadatable* > XmlIdList_t;
+
+/// Idref -> (content.xml element list, styles.xml element list)
+typedef ::std::hash_map< ::rtl::OUString,
+ ::std::pair< XmlIdList_t, XmlIdList_t >, ::rtl::OUStringHash > XmlIdMap_t;
+
+/// pointer hash template
+template<typename T> struct PtrHash
+{
+ size_t operator() (T const * i_pT) const
+ {
+ return reinterpret_cast<size_t>(i_pT);
+ }
+};
+
+/// element -> (stream name, idref)
+typedef ::std::hash_map< const Metadatable*,
+ ::std::pair< ::rtl::OUString, ::rtl::OUString>, PtrHash<Metadatable> >
+ XmlIdReverseMap_t;
+
+struct XmlIdRegistryDocument::XmlIdRegistry_Impl
+{
+ XmlIdRegistry_Impl()
+ : m_XmlIdMap(), m_XmlIdReverseMap() { }
+
+ bool TryInsertMetadatable(Metadatable& i_xObject,
+ const ::rtl::OUString & i_rStream, const ::rtl::OUString & i_rIdref);
+
+ bool LookupXmlId(const Metadatable& i_xObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const;
+
+ Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const;
+
+ const XmlIdList_t * LookupElementList(
+ const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const;
+
+ XmlIdList_t * LookupElementList(
+ const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref)
+ {
+ return const_cast<XmlIdList_t*>(
+ const_cast<const XmlIdRegistry_Impl*>(this)
+ ->LookupElementList(i_rStreamName, i_rIdref));
+ }
+
+ XmlIdMap_t m_XmlIdMap;
+ XmlIdReverseMap_t m_XmlIdReverseMap;
+};
+
+// -------------------------------------------------------------------
+
+static void
+rmIter(XmlIdMap_t & i_rXmlIdMap, XmlIdMap_t::iterator const& i_rIter,
+ ::rtl::OUString const & i_rStream, Metadatable const& i_rObject)
+{
+ if (i_rIter != i_rXmlIdMap.end())
+ {
+ XmlIdList_t & rList( isContentFile(i_rStream)
+ ? i_rIter->second.first : i_rIter->second.second );
+ rList.remove(&const_cast<Metadatable&>(i_rObject));
+ if (i_rIter->second.first.empty() && i_rIter->second.second.empty())
+ {
+ i_rXmlIdMap.erase(i_rIter);
+ }
+ }
+}
+
+// -------------------------------------------------------------------
+
+const XmlIdList_t *
+XmlIdRegistryDocument::XmlIdRegistry_Impl::LookupElementList(
+ const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const
+{
+ const XmlIdMap_t::const_iterator iter( m_XmlIdMap.find(i_rIdref) );
+ if (iter != m_XmlIdMap.end())
+ {
+ OSL_ENSURE(!iter->second.first.empty() || !iter->second.second.empty(),
+ "null entry in m_XmlIdMap");
+ return (isContentFile(i_rStreamName))
+ ? &iter->second.first
+ : &iter->second.second;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+Metadatable*
+XmlIdRegistryDocument::XmlIdRegistry_Impl::LookupElement(
+ const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const
+{
+ if (!isValidXmlId(i_rStreamName, i_rIdref))
+ {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "illegal XmlId"), 0, 0);
+ }
+
+ const XmlIdList_t * pList( LookupElementList(i_rStreamName, i_rIdref) );
+ if (pList)
+ {
+ const XmlIdList_t::const_iterator iter(
+ ::std::find_if(pList->begin(), pList->end(),
+ ::boost::bind(
+ ::std::logical_not<bool>(),
+ ::boost::bind(
+ ::std::logical_or<bool>(),
+ ::boost::bind( &Metadatable::IsInUndo, _1 ),
+ ::boost::bind( &Metadatable::IsInClipboard, _1 )
+ ) ) ) );
+ if (iter != pList->end())
+ {
+ return *iter;
+ }
+ }
+ return 0;
+}
+
+bool
+XmlIdRegistryDocument::XmlIdRegistry_Impl::LookupXmlId(
+ const Metadatable& i_rObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const
+{
+ const XmlIdReverseMap_t::const_iterator iter(
+ m_XmlIdReverseMap.find(&i_rObject) );
+ if (iter != m_XmlIdReverseMap.end())
+ {
+ OSL_ENSURE(!iter->second.first.equalsAscii(""),
+ "null stream in m_XmlIdReverseMap");
+ OSL_ENSURE(!iter->second.second.equalsAscii(""),
+ "null id in m_XmlIdReverseMap");
+ o_rStream = iter->second.first;
+ o_rIdref = iter->second.second;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool
+XmlIdRegistryDocument::XmlIdRegistry_Impl::TryInsertMetadatable(
+ Metadatable & i_rObject,
+ const ::rtl::OUString & i_rStreamName, const ::rtl::OUString & i_rIdref)
+{
+ const bool bContent( isContentFile(i_rStreamName) );
+ OSL_ENSURE(isContentFile(i_rStreamName) || isStylesFile(i_rStreamName),
+ "invalid stream");
+
+ XmlIdList_t * pList( LookupElementList(i_rStreamName, i_rIdref) );
+ if (pList)
+ {
+ if (pList->empty())
+ {
+ pList->push_back( &i_rObject );
+ return true;
+ }
+ else
+ {
+ // this is only called from TryRegister now, so check
+ // if all elements in the list are deleted (in undo) or
+ // placeholders, then "steal" the id from them
+ if ( pList->end() == ::std::find_if(pList->begin(), pList->end(),
+ ::boost::bind(
+ ::std::logical_not<bool>(),
+ ::boost::bind(
+ ::std::logical_or<bool>(),
+ ::boost::bind( &Metadatable::IsInUndo, _1 ),
+ ::boost::bind( &Metadatable::IsInClipboard, _1 )
+ ) ) ) )
+ {
+// ??? this is not undoable
+// pList->clear();
+// pList->push_back( &i_rObject );
+ pList->push_front( &i_rObject );
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ m_XmlIdMap.insert(::std::make_pair(i_rIdref, bContent
+ ? ::std::make_pair( XmlIdList_t( 1, &i_rObject ), XmlIdList_t() )
+ : ::std::make_pair( XmlIdList_t(), XmlIdList_t( 1, &i_rObject ) )));
+ return true;
+ }
+}
+
+//=============================================================================
+// Document XML ID Registry
+
+
+XmlIdRegistryDocument::XmlIdRegistryDocument()
+ : m_pImpl( new XmlIdRegistry_Impl )
+{
+}
+
+static void
+removeLink(Metadatable* i_pObject)
+{
+ OSL_ENSURE(i_pObject, "null in list ???");
+ if (!i_pObject) return;
+ if (i_pObject->IsInClipboard())
+ {
+ MetadatableClipboard* pLink(
+ dynamic_cast<MetadatableClipboard*>( i_pObject ) );
+ OSL_ENSURE(pLink, "IsInClipboard, but no MetadatableClipboard ?");
+ if (pLink)
+ {
+ pLink->OriginNoLongerInBusinessAnymore();
+ }
+ }
+}
+
+XmlIdRegistryDocument::~XmlIdRegistryDocument()
+{
+ // notify all list elements that are actually in the clipboard
+ for (XmlIdMap_t::iterator iter(m_pImpl->m_XmlIdMap.begin());
+ iter != m_pImpl->m_XmlIdMap.end(); ++iter)
+ {
+ ::std::for_each(iter->second.first.begin(), iter->second.first.end(),
+ removeLink);
+ ::std::for_each(iter->second.second.begin(), iter->second.second.end(),
+ removeLink);
+ }
+}
+
+bool
+XmlIdRegistryDocument::LookupXmlId(
+ const Metadatable& i_rObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const
+{
+ return m_pImpl->LookupXmlId(i_rObject, o_rStream, o_rIdref);
+}
+
+Metadatable*
+XmlIdRegistryDocument::LookupElement(
+ const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const
+{
+ return m_pImpl->LookupElement(i_rStreamName, i_rIdref);
+}
+
+bool
+XmlIdRegistryDocument::TryRegisterMetadatable(Metadatable & i_rObject,
+ ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref)
+{
+ OSL_TRACE("TryRegisterMetadatable: %p (%s#%s)\n", &i_rObject,
+ ::rtl::OUStringToOString(i_rStreamName, RTL_TEXTENCODING_UTF8).getStr(),
+ ::rtl::OUStringToOString(i_rIdref, RTL_TEXTENCODING_UTF8).getStr());
+
+ OSL_ENSURE(!dynamic_cast<MetadatableUndo*>(&i_rObject),
+ "TryRegisterMetadatable called for MetadatableUndo?");
+ OSL_ENSURE(!dynamic_cast<MetadatableClipboard*>(&i_rObject),
+ "TryRegisterMetadatable called for MetadatableClipboard?");
+
+ if (!isValidXmlId(i_rStreamName, i_rIdref))
+ {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "illegal XmlId"), 0, 0);
+ }
+ if (i_rObject.IsInContent()
+ ? !isContentFile(i_rStreamName)
+ : !isStylesFile(i_rStreamName))
+ {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "illegal XmlId: wrong stream"), 0, 0);
+ }
+
+ ::rtl::OUString old_path;
+ ::rtl::OUString old_idref;
+ m_pImpl->LookupXmlId(i_rObject, old_path, old_idref);
+ if (old_path == i_rStreamName && old_idref == i_rIdref)
+ {
+ return (m_pImpl->LookupElement(old_path, old_idref) == &i_rObject);
+ }
+ XmlIdMap_t::iterator old_id( m_pImpl->m_XmlIdMap.end() );
+ if (!old_idref.equalsAscii(""))
+ {
+ old_id = m_pImpl->m_XmlIdMap.find(old_idref);
+ OSL_ENSURE(old_id != m_pImpl->m_XmlIdMap.end(), "old id not found");
+ }
+ if (m_pImpl->TryInsertMetadatable(i_rObject, i_rStreamName, i_rIdref))
+ {
+ rmIter(m_pImpl->m_XmlIdMap, old_id, old_path, i_rObject);
+ m_pImpl->m_XmlIdReverseMap[&i_rObject] =
+ ::std::make_pair(i_rStreamName, i_rIdref);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void
+XmlIdRegistryDocument::RegisterMetadatableAndCreateID(Metadatable & i_rObject)
+{
+ OSL_TRACE("RegisterMetadatableAndCreateID: %p\n", &i_rObject);
+
+ OSL_ENSURE(!dynamic_cast<MetadatableUndo*>(&i_rObject),
+ "RegisterMetadatableAndCreateID called for MetadatableUndo?");
+ OSL_ENSURE(!dynamic_cast<MetadatableClipboard*>(&i_rObject),
+ "RegisterMetadatableAndCreateID called for MetadatableClipboard?");
+
+ const bool isInContent( i_rObject.IsInContent() );
+ const ::rtl::OUString stream( ::rtl::OUString::createFromAscii(
+ isInContent ? s_content : s_styles ) );
+ // check if we have a latent xmlid, and if yes, remove it
+ ::rtl::OUString old_path;
+ ::rtl::OUString old_idref;
+ m_pImpl->LookupXmlId(i_rObject, old_path, old_idref);
+
+ XmlIdMap_t::iterator old_id( m_pImpl->m_XmlIdMap.end() );
+ if (!old_idref.equalsAscii(""))
+ {
+ old_id = m_pImpl->m_XmlIdMap.find(old_idref);
+ OSL_ENSURE(old_id != m_pImpl->m_XmlIdMap.end(), "old id not found");
+ if (m_pImpl->LookupElement(old_path, old_idref) == &i_rObject)
+ {
+ return;
+ }
+ else
+ {
+ // remove latent xmlid
+ rmIter(m_pImpl->m_XmlIdMap, old_id, old_path, i_rObject);
+ }
+ }
+
+ // create id
+ const ::rtl::OUString id( create_id(m_pImpl->m_XmlIdMap) );
+ OSL_ENSURE(m_pImpl->m_XmlIdMap.find(id) == m_pImpl->m_XmlIdMap.end(),
+ "created id is in use");
+ m_pImpl->m_XmlIdMap.insert(::std::make_pair(id, isInContent
+ ? ::std::make_pair( XmlIdList_t( 1, &i_rObject ), XmlIdList_t() )
+ : ::std::make_pair( XmlIdList_t(), XmlIdList_t( 1, &i_rObject ) )));
+ m_pImpl->m_XmlIdReverseMap[&i_rObject] = ::std::make_pair(stream, id);
+}
+
+void XmlIdRegistryDocument::UnregisterMetadatable(const Metadatable& i_rObject)
+{
+ OSL_TRACE("UnregisterMetadatable: %p\n", &i_rObject);
+
+ ::rtl::OUString path;
+ ::rtl::OUString idref;
+ if (!m_pImpl->LookupXmlId(i_rObject, path, idref))
+ {
+ OSL_ENSURE(false, "unregister: no xml id?");
+ return;
+ }
+ const XmlIdMap_t::iterator iter( m_pImpl->m_XmlIdMap.find(idref) );
+ if (iter != m_pImpl->m_XmlIdMap.end())
+ {
+ rmIter(m_pImpl->m_XmlIdMap, iter, path, i_rObject);
+ }
+}
+
+void XmlIdRegistryDocument::RemoveXmlIdForElement(const Metadatable& i_rObject)
+{
+ OSL_TRACE("RemoveXmlIdForElement: %p\n", &i_rObject);
+
+ const XmlIdReverseMap_t::iterator iter(
+ m_pImpl->m_XmlIdReverseMap.find(&i_rObject) );
+ if (iter != m_pImpl->m_XmlIdReverseMap.end())
+ {
+ OSL_ENSURE(!iter->second.second.equalsAscii(""),
+ "null id in m_XmlIdReverseMap");
+ m_pImpl->m_XmlIdReverseMap.erase(iter);
+ }
+}
+
+// -------------------------------------------------------------------
+
+void XmlIdRegistryDocument::RegisterCopy(Metadatable const& i_rSource,
+ Metadatable & i_rCopy, const bool i_bCopyPrecedesSource)
+{
+ OSL_TRACE("RegisterCopy: %p -> %p (%d)\n",
+ &i_rSource, &i_rCopy, i_bCopyPrecedesSource);
+
+ // potential sources: clipboard, undo array, splitNode
+ // assumption: stream change can only happen via clipboard, and is handled
+ // by Metadatable::RegisterAsCopyOf
+ OSL_ENSURE(i_rSource.IsInUndo() || i_rCopy.IsInUndo() ||
+ (i_rSource.IsInContent() == i_rCopy.IsInContent()),
+ "RegisterCopy: not in same stream?");
+
+ ::rtl::OUString path;
+ ::rtl::OUString idref;
+ if (!m_pImpl->LookupXmlId( i_rSource, path, idref ))
+ {
+ OSL_ENSURE(false, "no xml id?");
+ return;
+ }
+ XmlIdList_t * pList ( m_pImpl->LookupElementList(path, idref) );
+ OSL_ENSURE( ::std::find( pList->begin(), pList->end(), &i_rCopy )
+ == pList->end(), "copy already registered???");
+ XmlIdList_t::iterator srcpos(
+ ::std::find( pList->begin(), pList->end(), &i_rSource ) );
+ OSL_ENSURE(srcpos != pList->end(), "source not in list???");
+ if (srcpos == pList->end())
+ {
+ return;
+ }
+ if (i_bCopyPrecedesSource)
+ {
+ pList->insert( srcpos, &i_rCopy );
+ }
+ else
+ {
+ // for undo push_back does not work! must insert right after source
+ pList->insert( ++srcpos, &i_rCopy );
+ }
+ m_pImpl->m_XmlIdReverseMap.insert(::std::make_pair(&i_rCopy,
+ ::std::make_pair(path, idref)));
+}
+
+::boost::shared_ptr<MetadatableUndo>
+XmlIdRegistryDocument::CreateUndo(Metadatable const& i_rObject)
+{
+ OSL_TRACE("CreateUndo: %p\n", &i_rObject);
+
+ return ::boost::shared_ptr<MetadatableUndo>(
+ new MetadatableUndo(i_rObject.IsInContent()) );
+}
+
+/*
+i_rMerged is both a source and the target node of the merge
+i_rOther is the other source, and will be deleted after the merge
+
+dimensions: none|latent|actual empty|nonempty
+i_rMerged(1) i_rOther(2) result
+ *|empty *|empty => 1|2 (arbitrary)
+ *|empty *|nonempty => 2
+ *|nonempty *|empty => 1
+ none|nonempty none|nonempty => none
+ none|nonempty latent|nonempty => 2
+latent|nonempty none|nonempty => 1
+latent|nonempty latent|nonempty => 1|2
+ *|nonempty actual|nonempty => 2
+actual|nonempty *|nonempty => 1
+actual|nonempty actual|nonempty => 1|2
+*/
+void
+XmlIdRegistryDocument::JoinMetadatables(
+ Metadatable & i_rMerged, Metadatable const & i_rOther)
+{
+ OSL_TRACE("JoinMetadatables: %p <- %p\n", &i_rMerged, &i_rOther);
+
+ bool mergedOwnsRef;
+ ::rtl::OUString path;
+ ::rtl::OUString idref;
+ if (m_pImpl->LookupXmlId(i_rMerged, path, idref))
+ {
+ mergedOwnsRef = (m_pImpl->LookupElement(path, idref) == &i_rMerged);
+ }
+ else
+ {
+ OSL_ENSURE(false, "JoinMetadatables: no xmlid?");
+ return;
+ }
+ if (!mergedOwnsRef)
+ {
+ i_rMerged.RemoveMetadataReference();
+ i_rMerged.RegisterAsCopyOf(i_rOther, true);
+ return;
+ }
+ // other cases: merged has actual ref and is nonempty,
+ // other has latent/actual ref and is nonempty: other loses => nothing to do
+}
+
+
+//=============================================================================
+// Clipboard XML ID Registry (_Impl)
+
+struct RMapEntry
+{
+ RMapEntry() : m_pLink() { }
+ RMapEntry(::rtl::OUString const& i_rStream,
+ ::rtl::OUString const& i_rXmlId,
+ ::boost::shared_ptr<MetadatableClipboard> const& i_pLink
+ = ::boost::shared_ptr<MetadatableClipboard>())
+ : m_Stream(i_rStream), m_XmlId(i_rXmlId), m_pLink(i_pLink)
+ {}
+ ::rtl::OUString m_Stream;
+ ::rtl::OUString m_XmlId;
+ // this would have been an auto_ptr, if only that would have compiled...
+ ::boost::shared_ptr<MetadatableClipboard> m_pLink;
+};
+
+/// element -> (stream name, idref, source)
+typedef ::std::hash_map< const Metadatable*,
+ struct RMapEntry,
+ PtrHash<Metadatable> >
+ ClipboardXmlIdReverseMap_t;
+
+/// Idref -> (content.xml element, styles.xml element)
+typedef ::std::hash_map< ::rtl::OUString,
+ ::std::pair< Metadatable*, Metadatable* >, ::rtl::OUStringHash >
+ ClipboardXmlIdMap_t;
+
+struct XmlIdRegistryClipboard::XmlIdRegistry_Impl
+{
+ XmlIdRegistry_Impl()
+ : m_XmlIdMap(), m_XmlIdReverseMap() { }
+
+ bool TryInsertMetadatable(Metadatable& i_xObject,
+ const ::rtl::OUString & i_rStream, const ::rtl::OUString & i_rIdref);
+
+ bool LookupXmlId(const Metadatable& i_xObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref,
+ MetadatableClipboard const* &o_rpLink) const;
+
+ Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const;
+
+ Metadatable* const* LookupEntry(const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const;
+
+ Metadatable* * LookupEntry(const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref)
+ {
+ return const_cast<Metadatable**>(
+ const_cast<const XmlIdRegistry_Impl*>(this)
+ ->LookupEntry(i_rStreamName, i_rIdref));
+ }
+
+ ClipboardXmlIdMap_t m_XmlIdMap;
+ ClipboardXmlIdReverseMap_t m_XmlIdReverseMap;
+};
+
+// -------------------------------------------------------------------
+
+static void
+rmIter(ClipboardXmlIdMap_t & i_rXmlIdMap,
+ ClipboardXmlIdMap_t::iterator const& i_rIter,
+ ::rtl::OUString const & i_rStream, Metadatable const& i_rObject)
+{
+ if (i_rIter != i_rXmlIdMap.end())
+ {
+ Metadatable *& rMeta = isContentFile(i_rStream)
+ ? i_rIter->second.first : i_rIter->second.second;
+ if (rMeta == &i_rObject)
+ {
+ rMeta = 0;
+ }
+ if (!i_rIter->second.first && !i_rIter->second.second)
+ {
+ i_rXmlIdMap.erase(i_rIter);
+ }
+ }
+}
+
+// -------------------------------------------------------------------
+
+Metadatable* const*
+XmlIdRegistryClipboard::XmlIdRegistry_Impl::LookupEntry(
+ const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const
+{
+ if (!isValidXmlId(i_rStreamName, i_rIdref))
+ {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "illegal XmlId"), 0, 0);
+ }
+
+ const ClipboardXmlIdMap_t::const_iterator iter( m_XmlIdMap.find(i_rIdref) );
+ if (iter != m_XmlIdMap.end())
+ {
+ OSL_ENSURE(iter->second.first || iter->second.second,
+ "null entry in m_XmlIdMap");
+ return (isContentFile(i_rStreamName))
+ ? &iter->second.first
+ : &iter->second.second;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+Metadatable*
+XmlIdRegistryClipboard::XmlIdRegistry_Impl::LookupElement(
+ const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const
+{
+ Metadatable * const * ppEntry = LookupEntry(i_rStreamName, i_rIdref);
+ return ppEntry ? *ppEntry : 0;
+}
+
+bool
+XmlIdRegistryClipboard::XmlIdRegistry_Impl::LookupXmlId(
+ const Metadatable& i_rObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref,
+ MetadatableClipboard const* &o_rpLink) const
+{
+ const ClipboardXmlIdReverseMap_t::const_iterator iter(
+ m_XmlIdReverseMap.find(&i_rObject) );
+ if (iter != m_XmlIdReverseMap.end())
+ {
+ OSL_ENSURE(!iter->second.m_Stream.equalsAscii(""),
+ "null stream in m_XmlIdReverseMap");
+ OSL_ENSURE(!iter->second.m_XmlId.equalsAscii(""),
+ "null id in m_XmlIdReverseMap");
+ o_rStream = iter->second.m_Stream;
+ o_rIdref = iter->second.m_XmlId;
+ o_rpLink = iter->second.m_pLink.get();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool
+XmlIdRegistryClipboard::XmlIdRegistry_Impl::TryInsertMetadatable(
+ Metadatable & i_rObject,
+ const ::rtl::OUString & i_rStreamName, const ::rtl::OUString & i_rIdref)
+{
+ bool bContent( isContentFile(i_rStreamName) );
+ OSL_ENSURE(isContentFile(i_rStreamName) || isStylesFile(i_rStreamName),
+ "invalid stream");
+
+ //wntmsci12 won't parse this:
+// Metadatable ** ppEntry( LookupEntry(i_rStreamName, i_rIdref) );
+ Metadatable ** ppEntry = LookupEntry(i_rStreamName, i_rIdref);
+ if (ppEntry)
+ {
+ if (*ppEntry)
+ {
+ return false;
+ }
+ else
+ {
+ *ppEntry = &i_rObject;
+ return true;
+ }
+ }
+ else
+ {
+ m_XmlIdMap.insert(::std::make_pair(i_rIdref, bContent
+ ? ::std::make_pair( &i_rObject, static_cast<Metadatable*>(0) )
+ : ::std::make_pair( static_cast<Metadatable*>(0), &i_rObject )));
+ return true;
+ }
+}
+
+//=============================================================================
+// Clipboard XML ID Registry
+
+
+XmlIdRegistryClipboard::XmlIdRegistryClipboard()
+ : m_pImpl( new XmlIdRegistry_Impl )
+{
+}
+
+XmlIdRegistryClipboard::~XmlIdRegistryClipboard()
+{
+}
+
+bool
+XmlIdRegistryClipboard::LookupXmlId(
+ const Metadatable& i_rObject,
+ ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const
+{
+ const MetadatableClipboard * pLink;
+ return m_pImpl->LookupXmlId(i_rObject, o_rStream, o_rIdref, pLink);
+}
+
+Metadatable*
+XmlIdRegistryClipboard::LookupElement(
+ const ::rtl::OUString & i_rStreamName,
+ const ::rtl::OUString & i_rIdref) const
+{
+ return m_pImpl->LookupElement(i_rStreamName, i_rIdref);
+}
+
+bool
+XmlIdRegistryClipboard::TryRegisterMetadatable(Metadatable & i_rObject,
+ ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref)
+{
+ OSL_TRACE("TryRegisterMetadatable: %p (%s#%s)\n", &i_rObject,
+ ::rtl::OUStringToOString(i_rStreamName, RTL_TEXTENCODING_UTF8).getStr(),
+ ::rtl::OUStringToOString(i_rIdref, RTL_TEXTENCODING_UTF8).getStr());
+
+ OSL_ENSURE(!dynamic_cast<MetadatableUndo*>(&i_rObject),
+ "TryRegisterMetadatable called for MetadatableUndo?");
+ OSL_ENSURE(!dynamic_cast<MetadatableClipboard*>(&i_rObject),
+ "TryRegisterMetadatable called for MetadatableClipboard?");
+
+ if (!isValidXmlId(i_rStreamName, i_rIdref))
+ {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "illegal XmlId"), 0, 0);
+ }
+ if (i_rObject.IsInContent()
+ ? !isContentFile(i_rStreamName)
+ : !isStylesFile(i_rStreamName))
+ {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "illegal XmlId: wrong stream"), 0, 0);
+ }
+
+ ::rtl::OUString old_path;
+ ::rtl::OUString old_idref;
+ const MetadatableClipboard * pLink;
+ m_pImpl->LookupXmlId(i_rObject, old_path, old_idref, pLink);
+ if (old_path == i_rStreamName && old_idref == i_rIdref)
+ {
+ return (m_pImpl->LookupElement(old_path, old_idref) == &i_rObject);
+ }
+ ClipboardXmlIdMap_t::iterator old_id( m_pImpl->m_XmlIdMap.end() );
+ if (!old_idref.equalsAscii(""))
+ {
+ old_id = m_pImpl->m_XmlIdMap.find(old_idref);
+ OSL_ENSURE(old_id != m_pImpl->m_XmlIdMap.end(), "old id not found");
+ }
+ if (m_pImpl->TryInsertMetadatable(i_rObject, i_rStreamName, i_rIdref))
+ {
+ rmIter(m_pImpl->m_XmlIdMap, old_id, old_path, i_rObject);
+ m_pImpl->m_XmlIdReverseMap[&i_rObject] =
+ RMapEntry(i_rStreamName, i_rIdref);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void
+XmlIdRegistryClipboard::RegisterMetadatableAndCreateID(Metadatable & i_rObject)
+{
+ OSL_TRACE("RegisterMetadatableAndCreateID: %p\n", &i_rObject);
+
+ OSL_ENSURE(!dynamic_cast<MetadatableUndo*>(&i_rObject),
+ "RegisterMetadatableAndCreateID called for MetadatableUndo?");
+ OSL_ENSURE(!dynamic_cast<MetadatableClipboard*>(&i_rObject),
+ "RegisterMetadatableAndCreateID called for MetadatableClipboard?");
+
+ bool isInContent( i_rObject.IsInContent() );
+ ::rtl::OUString stream( ::rtl::OUString::createFromAscii(
+ isInContent ? s_content : s_styles ) );
+
+ ::rtl::OUString old_path;
+ ::rtl::OUString old_idref;
+ LookupXmlId(i_rObject, old_path, old_idref);
+ if (!old_idref.equalsAscii("") &&
+ (m_pImpl->LookupElement(old_path, old_idref) == &i_rObject))
+ {
+ return;
+ }
+
+ // create id
+ const ::rtl::OUString id( create_id(m_pImpl->m_XmlIdMap) );
+ OSL_ENSURE(m_pImpl->m_XmlIdMap.find(id) == m_pImpl->m_XmlIdMap.end(),
+ "created id is in use");
+ m_pImpl->m_XmlIdMap.insert(::std::make_pair(id, isInContent
+ ? ::std::make_pair( &i_rObject, static_cast<Metadatable*>(0) )
+ : ::std::make_pair( static_cast<Metadatable*>(0), &i_rObject )));
+ // N.B.: if i_rObject had a latent XmlId, then we implicitly delete the
+ // MetadatableClipboard and thus the latent XmlId here
+ m_pImpl->m_XmlIdReverseMap[&i_rObject] = RMapEntry(stream, id);
+}
+
+void XmlIdRegistryClipboard::UnregisterMetadatable(const Metadatable& i_rObject)
+{
+ OSL_TRACE("UnregisterMetadatable: %p\n", &i_rObject);
+
+ ::rtl::OUString path;
+ ::rtl::OUString idref;
+ const MetadatableClipboard * pLink;
+ if (!m_pImpl->LookupXmlId(i_rObject, path, idref, pLink))
+ {
+ OSL_ENSURE(false, "unregister: no xml id?");
+ return;
+ }
+ const ClipboardXmlIdMap_t::iterator iter( m_pImpl->m_XmlIdMap.find(idref) );
+ if (iter != m_pImpl->m_XmlIdMap.end())
+ {
+ rmIter(m_pImpl->m_XmlIdMap, iter, path, i_rObject);
+ }
+}
+
+
+void XmlIdRegistryClipboard::RemoveXmlIdForElement(const Metadatable& i_rObject)
+{
+ OSL_TRACE("RemoveXmlIdForElement: %p\n", &i_rObject);
+
+ ClipboardXmlIdReverseMap_t::iterator iter(
+ m_pImpl->m_XmlIdReverseMap.find(&i_rObject) );
+ if (iter != m_pImpl->m_XmlIdReverseMap.end())
+ {
+ OSL_ENSURE(!iter->second.m_XmlId.equalsAscii(""),
+ "null id in m_XmlIdReverseMap");
+ m_pImpl->m_XmlIdReverseMap.erase(iter);
+ }
+}
+
+// -------------------------------------------------------------------
+
+::boost::shared_ptr<MetadatableClipboard>
+XmlIdRegistryClipboard::CreateClipboard(const bool i_isInContent)
+{
+ OSL_TRACE("CreateClipboard: \n");
+
+ return ::boost::shared_ptr<MetadatableClipboard>(
+ new MetadatableClipboard(i_isInContent) );
+}
+
+MetadatableClipboard &
+XmlIdRegistryClipboard::RegisterCopyClipboard(Metadatable & i_rCopy,
+ beans::StringPair const & i_rReference,
+ const bool i_isLatent)
+{
+ OSL_TRACE("RegisterCopyClipboard: %p -> "/*"%p"*/"(%s#%s) (%d)\n",
+ /*&i_rSource,*/ &i_rCopy,
+ ::rtl::OUStringToOString(i_rReference.First,
+ RTL_TEXTENCODING_UTF8).getStr(),
+ ::rtl::OUStringToOString(i_rReference.Second,
+ RTL_TEXTENCODING_UTF8).getStr(),
+ i_isLatent);
+
+ // N.B.: when copying to the clipboard, the selection is always inserted
+ // into the body, even if the source is a header/footer!
+ // so we do not check whether the stream is right in this function
+
+ if (!isValidXmlId(i_rReference.First, i_rReference.Second))
+ {
+ throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
+ "illegal XmlId"), 0, 0);
+ }
+
+ if (!i_isLatent)
+ {
+ // this should succeed assuming clipboard has a single source document
+ const bool success( m_pImpl->TryInsertMetadatable(i_rCopy,
+ i_rReference.First, i_rReference.Second) );
+ OSL_ENSURE(success, "RegisterCopyClipboard: TryInsert failed?");
+ (void) success;
+ }
+ const ::boost::shared_ptr<MetadatableClipboard> pLink(
+ CreateClipboard( isContentFile(i_rReference.First)) );
+ m_pImpl->m_XmlIdReverseMap.insert(::std::make_pair(&i_rCopy,
+ RMapEntry(i_rReference.First, i_rReference.Second, pLink)));
+ return *pLink.get();
+}
+
+MetadatableClipboard const*
+XmlIdRegistryClipboard::SourceLink(Metadatable const& i_rObject)
+{
+ ::rtl::OUString path;
+ ::rtl::OUString idref;
+ const MetadatableClipboard * pLink( 0 );
+ m_pImpl->LookupXmlId(i_rObject, path, idref, pLink);
+ return pLink;
+}
+
+
+//=============================================================================
+// Metadatable mixin
+
+
+Metadatable::~Metadatable()
+{
+ RemoveMetadataReference();
+}
+
+void Metadatable::RemoveMetadataReference()
+{
+ try
+ {
+ if (m_pReg)
+ {
+ m_pReg->UnregisterMetadatable( *this );
+ m_pReg->RemoveXmlIdForElement( *this );
+ m_pReg = 0;
+ }
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE(false, "Metadatable::RemoveMetadataReference: exception");
+ }
+}
+
+// ::com::sun::star::rdf::XMetadatable:
+beans::StringPair
+Metadatable::GetMetadataReference() const
+{
+ if (m_pReg)
+ {
+ return m_pReg->GetXmlIdForElement(*this);
+ }
+ return beans::StringPair();
+}
+
+void
+Metadatable::SetMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rReference)
+{
+ if (i_rReference.Second.equalsAscii(""))
+ {
+ RemoveMetadataReference();
+ }
+ else
+ {
+ ::rtl::OUString streamName( i_rReference.First );
+ if (streamName.equalsAscii(""))
+ {
+ // handle empty stream name as auto-detect.
+ // necessary for importing flat file format.
+ streamName = ::rtl::OUString::createFromAscii(
+ IsInContent() ? s_content : s_styles );
+ }
+ XmlIdRegistry & rReg( dynamic_cast<XmlIdRegistry&>( GetRegistry() ) );
+ if (rReg.TryRegisterMetadatable(*this, streamName, i_rReference.Second))
+ {
+ m_pReg = &rReg;
+ }
+ else
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii("Metadatable::"
+ "SetMetadataReference: argument is invalid"), /*this*/0, 0);
+ }
+ }
+}
+
+void Metadatable::EnsureMetadataReference()
+{
+ XmlIdRegistry& rReg(
+ m_pReg ? *m_pReg : dynamic_cast<XmlIdRegistry&>( GetRegistry() ) );
+ rReg.RegisterMetadatableAndCreateID( *this );
+ m_pReg = &rReg;
+}
+
+const ::sfx2::IXmlIdRegistry& GetRegistryConst(Metadatable const& i_rObject)
+{
+ return const_cast< Metadatable& >( i_rObject ).GetRegistry();
+}
+
+void
+Metadatable::RegisterAsCopyOf(Metadatable const & i_rSource,
+ const bool i_bCopyPrecedesSource)
+{
+ OSL_ENSURE(typeid(*this) == typeid(i_rSource)
+ || typeid(i_rSource) == typeid(MetadatableUndo)
+ || typeid(*this) == typeid(MetadatableUndo)
+ || typeid(i_rSource) == typeid(MetadatableClipboard)
+ || typeid(*this) == typeid(MetadatableClipboard),
+ "RegisterAsCopyOf element with different class?");
+ OSL_ENSURE(!this->m_pReg, "RegisterAsCopyOf called on element with XmlId?");
+
+ if (this->m_pReg)
+ {
+ RemoveMetadataReference();
+ }
+
+ try
+ {
+ if (i_rSource.m_pReg)
+ {
+ XmlIdRegistry & rReg(
+ dynamic_cast<XmlIdRegistry&>( GetRegistry() ) );
+ if (i_rSource.m_pReg == &rReg)
+ {
+ OSL_ENSURE(!IsInClipboard(),
+ "RegisterAsCopy: both in clipboard?");
+ if (!IsInClipboard())
+ {
+ XmlIdRegistryDocument & rRegDoc(
+ dynamic_cast<XmlIdRegistryDocument&>( rReg ) );
+ rRegDoc.RegisterCopy(i_rSource, *this,
+ i_bCopyPrecedesSource);
+ this->m_pReg = &rRegDoc;
+ }
+ return;
+ }
+ // source is in different document
+ XmlIdRegistryDocument * pRegDoc(
+ dynamic_cast<XmlIdRegistryDocument *>(&rReg) );
+ XmlIdRegistryClipboard * pRegClp(
+ dynamic_cast<XmlIdRegistryClipboard*>(&rReg) );
+
+ if (pRegClp)
+ {
+ beans::StringPair SourceRef(
+ i_rSource.m_pReg->GetXmlIdForElement(i_rSource) );
+ bool isLatent( SourceRef.Second.equalsAscii("") );
+ XmlIdRegistryDocument * pSourceRegDoc(
+ dynamic_cast<XmlIdRegistryDocument*>(i_rSource.m_pReg) );
+ OSL_ENSURE(pSourceRegDoc, "RegisterAsCopyOf: 2 clipboards?");
+ if (!pSourceRegDoc) return;
+ // this is a copy _to_ the clipboard
+ if (isLatent)
+ {
+ pSourceRegDoc->LookupXmlId(i_rSource,
+ SourceRef.First, SourceRef.Second);
+ }
+ Metadatable & rLink(
+ pRegClp->RegisterCopyClipboard(*this, SourceRef, isLatent));
+ this->m_pReg = pRegClp;
+ // register as copy in the non-clipboard registry
+ pSourceRegDoc->RegisterCopy(i_rSource, rLink,
+ false); // i_bCopyPrecedesSource);
+ rLink.m_pReg = pSourceRegDoc;
+ }
+ else if (pRegDoc)
+ {
+ XmlIdRegistryClipboard * pSourceRegClp(
+ dynamic_cast<XmlIdRegistryClipboard*>(i_rSource.m_pReg) );
+ OSL_ENSURE(pSourceRegClp,
+ "RegisterAsCopyOf: 2 non-clipboards?");
+ if (!pSourceRegClp) return;
+ const MetadatableClipboard * pLink(
+ pSourceRegClp->SourceLink(i_rSource) );
+ // may happen if src got its id via UNO call
+ if (!pLink) return;
+ // only register copy if clipboard content is from this SwDoc!
+ if (pLink && (&GetRegistryConst(*pLink) == pRegDoc))
+ {
+ // this is a copy _from_ the clipboard; check if the
+ // element is still in the same stream
+ // N.B.: we check the stream of pLink, not of i_rSource!
+ bool srcInContent( pLink->IsInContent() );
+ bool tgtInContent( this->IsInContent() );
+ if (srcInContent == tgtInContent)
+ {
+ pRegDoc->RegisterCopy(*pLink, *this,
+ true); // i_bCopyPrecedesSource);
+ this->m_pReg = pRegDoc;
+ }
+ // otherwise: stream change! do not register!
+ }
+ }
+ else
+ {
+ OSL_ENSURE(false, "neither RegDoc nor RegClp cannot happen");
+ }
+#if 0
+ {
+ //FIXME: do we need this at all???
+ XmlIdRegistryDocument & rRegDoc(
+ dynamic_cast<XmlIdRegistryDocument&>( rReg ) );
+ {
+ if (rRegDoc.TryRegisterMetadatable(*this, SourceRef))
+ {
+ this->m_pReg = &rRegDoc;
+ }
+ }
+ }
+#endif
+ }
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE(false, "Metadatable::RegisterAsCopyOf: exception");
+ }
+}
+
+::boost::shared_ptr<MetadatableUndo> Metadatable::CreateUndo(
+ const bool i_isDelete)
+{
+ OSL_ENSURE(!IsInUndo(), "CreateUndo called for object in undo?");
+ OSL_ENSURE(!IsInClipboard(), "CreateUndo called for object in clipboard?");
+ try
+ {
+ if (!IsInClipboard() && !IsInUndo() && m_pReg)
+ {
+ XmlIdRegistryDocument * pRegDoc(
+ dynamic_cast<XmlIdRegistryDocument*>( m_pReg ) );
+ ::boost::shared_ptr<MetadatableUndo> pUndo(
+ pRegDoc->CreateUndo(*this) );
+ pRegDoc->RegisterCopy(*this, *pUndo, false);
+ pUndo->m_pReg = pRegDoc;
+
+ if (i_isDelete)
+ {
+ RemoveMetadataReference();
+ }
+ return pUndo;
+ }
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE(false, "Metadatable::CreateUndo: exception");
+ }
+ return ::boost::shared_ptr<MetadatableUndo>();
+}
+
+void Metadatable::RestoreMetadata(
+ ::boost::shared_ptr<MetadatableUndo> const& i_pUndo)
+{
+ OSL_ENSURE(!IsInUndo(), "RestoreMetadata called for object in undo?");
+ OSL_ENSURE(!IsInClipboard(),
+ "RestoreMetadata called for object in clipboard?");
+ if (IsInClipboard() || IsInUndo()) return;
+ RemoveMetadataReference();
+ if (i_pUndo)
+ {
+ this->RegisterAsCopyOf(*i_pUndo, true);
+ }
+}
+
+void
+Metadatable::JoinMetadatable(Metadatable const & i_rOther,
+ const bool i_isMergedEmpty, const bool i_isOtherEmpty)
+{
+ OSL_ENSURE(!IsInUndo(), "JoinMetadatables called for object in undo?");
+ OSL_ENSURE(!IsInClipboard(),
+ "JoinMetadatables called for object in clipboard?");
+ if (IsInClipboard() || IsInUndo()) return;
+
+ if (i_isOtherEmpty && !i_isMergedEmpty)
+ {
+ // other is empty, thus loses => nothing to do
+ return;
+ }
+ if (i_isMergedEmpty && !i_isOtherEmpty)
+ {
+ this->RemoveMetadataReference();
+ this->RegisterAsCopyOf(i_rOther, true);
+ return;
+ }
+
+ if (!i_rOther.m_pReg)
+ {
+ // other doesn't have xmlid, thus loses => nothing to do
+ return;
+ }
+ if (!m_pReg)
+ {
+ this->RegisterAsCopyOf(i_rOther, true);
+ // assumption: i_rOther will be deleted, so don't unregister it here
+ return;
+ }
+ try
+ {
+ XmlIdRegistryDocument * pRegDoc(
+ dynamic_cast<XmlIdRegistryDocument*>( m_pReg ) );
+ OSL_ENSURE(pRegDoc, "JoinMetadatable: no pRegDoc?");
+ if (pRegDoc)
+ {
+ pRegDoc->JoinMetadatables(*this, i_rOther);
+ }
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE(false, "Metadatable::JoinMetadatable: exception");
+ }
+}
+
+
+//=============================================================================
+// XMetadatable mixin
+
+// ::com::sun::star::rdf::XNode:
+::rtl::OUString SAL_CALL MetadatableMixin::getStringValue()
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ return getNamespace() + getLocalName();
+}
+
+// ::com::sun::star::rdf::XURI:
+::rtl::OUString SAL_CALL MetadatableMixin::getLocalName()
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ beans::StringPair mdref( getMetadataReference() );
+ if (!mdref.Second.getLength())
+ {
+ ensureMetadataReference(); // N.B.: side effect!
+ mdref = getMetadataReference();
+ }
+ ::rtl::OUStringBuffer buf;
+ buf.append(mdref.First);
+ buf.append(static_cast<sal_Unicode>('#'));
+ buf.append(mdref.Second);
+ return buf.makeStringAndClear();
+}
+
+::rtl::OUString SAL_CALL MetadatableMixin::getNamespace()
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ const uno::Reference< frame::XModel > xModel( GetModel() );
+ const uno::Reference< rdf::XURI > xDMA( xModel, uno::UNO_QUERY_THROW );
+ return xDMA->getStringValue();
+}
+
+// ::com::sun::star::rdf::XMetadatable:
+beans::StringPair SAL_CALL
+MetadatableMixin::getMetadataReference()
+throw (uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ Metadatable* pObject( GetCoreObject() );
+ if (pObject)
+ {
+ return pObject->GetMetadataReference();
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+void SAL_CALL
+MetadatableMixin::setMetadataReference(
+ const beans::StringPair & i_rReference)
+throw (uno::RuntimeException, lang::IllegalArgumentException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ Metadatable* pObject( GetCoreObject() );
+ if (pObject)
+ {
+ return pObject->SetMetadataReference(i_rReference);
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+void SAL_CALL MetadatableMixin::ensureMetadataReference()
+throw (uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ Metadatable* pObject( GetCoreObject() );
+ if (pObject)
+ {
+ return pObject->EnsureMetadataReference();
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+} // namespace sfx2
+
+
+//=============================================================================
+
+#if OSL_DEBUG_LEVEL > 1
+
+static ::sfx2::XmlIdRegistryDocument s_Reg;
+static ::sfx2::XmlIdRegistryClipboard s_RegClip;
+
+class MockMetadatable : public ::sfx2::Metadatable
+{
+public:
+ MockMetadatable(bool i_isInClip = false) :
+ m_bInClipboard(i_isInClip), m_bInUndo(false), m_bInContent(true) {}
+ bool m_bInClipboard;
+ bool m_bInUndo;
+ bool m_bInContent;
+ virtual bool IsInClipboard() const { return m_bInClipboard; }
+ virtual bool IsInUndo() const { return m_bInUndo; }
+ virtual bool IsInContent() const { return m_bInContent; }
+ virtual ::sfx2::XmlIdRegistry& GetRegistry() { return m_bInClipboard ? static_cast< ::sfx2::XmlIdRegistry&>(s_RegClip) : static_cast< ::sfx2::XmlIdRegistry&>(s_Reg); }
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > MakeUnoObject() { return 0; }
+};
+
+bool operator==(beans::StringPair p1, beans::StringPair p2)
+{
+ return p1.First == p2.First && p1.Second == p2.Second;
+}
+
+void test()
+{
+ OSL_TRACE("SwMetadatable test(): start\n");
+ MockMetadatable m1;
+ MockMetadatable m2;
+ MockMetadatable m3;
+ MockMetadatable m4;
+ MockMetadatable m5;
+ ::rtl::OUString empty;
+ ::rtl::OUString content( ::rtl::OUString::createFromAscii("content.xml") );
+ ::rtl::OUString styles ( ::rtl::OUString::createFromAscii("styles.xml") );
+ ::rtl::OUString sid1( ::rtl::OUString::createFromAscii("id1") );
+ ::rtl::OUString sid2( ::rtl::OUString::createFromAscii("id2") );
+ ::rtl::OUString sid3( ::rtl::OUString::createFromAscii("id3") );
+ ::rtl::OUString sid4( ::rtl::OUString::createFromAscii("id4") );
+ beans::StringPair id1(content, sid1);
+ beans::StringPair id2(content, sid2);
+ beans::StringPair id3(content, sid3);
+ beans::StringPair id4(styles, sid4);
+ beans::StringPair id3e(empty, sid3);
+ beans::StringPair id4e(empty, sid4);
+ m1.SetMetadataReference(id1);
+ OSL_ENSURE(m1.GetMetadataReference() == id1, "set failed");
+ try {
+ m2.SetMetadataReference(id1);
+ OSL_ENSURE(false, "set duplicate succeeded");
+ } catch (lang::IllegalArgumentException) { }
+ m1.SetMetadataReference(id1);
+ OSL_ENSURE(m1.GetMetadataReference() == id1, "set failed (existing)");
+ m1.EnsureMetadataReference();
+ OSL_ENSURE(m1.GetMetadataReference() == id1, "ensure failed (existing)");
+
+ m2.EnsureMetadataReference();
+ beans::StringPair m2id(m2.GetMetadataReference());
+ OSL_ENSURE(m2id.Second.getLength(), "ensure failed");
+ m2.EnsureMetadataReference();
+ OSL_ENSURE(m2.GetMetadataReference() == m2id, "ensure failed (idempotent)");
+
+ m1.m_bInUndo = true;
+ OSL_ENSURE(!m1.GetMetadataReference().Second.getLength(), "move to undo failed");
+
+ m1.m_bInUndo = false;
+ OSL_ENSURE(m1.GetMetadataReference() == id1, "move from undo failed");
+
+ m1.m_bInUndo = true;
+ try {
+ m2.SetMetadataReference(id1); // steal!
+ } catch (lang::IllegalArgumentException &) {
+ OSL_ENSURE(false, "set duplicate to undo failed");
+ }
+ m1.m_bInUndo = false;
+ OSL_ENSURE(!m1.GetMetadataReference().Second.getLength(), "move from undo: duplicate");
+
+ m3.RegisterAsCopyOf(m2);
+ OSL_ENSURE(m2.GetMetadataReference() == id1, "copy: source");
+ OSL_ENSURE(!m3.GetMetadataReference().Second.getLength(), "copy: duplicate");
+ m4.RegisterAsCopyOf(m3);
+ OSL_ENSURE(m2.GetMetadataReference() == id1, "copy: source");
+ OSL_ENSURE(!m3.GetMetadataReference().Second.getLength(), "copy: duplicate");
+ OSL_ENSURE(!m4.GetMetadataReference().Second.getLength(), "copy: duplicate");
+ m2.m_bInUndo = true;
+ OSL_ENSURE(m3.GetMetadataReference() == id1, "duplicate to undo");
+ OSL_ENSURE(!m2.GetMetadataReference().Second.getLength(), "duplicate to undo");
+ m2.m_bInUndo = false;
+ OSL_ENSURE(m2.GetMetadataReference() == id1, "duplicate from undo");
+ OSL_ENSURE(!m3.GetMetadataReference().Second.getLength(), "duplicate from undo");
+
+ m4.EnsureMetadataReference(); // new!
+ beans::StringPair m4id(m4.GetMetadataReference());
+ OSL_ENSURE(m4id.Second.getLength() && !(m4id == id1), "ensure on duplicate");
+
+ MockMetadatable mc1(true); // in clipboard
+ MockMetadatable mc2(true);
+ MockMetadatable mc3(true);
+ MockMetadatable mc4(true);
+ MockMetadatable m2p;
+ MockMetadatable m3p;
+
+ mc1.SetMetadataReference(id2);
+ OSL_ENSURE(mc1.GetMetadataReference() == id2, "set failed");
+ try {
+ mc2.SetMetadataReference(id2);
+ OSL_ENSURE(false, "set duplicate succeeded");
+ } catch (lang::IllegalArgumentException) { }
+ mc1.SetMetadataReference(id2);
+ OSL_ENSURE(mc1.GetMetadataReference() == id2, "set failed (existing)");
+ mc1.EnsureMetadataReference();
+ OSL_ENSURE(mc1.GetMetadataReference() == id2, "ensure failed (existing)");
+ mc2.EnsureMetadataReference();
+ beans::StringPair mc2id(mc2.GetMetadataReference());
+ OSL_ENSURE(mc2id.Second.getLength(), "ensure failed");
+ mc2.EnsureMetadataReference();
+ OSL_ENSURE(mc2.GetMetadataReference() == mc2id, "ensure failed (idempotent)");
+ mc2.RemoveMetadataReference();
+ OSL_ENSURE(!mc2.GetMetadataReference().Second.getLength(), "remove failed");
+
+ // set up mc2 as copy of m2 and mc3 as copy of m3
+ mc3.RegisterAsCopyOf(m3);
+ OSL_ENSURE(!mc3.GetMetadataReference().Second.getLength() , "copy to clipboard (latent)");
+ mc2.RegisterAsCopyOf(m2);
+ OSL_ENSURE(mc2.GetMetadataReference() == id1, "copy to clipboard (non-latent)");
+ // paste mc2 to m2p and mc3 to m3p
+ m2p.RegisterAsCopyOf(mc2);
+ OSL_ENSURE(!m2p.GetMetadataReference().Second.getLength() , "paste from clipboard (non-latent)");
+ m3p.RegisterAsCopyOf(mc3);
+ OSL_ENSURE(!m3p.GetMetadataReference().Second.getLength() , "paste from clipboard (latent)");
+ // delete m2, m2p, m3
+ m2.RemoveMetadataReference();
+ OSL_ENSURE(!m2.GetMetadataReference().Second.getLength(), "remove failed");
+ OSL_ENSURE(m2p.GetMetadataReference() == id1, "paste-remove (non-latent)");
+ m2p.RemoveMetadataReference();
+ OSL_ENSURE(!m2p.GetMetadataReference().Second.getLength(), "remove failed");
+ OSL_ENSURE(m3.GetMetadataReference() == id1, "paste-remove2 (non-latent)");
+ m3.RemoveMetadataReference();
+ OSL_ENSURE(!m3.GetMetadataReference().Second.getLength(), "remove failed");
+ OSL_ENSURE(m3p.GetMetadataReference() == id1, "paste-remove (latent)");
+ // delete mc2
+ mc2.SetMetadataReference(beans::StringPair());
+ OSL_ENSURE(!mc3.GetMetadataReference().Second.getLength() , "in clipboard becomes non-latent");
+ // paste mc2
+ m2p.RegisterAsCopyOf(mc2);
+ OSL_ENSURE(!m2p.GetMetadataReference().Second.getLength(), "remove-paste");
+ OSL_ENSURE(m3p.GetMetadataReference() == id1, "remove-paste (stolen)");
+
+ // auto-detect stream
+ m5.SetMetadataReference(id3e);
+ OSL_ENSURE(m5.GetMetadataReference() == id3, "auto-detect (content)");
+ m5.m_bInContent = false;
+ m5.SetMetadataReference(id4e);
+ OSL_ENSURE(m5.GetMetadataReference() == id4, "auto-detect (styles)");
+
+ OSL_TRACE("sfx2::Metadatable test(): finished\n");
+}
+
+struct Test { Test() { test(); } };
+static Test s_test;
+
+
+#include <stdio.h>
+
+static void dump(sfx2::XmlIdList_t * pList)
+#ifdef GCC
+__attribute__ ((unused))
+#endif
+;
+static void dump(sfx2::XmlIdList_t * pList)
+{
+ fprintf(stderr, "\nXmlIdList(%p): ", pList);
+ for (sfx2::XmlIdList_t::iterator i = pList->begin(); i != pList->end(); ++i)
+ {
+ fprintf(stderr, "%p ", *i);
+ }
+ fprintf(stderr, "\n");
+}
+
+#endif
+
diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index 79197b6e5f52..c81595cfc6e6 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -3305,6 +3305,7 @@ SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< ::com::sun::star::b
// that must be copied here
SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE );
+ if (!pFileNameItem) throw uno::RuntimeException();
::rtl::OUString aNewTempFileURL = SfxMedium::CreateTempCopyWithExt( pFileNameItem->GetValue() );
if ( aNewTempFileURL.getLength() )
{
@@ -3326,6 +3327,7 @@ SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< ::com::sun::star::b
bReadOnly = TRUE;
SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE );
+ if (!pFileNameItem) throw uno::RuntimeException();
aLogicName = pFileNameItem->GetValue();
nStorOpenMode = bReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
bDirect = FALSE;
diff --git a/sfx2/source/doc/makefile.mk b/sfx2/source/doc/makefile.mk
index b46ee5aa30e8..4c893288ebb8 100644
--- a/sfx2/source/doc/makefile.mk
+++ b/sfx2/source/doc/makefile.mk
@@ -40,6 +40,10 @@ ENABLE_EXCEPTIONS=TRUE
.INCLUDE : settings.mk
.INCLUDE : $(PRJ)$/util$/makefile.pmk
+.IF "$(SYSTEM_LIBXML)" == "YES"
+CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS)
+.ENDIF
+
# --- Files --------------------------------------------------------
SRS1NAME=$(TARGET)
@@ -80,10 +84,13 @@ SLOFILES = \
$(SLO)$/docinsert.obj \
$(SLO)$/docmacromode.obj \
$(SLO)$/SfxDocumentMetaData.obj \
+ $(SLO)$/DocumentMetadataAccess.obj \
+ $(SLO)$/Metadatable.obj \
$(SLO)$/sfxmodelfactory.obj \
$(SLO)$/docstoragemodifylistener.obj \
$(SLO)$/querytemplate.obj
+
# --- Tagets -------------------------------------------------------
.INCLUDE : target.mk
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 3571c4226ff7..a47fc1bf4747 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -415,7 +415,7 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
if ( pDocInfItem )
{
// parameter, e.g. from replayed macro
- pDocInfItem->updateDocumentInfo(getDocProperties());
+ pDocInfItem->UpdateDocumentInfo(getDocProperties(), true);
SetUseUserData( pDocInfItem->IsUseUserData() );
}
else
@@ -478,7 +478,7 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
if ( pDocInfoItem )
{
// user has done some changes to DocumentInfo
- pDocInfoItem->updateDocumentInfo(getDocProperties());
+ pDocInfoItem->UpdateDocumentInfo(getDocProperties());
SetUseUserData( ((const SfxDocumentInfoItem *)pDocInfoItem)->IsUseUserData() );
// add data from dialog for possible recording purposes
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 76e6bb59e189..2c98f2a5d141 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -621,6 +621,7 @@ sal_Bool SfxObjectShell::DoLoad( SfxMedium *pMed )
else
aBaseURL = pMed->GetBaseURL();
}
+ pMed->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, aBaseURL ) );
pImp->nLoadedFlags = 0;
pImp->bModelInitialized = sal_False;
diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx
index d91ec392aa92..3edf1ddb60d7 100644
--- a/sfx2/source/doc/objxtor.cxx
+++ b/sfx2/source/doc/objxtor.cxx
@@ -722,11 +722,11 @@ namespace
{
static BasicManager* lcl_getBasicManagerForDocument( const SfxObjectShell& _rDocument )
{
- if ( !_rDocument.pImp->m_bNoBasicCapabilities )
+ if ( !_rDocument.Get_Impl()->m_bNoBasicCapabilities )
{
- if ( !_rDocument.pImp->bBasicInitialized )
+ if ( !_rDocument.Get_Impl()->bBasicInitialized )
const_cast< SfxObjectShell& >( _rDocument ).InitBasicManager_Impl();
- return _rDocument.pImp->pBasicManager->get();
+ return _rDocument.Get_Impl()->pBasicManager->get();
}
// assume we do not have Basic ourself, but we can refer to another
@@ -794,9 +794,13 @@ namespace
try
{
Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY );
+ const Reference< XComponentContext > xContext(
+ ::comphelper::getProcessComponentContext() );
_rxContainer.set ( _bScript
- ? DocumentScriptLibraryContainer::create( comphelper_getProcessComponentContext(), xStorageDoc )
- : DocumentDialogLibraryContainer::create( comphelper_getProcessComponentContext(), xStorageDoc )
+ ? DocumentScriptLibraryContainer::create(
+ xContext, xStorageDoc )
+ : DocumentDialogLibraryContainer::create(
+ xContext, xStorageDoc )
, UNO_QUERY_THROW );
}
catch( const Exception& )
@@ -1065,6 +1069,12 @@ void SfxObjectShell::SetAutoStyleFilterIndex(sal_uInt16 nSet)
pImp->nStyleFilter = nSet;
}
+sal_uInt16 SfxObjectShell::GetAutoStyleFilterIndex()
+{
+ return pImp->nStyleFilter;
+}
+
+
void SfxObjectShell::SetCurrentComponent( const Reference< XInterface >& _rxComponent )
{
if ( _rxComponent.get() == s_xCurrentComponent.get().get() )
diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index 43ce1593bbaf..53673b505d6d 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -66,6 +66,7 @@
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/Aspects.hpp>
#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp>
#include <comphelper/enumhelper.hxx> // can be removed when this is a "real" service
#include <cppuhelper/interfacecontainer.hxx>
@@ -124,6 +125,8 @@
#include "brokenpackageint.hxx"
#include "graphhelp.hxx"
#include <sfx2/msgpool.hxx>
+#include <sfx2/DocumentMetadataAccess.hxx>
+
#include <sfxresid.hxx>
//________________________________________________________________________________________________________
@@ -135,13 +138,14 @@ static const ::rtl::OUString SERVICENAME_DESKTOP = ::rtl::OUString::createFromAs
//________________________________________________________________________________________________________
namespace css = ::com::sun::star;
-using namespace com::sun::star;
+using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
//________________________________________________________________________________________________________
// impl. declarations
//________________________________________________________________________________________________________
+
struct IMPL_SfxBaseModel_DataContainer : public ::sfx2::IModifiableDocument
{
// counter for SfxBaseModel instances created.
@@ -172,6 +176,8 @@ struct IMPL_SfxBaseModel_DataContainer : public ::sfx2::IModifiableDocument
::rtl::OUString m_sModuleIdentifier;
css::uno::Reference< css::frame::XTitle > m_xTitleHelper;
css::uno::Reference< css::frame::XUntitledNumbers > m_xNumberedControllers;
+ uno::Reference< rdf::XDocumentMetadataAccess> m_xDocumentMetadata;
+
IMPL_SfxBaseModel_DataContainer( ::osl::Mutex& rMutex, SfxObjectShell* pObjectShell )
: m_pObjectShell ( pObjectShell )
@@ -184,6 +190,7 @@ struct IMPL_SfxBaseModel_DataContainer : public ::sfx2::IModifiableDocument
, m_pStorageModifyListen ( NULL )
, m_xTitleHelper ()
, m_xNumberedControllers ()
+ , m_xDocumentMetadata () // lazy
{
// increase global instance counter.
++g_nInstanceCounter;
@@ -201,6 +208,58 @@ struct IMPL_SfxBaseModel_DataContainer : public ::sfx2::IModifiableDocument
if ( m_pObjectShell.Is() && !m_pObjectShell->IsModified() )
m_pObjectShell->SetModified( sal_True );
}
+
+ uno::Reference<rdf::XDocumentMetadataAccess> GetDMA()
+ {
+ if (!m_xDocumentMetadata.is())
+ {
+ OSL_ENSURE(m_pObjectShell, "GetDMA: no object shell?");
+ if (!m_pObjectShell)
+ {
+ return 0;
+ }
+
+ const uno::Reference<uno::XComponentContext> xContext(
+ ::comphelper::getProcessComponentContext());
+ ::rtl::OUString uri;
+ const uno::Reference<frame::XModel> xModel(
+ m_pObjectShell->GetModel());
+ const uno::Reference<lang::XMultiComponentFactory> xMsf(
+ xContext->getServiceManager());
+ const uno::Reference<frame::
+ XTransientDocumentsDocumentContentFactory> xTDDCF(
+ xMsf->createInstanceWithContext(
+ ::rtl::OUString::createFromAscii( "com.sun.star.frame."
+ "TransientDocumentsDocumentContentFactory"),
+ xContext),
+ uno::UNO_QUERY_THROW);
+ const uno::Reference<ucb::XContent> xContent(
+ xTDDCF->createDocumentContent(xModel) );
+ OSL_ENSURE(xContent.is(), "GetDMA: cannot create DocumentContent");
+ if (!xContent.is())
+ {
+ return 0;
+ }
+ uri = xContent->getIdentifier()->getContentIdentifier();
+ OSL_ENSURE(uri.getLength(), "GetDMA: empty uri?");
+ if (uri.getLength() && !uri.endsWithAsciiL("/", 1))
+ {
+ uri = uri + ::rtl::OUString::createFromAscii("/");
+ }
+
+ m_xDocumentMetadata = new ::sfx2::DocumentMetadataAccess(
+ xContext, *m_pObjectShell, uri);
+ }
+ return m_xDocumentMetadata;
+ }
+
+ uno::Reference<rdf::XDocumentMetadataAccess> CreateDMAUninitialized()
+ {
+ return (m_pObjectShell)
+ ? new ::sfx2::DocumentMetadataAccess(
+ ::comphelper::getProcessComponentContext(), *m_pObjectShell)
+ : 0;
+ }
};
// static member initialization.
@@ -417,9 +476,9 @@ SfxSaveGuard::~SfxSaveGuard()
//________________________________________________________________________________________________________
DBG_NAME(sfx2_SfxBaseModel)
SfxBaseModel::SfxBaseModel( SfxObjectShell *pObjectShell )
-: IMPL_SfxBaseModel_MutexContainer()
+: BaseMutex()
, m_pData( new IMPL_SfxBaseModel_DataContainer( m_aMutex, pObjectShell ) )
-, m_bSupportEmbeddedScripts( pObjectShell && pObjectShell->pImp ? !pObjectShell->pImp->m_bNoBasicCapabilities : false )
+, m_bSupportEmbeddedScripts( pObjectShell && pObjectShell->Get_Impl() ? !pObjectShell->Get_Impl()->m_bNoBasicCapabilities : false )
{
DBG_CTOR(sfx2_SfxBaseModel,NULL);
if ( pObjectShell != NULL )
@@ -686,10 +745,9 @@ void SAL_CALL SfxBaseModel::dispose() throw(::com::sun::star::uno::RuntimeExcept
m_pData->m_xDocumentInfo = 0;
}
- if ( m_pData->m_xDocumentProperties.is() )
- {
- m_pData->m_xDocumentProperties = 0;
- }
+ m_pData->m_xDocumentProperties.clear();
+
+ m_pData->m_xDocumentMetadata.clear();
EndListening( *m_pData->m_pObjectShell );
@@ -3829,3 +3887,325 @@ css::uno::Reference< css::frame::XController2 > SAL_CALL SfxBaseModel::createVie
{
return css::uno::Reference< css::frame::XController2 >();
}
+
+//=============================================================================
+// RDF DocumentMetadataAccess
+
+// ::com::sun::star::rdf::XRepositorySupplier:
+uno::Reference< rdf::XRepository > SAL_CALL
+SfxBaseModel::getRDFRepository() throw (uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->getRDFRepository();
+}
+
+// ::com::sun::star::rdf::XNode:
+::rtl::OUString SAL_CALL
+SfxBaseModel::getStringValue() throw (uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->getStringValue();
+}
+
+// ::com::sun::star::rdf::XURI:
+::rtl::OUString SAL_CALL
+SfxBaseModel::getNamespace() throw (uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->getNamespace();
+}
+
+::rtl::OUString SAL_CALL
+SfxBaseModel::getLocalName() throw (uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->getLocalName();
+}
+
+// ::com::sun::star::rdf::XDocumentMetadataAccess:
+uno::Reference< rdf::XMetadatable > SAL_CALL
+SfxBaseModel::getElementByMetadataReference(
+ const ::com::sun::star::beans::StringPair & i_rReference)
+throw (uno::RuntimeException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->getElementByMetadataReference(i_rReference);
+}
+
+uno::Reference< rdf::XMetadatable > SAL_CALL
+SfxBaseModel::getElementByURI(const uno::Reference< rdf::XURI > & i_xURI)
+throw (uno::RuntimeException, lang::IllegalArgumentException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->getElementByURI(i_xURI);
+}
+
+uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
+SfxBaseModel::getMetadataGraphsWithType(
+ const uno::Reference<rdf::XURI> & i_xType)
+throw (uno::RuntimeException, lang::IllegalArgumentException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->getMetadataGraphsWithType(i_xType);
+}
+
+uno::Reference<rdf::XURI> SAL_CALL
+SfxBaseModel::addMetadataFile(const ::rtl::OUString & i_rFileName,
+ const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ container::ElementExistException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->addMetadataFile(i_rFileName, i_rTypes);
+}
+
+uno::Reference<rdf::XURI> SAL_CALL
+SfxBaseModel::importMetadataFile(::sal_Int16 i_Format,
+ const uno::Reference< io::XInputStream > & i_xInStream,
+ const ::rtl::OUString & i_rFileName,
+ const uno::Reference< rdf::XURI > & i_xBaseURI,
+ const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ datatransfer::UnsupportedFlavorException,
+ container::ElementExistException, rdf::ParseException, io::IOException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->importMetadataFile(i_Format,
+ i_xInStream, i_rFileName, i_xBaseURI, i_rTypes);
+}
+
+void SAL_CALL
+SfxBaseModel::removeMetadataFile(
+ const uno::Reference< rdf::XURI > & i_xGraphName)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ container::NoSuchElementException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->removeMetadataFile(i_xGraphName);
+}
+
+void SAL_CALL
+SfxBaseModel::addContentOrStylesFile(const ::rtl::OUString & i_rFileName)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ container::ElementExistException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->addContentOrStylesFile(i_rFileName);
+}
+
+void SAL_CALL
+SfxBaseModel::removeContentOrStylesFile(const ::rtl::OUString & i_rFileName)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ container::NoSuchElementException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->removeContentOrStylesFile(i_rFileName);
+}
+
+void SAL_CALL
+SfxBaseModel::loadMetadataFromStorage(
+ uno::Reference< embed::XStorage > const & i_xStorage,
+ uno::Reference<rdf::XURI> const & i_xBaseURI,
+ uno::Reference<task::XInteractionHandler> const & i_xHandler)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ lang::WrappedTargetException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(
+ m_pData->CreateDMAUninitialized());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ try {
+ xDMA->loadMetadataFromStorage(i_xStorage, i_xBaseURI, i_xHandler);
+ } catch (lang::IllegalArgumentException &) {
+ throw; // not initialized
+ } catch (uno::Exception &) {
+ // UGLY: if it's a RuntimeException, we can't be sure DMA is initialzed
+ m_pData->m_xDocumentMetadata = xDMA;
+ throw;
+ }
+ m_pData->m_xDocumentMetadata = xDMA;
+
+}
+
+void SAL_CALL
+SfxBaseModel::storeMetadataToStorage(
+ uno::Reference< embed::XStorage > const & i_xStorage)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ lang::WrappedTargetException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->storeMetadataToStorage(i_xStorage);
+}
+
+void SAL_CALL
+SfxBaseModel::loadMetadataFromMedium(
+ const uno::Sequence< beans::PropertyValue > & i_rMedium)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ lang::WrappedTargetException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(
+ m_pData->CreateDMAUninitialized());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ try {
+ xDMA->loadMetadataFromMedium(i_rMedium);
+ } catch (lang::IllegalArgumentException &) {
+ throw; // not initialized
+ } catch (uno::Exception &) {
+ // UGLY: if it's a RuntimeException, we can't be sure DMA is initialzed
+ m_pData->m_xDocumentMetadata = xDMA;
+ throw;
+ }
+ m_pData->m_xDocumentMetadata = xDMA;
+}
+
+void SAL_CALL
+SfxBaseModel::storeMetadataToMedium(
+ const uno::Sequence< beans::PropertyValue > & i_rMedium)
+throw (uno::RuntimeException, lang::IllegalArgumentException,
+ lang::WrappedTargetException)
+{
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( impl_isDisposed() )
+ throw lang::DisposedException();
+
+ const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
+ if (!xDMA.is()) {
+ throw uno::RuntimeException( ::rtl::OUString::createFromAscii(
+ "model has no document metadata"), *this );
+ }
+
+ return xDMA->storeMetadataToMedium(i_rMedium);
+}
+
diff --git a/sfx2/util/makefile.mk b/sfx2/util/makefile.mk
index cfed0a838ffa..5ee6e64daca0 100644
--- a/sfx2/util/makefile.mk
+++ b/sfx2/util/makefile.mk
@@ -98,7 +98,9 @@ SHL1STDLIBS+=\
$(CPPULIB) \
$(VOSLIB) \
$(SALLIB) \
- $(SJLIB)
+ $(SJLIB) \
+ $(LIBXML2LIB) \
+
.IF "$(GUI)"=="WNT"