1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "precompiled_xmloff.hxx" 29 30 #include "RDFaExportHelper.hxx" 31 32 #include "xmloff/xmlnmspe.hxx" 33 34 #include <xmloff/xmlexp.hxx> 35 #include <xmloff/xmltoken.hxx> 36 37 #include <comphelper/stlunosequence.hxx> 38 #include <comphelper/stl_types.hxx> 39 40 #include <com/sun/star/uri/XUriReference.hpp> 41 #include <com/sun/star/uri/XUriReferenceFactory.hpp> 42 #include <com/sun/star/rdf/Statement.hpp> 43 #include <com/sun/star/rdf/URIs.hpp> 44 #include <com/sun/star/rdf/URI.hpp> 45 #include <com/sun/star/rdf/XLiteral.hpp> 46 #include <com/sun/star/rdf/XRepositorySupplier.hpp> 47 #include <com/sun/star/rdf/XDocumentRepository.hpp> 48 49 #include <rtl/ustrbuf.hxx> 50 51 #include <boost/bind.hpp> 52 #include <boost/iterator_adaptors.hpp> 53 #ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ // from iterator_adaptors.hpp 54 // N.B.: the check for the header guard _of a specific version of boost_ 55 // is here so this may work on different versions of boost, 56 // which sadly put the goods in different header files 57 #include <boost/iterator/transform_iterator.hpp> 58 #endif 59 60 #include <functional> 61 #include <algorithm> 62 63 64 using namespace ::com::sun::star; 65 66 namespace xmloff { 67 68 static const char s_prefix [] = "_:b"; 69 70 static ::rtl::OUString 71 makeCURIE(SvXMLExport * i_pExport, 72 uno::Reference<rdf::XURI> const & i_xURI) 73 { 74 OSL_ENSURE(i_xURI.is(), "makeCURIE: null URI"); 75 if (!i_xURI.is()) throw uno::RuntimeException(); 76 77 const ::rtl::OUString Namespace( i_xURI->getNamespace() ); 78 OSL_ENSURE(Namespace.getLength(), "makeCURIE: no namespace"); 79 if (!Namespace.getLength()) throw uno::RuntimeException(); 80 81 ::rtl::OUStringBuffer buf; 82 buf.append( i_pExport->EnsureNamespace(Namespace) ); 83 buf.append( static_cast<sal_Unicode>(':') ); 84 // N.B.: empty LocalName is valid! 85 buf.append( i_xURI->getLocalName() ); 86 87 return buf.makeStringAndClear(); 88 } 89 90 // #i112473# SvXMLExport::GetRelativeReference() not right for RDF on SaveAs 91 // because the URIs in the repository are not rewritten on SaveAs, the 92 // URI of the loaded document has to be used, not the URI of the target doc. 93 static ::rtl::OUString 94 getRelativeReference(SvXMLExport const& rExport, ::rtl::OUString const& rURI) 95 { 96 uno::Reference< rdf::XURI > const xModelURI( 97 rExport.GetModel(), uno::UNO_QUERY_THROW ); 98 ::rtl::OUString const baseURI( xModelURI->getStringValue() ); 99 100 uno::Reference<uno::XComponentContext> const xContext( 101 rExport.GetComponentContext()); 102 uno::Reference<lang::XMultiComponentFactory> const xServiceFactory( 103 xContext->getServiceManager(), uno::UNO_SET_THROW); 104 uno::Reference<uri::XUriReferenceFactory> const xUriFactory( 105 xServiceFactory->createInstanceWithContext( 106 ::rtl::OUString::createFromAscii( 107 "com.sun.star.uri.UriReferenceFactory"), xContext), 108 uno::UNO_QUERY_THROW); 109 110 uno::Reference< uri::XUriReference > const xBaseURI( 111 xUriFactory->parse(baseURI), uno::UNO_SET_THROW ); 112 uno::Reference< uri::XUriReference > const xAbsoluteURI( 113 xUriFactory->parse(rURI), uno::UNO_SET_THROW ); 114 uno::Reference< uri::XUriReference > const xRelativeURI( 115 xUriFactory->makeRelative(xBaseURI, xAbsoluteURI, true, true, false), 116 uno::UNO_SET_THROW ); 117 ::rtl::OUString const relativeURI(xRelativeURI->getUriReference()); 118 119 return relativeURI; 120 } 121 122 123 //////////////////////////////////////////////////////////////////////////// 124 125 RDFaExportHelper::RDFaExportHelper(SvXMLExport & i_rExport) 126 : m_rExport(i_rExport), m_xRepository(0), m_Counter(0) 127 { 128 const uno::Reference<rdf::XRepositorySupplier> xRS( m_rExport.GetModel(), 129 uno::UNO_QUERY); 130 OSL_ENSURE(xRS.is(), "AddRDFa: model is no rdf::XRepositorySupplier"); 131 if (!xRS.is()) throw uno::RuntimeException(); 132 m_xRepository.set(xRS->getRDFRepository(), uno::UNO_QUERY_THROW); 133 } 134 135 ::rtl::OUString 136 RDFaExportHelper::LookupBlankNode( 137 uno::Reference<rdf::XBlankNode> const & i_xBlankNode) 138 { 139 OSL_ENSURE(i_xBlankNode.is(), "null BlankNode?"); 140 if (!i_xBlankNode.is()) throw uno::RuntimeException(); 141 ::rtl::OUString & rEntry( 142 m_BlankNodeMap[ i_xBlankNode->getStringValue() ] ); 143 if (!rEntry.getLength()) 144 { 145 ::rtl::OUStringBuffer buf; 146 buf.appendAscii(s_prefix); 147 buf.append(++m_Counter); 148 rEntry = buf.makeStringAndClear(); 149 } 150 return rEntry; 151 } 152 153 //////////////////////////////////////////////////////////////////////////// 154 155 void 156 RDFaExportHelper::AddRDFa( 157 uno::Reference<rdf::XMetadatable> const & i_xMetadatable) 158 { 159 try 160 { 161 beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > const 162 RDFaResult( m_xRepository->getStatementRDFa(i_xMetadatable) ); 163 164 uno::Sequence<rdf::Statement> const & rStatements( RDFaResult.First ); 165 166 if (0 == rStatements.getLength()) 167 { 168 return; // no RDFa 169 } 170 171 // all stmts have the same subject, so we only handle first one 172 const uno::Reference<rdf::XURI> xSubjectURI(rStatements[0].Subject, 173 uno::UNO_QUERY); 174 const uno::Reference<rdf::XBlankNode> xSubjectBNode( 175 rStatements[0].Subject, uno::UNO_QUERY); 176 if (!xSubjectURI.is() && !xSubjectBNode.is()) 177 { 178 throw uno::RuntimeException(); 179 } 180 static const sal_Unicode s_OpenBracket ('['); 181 static const sal_Unicode s_CloseBracket(']'); 182 const ::rtl::OUString about( xSubjectURI.is() 183 ? getRelativeReference(m_rExport, xSubjectURI->getStringValue()) 184 : ::rtl::OUStringBuffer().append(s_OpenBracket).append( 185 LookupBlankNode(xSubjectBNode)).append(s_CloseBracket) 186 .makeStringAndClear() 187 ); 188 189 const uno::Reference<rdf::XLiteral> xContent( 190 rStatements[0].Object, uno::UNO_QUERY_THROW ); 191 const uno::Reference<rdf::XURI> xDatatype(xContent->getDatatype()); 192 if (xDatatype.is()) 193 { 194 const ::rtl::OUString datatype( 195 makeCURIE(&m_rExport, xDatatype) ); 196 m_rExport.AddAttribute(XML_NAMESPACE_XHTML, 197 token::XML_DATATYPE, datatype); 198 } 199 if (RDFaResult.Second) // there is xhtml:content 200 { 201 m_rExport.AddAttribute(XML_NAMESPACE_XHTML, token::XML_CONTENT, 202 xContent->getValue()); 203 } 204 205 ::rtl::OUStringBuffer property; 206 ::comphelper::intersperse( 207 ::boost::make_transform_iterator( 208 ::comphelper::stl_begin(rStatements), 209 ::boost::bind(&makeCURIE, &m_rExport, 210 ::boost::bind(&rdf::Statement::Predicate, _1))), 211 // argh, this must be the same type :( 212 ::boost::make_transform_iterator( 213 ::comphelper::stl_end(rStatements), 214 ::boost::bind(&makeCURIE, &m_rExport, 215 ::boost::bind(&rdf::Statement::Predicate, _1))), 216 ::comphelper::OUStringBufferAppender(property), 217 ::rtl::OUString::createFromAscii(" ")); 218 219 m_rExport.AddAttribute(XML_NAMESPACE_XHTML, token::XML_PROPERTY, 220 property.makeStringAndClear()); 221 222 m_rExport.AddAttribute(XML_NAMESPACE_XHTML, token::XML_ABOUT, about); 223 } 224 catch (uno::Exception &) 225 { 226 OSL_ENSURE(false, "AddRDFa: exception"); 227 } 228 } 229 230 } // namespace xmloff 231 232