blob: 83718bf8add11669f199513216d765235a2ca663 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "precompiled_xmloff.hxx"
#include "RDFaExportHelper.hxx"
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmlexp.hxx>
#include <xmloff/xmltoken.hxx>
#include <comphelper/stlunosequence.hxx>
#include <comphelper/stl_types.hxx>
#include <com/sun/star/uri/XUriReference.hpp>
#include <com/sun/star/uri/XUriReferenceFactory.hpp>
#include <com/sun/star/rdf/Statement.hpp>
#include <com/sun/star/rdf/URIs.hpp>
#include <com/sun/star/rdf/URI.hpp>
#include <com/sun/star/rdf/XLiteral.hpp>
#include <com/sun/star/rdf/XRepositorySupplier.hpp>
#include <com/sun/star/rdf/XDocumentRepository.hpp>
#include <rtl/ustrbuf.hxx>
#include <boost/bind.hpp>
#include <boost/iterator_adaptors.hpp>
#ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ // from iterator_adaptors.hpp
// N.B.: the check for the header guard _of a specific version of boost_
// is here so this may work on different versions of boost,
// which sadly put the goods in different header files
#include <boost/iterator/transform_iterator.hpp>
#endif
#include <functional>
#include <algorithm>
using namespace ::com::sun::star;
namespace xmloff {
static const char s_prefix [] = "_:b";
static ::rtl::OUString
makeCURIE(SvXMLExport * i_pExport,
uno::Reference<rdf::XURI> const & i_xURI)
{
OSL_ENSURE(i_xURI.is(), "makeCURIE: null URI");
if (!i_xURI.is()) throw uno::RuntimeException();
const ::rtl::OUString Namespace( i_xURI->getNamespace() );
OSL_ENSURE(Namespace.getLength(), "makeCURIE: no namespace");
if (!Namespace.getLength()) throw uno::RuntimeException();
::rtl::OUStringBuffer buf;
buf.append( i_pExport->EnsureNamespace(Namespace) );
buf.append( static_cast<sal_Unicode>(':') );
// N.B.: empty LocalName is valid!
buf.append( i_xURI->getLocalName() );
return buf.makeStringAndClear();
}
// #i112473# SvXMLExport::GetRelativeReference() not right for RDF on SaveAs
// because the URIs in the repository are not rewritten on SaveAs, the
// URI of the loaded document has to be used, not the URI of the target doc.
static ::rtl::OUString
getRelativeReference(SvXMLExport const& rExport, ::rtl::OUString const& rURI)
{
uno::Reference< rdf::XURI > const xModelURI(
rExport.GetModel(), uno::UNO_QUERY_THROW );
::rtl::OUString const baseURI( xModelURI->getStringValue() );
uno::Reference<uno::XComponentContext> const xContext(
rExport.GetComponentContext());
uno::Reference<lang::XMultiComponentFactory> const xServiceFactory(
xContext->getServiceManager(), uno::UNO_SET_THROW);
uno::Reference<uri::XUriReferenceFactory> const xUriFactory(
xServiceFactory->createInstanceWithContext(
::rtl::OUString::createFromAscii(
"com.sun.star.uri.UriReferenceFactory"), xContext),
uno::UNO_QUERY_THROW);
uno::Reference< uri::XUriReference > const xBaseURI(
xUriFactory->parse(baseURI), uno::UNO_SET_THROW );
uno::Reference< uri::XUriReference > const xAbsoluteURI(
xUriFactory->parse(rURI), uno::UNO_SET_THROW );
uno::Reference< uri::XUriReference > const xRelativeURI(
xUriFactory->makeRelative(xBaseURI, xAbsoluteURI, true, true, false),
uno::UNO_SET_THROW );
::rtl::OUString const relativeURI(xRelativeURI->getUriReference());
return relativeURI;
}
////////////////////////////////////////////////////////////////////////////
RDFaExportHelper::RDFaExportHelper(SvXMLExport & i_rExport)
: m_rExport(i_rExport), m_xRepository(0), m_Counter(0)
{
const uno::Reference<rdf::XRepositorySupplier> xRS( m_rExport.GetModel(),
uno::UNO_QUERY);
OSL_ENSURE(xRS.is(), "AddRDFa: model is no rdf::XRepositorySupplier");
if (!xRS.is()) throw uno::RuntimeException();
m_xRepository.set(xRS->getRDFRepository(), uno::UNO_QUERY_THROW);
}
::rtl::OUString
RDFaExportHelper::LookupBlankNode(
uno::Reference<rdf::XBlankNode> const & i_xBlankNode)
{
OSL_ENSURE(i_xBlankNode.is(), "null BlankNode?");
if (!i_xBlankNode.is()) throw uno::RuntimeException();
::rtl::OUString & rEntry(
m_BlankNodeMap[ i_xBlankNode->getStringValue() ] );
if (!rEntry.getLength())
{
::rtl::OUStringBuffer buf;
buf.appendAscii(s_prefix);
buf.append(++m_Counter);
rEntry = buf.makeStringAndClear();
}
return rEntry;
}
////////////////////////////////////////////////////////////////////////////
void
RDFaExportHelper::AddRDFa(
uno::Reference<rdf::XMetadatable> const & i_xMetadatable)
{
try
{
beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > const
RDFaResult( m_xRepository->getStatementRDFa(i_xMetadatable) );
uno::Sequence<rdf::Statement> const & rStatements( RDFaResult.First );
if (0 == rStatements.getLength())
{
return; // no RDFa
}
// all stmts have the same subject, so we only handle first one
const uno::Reference<rdf::XURI> xSubjectURI(rStatements[0].Subject,
uno::UNO_QUERY);
const uno::Reference<rdf::XBlankNode> xSubjectBNode(
rStatements[0].Subject, uno::UNO_QUERY);
if (!xSubjectURI.is() && !xSubjectBNode.is())
{
throw uno::RuntimeException();
}
static const sal_Unicode s_OpenBracket ('[');
static const sal_Unicode s_CloseBracket(']');
const ::rtl::OUString about( xSubjectURI.is()
? getRelativeReference(m_rExport, xSubjectURI->getStringValue())
: ::rtl::OUStringBuffer().append(s_OpenBracket).append(
LookupBlankNode(xSubjectBNode)).append(s_CloseBracket)
.makeStringAndClear()
);
const uno::Reference<rdf::XLiteral> xContent(
rStatements[0].Object, uno::UNO_QUERY_THROW );
const uno::Reference<rdf::XURI> xDatatype(xContent->getDatatype());
if (xDatatype.is())
{
const ::rtl::OUString datatype(
makeCURIE(&m_rExport, xDatatype) );
m_rExport.AddAttribute(XML_NAMESPACE_XHTML,
token::XML_DATATYPE, datatype);
}
if (RDFaResult.Second) // there is xhtml:content
{
m_rExport.AddAttribute(XML_NAMESPACE_XHTML, token::XML_CONTENT,
xContent->getValue());
}
::rtl::OUStringBuffer property;
::comphelper::intersperse(
::boost::make_transform_iterator(
::comphelper::stl_begin(rStatements),
::boost::bind(&makeCURIE, &m_rExport,
::boost::bind(&rdf::Statement::Predicate, _1))),
// argh, this must be the same type :(
::boost::make_transform_iterator(
::comphelper::stl_end(rStatements),
::boost::bind(&makeCURIE, &m_rExport,
::boost::bind(&rdf::Statement::Predicate, _1))),
::comphelper::OUStringBufferAppender(property),
::rtl::OUString::createFromAscii(" "));
m_rExport.AddAttribute(XML_NAMESPACE_XHTML, token::XML_PROPERTY,
property.makeStringAndClear());
m_rExport.AddAttribute(XML_NAMESPACE_XHTML, token::XML_ABOUT, about);
}
catch (uno::Exception &)
{
OSL_ENSURE(false, "AddRDFa: exception");
}
}
} // namespace xmloff