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