diff options
Diffstat (limited to 'unoxml')
88 files changed, 21832 insertions, 0 deletions
diff --git a/unoxml/JunitTest_unordf_complex.mk b/unoxml/JunitTest_unordf_complex.mk new file mode 100644 index 000000000000..ce897704edd2 --- /dev/null +++ b/unoxml/JunitTest_unordf_complex.mk @@ -0,0 +1,53 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_JunitTest_JunitTest,unordf_complex,SRCDIR)) + +$(eval $(call gb_JunitTest_set_defs,unordf_complex,\ + $$(DEFS) \ + -Dorg.openoffice.test.arg.tdoc=$(SRCDIR)/unoxml/qa/complex/unoxml/testdocuments \ +)) + +$(eval $(call gb_JunitTest_add_jars,unordf_complex,\ + $(OUTDIR)/bin/OOoRunner.jar \ + $(OUTDIR)/bin/ridl.jar \ + $(OUTDIR)/bin/test.jar \ + $(OUTDIR)/bin/unoil.jar \ + $(OUTDIR)/bin/jurt.jar \ +)) + +$(eval $(call gb_JunitTest_add_sourcefiles,unordf_complex,\ + unoxml/qa/complex/unoxml/RDFRepositoryTest \ + unoxml/qa/complex/unoxml/TestDocument \ +)) + +$(eval $(call gb_JunitTest_add_classes,unordf_complex,\ + complex.unoxml.RDFRepositoryTest \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/JunitTest_unoxml_complex.mk b/unoxml/JunitTest_unoxml_complex.mk new file mode 100644 index 000000000000..beeb2f728490 --- /dev/null +++ b/unoxml/JunitTest_unoxml_complex.mk @@ -0,0 +1,53 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_JunitTest_JunitTest,unoxml_complex,SRCDIR)) + +$(eval $(call gb_JunitTest_set_defs,unoxml_complex,\ + $$(DEFS) \ + -Dorg.openoffice.test.arg.tdoc=$(SRCDIR)/unoxml/qa/complex/unoxml/testdocuments \ +)) + +$(eval $(call gb_JunitTest_add_jars,unoxml_complex,\ + $(OUTDIR)/bin/OOoRunner.jar \ + $(OUTDIR)/bin/ridl.jar \ + $(OUTDIR)/bin/test.jar \ + $(OUTDIR)/bin/unoil.jar \ + $(OUTDIR)/bin/jurt.jar \ +)) + +$(eval $(call gb_JunitTest_add_sourcefiles,unoxml_complex,\ + unoxml/qa/complex/unoxml/DOMTest \ + unoxml/qa/complex/unoxml/TestDocument \ +)) + +$(eval $(call gb_JunitTest_add_classes,unoxml_complex,\ + complex.unoxml.DOMTest \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/Library_unordf.mk b/unoxml/Library_unordf.mk new file mode 100644 index 000000000000..2d0276a01a97 --- /dev/null +++ b/unoxml/Library_unordf.mk @@ -0,0 +1,63 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,unordf)) + +$(eval $(call gb_Library_set_componentfile,unordf,unoxml/source/rdf/unordf)) + +$(eval $(call gb_Library_set_include,unordf,\ + $$(INCLUDE) \ +)) + +$(eval $(call gb_Library_add_api,unordf,\ + udkapi \ + offapi \ +)) + +$(eval $(call gb_Library_add_linked_libs,unordf,\ + cppuhelper \ + cppu \ + sal \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Library_use_externals,unordf,\ + librdf \ + libxslt \ + libxml2 \ +)) + +$(eval $(call gb_Library_add_exception_objects,unordf,\ + unoxml/source/rdf/CBlankNode \ + unoxml/source/rdf/CURI \ + unoxml/source/rdf/CLiteral \ + unoxml/source/rdf/librdf_repository \ + unoxml/source/rdf/librdf_services \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/Library_unoxml.mk b/unoxml/Library_unoxml.mk new file mode 100644 index 000000000000..8014bace26cb --- /dev/null +++ b/unoxml/Library_unoxml.mk @@ -0,0 +1,89 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,unoxml)) + +$(eval $(call gb_Library_set_componentfile,unoxml,unoxml/source/service/unoxml)) + +$(eval $(call gb_Library_set_include,unoxml,\ + $$(INCLUDE) \ +)) + +$(eval $(call gb_Library_add_api,unoxml,\ + udkapi \ + offapi \ +)) + +$(eval $(call gb_Library_add_linked_libs,unoxml,\ + ucbhelper \ + sax \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Library_use_external,unoxml,libxml2)) + +$(eval $(call gb_Library_add_exception_objects,unoxml,\ + unoxml/source/dom/node \ + unoxml/source/dom/document \ + unoxml/source/dom/element \ + unoxml/source/dom/attr \ + unoxml/source/dom/cdatasection \ + unoxml/source/dom/characterdata \ + unoxml/source/dom/comment \ + unoxml/source/dom/documentbuilder \ + unoxml/source/dom/documentfragment \ + unoxml/source/dom/documenttype \ + unoxml/source/dom/entity \ + unoxml/source/dom/entityreference \ + unoxml/source/dom/notation \ + unoxml/source/dom/processinginstruction \ + unoxml/source/dom/text \ + unoxml/source/dom/domimplementation \ + unoxml/source/dom/elementlist \ + unoxml/source/dom/childlist \ + unoxml/source/dom/notationsmap \ + unoxml/source/dom/entitiesmap \ + unoxml/source/dom/attributesmap \ + unoxml/source/dom/saxbuilder \ + unoxml/source/xpath/xpathobject \ + unoxml/source/xpath/nodelist \ + unoxml/source/xpath/xpathapi \ + unoxml/source/events/event \ + unoxml/source/events/eventdispatcher \ + unoxml/source/events/mutationevent \ + unoxml/source/events/uievent \ + unoxml/source/events/mouseevent \ + unoxml/source/events/testlistener \ + unoxml/source/service/services \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/Makefile b/unoxml/Makefile new file mode 100644 index 000000000000..6c4d53b5f316 --- /dev/null +++ b/unoxml/Makefile @@ -0,0 +1,39 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +ifeq ($(strip $(SOLARENV)),) +$(error No environment set!) +endif + +gb_PARTIALBUILD := T +GBUILDDIR := $(SOLARENV)/gbuild +include $(GBUILDDIR)/gbuild.mk + +$(eval $(call gb_Module_make_global_targets,$(shell ls $(dir $(realpath $(firstword $(MAKEFILE_LIST))))/Module*.mk))) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/Module_unoxml.mk b/unoxml/Module_unoxml.mk new file mode 100644 index 000000000000..295546ae4da4 --- /dev/null +++ b/unoxml/Module_unoxml.mk @@ -0,0 +1,41 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_Module_Module,unoxml)) + +$(eval $(call gb_Module_add_targets,unoxml,\ + Library_unoxml \ + Library_unordf \ +)) + +$(eval $(call gb_Module_add_subsequentcheck_targets,unoxml,\ + JunitTest_unoxml_complex \ + JunitTest_unordf_complex \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/prj/build.lst b/unoxml/prj/build.lst new file mode 100644 index 000000000000..97aed0f47b94 --- /dev/null +++ b/unoxml/prj/build.lst @@ -0,0 +1,2 @@ +ux unoxml : offapi cppuhelper LIBXML2:libxml2 LIBXSLT:libxslt REDLAND:redland sax comphelper ucbhelper NULL +ux unoxml\prj nmake - all ux_prj NULL diff --git a/unoxml/prj/d.lst b/unoxml/prj/d.lst new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/unoxml/prj/d.lst diff --git a/unoxml/prj/makefile.mk b/unoxml/prj/makefile.mk new file mode 100644 index 000000000000..6d474ca27aee --- /dev/null +++ b/unoxml/prj/makefile.mk @@ -0,0 +1,40 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +PRJ=.. +TARGET=prj + +.INCLUDE : settings.mk + +.IF "$(VERBOSE)"!="" +VERBOSEFLAG := +.ELSE +VERBOSEFLAG := -s +.ENDIF + +all: + cd $(PRJ) && $(GNUMAKE) $(VERBOSEFLAG) -r -j$(GMAKE_MODULE_PARALLELISM) $(gb_MAKETARGET) diff --git a/unoxml/qa/complex/unoxml/DOMTest.java b/unoxml/qa/complex/unoxml/DOMTest.java new file mode 100644 index 000000000000..d4b9a5fcf3b6 --- /dev/null +++ b/unoxml/qa/complex/unoxml/DOMTest.java @@ -0,0 +1,2987 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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.unoxml; + +import lib.TestParameters; +import helper.StreamSimulator; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.beans.XPropertySet; +import com.sun.star.io.XInputStream; +import com.sun.star.xml.dom.*; +import static com.sun.star.xml.dom.DOMExceptionType.*; +import static com.sun.star.xml.dom.NodeType.*; +import com.sun.star.xml.dom.events.*; +import com.sun.star.xml.xpath.*; +import static com.sun.star.xml.xpath.XPathObjectType.*; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openoffice.test.OfficeConnection; +import static org.junit.Assert.*; + +/** + * Test for com.sun.star.xml.dom.*, com.sun.star.xml.xpath.* + */ +public class DOMTest +{ + private static final OfficeConnection connection = new OfficeConnection(); + + // setup and close connections + @BeforeClass public static void setUpConnection() throws Exception { + System.out.println("setUpConnection()"); + connection.setUp(); + } + + @AfterClass public static void tearDownConnection() + throws InterruptedException, com.sun.star.uno.Exception + { + System.out.println("tearDownConnection()"); + connection.tearDown(); + } + + XComponentContext m_xContext; + XMultiServiceFactory m_xMSF; + TestParameters m_params; + + @Before public void before() throws Exception + { + final XMultiServiceFactory xMSF = UnoRuntime.queryInterface( + XMultiServiceFactory.class, + connection.getComponentContext().getServiceManager()); + assertNotNull("could not create MultiServiceFactory.", xMSF); + m_params = new TestParameters(); + m_params.put("ServiceFactory", xMSF); + XPropertySet xPropertySet = + UnoRuntime.queryInterface(XPropertySet.class, xMSF); + m_xContext = UnoRuntime.queryInterface(XComponentContext.class, + xPropertySet.getPropertyValue("DefaultContext")); + assertNotNull("could not get component context.", m_xContext); + m_xMSF = xMSF; + } + + @Test public void testXSAXDocumentBuilder() throws Exception + { + XSAXDocumentBuilder xSAXBuilder = + UnoRuntime.queryInterface(XSAXDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.SAXDocumentBuilder")); + //FIXME TODO + } + + @Test + public void testXDocumentBuilder() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + XDOMImplementation xDomImpl = xBuilder.getDOMImplementation(); +//FIXME fails assertNotNull("getDOMImplementation", xDomImpl); + + xBuilder.isNamespaceAware(); + xBuilder.isValidating(); + + { + XDocument xDoc = xBuilder.newDocument(); + assertNotNull("newDocument", xDoc); + } + + try { + xBuilder.parse(null); + fail("XDocumentBuilder.parse(null)"); + } catch (Exception e) { /* expected */ } + { + XInputStream xIn = new StreamSimulator( + TestDocument.getUrl("example.rdf"), true, m_params); + XDocument xDoc = xBuilder.parse(xIn); + assertNotNull("XDocumentBuilder.parse", xDoc); + } + try { + xBuilder.parseURI(""); + fail("XDocumentBuilder.parseURI(\"\")"); + } catch (Exception e) { /* expected */ } + { + XDocument xDoc = + xBuilder.parseURI(TestDocument.getUrl("example.rdf")); + assertNotNull("XDocumentBuilder.parseURI", xDoc); + } + + xBuilder.setEntityResolver(null); + /* FIXME TODO + XEntityResolver xER; + xBuilder.setEntityResolver(xER); + */ + + xBuilder.setErrorHandler(null); + /* FIXME TODO + XErrorHandler xEH; + xBuilder.setErrorHandler(xEH); + */ + } + + @Test public void testXDocument() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + /* FIXME + try { + xDoc.createAttribute("&"); + fail("XDocument.createAttribute"); + } catch (DOMException e) { + assertTrue("XDocument.createAttribute", + INVALID_CHARACTER_ERR == e.Code); + }*/ + { + XAttr xAttr = xDoc.createAttribute("foo"); + assertNotNull("XDocument.createAttribute", xAttr); + assertEquals("XDocument.createAttribute", + "foo", xAttr.getNodeName()); + } + + String ns = "http://example.com/"; + /* FIXME + try { + xDoc.createAttributeNS(ns, "&"); + fail("XDocument.createAttributeNS"); + } catch (DOMException e) { + assertTrue("XDocument.createAttributeNS", + INVALID_CHARACTER_ERR == e.Code); + } + */ + { + XAttr xAttr = xDoc.createAttributeNS(ns, "e:foo"); + assertNotNull("XDocument.createAttributeNS", xAttr); + assertEquals("XDocument.createAttributeNS", "foo", + xAttr.getNodeName()); + } + + XCDATASection xCDS = xDoc.createCDATASection("foo"); + assertNotNull("XDocument.createCDATASection", xCDS); + + XComment xComment = xDoc.createComment("foo"); + assertNotNull("XDocument.createComment", xComment); + + XDocumentFragment xDF = xDoc.createDocumentFragment(); + assertNotNull("XDocument.createDocumentFragment", xDF); + + /* FIXME + try { + xDoc.createElement("&"); + fail("XDocument.createElement(\"&\")"); + } catch (DOMException e) { + assertTrue("XDocument.createElement(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement(\"foo\")", xElemFoo); + assertEquals("XDocument.createElement(\"foo\")", + "foo", xElemFoo.getNodeName()); + + /* FIXME + try { + xDoc.createElementNS(ns, "&"); + fail("XDocument.createElementNS(\"&\")"); + } catch (DOMException e) { + assertTrue("XDocument.createElementNS(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + XElement xElemFooNs = xDoc.createElementNS(ns, "foo"); + assertNotNull("XDocument.createElementNS(\"foo\")", xElemFooNs); + assertEquals("XDocument.createElementNS(\"foo\")", + "foo", xElemFooNs.getNodeName()); + + XEntityReference xER = xDoc.createEntityReference("foo"); + assertNotNull("XDocument.createEntityReference", xER); + + XProcessingInstruction xPI = + xDoc.createProcessingInstruction("foo", "bar"); + assertNotNull("XDocument.createProcessingInstruction", xPI); + + XText xText = xDoc.createTextNode("foo"); + assertNotNull("XDocument.createTextNode", xText); + + XDocumentType xDT = xDoc.getDoctype(); + assertNull("XDocument.getDoctype", xDT); + + { + XElement xDE = xDoc.getDocumentElement(); + assertNull("XDocument.getDocumentElement", xDE); + } + { + XElement xById = xDoc.getElementById("foo"); + assertNull("XDocument.getDocumentElement", xById); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagName("foo"); + assertNotNull("XDocument.getElementsByTagName", xNodeList); + assertTrue("XDocument.getElementsByTagName", + 0 == xNodeList.getLength()); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XDocument.getElementsByTagNameNS", xNodeList); + assertTrue("XDocument.getElementsByTagNameNS", + 0 == xNodeList.getLength()); + } + + XDOMImplementation xDOMImpl = xDoc.getImplementation(); + assertNotNull("XDocument.getImplementation", xDOMImpl); + + { + XNode xRet = xElemFooNs.appendChild(xElemFoo); + assertEquals("XElement.appendChild(xElemFoo)", xElemFoo, xRet); + } + { + XNode xRet = xDoc.appendChild(xElemFooNs); + assertTrue("XDocument.appendChild(xElemFooNs)", + xElemFooNs.equals(xRet)); + } + + XElement xDE = xDoc.getDocumentElement(); + assertNotNull("XDocument.getDocumentElement", xDE); + assertEquals("XDocument.getDocumentElement", xElemFooNs, xDE); + + { + XNodeList xNodeList = xDoc.getElementsByTagName("foo"); + assertNotNull("XDocument.getElementsByTagName", xNodeList); + assertTrue("XDocument.getElementsByTagName", + 2 == xNodeList.getLength()); + assertEquals("XDocument.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + assertEquals("XDocument.getElementsByTagName", + xElemFoo, xNodeList.item(1)); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XDocument.getElementsByTagNameNS", xNodeList); + assertTrue("XDocument.getElementsByTagNameNS", + 1 == xNodeList.getLength()); + assertEquals("XDocument.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + } + + xElemFoo.setAttributeNS("http://www.w3.org/XML/1998/namespace", + "xml:id", "bar"); + + XElement xById = xDoc.getElementById("bar"); + assertNotNull("XDocument.getDocumentElement", xById); + assertEquals("XDocument.getDocumentElement", xElemFoo, xById); + + try { + xDoc.importNode(null, false); + fail("XDocument.importNode(null)"); + } catch (Exception e) { /* expected */ } + { + XNode xImported = xDoc.importNode(xElemFoo, false); + assertNotNull("XDocument.importNode()", xImported); + assertEquals("XDocument.importNode()", xElemFoo, xImported); + } + { + MockAttr xMockAttrBar = new MockAttr("bar", "blah"); + MockAttr xMockAttrBaz = new MockAttr("baz", "quux"); + MockElement xMockElemFoo = new MockElement("foo", + new MockAttr[] { xMockAttrBar, xMockAttrBaz }); + MockElement xMockElemBar = new MockElement("bar", + new MockAttr[] { }); + MockElement xMockElemRoot = + new MockElement("root", new MockAttr[] { }); + MockDoc xMockDoc = new MockDoc(); + xMockDoc.init(new MockNode[] { xMockElemRoot }); + xMockElemRoot.init(xMockDoc, xMockDoc, null, null, + new MockNode[] { xMockElemFoo, xMockElemBar }); + xMockElemFoo.init(xMockDoc, xMockElemRoot, null, xMockElemBar, + new MockNode[] { }); + xMockElemBar.init(xMockDoc, xMockElemRoot, xMockElemFoo, null, + new MockNode[] { }); + + { + XNode xImported = xDoc.importNode(xMockElemRoot, false); + assertNotNull("XDocument.importNode(false)", xImported); + XElement xE = + UnoRuntime.queryInterface(XElement.class, xImported); + assertNotNull("XDocument.importNode(false)", xE); + assertEquals("XDocument.importNode(false)", + "root", xE.getLocalName()); + assertFalse("XDocument.importNode(false)", xE.hasAttributes()); + assertFalse("XDocument.importNode(false)", xE.hasChildNodes()); + } + + { + XNode xImported = xDoc.importNode(xMockElemRoot, true); + assertNotNull("XDocument.importNode(true)", xImported); + XElement xImpRoot = + UnoRuntime.queryInterface(XElement.class, xImported); + assertNotNull("XDocument.importNode(true)", xImpRoot); + assertEquals("XDocument.importNode(true)", + "root", xImpRoot.getLocalName()); + assertFalse("XDocument.importNode(true)", + xImpRoot.hasAttributes()); + assertTrue("XDocument.importNode(true)", + xImpRoot.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "root", xImpRoot.getNodeName()); + + XNode xImpFooN = xImpRoot.getFirstChild(); + assertNotNull("XDocument.importNode(true)", xImpFooN); + XElement xImpFoo = + UnoRuntime.queryInterface(XElement.class, xImpFooN); + assertNotNull("XDocument.importNode(true)", xImpFoo); + assertTrue("XDocument.importNode(true)", + xImpFoo.hasAttributes()); + assertFalse("XDocument.importNode(true)", + xImpFoo.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "foo", xImpFoo.getNodeName()); + assertEquals("XDocument.importNode(true)", + "blah", xImpFoo.getAttribute("bar")); + assertEquals("XDocument.importNode(true)", + "quux", xImpFoo.getAttribute("baz")); + XNode xImpBarN = xImpFooN.getNextSibling(); + assertNotNull("XDocument.importNode(true)", xImpBarN); + XElement xImpBar = + UnoRuntime.queryInterface(XElement.class, xImpBarN); + assertNotNull("XDocument.importNode(true)", xImpBar); + assertFalse("XDocument.importNode(true)", + xImpBar.hasAttributes()); + assertFalse("XDocument.importNode(true)", + xImpBar.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "bar", xImpBar.getNodeName()); + assertNull("XDocument.importNode(true)", + xImpBar.getNextSibling()); + } + } + + // XNode //////////////////////////////////////////////////// + + { + XNode xDocCloneN = xDoc.cloneNode(false); + assertNotNull("XDocument.cloneNode(false)", xDocCloneN); + XDocument xDocClone = + UnoRuntime.queryInterface(XDocument.class, xDocCloneN); + assertNotNull("XDocument.cloneNode(false)", xDocClone); + assertFalse("XDocument.cloneNode(false)", + xDocClone.hasChildNodes()); + assertNull("XDocument.cloneNode(false)", xDocClone.getFirstChild()); + assertNull("XDocument.cloneNode(false)", + xDocClone.getDocumentElement()); + } + { + XNode xDocCloneN = xDoc.cloneNode(true); + assertNotNull("XDocument.cloneNode(true)", xDocCloneN); + XDocument xDocClone = + UnoRuntime.queryInterface(XDocument.class, xDocCloneN); + assertNotNull("XDocument.cloneNode(true)", xDocClone); + assertTrue("XDocument.cloneNode(true)", xDocClone.hasChildNodes()); + assertNotNull("XDocument.cloneNode(true)", + xDocClone.getFirstChild()); + XElement xE = xDocClone.getDocumentElement(); + assertNotNull("XDocument.cloneNode(true)", xE); + assertFalse("XDocument.cloneNode(true)", xElemFooNs.equals(xE)); + assertEquals("XDocument.cloneNode(true)", "foo", xE.getLocalName()); + assertEquals("XDocument.cloneNode(true)", ns, xE.getNamespaceURI()); + } + + assertNull("XDocument.getAttributes()", xDoc.getAttributes()); + + { + XNodeList xChildren = xDoc.getChildNodes(); + assertTrue("XDocument.getChildNodes()", 1 == xChildren.getLength()); + assertEquals("XDocument.getChildNodes()", + xElemFooNs, xChildren.item(0)); + + XNode xFirst = xDoc.getFirstChild(); + assertEquals("XDocument.getFirstChild()", xElemFooNs, xFirst); + XNode xLast = xDoc.getLastChild(); + assertEquals("XDocument.getLastChild()", xElemFooNs, xLast); + } + + assertEquals("XDocument.getLocalName()", "", xDoc.getLocalName()); + + assertEquals("XDocument.getNamespaceURI()", "", xDoc.getNamespaceURI()); + + assertNull("XDocument.getNextSibling()", xDoc.getNextSibling()); + + assertEquals("XDocument.getNodeName()", + "#document", xDoc.getNodeName()); + + assertTrue("XDocument.getNodeType()", + DOCUMENT_NODE == xDoc.getNodeType()); + + assertEquals("XDocument.getNodeValue()", "", xDoc.getNodeValue()); + + assertEquals("XDocument.getOwnerDocument()", + xDoc, xDoc.getOwnerDocument()); + + assertNull("XDocument.getParentNode()", xDoc.getParentNode()); + + assertEquals("XDocument.getPrefix()", "", xDoc.getPrefix()); + + assertNull("XDocument.getPreviousSibling()", xDoc.getPreviousSibling()); + + assertFalse("XDocument.hasAttributes()", xDoc.hasAttributes()); + + assertTrue("XDocument.hasChildNodes()", xDoc.hasChildNodes()); + + assertFalse("XDocument.isSupported()", + xDoc.isSupported("frobnication", "v99.33.0.0.0.1")); + + xDoc.normalize(); + + try { + xDoc.setNodeValue("42"); + fail("XDocument.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XDocument.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDoc.setPrefix("foo"); + fail("XDocument.setPrefix()"); + } catch (DOMException e) { + assertTrue("XDocument.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDoc.appendChild(null); + fail("XDocument.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + + try { + xDoc.insertBefore(null, xText); + fail("XDocument.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.insertBefore(xText, null); + fail("XDocument.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.insertBefore(xText, xText); + fail("XDocument.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocument.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xDoc.insertBefore(xComment, xElemFooNs); + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xRet, xElemFooNs); // why does this return the old node? + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xComment, xDoc.getFirstChild()); + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xDoc, xComment.getParentNode()); + assertEquals("XDocument.insertBefore(xCommnet, xElemFooNs)", + xElemFooNs, xDoc.getLastChild()); + } + + try { + xDoc.replaceChild(null, xText); + fail("XDocument.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xDoc.replaceChild(xText, null); + fail("XDocument.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.replaceChild(xElemFoo, xElemFoo); // not child + fail("XDocument.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XDocument.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xDoc.replaceChild(xElemFooNs, xElemFooNs); // child + assertFalse("XDocument.replaceChild(xElemFooNs, xElemFooNs)", + false); + } catch (DOMException e) { + assertTrue("XDocument.replaceChild(xElemFooNs, xElemFooNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xDoc.replaceChild(xPI, xComment); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xReplaced, xComment); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xPI, xDoc.getFirstChild()); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xElemFooNs, xDoc.getLastChild()); + + try { + xDoc.removeChild(null); + fail("XDocument.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.removeChild(xElemFoo); + fail("XDocument.removeChild()"); + } catch (DOMException e) { + assertTrue("XDocument.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xDoc.removeChild(xPI); + assertEquals("XDocument.removeChild(xPI)", xRemoved, xPI); + assertTrue("XDocument.removeChild(xPI)", xDoc.hasChildNodes()); + assertEquals("XDocument.removeChild(xPI)", + xElemFooNs, xDoc.getFirstChild()); + assertEquals("XDocument.removeChild(xPI)", + xElemFooNs, xDoc.getLastChild()); + } + + @Test public void testXDocumentFragment() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XDocumentFragment xDF = xDoc.createDocumentFragment(); + assertNotNull("XDocument.createDocumentFragment", xDF); + + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement", xElemFoo); + + xDF.appendChild(xElemFoo); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNode xDFCloneN = xDF.cloneNode(false); + assertNotNull("XDocumentFragment.cloneNode(false)", xDFCloneN); + XDocumentFragment xDFClone = + UnoRuntime.queryInterface(XDocumentFragment.class, xDFCloneN); + assertNotNull("XDocumentFragment.cloneNode(false)", xDFClone); + assertFalse("XDocumentFragment.cloneNode(false)", + xDFClone.hasChildNodes()); + assertNull("XDocumentFragment.cloneNode(false)", + xDFClone.getFirstChild()); + } + { + XNode xDFCloneN = xDF.cloneNode(true); + assertNotNull("XDocumentFragment.cloneNode(true)", xDFCloneN); + XDocumentFragment xDFClone = + UnoRuntime.queryInterface(XDocumentFragment.class, xDFCloneN); + assertNotNull("XDocumentFragment.cloneNode(true)", xDFClone); + assertTrue("XDocumentFragment.cloneNode(true)", + xDFClone.hasChildNodes()); + XNode xChild = xDFClone.getFirstChild(); + assertNotNull("XDocumentFragment.cloneNode(true)", xChild); + XElement xE = UnoRuntime.queryInterface(XElement.class, xChild); + assertFalse("XDocumentFragment.cloneNode(true)", + xElemFoo.equals(xE)); + assertEquals("XDocumentFragment.cloneNode(true)", + "foo", xE.getLocalName()); + } + + assertNull("XDocumentFragment.getAttributes()", xDF.getAttributes()); + + { + XNodeList xChildren = xDF.getChildNodes(); + assertTrue("XDocumentFragment.getChildNodes()", + 1 == xChildren.getLength()); + assertEquals("XDocumentFragment.getChildNodes()", + xElemFoo, xChildren.item(0)); + + XNode xFirst = xDF.getFirstChild(); + assertEquals("XDocumentFragment.getFirstChild()", + xElemFoo, xFirst); + XNode xLast = xDF.getLastChild(); + assertEquals("XDocumentFragment.getLastChild()", xElemFoo, xLast); + } + + assertEquals("XDocumentFragment.getLocalName()", + "", xDF.getLocalName()); + + assertEquals("XDocumentFragment.getNamespaceURI()", + "", xDF.getNamespaceURI()); + + assertNull("XDocumentFragment.getNextSibling()", xDF.getNextSibling()); + + assertEquals("XDocumentFragment.getNodeName()", + "#document-fragment", xDF.getNodeName()); + + assertTrue("XDocumentFragment.getNodeType()", + DOCUMENT_FRAGMENT_NODE == xDF.getNodeType()); + + assertEquals("XDocumentFragment.getNodeValue()", + "", xDF.getNodeValue()); + + assertEquals("XDocumentFragment.getOwnerDocument()", + xDoc, xDF.getOwnerDocument()); + + assertNull("XDocumentFragment.getParentNode()", xDF.getParentNode()); + + assertEquals("XDocumentFragment.getPrefix()", "", xDF.getPrefix()); + + assertNull("XDocumentFragment.getPreviousSibling()", + xDF.getPreviousSibling()); + + assertFalse("XDocumentFragment.hasAttributes()", xDF.hasAttributes()); + + assertTrue("XDocumentFragment.hasChildNodes()", xDF.hasChildNodes()); + + assertFalse("XDocumentFragment.isSupported()", + xDF.isSupported("frobnication", "v99.33.0.0.0.1")); + + xDF.normalize(); + + try { + xDF.setNodeValue("42"); + fail("XDocumentFragment.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDF.setPrefix("foo"); + fail("XDocumentFragment.setPrefix()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDF.appendChild(null); + fail("XDocumentFragment.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + + try { + xDF.insertBefore(null, xText); + fail("XDocumentFragment.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xDF.insertBefore(xText, null); + fail("XDocumentFragment.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.insertBefore(xText, xText); + fail("XDocumentFragment.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xDF.insertBefore(xComment, xElemFoo); + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xRet, xElemFoo); // why does this return the old node? + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xComment, xDF.getFirstChild()); + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xDF, xComment.getParentNode()); + assertEquals("XDocumentFragment.insertBefore(xCommnet, xElemFoo)", + xElemFoo, xDF.getLastChild()); + } + + try { + xDF.replaceChild(null, xText); + fail("XDocumentFragment.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xDF.replaceChild(xText, null); + fail("XDocumentFragment.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.replaceChild(xElemFoo, xElemFoo); // not child + fail("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xDF.replaceChild(xElemFoo, xElemFoo); // child + assertFalse("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + false); + } catch (DOMException e) { + assertTrue("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xDF.replaceChild(xText, xComment); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xReplaced, xComment); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xText, xDF.getFirstChild()); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xElemFoo, xDF.getLastChild()); + + try { + xDF.removeChild(null); + fail("XDocumentFragment.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.removeChild(xComment); + fail("XDocumentFragment.removeChild()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xDF.removeChild(xText); + assertEquals("XDocumentFragment.removeChild(xText)", xRemoved, xText); + assertTrue("XDocumentFragment.removeChild(xText)", xDF.hasChildNodes()); + assertEquals("XDocumentFragment.removeChild(xText)", + xElemFoo, xDF.getFirstChild()); + assertEquals("XDocumentFragment.removeChild(xText)", + xElemFoo, xDF.getLastChild()); + } + + @Test public void testXElement() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement(\"foo\")", xElemFoo); + + XElement xElemFooNs = xDoc.createElementNS(ns, "e:foo"); + assertNotNull("XDocument.createElementNs(\"foo\")", xElemFooNs); + + assertEquals("XElement.getTagName", "foo", xElemFoo.getTagName()); + + { + XNodeList xNodeList = xElemFoo.getElementsByTagName("bar"); + assertNotNull("XElement.getElementsByTagName", xNodeList); + assertTrue("XElement.getElementsByTagName", + 0 == xNodeList.getLength()); + } + + { + XNodeList xNodeList = xElemFoo.getElementsByTagNameNS(ns, "bar"); + assertNotNull("XElement.getElementsByTagNameNS", xNodeList); + assertTrue("XElement.getElementsByTagNameNS", + 0 == xNodeList.getLength()); + } + + xElemFoo.appendChild(xElemFooNs); + + { + XNodeList xNodeList = xElemFoo.getElementsByTagName("foo"); + assertNotNull("XElement.getElementsByTagName", xNodeList); + assertTrue("XElement.getElementsByTagName", + 2 == xNodeList.getLength()); + assertEquals("XElement.getElementsByTagName", + xElemFoo, xNodeList.item(0)); + assertEquals("XElement.getElementsByTagName", + xElemFooNs, xNodeList.item(1)); + } + { + XNodeList xNodeList = xElemFoo.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XElement.getElementsByTagNameNS", xNodeList); + assertTrue("XElement.getElementsByTagNameNS", + 1 == xNodeList.getLength()); + assertEquals("XElement.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + } + + { + String ret = xElemFoo.getAttribute("foo"); + assertEquals("XElement.getAttribute", "", ret); + } + { + String ret = xElemFoo.getAttributeNS(ns, "foo"); + assertEquals("XElement.getAttributeNS", "", ret); + } + { + XNode xAttr = xElemFoo.getAttributeNode("foo"); + assertNull("XElement.getAttributeNode", xAttr); + } + { + XNode xAttr = xElemFoo.getAttributeNodeNS(ns, "foo"); + assertNull("XElement.getAttributeNodeNS", xAttr); + } + assertFalse("XElement.hasAttribute", xElemFoo.hasAttribute("foo")); + assertFalse("XElement.hasAttributeNS", + xElemFoo.hasAttributeNS(ns, "foo")); + + // surprisingly this does not throw? + xElemFoo.removeAttribute("foo"); + xElemFoo.removeAttributeNS(ns, "foo"); + + XAttr xAttr = xDoc.createAttribute("foo"); + XAttr xAttrNs = xDoc.createAttributeNS(ns, "foo"); + + try { + xElemFoo.removeAttributeNode(null); + fail("XElement.removeAttributeNode(null)"); + } catch (Exception e) { /* expected */ } + + try { + xElemFoo.removeAttributeNode(xAttr); + fail("XElement.removeAttributeNode(xAttr)"); + } catch (DOMException e) { + assertTrue("XElement.removeAttributeNode(xAttr)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + /* FIXME + try { + xElemFoo.setAttribute("&", "foo"); + fail("XElement.setAttribute(\"&\")"); + } catch (DOMException e) { + assertTrue("XElement.setAttribute(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + try { + xElemFoo.setAttributeNS(ns, "&", "foo"); + fail("XElement.setAttributeNS(\"&\")"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNS(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + + XAttr xAttrSet = xElemFoo.setAttributeNode(xAttr); + assertEquals("XElement.setAttributeNode(xAttr)", + xAttrSet, xElemFoo.getAttributeNode("foo")); + assertEquals("XElement.setAttributeNode(xAttr)", + xElemFoo, xAttrSet.getOwnerElement()); + try { + xElemFooNs.setAttributeNode(xAttrSet); + fail("XElement.setAttributeNode(xAttrSet)"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNode(xAttrSet)", + INUSE_ATTRIBUTE_ERR == e.Code); + } + + XAttr xAttrNsSet = xElemFooNs.setAttributeNodeNS(xAttrNs); + assertEquals("XElement.setAttributeNodeNS(xAttr)", + xAttrNsSet, xElemFooNs.getAttributeNodeNS(ns, "foo")); + assertEquals("XElement.setAttributeNodeNS(xAttrNs)", + xElemFooNs, xAttrNsSet.getOwnerElement()); + try { + xElemFooNs.setAttributeNodeNS(xAttrNsSet); + fail("XElement.setAttributeNodeNS(xAttrNsSet)"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNodeNS(xAttrNsSet)", + INUSE_ATTRIBUTE_ERR == e.Code); + } + + XAttr xAttrRemoved = xElemFoo.removeAttributeNode(xAttrSet); + assertNotNull("XElement.removeAttributeNode(xAttrSet)", xAttrRemoved); + assertEquals("XElement.removeAttributeNode(xAttrSet)", + "foo", xAttrRemoved.getName()); + assertNull("XElement.removeAttributeNode(xAttrSet)", + xAttrRemoved.getOwnerElement()); + + XAttr xAttrNsRemoved = xElemFooNs.removeAttributeNode(xAttrNsSet); + assertNotNull("XElement.removeAttributeNode(xAttrNsSet)", + xAttrNsRemoved); + assertEquals("XElement.removeAttributeNode(xAttrNsSet)", + "foo", xAttrNsRemoved.getName()); + assertNull("XElement.removeAttributeNode(xAttrNsSet)", + xAttrNsRemoved.getOwnerElement()); + + + xElemFoo.setAttribute("foo", "bar"); + assertEquals("XElement.setAttribute()", + "bar", xElemFoo.getAttribute("foo")); + + xElemFooNs.setAttributeNS(ns, "foo", "bar"); + assertEquals("XElement.setAttributeNS()", + "bar", xElemFooNs.getAttributeNS(ns, "foo")); + + xElemFoo.removeAttribute("foo"); + assertNull("XElement.removeAttribute", + xElemFoo.getAttributeNode("foo")); + + xElemFooNs.removeAttributeNS(ns, "foo"); + assertNull("XElement.removeAttributeNS", + xElemFooNs.getAttributeNodeNS(ns, "foo")); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNamedNodeMap xAttrMap = xElemFoo.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 0 == xAttrMap.getLength()); + assertFalse("XElement.hasAttributes()", xElemFoo.hasAttributes()); + } + + xElemFooNs.setAttribute("foo", "bar"); + xElemFoo.setAttributeNS(ns, "foo", "bar"); + + { + XNamedNodeMap xAttrMap = xElemFoo.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 1 == xAttrMap.getLength()); + XNode xAttr_ = xAttrMap.getNamedItemNS(ns, "foo"); + assertNotNull("XElement.getAttributes", xAttr_); + } + { + XNamedNodeMap xAttrMap = xElemFooNs.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 1 == xAttrMap.getLength()); + XNode xAttr_ = xAttrMap.getNamedItem("foo"); + assertNotNull("XElement.getAttributes", xAttr_); + } + + { + XNode xElemFooCloneN = xElemFoo.cloneNode(false); + assertNotNull("XElement.cloneNode(false)", xElemFooCloneN); + XElement xElemFooClone = + UnoRuntime.queryInterface(XElement.class, xElemFooCloneN); + assertNotNull("XElement.cloneNode(false)", xElemFooClone); + assertFalse("XElement.cloneNode(false)", + xElemFooClone.hasChildNodes()); + assertNull("XElement.cloneNode(false)", + xElemFooClone.getFirstChild()); + } + { + XNode xElemFooCloneN = xElemFoo.cloneNode(true); + assertNotNull("XElement.cloneNode(true)", xElemFooCloneN); + XElement xElemFooClone = + UnoRuntime.queryInterface(XElement.class, xElemFooCloneN); + assertNotNull("XElement.cloneNode(true)", xElemFooClone); + assertTrue("XElement.cloneNode(true)", + xElemFooClone.hasChildNodes()); + assertTrue("XElement.cloneNode(true)", + xElemFooClone.hasAttributeNS(ns, "foo")); + XNode xChild = xElemFooClone.getFirstChild(); + assertNotNull("XElement.cloneNode(true)", xChild); + XElement xElemFooNsClone = + UnoRuntime.queryInterface(XElement.class, xChild); + assertNotNull("XElement.cloneNode(true)", xElemFooNsClone); + assertEquals("XElement.cloneNode(true)", "foo", + xElemFooNsClone.getLocalName()); + assertEquals("XElement.cloneNode(true)", ns, + xElemFooNsClone.getNamespaceURI()); + assertTrue("XElement.cloneNode(true)", + xElemFooNsClone.hasAttribute("foo")); + } + + { + XNodeList xChildren = xElemFoo.getChildNodes(); + assertTrue("XElement.getChildNodes()", 1 == xChildren.getLength()); + assertEquals("XElement.getChildNodes()", + xElemFooNs, xChildren.item(0)); + + XNode xFirst = xElemFoo.getFirstChild(); + assertEquals("XDocument.getFirstChild()", xElemFooNs, xFirst); + XNode xLast = xElemFoo.getLastChild(); + assertEquals("XDocument.getLastChild()", xElemFooNs, xLast); + } + + assertEquals("XElement.getLocalName()", "foo", xElemFoo.getLocalName()); + assertEquals("XElement.getLocalName()", "foo", + xElemFooNs.getLocalName()); + + assertEquals("XElement.getNamespaceURI()", "", + xElemFoo.getNamespaceURI()); + assertEquals("XElement.getNamespaceURI()", ns, + xElemFooNs.getNamespaceURI()); + + assertNull("XElement.getNextSibling()", xElemFoo.getNextSibling()); + + assertEquals("XElement.getNodeName()", "foo", xElemFoo.getNodeName()); + assertEquals("XElement.getNodeName()", "foo", + xElemFooNs.getNodeName()); + + assertTrue("XElement.getNodeType()", + ELEMENT_NODE == xElemFoo.getNodeType()); + + assertEquals("XElement.getNodeValue()", "", xElemFoo.getNodeValue()); + + assertEquals("XElement.getOwnerDocument()", + xDoc, xElemFoo.getOwnerDocument()); + + assertNull("XElement.getParentNode()", xElemFoo.getParentNode()); + assertEquals("XElement.getParentNode()", + xElemFoo, xElemFooNs.getParentNode()); + + assertEquals("XElement.getPrefix()", "", xElemFoo.getPrefix()); + assertEquals("XElement.getPrefix()", "e", xElemFooNs.getPrefix()); + + assertNull("XElement.getPreviousSibling()", + xElemFoo.getPreviousSibling()); + + assertTrue("XElement.hasAttributes()", xElemFoo.hasAttributes()); + + assertTrue("XElement.hasChildNodes()", xElemFoo.hasChildNodes()); + assertFalse("XElement.hasChildNodes()", xElemFooNs.hasChildNodes()); + + assertFalse("XElement.isSupported()", + xElemFoo.isSupported("frobnication", "v99.33.0.0.0.1")); + + xElemFoo.normalize(); + + try { + xElemFoo.setNodeValue("42"); + fail("XElement.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XElement.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + xElemFooNs.setPrefix("f"); + assertEquals("XElement.getPrefix()", "f", xElemFooNs.getPrefix()); + + try { + xElemFoo.appendChild(null); + fail("XElement.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xElemFoo.insertBefore(null, xText); + fail("XElemFoo.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.insertBefore(xText, null); + fail("XElemFoo.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.insertBefore(xText, xText); + fail("XElement.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocument.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xElemFoo.insertBefore(xText, xElemFooNs); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xRet, xElemFooNs); // why does this return the old node? + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xText, xElemFoo.getFirstChild()); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xElemFoo, xText.getParentNode()); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xElemFooNs, xElemFoo.getLastChild()); + } + + try { + xElemFoo.replaceChild(null, xText); + fail("XElement.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.replaceChild(xText, null); + fail("XElement.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.replaceChild(xElemFoo, xElemFoo); // not child + fail("XElement.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XElement.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xElemFoo.replaceChild(xElemFooNs, xElemFooNs); // child + assertFalse("XElement.replaceChild(xElemFooNs, xElemFooNs)", + false); + } catch (DOMException e) { + assertTrue("XElement.replaceChild(xElemFooNs, xElemFooNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xElemFoo.replaceChild(xComment, xText); + assertEquals("XElement.replaceChild(xComment, xText)", + xReplaced, xText); + assertEquals("XElement.replaceChild(xComment, xText)", + xComment, xElemFoo.getFirstChild()); + assertEquals("XElement.replaceChild(xComment, xText)", + xElemFooNs, xElemFoo.getLastChild()); + + try { + xElemFoo.removeChild(null); + fail("XElement.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.removeChild(xElemFoo); + fail("XElement.removeChild()"); + } catch (DOMException e) { + assertTrue("XElement.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xElemFoo.removeChild(xComment); + assertEquals("XElement.removeChild(xComment)", xRemoved, xComment); + assertTrue("XElement.removeChild(xComment)", xElemFoo.hasChildNodes()); + assertEquals("XElement.removeChild(xComment)", + xElemFooNs, xElemFoo.getFirstChild()); + assertEquals("XElement.removeChild(xComment)", + xElemFooNs, xElemFoo.getLastChild()); + } + + @Test public void testXAttr() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XAttr xAttr = xDoc.createAttribute("foo"); + assertNotNull("XDocument.createAttribute", xAttr); + + XAttr xAttrNs = xDoc.createAttributeNS(ns, "e:foo"); + assertNotNull("XDocument.createAttribute", xAttr); + + assertTrue("XAttr.getSpecified", xAttr.getSpecified()); + + assertEquals("XAttr.getName()", "foo", xAttr.getName()); + + assertNull("XAttr.getOwnerElement()", xAttr.getOwnerElement()); + + XElement xElemFoo = xDoc.createElement("foo"); + XNode xInserted = xElemFoo.appendChild(xAttr); + XAttr xAttrIns = + UnoRuntime.queryInterface(XAttr.class, xInserted); + assertNotNull(xAttrIns); + assertEquals("XAttr.getOwnerElement()", + xElemFoo, xAttrIns.getOwnerElement()); + + assertEquals("XAttr.getValue()", "", xAttr.getValue()); + + xAttr.setValue("bar"); + assertEquals("XAttr.setValue()", "bar", xAttr.getValue()); + + // XNode //////////////////////////////////////////////////// + + { + XNode xAttrCloneN = xAttr.cloneNode(false); + assertNotNull("XAttr.cloneNode(false)", xAttrCloneN); + XAttr xAttrClone = + UnoRuntime.queryInterface(XAttr.class, xAttrCloneN); + assertNotNull("XAttr.cloneNode(false)", xAttrClone); + // actually the children are copied even if bDeep=false + // does that make sense for attributes? + /* + assertFalse("XAttr.cloneNode(false)", xAttrClone.hasChildNodes()); + assertNull("XAttr.cloneNode(false)", xAttrClone.getFirstChild()); + */ + assertTrue("XAttr.cloneNode(true)", xAttrClone.hasChildNodes()); + XNode xChild = xAttrClone.getFirstChild(); + assertNotNull("XAttr.cloneNode(true)", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.cloneNode(true)", xText); + assertEquals("XAttr.cloneNode(true)", "bar", xText.getNodeValue()); + } + { + XNode xAttrCloneN = xAttr.cloneNode(true); + assertNotNull("XAttr.cloneNode(true)", xAttrCloneN); + XAttr xAttrClone = + UnoRuntime.queryInterface(XAttr.class, xAttrCloneN); + assertNotNull("XAttr.cloneNode(true)", xAttrClone); + assertTrue("XAttr.cloneNode(true)", xAttrClone.hasChildNodes()); + XNode xChild = xAttrClone.getFirstChild(); + assertNotNull("XAttr.cloneNode(true)", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.cloneNode(true)", xText); + assertEquals("XAttr.cloneNode(true)", "bar", xText.getNodeValue()); + } + + assertNull("XAttr.getAttributes()", xAttr.getAttributes()); + + { + XNodeList xChildren = xAttr.getChildNodes(); + assertTrue("XAttr.getChildNodes()", 1 == xChildren.getLength()); + XNode xChild = xChildren.item(0); + assertNotNull("XAttr.getChildNodes()", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.getChildNodes()", xText); + + XNode xFirst = xAttr.getFirstChild(); + assertEquals("XAttr.getFirstChild()", xText, xFirst); + XNode xLast = xAttr.getLastChild(); + assertEquals("XAttr.getLastChild()", xText, xLast); + } + + assertEquals("XAttr.getLocalName()", "foo", xAttr.getLocalName()); + assertEquals("XAttr.getLocalName()", "foo", xAttrNs.getLocalName()); + + assertEquals("XAttr.getNamespaceURI()", "", xAttr.getNamespaceURI()); + assertEquals("XAttr.getNamespaceURI()", ns, xAttrNs.getNamespaceURI()); + + assertNull("XAttr.getNextSibling()", xAttr.getNextSibling()); + + assertEquals("XAttr.getNodeName()", "foo", xAttr.getNodeName()); + assertEquals("XAttr.getNodeName()", "foo", xAttrNs.getNodeName()); + + assertTrue("XAttr.getNodeType()", + ATTRIBUTE_NODE == xAttr.getNodeType()); + + assertEquals("XAttr.getNodeValue()", "bar", xAttr.getNodeValue()); + assertEquals("XAttr.getNodeValue()", "", xAttrNs.getNodeValue()); + + assertEquals("XAttr.getOwnerDocument()", + xDoc, xDoc.getOwnerDocument()); + + assertNull("XAttr.getParentNode()", xAttr.getParentNode()); + + assertEquals("XAttr.getPrefix()", "", xAttr.getPrefix()); + assertEquals("XAttr.getPrefix()", "e", xAttrNs.getPrefix()); + + assertNull("XAttr.getPreviousSibling()", xAttr.getPreviousSibling()); + + assertFalse("XAttr.hasAttributes()", xAttr.hasAttributes()); + + assertTrue("XAttr.hasChildNodes()", xAttr.hasChildNodes()); + + assertFalse("XAttr.isSupported()", + xAttr.isSupported("frobnication", "v99.33.0.0.0.1")); + + xAttr.normalize(); + + xAttr.setNodeValue("42"); + assertEquals("XAttr.setNodeValue()", "42", xAttr.getNodeValue()); + + xAttrNs.setPrefix("f"); + assertEquals("XAttr.setPrefix()", "f", xAttrNs.getPrefix()); + + XText xText = xDoc.createTextNode("baz"); + XText xTextNew = xDoc.createTextNode("quux"); + + try { + xAttr.appendChild(null); + fail("XAttr.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xAttr.insertBefore(null, xText); + fail("XAttr.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.insertBefore(xText, null); + fail("XAttr.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.insertBefore(xText, xText); + fail("XAttr.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XAttr.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xChild = xAttr.getFirstChild(); + assertNotNull(xChild); + + { + XNode xRet = xAttr.insertBefore(xText, xChild); + assertEquals("XAttr.insertBefore(xText, xChild)", + xRet, xChild); // why does this return the old node? + assertEquals("XAttr.insertBefore(xText, xChild)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.insertBefore(xText, xChild)", + xAttr, xText.getParentNode()); + assertEquals("XAttr.insertBefore(xText, xChild)", + xChild, xAttr.getLastChild()); + } + + try { + xAttr.replaceChild(null, xText); + fail("XAttr.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xAttr.replaceChild(xText, null); + fail("XAttr.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.replaceChild(xAttrNs, xAttrNs); // not child + fail("XAttr.replaceChild(xAttrNs, xAttrNs)"); + } catch (DOMException e) { + assertTrue("XAttr.replaceChild(xAttrNs, xAttrNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xAttr.replaceChild(xChild, xChild); // child + assertFalse("XAttr.replaceChild(xChild, xChild)", + false); + } catch (DOMException e) { + assertTrue("XAttr.replaceChild(xChild, xChild)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xAttr.replaceChild(xTextNew, xChild); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", xChild, xReplaced); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", + xTextNew, xAttr.getLastChild()); + + try { + xAttr.removeChild(null); + fail("XAttr.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.removeChild(xAttrNs); + fail("XAttr.removeChild()"); + } catch (DOMException e) { + assertTrue("XAttr.removeChild()", HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xAttr.removeChild(xTextNew); + assertEquals("XAttr.removeChild(xText)", xRemoved, xTextNew); + assertTrue("XAttr.removeChild(xText)", xAttr.hasChildNodes()); + assertEquals("XAttr.removeChild(xText)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.removeChild(xText)", + xText, xAttr.getLastChild()); + } + + @Test public void testXText() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XText xText = xDoc.createTextNode("foobar"); + assertNotNull(xText); + + assertEquals("XText.getData", "foobar", xText.getData()); + assertEquals("XText.getLength", 6, xText.getLength()); + + /* FIXME + try { + xText.splitText(9999); + fail("XText.splitText(9999)"); + } catch (DOMException e) { + assertTrue("XText.splitText(9999)", INDEX_SIZE_ERR == e.Code); + } + + { + XText xTextBar = xText.splitText(2); + assertNotNull("XText.splitText", xTextBar); + assertEquals("XText.splitText", "foo", xText.getData()); + assertEquals("XText.splitText", "bar", xTextBar.getData()); + } + */ + xText.setData("foo"); + + xText.appendData("baz"); + assertEquals("XText.appendData", "foobaz", xText.getData()); + + try { + xText.deleteData(999,999); + fail("XText.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XText.deleteData(999,999)", INDEX_SIZE_ERR == e.Code); + } + xText.deleteData(0, 3); + assertEquals("XText.deleteData", "baz", xText.getData()); + + try { + xText.insertData(999,"blah"); + fail("XText.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XText.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xText.insertData(1, "arb"); + assertEquals("XText.insertData", "barbaz", xText.getData()); + + try { + xText.replaceData(999,999,"x"); + fail("XText.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XText.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xText.replaceData(3, 3, "foo"); + assertEquals("XText.replaceData", "barfoo", xText.getData()); + + xText.setData("quux"); + assertEquals("XText.setData", "quux", xText.getData()); + + try { + xText.subStringData(999,999); + fail("XText.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XText.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XText.subStringData", "x", xText.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xTextCloneN = xText.cloneNode(false); + assertNotNull("XText.cloneNode(false)", xTextCloneN); + XText xTextClone = + UnoRuntime.queryInterface(XText.class, xTextCloneN); + assertNotNull("XText.cloneNode(false)", xTextClone); + assertFalse("XText.cloneNode(false)", + xTextClone.hasChildNodes()); + } + { + XNode xTextCloneN = xText.cloneNode(true); + assertNotNull("XText.cloneNode(true)", xTextCloneN); + XText xTextClone = + UnoRuntime.queryInterface(XText.class, xTextCloneN); + assertNotNull("XText.cloneNode(true)", xTextClone); + assertFalse("XText.cloneNode(true)", xTextClone.hasChildNodes()); + } + + assertNull("XText.getAttributes()", xText.getAttributes()); + + { + XNodeList xChildren = xText.getChildNodes(); + assertTrue("XText.getChildNodes()", 0 == xChildren.getLength()); + } + + assertEquals("XText.getLocalName()", "", xText.getLocalName()); + + assertEquals("XText.getNamespaceURI()", "", xText.getNamespaceURI()); + + assertNull("XText.getNextSibling()", xText.getNextSibling()); + + assertEquals("XText.getNodeName()", "#text", xText.getNodeName()); + + assertTrue("XText.getNodeType()", + TEXT_NODE == xText.getNodeType()); + + assertEquals("XText.getNodeValue()", "quux", xText.getNodeValue()); + + assertEquals("XText.getOwnerDocument()", + xDoc, xText.getOwnerDocument()); + + assertNull("XText.getParentNode()", xText.getParentNode()); + + assertEquals("XText.getPrefix()", "", xText.getPrefix()); + + assertNull("XText.getPreviousSibling()", xText.getPreviousSibling()); + + assertFalse("XText.hasAttributes()", xText.hasAttributes()); + + assertFalse("XText.hasChildNodes()", xText.hasChildNodes()); + + assertFalse("XText.isSupported()", + xText.isSupported("frobnication", "v99.33.0.0.0.1")); + + xText.normalize(); + + xText.setNodeValue("42"); + assertEquals("XText.setNodeValue()", "42", xText.getNodeValue()); + + try { + xText.setPrefix("foo"); + fail("XText.setPrefix()"); + } catch (DOMException e) { + assertTrue("XText.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XText xText2 = xDoc.createTextNode("foobar"); + XText xText3 = xDoc.createTextNode("foobar"); + + try { + xText.appendChild(null); + fail("XText.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xText.appendChild(xText2); + fail("XText.appendChild(xText2)"); + } catch (DOMException e) { + assertTrue("XText.appendChild(xText2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xText.insertBefore(xText2, xText3); + fail("XText.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xText.replaceChild(xText2, xText3); + fail("XText.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xText.removeChild(null); + fail("XText.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xText.removeChild(xText2); + fail("XText.removeChild"); + } catch (DOMException e) { + assertTrue("XText.removeChild", HIERARCHY_REQUEST_ERR == e.Code); + } + } + + @Test public void testXCDataSection() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XCDATASection xCDS = xDoc.createCDATASection("foobar"); + assertNotNull(xCDS); + + assertEquals("XCDATASection.getData", "foobar", xCDS.getData()); + assertEquals("XCDATASection.getLength", 6, xCDS.getLength()); + + /* FIXME + try { + xCDS.splitText(9999); + fail("XCDATASection.splitText(9999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.splitText(9999)", + INDEX_SIZE_ERR == e.Code); + } + + { + XCDATASection xCDSBar = xCDS.splitText(2); + assertNotNull("XCDATASection.splitText", xCDSBar); + assertEquals("XCDATASection.splitText", "foo", xCDS.getData()); + assertEquals("XCDATASection.splitText", "bar", xCDSBar.getData()); + } + */ + xCDS.setData("foo"); + + xCDS.appendData("baz"); + assertEquals("XCDATASection.appendData", "foobaz", xCDS.getData()); + + try { + xCDS.deleteData(999,999); + fail("XCDATASection.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.deleteData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + xCDS.deleteData(0, 3); + assertEquals("XCDATASection.deleteData", "baz", xCDS.getData()); + + try { + xCDS.insertData(999,"blah"); + fail("XCDATASection.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XCDATASection.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xCDS.insertData(1, "arb"); + assertEquals("XCDATASection.insertData", "barbaz", xCDS.getData()); + + try { + xCDS.replaceData(999,999,"x"); + fail("XCDATASection.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XCDATASection.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xCDS.replaceData(3, 3, "foo"); + assertEquals("XCDATASection.replaceData", "barfoo", xCDS.getData()); + + xCDS.setData("quux"); + assertEquals("XCDATASection.setData", "quux", xCDS.getData()); + + try { + xCDS.subStringData(999,999); + fail("XCDATASection.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XCDATASection.subStringData", "x", + xCDS.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xCDSCloneN = xCDS.cloneNode(false); + assertNotNull("XCDATASection.cloneNode(false)", xCDSCloneN); + XCDATASection xCDSClone = + UnoRuntime.queryInterface(XCDATASection.class, xCDSCloneN); + assertNotNull("XCDATASection.cloneNode(false)", xCDSClone); + assertFalse("XCDATASection.cloneNode(false)", + xCDSClone.hasChildNodes()); + } + { + XNode xCDSCloneN = xCDS.cloneNode(true); + assertNotNull("XCDATASection.cloneNode(true)", xCDSCloneN); + XCDATASection xCDSClone = + UnoRuntime.queryInterface(XCDATASection.class, xCDSCloneN); + assertNotNull("XCDATASection.cloneNode(true)", xCDSClone); + assertFalse("XCDATASection.cloneNode(true)", + xCDSClone.hasChildNodes()); + } + + assertNull("XCDATASection.getAttributes()", xCDS.getAttributes()); + + { + XNodeList xChildren = xCDS.getChildNodes(); + assertTrue("XCDATASection.getChildNodes()", + 0 == xChildren.getLength()); + } + + assertEquals("XCDATASection.getLocalName()", "", xCDS.getLocalName()); + + assertEquals("XCDATASection.getNamespaceURI()", "", + xCDS.getNamespaceURI()); + + assertNull("XCDATASection.getNextSibling()", xCDS.getNextSibling()); + + assertEquals("XCDATASection.getNodeName()", "#cdata-section", + xCDS.getNodeName()); + + assertTrue("XCDATASection.getNodeType()", + CDATA_SECTION_NODE == xCDS.getNodeType()); + + assertEquals("XCDATASection.getNodeValue()", "quux", + xCDS.getNodeValue()); + + assertEquals("XCDATASection.getOwnerDocument()", + xDoc, xCDS.getOwnerDocument()); + + assertNull("XCDATASection.getParentNode()", xCDS.getParentNode()); + + assertEquals("XCDATASection.getPrefix()", "", xCDS.getPrefix()); + + assertNull("XCDATASection.getPreviousSibling()", + xCDS.getPreviousSibling()); + + assertFalse("XCDATASection.hasAttributes()", xCDS.hasAttributes()); + + assertFalse("XCDATASection.hasChildNodes()", xCDS.hasChildNodes()); + + assertFalse("XCDATASection.isSupported()", + xCDS.isSupported("frobnication", "v99.33.0.0.0.1")); + + xCDS.normalize(); + + xCDS.setNodeValue("42"); + assertEquals("XCDATASection.setNodeValue()", "42", xCDS.getNodeValue()); + + try { + xCDS.setPrefix("foo"); + fail("XCDATASection.setPrefix()"); + } catch (DOMException e) { + assertTrue("XCDATASection.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XCDATASection xCDS2 = xDoc.createCDATASection("foobar"); + XCDATASection xCDS3 = xDoc.createCDATASection("foobar"); + + try { + xCDS.appendChild(null); + fail("XCDATASection.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xCDS.appendChild(xCDS2); + fail("XCDATASection.appendChild(xCDS2)"); + } catch (DOMException e) { + assertTrue("XCDATASection.appendChild(xCDS2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xCDS.insertBefore(xCDS2, xCDS3); + fail("XCDATASection.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.replaceChild(xCDS2, xCDS3); + fail("XCDATASection.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.removeChild(null); + fail("XCDATASection.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.removeChild(xCDS2); + fail("XCDATASection.removeChild"); + } catch (DOMException e) { + assertTrue("XCDATASection.removeChild", + HIERARCHY_REQUEST_ERR == e.Code); + } + + } + + @Test public void testXComment() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XComment xComment = xDoc.createComment("foo"); + assertNotNull(xComment); + + assertEquals("XComment.getData", "foo", xComment.getData()); + assertEquals("XComment.getLength", 3, xComment.getLength()); + + xComment.appendData("baz"); + assertEquals("XComment.appendData", "foobaz", xComment.getData()); + + try { + xComment.deleteData(999,999); + fail("XComment.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XComment.deleteData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + xComment.deleteData(0, 3); + assertEquals("XComment.deleteData", "baz", xComment.getData()); + + try { + xComment.insertData(999,"blah"); + fail("XComment.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XComment.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xComment.insertData(1, "arb"); + assertEquals("XComment.insertData", "barbaz", xComment.getData()); + + try { + xComment.replaceData(999,999,"x"); + fail("XComment.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XComment.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xComment.replaceData(3, 3, "foo"); + assertEquals("XComment.replaceData", "barfoo", xComment.getData()); + + xComment.setData("quux"); + assertEquals("XComment.setData", "quux", xComment.getData()); + + try { + xComment.subStringData(999,999); + fail("XComment.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XComment.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XComment.subStringData", "x", + xComment.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xCommentCloneN = xComment.cloneNode(false); + assertNotNull("XComment.cloneNode(false)", xCommentCloneN); + XComment xCommentClone = + UnoRuntime.queryInterface(XComment.class, xCommentCloneN); + assertNotNull("XComment.cloneNode(false)", xCommentClone); + assertFalse("XComment.cloneNode(false)", + xCommentClone.hasChildNodes()); + } + { + XNode xCommentCloneN = xComment.cloneNode(true); + assertNotNull("XComment.cloneNode(true)", xCommentCloneN); + XComment xCommentClone = + UnoRuntime.queryInterface(XComment.class, xCommentCloneN); + assertNotNull("XComment.cloneNode(true)", xCommentClone); + assertFalse("XComment.cloneNode(true)", + xCommentClone.hasChildNodes()); + } + + assertNull("XComment.getAttributes()", xComment.getAttributes()); + + { + XNodeList xChildren = xComment.getChildNodes(); + assertTrue("XComment.getChildNodes()", 0 == xChildren.getLength()); + } + + assertEquals("XComment.getLocalName()", "", xComment.getLocalName()); + + assertEquals("XComment.getNamespaceURI()", "", + xComment.getNamespaceURI()); + + assertNull("XComment.getNextSibling()", xComment.getNextSibling()); + + assertEquals("XComment.getNodeName()", "#comment", + xComment.getNodeName()); + + assertTrue("XComment.getNodeType()", + COMMENT_NODE == xComment.getNodeType()); + + assertEquals("XComment.getNodeValue()", "quux", + xComment.getNodeValue()); + + assertEquals("XComment.getOwnerDocument()", + xDoc, xComment.getOwnerDocument()); + + assertNull("XComment.getParentNode()", xComment.getParentNode()); + + assertEquals("XComment.getPrefix()", "", xComment.getPrefix()); + + assertNull("XComment.getPreviousSibling()", + xComment.getPreviousSibling()); + + assertFalse("XComment.hasAttributes()", xComment.hasAttributes()); + + assertFalse("XComment.hasChildNodes()", xComment.hasChildNodes()); + + assertFalse("XComment.isSupported()", + xComment.isSupported("frobnication", "v99.33.0.0.0.1")); + + xComment.normalize(); + + xComment.setNodeValue("42"); + assertEquals("XComment.setNodeValue()", "42", xComment.getNodeValue()); + + try { + xComment.setPrefix("foo"); + fail("XComment.setPrefix()"); + } catch (DOMException e) { + assertTrue("XComment.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XComment xComment2 = xDoc.createComment("foobar"); + XComment xComment3 = xDoc.createComment("foobar"); + + try { + xComment.appendChild(null); + fail("XComment.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xComment.appendChild(xComment2); + fail("XComment.appendChild(xComment2)"); + } catch (DOMException e) { + assertTrue("XComment.appendChild(xComment2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xComment.insertBefore(xComment2, xComment3); + fail("XComment.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xComment.replaceChild(xComment2, xComment3); + fail("XComment.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xComment.removeChild(null); + fail("XComment.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xComment.removeChild(xComment2); + fail("XComment.removeChild"); + } catch (DOMException e) { + assertTrue("XComment.removeChild", HIERARCHY_REQUEST_ERR == e.Code); + } + } + + @Test public void testXEntityReference() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XEntityReference xER = xDoc.createEntityReference("foobar"); + assertNotNull(xER); + + XEntityReference xERChild = xDoc.createEntityReference("baz"); + assertNotNull(xERChild); + + xER.appendChild(xERChild); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNode xERCloneN = xER.cloneNode(false); + assertNotNull("XEntityReference.cloneNode(false)", xERCloneN); + XEntityReference xERClone = + UnoRuntime.queryInterface(XEntityReference.class, xERCloneN); + assertNotNull("XEntityReference.cloneNode(false)", xERClone); + assertFalse("XEntityReference.cloneNode(false)", + xERClone.hasChildNodes()); + assertNull("XEntityReference.cloneNode(false)", + xERClone.getFirstChild()); + } + { + XNode xERCloneN = xER.cloneNode(true); + assertNotNull("XEntityReference.cloneNode(true)", xERCloneN); + XEntityReference xERClone = + UnoRuntime.queryInterface(XEntityReference.class, xERCloneN); + assertNotNull("XEntityReference.cloneNode(true)", xERClone); + /* FIXME this is actually in libxml2: children are not copied + assertTrue("XEntityReference.cloneNode(true)", + xERClone.hasChildNodes()); + XNode xChild = xERClone.getFirstChild(); + assertNotNull("XEntityReference.cloneNode(true)", xChild); + XEntityReference xChildER = + UnoRuntime.queryInterface(XEntityReference.class, xChild); + assertNotNull("XEntityReference.cloneNode(true)", xChildER); + assertFalse("XEntityReference.cloneNode(true)", + xChildER.equals(xERChild)); + assertEquals("XEntityReference.cloneNode(true)", + "baz", xChildER.getLocalName()); + */ + } + + assertNull("XEntityReference.getAttributes()", xER.getAttributes()); + + { + XNodeList xChildren = xER.getChildNodes(); + assertTrue("XEntityReference.getChildNodes()", + 1 == xChildren.getLength()); + assertEquals("XEntityReference.getChildNodes()", + xERChild, xChildren.item(0)); + + XNode xFirst = xER.getFirstChild(); + assertEquals("XEntityReference.getFirstChild()", + xERChild, xFirst); + XNode xLast = xER.getLastChild(); + assertEquals("XEntityReference.getLastChild()", xERChild, xLast); + } + + assertEquals("XEntityReference.getLocalName()", "", xER.getLocalName()); + + assertEquals("XEntityReference.getNamespaceURI()", "", + xER.getNamespaceURI()); + + assertNull("XEntityReference.getNextSibling()", xER.getNextSibling()); + + assertEquals("XEntityReference.getNodeName()", + "foobar", xER.getNodeName()); + + assertTrue("XEntityReference.getNodeType()", + ENTITY_REFERENCE_NODE == xER.getNodeType()); + + assertEquals("XEntityReference.getNodeValue()", "", xER.getNodeValue()); + + assertEquals("XEntityReference.getOwnerDocument()", + xDoc, xER.getOwnerDocument()); + + assertNull("XEntityReference.getParentNode()", xER.getParentNode()); + + assertEquals("XEntityReference.getPrefix()", "", xER.getPrefix()); + + assertNull("XEntityReference.getPreviousSibling()", + xER.getPreviousSibling()); + + assertFalse("XEntityReference.hasAttributes()", xER.hasAttributes()); + + assertTrue("XEntityReference.hasChildNodes()", xER.hasChildNodes()); + + assertFalse("XEntityReference.isSupported()", + xER.isSupported("frobnication", "v99.33.0.0.0.1")); + + xER.normalize(); + + try { + xER.setNodeValue("42"); + fail("XEntityReference.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XEntityReference.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xER.setPrefix("foo"); + fail("XEntityReference.setPrefix()"); + } catch (DOMException e) { + assertTrue("XEntityReference.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xER.appendChild(null); + fail("XEntityReference.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xER.insertBefore(null, xText); + fail("XEntityReference.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xER.insertBefore(xText, null); + fail("XEntityReference.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xER.insertBefore(xText, xText); + fail("XEntityReference.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XEntityReference.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xER.insertBefore(xComment, xERChild); + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xRet, xERChild); // why does this return the old node? + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xComment, xER.getFirstChild()); + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xER, xComment.getParentNode()); + assertEquals("XEntityReference.insertBefore(xCommnet, xERChild)", + xERChild, xER.getLastChild()); + } + + try { + xER.replaceChild(null, xText); + fail("XEntityReference.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xER.replaceChild(xText, null); + fail("XEntityReference.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xER.replaceChild(xText, xText); // not child + fail("XEntityReference.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XEntityReference.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xER.replaceChild(xERChild, xERChild); // child + assertFalse("XEntityReference.replaceChild(xERChild, xERChild)", + false); + } catch (DOMException e) { + assertTrue("XEntityReference.replaceChild(xERChild, xERChild)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xER.replaceChild(xText, xComment); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xReplaced, xComment); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xText, xER.getFirstChild()); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xERChild, xER.getLastChild()); + + try { + xER.removeChild(null); + fail("XEntityReference.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xER.removeChild(xER); + fail("XEntityReference.removeChild()"); + } catch (DOMException e) { + assertTrue("XEntityReference.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xER.removeChild(xText); + assertEquals("XEntityReference.removeChild(xText)", xRemoved, xText); + assertTrue("XEntityReference.removeChild(xText)", xER.hasChildNodes()); + assertEquals("XEntityReference.removeChild(xText)", + xERChild, xER.getFirstChild()); + assertEquals("XEntityReference.removeChild(xText)", + xERChild, xER.getLastChild()); + } + + @Test public void testXProcessingInstruction() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XProcessingInstruction xPI = + xDoc.createProcessingInstruction("foo", "bar"); + assertNotNull(xPI); + + assertEquals("XProcessingInstruction.getTarget", + "foo", xPI.getTarget()); + + assertEquals("XProcessingInstruction.getData", "bar", xPI.getData()); + + xPI.setData("baz"); + assertEquals("XProcessingInstruction.setData", "baz", xPI.getData()); + + // XNode //////////////////////////////////////////////////// + + { + XNode xPICloneN = xPI.cloneNode(false); + assertNotNull("XProcessingInstruction.cloneNode(false)", xPICloneN); + XProcessingInstruction xPIClone = UnoRuntime.queryInterface( + XProcessingInstruction.class, xPICloneN); + assertNotNull("XProcessingInstruction.cloneNode(false)", xPIClone); + assertFalse("XProcessingInstruction.cloneNode(false)", + xPIClone.hasChildNodes()); + } + { + XNode xPICloneN = xPI.cloneNode(true); + assertNotNull("XProcessingInstruction.cloneNode(true)", xPICloneN); + XProcessingInstruction xPIClone = UnoRuntime.queryInterface( + XProcessingInstruction.class, xPICloneN); + assertNotNull("XProcessingInstruction.cloneNode(true)", xPIClone); + assertFalse("XProcessingInstruction.cloneNode(true)", + xPIClone.hasChildNodes()); + } + + assertNull("XProcessingInstruction.getAttributes()", + xPI.getAttributes()); + + { + XNodeList xChildren = xPI.getChildNodes(); + assertTrue("XProcessingInstruction.getChildNodes()", + 0 == xChildren.getLength()); + } + + assertEquals("XProcessingInstruction.getLocalName()", + "", xPI.getLocalName()); + + assertEquals("XProcessingInstruction.getNamespaceURI()", + "", xPI.getNamespaceURI()); + + assertNull("XProcessingInstruction.getNextSibling()", + xPI.getNextSibling()); + + assertEquals("XProcessingInstruction.getNodeName()", + "foo", xPI.getNodeName()); + + assertTrue("XProcessingInstruction.getNodeType()", + PROCESSING_INSTRUCTION_NODE == xPI.getNodeType()); + + assertEquals("XProcessingInstruction.getNodeValue()", + "baz", xPI.getNodeValue()); + + assertEquals("XProcessingInstruction.getOwnerDocument()", + xDoc, xPI.getOwnerDocument()); + + assertNull("XProcessingInstruction.getParentNode()", + xPI.getParentNode()); + + assertEquals("XProcessingInstruction.getPrefix()", "", xPI.getPrefix()); + + assertNull("XProcessingInstruction.getPreviousSibling()", + xPI.getPreviousSibling()); + + assertFalse("XProcessingInstruction.hasAttributes()", + xPI.hasAttributes()); + + assertFalse("XProcessingInstruction.hasChildNodes()", + xPI.hasChildNodes()); + + assertFalse("XProcessingInstruction.isSupported()", + xPI.isSupported("frobnication", "v99.33.0.0.0.1")); + + xPI.normalize(); + + xPI.setNodeValue("42"); + assertEquals("XProcessingInstruction.setNodeValue()", + "42", xPI.getNodeValue()); + + try { + xPI.setPrefix("foo"); + fail("XProcessingInstruction.setPrefix()"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XText xText2 = xDoc.createTextNode("foobar"); + XText xText3 = xDoc.createTextNode("foobar"); + + try { + xPI.appendChild(null); + fail("XProcessingInstruction.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xPI.appendChild(xText2); + fail("XProcessingInstruction.appendChild(xText2)"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.appendChild(xText2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xPI.insertBefore(xText2, xText3); + fail("XProcessingInstruction.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xPI.replaceChild(xText2, xText3); + fail("XProcessingInstruction.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xPI.removeChild(null); + fail("XProcessingInstruction.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xPI.removeChild(xText2); + fail("XProcessingInstruction.removeChild"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.removeChild", + HIERARCHY_REQUEST_ERR == e.Code); + } + } + + /* + @Test public void testXEntity() throws Exception + { + XEntity xEntity = FIXME how to get at this shy creature? + } + */ + + /* + @Test public void testXNotation() throws Exception + { + XNotation xNotation = FIXME how to create? + } + */ + + /* + @Test public void testXDocumentType() throws Exception + { + XDocumentType xDT = FIXME how to create? + } + */ + + @Test public void testXNodeList_ChildList() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + XElement xFoo = xDoc.createElement("foo"); + XElement xBar = xDoc.createElement("bar"); + XElement xBaz = xDoc.createElement("baz"); + + xDoc.appendChild(xRoot); + + XNodeList xChildList = xRoot.getChildNodes(); + assertNotNull(xChildList); + assertSame("ChildList.getLength()", 0, xChildList.getLength()); + + try { + xChildList.item(4); + } catch (Exception e) { /* expected */ } + + xRoot.appendChild(xFoo); + assertSame("ChildList.getLength()", 1, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + + xRoot.appendChild(xBar); + assertSame("ChildList.getLength()", 2, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBar, xChildList.item(1)); + + xRoot.appendChild(xBaz); + assertSame("ChildList.getLength()", 3, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBar, xChildList.item(1)); + assertEquals("ChildList.item", xBaz, xChildList.item(2)); + + xRoot.removeChild(xBar); + assertSame("ChildList.getLength()", 2, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBaz, xChildList.item(1)); + } + + @Test public void testXNodeList_ElementList() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + XElement xBar = xDoc.createElement("bar"); + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFoo3 = xDoc.createElement("foo"); + + xDoc.appendChild(xRoot); + + XNodeList xElementList = xRoot.getElementsByTagName("foo"); + assertNotNull(xElementList); + assertSame("ElementList.getLength()", 0, xElementList.getLength()); + + try { + xElementList.item(4); + } catch (Exception e) { /* expected */ } + + xRoot.appendChild(xFoo1); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + + xFoo1.appendChild(xBar); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + + xRoot.appendChild(xFoo3); + assertSame("ElementList.getLength()", 2, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + assertEquals("ElementList.item", xFoo3, xElementList.item(1)); + + xBar.appendChild(xFoo2); + assertSame("ElementList.getLength()", 3, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + assertEquals("ElementList.item", xFoo2, xElementList.item(1)); + assertEquals("ElementList.item", xFoo3, xElementList.item(2)); + + xRoot.removeChild(xFoo1); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo3, xElementList.item(0)); + } + + @Test public void testXNamedNodeMap_AttributesMap() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XElement xElem = xDoc.createElement("foo"); + + XNamedNodeMap xAttributes = xElem.getAttributes(); + assertNotNull(xAttributes); + assertSame("AttributesMap.getLength()", 0, xAttributes.getLength()); + + try { + xAttributes.item(4); + } catch (Exception e) { /* expected */ } + + xElem.setAttribute("bar", "42"); + XAttr xAttrBar = xElem.getAttributeNode("bar"); + assertSame("AttributesMap.getLength()", 1, xAttributes.getLength()); + assertEquals("AttributesMap.item", xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.getNamedItem", + xAttrBar, xAttributes.getNamedItem("bar")); + + xElem.setAttributeNS(ns, "n:bar", "43"); + XAttr xAttrBarNs = xElem.getAttributeNodeNS(ns, "bar"); + assertSame("AttributesMap.getLength()", 2, xAttributes.getLength()); + assertEquals("AttributesMap.item", xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.item", xAttrBarNs, xAttributes.item(1)); + assertEquals("AttributesMap.getNamedItem", + xAttrBar, xAttributes.getNamedItem("bar")); + assertEquals("AttributesMap.getNamedItemNS", + xAttrBarNs, xAttributes.getNamedItemNS(ns, "bar")); + + XNode xAttrBarNsRem = xAttributes.removeNamedItemNS(ns, "bar"); + assertSame("AttributesMap.getLength()", 1, xAttributes.getLength()); + assertEquals("AttributesMap.removeNamedItemNS", + xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.removeNamedItemNS", + xAttrBar, xAttributes.getNamedItem("bar")); + assertNull("AttributesMap.removeNamedItemNS", + xAttrBarNsRem.getParentNode()); + + XNode xAttrBarRem = xAttributes.removeNamedItem("bar"); + assertSame("AttributesMap.getLength()", 0, xAttributes.getLength()); + assertNull("AttributesMap.removeNamedItem", + xAttrBarRem.getParentNode()); + + XNode xAttrBarSetN = xAttributes.setNamedItem(xAttrBarRem); + assertNotNull("AttributesMap.setNamedItem", xAttrBarSetN); + XAttr xAttrBarSet = + UnoRuntime.queryInterface(XAttr.class, xAttrBarSetN); + assertNotNull("AttributesMap.setNamedItem", xAttrBarSet); + assertEquals("AttributesMap.setNamedItem", + xAttrBarSet, xAttributes.getNamedItem("bar")); + + XNode xAttrBarNsSetN = xAttributes.setNamedItemNS(xAttrBarNsRem); + assertNotNull("AttributesMap.setNamedItemNS", xAttrBarNsSetN); + XAttr xAttrBarNsSet = + UnoRuntime.queryInterface(XAttr.class, xAttrBarNsSetN); + assertNotNull("AttributesMap.setNamedItemNS", xAttrBarNsSet); + assertEquals("AttributesMap.setNamedItemNS", + xAttrBarNsSet, xAttributes.getNamedItemNS(ns, "bar")); + assertSame("AttributesMap.getLength()", 2, xAttributes.getLength()); + } + + /* + @Test public void testXNamedNodeMap_EntitiesMap() throws Exception + { + XNamedNodeMap xEntities = FIXME + } + */ + + /* + @Test public void testXNamedNodeMap_NotationsMap() throws Exception + { + XNamedNodeMap xNotations = FIXME + } + */ + + @Test public void testXXPathAPI() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + try { + xXPathAPI.eval(xRoot, "~/-$+&#_"); + fail("XXPathAPI.eval"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.evalNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.evalNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectNodeList(xRoot, "~/-$+&#_"); + fail("XXPathAPI.selectNodeList"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectNodeListNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.selectNodeListNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectSingleNode(xRoot, "~/-$+&#_"); + fail("XXPathAPI.selectSingleNode"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectSingleNodeNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.selectSingleNodeNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.eval(null, "child::foo"); + fail("XXPathAPI.eval(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.evalNS(null, "child::foo", xRoot); + fail("XXPathAPI.evalNS(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectNodeList(null, "child::foo"); + fail("XXPathAPI.selectNodeList(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectNodeListNS(null, "child::foo", xRoot); + fail("XXPathAPI.selectNodeListNS(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectSingleNode(null, "child::foo"); + fail("XXPathAPI.selectSingleNode(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectSingleNodeNS(null, "child::foo", xRoot); + fail("XXPathAPI.selectSingleNodeNS(null)"); + } catch (Exception e) { /* expected */ } + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(child::foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathAPI.eval", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathAPI.eval", 1, xResult.getLong()); + } + { + XXPathObject xResult = + xXPathAPI.evalNS(xRoot, "count(//ns:foo)", xFooNs); + assertNotNull("XXPathAPI.evalNS", xResult); + assertEquals("XXPathAPI.evalNS", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathAPI.evalNS", 1, xResult.getLong()); + } + { + XNodeList xResult = xXPathAPI.selectNodeList(xRoot, "child::foo"); + assertNotNull("XXPathAPI.selectNodeList", xResult); + assertEquals("XXPathAPI.selectNodeList", 1, xResult.getLength()); + assertEquals("XXPathAPI.selectNodeList", xFoo1, xResult.item(0)); + } + { + XNodeList xResult = + xXPathAPI.selectNodeListNS(xRoot, ".//ns:foo", xFooNs); + assertNotNull("XXPathAPI.selectNodeListNS", xResult); + assertEquals("XXPathAPI.selectNodeListNS", 1, xResult.getLength()); + assertEquals("XXPathAPI.selectNodeListNS", xFooNs, xResult.item(0)); + } + { + XNode xResult = xXPathAPI.selectSingleNode(xBar, "child::foo"); + assertNotNull("XXPathAPI.selectSingleNode", xResult); + assertEquals("XXPathAPI.selectSingleNode", xFoo2, xResult); + } + { + XNode xResult = + xXPathAPI.selectSingleNodeNS(xFoo2, "//ns:foo", xFooNs); + assertNotNull("XXPathAPI.selectSingleNodeNS", xResult); + assertEquals("XXPathAPI.selectSingleNodeNS", xFooNs, xResult); + } + + try { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + fail("XXPathAPI.selectSingleNode"); + } catch (XPathException e) { /* expected */ } + xXPathAPI.registerNS("pre", ns); + { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + assertNotNull("XXPathAPI.registerNS", xResult); + assertEquals("XXPathAPI.registerNS", xFooNs, xResult); + } + + xXPathAPI.unregisterNS("pre", ns); + try { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + fail("XXPathAPI.unregisterNS"); + } catch (XPathException e) { /* expected */ } + + /* FIXME + registerExtension(""); + registerExtensionInstance(xExtension); + */ + } + + @Test public void testXXPathObject() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathObject.getByte", 2, xResult.getByte()); + assertEquals("XXPathObject.getShort", 2, xResult.getShort()); + assertEquals("XXPathObject.getLong", 2, xResult.getLong()); + assertEquals("XXPathObject.getHyper", 2, xResult.getHyper()); + assertEquals("XXPathObject.getFloat", 2.0, xResult.getFloat(), 0.0); + assertEquals("XXPathObject.getDouble", + 2.0, xResult.getDouble(), 0.0); + assertEquals("XXPathObject.getString", "2", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo) = 2"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_BOOLEAN, xResult.getObjectType()); + assertEquals("XXPathObject.getBoolean", true, xResult.getBoolean()); + assertEquals("XXPathObject.getString", "true", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo) = 2"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_BOOLEAN, xResult.getObjectType()); + assertEquals("XXPathObject.getBoolean", true, xResult.getBoolean()); + assertEquals("XXPathObject.getString", "true", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "local-name(foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_STRING, xResult.getObjectType()); + assertEquals("XXPathObject.getString", "foo", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "//foo"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NODESET, xResult.getObjectType()); + assertNotNull("XXPathObject.getNodeList", xResult.getNodeList()); + } + } + + @Test public void testXNodeList_NodeList() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "//foo"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NODESET, xResult.getObjectType()); + XNodeList xNodeList = xResult.getNodeList(); + assertNotNull("XXPathObject.getNodeList", xNodeList); + assertEquals("NodeList.getLength", 2, xNodeList.getLength()); + assertEquals("NodeList.item", xFoo1, xNodeList.item(0)); + assertEquals("NodeList.item", xFoo2, xNodeList.item(1)); + } + } + + + // just for importNode... + abstract class MockNode implements XNode + { + MockDoc m_document; + MockNode m_parent; + MockNode m_prev; + MockNode m_next; + MockNode[] m_children; + String m_localname; + +// MockNode() { ; } + void init(MockDoc doc, MockNode parent, MockNode prev, MockNode next, + MockNode[] children) + { + m_document = doc; + m_parent = parent; m_prev = prev; m_next = next; + m_children = children; + } + + public XNode appendChild(XNode c) throws DOMException { + fail("MockNode.appendChild called?"); + return null; + } + public XNode cloneNode(boolean b) { + fail("MockNode.cloneNode called?"); + return null; + } + public XNamedNodeMap getAttributes() { + fail("MockNode.getAttributes not implemented"); + return null; + } + public XNodeList getChildNodes() { + fail("MockNode.getChildList not implemented"); + return null; + } + public XNode getFirstChild() { + return (m_children.length != 0) ? m_children[0] : null; + } + public XNode getLastChild() { + return (m_children.length != 0) + ? m_children[m_children.length-1] : null; + } + public String getLocalName() { return m_localname; } + public String getNamespaceURI() { return ""; } + public XNode getNextSibling() { return m_next; } + public String getNodeName() { return m_localname; } +// NodeType getNodeType() { return m_type; } + public String getNodeValue() throws DOMException { return ""; } + public XDocument getOwnerDocument() { return m_document; } + public XNode getParentNode() { return m_parent; } + public String getPrefix() { return ""; } + public XNode getPreviousSibling() { return m_prev; } + public boolean hasAttributes() { return false; } + public boolean hasChildNodes() { return m_children.length != 0; } + public XNode insertBefore(XNode c, XNode r) throws DOMException { + fail("MockNode.insertBefore called?"); + return null; + } + public boolean isSupported(String a, String b) { return false; } + public void normalize() { + fail("MockNode.normalize called?"); + } + public XNode removeChild(XNode c) throws DOMException { + fail("MockNode.removeChild called?"); + return null; + } + public XNode replaceChild(XNode c, XNode o) throws DOMException { + fail("MockNode.replaceChild called?"); + return null; + } + public void setNodeValue(String v) throws DOMException { + fail("MockNode.setNodeValue called?"); + } + public void setPrefix(String p) throws DOMException { + fail("MockNode.setPrefix called?"); + } + } + class MockDoc extends MockNode implements XDocument + { +// MockDoc() { } + void init(MockNode[] children) { + super.init(this, null, null, null, children); + } + + public NodeType getNodeType() { return DOCUMENT_NODE; } + + public XAttr createAttribute(String n) throws DOMException { + fail("MockNode.createAttribute called?"); + return null; + } + public XAttr createAttributeNS(String n, String q) throws DOMException { + fail("MockNode.createAttributeNS called?"); + return null; + } + public XCDATASection createCDATASection(String s) throws DOMException { + fail("MockNode.createCDATASection called?"); + return null; + } + public XComment createComment(String s) { + fail("MockNode.createCDATASection called?"); + return null; + } + public XDocumentFragment createDocumentFragment() { + fail("MockNode.createDocumentFragment called?"); + return null; + } + public XElement createElement(String n) { + fail("MockNode.createElement called?"); + return null; + } + public XElement createElementNS(String n, String q) { + fail("MockNode.createElementNS called?"); + return null; + } + public XEntityReference createEntityReference(String n) + throws DOMException { + fail("MockNode.createEntityReference called?"); + return null; + } + public XProcessingInstruction createProcessingInstruction(String t, + String d) throws DOMException { + fail("MockNode.createEntityReference called?"); + return null; + } + public XText createTextNode(String d) { + fail("MockNode.createTextNode called?"); + return null; + } + public XDocumentType getDoctype() { + fail("MockNode.getDoctype called?"); + return null; + } + public XElement getDocumentElement() { + fail("MockNode.getDocumentElement called?"); + return null; + } + public XElement getElementById(String id) { + fail("MockNode.getElementById called?"); + return null; + } + public XNodeList getElementsByTagName(String n) { + fail("MockNode.getElementsByTagName called?"); + return null; + } + public XNodeList getElementsByTagNameNS(String n, String q) { + fail("MockNode.getElementsByTagNameNS called?"); + return null; + } + public XDOMImplementation getImplementation() { + fail("MockNode.getImplementation called?"); + return null; + } + public XNode importNode(XNode i, boolean b) throws DOMException { + fail("MockNode.importNode called?"); + return null; + } + } + class MockNodeMap implements XNamedNodeMap + { + MockAttr[] m_attributes; + + MockNodeMap(MockAttr[] attrs) { m_attributes = attrs; } + + public int getLength() { return m_attributes.length; } + public XNode getNamedItem(String name) { + fail("MockNodeMap.getNamedItem not implemented"); + return null; + } + public XNode getNamedItemNS(String n, String l) { + fail("MockNodeMap.getNamedItemNS not implemented"); + return null; + } + public XNode item(int index) { + return m_attributes[index]; + } + public XNode removeNamedItem(String n) throws DOMException { + fail("MockNodeMap.removeNamedItem called?"); + return null; + } + public XNode removeNamedItemNS(String n, String l) throws DOMException { + fail("MockNodeMap.removeNamedItemNS called?"); + return null; + } + public XNode setNamedItem(XNode n) throws DOMException { + fail("MockNodeMap.setNamedItem called?"); + return null; + } + public XNode setNamedItemNS(XNode n) throws DOMException { + fail("MockNodeMap.setNamedItemNS called?"); + return null; + } + } + class MockElement extends MockNode implements XElement + { + MockAttr[] m_attributes; + + MockElement(String name, MockAttr[] attrs) { + m_localname = name; m_attributes = attrs; + } + + public NodeType getNodeType() { return ELEMENT_NODE; } + public XNamedNodeMap getAttributes() { + return new MockNodeMap(m_attributes); + } + public boolean hasAttributes() { return m_attributes.length != 0; } + + public String getAttribute(String n) { + fail("MockNode.getAttribute not implemented"); + return null; + } + public XAttr getAttributeNode(String n) { + fail("MockNode.getAttributeNode not implemented"); + return null; + } + public XAttr getAttributeNodeNS(String n, String l) { + fail("MockNode.getAttributeNodeNS not implemented"); + return null; + } + public String getAttributeNS(String n, String q) { + fail("MockNode.getAttributeNS not implemented"); + return null; + } + public XNodeList getElementsByTagName(String n) { + fail("MockNode.getElementsByTagName called?"); + return null; + } + public XNodeList getElementsByTagNameNS(String n, String l) { + fail("MockNode.getElementsByTagNameNS called?"); + return null; + } + public String getTagName() { + return getLocalName(); + } + public boolean hasAttribute(String n) { + fail("MockNode.hasAttribute not implemented"); + return false; + } + public boolean hasAttributeNS(String n, String l) { + fail("MockNode.hasAttributeNS not implemented"); + return false; + } + public void removeAttribute(String n) throws DOMException { + fail("MockNode.removeAttribute called?"); + } + public XAttr removeAttributeNode(XAttr o) throws DOMException { + fail("MockNode.removeAttributeNode called?"); + return null; + } + public void removeAttributeNS(String n, String l) throws DOMException { + fail("MockNode.removeAttributeNS called?"); + } + public void setAttribute(String n, String v) throws DOMException { + fail("MockNode.setAttribute called?"); + } + public XAttr setAttributeNode(XAttr n) throws DOMException { + fail("MockNode.setAttributeNode called?"); + return null; + } + public XAttr setAttributeNodeNS(XAttr n) throws DOMException { + fail("MockNode.setAttributeNodeNS called?"); + return null; + } + public void setAttributeNS(String n, String q, String v) + throws DOMException { + fail("MockNode.setAttributeNS called?"); + } + } + class MockAttr extends MockNode implements XAttr + { + String m_value; + + MockAttr(String name, String value) { + m_localname = name; m_value = value; + } + + public NodeType getNodeType() { return ATTRIBUTE_NODE; } + + public String getName() { return m_localname; } + public XElement getOwnerElement() { return (XElement) m_parent; } + public boolean getSpecified() { return true; } + public String getValue() { return m_value; } + public void setValue(String v) { + fail("MockNode.setValue called?"); + } + } +} + diff --git a/unoxml/qa/complex/unoxml/RDFRepositoryTest.java b/unoxml/qa/complex/unoxml/RDFRepositoryTest.java new file mode 100644 index 000000000000..7944a0edc064 --- /dev/null +++ b/unoxml/qa/complex/unoxml/RDFRepositoryTest.java @@ -0,0 +1,894 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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.unoxml; + +import helper.StreamSimulator; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiServiceFactory; +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.Pair; +import com.sun.star.beans.StringPair; +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.text.XTextRange; +import com.sun.star.text.XText; +import com.sun.star.rdf.*; +import lib.TestParameters; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openoffice.test.OfficeConnection; +import static org.junit.Assert.*; + +/** + * Test case for service com.sun.star.rdf.Repository + * Currently, this service is implemented in + * unoxml/source/rdf/librdf_repository.cxx + * + * @author mst + */ +public class RDFRepositoryTest +{ + XComponentContext xContext; + String tempDir; + + XDocumentRepository xRep; + XURI foo; + XURI bar; + XURI baz; + XURI uint; + XURI rdfslabel; + XURI manifest; + XURI uuid; + XURI base; + XBlankNode blank; + XLiteral lit; + XLiteral litlang; + XLiteral littype; + String rdfs = "http://www.w3.org/2000/01/rdf-schema#"; + + /** + * The test parameters + */ + private static TestParameters param = null; + +// public String[] getTestMethodNames () +// { +// return new String[] { "check", "checkSPARQL", "checkRDFa" }; +// } + + @Before public void before() + { + try { + XMultiServiceFactory xMSF = getMSF(); + param = new TestParameters(); + param.put("ServiceFactory", xMSF); + + assertNotNull("could not create MultiServiceFactory.", xMSF); + XPropertySet xPropertySet = UnoRuntime.queryInterface(XPropertySet.class, xMSF); + Object defaultCtx = xPropertySet.getPropertyValue("DefaultContext"); + xContext = UnoRuntime.queryInterface(XComponentContext.class, defaultCtx); + assertNotNull("could not get component context.", xContext); + + tempDir = util.utils.getOfficeTemp/*Dir*/(xMSF); + System.out.println("tempdir: " + tempDir); + + foo = URI.create(xContext, "uri:foo"); + assertNotNull("foo", foo); + bar = URI.create(xContext, "uri:bar"); + assertNotNull("bar", bar); + baz = URI.create(xContext, "uri:baz"); + assertNotNull("baz", baz); + uint = URI.create(xContext, "uri:int"); + assertNotNull("uint", uint); + blank = BlankNode.create(xContext, "_:uno"); + assertNotNull("blank", blank); + lit = Literal.create(xContext, "i am the literal"); + assertNotNull("lit", lit); + litlang = Literal.createWithLanguage(xContext, + "i am the literal", "en"); + assertNotNull("litlang", litlang); + littype = Literal.createWithType(xContext, "42", uint); + assertNotNull("littype", littype); + + rdfslabel = URI.create(xContext, rdfs + "label"); + assertNotNull("rdfslabel", rdfslabel); + manifest = URI.create(xContext, "manifest:manifest"); //FIXME + assertNotNull("manifest", manifest); + uuid = URI.create(xContext, + "urn:uuid:224ab023-77b8-4396-a75a-8cecd85b81e3"); + assertNotNull("uuid", uuid); + base = URI.create(xContext, "base-uri:"); //FIXME + assertNotNull("base", base); + } catch (Exception e) { + report(e); + } + //FIXME: ? +// xRep = Repository.create(xContext); + System.out.println("Creating service Repository..."); + xRep = UnoRuntime.queryInterface(XDocumentRepository.class, Repository.create(xContext)); + assertNotNull("null", xRep); + System.out.println("...done"); + } + + @After public void after() + { + xRep = null; + } + + @Test public void check() + { + try { + System.out.println("Checking that new repository is really empty..."); + assertTrue("empty: graphs", 0 == xRep.getGraphNames().length); + + XEnumeration stmts; + stmts = xRep.getStatements(null, null, null); + assertTrue("empty: stmts", !stmts.hasMoreElements()); + + System.out.println("...done"); + + System.out.println("Checking graph creation..."); + + XNamedGraph xFooGraph = xRep.createGraph(foo); + assertNotNull("foo graph", xFooGraph); + + try { + xRep.createGraph(foo); + fail("creating duplicate graph was allowed"); + } catch (ElementExistException e) { + // ignore + } + + try { + xRep.createGraph(null); + fail("invalid graph name was allowed"); + } catch (IllegalArgumentException e) { + // ignore + } + + XURI[] names = xRep.getGraphNames(); + assertTrue("no foo graph in getGraphNames", + 1 == names.length && eq(names[0], foo)); + assertNotNull("no foo graph", xRep.getGraph(foo)); + + stmts = xFooGraph.getStatements(null, null, null); + assertTrue("stmts in foo graph", !stmts.hasMoreElements()); + + XOutputStream xFooOut = + new StreamSimulator(tempDir + "empty.rdf", false, param); + xRep.exportGraph(FileFormat.RDF_XML, xFooOut, foo, base); + xFooOut.closeOutput(); + + XInputStream xFooIn = + new StreamSimulator(tempDir + "empty.rdf", true, param); + xRep.importGraph(FileFormat.RDF_XML, xFooIn, bar, base); + assertNotNull("no bar graph", xRep.getGraph(bar)); + + System.out.println("...done"); + + System.out.println("Checking graph manipulation..."); + + XEnumeration xFooEnum; + + Statement xFoo_FooBarBaz = new Statement(foo, bar, baz, foo); + xFooGraph.addStatement(foo, bar, baz); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("addStatement(foo,bar,baz)", + eq(xFooEnum, new Statement[] { xFoo_FooBarBaz })); + + Statement xFoo_FooBarBlank = new Statement(foo, bar, blank, foo); + xFooGraph.addStatement(foo, bar, blank); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("addStatement(foo,bar,blank)", + eq(xFooEnum, + new Statement[] { xFoo_FooBarBaz, xFoo_FooBarBlank })); + xFooEnum = xRep.getStatements(null, null, null); + assertTrue("addStatement(foo,bar,blank) (global)", + eq(xFooEnum, + new Statement[] { xFoo_FooBarBaz, xFoo_FooBarBlank })); + + Statement xFoo_BazBarLit = new Statement(baz, bar, lit, foo); + xFooGraph.addStatement(baz, bar, lit); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("addStatement(baz,bar,lit)", + eq(xFooEnum, new Statement[] { + xFoo_FooBarBaz, xFoo_FooBarBlank, xFoo_BazBarLit })); + xFooEnum = xFooGraph.getStatements(baz, bar, null); + assertTrue("addStatement(baz,bar,lit) (baz,bar)", + eq(xFooEnum, new Statement[] { xFoo_BazBarLit })); + + Statement xFoo_BazBarLitlang = + new Statement(baz, bar, litlang, foo); + xFooGraph.addStatement(baz, bar, litlang); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("addStatement(baz,bar,litlang)", + eq(xFooEnum, new Statement[] { + xFoo_FooBarBaz, xFoo_FooBarBlank, xFoo_BazBarLit, + xFoo_BazBarLitlang })); + xFooEnum = xFooGraph.getStatements(null, null, baz); + assertTrue("addStatement(baz,bar,litlang) (baz)", + eq(xFooEnum, new Statement[] { xFoo_FooBarBaz })); + + Statement xFoo_BazBarLittype = + new Statement(baz, bar, littype, foo); + xFooGraph.addStatement(baz, bar, littype); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("addStatement(baz,bar,littype)", + eq(xFooEnum, new Statement[] { xFoo_FooBarBaz, xFoo_FooBarBlank, + xFoo_BazBarLit, xFoo_BazBarLitlang, xFoo_BazBarLittype })); + + xFooGraph.removeStatements(baz, bar, litlang); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("removeStatement(baz,bar,litlang)", + eq(xFooEnum, new Statement[] { xFoo_FooBarBaz, xFoo_FooBarBlank, + xFoo_BazBarLit, xFoo_BazBarLittype })); + + xFooGraph.removeStatements(foo, bar, null); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("removeStatement(foo,bar,null)", + eq(xFooEnum, new Statement[] { + xFoo_BazBarLit, xFoo_BazBarLittype })); + + xFooGraph.addStatement(foo, bar, baz); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("addStatement(foo,bar,baz) (re-add)", + eq(xFooEnum, new Statement[] { xFoo_FooBarBaz, + xFoo_BazBarLit, xFoo_BazBarLittype })); + + xFooGraph.addStatement(foo, bar, baz); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("addStatement(foo,bar,baz) (duplicate)", + eq(xFooEnum, new Statement[] { xFoo_FooBarBaz, + xFoo_BazBarLit, xFoo_BazBarLittype })); + + xFooGraph.addStatement(xFooGraph, bar, baz); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("addStatement(foo,bar,baz) (triplicate, as graph)", + eq(xFooEnum, new Statement[] { xFoo_FooBarBaz, + xFoo_BazBarLit, xFoo_BazBarLittype })); + + System.out.println("...done"); + + System.out.println("Checking graph import/export..."); + + xFooOut = new StreamSimulator(tempDir + "foo.rdf", false, param); + xRep.exportGraph(FileFormat.RDF_XML, xFooOut, foo, base); + xFooOut.closeOutput(); + + xFooIn = new StreamSimulator(tempDir + "foo.rdf", true, param); + try { + xRep.importGraph(FileFormat.RDF_XML, xFooIn, bar, base); + fail("importing existing graph did not fail"); + } catch (ElementExistException e) { + // ignore + } + + xFooIn = new StreamSimulator(tempDir + "foo.rdf", true, param); + xRep.importGraph(FileFormat.RDF_XML, xFooIn, baz, base); + XNamedGraph xBazGraph = xRep.getGraph(baz); + assertNotNull("no baz graph", xBazGraph); + + Statement xBaz_FooBarBaz = new Statement(foo, bar, baz, baz); + Statement xBaz_BazBarLit = new Statement(baz, bar, lit, baz); + Statement xBaz_BazBarLittype = + new Statement(baz, bar, littype, baz); + XEnumeration xBazEnum = xBazGraph.getStatements(null, null, null); + assertTrue("importing exported graph", + eq(xBazEnum, new Statement[] { + xBaz_FooBarBaz, xBaz_BazBarLit, xBaz_BazBarLittype })); + + System.out.println("...done"); + + System.out.println("Checking graph deletion..."); + + xFooGraph.clear(); + xFooEnum = xFooGraph.getStatements(null, null, null); + assertTrue("clear", eq(xFooEnum, new Statement[] { })); + + xRep.destroyGraph(baz); + assertNull("baz graph zombie", xRep.getGraph(baz)); + + try { + xBazGraph.clear(); + fail("deleted graph not invalid (clear)"); + } catch (NoSuchElementException e) { + // ignore + } + + try { + xBazGraph.addStatement(foo, foo, foo); + fail("deleted graph not invalid (add)"); + } catch (NoSuchElementException e) { + // ignore + } + + try { + xBazGraph.removeStatements(null, null, null); + fail("deleted graph not invalid (remove)"); + } catch (NoSuchElementException e) { + // ignore + } + + try { + xBazGraph.getStatements(null, null, null); + fail("deleted graph not invalid (get)"); + } catch (NoSuchElementException e) { + // ignore + } + + System.out.println("...done"); + + } catch (Exception e) { + report(e); + } + } + + @Test + public void checkSPARQL() + { + try { + + System.out.println("Checking SPARQL queries..."); + + XInputStream xIn = new StreamSimulator(TestDocument.getUrl("example.rdf"), true, param); + // util.utils.getFullTestDocName("example.rdf"), true, param); + xRep.importGraph(FileFormat.RDF_XML, xIn, manifest, base); + + String query; + query = "SELECT ?p WHERE { ?p rdf:type pkg:Package . }"; + XQuerySelectResult result = xRep.querySelect(mkNss() + query); + assertTrue("query: package-id\n" + query, + eq(result, new String[] { "p" }, + new XNode[][] { { uuid } })); + + query = "SELECT ?part ?path FROM <" + manifest + + "> WHERE { ?pkg rdf:type pkg:Package . ?pkg pkg:hasPart ?part ." + + " ?part pkg:path ?path . ?part rdf:type odf:ContentFile. }"; + result = xRep.querySelect(mkNss() + query); + assertTrue("query: contentfile", + eq(result, new String[] { "part", "path" }, + new XNode[][] { { BlankNode.create(xContext, "whatever"), + Literal.create(xContext, "content.xml") } })); + + query = "SELECT ?pkg ?path FROM <" + toS(manifest) + "> WHERE { " + + "?pkg rdf:type pkg:Package . ?pkg pkg:hasPart ?part . " + + "?part pkg:path ?path . ?part rdf:type odf:ContentFile. }"; + result = xRep.querySelect(mkNss() + query); + assertTrue("query: contentfile\n" + query, + eq(result, new String[] { "pkg", "path" }, + new XNode[][] { { uuid , + Literal.create(xContext, "content.xml") } })); + + query = "SELECT ?part ?path FROM <" + toS(manifest) + "> WHERE { " + + "?pkg rdf:type pkg:Package . ?pkg pkg:hasPart ?part . " + + "?part pkg:path ?path . ?part rdf:type odf:StylesFile. }"; + result = xRep.querySelect(mkNss() + query); + assertTrue("query: stylesfile\n" + query, + eq(result, new String[] { "part", "path" }, + new XNode[][] { })); + + query = "SELECT ?part ?path FROM <" + toS(manifest) + "> WHERE { " + + "?pkg rdf:type pkg:Package . ?pkg pkg:hasPart ?part . " + + "?part pkg:path ?path . ?part rdf:type odf:MetadataFile. }"; + result = xRep.querySelect(mkNss() + query); + assertTrue("query: metadatafile\n" + query, + eq(result, new String[] { "part", "path" }, + new XNode[][] { { + URI.create(xContext, "http://hospital-employee/doctor"), + Literal.create(xContext, + "meta/hospital/doctor.rdf") } })); + +//FIXME redland BUG + String uri = "uri:example-element-2"; + query = "SELECT ?path ?idref FROM <" + toS(manifest) + "> WHERE { " +// + "<" + toS(uuid) + "> rdf:type pkg:Package ; " +// + " pkg:hasPart ?part . " + + "<" + toS(uuid) + "> pkg:hasPart ?part . " + + "?part pkg:path ?path ; " + + " rdf:type ?type ; " + + " pkg:hasPart <" + uri + "> . " +// + "<" + uri + "> rdf:type odf:Element ; " + + "<" + uri + "> " + + " pkg:idref ?idref . " + + " FILTER (?type = odf:ContentFile || ?type = odf:StylesFile)" + + " }"; +//System.out.println(query); + result = xRep.querySelect(mkNss() + query); + assertTrue("query: example-element-2\n" + query, + eq(result, new String[] { "path", "idref" }, + new XNode[][] { { + Literal.create(xContext, "content.xml"), + Literal.create(xContext, "ID_B") } })); + + // CONSTRUCT result triples have no graph! + Statement x_PkgFooLit = new Statement(uuid, foo, lit, null); + query = "CONSTRUCT { ?pkg <" + toS(foo) + "> \"" + + lit.getStringValue() + "\" } FROM <" + toS(manifest) + + "> WHERE { ?pkg rdf:type pkg:Package . } "; + XEnumeration xResultEnum = xRep.queryConstruct(mkNss() + query); + assertTrue("query: construct\n" + query, + eq(xResultEnum, new Statement[] { x_PkgFooLit })); + + query = "ASK { ?pkg rdf:type pkg:Package . }"; + boolean bResult = xRep.queryAsk(mkNss() + query); + assertTrue("query: ask\n" + query, bResult); + + System.out.println("...done"); + + } catch (Exception e) { + report(e); + } + } + + @Test public void checkRDFa() + { + try { + System.out.println("Checking RDFa gunk..."); + + String content = "behold, for i am the content."; + XTextRange xTR = new TestRange(content); + XMetadatable xM = (XMetadatable) xTR; + + Pair<Statement[], Boolean> result = + xRep.getStatementRDFa((XMetadatable)xTR); + assertTrue("RDFa: get: not empty (initial)", + 0 == result.First.length); + + try { + xRep.setStatementRDFa(foo, new XURI[] {}, xM, "", null); + fail("RDFa: set: no predicate"); + } catch (IllegalArgumentException e) { + // ignore + } + + try { + xRep.setStatementRDFa(foo, new XURI[] {bar}, null, "", null); + fail("RDFa: set: null"); + } catch (IllegalArgumentException e) { + // ignore + } + + XLiteral trlit = Literal.create(xContext, content); + Statement x_FooBarTRLit = new Statement(foo, bar, trlit, null); + xRep.setStatementRDFa(foo, new XURI[] { bar }, xM, "", null); + + result = xRep.getStatementRDFa((XMetadatable)xTR); + assertTrue("RDFa: get: without content", + !result.Second && (1 == result.First.length) + && eq(result.First[0], x_FooBarTRLit)); + + //FIXME: do this? + xTR.setString(lit.getStringValue()); +/* + Statement xFooBarLit = new Statement(foo, bar, lit, null); + result = xRep.getStatementRDFa((XMetadatable)xTR); + assertTrue("RDFa: get: change", + eq((Statement)result.First, xFooBarLit) && null == result.Second); +*/ + + Statement x_FooBarLittype = new Statement(foo, bar, littype, null); + xRep.setStatementRDFa(foo, new XURI[] { bar }, xM, "42", uint); + + result = xRep.getStatementRDFa((XMetadatable)xTR); + assertTrue("RDFa: get: with content", + result.Second && + (1 == result.First.length) && + eq(result.First[0], x_FooBarLittype)); + + //FIXME: do this? + xTR.setString(content); +/* + Statement xFooLabelTRLit = new Statement(foo, rdfslabel, trlit, null); + result = xRep.getStatementRDFa((XMetadatable)xTR); + assertTrue("RDFa: get: change (label)", + eq((Statement)result.First, xFooBarLittype) && + eq((Statement)result.Second, xFooLabelTRLit)); +*/ + + xRep.removeStatementRDFa((XMetadatable)xTR); + + result = xRep.getStatementRDFa((XMetadatable)xTR); + assertTrue("RDFa: get: not empty (removed)", + 0 == result.First.length); + + xRep.setStatementRDFa(foo, new XURI[] { foo, bar, baz }, xM, + "", null); + + Statement x_FooFooTRLit = new Statement(foo, foo, trlit, null); + Statement x_FooBazTRLit = new Statement(foo, baz, trlit, null); + result = xRep.getStatementRDFa((XMetadatable) xTR); + assertTrue("RDFa: get: without content (multiple predicates, reinsert)", + !result.Second && + eq(result.First, new Statement[] { + x_FooFooTRLit, x_FooBarTRLit, x_FooBazTRLit })); + + xRep.removeStatementRDFa((XMetadatable)xTR); + + result = xRep.getStatementRDFa((XMetadatable) xTR); + assertTrue("RDFa: get: not empty (re-removed)", + 0 == result.First.length); + + System.out.println("...done"); + + } catch (Exception e) { + report(e); + } + } + +// utilities ------------------------------------------------------------- + + public void report2(Exception e) + { + if (e instanceof WrappedTargetException) + { + System.out.println("Cause:"); + Exception cause = (Exception) + (((WrappedTargetException)e).TargetException); + System.out.println(cause.toString()); + report2(cause); + } else if (e instanceof WrappedTargetRuntimeException) { + System.out.println("Cause:"); + Exception cause = (Exception) + (((WrappedTargetRuntimeException)e).TargetException); + System.out.println(cause.toString()); + report2(cause); + } + } + + public void report(Exception e) { + System.out.println("Exception occurred:"); + e.printStackTrace(); + report2(e); + fail(); + } + + public static String toS(XNode n) { + if (null == n) + { + return "< null >"; + } + return n.getStringValue(); + } + + static boolean isBlank(XNode i_node) + { + XBlankNode blank = 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(); +//System.out.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)) { + System.out.println("Graphs differ: " + toS(lG) + " != " + toS(rG)); + return false; + } + if (!eq(i_Left.Subject, i_Right.Subject)) { + System.out.println("Subjects differ: " + + i_Left.Subject.getStringValue() + " != " + + i_Right.Subject.getStringValue()); + return false; + } + if (!eq(i_Left.Predicate, i_Right.Predicate)) { + System.out.println("Predicates differ: " + + i_Left.Predicate.getStringValue() + " != " + + i_Right.Predicate.getStringValue()); + return false; + } + if (!eq(i_Left.Object, i_Right.Object)) { + System.out.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) { + System.out.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) { + System.out.println("var lengths differ"); + return false; + } + if (bindings.length != i_Bindings.length) { + System.out.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) { + System.out.println("TEST ERROR!"); + throw new Exception(); + } + if (bindings[i].length != i_Vars.length) { + System.out.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])) { + System.out.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])) { + System.out.println("variable names differ: " + + vars[i] + " != " + i_Vars[i]); + return false; + } + } + return true; + } + + 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; + } + + 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 = i_Ref.First; m_XmlId = 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; } + } + + private XMultiServiceFactory getMSF() + { + final XMultiServiceFactory xMSF1 = UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager()); + return xMSF1; + } + + // setup and close connections + @BeforeClass public static void setUpConnection() throws Exception { + System.out.println("setUpConnection()"); + connection.setUp(); + } + + @AfterClass public static void tearDownConnection() + throws InterruptedException, com.sun.star.uno.Exception + { + System.out.println("tearDownConnection()"); + connection.tearDown(); + } + + private static final OfficeConnection connection = new OfficeConnection(); +} + diff --git a/unoxml/qa/complex/unoxml/TestDocument.java b/unoxml/qa/complex/unoxml/TestDocument.java new file mode 100644 index 000000000000..d64431f21741 --- /dev/null +++ b/unoxml/qa/complex/unoxml/TestDocument.java @@ -0,0 +1,40 @@ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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.unoxml; + +import java.io.File; +import org.openoffice.test.OfficeFileUrl; +import org.openoffice.test.Argument; + +final class TestDocument { + public static String getUrl(String name) { + return OfficeFileUrl.getAbsolute(new File(Argument.get("tdoc"), name)); + } + + private TestDocument() {} +} diff --git a/unoxml/qa/complex/unoxml/testdocuments/example.rdf b/unoxml/qa/complex/unoxml/testdocuments/example.rdf new file mode 100644 index 000000000000..07ef7f07b6fd --- /dev/null +++ b/unoxml/qa/complex/unoxml/testdocuments/example.rdf @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<rdf:RDF + xmlns:pkg="http://docs.oasis-open.org/opendocument/meta/package/common#" + xmlns:odf="http://docs.oasis-open.org/opendocument/meta/package/odf#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> +<pkg:Package rdf:about="urn:uuid:224ab023-77b8-4396-a75a-8cecd85b81e3"> + <pkg:hasPart> + <odf:ContentFile pkg:path="content.xml"> + <pkg:hasPart> + <odf:Element rdf:about="uri:example-element-1" + pkg:idref="ID_A"/> + </pkg:hasPart> + <pkg:hasPart> + <odf:Element rdf:about="uri:example-element-2" + pkg:idref="ID_B"/> + </pkg:hasPart> + </odf:ContentFile> + </pkg:hasPart> + <pkg:hasPart> + <odf:MetadataFile rdf:about="http://hospital-employee/doctor" + pkg:path="meta/hospital/doctor.rdf"> + <rdf:type rdf:resource="http://medical-employee/data"/> + <rdf:type rdf:resource="http://www.w3.org/2006/vcard/ns#"/> + </odf:MetadataFile> + </pkg:hasPart> +</pkg:Package> +</rdf:RDF> diff --git a/unoxml/source/dom/attr.cxx b/unoxml/source/dom/attr.cxx new file mode 100644 index 000000000000..ddfbe21fdf2f --- /dev/null +++ b/unoxml/source/dom/attr.cxx @@ -0,0 +1,274 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <attr.hxx> + +#include <string.h> + +#include <boost/shared_ptr.hpp> + +#include <com/sun/star/xml/dom/DOMException.hdl> +#include <com/sun/star/xml/dom/events/XMutationEvent.hpp> + +#include <document.hxx> + + +namespace DOM +{ + CAttr::CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlAttrPtr const pAttr) + : CAttr_Base(rDocument, rMutex, + NodeType_ATTRIBUTE_NODE, reinterpret_cast<xmlNodePtr>(pAttr)) + , m_aAttrPtr(pAttr) + { + } + + xmlNsPtr CAttr::GetNamespace(xmlNodePtr const pNode) + { + if (!m_pNamespace.get()) { + return 0; + } + xmlChar const*const pUri(reinterpret_cast<xmlChar const*>( + m_pNamespace->first.getStr())); + xmlChar const*const pPrefix(reinterpret_cast<xmlChar const*>( + m_pNamespace->second.getStr())); + xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, pPrefix); + if (pNs && (0 != xmlStrcmp(pNs->href, pUri))) { + return pNs; + } + pNs = xmlNewNs(pNode, pUri, pPrefix); + if (pNs) { + return pNs; + } + pNs = xmlSearchNsByHref(pNode->doc, pNode, pUri); + // if (!pNs) hmm... now what? throw? + if (!pNs) { OSL_TRACE("CAtttr: cannot create namespace"); } + return pNs; + } + + bool CAttr::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_TEXT_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } + } + + OUString SAL_CALL CAttr::getNodeName() + throw (RuntimeException) + { + return getName(); + } + OUString SAL_CALL CAttr::getNodeValue() + throw (RuntimeException) + { + return getValue(); + } + OUString SAL_CALL CAttr::getLocalName() + throw (RuntimeException) + { + return getName(); + } + + + /** + Returns the name of this attribute. + */ + OUString SAL_CALL CAttr::getName() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return ::rtl::OUString(); + } + OUString const aName((char*)m_aAttrPtr->name, + strlen((char*)m_aAttrPtr->name), RTL_TEXTENCODING_UTF8); + return aName; + } + + /** + The Element node this attribute is attached to or null if this + attribute is not in use. + */ + Reference< XElement > SAL_CALL CAttr::getOwnerElement() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return 0; + } + if (0 == m_aAttrPtr->parent) { + return 0; + } + Reference< XElement > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + m_aAttrPtr->parent).get()), + UNO_QUERY_THROW); + return xRet; + } + + /** + If this attribute was explicitly given a value in the original + document, this is true; otherwise, it is false. + */ + sal_Bool SAL_CALL CAttr::getSpecified() + throw (RuntimeException) + { + // FIXME if this DOM implemenatation supported DTDs it would need + // to check that this attribute is not default or something + return sal_True; + } + + /** + On retrieval, the value of the attribute is returned as a string. + */ + OUString SAL_CALL CAttr::getValue() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return ::rtl::OUString(); + } + if (0 == m_aAttrPtr->children) { + return ::rtl::OUString(); + } + char const*const pContent((m_aAttrPtr->children) + ? reinterpret_cast<char const*>(m_aAttrPtr->children->content) + : ""); + OUString const ret(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8); + return ret; + } + + /** + Sets the value of the attribute from a string. + */ + void SAL_CALL CAttr::setValue(const OUString& value) + throw (RuntimeException, DOMException) + { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return; + } + + // remember old value (for mutation event) + OUString sOldValue = getValue(); + + OString o1 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); + xmlChar* xValue = (xmlChar*)o1.getStr(); + // xmlChar* xName = OUStringToOString(m_aAttrPtr->name, RTL_TEXTENCODING_UTF8).getStr(); + // this does not work if the attribute was created anew + // xmlNodePtr pNode = m_aAttrPtr->parent; + // xmlSetProp(pNode, m_aAttrPtr->name, xValue); + ::boost::shared_ptr<xmlChar const> const buffer( + xmlEncodeEntitiesReentrant(m_aAttrPtr->doc, xValue), xmlFree); + xmlFreeNodeList(m_aAttrPtr->children); + m_aAttrPtr->children = + xmlStringGetNodeList(m_aAttrPtr->doc, buffer.get()); + xmlNodePtr tmp = m_aAttrPtr->children; + while (tmp != NULL) { + tmp->parent = (xmlNodePtr) m_aNodePtr; + tmp->doc = m_aAttrPtr->doc; + if (tmp->next == NULL) + m_aNodePtr->last = tmp; + tmp = tmp->next; + } + + // dispatch DOM events to signal change in attribute value + // dispatch DomAttrModified + DOMSubtreeModified + OUString sEventName( RTL_CONSTASCII_USTRINGPARAM("DOMAttrModified") ); + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent(sEventName),UNO_QUERY); + event->initMutationEvent( + sEventName, sal_True, sal_False, + Reference<XNode>( static_cast<XAttr*>( this ) ), + sOldValue, value, getName(), AttrChangeType_MODIFICATION ); + + guard.clear(); // release mutex before calling event handlers + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); + } + + void SAL_CALL CAttr::setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return; } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + m_pNamespace->second = + OUStringToOString(prefix, RTL_TEXTENCODING_UTF8); + } else { + CNode::setPrefix(prefix); + } + } + + OUString SAL_CALL CAttr::getPrefix() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return ::rtl::OUString(); } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + OUString const ret(::rtl::OStringToOUString( + m_pNamespace->second, RTL_TEXTENCODING_UTF8)); + return ret; + } else { + return CNode::getPrefix(); + } + } + + OUString SAL_CALL CAttr::getNamespaceURI() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return ::rtl::OUString(); } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + OUString const ret(::rtl::OStringToOUString( + m_pNamespace->first, RTL_TEXTENCODING_UTF8)); + return ret; + } else { + return CNode::getNamespaceURI(); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/attr.hxx b/unoxml/source/dom/attr.hxx new file mode 100644 index 000000000000..9a712ccf715b --- /dev/null +++ b/unoxml/source/dom/attr.hxx @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_ATTR_HXX +#define DOM_ATTR_HXX + +#include <memory> + +#include <libxml/tree.h> + +#include <cppuhelper/implbase1.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XAttr.hpp> + +#include <node.hxx> + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::std::pair< ::rtl::OString, ::rtl::OString > stringpair_t; + + typedef ::cppu::ImplInheritanceHelper1< CNode, XAttr > CAttr_Base; + + class CAttr + : public CAttr_Base + { + private: + friend class CDocument; + + private: + xmlAttrPtr m_aAttrPtr; + ::std::auto_ptr< stringpair_t > m_pNamespace; + + protected: + CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlAttrPtr const pAttr); + + public: + /// return the libxml namespace corresponding to m_pNamespace on pNode + xmlNsPtr GetNamespace(xmlNodePtr const pNode); + + virtual bool IsChildTypeAllowed(NodeType const nodeType); + + /** + Returns the name of this attribute. + */ + virtual OUString SAL_CALL getName() throw (RuntimeException); + + /** + The Element node this attribute is attached to or null if this + attribute is not in use. + */ + virtual Reference< XElement > SAL_CALL getOwnerElement() throw (RuntimeException); + + /** + If this attribute was explicitly given a value in the original + document, this is true; otherwise, it is false. + */ + virtual sal_Bool SAL_CALL getSpecified()throw (RuntimeException); + + /** + On retrieval, the value of the attribute is returned as a string. + */ + virtual OUString SAL_CALL getValue() throw (RuntimeException); + + /** + Sets the value of the attribute from a string. + */ + + virtual void SAL_CALL setValue(const OUString& value) throw (RuntimeException, DOMException); + + // resolve uno inheritance problems... + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException); + + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return setValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException); + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/attributesmap.cxx b/unoxml/source/dom/attributesmap.cxx new file mode 100644 index 000000000000..539320df62b9 --- /dev/null +++ b/unoxml/source/dom/attributesmap.cxx @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <attributesmap.hxx> + +#include <string.h> + +#include <element.hxx> +#include <document.hxx> + + +namespace DOM +{ + CAttributesMap::CAttributesMap(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex) + : m_pElement(pElement) + , m_rMutex(rMutex) + { + } + + /** + The number of nodes in this map. + */ + sal_Int32 SAL_CALL CAttributesMap::getLength() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + sal_Int32 count = 0; + xmlNodePtr pNode = m_pElement->GetNodePtr(); + if (pNode != NULL) + { + xmlAttrPtr cur = pNode->properties; + while (cur != NULL) + { + count++; + cur = cur->next; + } + } + return count; + } + + /** + Retrieves a node specified by local name + */ + Reference< XNode > SAL_CALL + CAttributesMap::getNamedItem(OUString const& name) throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNode > aNode; + xmlNodePtr pNode = m_pElement->GetNodePtr(); + if (pNode != NULL) + { + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar* xName = (xmlChar*)o1.getStr(); + xmlAttrPtr cur = pNode->properties; + while (cur != NULL) + { + if( strcmp((char*)xName, (char*)cur->name) == 0) + { + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); + break; + } + cur = cur->next; + } + } + return aNode; + } + + /** + Retrieves a node specified by local name and namespace URI. + */ + Reference< XNode > SAL_CALL + CAttributesMap::getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNode > aNode; + xmlNodePtr pNode = m_pElement->GetNodePtr(); + if (pNode != NULL) + { + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar* xName = (xmlChar*)o1.getStr(); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar const*const xNs = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlNsPtr const pNs = xmlSearchNsByHref(pNode->doc, pNode, xNs); + xmlAttrPtr cur = pNode->properties; + while (cur != NULL && pNs != NULL) + { + if( strcmp((char*)xName, (char*)cur->name) == 0 && + cur->ns == pNs) + { + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); + break; + } + cur = cur->next; + } + } + return aNode; + } + + /** + Returns the indexth item in the map. + */ + Reference< XNode > SAL_CALL + CAttributesMap::item(sal_Int32 index) throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNode > aNode; + xmlNodePtr pNode = m_pElement->GetNodePtr(); + if (pNode != NULL) + { + xmlAttrPtr cur = pNode->properties; + sal_Int32 count = 0; + while (cur != NULL) + { + if (count == index) + { + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); + break; + } + count++; + cur = cur->next; + } + } + return aNode; + } + + /** + Removes a node specified by name. + */ + Reference< XNode > SAL_CALL + CAttributesMap::removeNamedItem(OUString const& name) + throw (RuntimeException) + { + // no MutexGuard needed: m_pElement is const + Reference< XAttr > const xAttr(m_pElement->getAttributeNode(name)); + if (!xAttr.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::removeNamedItem: no such attribute")), + static_cast<OWeakObject*>(this), + DOMExceptionType_NOT_FOUND_ERR); + } + Reference< XNode > const xRet( + m_pElement->removeAttributeNode(xAttr), UNO_QUERY); + return xRet; + } + + /** + // Removes a node specified by local name and namespace URI. + */ + Reference< XNode > SAL_CALL + CAttributesMap::removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException) + { + // no MutexGuard needed: m_pElement is const + Reference< XAttr > const xAttr( + m_pElement->getAttributeNodeNS(namespaceURI, localName)); + if (!xAttr.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::removeNamedItemNS: no such attribute")), + static_cast<OWeakObject*>(this), + DOMExceptionType_NOT_FOUND_ERR); + } + Reference< XNode > const xRet( + m_pElement->removeAttributeNode(xAttr), UNO_QUERY); + return xRet; + } + + /** + // Adds a node using its nodeName attribute. + */ + Reference< XNode > SAL_CALL + CAttributesMap::setNamedItem(Reference< XNode > const& xNode) + throw (RuntimeException) + { + Reference< XAttr > const xAttr(xNode, UNO_QUERY); + if (!xNode.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::setNamedItem: XAttr argument expected")), + static_cast<OWeakObject*>(this), + DOMExceptionType_HIERARCHY_REQUEST_ERR); + } + // no MutexGuard needed: m_pElement is const + Reference< XNode > const xRet( + m_pElement->setAttributeNode(xAttr), UNO_QUERY); + return xRet; + } + + /** + Adds a node using its namespaceURI and localName. + */ + Reference< XNode > SAL_CALL + CAttributesMap::setNamedItemNS(Reference< XNode > const& xNode) + throw (RuntimeException) + { + Reference< XAttr > const xAttr(xNode, UNO_QUERY); + if (!xNode.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::setNamedItemNS: XAttr argument expected")), + static_cast<OWeakObject*>(this), + DOMExceptionType_HIERARCHY_REQUEST_ERR); + } + // no MutexGuard needed: m_pElement is const + Reference< XNode > const xRet( + m_pElement->setAttributeNodeNS(xAttr), UNO_QUERY); + return xRet; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/attributesmap.hxx b/unoxml/source/dom/attributesmap.hxx new file mode 100644 index 000000000000..bb2cd6aa0a56 --- /dev/null +++ b/unoxml/source/dom/attributesmap.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_ATTRIBUTESMAP_HXX +#define DOM_ATTRIBUTESMAP_HXX + +#include <sal/types.h> +#include <rtl/ref.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNamedNodeMap.hpp> + +#include <cppuhelper/implbase1.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + class CElement; + + class CAttributesMap + : public cppu::WeakImplHelper1< XNamedNodeMap > + { + private: + ::rtl::Reference<CElement> const m_pElement; + ::osl::Mutex & m_rMutex; + + public: + CAttributesMap(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex); + + /** + The number of nodes in this map. + */ + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); + + /** + Retrieves a node specified by local name + */ + virtual Reference< XNode > SAL_CALL getNamedItem(OUString const& name) + throw (RuntimeException); + + /** + Retrieves a node specified by local name and namespace URI. + */ + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); + + /** + Returns the indexth item in the map. + */ + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); + + /** + Removes a node specified by name. + */ + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) + throw (RuntimeException); + + /** + // Removes a node specified by local name and namespace URI. + */ + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); + + /** + // Adds a node using its nodeName attribute. + */ + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); + + /** + Adds a node using its namespaceURI and localName. + */ + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/cdatasection.cxx b/unoxml/source/dom/cdatasection.cxx new file mode 100644 index 000000000000..41637696f96a --- /dev/null +++ b/unoxml/source/dom/cdatasection.cxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cdatasection.hxx> + +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + +namespace DOM +{ + CCDATASection::CCDATASection( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CCDATASection_Base(rDocument, rMutex, + NodeType_CDATA_SECTION_NODE, pNode) + { + } + + void CCDATASection::saxify(const Reference< XDocumentHandler >& i_xHandler) + { + if (!i_xHandler.is()) throw RuntimeException(); + Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); + if (xExtended.is()) { + xExtended->startCDATA(); + i_xHandler->characters(getData()); + xExtended->endCDATA(); + } + } + + OUString SAL_CALL CCDATASection::getNodeName()throw (RuntimeException) + { + return OUString(RTL_CONSTASCII_USTRINGPARAM("#cdata-section")); + } + + OUString SAL_CALL CCDATASection::getNodeValue() throw (RuntimeException) + { + return CCharacterData::getData(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/cdatasection.hxx b/unoxml/source/dom/cdatasection.hxx new file mode 100644 index 000000000000..2eb0afc194ac --- /dev/null +++ b/unoxml/source/dom/cdatasection.hxx @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_CDATASECTION_HXX +#define DOM_CDATASECTION_HXX + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XCDATASection.hpp> + +#include <text.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CText, XCDATASection > + CCDATASection_Base; + + class CCDATASection + : public CCDATASection_Base + { + friend class CDocument; + + protected: + CCDATASection(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); + + public: + + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + virtual Reference< XText > SAL_CALL splitText(sal_Int32 offset) + throw (RuntimeException) + { + return CText::splitText(offset); + } + + // --- delegations for XCharacterData + virtual void SAL_CALL appendData(const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::appendData(arg); + } + virtual void SAL_CALL deleteData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException) + { + CCharacterData::deleteData(offset, count); + } + virtual OUString SAL_CALL getData() throw (RuntimeException) + { + return CCharacterData::getData(); + } + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException) + { + return CCharacterData::getLength(); + } + virtual void SAL_CALL insertData(sal_Int32 offset, const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::insertData(offset, arg); + } + virtual void SAL_CALL replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::replaceData(offset, count, arg); + } + virtual void SAL_CALL setData(const OUString& data) + throw (RuntimeException, DOMException) + { + CCharacterData::setData(data); + } + virtual OUString SAL_CALL subStringData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException) + { + return CCharacterData::subStringData(offset, count); + } + + + // --- overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CText::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/characterdata.cxx b/unoxml/source/dom/characterdata.cxx new file mode 100644 index 000000000000..39bdc788ddae --- /dev/null +++ b/unoxml/source/dom/characterdata.cxx @@ -0,0 +1,272 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <characterdata.hxx> + +#include <string.h> + +#include <boost/shared_ptr.hpp> + +#include <com/sun/star/xml/dom/events/XDocumentEvent.hpp> + +#include "../events/mutationevent.hxx" + + +namespace DOM +{ + + CCharacterData::CCharacterData( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : CCharacterData_Base(rDocument, rMutex, reNodeType, rpNode) + { + } + + void CCharacterData::dispatchEvent_Impl( + OUString const& prevValue, OUString const& newValue) + { + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMCharacterDataModified"))), UNO_QUERY); + event->initMutationEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMCharacterDataModified")), + sal_True, sal_False, Reference< XNode >(), + prevValue, newValue, OUString(), (AttrChangeType)0 ); + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); + } + + /** + Append the string to the end of the character data of the node. + */ + void SAL_CALL CCharacterData::appendData(const OUString& arg) + throw (RuntimeException, DOMException) + { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (m_aNodePtr != NULL) + { + OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + xmlNodeAddContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(arg, RTL_TEXTENCODING_UTF8).getStr())); + OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); + } + } + + /** + Remove a range of 16-bit units from the node. + */ + void SAL_CALL CCharacterData::deleteData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException) + { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (m_aNodePtr != NULL) + { + // get current data + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); + OUString tmp(rtl::OStringToOUString(aData, RTL_TEXTENCODING_UTF8)); + if (offset > tmp.getLength() || offset < 0 || count < 0) { + DOMException e; + e.Code = DOMExceptionType_INDEX_SIZE_ERR; + throw e; + } + if ((offset+count) > tmp.getLength()) + count = tmp.getLength() - offset; + + OUString tmp2 = tmp.copy(0, offset); + tmp2 += tmp.copy(offset+count, tmp.getLength() - (offset+count)); + OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); + OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); + } + } + + + /** + Return the character data of the node that implements this interface. + */ + OUString SAL_CALL CCharacterData::getData() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aData; + if (m_aNodePtr != NULL) + { + OSL_ENSURE(m_aNodePtr->content, "character data node with NULL content, please inform lars.oppermann@sun.com!"); + if (m_aNodePtr->content != NULL) + { + aData = OUString((const sal_Char*)m_aNodePtr->content, strlen((const sal_Char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + } + } + return aData; + } + + /** + The number of 16-bit units that are available through data and the + substringData method below. + */ + sal_Int32 SAL_CALL CCharacterData::getLength() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + sal_Int32 length = 0; + if (m_aNodePtr != NULL) + { + OUString aData((const sal_Char*)m_aNodePtr->content, strlen((const sal_Char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + length = aData.getLength(); + } + return length; + } + + /** + Insert a string at the specified 16-bit unit offset. + */ + void SAL_CALL CCharacterData::insertData(sal_Int32 offset, const OUString& arg) + throw (RuntimeException, DOMException) + { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (m_aNodePtr != NULL) + { + // get current data + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); + OUString tmp(rtl::OStringToOUString(aData, RTL_TEXTENCODING_UTF8)); + if (offset > tmp.getLength() || offset < 0) { + DOMException e; + e.Code = DOMExceptionType_INDEX_SIZE_ERR; + throw e; + } + + OUString tmp2 = tmp.copy(0, offset); + tmp2 += arg; + tmp2 += tmp.copy(offset, tmp.getLength() - offset); + OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); + OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); + } + } + + + /** + Replace the characters starting at the specified 16-bit unit offset + with the specified string. + */ + void SAL_CALL CCharacterData::replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg) + throw (RuntimeException, DOMException) + { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (m_aNodePtr != NULL) + { + // get current data + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); + OUString tmp(rtl::OStringToOUString(aData, RTL_TEXTENCODING_UTF8)); + if (offset > tmp.getLength() || offset < 0 || count < 0){ + DOMException e; + e.Code = DOMExceptionType_INDEX_SIZE_ERR; + throw e; + } + if ((offset+count) > tmp.getLength()) + count = tmp.getLength() - offset; + + OUString tmp2 = tmp.copy(0, offset); + tmp2 += arg; + tmp2 += tmp.copy(offset+count, tmp.getLength() - (offset+count)); + OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); + OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); + } + } + + /** + Set the character data of the node that implements this interface. + */ + void SAL_CALL CCharacterData::setData(const OUString& data) + throw (RuntimeException, DOMException) + { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (m_aNodePtr != NULL) + { + OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr())); + OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); + } + } + + /** + Extracts a range of data from the node. + */ + OUString SAL_CALL CCharacterData::subStringData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aStr; + if (m_aNodePtr != NULL) + { + // get current data + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); + OUString tmp(rtl::OStringToOUString(aData, RTL_TEXTENCODING_UTF8)); + if (offset > tmp.getLength() || offset < 0 || count < 0) { + DOMException e; + e.Code = DOMExceptionType_INDEX_SIZE_ERR; + throw e; + } + aStr = tmp.copy(offset, count); + } + return aStr; + } + + +} // namspace DOM + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/characterdata.hxx b/unoxml/source/dom/characterdata.hxx new file mode 100644 index 000000000000..85d4d1fc857b --- /dev/null +++ b/unoxml/source/dom/characterdata.hxx @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_CHARACTERDATA_HXX +#define DOM_CHARACTERDATA_HXX + +#include <libxml/tree.h> + +#include <sal/types.h> + +#include <cppuhelper/implbase1.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XCharacterData.hpp> + +#include <node.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CNode, XCharacterData > + CCharacterData_Base; + + class CCharacterData + : public CCharacterData_Base + { + + protected: + CCharacterData(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + + void dispatchEvent_Impl( + OUString const& prevValue, OUString const& newValue); + + public: + /** + Append the string to the end of the character data of the node. + */ + virtual void SAL_CALL appendData(const OUString& arg) + throw (RuntimeException, DOMException); + + /** + Remove a range of 16-bit units from the node. + */ + virtual void SAL_CALL deleteData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException); + + /** + Return the character data of the node that implements this interface. + */ + virtual OUString SAL_CALL getData() throw (RuntimeException); + + /** + The number of 16-bit units that are available through data and the + substringData method below. + */ + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); + + /** + Insert a string at the specified 16-bit unit offset. + */ + virtual void SAL_CALL insertData(sal_Int32 offset, const OUString& arg) + throw (RuntimeException, DOMException); + + /** + Replace the characters starting at the specified 16-bit unit offset + with the specified string. + */ + virtual void SAL_CALL replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg) + throw (RuntimeException, DOMException); + + /** + Set the character data of the node that implements this interface. + */ + virtual void SAL_CALL setData(const OUString& data) + throw (RuntimeException, DOMException); + + /** + Extracts a range of data from the node. + */ + virtual OUString SAL_CALL subStringData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException); + + // --- delegation for XNode base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException) + { + return CNode::getNodeName(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException) + { + return getData(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return setData(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/childlist.cxx b/unoxml/source/dom/childlist.cxx new file mode 100644 index 000000000000..28731cef8c63 --- /dev/null +++ b/unoxml/source/dom/childlist.cxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <childlist.hxx> + +#include <libxml/tree.h> + +#include <node.hxx> +#include <document.hxx> + + +namespace DOM +{ + CChildList::CChildList(::rtl::Reference<CNode> const& pBase, + ::osl::Mutex & rMutex) + : m_pNode(pBase) + , m_rMutex(rMutex) + { + } + + /** + The number of nodes in the list. + */ + sal_Int32 SAL_CALL CChildList::getLength() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + sal_Int32 length = 0; + if (m_pNode != NULL) + { + xmlNodePtr cur = m_pNode->GetNodePtr(); + if (0 != cur) { + cur = cur->children; + } + while (cur != NULL) + { + length++; + cur = cur->next; + } + } + return length; + + } + /** + Returns the indexth item in the collection. + */ + Reference< XNode > SAL_CALL CChildList::item(sal_Int32 index) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (m_pNode != NULL) + { + xmlNodePtr cur = m_pNode->GetNodePtr(); + if (0 != cur) { + cur = cur->children; + } + while (cur != NULL) + { + if (index-- == 0) { + return Reference< XNode >( + m_pNode->GetOwnerDocument().GetCNode(cur).get()); + } + cur = cur->next; + } + } + return 0; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/childlist.hxx b/unoxml/source/dom/childlist.hxx new file mode 100644 index 000000000000..d9d96db13429 --- /dev/null +++ b/unoxml/source/dom/childlist.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_CHILDLIST_HXX +#define DOM_CHILDLIST_HXX + +#include <sal/types.h> +#include <rtl/ref.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> + +#include <cppuhelper/implbase1.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + class CNode; + + class CChildList + : public cppu::WeakImplHelper1< XNodeList > + { + private: + ::rtl::Reference<CNode> const m_pNode; + ::osl::Mutex & m_rMutex; + + public: + CChildList(::rtl::Reference<CNode> const& pBase, + ::osl::Mutex & rMutex); + + /** + The number of nodes in the list. + */ + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); + /** + Returns the indexth item in the collection. + */ + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/comment.cxx b/unoxml/source/dom/comment.cxx new file mode 100644 index 000000000000..e2bd7ec26c32 --- /dev/null +++ b/unoxml/source/dom/comment.cxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <comment.hxx> + +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + + +namespace DOM +{ + CComment::CComment(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CComment_Base(rDocument, rMutex, NodeType_COMMENT_NODE, pNode) + { + } + + void CComment::saxify( + const Reference< XDocumentHandler >& i_xHandler) { + if (!i_xHandler.is()) throw RuntimeException(); + Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); + if (xExtended.is()) { + xExtended->comment(getData()); + } + } + + OUString SAL_CALL CComment::getNodeName()throw (RuntimeException) + { + return OUString(RTL_CONSTASCII_USTRINGPARAM("#comment")); + } + + OUString SAL_CALL CComment::getNodeValue() throw (RuntimeException) + { + return CCharacterData::getData(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/comment.hxx b/unoxml/source/dom/comment.hxx new file mode 100644 index 000000000000..d18b94c12590 --- /dev/null +++ b/unoxml/source/dom/comment.hxx @@ -0,0 +1,232 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_COMMENT_HXX +#define DOM_COMMENT_HXX + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XComment.hpp> + +#include <characterdata.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CCharacterData, XComment > + CComment_Base; + + class CComment + : public CComment_Base + { + private: + friend class CDocument; + + protected: + CComment(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); + + public: + + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + // --- delegations for XCharacterData + virtual void SAL_CALL appendData(const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::appendData(arg); + } + virtual void SAL_CALL deleteData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException) + { + CCharacterData::deleteData(offset, count); + } + virtual OUString SAL_CALL getData() throw (RuntimeException) + { + return CCharacterData::getData(); + } + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException) + { + return CCharacterData::getLength(); + } + virtual void SAL_CALL insertData(sal_Int32 offset, const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::insertData(offset, arg); + } + virtual void SAL_CALL replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::replaceData(offset, count, arg); + } + virtual void SAL_CALL setData(const OUString& data) + throw (RuntimeException, DOMException) + { + CCharacterData::setData(data); + } + virtual OUString SAL_CALL subStringData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException) + { + return CCharacterData::subStringData(offset, count); + } + + + // --- overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CCharacterData::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CCharacterData::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CCharacterData::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CCharacterData::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CCharacterData::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CCharacterData::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CCharacterData::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CCharacterData::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CCharacterData::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CCharacterData::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CCharacterData::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CCharacterData::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CCharacterData::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CCharacterData::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CCharacterData::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CCharacterData::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CCharacterData::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CCharacterData::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CCharacterData::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CCharacterData::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CCharacterData::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CCharacterData::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CCharacterData::setPrefix(prefix); + } + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/document.cxx b/unoxml/source/dom/document.cxx new file mode 100644 index 000000000000..50f4dc1c52e2 --- /dev/null +++ b/unoxml/source/dom/document.cxx @@ -0,0 +1,1091 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <com/sun/star/uno/Sequence.h> + +#include "document.hxx" +#include "attr.hxx" +#include "element.hxx" +#include "cdatasection.hxx" +#include "documentfragment.hxx" +#include "text.hxx" +#include "cdatasection.hxx" +#include "comment.hxx" +#include "processinginstruction.hxx" +#include "entityreference.hxx" +#include "documenttype.hxx" +#include "elementlist.hxx" +#include "domimplementation.hxx" +#include <entity.hxx> +#include <notation.hxx> + +#include "../events/event.hxx" +#include "../events/mutationevent.hxx" +#include "../events/uievent.hxx" +#include "../events/mouseevent.hxx" +#include "../events/eventdispatcher.hxx" + +#include <string.h> + +#include <com/sun/star/xml/sax/FastToken.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + +namespace DOM +{ + static xmlNodePtr lcl_getDocumentType(xmlDocPtr const i_pDocument) + { + // find the doc type + xmlNodePtr cur = i_pDocument->children; + while (cur != NULL) + { + if ((cur->type == XML_DOCUMENT_TYPE_NODE) || + (cur->type == XML_DTD_NODE)) { + return cur; + } + } + return 0; + } + + /// get the pointer to the root element node of the document + static xmlNodePtr lcl_getDocumentRootPtr(xmlDocPtr const i_pDocument) + { + // find the document element + xmlNodePtr cur = i_pDocument->children; + while (cur != NULL) + { + if (cur->type == XML_ELEMENT_NODE) + break; + cur = cur->next; + } + return cur; + } + + CDocument::CDocument(xmlDocPtr const pDoc) + : CDocument_Base(*this, m_Mutex, + NodeType_DOCUMENT_NODE, reinterpret_cast<xmlNodePtr>(pDoc)) + , m_aDocPtr(pDoc) + , m_streamListeners() + , m_pEventDispatcher(new events::CEventDispatcher()) + { + } + + ::rtl::Reference<CDocument> CDocument::CreateCDocument(xmlDocPtr const pDoc) + { + ::rtl::Reference<CDocument> const xDoc(new CDocument(pDoc)); + // add the doc itself to its nodemap! + xDoc->m_NodeMap.insert( + nodemap_t::value_type(reinterpret_cast<xmlNodePtr>(pDoc), + ::std::make_pair( + WeakReference<XNode>(static_cast<XDocument*>(xDoc.get())), + xDoc.get()))); + return xDoc; + } + + CDocument::~CDocument() + { + ::osl::MutexGuard const g(m_Mutex); +#ifdef DBG_UTIL + // node map must be empty now, otherwise CDocument must not die! + for (nodemap_t::iterator i = m_NodeMap.begin(); + i != m_NodeMap.end(); ++i) + { + Reference<XNode> const xNode(i->second.first); + OSL_ENSURE(!xNode.is(), + "CDocument::~CDocument(): ERROR: live node in document node map!"); + } +#endif + xmlFreeDoc(m_aDocPtr); + } + + + events::CEventDispatcher & CDocument::GetEventDispatcher() + { + return *m_pEventDispatcher; + } + + ::rtl::Reference< CElement > CDocument::GetDocumentElement() + { + xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr); + ::rtl::Reference< CElement > const xRet( + dynamic_cast<CElement*>(GetCNode(pNode).get())); + return xRet; + } + + void + CDocument::RemoveCNode(xmlNodePtr const pNode, CNode const*const pCNode) + { + nodemap_t::iterator const i = m_NodeMap.find(pNode); + if (i != m_NodeMap.end()) { + // #i113681# consider this scenario: + // T1 calls ~CNode + // T2 calls getCNode: lookup will find i->second->first invalid + // so a new CNode is created and inserted + // T1 calls removeCNode: i->second->second now points to a + // different CNode instance! + // + // check that the CNode is the right one + CNode *const pCurrent = i->second.second; + if (pCurrent == pCNode) { + m_NodeMap.erase(i); + } + } + } + + /** NB: this is the CNode factory. + it is the only place where CNodes may be instantiated. + all CNodes must be registered at the m_NodeMap. + */ + ::rtl::Reference<CNode> + CDocument::GetCNode(xmlNodePtr const pNode, bool const bCreate) + { + if (0 == pNode) { + return 0; + } + //check whether there is already an instance for this node + nodemap_t::const_iterator const i = m_NodeMap.find(pNode); + if (i != m_NodeMap.end()) { + // #i113681# check that the CNode is still alive + uno::Reference<XNode> const xNode(i->second.first); + if (xNode.is()) + { + ::rtl::Reference<CNode> ret(i->second.second); + OSL_ASSERT(ret.is()); + return ret; + } + } + + if (!bCreate) { return 0; } + + // there is not yet an instance wrapping this node, + // create it and store it in the map + + ::rtl::Reference<CNode> pCNode; + switch (pNode->type) + { + case XML_ELEMENT_NODE: + // m_aNodeType = NodeType::ELEMENT_NODE; + pCNode = static_cast< CNode* >( + new CElement(*this, m_Mutex, pNode)); + break; + case XML_TEXT_NODE: + // m_aNodeType = NodeType::TEXT_NODE; + pCNode = static_cast< CNode* >( + new CText(*this, m_Mutex, pNode)); + break; + case XML_CDATA_SECTION_NODE: + // m_aNodeType = NodeType::CDATA_SECTION_NODE; + pCNode = static_cast< CNode* >( + new CCDATASection(*this, m_Mutex, pNode)); + break; + case XML_ENTITY_REF_NODE: + // m_aNodeType = NodeType::ENTITY_REFERENCE_NODE; + pCNode = static_cast< CNode* >( + new CEntityReference(*this, m_Mutex, pNode)); + break; + case XML_ENTITY_NODE: + // m_aNodeType = NodeType::ENTITY_NODE; + pCNode = static_cast< CNode* >(new CEntity(*this, m_Mutex, + reinterpret_cast<xmlEntityPtr>(pNode))); + break; + case XML_PI_NODE: + // m_aNodeType = NodeType::PROCESSING_INSTRUCTION_NODE; + pCNode = static_cast< CNode* >( + new CProcessingInstruction(*this, m_Mutex, pNode)); + break; + case XML_COMMENT_NODE: + // m_aNodeType = NodeType::COMMENT_NODE; + pCNode = static_cast< CNode* >( + new CComment(*this, m_Mutex, pNode)); + break; + case XML_DOCUMENT_NODE: + // m_aNodeType = NodeType::DOCUMENT_NODE; + OSL_ENSURE(false, "CDocument::GetCNode is not supposed to" + " create a CDocument!!!"); + pCNode = static_cast< CNode* >(new CDocument( + reinterpret_cast<xmlDocPtr>(pNode))); + break; + case XML_DOCUMENT_TYPE_NODE: + case XML_DTD_NODE: + // m_aNodeType = NodeType::DOCUMENT_TYPE_NODE; + pCNode = static_cast< CNode* >(new CDocumentType(*this, m_Mutex, + reinterpret_cast<xmlDtdPtr>(pNode))); + break; + case XML_DOCUMENT_FRAG_NODE: + // m_aNodeType = NodeType::DOCUMENT_FRAGMENT_NODE; + pCNode = static_cast< CNode* >( + new CDocumentFragment(*this, m_Mutex, pNode)); + break; + case XML_NOTATION_NODE: + // m_aNodeType = NodeType::NOTATION_NODE; + pCNode = static_cast< CNode* >(new CNotation(*this, m_Mutex, + reinterpret_cast<xmlNotationPtr>(pNode))); + break; + case XML_ATTRIBUTE_NODE: + // m_aNodeType = NodeType::ATTRIBUTE_NODE; + pCNode = static_cast< CNode* >(new CAttr(*this, m_Mutex, + reinterpret_cast<xmlAttrPtr>(pNode))); + break; + // unsupported node types + case XML_HTML_DOCUMENT_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + default: + break; + } + + if (pCNode != 0) { + bool const bInserted = m_NodeMap.insert( + nodemap_t::value_type(pNode, + ::std::make_pair(WeakReference<XNode>(pCNode.get()), + pCNode.get())) + ).second; + OSL_ASSERT(bInserted); + if (!bInserted) { + // if insertion failed, delete new instance and return null + return 0; + } + } + + OSL_ENSURE(pCNode.is(), "no node produced during CDocument::GetCNode!"); + return pCNode; + } + + + CDocument & CDocument::GetOwnerDocument() + { + return *this; + } + + void CDocument::saxify(const Reference< XDocumentHandler >& i_xHandler) + { + i_xHandler->startDocument(); + for (xmlNodePtr pChild = m_aNodePtr->children; + pChild != 0; pChild = pChild->next) { + ::rtl::Reference<CNode> const pNode = GetCNode(pChild); + OSL_ENSURE(pNode != 0, "CNode::get returned 0"); + pNode->saxify(i_xHandler); + } + i_xHandler->endDocument(); + } + + void CDocument::fastSaxify( Context& rContext ) + { + rContext.mxDocHandler->startDocument(); + for (xmlNodePtr pChild = m_aNodePtr->children; + pChild != 0; pChild = pChild->next) { + ::rtl::Reference<CNode> const pNode = GetCNode(pChild); + OSL_ENSURE(pNode != 0, "CNode::get returned 0"); + pNode->fastSaxify(rContext); + } + rContext.mxDocHandler->endDocument(); + } + + bool CDocument::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + return true; + case NodeType_ELEMENT_NODE: + // there may be only one! + return 0 == lcl_getDocumentRootPtr(m_aDocPtr); + case NodeType_DOCUMENT_TYPE_NODE: + // there may be only one! + return 0 == lcl_getDocumentType(m_aDocPtr); + default: + return false; + } + } + + + void SAL_CALL CDocument::addListener(const Reference< XStreamListener >& aListener ) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + m_streamListeners.insert(aListener); + } + + void SAL_CALL CDocument::removeListener(const Reference< XStreamListener >& aListener ) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + m_streamListeners.erase(aListener); + } + + // IO context functions for libxml2 interaction + typedef struct { + Reference< XOutputStream > stream; + bool allowClose; + } IOContext; + + extern "C" { + // write callback + // int xmlOutputWriteCallback (void * context, const char * buffer, int len) + static int writeCallback(void *context, const char* buffer, int len){ + // create a sequence and write it to the stream + IOContext *pContext = static_cast<IOContext*>(context); + Sequence<sal_Int8> bs(reinterpret_cast<const sal_Int8*>(buffer), len); + pContext->stream->writeBytes(bs); + return len; + } + + // clsoe callback + //int xmlOutputCloseCallback (void * context) + static int closeCallback(void *context) + { + IOContext *pContext = static_cast<IOContext*>(context); + if (pContext->allowClose) { + pContext->stream->closeOutput(); + } + return 0; + } + } // extern "C" + + void SAL_CALL CDocument::start() + throw (RuntimeException) + { + listenerlist_t streamListeners; + { + ::osl::MutexGuard const g(m_Mutex); + + if (! m_rOutputStream.is()) { throw RuntimeException(); } + streamListeners = m_streamListeners; + } + + // notify listeners about start + listenerlist_t::const_iterator iter1 = streamListeners.begin(); + while (iter1 != streamListeners.end()) { + Reference< XStreamListener > aListener = *iter1; + aListener->started(); + ++iter1; + } + + { + ::osl::MutexGuard const g(m_Mutex); + + // check again! could have been reset... + if (! m_rOutputStream.is()) { throw RuntimeException(); } + + // setup libxml IO and write data to output stream + IOContext ioctx = {m_rOutputStream, false}; + xmlOutputBufferPtr pOut = xmlOutputBufferCreateIO( + writeCallback, closeCallback, &ioctx, NULL); + xmlSaveFileTo(pOut, m_aNodePtr->doc, NULL); + } + + // call listeners + listenerlist_t::const_iterator iter2 = streamListeners.begin(); + while (iter2 != streamListeners.end()) { + Reference< XStreamListener > aListener = *iter2; + aListener->closed(); + ++iter2; + } + } + + void SAL_CALL CDocument::terminate() + throw (RuntimeException) + { + // not supported + } + + void SAL_CALL CDocument::setOutputStream( const Reference< XOutputStream >& aStream ) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + m_rOutputStream = aStream; + } + + Reference< XOutputStream > SAL_CALL CDocument::getOutputStream() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + return m_rOutputStream; + } + + // Creates an Attr of the given name. + Reference< XAttr > SAL_CALL CDocument::createAttribute(const OUString& name) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_Mutex); + + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr, xName, NULL); + ::rtl::Reference< CAttr > const pCAttr( + dynamic_cast< CAttr* >(GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get())); + pCAttr->m_bUnlinked = true; + return pCAttr.get(); + }; + + // Creates an attribute of the given qualified name and namespace URI. + Reference< XAttr > SAL_CALL CDocument::createAttributeNS( + const OUString& ns, const OUString& qname) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_Mutex); + + // libxml does not allow a NS definition to be attached to an + // attribute node - which is a good thing, since namespaces are + // only defined as parts of element nodes + // thus the namespace data is stored in CAttr::m_pNamespace + sal_Int32 i = qname.indexOf(':'); + OString oPrefix, oName, oUri; + if (i != -1) + { + oPrefix = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8); + oName = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8); + } + else + { + oName = OUStringToOString(qname, RTL_TEXTENCODING_UTF8); + } + oUri = OUStringToOString(ns, RTL_TEXTENCODING_UTF8); + xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr, + reinterpret_cast<xmlChar const*>(oName.getStr()), 0); + ::rtl::Reference< CAttr > const pCAttr( + dynamic_cast< CAttr* >(GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get())); + if (!pCAttr.is()) { throw RuntimeException(); } + // store the namespace data! + pCAttr->m_pNamespace.reset( new stringpair_t(oUri, oPrefix) ); + pCAttr->m_bUnlinked = true; + + return pCAttr.get(); + }; + + // Creates a CDATASection node whose value is the specified string. + Reference< XCDATASection > SAL_CALL CDocument::createCDATASection(const OUString& data) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + OString const oData( + ::rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8)); + xmlChar const*const pData = + reinterpret_cast<xmlChar const*>(oData.getStr()); + xmlNodePtr const pText = + xmlNewCDataBlock(m_aDocPtr, pData, strlen(oData.getStr())); + Reference< XCDATASection > const xRet( + static_cast< XNode* >(GetCNode(pText).get()), + UNO_QUERY_THROW); + return xRet; + } + + // Creates a Comment node given the specified string. + Reference< XComment > SAL_CALL CDocument::createComment(const OUString& data) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); + xmlChar *xData = (xmlChar*)o1.getStr(); + xmlNodePtr pComment = xmlNewDocComment(m_aDocPtr, xData); + Reference< XComment > const xRet( + static_cast< XNode* >(GetCNode(pComment).get()), + UNO_QUERY_THROW); + return xRet; + } + + //Creates an empty DocumentFragment object. + Reference< XDocumentFragment > SAL_CALL CDocument::createDocumentFragment() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + xmlNodePtr pFrag = xmlNewDocFragment(m_aDocPtr); + Reference< XDocumentFragment > const xRet( + static_cast< XNode* >(GetCNode(pFrag).get()), + UNO_QUERY_THROW); + return xRet; + } + + // Creates an element of the type specified. + Reference< XElement > SAL_CALL CDocument::createElement(const OUString& tagName) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_Mutex); + + OString o1 = OUStringToOString(tagName, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; + } + + // Creates an element of the given qualified name and namespace URI. + Reference< XElement > SAL_CALL CDocument::createElementNS( + const OUString& ns, const OUString& qname) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_Mutex); + + sal_Int32 i = qname.indexOf(':'); + if (ns.getLength() == 0) throw RuntimeException(); + xmlChar *xPrefix; + xmlChar *xName; + OString o1, o2, o3; + if ( i != -1) { + o1 = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8); + xPrefix = (xmlChar*)o1.getStr(); + o2 = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8); + xName = (xmlChar*)o2.getStr(); + } else { + // default prefix + xPrefix = (xmlChar*)""; + o2 = OUStringToOString(qname, RTL_TEXTENCODING_UTF8); + xName = (xmlChar*)o2.getStr(); + } + o3 = OUStringToOString(ns, RTL_TEXTENCODING_UTF8); + xmlChar *xUri = (xmlChar*)o3.getStr(); + + // xmlNsPtr aNsPtr = xmlNewReconciledNs? + // xmlNsPtr aNsPtr = xmlNewGlobalNs? + xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); + xmlNsPtr const pNs = xmlNewNs(pNode, xUri, xPrefix); + xmlSetNs(pNode, pNs); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; + } + + //Creates an EntityReference object. + Reference< XEntityReference > SAL_CALL CDocument::createEntityReference(const OUString& name) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_Mutex); + + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + xmlNodePtr const pNode = xmlNewReference(m_aDocPtr, xName); + Reference< XEntityReference > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; + } + + // Creates a ProcessingInstruction node given the specified name and + // data strings. + Reference< XProcessingInstruction > SAL_CALL CDocument::createProcessingInstruction( + const OUString& target, const OUString& data) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_Mutex); + + OString o1 = OUStringToOString(target, RTL_TEXTENCODING_UTF8); + xmlChar *xTarget = (xmlChar*)o1.getStr(); + OString o2 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); + xmlChar *xData = (xmlChar*)o2.getStr(); + xmlNodePtr const pNode = xmlNewDocPI(m_aDocPtr, xTarget, xData); + pNode->doc = m_aDocPtr; + Reference< XProcessingInstruction > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; + } + + // Creates a Text node given the specified string. + Reference< XText > SAL_CALL CDocument::createTextNode(const OUString& data) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); + xmlChar *xData = (xmlChar*)o1.getStr(); + xmlNodePtr const pNode = xmlNewDocText(m_aDocPtr, xData); + Reference< XText > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; + } + + // The Document Type Declaration (see DocumentType) associated with this + // document. + Reference< XDocumentType > SAL_CALL CDocument::getDoctype() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + xmlNodePtr const pDocType(lcl_getDocumentType(m_aDocPtr)); + Reference< XDocumentType > const xRet( + static_cast< XNode* >(GetCNode(pDocType).get()), + UNO_QUERY); + return xRet; + } + + // This is a convenience attribute that allows direct access to the child + // node that is the root element of the document. + Reference< XElement > SAL_CALL CDocument::getDocumentElement() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr); + if (!pNode) { return 0; } + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY); + return xRet; + } + + static xmlNodePtr + lcl_search_element_by_id(const xmlNodePtr cur, const xmlChar* id) + { + if (cur == NULL) + return NULL; + // look in current node + if (cur->type == XML_ELEMENT_NODE) + { + xmlAttrPtr a = cur->properties; + while (a != NULL) + { + if (a->atype == XML_ATTRIBUTE_ID) { + if (strcmp((char*)a->children->content, (char*)id) == 0) + return cur; + } + a = a->next; + } + } + // look in children + xmlNodePtr result = lcl_search_element_by_id(cur->children, id); + if (result != NULL) + return result; + result = lcl_search_element_by_id(cur->next, id); + return result; + } + + // Returns the Element whose ID is given by elementId. + Reference< XElement > SAL_CALL + CDocument::getElementById(const OUString& elementId) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + // search the tree for an element with the given ID + OString o1 = OUStringToOString(elementId, RTL_TEXTENCODING_UTF8); + xmlChar *xId = (xmlChar*)o1.getStr(); + xmlNodePtr const pStart = lcl_getDocumentRootPtr(m_aDocPtr); + if (!pStart) { return 0; } + xmlNodePtr const pNode = lcl_search_element_by_id(pStart, xId); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY); + return xRet; + } + + + Reference< XNodeList > SAL_CALL + CDocument::getElementsByTagName(OUString const& rTagname) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + Reference< XNodeList > const xRet( + new CElementList(this->GetDocumentElement(), m_Mutex, rTagname)); + return xRet; + } + + Reference< XNodeList > SAL_CALL CDocument::getElementsByTagNameNS( + OUString const& rNamespaceURI, OUString const& rLocalName) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + Reference< XNodeList > const xRet( + new CElementList(this->GetDocumentElement(), m_Mutex, + rLocalName, &rNamespaceURI)); + return xRet; + } + + Reference< XDOMImplementation > SAL_CALL CDocument::getImplementation() + throw (RuntimeException) + { + // does not need mutex currently + return Reference< XDOMImplementation >(CDOMImplementation::get()); + } + + // helper function to recursively import siblings + static void lcl_ImportSiblings( + Reference< XDocument > const& xTargetDocument, + Reference< XNode > const& xTargetParent, + Reference< XNode > const& xChild) + { + Reference< XNode > xSibling = xChild; + while (xSibling.is()) + { + Reference< XNode > const xTmp( + xTargetDocument->importNode(xSibling, sal_True)); + xTargetParent->appendChild(xTmp); + xSibling = xSibling->getNextSibling(); + } + } + + static Reference< XNode > + lcl_ImportNode( Reference< XDocument > const& xDocument, + Reference< XNode > const& xImportedNode, sal_Bool deep) + { + Reference< XNode > xNode; + NodeType aNodeType = xImportedNode->getNodeType(); + switch (aNodeType) + { + case NodeType_ATTRIBUTE_NODE: + { + Reference< XAttr > const xAttr(xImportedNode, UNO_QUERY_THROW); + Reference< XAttr > const xNew = + xDocument->createAttribute(xAttr->getName()); + xNew->setValue(xAttr->getValue()); + xNode.set(xNew, UNO_QUERY); + break; + } + case NodeType_CDATA_SECTION_NODE: + { + Reference< XCDATASection > const xCData(xImportedNode, + UNO_QUERY_THROW); + Reference< XCDATASection > const xNewCData = + xDocument->createCDATASection(xCData->getData()); + xNode.set(xNewCData, UNO_QUERY); + break; + } + case NodeType_COMMENT_NODE: + { + Reference< XComment > const xComment(xImportedNode, + UNO_QUERY_THROW); + Reference< XComment > const xNewComment = + xDocument->createComment(xComment->getData()); + xNode.set(xNewComment, UNO_QUERY); + break; + } + case NodeType_DOCUMENT_FRAGMENT_NODE: + { + Reference< XDocumentFragment > const xFrag(xImportedNode, + UNO_QUERY_THROW); + Reference< XDocumentFragment > const xNewFrag = + xDocument->createDocumentFragment(); + xNode.set(xNewFrag, UNO_QUERY); + break; + } + case NodeType_ELEMENT_NODE: + { + Reference< XElement > const xElement(xImportedNode, + UNO_QUERY_THROW); + OUString const aNsUri = xImportedNode->getNamespaceURI(); + OUString const aNsPrefix = xImportedNode->getPrefix(); + OUString aQName = xElement->getTagName(); + Reference< XElement > xNewElement; + if (aNsUri.getLength() > 0) + { + if (aNsPrefix.getLength() > 0) { + aQName = aNsPrefix + OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + + aQName; + } + xNewElement = xDocument->createElementNS(aNsUri, aQName); + } else { + xNewElement = xDocument->createElement(aQName); + } + + // get attributes + if (xElement->hasAttributes()) + { + Reference< XNamedNodeMap > attribs = xElement->getAttributes(); + for (sal_Int32 i = 0; i < attribs->getLength(); i++) + { + Reference< XAttr > const curAttr(attribs->item(i), + UNO_QUERY_THROW); + OUString const aAttrUri = curAttr->getNamespaceURI(); + OUString const aAttrPrefix = curAttr->getPrefix(); + OUString aAttrName = curAttr->getName(); + OUString const sValue = curAttr->getValue(); + if (aAttrUri.getLength() > 0) + { + if (aAttrPrefix.getLength() > 0) { + aAttrName = aAttrPrefix + + OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + aAttrName; + } + xNewElement->setAttributeNS( + aAttrUri, aAttrName, sValue); + } else { + xNewElement->setAttribute(aAttrName, sValue); + } + } + } + xNode.set(xNewElement, UNO_QUERY); + break; + } + case NodeType_ENTITY_REFERENCE_NODE: + { + Reference< XEntityReference > const xRef(xImportedNode, + UNO_QUERY_THROW); + Reference< XEntityReference > const xNewRef( + xDocument->createEntityReference(xRef->getNodeName())); + xNode.set(xNewRef, UNO_QUERY); + break; + } + case NodeType_PROCESSING_INSTRUCTION_NODE: + { + Reference< XProcessingInstruction > const xPi(xImportedNode, + UNO_QUERY_THROW); + Reference< XProcessingInstruction > const xNewPi( + xDocument->createProcessingInstruction( + xPi->getTarget(), xPi->getData())); + xNode.set(xNewPi, UNO_QUERY); + break; + } + case NodeType_TEXT_NODE: + { + Reference< XText > const xText(xImportedNode, UNO_QUERY_THROW); + Reference< XText > const xNewText( + xDocument->createTextNode(xText->getData())); + xNode.set(xNewText, UNO_QUERY); + break; + } + case NodeType_ENTITY_NODE: + case NodeType_DOCUMENT_NODE: + case NodeType_DOCUMENT_TYPE_NODE: + case NodeType_NOTATION_NODE: + default: + // can't be imported + throw RuntimeException(); + + } + if (deep) + { + // get children and import them + Reference< XNode > const xChild = xImportedNode->getFirstChild(); + if (xChild.is()) + { + lcl_ImportSiblings(xDocument, xNode, xChild); + } + } + + /* DOMNodeInsertedIntoDocument + * Fired when a node is being inserted into a document, + * either through direct insertion of the Node or insertion of a + * subtree in which it is contained. This event is dispatched after + * the insertion has taken place. The target of this event is the node + * being inserted. If the Node is being directly inserted the DOMNodeInserted + * event will fire before the DOMNodeInsertedIntoDocument event. + * Bubbles: No + * Cancelable: No + * Context Info: None + */ + if (xNode.is()) + { + Reference< XDocumentEvent > const xDocevent(xDocument, UNO_QUERY); + Reference< XMutationEvent > const event(xDocevent->createEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMNodeInsertedIntoDocument"))), + UNO_QUERY_THROW); + event->initMutationEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMNodeInsertedIntoDocument")) + , sal_True, sal_False, Reference< XNode >(), + OUString(), OUString(), OUString(), (AttrChangeType)0 ); + Reference< XEventTarget > const xDocET(xDocument, UNO_QUERY); + xDocET->dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + } + + return xNode; + } + + Reference< XNode > SAL_CALL CDocument::importNode( + Reference< XNode > const& xImportedNode, sal_Bool deep) + throw (RuntimeException, DOMException) + { + if (!xImportedNode.is()) { throw RuntimeException(); } + + // NB: this whole operation inherently accesses 2 distinct documents. + // The imported node could even be from a different DOM implementation, + // so this implementation cannot make any assumptions about the + // locking strategy of the imported node. + // So the import takes no lock on this document; + // it only calls UNO methods on this document that temporarily + // lock the document, and UNO methods on the imported node that + // may temporarily lock the other document. + // As a consequence, the import is not atomic with regard to + // concurrent modifications of either document, but it should not + // deadlock. + // To ensure that no members are accessed, the implementation is in + // static non-member functions. + + Reference< XDocument > const xDocument(this); + // already in doc? + if (xImportedNode->getOwnerDocument() == xDocument) { + return xImportedNode; + } + + Reference< XNode > const xNode( + lcl_ImportNode(xDocument, xImportedNode, deep) ); + return xNode; + } + + + OUString SAL_CALL CDocument::getNodeName()throw (RuntimeException) + { + // does not need mutex currently + return OUString(RTL_CONSTASCII_USTRINGPARAM("#document")); + } + + OUString SAL_CALL CDocument::getNodeValue() throw (RuntimeException) + { + // does not need mutex currently + return OUString(); + } + + Reference< XNode > SAL_CALL CDocument::cloneNode(sal_Bool bDeep) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OSL_ASSERT(0 != m_aNodePtr); + if (0 == m_aNodePtr) { + return 0; + } + xmlDocPtr const pClone(xmlCopyDoc(m_aDocPtr, (bDeep) ? 1 : 0)); + if (0 == pClone) { return 0; } + Reference< XNode > const xRet( + static_cast<CNode*>(CDocument::CreateCDocument(pClone).get())); + return xRet; + } + + Reference< XEvent > SAL_CALL CDocument::createEvent(const OUString& aType) throw (RuntimeException) + { + // does not need mutex currently + events::CEvent *pEvent = 0; + if ( + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMSubtreeModified")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMNodeInserted")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMNodeRemoved")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMNodeRemovedFromDocument")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMNodeInsertedIntoDocument")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMAttrModified")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMCharacterDataModified"))) + { + pEvent = new events::CMutationEvent; + + } else if ( + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMFocusIn")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMFocusOut")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DOMActivate"))) + { + pEvent = new events::CUIEvent; + } else if ( + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("click")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("mousedown")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("mouseup")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("mouseover")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("mousemove")) || + aType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("mouseout")) ) + { + pEvent = new events::CMouseEvent; + } + else // generic event + { + pEvent = new events::CEvent; + } + return Reference< XEvent >(pEvent); + } + + // ::com::sun::star::xml::sax::XSAXSerializable + void SAL_CALL CDocument::serialize( + const Reference< XDocumentHandler >& i_xHandler, + const Sequence< beans::StringPair >& i_rNamespaces) + throw (RuntimeException, SAXException) + { + ::osl::MutexGuard const g(m_Mutex); + + // add new namespaces to root node + xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr); + if (0 != pRoot) { + const beans::StringPair * pSeq = i_rNamespaces.getConstArray(); + for (const beans::StringPair *pNsDef = pSeq; + pNsDef < pSeq + i_rNamespaces.getLength(); ++pNsDef) { + OString prefix = OUStringToOString(pNsDef->First, + RTL_TEXTENCODING_UTF8); + OString href = OUStringToOString(pNsDef->Second, + RTL_TEXTENCODING_UTF8); + // this will only add the ns if it does not exist already + xmlNewNs(pRoot, reinterpret_cast<const xmlChar*>(href.getStr()), + reinterpret_cast<const xmlChar*>(prefix.getStr())); + } + // eliminate duplicate namespace declarations + nscleanup(pRoot->children, pRoot); + } + saxify(i_xHandler); + } + + // ::com::sun::star::xml::sax::XFastSAXSerializable + void SAL_CALL CDocument::fastSerialize( const Reference< XFastDocumentHandler >& i_xHandler, + const Reference< XFastTokenHandler >& i_xTokenHandler, + const Sequence< beans::StringPair >& i_rNamespaces, + const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& i_rRegisterNamespaces ) + throw (SAXException, RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + // add new namespaces to root node + xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr); + if (0 != pRoot) { + const beans::StringPair * pSeq = i_rNamespaces.getConstArray(); + for (const beans::StringPair *pNsDef = pSeq; + pNsDef < pSeq + i_rNamespaces.getLength(); ++pNsDef) { + OString prefix = OUStringToOString(pNsDef->First, + RTL_TEXTENCODING_UTF8); + OString href = OUStringToOString(pNsDef->Second, + RTL_TEXTENCODING_UTF8); + // this will only add the ns if it does not exist already + xmlNewNs(pRoot, reinterpret_cast<const xmlChar*>(href.getStr()), + reinterpret_cast<const xmlChar*>(prefix.getStr())); + } + // eliminate duplicate namespace declarations + nscleanup(pRoot->children, pRoot); + } + + Context aContext(i_xHandler, + i_xTokenHandler); + + // register namespace ids + const beans::Pair<OUString,sal_Int32>* pSeq = i_rRegisterNamespaces.getConstArray(); + for (const beans::Pair<OUString,sal_Int32>* pNs = pSeq; + pNs < pSeq + i_rRegisterNamespaces.getLength(); ++pNs) + { + OSL_ENSURE(pNs->Second >= FastToken::NAMESPACE, + "CDocument::fastSerialize(): invalid NS token id"); + aContext.maNamespaceMap[ pNs->First ] = pNs->Second; + } + + fastSaxify(aContext); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/document.hxx b/unoxml/source/dom/document.hxx new file mode 100644 index 000000000000..7045603b06d6 --- /dev/null +++ b/unoxml/source/dom/document.hxx @@ -0,0 +1,401 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_DOCUMENT_HXX +#define DOM_DOCUMENT_HXX + +#include <set> +#include <memory> + +#include <libxml/tree.h> + +#include <sal/types.h> + +#include <cppuhelper/implbase6.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XAttr.hpp> +#include <com/sun/star/xml/dom/XElement.hpp> +#include <com/sun/star/xml/dom/XDOMImplementation.hpp> +#include <com/sun/star/xml/dom/events/XDocumentEvent.hpp> +#include <com/sun/star/xml/dom/events/XEvent.hpp> +#include <com/sun/star/xml/sax/XSAXSerializable.hpp> +#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XActiveDataControl.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XStreamListener.hpp> + +#include "node.hxx" + + +using namespace std; +using ::rtl::OUString; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::sax; +using namespace com::sun::star::io; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::dom::events; + +namespace DOM +{ + namespace events { + class CEventDispatcher; + } + + class CElement; + + typedef ::cppu::ImplInheritanceHelper6< + CNode, XDocument, XDocumentEvent, + XActiveDataControl, XActiveDataSource, + XSAXSerializable, XFastSAXSerializable> + CDocument_Base; + + class CDocument + : public CDocument_Base + { + + private: + /// this Mutex is used for synchronization of all UNO wrapper + /// objects that belong to this document + ::osl::Mutex m_Mutex; + /// the libxml document: freed in destructor + /// => all UNO wrapper objects must keep the CDocument alive + xmlDocPtr const m_aDocPtr; + + // datacontrol/source state + typedef set< Reference< XStreamListener > > listenerlist_t; + listenerlist_t m_streamListeners; + Reference< XOutputStream > m_rOutputStream; + + typedef std::map< const xmlNodePtr, + ::std::pair< WeakReference<XNode>, CNode* > > nodemap_t; + nodemap_t m_NodeMap; + + ::std::auto_ptr<events::CEventDispatcher> const m_pEventDispatcher; + + CDocument(xmlDocPtr const pDocPtr); + + + public: + /// factory: only way to create instance! + static ::rtl::Reference<CDocument> + CreateCDocument(xmlDocPtr const pDoc); + + virtual ~CDocument(); + + // needed by CXPathAPI + ::osl::Mutex & GetMutex() { return m_Mutex; } + + events::CEventDispatcher & GetEventDispatcher(); + ::rtl::Reference< CElement > GetDocumentElement(); + + /// get UNO wrapper instance for a libxml node + ::rtl::Reference<CNode> GetCNode( + xmlNodePtr const pNode, bool const bCreate = true); + /// remove a UNO wrapper instance + void RemoveCNode(xmlNodePtr const pNode, CNode const*const pCNode); + + virtual CDocument & GetOwnerDocument(); + + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + virtual void fastSaxify( Context& rContext ); + + virtual bool IsChildTypeAllowed(NodeType const nodeType); + + /** + Creates an Attr of the given name. + */ + virtual Reference< XAttr > SAL_CALL createAttribute(const OUString& name) + throw (RuntimeException, DOMException); + + /** + Creates an attribute of the given qualified name and namespace URI. + */ + virtual Reference< XAttr > SAL_CALL createAttributeNS(const OUString& namespaceURI, const OUString& qualifiedName) + throw (RuntimeException, DOMException); + + /** + Creates a CDATASection node whose value is the specified string. + */ + virtual Reference< XCDATASection > SAL_CALL createCDATASection(const OUString& data) + throw (RuntimeException); + + /** + Creates a Comment node given the specified string. + */ + virtual Reference< XComment > SAL_CALL createComment(const OUString& data) + throw (RuntimeException); + + /** + Creates an empty DocumentFragment object. + */ + virtual Reference< XDocumentFragment > SAL_CALL createDocumentFragment() + throw (RuntimeException); + + /** + Creates an element of the type specified. + */ + virtual Reference< XElement > SAL_CALL createElement(const OUString& tagName) + throw (RuntimeException, DOMException); + + /** + Creates an element of the given qualified name and namespace URI. + */ + virtual Reference< XElement > SAL_CALL createElementNS(const OUString& namespaceURI, const OUString& qualifiedName) + throw (RuntimeException, DOMException); + + /** + Creates an EntityReference object. + */ + virtual Reference< XEntityReference > SAL_CALL createEntityReference(const OUString& name) + throw (RuntimeException, DOMException); + + /** + Creates a ProcessingInstruction node given the specified name and + data strings. + */ + virtual Reference< XProcessingInstruction > SAL_CALL createProcessingInstruction( + const OUString& target, const OUString& data) + throw (RuntimeException, DOMException); + + /** + Creates a Text node given the specified string. + */ + virtual Reference< XText > SAL_CALL createTextNode(const OUString& data) + throw (RuntimeException); + + /** + The Document Type Declaration (see DocumentType) associated with this + document. + */ + virtual Reference< XDocumentType > SAL_CALL getDoctype() + throw (RuntimeException); + + /** + This is a convenience attribute that allows direct access to the child + node that is the root element of the document. + */ + virtual Reference< XElement > SAL_CALL getDocumentElement() + throw (RuntimeException); + + /** + Returns the Element whose ID is given by elementId. + */ + virtual Reference< XElement > SAL_CALL getElementById(const OUString& elementId) + throw (RuntimeException); + + /** + Returns a NodeList of all the Elements with a given tag name in the + order in which they are encountered in a preorder traversal of the + Document tree. + */ + virtual Reference< XNodeList > SAL_CALL getElementsByTagName(const OUString& tagname) + throw (RuntimeException); + + /** + Returns a NodeList of all the Elements with a given local name and + namespace URI in the order in which they are encountered in a preorder + traversal of the Document tree. + */ + virtual Reference< XNodeList > SAL_CALL getElementsByTagNameNS(const OUString& namespaceURI, const OUString& localName) + throw (RuntimeException); + + /** + The DOMImplementation object that handles this document. + */ + virtual Reference< XDOMImplementation > SAL_CALL getImplementation() + throw (RuntimeException); + + /** + Imports a node from another document to this document. + */ + virtual Reference< XNode > SAL_CALL importNode(const Reference< XNode >& importedNode, sal_Bool deep) + throw (RuntimeException, DOMException); + + // XDocumentEvent + virtual Reference< XEvent > SAL_CALL createEvent(const OUString& eventType) throw (RuntimeException); + + // XActiveDataControl, + // see http://api.openoffice.org/docs/common/ref/com/sun/star/io/XActiveDataControl.html + virtual void SAL_CALL addListener(const Reference< XStreamListener >& aListener ) throw (RuntimeException); + virtual void SAL_CALL removeListener(const Reference< XStreamListener >& aListener ) throw (RuntimeException); + virtual void SAL_CALL start() throw (RuntimeException); + virtual void SAL_CALL terminate() throw (RuntimeException); + + // XActiveDataSource + // see http://api.openoffice.org/docs/common/ref/com/sun/star/io/XActiveDataSource.html + virtual void SAL_CALL setOutputStream( const Reference< XOutputStream >& aStream ) throw (RuntimeException); + virtual Reference< XOutputStream > SAL_CALL getOutputStream() throw (RuntimeException); + + // ---- resolve uno inheritance problems... + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException); + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CNode::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + // ::com::sun::star::xml::sax::XSAXSerializable + virtual void SAL_CALL serialize( + const Reference< XDocumentHandler >& i_xHandler, + const Sequence< beans::StringPair >& i_rNamespaces) + throw (RuntimeException, SAXException); + + // ::com::sun::star::xml::sax::XFastSAXSerializable + virtual void SAL_CALL fastSerialize( const Reference< XFastDocumentHandler >& handler, + const Reference< XFastTokenHandler >& tokenHandler, + const Sequence< beans::StringPair >& i_rNamespaces, + const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& namespaces ) + throw (SAXException, RuntimeException); + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/documentbuilder.cxx b/unoxml/source/dom/documentbuilder.cxx new file mode 100644 index 000000000000..b5c19d0a5a40 --- /dev/null +++ b/unoxml/source/dom/documentbuilder.cxx @@ -0,0 +1,415 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <documentbuilder.hxx> + +#include <string.h> +#include <stdio.h> +#include <stdarg.h> + +#include <libxml/xmlerror.h> +#include <libxml/tree.h> + +#include <boost/shared_ptr.hpp> + +#include <rtl/alloc.h> +#include <rtl/memory.h> +#include <rtl/ustrbuf.hxx> + +#include <cppuhelper/implbase1.hxx> + +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> + +#include <ucbhelper/content.hxx> +#include <ucbhelper/commandenvironment.hxx> + +#include <node.hxx> +#include <document.hxx> + + +using ::rtl::OUStringBuffer; +using ::rtl::OString; +using ::com::sun::star::xml::sax::InputSource; +using namespace ucbhelper; +using namespace ::com::sun::star::ucb; +using ::com::sun::star::task::XInteractionHandler; + + +namespace DOM +{ + + class CDefaultEntityResolver : public cppu::WeakImplHelper1< XEntityResolver > + { + public: + virtual InputSource SAL_CALL resolveEntity( const OUString& sPublicId, const OUString& sSystemId ) + throw (::com::sun::star::uno::RuntimeException) + { + InputSource is; + is.sPublicId = sPublicId; + is.sSystemId = sSystemId; + is.sEncoding = OUString(); + + try { + Reference< XCommandEnvironment > aEnvironment( + new CommandEnvironment(Reference< XInteractionHandler >(), + Reference< XProgressHandler >() )); + Content aContent(sSystemId, aEnvironment); + + is.aInputStream = aContent.openStream(); + } catch (const com::sun::star::uno::Exception&) { + OSL_FAIL("exception in default entity resolver"); + is.aInputStream = Reference< XInputStream >(); + } + return is; + } + + }; + + CDocumentBuilder::CDocumentBuilder( + Reference< XMultiServiceFactory > const& xFactory) + : m_xFactory(xFactory) + , m_xEntityResolver(new CDefaultEntityResolver()) + { + // init libxml. libxml will protect itself against multiple + // initializations so there is no problem here if this gets + // called multiple times. + xmlInitParser(); + } + + Reference< XInterface > CDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr) + { + return static_cast< XDocumentBuilder* >(new CDocumentBuilder(rSMgr)); + } + + const char* CDocumentBuilder::aImplementationName = "com.sun.star.comp.xml.dom.DocumentBuilder"; + const char* CDocumentBuilder::aSupportedServiceNames[] = { + "com.sun.star.xml.dom.DocumentBuilder", + NULL + }; + + OUString CDocumentBuilder::_getImplementationName() + { + return OUString::createFromAscii(aImplementationName); + } + Sequence<OUString> CDocumentBuilder::_getSupportedServiceNames() + { + Sequence<OUString> aSequence; + for (int i=0; aSupportedServiceNames[i]!=NULL; i++) { + aSequence.realloc(i+1); + aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i])); + } + return aSequence; + } + + Sequence< OUString > SAL_CALL CDocumentBuilder::getSupportedServiceNames() + throw (RuntimeException) + { + return CDocumentBuilder::_getSupportedServiceNames(); + } + + OUString SAL_CALL CDocumentBuilder::getImplementationName() + throw (RuntimeException) + { + return CDocumentBuilder::_getImplementationName(); + } + + sal_Bool SAL_CALL CDocumentBuilder::supportsService(const OUString& aServiceName) + throw (RuntimeException) + { + Sequence< OUString > supported = CDocumentBuilder::_getSupportedServiceNames(); + for (sal_Int32 i=0; i<supported.getLength(); i++) + { + if (supported[i] == aServiceName) return sal_True; + } + return sal_False; + } + + Reference< XDOMImplementation > SAL_CALL CDocumentBuilder::getDOMImplementation() + throw (RuntimeException) + { + + return Reference< XDOMImplementation >(); + } + + sal_Bool SAL_CALL CDocumentBuilder::isNamespaceAware() + throw (RuntimeException) + { + return sal_True; + } + + sal_Bool SAL_CALL CDocumentBuilder::isValidating() + throw (RuntimeException) + { + return sal_False; + } + + Reference< XDocument > SAL_CALL CDocumentBuilder::newDocument() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + // create a new document + xmlDocPtr pDocument = xmlNewDoc((const xmlChar*)"1.0"); + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDocument).get()); + return xRet; + } + + static OUString make_error_message(xmlParserCtxtPtr ctxt) + { + OUStringBuffer buf; + buf.appendAscii(ctxt->lastError.message); + buf.appendAscii("Line: "); + buf.append(static_cast<sal_Int32>(ctxt->lastError.line)); + buf.appendAscii("\nColumn: "); + buf.append(static_cast<sal_Int32>(ctxt->lastError.int2)); + OUString msg = buf.makeStringAndClear(); + return msg; + } + + // -- callbacks and context struct for parsing from stream + // -- c-linkage, so the callbacks can be used by libxml + extern "C" { + + // context struct passed to IO functions + typedef struct context { + CDocumentBuilder *pBuilder; + Reference< XInputStream > rInputStream; + bool close; + bool freeOnClose; + } context_t; + + static int xmlIO_read_func( void *context, char *buffer, int len) + { + // get the context... + context_t *pctx = static_cast<context_t*>(context); + if (!pctx->rInputStream.is()) + return -1; + try { + // try to read the requested number of bytes + Sequence< sal_Int8 > chunk(len); + int nread = pctx->rInputStream->readBytes(chunk, len); + + // copy bytes to the provided buffer + rtl_copyMemory(buffer, chunk.getConstArray(), nread); + return nread; + } catch (com::sun::star::uno::Exception& ex) { + (void) ex; + OSL_FAIL(OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr()); + return -1; + } + } + + static int xmlIO_close_func(void* context) + { + // get the context... + context_t *pctx = static_cast<context_t*>(context); + if (!pctx->rInputStream.is()) + return 0; + try + { + if (pctx->close) + pctx->rInputStream->closeInput(); + if (pctx->freeOnClose) + delete pctx; + return 0; + } catch (com::sun::star::uno::Exception& ex) { + (void) ex; + OSL_FAIL(OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr()); + return -1; + } + } + + static xmlParserInputPtr resolve_func(void *ctx, + const xmlChar *publicId, + const xmlChar *systemId) + { + // get the CDocumentBuilder object + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr)ctx; + CDocumentBuilder *builder = static_cast< CDocumentBuilder* >(ctxt->_private); + Reference< XEntityResolver > resolver = builder->getEntityResolver(); + OUString sysid; + if (systemId != 0) + sysid = OUString((sal_Char*)systemId, strlen((char*)systemId), RTL_TEXTENCODING_UTF8); + OUString pubid; + if (publicId != 0) + pubid = OUString((sal_Char*)publicId, strlen((char*)publicId), RTL_TEXTENCODING_UTF8); + + // resolve the entity + InputSource src = resolver->resolveEntity(pubid, sysid); + + // create IO context on heap because this call will no longer be on the stack + // when IO is actually performed through the callbacks. The close function must + // free the memory which is indicated by the freeOnClose field in the context struct + context_t *c = new context_t; + c->pBuilder = builder; + c->rInputStream = src.aInputStream; + c->close = true; + c->freeOnClose = true; + + // set up the inputBuffer and inputPtr for libxml + xmlParserInputBufferPtr pBuffer = + xmlParserInputBufferCreateIO(xmlIO_read_func, xmlIO_close_func, c, XML_CHAR_ENCODING_NONE); + xmlParserInputPtr pInput = + xmlNewIOInputStream(ctxt, pBuffer, XML_CHAR_ENCODING_NONE); + return pInput; + } + +#if 0 + static xmlParserInputPtr external_entity_loader(const char *URL, const char * /*ID*/, xmlParserCtxtPtr ctxt) + { + // just call our resolver function using the URL as systemId + return resolve_func(ctxt, 0, (const xmlChar*)URL); + } +#endif + + // default warning handler does not trigger assertion + static void warning_func(void * ctx, const char * /*msg*/, ...) + { + OUStringBuffer buf(OUString(RTL_CONSTASCII_USTRINGPARAM("libxml2 warning\n"))); + buf.append(make_error_message(static_cast< xmlParserCtxtPtr >(ctx))); + OString msg = OUStringToOString(buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US); + OSL_TRACE(msg.getStr()); + } + + // default error handler triggers assertion + static void error_func(void * ctx, const char * /*msg*/, ...) + { + OUStringBuffer buf(OUString(RTL_CONSTASCII_USTRINGPARAM("libxml2 error\n"))); + buf.append(make_error_message(static_cast< xmlParserCtxtPtr >(ctx))); + OString msg = OUStringToOString(buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(msg.getStr()); + } + + } // extern "C" + + void throwEx(xmlParserCtxtPtr ctxt) + { + com::sun::star::xml::sax::SAXParseException saxex; + saxex.Message = make_error_message(ctxt); + saxex.LineNumber = static_cast<sal_Int32>(ctxt->lastError.line); + saxex.ColumnNumber = static_cast<sal_Int32>(ctxt->lastError.int2); + throw saxex; + } + + Reference< XDocument > SAL_CALL CDocumentBuilder::parse(const Reference< XInputStream >& is) + throw (RuntimeException, SAXParseException, IOException) + { + if (!is.is()) { + throw RuntimeException(); + } + + ::osl::MutexGuard const g(m_Mutex); + + // encoding... + /* + xmlChar *encstr = (xmlChar*) OUStringToOString(src.sEncoding, RTL_TEXTENCODING_UTF8).getStr(); + xmlCharEncoding enc = xmlParseCharEncoding(encstr); + */ + + ::boost::shared_ptr<xmlParserCtxt> const pContext( + xmlNewParserCtxt(), xmlFreeParserCtxt); + + // register error functions to prevent errors being printed + // on the console + pContext->_private = this; + pContext->sax->error = error_func; + pContext->sax->warning = warning_func; + pContext->sax->resolveEntity = resolve_func; + + // IO context struct + context_t c; + c.pBuilder = this; + c.rInputStream = is; + // we did not open the stream, thus we do not close it. + c.close = false; + c.freeOnClose = false; + xmlDocPtr const pDoc = xmlCtxtReadIO(pContext.get(), + xmlIO_read_func, xmlIO_close_func, &c, 0, 0, 0); + + if (pDoc == 0) { + throwEx(pContext.get()); + } + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDoc).get()); + return xRet; + } + + Reference< XDocument > SAL_CALL CDocumentBuilder::parseURI(const OUString& sUri) + throw (RuntimeException, SAXParseException, IOException) + { + ::osl::MutexGuard const g(m_Mutex); + + ::boost::shared_ptr<xmlParserCtxt> const pContext( + xmlNewParserCtxt(), xmlFreeParserCtxt); + pContext->_private = this; + pContext->sax->error = error_func; + pContext->sax->warning = warning_func; + pContext->sax->resolveEntity = resolve_func; + // xmlSetExternalEntityLoader(external_entity_loader); + OString oUri = OUStringToOString(sUri, RTL_TEXTENCODING_UTF8); + char *uri = (char*) oUri.getStr(); + xmlDocPtr pDoc = xmlCtxtReadFile(pContext.get(), uri, 0, 0); + if (pDoc == 0) { + throwEx(pContext.get()); + } + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDoc).get()); + return xRet; + } + + void SAL_CALL + CDocumentBuilder::setEntityResolver(Reference< XEntityResolver > const& xER) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + m_xEntityResolver = xER; + } + + Reference< XEntityResolver > SAL_CALL CDocumentBuilder::getEntityResolver() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + return m_xEntityResolver; + } + + void SAL_CALL + CDocumentBuilder::setErrorHandler(Reference< XErrorHandler > const& xEH) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + m_xErrorHandler = xEH; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/documentbuilder.hxx b/unoxml/source/dom/documentbuilder.hxx new file mode 100644 index 000000000000..3cb47696da96 --- /dev/null +++ b/unoxml/source/dom/documentbuilder.hxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_DOCUMENTBUILDER_HXX +#define DOM_DOCUMENTBUILDER_HXX + +#include <sal/types.h> + +#include <cppuhelper/implbase2.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Sequence.h> + +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XDOMImplementation.hpp> +#include <com/sun/star/xml/sax/XEntityResolver.hpp> +#include <com/sun/star/xml/sax/XErrorHandler.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::sax; +using namespace com::sun::star::io; + +namespace DOM +{ + typedef ::cppu::WeakImplHelper2 + < XDocumentBuilder + , ::com::sun::star::lang::XServiceInfo + > CDocumentBuilder_Base; + + class CDocumentBuilder + : public CDocumentBuilder_Base + { + private: + ::osl::Mutex m_Mutex; + Reference< ::com::sun::star::lang::XMultiServiceFactory > const + m_xFactory; + Reference< XEntityResolver > m_xEntityResolver; + Reference< XErrorHandler > m_xErrorHandler; + + public: + + // ctor + CDocumentBuilder( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + xFactory); + + // call for factory + static Reference< XInterface > getInstance( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + xFactory); + + // static helpers for service info and component management + static const char* aImplementationName; + static const char* aSupportedServiceNames[]; + static OUString _getImplementationName(); + static Sequence< OUString > _getSupportedServiceNames(); + static Reference< XInterface > _getInstance( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + rSMgr); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames () + throw (RuntimeException); + + /** + Obtain an instance of a DOMImplementation object. + */ + virtual Reference< XDOMImplementation > SAL_CALL getDOMImplementation() + throw (RuntimeException); + + /** + Indicates whether or not this parser is configured to understand + namespaces. + */ + virtual sal_Bool SAL_CALL isNamespaceAware() + throw (RuntimeException); + + /** + Indicates whether or not this parser is configured to validate XML + documents. + */ + virtual sal_Bool SAL_CALL isValidating() + throw (RuntimeException); + + /** + Obtain a new instance of a DOM Document object to build a DOM tree + with. + */ + virtual Reference< XDocument > SAL_CALL newDocument() + throw (RuntimeException); + + /** + Parse the content of the given InputStream as an XML document and + return a new DOM Document object. + */ + virtual Reference< XDocument > SAL_CALL parse(const Reference< XInputStream >& is) + throw (RuntimeException, SAXParseException, IOException); + + /** + Parse the content of the given URI as an XML document and return + a new DOM Document object. + */ + virtual Reference< XDocument > SAL_CALL parseURI(const OUString& uri) + throw (RuntimeException, SAXParseException, IOException); + + /** + Specify the EntityResolver to be used to resolve entities present + in the XML document to be parsed. + */ + virtual void SAL_CALL setEntityResolver(const Reference< XEntityResolver >& er) + throw (RuntimeException); + + virtual Reference< XEntityResolver > SAL_CALL getEntityResolver() + throw (RuntimeException); + + + /** + Specify the ErrorHandler to be used to report errors present in + the XML document to be parsed. + */ + virtual void SAL_CALL setErrorHandler(const Reference< XErrorHandler >& eh) + throw (RuntimeException); + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/documentfragment.cxx b/unoxml/source/dom/documentfragment.cxx new file mode 100644 index 000000000000..1a7954b0c5bb --- /dev/null +++ b/unoxml/source/dom/documentfragment.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <documentfragment.hxx> + +namespace DOM +{ + CDocumentFragment::CDocumentFragment( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CDocumentFragment_Base(rDocument, rMutex, + NodeType_DOCUMENT_FRAGMENT_NODE, pNode) + { + } + + bool CDocumentFragment::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } + } + + OUString SAL_CALL CDocumentFragment::getNodeName()throw (RuntimeException) + { + return OUString(RTL_CONSTASCII_USTRINGPARAM("#document-fragment")); + } + OUString SAL_CALL CDocumentFragment::getNodeValue() throw (RuntimeException) + { + return OUString(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/documentfragment.hxx b/unoxml/source/dom/documentfragment.hxx new file mode 100644 index 000000000000..7e08150a832e --- /dev/null +++ b/unoxml/source/dom/documentfragment.hxx @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_DOCUMENTFRAGMENT_HXX +#define DOM_DOCUMENTFRAGMENT_HXX + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> + +#include <node.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CNode, XDocumentFragment > + CDocumentFragment_Base; + + class CDocumentFragment + : public CDocumentFragment_Base + { + private: + friend class CDocument; + + protected: + CDocumentFragment( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); + + public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); + + // ---- resolve uno inheritance problems... + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CNode::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + + }; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/documenttype.cxx b/unoxml/source/dom/documenttype.cxx new file mode 100644 index 000000000000..6c7103d57533 --- /dev/null +++ b/unoxml/source/dom/documenttype.cxx @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <documenttype.hxx> + +#include <string.h> + +#include <entitiesmap.hxx> +#include <notationsmap.hxx> + + +namespace DOM +{ + + CDocumentType::CDocumentType( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlDtdPtr const pDtd) + : CDocumentType_Base(rDocument, rMutex, + NodeType_DOCUMENT_TYPE_NODE, reinterpret_cast<xmlNodePtr>(pDtd)) + , m_aDtdPtr(pDtd) + { + } + + /** + A NamedNodeMap containing the general entities, both external and + internal, declared in the DTD. + */ + Reference< XNamedNodeMap > SAL_CALL CDocumentType::getEntities() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNamedNodeMap > aMap; + if (m_aDtdPtr != NULL) + { + aMap.set(new CEntitiesMap(this, m_rMutex)); + } + return aMap; + } + + /** + The internal subset as a string, or null if there is none. + */ + OUString SAL_CALL CDocumentType::getInternalSubset() throw (RuntimeException) + { + OSL_ENSURE(false, + "CDocumentType::getInternalSubset: not implemented (#i113683#)"); + return OUString(); + } + + /** + The name of DTD; i.e., the name immediately following the DOCTYPE + keyword. + */ + OUString SAL_CALL CDocumentType::getName() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aName; + if (m_aDtdPtr != NULL) + { + aName = OUString((sal_Char*)m_aDtdPtr->name, strlen((char*)m_aDtdPtr->name), RTL_TEXTENCODING_UTF8); + } + return aName; + } + + /** + A NamedNodeMap containing the notations declared in the DTD. + */ + Reference< XNamedNodeMap > SAL_CALL CDocumentType::getNotations() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNamedNodeMap > aMap; + if (m_aDtdPtr != NULL) + { + aMap.set(new CNotationsMap(this, m_rMutex)); + } + return aMap; + } + + /** + The public identifier of the external subset. + */ + OUString SAL_CALL CDocumentType::getPublicId() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aId; + if (m_aDtdPtr != NULL) + { + aId = OUString((sal_Char*)m_aDtdPtr->name, strlen((char*)m_aDtdPtr->ExternalID), RTL_TEXTENCODING_UTF8); + } + return aId; + } + + /** + The system identifier of the external subset. + */ + OUString SAL_CALL CDocumentType::getSystemId() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aId; + if (m_aDtdPtr != NULL) + { + aId = OUString((sal_Char*)m_aDtdPtr->name, strlen((char*)m_aDtdPtr->SystemID), RTL_TEXTENCODING_UTF8); + } + return aId; + } + + OUString SAL_CALL CDocumentType::getNodeName()throw (RuntimeException) + { + return getName(); + } + + OUString SAL_CALL CDocumentType::getNodeValue() throw (RuntimeException) + { + return OUString(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/documenttype.hxx b/unoxml/source/dom/documenttype.hxx new file mode 100644 index 000000000000..5f5ee5a1f449 --- /dev/null +++ b/unoxml/source/dom/documenttype.hxx @@ -0,0 +1,228 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_DOCUMENTTYPE_HXX +#define DOM_DOCUMENTTYPE_HXX + +#include <libxml/tree.h> + +#include <sal/types.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XDocumentType.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/XNamedNodeMap.hpp> + +#include <node.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CNode, XDocumentType > + CDocumentType_Base; + + class CDocumentType + : public CDocumentType_Base + { + private: + friend class CDocument; + + private: + xmlDtdPtr m_aDtdPtr; + + protected: + CDocumentType(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlDtdPtr const pDtd); + + public: + /** + A NamedNodeMap containing the general entities, both external and + internal, declared in the DTD. + */ + virtual Reference< XNamedNodeMap > SAL_CALL getEntities() throw (RuntimeException); + + /** + The internal subset as a string, or null if there is none. + */ + virtual OUString SAL_CALL getInternalSubset() throw (RuntimeException); + + /** + The name of DTD; i.e., the name immediately following the DOCTYPE + keyword. + */ + virtual OUString SAL_CALL getName() throw (RuntimeException); + + /** + A NamedNodeMap containing the notations declared in the DTD. + */ + virtual Reference< XNamedNodeMap > SAL_CALL getNotations() throw (RuntimeException); + + /** + The public identifier of the external subset. + */ + virtual OUString SAL_CALL getPublicId() throw (RuntimeException); + + /** + The system identifier of the external subset. + */ + virtual OUString SAL_CALL getSystemId() throw (RuntimeException); + + // ---- resolve uno inheritance problems... + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CNode::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + }; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/domimplementation.cxx b/unoxml/source/dom/domimplementation.cxx new file mode 100644 index 000000000000..95d01d3c4b29 --- /dev/null +++ b/unoxml/source/dom/domimplementation.cxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <domimplementation.hxx> + +#include <rtl/instance.hxx> + + +namespace DOM +{ + // why the heck is this thing static? + // perhaps it would be helpful to know what the implementation should + // do to answer this question... + namespace { + struct DOMImplementation + : public ::rtl::Static<CDOMImplementation, DOMImplementation> {}; + } + + CDOMImplementation* CDOMImplementation::get() + { + return & DOMImplementation::get(); + } + + // there is just 1 static instance, so these must not delete it! + void SAL_CALL CDOMImplementation::acquire() throw () { } + void SAL_CALL CDOMImplementation::release() throw () { } + + /** + Creates a DOM Document object of the specified type with its document element. + */ + Reference <XDocument > SAL_CALL CDOMImplementation::createDocument( + OUString const& /*rNamespaceURI*/, + OUString const& /*rQualifiedName*/, + Reference< XDocumentType > const& /*xDoctype*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CDOMImplementation::createDocument: not implemented (#i113683#)"); + return Reference<XDocument>(); + } + + /** + Creates an empty DocumentType node. + */ + Reference< XDocumentType > SAL_CALL CDOMImplementation::createDocumentType( + OUString const& /*rQualifiedName*/, + OUString const& /*rPublicId*/, OUString const& /*rSystemId*/) + throw (RuntimeException) + { + OSL_ENSURE(false, "CDOMImplementation::createDocumentType: " + "not implemented (#i113683#)"); + return Reference<XDocumentType>(); + } + + /** + Test if the DOM implementation implements a specific feature. + */ + sal_Bool SAL_CALL + CDOMImplementation::hasFeature(OUString const& /*feature*/, OUString const& /*ver*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CDOMImplementation::hasFeature: not implemented (#i113683#)"); + return sal_False; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/domimplementation.hxx b/unoxml/source/dom/domimplementation.hxx new file mode 100644 index 000000000000..5ef1aa254224 --- /dev/null +++ b/unoxml/source/dom/domimplementation.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_DOMIMPLEMENTATION_HXX +#define DOM_DOMIMPLEMENTATION_HXX + +#include <sal/types.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XDocumentType.hpp> +#include <com/sun/star/xml/dom/XDOMImplementation.hpp> + +#include <cppuhelper/implbase1.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + class CDOMImplementation + : public cppu::WeakImplHelper1< XDOMImplementation > + { + + public: + static CDOMImplementation* get(); + + // there is just 1 static instance, so these must not delete it! + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + + /** + Creates a DOM Document object of the specified type with its document element. + */ + virtual Reference <XDocument > SAL_CALL createDocument(const OUString& namespaceURI, const OUString& qualifiedName, const Reference< XDocumentType >& doctype) + throw (RuntimeException); + + /** + Creates an empty DocumentType node. + */ + virtual Reference< XDocumentType > SAL_CALL createDocumentType(const OUString& qualifiedName, const OUString& publicId, const OUString& systemId) + throw (RuntimeException); + + /** + Test if the DOM implementation implements a specific feature. + */ + virtual sal_Bool SAL_CALL hasFeature(const OUString& feature, const OUString& ver) + throw (RuntimeException); + }; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/element.cxx b/unoxml/source/dom/element.cxx new file mode 100644 index 000000000000..9259caa318e0 --- /dev/null +++ b/unoxml/source/dom/element.cxx @@ -0,0 +1,801 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <element.hxx> + +#include <string.h> + +#include <boost/shared_ptr.hpp> + +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/xml/sax/FastToken.hdl> + +#include <comphelper/attributelist.hxx> + +#include <node.hxx> +#include <attr.hxx> +#include <elementlist.hxx> +#include <attributesmap.hxx> +#include <document.hxx> + +#include "../events/mutationevent.hxx" + + +namespace DOM +{ + + CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode) + { + } + + void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler) + { + if (!i_xHandler.is()) throw RuntimeException(); + comphelper::AttributeList *pAttrs = + new comphelper::AttributeList(); + OUString type = OUString(); + // add namespace definitions to attributes + for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != 0; pNs = pNs->next) { + const xmlChar *pPrefix = pNs->prefix; + OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix), + strlen(reinterpret_cast<const char*>(pPrefix)), + RTL_TEXTENCODING_UTF8); + OUString name = (prefix.getLength() == 0) + ? OUString(RTL_CONSTASCII_USTRINGPARAM("xmlns")) + : OUString(RTL_CONSTASCII_USTRINGPARAM("xmlns:")) + prefix; + const xmlChar *pHref = pNs->href; + OUString val(reinterpret_cast<const sal_Char*>(pHref), + strlen(reinterpret_cast<const char*>(pHref)), + RTL_TEXTENCODING_UTF8); + pAttrs->AddAttribute(name, type, val); + } + // add attributes + for (xmlAttrPtr pAttr = m_aNodePtr->properties; + pAttr != 0; pAttr = pAttr->next) { + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)); + OSL_ENSURE(pNode != 0, "CNode::get returned 0"); + OUString prefix = pNode->getPrefix(); + OUString name = (prefix.getLength() == 0) + ? pNode->getLocalName() + : prefix + OUString(static_cast<sal_Unicode>(':')) + pNode->getLocalName(); + OUString val = pNode->getNodeValue(); + pAttrs->AddAttribute(name, type, val); + } + OUString prefix = getPrefix(); + OUString name = (prefix.getLength() == 0) + ? getLocalName() + : prefix + OUString(static_cast<sal_Unicode>(':')) + getLocalName(); + Reference< XAttributeList > xAttrList(pAttrs); + i_xHandler->startElement(name, xAttrList); + // recurse + for (xmlNodePtr pChild = m_aNodePtr->children; + pChild != 0; pChild = pChild->next) { + ::rtl::Reference<CNode> const pNode( + GetOwnerDocument().GetCNode(pChild)); + OSL_ENSURE(pNode != 0, "CNode::get returned 0"); + pNode->saxify(i_xHandler); + } + i_xHandler->endElement(name); + } + + void CElement::fastSaxify( Context& i_rContext ) + { + if (!i_rContext.mxDocHandler.is()) throw RuntimeException(); + pushContext(i_rContext); + addNamespaces(i_rContext,m_aNodePtr); + + // add attributes + i_rContext.mxAttribList->clear(); + for (xmlAttrPtr pAttr = m_aNodePtr->properties; + pAttr != 0; pAttr = pAttr->next) { + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)); + OSL_ENSURE(pNode != 0, "CNode::get returned 0"); + + const xmlChar* xName = pAttr->name; + sal_Int32 nAttributeToken=FastToken::DONTKNOW; + + if( pAttr->ns && strlen((char*)pAttr->ns->prefix) ) + nAttributeToken = getTokenWithPrefix( i_rContext, + (sal_Char*)pAttr->ns->prefix, + (sal_Char*)xName ); + else + nAttributeToken = getToken( i_rContext, (sal_Char*)xName ); + + if( nAttributeToken != FastToken::DONTKNOW ) + i_rContext.mxAttribList->add( nAttributeToken, + OUStringToOString(pNode->getNodeValue(), + RTL_TEXTENCODING_UTF8)); + } + + const xmlChar* xPrefix = m_aNodePtr->ns ? m_aNodePtr->ns->prefix : (const xmlChar*)""; + const xmlChar* xName = m_aNodePtr->name; + sal_Int32 nElementToken=FastToken::DONTKNOW; + if( strlen((char*)xPrefix) ) + nElementToken = getTokenWithPrefix( i_rContext, (sal_Char*)xPrefix, (sal_Char*)xName ); + else + nElementToken = getToken( i_rContext, (sal_Char*)xName ); + + Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler); + try + { + Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() ); + if( nElementToken == FastToken::DONTKNOW ) + { + const OUString aNamespace; + const OUString aElementName( (sal_Char*)xPrefix, + strlen((char*)xPrefix), + RTL_TEXTENCODING_UTF8 ); + + if( xParentHandler.is() ) + i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr ); + else + i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr ); + + if( i_rContext.mxCurrentHandler.is() ) + i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr ); + } + else + { + if( xParentHandler.is() ) + i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr ); + else + i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr ); + + if( i_rContext.mxCurrentHandler.is() ) + i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr ); + } + } + catch( Exception& ) + {} + + // recurse + for (xmlNodePtr pChild = m_aNodePtr->children; + pChild != 0; pChild = pChild->next) { + ::rtl::Reference<CNode> const pNode( + GetOwnerDocument().GetCNode(pChild)); + OSL_ENSURE(pNode != 0, "CNode::get returned 0"); + pNode->fastSaxify(i_rContext); + } + + if( i_rContext.mxCurrentHandler.is() ) try + { + if( nElementToken != FastToken::DONTKNOW ) + i_rContext.mxCurrentHandler->endFastElement( nElementToken ); + else + { + const OUString aNamespace; + const OUString aElementName( (sal_Char*)xPrefix, + strlen((char*)xPrefix), + RTL_TEXTENCODING_UTF8 ); + + i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName ); + } + } + catch( Exception& ) + {} + + // restore after children have been processed + i_rContext.mxCurrentHandler = xParentHandler; + popContext(i_rContext); + } + + bool CElement::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_COMMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + case NodeType_ATTRIBUTE_NODE: + /* this is not relly allowed by the DOM spec, but this + implementation has evidently supported it (by special case + handling, so the attribute does not actually become a child) + so allow it for backward compatiblity */ + return true; + default: + return false; + } + } + + + /** + Retrieves an attribute value by name. + return empty string if attribute is not set + */ + OUString SAL_CALL CElement::getAttribute(OUString const& name) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + // search properties + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + ::boost::shared_ptr<xmlChar const> const pValue( + xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()), xmlFree); + OUString const ret( (pValue) + ? OUString(reinterpret_cast<sal_Char const*>(pValue.get()), + strlen(reinterpret_cast<char const*>(pValue.get())), + RTL_TEXTENCODING_UTF8) + : OUString() ); + return ret; + } + + /** + Retrieves an attribute node by name. + */ + Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); + if (0 == pAttr) { + return 0; + } + Reference< XAttr > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get()), + UNO_QUERY_THROW); + return xRet; + } + + /** + Retrieves an Attr node by local name and namespace URI. + */ + Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS( + const OUString& namespaceURI, const OUString& localName) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar const*const pNS = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS); + if (0 == pAttr) { + return 0; + } + Reference< XAttr > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get()), + UNO_QUERY_THROW); + return xRet; + } + + /** + Retrieves an attribute value by local name and namespace URI. + return empty string if attribute is not set + */ + OUString SAL_CALL + CElement::getAttributeNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar const*const pNS = + reinterpret_cast<xmlChar const*>(o2.getStr()); + ::boost::shared_ptr<xmlChar const> const pValue( + xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree); + if (0 == pValue) { + return ::rtl::OUString(); + } + OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()), + strlen(reinterpret_cast<char const*>(pValue.get())), + RTL_TEXTENCODING_UTF8); + return ret; + } + + /** + Returns a NodeList of all descendant Elements with a given tag name, + in the order in which they are + encountered in a preorder traversal of this Element tree. + */ + Reference< XNodeList > SAL_CALL + CElement::getElementsByTagName(OUString const& rLocalName) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xList( + new CElementList(this, m_rMutex, rLocalName)); + return xList; + } + + /** + Returns a NodeList of all the descendant Elements with a given local + name and namespace URI in the order in which they are encountered in + a preorder traversal of this Element tree. + */ + Reference< XNodeList > SAL_CALL + CElement::getElementsByTagNameNS( + OUString const& rNamespaceURI, OUString const& rLocalName) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xList( + new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI)); + return xList; + } + + /** + The name of the element. + */ + OUString SAL_CALL CElement::getTagName() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + OUString const ret((sal_Char*)m_aNodePtr->name, + strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8); + return ret; + } + + + /** + Returns true when an attribute with a given name is specified on this + element or has a default value, false otherwise. + */ + sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + return (m_aNodePtr != NULL && xmlHasProp(m_aNodePtr, xName) != NULL); + } + + /** + Returns true when an attribute with a given local name and namespace + URI is specified on this element or has a default value, false otherwise. + */ + sal_Bool SAL_CALL CElement::hasAttributeNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar *xNs = (xmlChar*)o2.getStr(); + return (m_aNodePtr != NULL && xmlHasNsProp(m_aNodePtr, xName, xNs) != NULL); + } + + /** + Removes an attribute by name. + */ + void SAL_CALL CElement::removeAttribute(OUString const& name) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return; + } + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); + if (0 == xmlUnsetProp(m_aNodePtr, pName)) { + ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr), false)); + if (pCNode.is()) { + pCNode->invalidate(); // freed by xmlUnsetProp + } + } + } + + /** + Removes an attribute by local name and namespace URI. + */ + void SAL_CALL CElement::removeAttributeNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return; + } + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar const*const pURI = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlNsPtr const pNs = + xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI); + xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI); + if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) { + ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr), false)); + if (pCNode.is()) { + pCNode->invalidate(); // freed by xmlUnsetNsProp + } + } + } + + /** + Removes the specified attribute node. + */ + Reference< XAttr > SAL_CALL + CElement::removeAttributeNode(Reference< XAttr > const& oldAttr) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + + ::rtl::Reference<CNode> const pCNode( + CNode::GetImplementation(Reference<XNode>(oldAttr.get()))); + if (!pCNode.is()) { throw RuntimeException(); } + + xmlNodePtr const pNode = pCNode->GetNodePtr(); + xmlAttrPtr const pAttr = (xmlAttrPtr) pNode; + if (!pAttr) { throw RuntimeException(); } + + if (pAttr->parent != m_aNodePtr) + { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (pAttr->doc != m_aNodePtr->doc) + { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + + Reference< XAttr > aAttr; + if (oldAttr->getNamespaceURI().getLength() > 0) { + ::rtl::OUStringBuffer qname(oldAttr->getPrefix()); + if (0 != qname.getLength()) { + qname.append(sal_Unicode(':')); + } + qname.append(oldAttr->getName()); + aAttr = GetOwnerDocument().createAttributeNS( + oldAttr->getNamespaceURI(), qname.makeStringAndClear()); + } else { + aAttr = GetOwnerDocument().createAttribute(oldAttr->getName()); + } + aAttr->setValue(oldAttr->getValue()); + xmlRemoveProp(pAttr); + pCNode->invalidate(); // freed by xmlRemoveProp + + return aAttr; + } + + /** + Adds a new attribute node. + */ + Reference< XAttr > + CElement::setAttributeNode_Impl_Lock( + Reference< XAttr > const& xNewAttr, bool const bNS) + { + if (xNewAttr->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + + // get the implementation + CAttr *const pCAttr = dynamic_cast<CAttr*>( + CNode::GetImplementation(xNewAttr)); + if (!pCAttr) { throw RuntimeException(); } + xmlAttrPtr const pAttr = + reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr()); + if (!pAttr) { throw RuntimeException(); } + + // check whether the attribute is not in use by another element + if (pAttr->parent) { + DOMException e; + e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR; + throw e; + } + + xmlAttrPtr res = NULL; + xmlChar const*const pContent( + (pAttr->children) ? pAttr->children->content : 0); + + if (bNS) { + xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) ); + res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent); + } else { + res = xmlNewProp(m_aNodePtr, pAttr->name, pContent); + } + + // get the new attr node + Reference< XAttr > const xAttr( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(res)).get()), + UNO_QUERY_THROW); + + // attribute addition event + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMAttrModified"))), UNO_QUERY); + event->initMutationEvent(OUString(RTL_CONSTASCII_USTRINGPARAM("DOMAttrModified")), + sal_True, sal_False, Reference< XNode >(xAttr, UNO_QUERY), + OUString(), xAttr->getValue(), xAttr->getName(), + AttrChangeType_ADDITION); + + guard.clear(); // release mutex before calling event handlers + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); + + return xAttr; + } + + Reference< XAttr > + CElement::setAttributeNode(const Reference< XAttr >& newAttr) + throw (RuntimeException, DOMException) + { + return setAttributeNode_Impl_Lock(newAttr, false); + } + + /** + Adds a new attribute. + */ + Reference< XAttr > + CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr) + throw (RuntimeException, DOMException) + { + return setAttributeNode_Impl_Lock(newAttr, true); + } + + /** + Adds a new attribute. + */ + void SAL_CALL + CElement::setAttribute(OUString const& name, OUString const& value) + throw (RuntimeException, DOMException) + { + ::osl::ClearableMutexGuard guard(m_rMutex); + + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); + xmlChar *xValue = (xmlChar*)o2.getStr(); + + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + OUString oldValue; + AttrChangeType aChangeType = AttrChangeType_MODIFICATION; + ::boost::shared_ptr<xmlChar const> const pOld( + xmlGetProp(m_aNodePtr, xName), xmlFree); + if (pOld == NULL) { + aChangeType = AttrChangeType_ADDITION; + xmlNewProp(m_aNodePtr, xName, xValue); + } else { + oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), + strlen(reinterpret_cast<char const*>(pOld.get())), + RTL_TEXTENCODING_UTF8); + xmlSetProp(m_aNodePtr, xName, xValue); + } + + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMAttrModified"))), UNO_QUERY); + event->initMutationEvent(OUString(RTL_CONSTASCII_USTRINGPARAM("DOMAttrModified")), + sal_True, sal_False, + Reference< XNode >(getAttributeNode(name), UNO_QUERY), + oldValue, value, name, aChangeType); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); + } + + /** + Adds a new attribute. + */ + void SAL_CALL + CElement::setAttributeNS(OUString const& namespaceURI, + OUString const& qualifiedName, OUString const& value) + throw (RuntimeException, DOMException) + { + if (namespaceURI.getLength() == 0) throw RuntimeException(); + + ::osl::ClearableMutexGuard guard(m_rMutex); + + OString o1, o2, o3, o4, o5; + xmlChar *xPrefix = NULL; + xmlChar *xLName = NULL; + o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8); + xmlChar *xQName = (xmlChar*)o1.getStr(); + sal_Int32 idx = qualifiedName.indexOf(':'); + if (idx != -1) + { + o2 = OUStringToOString( + qualifiedName.copy(0,idx), + RTL_TEXTENCODING_UTF8); + xPrefix = (xmlChar*)o2.getStr(); + o3 = OUStringToOString( + qualifiedName.copy(idx+1), + RTL_TEXTENCODING_UTF8); + xLName = (xmlChar*)o3.getStr(); + } else { + xPrefix = (xmlChar*)""; + xLName = xQName; + } + o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); + xmlChar *xURI= (xmlChar*)o4.getStr(); + xmlChar *xValue = (xmlChar*)o5.getStr(); + + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + + //find the right namespace + xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix); + // if no namespace found, create a new one + if (pNs == NULL) { + pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix); + } + + if (strcmp((char*)pNs->href, (char*)xURI) != 0) { + // ambiguous ns prefix + throw RuntimeException(); + } + + // found namespace matches + + OUString oldValue; + AttrChangeType aChangeType = AttrChangeType_MODIFICATION; + ::boost::shared_ptr<xmlChar const> const pOld( + xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree); + if (pOld == NULL) { + aChangeType = AttrChangeType_ADDITION; + xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue); + } else { + oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), + strlen(reinterpret_cast<char const*>(pOld.get())), + RTL_TEXTENCODING_UTF8); + xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue); + } + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMAttrModified"))), UNO_QUERY); + event->initMutationEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMAttrModified")), + sal_True, sal_False, + Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY), + oldValue, value, qualifiedName, aChangeType); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); + } + + Reference< XNamedNodeMap > SAL_CALL + CElement::getAttributes() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNamedNodeMap > const xMap( + new CAttributesMap(this, m_rMutex)); + return xMap; + } + + OUString SAL_CALL CElement::getNodeName()throw (RuntimeException) + { + return getLocalName(); + } + + OUString SAL_CALL CElement::getLocalName()throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aName; + if (m_aNodePtr != NULL) + { + const xmlChar* xName = m_aNodePtr->name; + aName = OUString((const sal_Char*)xName, strlen((const char*)xName), RTL_TEXTENCODING_UTF8); + } + return aName; + } + + OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException) + { + return OUString(); + } + + void SAL_CALL CElement::setElementName(const OUString& aName) + throw (RuntimeException, DOMException) + { + if ((aName.getLength() <= 0) || + (0 <= aName.indexOf(OUString(RTL_CONSTASCII_USTRINGPARAM(":"))))) + { + DOMException e; + e.Code = DOMExceptionType_INVALID_CHARACTER_ERR; + throw e; + } + + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)oName.getStr(); + xmlNodeSetName(m_aNodePtr, xName); + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/element.hxx b/unoxml/source/dom/element.hxx new file mode 100644 index 000000000000..a425becb131e --- /dev/null +++ b/unoxml/source/dom/element.hxx @@ -0,0 +1,308 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_ELEMENT_HXX +#define DOM_ELEMENT_HXX + +#include <libxml/tree.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/XNamedNodeMap.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> + +#include <node.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1<CNode, XElement > CElement_Base; + + class CElement + : public CElement_Base + { + private: + friend class CDocument; + + Reference< XAttr > setAttributeNode_Impl_Lock( + Reference< XAttr > const& xNewAttr, bool const bNS); + + protected: + CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); + + public: + + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + virtual void fastSaxify( Context& i_rContext ); + + virtual bool IsChildTypeAllowed(NodeType const nodeType); + + /** + Retrieves an attribute value by name. + */ + virtual OUString SAL_CALL getAttribute(const OUString& name) + throw (RuntimeException); + + /** + Retrieves an attribute node by name. + */ + virtual Reference< XAttr > SAL_CALL getAttributeNode(const OUString& name) + throw (RuntimeException); + + /** + Retrieves an Attr node by local name and namespace URI. + */ + virtual Reference< XAttr > SAL_CALL getAttributeNodeNS(const OUString& namespaceURI, const OUString& localName) + throw (RuntimeException); + + /** + Retrieves an attribute value by local name and namespace URI. + */ + virtual OUString SAL_CALL getAttributeNS(const OUString& namespaceURI, const OUString& localName) + throw (RuntimeException); + + /** + Returns a NodeList of all descendant Elements with a given tag name, + in the order in which they are + encountered in a preorder traversal of this Element tree. + */ + virtual Reference< XNodeList > SAL_CALL getElementsByTagName(const OUString& name) + throw (RuntimeException); + + /** + Returns a NodeList of all the descendant Elements with a given local + name and namespace URI in the order in which they are encountered in + a preorder traversal of this Element tree. + */ + virtual Reference< XNodeList > SAL_CALL getElementsByTagNameNS(const OUString& namespaceURI, + const OUString& localName) + throw (RuntimeException); + + /** + The name of the element. + */ + virtual OUString SAL_CALL getTagName() + throw (RuntimeException); + + /** + Returns true when an attribute with a given name is specified on this + element or has a default value, false otherwise. + */ + virtual sal_Bool SAL_CALL hasAttribute(const OUString& name) + throw (RuntimeException); + + /** + Returns true when an attribute with a given local name and namespace + URI is specified on this element or has a default value, false otherwise. + */ + virtual sal_Bool SAL_CALL hasAttributeNS(const OUString& namespaceURI, const OUString& localName) + throw (RuntimeException); + + /** + Removes an attribute by name. + */ + virtual void SAL_CALL removeAttribute(const OUString& name) + throw (RuntimeException, DOMException); + + /** + Removes the specified attribute node. + */ + virtual Reference< XAttr > SAL_CALL removeAttributeNode(const Reference< XAttr >& oldAttr) + throw (RuntimeException, DOMException); + + /** + Removes an attribute by local name and namespace URI. + */ + virtual void SAL_CALL removeAttributeNS(const OUString& namespaceURI, const OUString& localName) + throw (RuntimeException, DOMException); + + /** + Adds a new attribute. + */ + virtual void SAL_CALL setAttribute(const OUString& name, const OUString& value) + throw (RuntimeException, DOMException); + + /** + Adds a new attribute node. + */ + virtual Reference< XAttr > SAL_CALL setAttributeNode(const Reference< XAttr >& newAttr) + throw (RuntimeException, DOMException); + + /** + Adds a new attribute. + */ + virtual Reference< XAttr > SAL_CALL setAttributeNodeNS(const Reference< XAttr >& newAttr) + throw (RuntimeException, DOMException); + + /** + Adds a new attribute. + */ + virtual void SAL_CALL setAttributeNS( + const OUString& namespaceURI, const OUString& qualifiedName, const OUString& value) + throw (RuntimeException, DOMException); + + /** + sets the element name + */ + virtual void SAL_CALL setElementName(const OUString& elementName) + throw (RuntimeException, DOMException); + + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException); + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException); + + // resolve uno inheritance problems... + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CNode::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/elementlist.cxx b/unoxml/source/dom/elementlist.cxx new file mode 100644 index 000000000000..f12795273882 --- /dev/null +++ b/unoxml/source/dom/elementlist.cxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "elementlist.hxx" + +#include <string.h> + +#include <element.hxx> +#include <document.hxx> + + +namespace DOM +{ + + static xmlChar* lcl_initXmlString(::rtl::OUString const& rString) + { + ::rtl::OString const os = + ::rtl::OUStringToOString(rString, RTL_TEXTENCODING_UTF8); + xmlChar *const pRet = new xmlChar[os.getLength() + 1]; + strcpy(reinterpret_cast<char*>(pRet), os.getStr()); + return pRet; + } + + CElementList::CElementList(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex, + OUString const& rName, OUString const*const pURI) + : m_pElement(pElement) + , m_rMutex(rMutex) + , m_pName(lcl_initXmlString(rName)) + , m_pURI((pURI) ? lcl_initXmlString(*pURI) : 0) + , m_bRebuild(true) + { + if (m_pElement.is()) { + registerListener(*m_pElement); + } + } + + void CElementList::registerListener(CElement & rElement) + { + try { + Reference< XEventTarget > const xTarget( + static_cast<XElement*>(& rElement), UNO_QUERY_THROW); + OUString aType(RTL_CONSTASCII_USTRINGPARAM("DOMSubtreeModified")); + sal_Bool capture = sal_False; + xTarget->addEventListener(aType, + Reference< XEventListener >(this), capture); + } catch (Exception &e){ + OString aMsg("Exception caught while registering NodeList as listener:\n"); + aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + } + } + + void CElementList::buildlist(xmlNodePtr pNode, sal_Bool start) + { + // bail out if no rebuild is needed + if (start) { + if (!m_bRebuild) + { + return; + } else { + m_nodevector.erase(m_nodevector.begin(), m_nodevector.end()); + m_bRebuild = false; // don't rebuild until tree is mutated + } + } + + while (pNode != NULL ) + { + if (pNode->type == XML_ELEMENT_NODE && + (strcmp((char*)pNode->name, (char*)m_pName.get()) == 0)) + { + if (!m_pURI) { + m_nodevector.push_back(pNode); + } else { + if (pNode->ns != NULL && (0 == + strcmp((char*)pNode->ns->href, (char*)m_pURI.get()))) + { + m_nodevector.push_back(pNode); + } + } + } + if (pNode->children != NULL) buildlist(pNode->children, sal_False); + + if (!start) pNode = pNode->next; + else break; // fold back + } + } + + /** + The number of nodes in the list. + */ + sal_Int32 SAL_CALL CElementList::getLength() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_pElement.is()) { return 0; } + + // this has to be 'live' + buildlist(m_pElement->GetNodePtr()); + return m_nodevector.size(); + } + /** + Returns the indexth item in the collection. + */ + Reference< XNode > SAL_CALL CElementList::item(sal_Int32 index) + throw (RuntimeException) + { + if (index < 0) throw RuntimeException(); + + ::osl::MutexGuard const g(m_rMutex); + + if (!m_pElement.is()) { return 0; } + + buildlist(m_pElement->GetNodePtr()); + if (m_nodevector.size() <= static_cast<size_t>(index)) { + throw RuntimeException(); + } + Reference< XNode > const xRet( + m_pElement->GetOwnerDocument().GetCNode(m_nodevector[index]).get()); + return xRet; + } + + // tree mutations can change the list + void SAL_CALL CElementList::handleEvent(Reference< XEvent > const&) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + m_bRebuild = true; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/elementlist.hxx b/unoxml/source/dom/elementlist.hxx new file mode 100644 index 000000000000..eeb2cd89094f --- /dev/null +++ b/unoxml/source/dom/elementlist.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_ELEMENTLIST_HXX +#define DOM_ELEMENTLIST_HXX + +#include <vector> + +#include <boost/scoped_array.hpp> + +#include <libxml/tree.h> + +#include <sal/types.h> +#include <rtl/ref.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/events/XEvent.hpp> +#include <com/sun/star/xml/dom/events/XEventListener.hpp> + +#include <cppuhelper/implbase2.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::dom::events; + +namespace DOM +{ + class CElement; + + typedef std::vector< xmlNodePtr > nodevector_t; + + class CElementList + : public cppu::WeakImplHelper2< XNodeList, + com::sun::star::xml::dom::events::XEventListener > + { + private: + ::rtl::Reference<CElement> const m_pElement; + ::osl::Mutex & m_rMutex; + ::boost::scoped_array<xmlChar> const m_pName; + ::boost::scoped_array<xmlChar> const m_pURI; + bool m_bRebuild; + nodevector_t m_nodevector; + + void buildlist(xmlNodePtr pNode, sal_Bool start=sal_True); + void registerListener(CElement & rElement); + + public: + CElementList(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex, + OUString const& rName, OUString const*const pURI = 0); + + /** + The number of nodes in the list. + */ + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); + /** + Returns the indexth item in the collection. + */ + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); + + // XEventListener + virtual void SAL_CALL handleEvent(const Reference< XEvent >& evt) + throw (RuntimeException); + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/entitiesmap.cxx b/unoxml/source/dom/entitiesmap.cxx new file mode 100644 index 000000000000..381e8945f609 --- /dev/null +++ b/unoxml/source/dom/entitiesmap.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <entitiesmap.hxx> + +#include <documenttype.hxx> + + +namespace DOM +{ + CEntitiesMap::CEntitiesMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex) + : m_pDocType(pDocType) + , m_rMutex(rMutex) + { + } + + /** + The number of nodes in this map. + */ + sal_Int32 SAL_CALL CEntitiesMap::getLength() throw (RuntimeException) + { + OSL_ENSURE(false, + "CEntitiesMap::getLength: not implemented (#i113683#)"); + return 0; + } + + /** + Retrieves a node specified by local name + */ + Reference< XNode > SAL_CALL + CEntitiesMap::getNamedItem(OUString const& /*name*/) throw (RuntimeException) + { + OSL_ENSURE(false, + "CEntitiesMap::getNamedItem: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + Retrieves a node specified by local name and namespace URI. + */ + Reference< XNode > SAL_CALL + CEntitiesMap::getNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CEntitiesMap::getNamedItemNS: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + Returns the indexth item in the map. + */ + Reference< XNode > SAL_CALL + CEntitiesMap::item(sal_Int32 /*index*/) throw (RuntimeException) + { + OSL_ENSURE(false, "CEntitiesMap::item: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + Removes a node specified by name. + */ + Reference< XNode > SAL_CALL + CEntitiesMap::removeNamedItem(OUString const& /*name*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CEntitiesMap::removeNamedItem: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + // Removes a node specified by local name and namespace URI. + */ + Reference< XNode > SAL_CALL + CEntitiesMap::removeNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CEntitiesMap::removeNamedItemNS: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + // Adds a node using its nodeName attribute. + */ + Reference< XNode > SAL_CALL + CEntitiesMap::setNamedItem(Reference< XNode > const& /*arg*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CEntitiesMap::setNamedItem: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + Adds a node using its namespaceURI and localName. + */ + Reference< XNode > SAL_CALL + CEntitiesMap::setNamedItemNS(Reference< XNode > const& /*arg*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CEntitiesMap::setNamedItemNS: not implemented (#i113683#)"); + return Reference< XNode >(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/entitiesmap.hxx b/unoxml/source/dom/entitiesmap.hxx new file mode 100644 index 000000000000..83703991f898 --- /dev/null +++ b/unoxml/source/dom/entitiesmap.hxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_ENTITIESMAP_HXX +#define DOM_ENTITIESMAP_HXX + +#include <sal/types.h> +#include <rtl/ref.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNamedNodeMap.hpp> + +#include <cppuhelper/implbase1.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + class CDocumentType; + + class CEntitiesMap + : public cppu::WeakImplHelper1< XNamedNodeMap > + { + private: + ::rtl::Reference<CDocumentType> const m_pDocType; + ::osl::Mutex & m_rMutex; + + public: + CEntitiesMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex); + + /** + The number of nodes in this map. + */ + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); + + /** + Retrieves a node specified by local name + */ + virtual Reference< XNode > SAL_CALL + getNamedItem(const OUString& name) throw (RuntimeException); + + /** + Retrieves a node specified by local name and namespace URI. + */ + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); + + /** + Returns the indexth item in the map. + */ + virtual Reference< XNode > SAL_CALL + item(sal_Int32 index) throw (RuntimeException); + + /** + Removes a node specified by name. + */ + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) throw (RuntimeException); + + /** + // Removes a node specified by local name and namespace URI. + */ + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); + + /** + // Adds a node using its nodeName attribute. + */ + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); + + /** + Adds a node using its namespaceURI and localName. + */ + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/entity.cxx b/unoxml/source/dom/entity.cxx new file mode 100644 index 000000000000..134d78c8d4bc --- /dev/null +++ b/unoxml/source/dom/entity.cxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <entity.hxx> + +#include <string.h> + + +namespace DOM +{ + + CEntity::CEntity(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlEntityPtr const pEntity) + : CEntity_Base(rDocument, rMutex, + NodeType_ENTITY_NODE, reinterpret_cast<xmlNodePtr>(pEntity)) + , m_aEntityPtr(pEntity) + { + } + + bool CEntity::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } + } + + /** + For unparsed entities, the name of the notation for the entity. + */ + OUString SAL_CALL CEntity::getNotationName() throw (RuntimeException) + { + OSL_ENSURE(false, + "CEntity::getNotationName: not implemented (#i113683#)"); + return OUString(); + } + + /** + The public identifier associated with the entity, if specified. + */ + OUString SAL_CALL CEntity::getPublicId() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aID; + if(m_aEntityPtr != NULL) + { + aID = OUString((sal_Char*)m_aEntityPtr->ExternalID, strlen((char*)m_aEntityPtr->ExternalID), RTL_TEXTENCODING_UTF8); + } + return aID; + } + + /** + The system identifier associated with the entity, if specified. + */ + OUString SAL_CALL CEntity::getSystemId() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aID; + if(m_aEntityPtr != NULL) + { + aID = OUString((sal_Char*)m_aEntityPtr->SystemID, strlen((char*)m_aEntityPtr->SystemID), RTL_TEXTENCODING_UTF8); + } + return aID; + } + OUString SAL_CALL CEntity::getNodeName()throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aName; + if (m_aNodePtr != NULL) + { + const xmlChar* xName = m_aNodePtr->name; + aName = OUString((sal_Char*)xName, strlen((char*)xName), RTL_TEXTENCODING_UTF8); + } + return aName; + } + OUString SAL_CALL CEntity::getNodeValue() throw (RuntimeException) + { + return OUString(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/entity.hxx b/unoxml/source/dom/entity.hxx new file mode 100644 index 000000000000..dea53fd421ab --- /dev/null +++ b/unoxml/source/dom/entity.hxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_ENTITY_HXX +#define DOM_ENTITY_HXX + +#include <libxml/tree.h> +#include <libxml/entities.h> + +#include <sal/types.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XEntity.hpp> + +#include <node.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CNode, XEntity > CEntity_Base; + + class CEntity + : public CEntity_Base + { + private: + friend class CDocument; + + private: + xmlEntityPtr m_aEntityPtr; + + protected: + CEntity(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlEntityPtr const pEntity); + + public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); + + /** + For unparsed entities, the name of the notation for the entity. + */ + virtual OUString SAL_CALL getNotationName() throw (RuntimeException); + + /** + The public identifier associated with the entity, if specified. + */ + virtual OUString SAL_CALL getPublicId() throw (RuntimeException); + + /** + The system identifier associated with the entity, if specified. + */ + virtual OUString SAL_CALL getSystemId() throw (RuntimeException); + + // ---- resolve uno inheritance problems... + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CNode::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/entityreference.cxx b/unoxml/source/dom/entityreference.cxx new file mode 100644 index 000000000000..de773f2f88c7 --- /dev/null +++ b/unoxml/source/dom/entityreference.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <entityreference.hxx> + +#include <string.h> + +namespace DOM +{ + CEntityReference::CEntityReference( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CEntityReference_Base(rDocument, rMutex, + NodeType_ENTITY_REFERENCE_NODE, pNode) + { + } + + bool CEntityReference::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } + } + + OUString SAL_CALL CEntityReference::getNodeName()throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aName; + if (m_aNodePtr != NULL) + { + const xmlChar* xName = m_aNodePtr->name; + aName = OUString((sal_Char*)xName, strlen((char*)xName), RTL_TEXTENCODING_UTF8); + } + return aName; + } + + OUString SAL_CALL CEntityReference::getNodeValue() throw (RuntimeException) + { + return OUString(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/entityreference.hxx b/unoxml/source/dom/entityreference.hxx new file mode 100644 index 000000000000..ff2dc2542fa4 --- /dev/null +++ b/unoxml/source/dom/entityreference.hxx @@ -0,0 +1,192 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_ENTITYREFERENCE_HXX +#define DOM_ENTITYREFERENCE_HXX + +#include <libxml/tree.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XEntityReference.hpp> + +#include <node.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CNode, XEntityReference > + CEntityReference_Base; + + class CEntityReference + : public CEntityReference_Base + { + private: + friend class CDocument; + + protected: + CEntityReference( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); + + public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); + + // ---- resolve uno inheritance problems... + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CNode::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + }; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/node.cxx b/unoxml/source/dom/node.cxx new file mode 100644 index 000000000000..8cbcfc534a7d --- /dev/null +++ b/unoxml/source/dom/node.cxx @@ -0,0 +1,1058 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <node.hxx> + +#include <stdio.h> +#include <string.h> + +#include <libxml/xmlstring.h> + +#include <algorithm> + +#include <boost/bind.hpp> + +#include <rtl/uuid.h> +#include <rtl/instance.hxx> +#include <osl/mutex.hxx> + +#include <com/sun/star/xml/sax/FastToken.hpp> + +#include <comphelper/servicehelper.hxx> + +#include <document.hxx> +#include <attr.hxx> +#include <childlist.hxx> + +#include "../events/eventdispatcher.hxx" +#include "../events/mutationevent.hxx" + + + +using namespace ::com::sun::star; + +namespace +{ + class theCNodeUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theCNodeUnoTunnelId > {}; +} + +namespace DOM +{ + void pushContext(Context& io_rContext) + { + io_rContext.maNamespaces.push_back( + io_rContext.maNamespaces.back()); + } + + void popContext(Context& io_rContext) + { + io_rContext.maNamespaces.pop_back(); + } + + void addNamespaces(Context& io_rContext, xmlNodePtr pNode) + { + // add node's namespaces to current context + for (xmlNsPtr pNs = pNode->nsDef; pNs != 0; pNs = pNs->next) { + const xmlChar *pPrefix = pNs->prefix; + // prefix can be NULL when xmlns attribute is empty (xmlns="") + OString prefix(reinterpret_cast<const sal_Char*>(pPrefix), + pPrefix ? strlen(reinterpret_cast<const char*>(pPrefix)) : 0); + const xmlChar *pHref = pNs->href; + OUString val(reinterpret_cast<const sal_Char*>(pHref), + strlen(reinterpret_cast<const char*>(pHref)), + RTL_TEXTENCODING_UTF8); + + OSL_TRACE("Trying to add namespace %s (prefix %s)", + (const char*)pHref, (const char*)pPrefix); + + Context::NamespaceMapType::iterator aIter= + io_rContext.maNamespaceMap.find(val); + if( aIter != io_rContext.maNamespaceMap.end() ) + { + Context::Namespace aNS; + aNS.maPrefix = prefix; + aNS.mnToken = aIter->second; + aNS.maNamespaceURL = val; + + io_rContext.maNamespaces.back().push_back(aNS); + + OSL_TRACE("Added with token 0x%x", aIter->second); + } + } + } + + sal_Int32 getToken( const Context& rContext, const sal_Char* pToken ) + { + const Sequence<sal_Int8> aSeq( (sal_Int8*)pToken, strlen( pToken ) ); + return rContext.mxTokenHandler->getTokenFromUTF8( aSeq ); + } + + sal_Int32 getTokenWithPrefix( const Context& rContext, const sal_Char* pPrefix, const sal_Char* pName ) + { + sal_Int32 nNamespaceToken = FastToken::DONTKNOW; + OString prefix(pPrefix, + strlen(reinterpret_cast<const char*>(pPrefix))); + + OSL_TRACE("getTokenWithPrefix(): prefix %s, name %s", + (const char*)pPrefix, (const char*)pName); + + Context::NamespaceVectorType::value_type::const_iterator aIter; + if( (aIter=std::find_if(rContext.maNamespaces.back().begin(), + rContext.maNamespaces.back().end(), + boost::bind(std::equal_to<OString>(), + boost::bind(&Context::Namespace::getPrefix, + _1), + boost::cref(prefix)))) != rContext.maNamespaces.back().end() ) + { + nNamespaceToken = aIter->mnToken; + sal_Int32 nNameToken = getToken( rContext, pName ); + if( nNameToken != FastToken::DONTKNOW ) + nNamespaceToken |= nNameToken; + } + + return nNamespaceToken; + } + + + CNode::CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : m_bUnlinked(false) + , m_aNodeType(reNodeType) + , m_aNodePtr(rpNode) + // keep containing document alive + // (but not if this is a document; that would create a leak!) + , m_xDocument( (m_aNodePtr->type != XML_DOCUMENT_NODE) + ? &const_cast<CDocument&>(rDocument) : 0 ) + , m_rMutex(const_cast< ::osl::Mutex & >(rMutex)) + { + OSL_ASSERT(m_aNodePtr); + } + + void CNode::invalidate() + { + //remove from list if this wrapper goes away + if (m_aNodePtr != 0 && m_xDocument.is()) { + m_xDocument->RemoveCNode(m_aNodePtr, this); + } + // #i113663#: unlinked nodes will not be freed by xmlFreeDoc + if (m_bUnlinked) { + xmlFreeNode(m_aNodePtr); + } + m_aNodePtr = 0; + } + + CNode::~CNode() + { + // if this is the document itself, the mutex is already freed! + if (NodeType_DOCUMENT_NODE == m_aNodeType) { + invalidate(); + } else { + ::osl::MutexGuard const g(m_rMutex); + invalidate(); // other nodes are still alive so must lock mutex + } + } + + CNode * + CNode::GetImplementation(uno::Reference<uno::XInterface> const& xNode) + { + uno::Reference<lang::XUnoTunnel> const xUnoTunnel(xNode, UNO_QUERY); + if (!xUnoTunnel.is()) { return 0; } + CNode *const pCNode( reinterpret_cast< CNode* >( + ::sal::static_int_cast< sal_IntPtr >( + xUnoTunnel->getSomething(theCNodeUnoTunnelId::get().getSeq())))); + return pCNode; + } + + CDocument & CNode::GetOwnerDocument() + { + OSL_ASSERT(m_xDocument.is()); + return *m_xDocument; // needs overriding in CDocument! + } + + + static void lcl_nsexchange( + xmlNodePtr const aNode, xmlNsPtr const oldNs, xmlNsPtr const newNs) + { + // recursively exchange any references to oldNs with references to newNs + xmlNodePtr cur = aNode; + while (cur != 0) + { + if (cur->ns == oldNs) + cur->ns = newNs; + if (cur->type == XML_ELEMENT_NODE) + { + xmlAttrPtr curAttr = cur->properties; + while(curAttr != 0) + { + if (curAttr->ns == oldNs) + curAttr->ns = newNs; + curAttr = curAttr->next; + } + lcl_nsexchange(cur->children, oldNs, newNs); + } + cur = cur->next; + } + } + + /*static*/ void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent) + { + xmlNodePtr cur = aNode; + + //handle attributes + if (cur != NULL && cur->type == XML_ELEMENT_NODE) + { + xmlAttrPtr curAttr = cur->properties; + while(curAttr != 0) + { + if (curAttr->ns != NULL) + { + xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, curAttr->ns->prefix); + if (ns != NULL) + curAttr->ns = ns; + } + curAttr = curAttr->next; + } + } + + while (cur != NULL) + { + nscleanup(cur->children, cur); + if (cur->ns != NULL) + { + xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, cur->ns->prefix); + if (ns != NULL && ns != cur->ns && strcmp((char*)ns->href, (char*)cur->ns->href)==0) + { + xmlNsPtr curDef = cur->nsDef; + xmlNsPtr *refp = &(cur->nsDef); // insert point + while (curDef != NULL) + { + ns = xmlSearchNs(cur->doc, aParent, curDef->prefix); + if (ns != NULL && ns != curDef && strcmp((char*)ns->href, (char*)curDef->href)==0) + { + // reconnect ns pointers in sub-tree to newly found ns before + // removing redundant nsdecl to prevent dangling pointers. + lcl_nsexchange(cur, curDef, ns); + *refp = curDef->next; + xmlFreeNs(curDef); + curDef = *refp; + } else { + refp = &(curDef->next); + curDef = curDef->next; + } + } + } + } + cur = cur->next; + } + } + + void CNode::saxify(const Reference< XDocumentHandler >& i_xHandler) + { + if (!i_xHandler.is()) throw RuntimeException(); + // default: do nothing + } + + void CNode::fastSaxify(Context& io_rContext) + { + if (!io_rContext.mxDocHandler.is()) throw RuntimeException(); + // default: do nothing + } + + bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/) + { + // default: no children allowed + return false; + } + + /** + Adds the node newChild to the end of the list of children of this node. + */ + Reference< XNode > SAL_CALL CNode::appendChild( + Reference< XNode > const& xNewChild) + throw (RuntimeException, DOMException) + { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (0 == m_aNodePtr) { return 0; } + + CNode *const pNewChild(CNode::GetImplementation(xNewChild)); + if (!pNewChild) { throw RuntimeException(); } + xmlNodePtr const cur = pNewChild->GetNodePtr(); + if (!cur) { throw RuntimeException(); } + + // error checks: + // from other document + if (cur->doc != m_aNodePtr->doc) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + // same node + if (cur == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (cur->parent != NULL) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + // check whether this is an attribute node; it needs special handling + xmlNodePtr res = NULL; + if (cur->type == XML_ATTRIBUTE_NODE) + { + xmlChar const*const pChildren((cur->children) + ? cur->children->content + : reinterpret_cast<xmlChar const*>("")); + CAttr *const pCAttr(dynamic_cast<CAttr *>(pNewChild)); + if (!pCAttr) { throw RuntimeException(); } + xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) ); + if (pNs) { + res = reinterpret_cast<xmlNodePtr>( + xmlNewNsProp(m_aNodePtr, pNs, cur->name, pChildren)); + } else { + res = reinterpret_cast<xmlNodePtr>( + xmlNewProp(m_aNodePtr, cur->name, pChildren)); + } + } + else + { + res = xmlAddChild(m_aNodePtr, cur); + + // libxml can do optimization when appending nodes. + // if res != cur, something was optimized and the newchild-wrapper + // should be updated + if (res && (cur != res)) { + pNewChild->invalidate(); // cur has been freed + } + } + + if (!res) { return 0; } + + // use custom ns cleanup instead of + // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr); + // because that will not remove unneeded ns decls + nscleanup(res, m_aNodePtr); + + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(res); + + if (!pNode.is()) { return 0; } + + // dispatch DOMNodeInserted event, target is the new node + // this node is the related node + // does bubble + pNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMNodeInserted"))), UNO_QUERY); + event->initMutationEvent(OUString(RTL_CONSTASCII_USTRINGPARAM("DOMNodeInserted")) + , sal_True, sal_False, + this, + OUString(), OUString(), OUString(), (AttrChangeType)0 ); + + // the following dispatch functions use only UNO interfaces + // and call event listeners, so release mutex to prevent deadlocks. + guard.clear(); + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + // dispatch subtree modified for this node + dispatchSubtreeModified(); + + return pNode.get(); + } + + /** + Returns a duplicate of this node, i.e., serves as a generic copy + constructor for nodes. + */ + Reference< XNode > SAL_CALL CNode::cloneNode(sal_Bool bDeep) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + xmlCopyNode(m_aNodePtr, (bDeep) ? 1 : 0)); + if (!pNode.is()) { return 0; } + pNode->m_bUnlinked = true; // not linked yet + return pNode.get(); + } + + /** + A NamedNodeMap containing the attributes of this node (if it is an Element) + or null otherwise. + */ + Reference< XNamedNodeMap > SAL_CALL CNode::getAttributes() + throw (RuntimeException) + { + // return empty reference; only element node may override this impl + return Reference< XNamedNodeMap>(); + } + + /** + A NodeList that contains all children of this node. + */ + Reference< XNodeList > SAL_CALL CNode::getChildNodes() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + Reference< XNodeList > const xNodeList(new CChildList(this, m_rMutex)); + return xNodeList; + } + + /** + The first child of this node. + */ + Reference< XNode > SAL_CALL CNode::getFirstChild() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->children).get()); + return xNode; + } + + /** + The last child of this node. + */ + Reference< XNode > SAL_CALL CNode::getLastChild() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(xmlGetLastChild(m_aNodePtr)).get()); + return xNode; + } + + /** + Returns the local part of the qualified name of this node. + */ + OUString SAL_CALL CNode::getLocalName() + throw (RuntimeException) + { + // see CElement/CAttr + return ::rtl::OUString(); + } + + + /** + The namespace URI of this node, or null if it is unspecified. + */ + OUString SAL_CALL CNode::getNamespaceURI() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aURI; + if (m_aNodePtr != NULL && + (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) && + m_aNodePtr->ns != NULL) + { + const xmlChar* xHref = m_aNodePtr->ns->href; + aURI = OUString((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8); + } + return aURI; + } + + /** + The node immediately following this node. + */ + Reference< XNode > SAL_CALL CNode::getNextSibling() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->next).get()); + return xNode; + } + + /** + The name of this node, depending on its type; see the table above. + */ + OUString SAL_CALL CNode::getNodeName() + throw (RuntimeException) + { + /* + Interface nodeName nodeValue attributes + -------------------------------------------------------------------------------------- + Attr name of attribute value of attribute null + CDATASection "#cdata-section" content of the CDATA Section null + Comment "#comment" content of the comment null + Document "#document" null null + DocumentFragment "#document-fragment" null null + DocumentType document type name null null + Element tag name null NamedNodeMap + Entity entity name null null + EntityReference name of entity null null + referenced + Notation notation name null null + Processing\ target entire content excluding null + Instruction the target + Text "#text" content of the text node null + */ + OUString aName; + return aName; + } + + /** + A code representing the type of the underlying object, as defined above. + */ + NodeType SAL_CALL CNode::getNodeType() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return m_aNodeType; + } + + /** + The value of this node, depending on its type; see the table above. + */ + OUString SAL_CALL CNode::getNodeValue() + throw (RuntimeException) + { + OUString aValue; + return aValue; + } + + /** + The Document object associated with this node. + */ + Reference< XDocument > SAL_CALL CNode::getOwnerDocument() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + Reference< XDocument > const xDoc(& GetOwnerDocument()); + return xDoc; + } + + /** + The parent of this node. + */ + Reference< XNode > SAL_CALL CNode::getParentNode() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->parent).get()); + return xNode; + } + + /** + The namespace prefix of this node, or null if it is unspecified. + */ + OUString SAL_CALL CNode::getPrefix() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aPrefix; + if (m_aNodePtr != NULL && + (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) && + m_aNodePtr->ns != NULL) + { + const xmlChar* xPrefix = m_aNodePtr->ns->prefix; + if( xPrefix != NULL ) + aPrefix = OUString((sal_Char*)xPrefix, strlen((char*)xPrefix), RTL_TEXTENCODING_UTF8); + } + return aPrefix; + + } + + /** + The node immediately preceding this node. + */ + Reference< XNode > SAL_CALL CNode::getPreviousSibling() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; + } + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->prev).get()); + return xNode; + } + + /** + Returns whether this node (if it is an element) has any attributes. + */ + sal_Bool SAL_CALL CNode::hasAttributes() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return (m_aNodePtr != NULL && m_aNodePtr->properties != NULL); + } + + /** + Returns whether this node has any children. + */ + sal_Bool SAL_CALL CNode::hasChildNodes() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return (m_aNodePtr != NULL && m_aNodePtr->children != NULL); + } + + /** + Inserts the node newChild before the existing child node refChild. + */ + Reference< XNode > SAL_CALL CNode::insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + if (!newChild.is() || !refChild.is()) { throw RuntimeException(); } + + if (newChild->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + if (refChild->getParentNode() != Reference< XNode >(this)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + ::osl::ClearableMutexGuard guard(m_rMutex); + + CNode *const pNewNode(CNode::GetImplementation(newChild)); + CNode *const pRefNode(CNode::GetImplementation(refChild)); + if (!pNewNode || !pRefNode) { throw RuntimeException(); } + xmlNodePtr const pNewChild(pNewNode->GetNodePtr()); + xmlNodePtr const pRefChild(pRefNode->GetNodePtr()); + if (!pNewChild || !pRefChild) { throw RuntimeException(); } + + if (pNewChild == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + // already has parent + if (pNewChild->parent != NULL) + { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + // attributes are unordered anyway, so just do appendChild + if (XML_ATTRIBUTE_NODE == pNewChild->type) { + guard.clear(); + return appendChild(newChild); + } + + xmlNodePtr cur = m_aNodePtr->children; + + //search child before which to insert + while (cur != NULL) + { + if (cur == pRefChild) { + // insert before + pNewChild->next = cur; + pNewChild->prev = cur->prev; + cur->prev = pNewChild; + if (pNewChild->prev != NULL) { + pNewChild->prev->next = pNewChild; + } + pNewChild->parent = cur->parent; + if (pNewChild->parent->children == cur) { + pNewChild->parent->children = pNewChild; + } + // do not update parent->last here! + pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc + break; + } + cur = cur->next; + } + return refChild; + } + + /** + Tests whether the DOM implementation implements a specific feature and + that feature is supported by this node. + */ + sal_Bool SAL_CALL CNode::isSupported(const OUString& /*feature*/, const OUString& /*ver*/) + throw (RuntimeException) + { + OSL_ENSURE(false, "CNode::isSupported: not implemented (#i113683#)"); + return sal_False; + } + + /** + Puts all Text nodes in the full depth of the sub-tree underneath this + Node, including attribute nodes, into a "normal" form where only structure + (e.g., elements, comments, processing instructions, CDATA sections, and + entity references) separates Text nodes, i.e., there are neither adjacent + Text nodes nor empty Text nodes. + */ + void SAL_CALL CNode::normalize() + throw (RuntimeException) + { + //XXX combine adjacent text nodes and remove empty ones + OSL_ENSURE(false, "CNode::normalize: not implemented (#i113683#)"); + } + + /** + Removes the child node indicated by oldChild from the list of children, + and returns it. + */ + Reference< XNode > SAL_CALL + CNode::removeChild(const Reference< XNode >& xOldChild) + throw (RuntimeException, DOMException) + { + if (!xOldChild.is()) { + throw RuntimeException(); + } + + if (xOldChild->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + if (xOldChild->getParentNode() != Reference< XNode >(this)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (!m_aNodePtr) { throw RuntimeException(); } + + Reference<XNode> xReturn( xOldChild ); + + ::rtl::Reference<CNode> const pOld(CNode::GetImplementation(xOldChild)); + if (!pOld.is()) { throw RuntimeException(); } + xmlNodePtr const old = pOld->GetNodePtr(); + if (!old) { throw RuntimeException(); } + + if( old->type == XML_ATTRIBUTE_NODE ) + { + xmlAttrPtr pAttr = reinterpret_cast<xmlAttrPtr>(old); + xmlRemoveProp( pAttr ); + pOld->invalidate(); // freed by xmlRemoveProp + xReturn.clear(); + } + else + { + xmlUnlinkNode(old); + pOld->m_bUnlinked = true; + } + + /*DOMNodeRemoved + * Fired when a node is being removed from its parent node. + * This event is dispatched before the node is removed from the tree. + * The target of this event is the node being removed. + * Bubbles: Yes + * Cancelable: No + * Context Info: relatedNode holds the parent node + */ + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMNodeRemoved"))), UNO_QUERY); + event->initMutationEvent(OUString(RTL_CONSTASCII_USTRINGPARAM("DOMNodeRemoved")), + sal_True, + sal_False, + this, + OUString(), OUString(), OUString(), (AttrChangeType)0 ); + + // the following dispatch functions use only UNO interfaces + // and call event listeners, so release mutex to prevent deadlocks. + guard.clear(); + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + // subtree modified for this node + dispatchSubtreeModified(); + + return xReturn; + } + + /** + Replaces the child node oldChild with newChild in the list of children, + and returns the oldChild node. + */ + Reference< XNode > SAL_CALL CNode::replaceChild( + Reference< XNode > const& xNewChild, + Reference< XNode > const& xOldChild) + throw (RuntimeException, DOMException) + { + if (!xOldChild.is() || !xNewChild.is()) { + throw RuntimeException(); + } + + if (xNewChild->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + if (xOldChild->getParentNode() != Reference< XNode >(this)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + ::osl::ClearableMutexGuard guard(m_rMutex); + +/* + Reference< XNode > aNode = removeChild(oldChild); + appendChild(newChild); +*/ + ::rtl::Reference<CNode> const pOldNode( + CNode::GetImplementation(xOldChild)); + ::rtl::Reference<CNode> const pNewNode( + CNode::GetImplementation(xNewChild)); + if (!pOldNode.is() || !pNewNode.is()) { throw RuntimeException(); } + xmlNodePtr const pOld = pOldNode->GetNodePtr(); + xmlNodePtr const pNew = pNewNode->GetNodePtr(); + if (!pOld || !pNew) { throw RuntimeException(); } + + if (pNew == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + // already has parent + if (pNew->parent != NULL) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + if( pOld->type == XML_ATTRIBUTE_NODE ) + { + // can only replace attribute with attribute + if ( pOld->type != pNew->type ) + { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + xmlAttrPtr pAttr = (xmlAttrPtr)pOld; + xmlRemoveProp( pAttr ); + pOldNode->invalidate(); // freed by xmlRemoveProp + appendChild(xNewChild); + } + else + { + + xmlNodePtr cur = m_aNodePtr->children; + //find old node in child list + while (cur != NULL) + { + if(cur == pOld) + { + // exchange nodes + pNew->prev = pOld->prev; + if (pNew->prev != NULL) + pNew->prev->next = pNew; + pNew->next = pOld->next; + if (pNew->next != NULL) + pNew->next->prev = pNew; + pNew->parent = pOld->parent; + if(pNew->parent->children == pOld) + pNew->parent->children = pNew; + if(pNew->parent->last == pOld) + pNew->parent->last = pNew; + pOld->next = NULL; + pOld->prev = NULL; + pOld->parent = NULL; + pOldNode->m_bUnlinked = true; + pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc + } + cur = cur->next; + } + } + + guard.clear(); // release for calling event handlers + dispatchSubtreeModified(); + + return xOldChild; + } + + void CNode::dispatchSubtreeModified() + { + // only uses UNO interfaces => needs no mutex + + // dispatch DOMSubtreeModified + // target is _this_ node + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMSubtreeModified"))), UNO_QUERY); + event->initMutationEvent( + OUString(RTL_CONSTASCII_USTRINGPARAM("DOMSubtreeModified")), sal_True, + sal_False, Reference< XNode >(), + OUString(), OUString(), OUString(), (AttrChangeType)0 ); + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + } + + /** + The value of this node, depending on its type; see the table above. + */ + void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/) + throw (RuntimeException, DOMException) + { + // use specific node implememntation + // if we end up down here, something went wrong + DOMException e; + e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR; + throw e; + } + + /** + The namespace prefix of this node, or null if it is unspecified. + */ + void SAL_CALL CNode::setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || + ((m_aNodePtr->type != XML_ELEMENT_NODE) && + (m_aNodePtr->type != XML_ATTRIBUTE_NODE))) + { + DOMException e; + e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR; + throw e; + } + OString o1 = OUStringToOString(prefix, RTL_TEXTENCODING_UTF8); + xmlChar *pBuf = (xmlChar*)o1.getStr(); + if (m_aNodePtr != NULL && m_aNodePtr->ns != NULL) + { + xmlFree(const_cast<xmlChar *>(m_aNodePtr->ns->prefix)); + m_aNodePtr->ns->prefix = xmlStrdup(pBuf); + } + + } + + // --- XEventTarget + void SAL_CALL CNode::addEventListener(const OUString& eventType, + const Reference< com::sun::star::xml::dom::events::XEventListener >& listener, + sal_Bool useCapture) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + CDocument & rDocument(GetOwnerDocument()); + events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher()); + rDispatcher.addListener(m_aNodePtr, eventType, listener, useCapture); + } + + void SAL_CALL CNode::removeEventListener(const OUString& eventType, + const Reference< com::sun::star::xml::dom::events::XEventListener >& listener, + sal_Bool useCapture) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + CDocument & rDocument(GetOwnerDocument()); + events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher()); + rDispatcher.removeListener(m_aNodePtr, eventType, listener, useCapture); + } + + sal_Bool SAL_CALL CNode::dispatchEvent(const Reference< XEvent >& evt) + throw(RuntimeException, EventException) + { + CDocument * pDocument; + events::CEventDispatcher * pDispatcher; + xmlNodePtr pNode; + { + ::osl::MutexGuard const g(m_rMutex); + + pDocument = & GetOwnerDocument(); + pDispatcher = & pDocument->GetEventDispatcher(); + pNode = m_aNodePtr; + } + // this calls event listeners, do not call with locked mutex + pDispatcher->dispatchEvent(*pDocument, m_rMutex, pNode, this, evt); + return sal_True; + } + + ::sal_Int64 SAL_CALL + CNode::getSomething(Sequence< ::sal_Int8 > const& rId) + throw (RuntimeException) + { + if ((rId.getLength() == 16) && + (0 == rtl_compareMemory(theCNodeUnoTunnelId::get().getSeq().getConstArray(), + rId.getConstArray(), 16))) + { + return ::sal::static_int_cast< sal_Int64 >( + reinterpret_cast< sal_IntPtr >(this) ); + } + return 0; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/node.hxx b/unoxml/source/dom/node.hxx new file mode 100644 index 000000000000..3d0ff86afab7 --- /dev/null +++ b/unoxml/source/dom/node.hxx @@ -0,0 +1,353 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_NODE_HXX +#define DOM_NODE_HXX + +#include <libxml/tree.h> + +#include <sal/types.h> +#include <rtl/ref.hxx> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> + +#include <cppuhelper/implbase3.hxx> + +#include <sax/fastattribs.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/XNamedNodeMap.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/xml/dom/events/XEventTarget.hpp> +#include <com/sun/star/xml/dom/events/XEvent.hpp> +#include <com/sun/star/xml/dom/DOMException.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp> + +#include <boost/unordered_map.hpp> + +using ::rtl::OUString; +using ::rtl::OString; +using namespace sax_fastparser; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::sax; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::dom::events; +using com::sun::star::lang::XUnoTunnel; + + +namespace DOM +{ + struct Context + { + Context( const Reference< XFastDocumentHandler >& i_xHandler, + const Reference< XFastTokenHandler >& i_xTokenHandler ) : + maNamespaces( 1, std::vector<Namespace>() ), + maNamespaceMap(101), + mxAttribList(new FastAttributeList(i_xTokenHandler)), + mxCurrentHandler(i_xHandler, UNO_QUERY_THROW), + mxDocHandler(i_xHandler), + mxTokenHandler(i_xTokenHandler) + {} + + struct Namespace + { + OString maPrefix; + sal_Int32 mnToken; + OUString maNamespaceURL; + + const OString& getPrefix() const { return maPrefix; } + }; + + typedef std::vector< std::vector<Namespace> > NamespaceVectorType; + typedef boost::unordered_map< OUString, + sal_Int32, + rtl::OUStringHash > NamespaceMapType; + + /// outer vector: xml context; inner vector: current NS + NamespaceVectorType maNamespaces; + NamespaceMapType maNamespaceMap; + ::rtl::Reference<FastAttributeList> mxAttribList; + Reference<XFastContextHandler> mxCurrentHandler; + Reference<XFastDocumentHandler> mxDocHandler; + Reference<XFastTokenHandler> mxTokenHandler; + }; + + void pushContext(Context& io_rContext); + void popContext(Context& io_rContext); + + sal_Int32 getTokenWithPrefix( const Context& rContext, const sal_Char* xPrefix, const sal_Char* xName ); + sal_Int32 getToken( const Context& rContext, const sal_Char* xName ); + + /// add namespaces on this node to context + void addNamespaces(Context& io_rContext, xmlNodePtr pNode); + + class CDocument; + + class CNode : public cppu::WeakImplHelper3< XNode, XUnoTunnel, XEventTarget > + { + friend class CDocument; + friend class CElement; + friend class CAttributesMap; + + private: + bool m_bUnlinked; /// node has been removed from document + + protected: + NodeType const m_aNodeType; + /// libxml node; NB: not const, because invalidate may reset it to 0! + xmlNodePtr m_aNodePtr; + + ::rtl::Reference< CDocument > const m_xDocument; + ::osl::Mutex & m_rMutex; + + // for initialization by classes derived through ImplInheritanceHelper + CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + void invalidate(); + + void dispatchSubtreeModified(); + + public: + + virtual ~CNode(); + + static CNode * GetImplementation(::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface> const& xNode); + + xmlNodePtr GetNodePtr() { return m_aNodePtr; } + + virtual CDocument & GetOwnerDocument(); + + // recursively create SAX events + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + // recursively create SAX events + virtual void fastSaxify( Context& io_rContext ); + + // constrains child relationship between nodes based on type + virtual bool IsChildTypeAllowed(NodeType const nodeType); + + // ---- DOM interfaces + + /** + Adds the node newChild to the end of the list of children of this node. + */ + virtual Reference< XNode > SAL_CALL + appendChild(Reference< XNode > const& xNewChild) + throw (RuntimeException, DOMException); + + /** + Returns a duplicate of this node, i.e., serves as a generic copy + constructor for nodes. + */ + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException); + + /** + A NamedNodeMap containing the attributes of this node + (if it is an Element) or null otherwise. + */ + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException); + + /** + A NodeList that contains all children of this node. + */ + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException); + + /** + The first child of this node. + */ + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException); + + /** + The last child of this node. + */ + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException); + + /** + Returns the local part of the qualified name of this node. + */ + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException); + + /** + The namespace URI of this node, or null if it is unspecified. + */ + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException); + + /** + The node immediately following this node. + */ + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException); + + /** + The name of this node, depending on its type; see the table above. + -- virtual implemented by actual node types + */ + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + + /** + A code representing the type of the underlying object, as defined above. + */ + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException); + + /** + The value of this node, depending on its type; see the table above. + -- virtual implemented by actual node types + */ + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + + /** + The Document object associated with this node. + */ + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException); + + /** + The parent of this node. + */ + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException); + + /** + The namespace prefix of this node, or null if it is unspecified. + */ + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException); + + /** + The node immediately preceding this node. + */ + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException); + + /** + Returns whether this node (if it is an element) has any attributes. + */ + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException); + + /** + Returns whether this node has any children. + */ + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException); + + /** + Inserts the node newChild before the existing child node refChild. + */ + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException); + + /** + Tests whether the DOM implementation implements a specific feature and + that feature is supported by this node. + */ + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException); + + /** + Puts all Text nodes in the full depth of the sub-tree underneath this + Node, including attribute nodes, into a "normal" form where only structure + (e.g., elements, comments, processing instructions, CDATA sections, and + entity references) separates Text nodes, i.e., there are neither adjacent + Text nodes nor empty Text nodes. + */ + virtual void SAL_CALL normalize() + throw (RuntimeException); + + /** + Removes the child node indicated by oldChild from the list of children, + and returns it. + */ + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException); + + /** + Replaces the child node oldChild with newChild in the list of children, + and returns the oldChild node. + */ + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException); + + /** + The value of this node, depending on its type; see the table above. + */ + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException); + + /** + The namespace prefix of this node, or null if it is unspecified. + */ + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException); + + + // --- XEventTarget + virtual void SAL_CALL addEventListener(const OUString& eventType, + const Reference< XEventListener >& listener, + sal_Bool useCapture) + throw (RuntimeException); + + virtual void SAL_CALL removeEventListener(const OUString& eventType, + const Reference< XEventListener >& listener, + sal_Bool useCapture) + throw (RuntimeException); + + virtual sal_Bool SAL_CALL dispatchEvent(const Reference< XEvent >& evt) + throw(RuntimeException, EventException); + + // --- XUnoTunnel + virtual ::sal_Int64 SAL_CALL + getSomething(Sequence< ::sal_Int8 > const& rId) + throw (RuntimeException); + }; + + /// eliminate redundant namespace declarations + void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/notation.cxx b/unoxml/source/dom/notation.cxx new file mode 100644 index 000000000000..63a6d6ec869e --- /dev/null +++ b/unoxml/source/dom/notation.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <notation.hxx> + +#include <string.h> + +namespace DOM +{ + CNotation::CNotation(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNotationPtr const pNotation) + : CNotation_Base(rDocument, rMutex, + NodeType_NOTATION_NODE, reinterpret_cast<xmlNodePtr>(pNotation)) + , m_aNotationPtr(pNotation) + { + } + + OUString SAL_CALL CNotation::getPublicId() throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotation::getPublicId: not implemented (#i113683#)"); + return OUString(); + } + + /** + The system identifier of this notation. + */ + OUString SAL_CALL CNotation::getSystemId() throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotation::getSystemId: not implemented (#i113683#)"); + return OUString(); + } + + + OUString SAL_CALL CNotation::getNodeName()throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OUString aName; + if (m_aNodePtr != NULL) + { + const xmlChar* xName = m_aNodePtr->name; + aName = OUString((sal_Char*)xName, strlen((char*)xName), RTL_TEXTENCODING_UTF8); + } + return aName; + } + + OUString SAL_CALL CNotation::getNodeValue() throw (RuntimeException) + { + return OUString(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/notation.hxx b/unoxml/source/dom/notation.hxx new file mode 100644 index 000000000000..414bc0e80cf4 --- /dev/null +++ b/unoxml/source/dom/notation.hxx @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_NOTATION_HXX +#define DOM_NOTATION_HXX + +#include <libxml/tree.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNotation.hpp> + +#include <node.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef cppu::ImplInheritanceHelper1< CNode, XNotation > CNotation_Base; + + class CNotation + : public CNotation_Base + { + private: + friend class CDocument; + + private: + xmlNotationPtr m_aNotationPtr; + + protected: + CNotation(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNotationPtr const pNotation); + + /** + The public identifier of this notation. + */ + virtual OUString SAL_CALL getPublicId() throw (RuntimeException); + + /** + The system identifier of this notation. + */ + virtual OUString SAL_CALL getSystemId() throw (RuntimeException); + + // ---- resolve uno inheritance problems... + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CNode::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/notationsmap.cxx b/unoxml/source/dom/notationsmap.cxx new file mode 100644 index 000000000000..171baa96365f --- /dev/null +++ b/unoxml/source/dom/notationsmap.cxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <notationsmap.hxx> + +#include <documenttype.hxx> + + +namespace DOM +{ + CNotationsMap::CNotationsMap( + ::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex) + : m_pDocType(pDocType) + , m_rMutex(rMutex) + { + } + + /** + The number of nodes in this map. + */ + sal_Int32 SAL_CALL CNotationsMap::getLength() throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotationsMap::getLength: not implemented (#i113683#)"); + return 0; + } + + /** + Retrieves a node specified by local name + */ + Reference< XNode > SAL_CALL + CNotationsMap::getNamedItem(OUString const& /*name*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotationsMap::getNamedItem: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + Retrieves a node specified by local name and namespace URI. + */ + Reference< XNode > SAL_CALL + CNotationsMap::getNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotationsMap::getNamedItemNS: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + Returns the indexth item in the map. + */ + Reference< XNode > SAL_CALL + CNotationsMap::item(sal_Int32 /*index*/) throw (RuntimeException) + { + OSL_ENSURE(false, "CNotationsMap::item: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + Removes a node specified by name. + */ + Reference< XNode > SAL_CALL + CNotationsMap::removeNamedItem(OUString const& /*name*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotationsMap::removeNamedItem: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + // Removes a node specified by local name and namespace URI. + */ + Reference< XNode > SAL_CALL + CNotationsMap::removeNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotationsMap::removeNamedItemNS: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + // Adds a node using its nodeName attribute. + */ + Reference< XNode > SAL_CALL + CNotationsMap::setNamedItem(Reference< XNode > const& /*arg*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotationsMap::setNamedItem: not implemented (#i113683#)"); + return Reference< XNode >(); + } + + /** + Adds a node using its namespaceURI and localName. + */ + Reference< XNode > SAL_CALL + CNotationsMap::setNamedItemNS(Reference< XNode > const& /*arg*/) + throw (RuntimeException) + { + OSL_ENSURE(false, + "CNotationsMap::setNamedItemNS: not implemented (#i113683#)"); + return Reference< XNode >(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/notationsmap.hxx b/unoxml/source/dom/notationsmap.hxx new file mode 100644 index 000000000000..b4355e903da0 --- /dev/null +++ b/unoxml/source/dom/notationsmap.hxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_NOTATIONSMAP_HXX +#define DOM_NOTATIONSMAP_HXX + +#include <sal/types.h> +#include <rtl/ref.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNamedNodeMap.hpp> + +#include <cppuhelper/implbase1.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + class CDocumentType; + + class CNotationsMap + : public cppu::WeakImplHelper1< XNamedNodeMap > + { + private: + ::rtl::Reference<CDocumentType> const m_pDocType; + ::osl::Mutex & m_rMutex; + + public: + CNotationsMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex); + + /** + The number of nodes in this map. + */ + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); + + /** + Retrieves a node specified by local name + */ + virtual Reference< XNode > SAL_CALL + getNamedItem(OUString const& name) throw (RuntimeException); + + /** + Retrieves a node specified by local name and namespace URI. + */ + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); + + /** + Returns the indexth item in the map. + */ + virtual Reference< XNode > SAL_CALL + item(sal_Int32 index) throw (RuntimeException); + + /** + Removes a node specified by name. + */ + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) throw (RuntimeException); + + /** + // Removes a node specified by local name and namespace URI. + */ + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); + + /** + // Adds a node using its nodeName attribute. + */ + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); + + /** + Adds a node using its namespaceURI and localName. + */ + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/processinginstruction.cxx b/unoxml/source/dom/processinginstruction.cxx new file mode 100644 index 000000000000..aa119c7ade0f --- /dev/null +++ b/unoxml/source/dom/processinginstruction.cxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <processinginstruction.hxx> + +#include <string.h> + +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + + +namespace DOM +{ + CProcessingInstruction::CProcessingInstruction( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CProcessingInstruction_Base(rDocument, rMutex, + NodeType_PROCESSING_INSTRUCTION_NODE, pNode) + { + } + + void CProcessingInstruction::saxify( + const Reference< XDocumentHandler >& i_xHandler) { + if (!i_xHandler.is()) throw RuntimeException(); + Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); + if (xExtended.is()) { + xExtended->processingInstruction(getTarget(), getData()); + } + } + + /** + The content of this processing instruction. + */ + OUString SAL_CALL + CProcessingInstruction::getData() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + + char const*const pContent( + reinterpret_cast<char const*>(m_aNodePtr->content)); + if (0 == pContent) { + return ::rtl::OUString(); + } + OUString const ret(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8); + return ret; + } + + /** + The target of this processing instruction. + */ + OUString SAL_CALL + CProcessingInstruction::getTarget() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + + char const*const pName( + reinterpret_cast<char const*>(m_aNodePtr->name)); + if (0 == pName) { + return ::rtl::OUString(); + } + OUString const ret(pName, strlen(pName), RTL_TEXTENCODING_UTF8); + return ret; + } + + /** + The content of this processing instruction. + */ + void SAL_CALL CProcessingInstruction::setData(OUString const& rData) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + + OString const data( + ::rtl::OUStringToOString(rData, RTL_TEXTENCODING_UTF8)); + xmlChar const*const pData( + reinterpret_cast<xmlChar const*>(data.getStr()) ); + xmlFree(m_aNodePtr->content); + m_aNodePtr->content = xmlStrdup(pData); + } + + OUString SAL_CALL + CProcessingInstruction::getNodeName() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + + sal_Char const*const pName = + reinterpret_cast<sal_Char const*>(m_aNodePtr->name); + OUString const ret(pName, strlen(pName), RTL_TEXTENCODING_UTF8); + return ret; + } + + OUString SAL_CALL CProcessingInstruction::getNodeValue() + throw (RuntimeException) + { + return getData(); + } + + void SAL_CALL + CProcessingInstruction::setNodeValue(OUString const& rNodeValue) + throw (RuntimeException, DOMException) + { + return setData(rNodeValue); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/processinginstruction.hxx b/unoxml/source/dom/processinginstruction.hxx new file mode 100644 index 000000000000..41ee9f6f17c6 --- /dev/null +++ b/unoxml/source/dom/processinginstruction.hxx @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_PROCESSINGINSTRUCTION_HXX +#define DOM_PROCESSINGINSTRUCTION_HXX + +#include <libxml/tree.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XProcessingInstruction.hpp> + +#include <node.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CNode, XProcessingInstruction > + CProcessingInstruction_Base; + + class CProcessingInstruction + : public CProcessingInstruction_Base + { + private: + friend class CDocument; + + protected: + CProcessingInstruction( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); + + public: + + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + /** + The content of this processing instruction. + */ + virtual OUString SAL_CALL getData() throw (RuntimeException); + + /** + The target of this processing instruction. + */ + virtual OUString SAL_CALL getTarget() throw (RuntimeException); + + /** + The content of this processing instruction. + */ + virtual void SAL_CALL setData(const OUString& data) throw (RuntimeException, DOMException); + + // ---- resolve uno inheritance problems... + // overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + virtual OUString SAL_CALL getNodeValue() + throw (RuntimeException); + virtual void SAL_CALL setNodeValue(OUString const& rNodeValue) + throw (RuntimeException, DOMException); + + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CNode::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CNode::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CNode::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CNode::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CNode::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CNode::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CNode::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CNode::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CNode::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CNode::getNodeType(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CNode::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CNode::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CNode::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CNode::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CNode::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CNode::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CNode::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CNode::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CNode::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CNode::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CNode::setPrefix(prefix); + } + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/saxbuilder.cxx b/unoxml/source/dom/saxbuilder.cxx new file mode 100644 index 000000000000..6b73cbfb733f --- /dev/null +++ b/unoxml/source/dom/saxbuilder.cxx @@ -0,0 +1,383 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ +#if defined(_MSC_VER) && (_MSC_VER > 1310) +#pragma warning(disable : 4701) +#endif + +#include "saxbuilder.hxx" + +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> + + +namespace DOM +{ + Reference< XInterface > CSAXDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr) + { + return static_cast< XSAXDocumentBuilder* >(new CSAXDocumentBuilder(rSMgr)); + } + + const char* CSAXDocumentBuilder::aImplementationName = "com.sun.star.comp.xml.dom.SAXDocumentBuilder"; + const char* CSAXDocumentBuilder::aSupportedServiceNames[] = { + "com.sun.star.xml.dom.SAXDocumentBuilder", + NULL + }; + + CSAXDocumentBuilder::CSAXDocumentBuilder(const Reference< XMultiServiceFactory >& mgr) + : m_aServiceManager(mgr) + , m_aState( SAXDocumentBuilderState_READY) + {} + + OUString CSAXDocumentBuilder::_getImplementationName() + { + return OUString::createFromAscii(aImplementationName); + } + Sequence<OUString> CSAXDocumentBuilder::_getSupportedServiceNames() + { + Sequence<OUString> aSequence; + for (int i=0; aSupportedServiceNames[i]!=NULL; i++) { + aSequence.realloc(i+1); + aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i])); + } + return aSequence; + } + + Sequence< OUString > SAL_CALL CSAXDocumentBuilder::getSupportedServiceNames() + throw (RuntimeException) + { + return CSAXDocumentBuilder::_getSupportedServiceNames(); + } + + OUString SAL_CALL CSAXDocumentBuilder::getImplementationName() + throw (RuntimeException) + { + return CSAXDocumentBuilder::_getImplementationName(); + } + + sal_Bool SAL_CALL CSAXDocumentBuilder::supportsService(const OUString& aServiceName) + throw (RuntimeException) + { + Sequence< OUString > supported = CSAXDocumentBuilder::_getSupportedServiceNames(); + for (sal_Int32 i=0; i<supported.getLength(); i++) + { + if (supported[i] == aServiceName) return sal_True; + } + return sal_False; + } + + + SAXDocumentBuilderState SAL_CALL CSAXDocumentBuilder::getState() + throw (RuntimeException) + { + ::osl::MutexGuard g(m_Mutex); + + return m_aState; + } + + void SAL_CALL CSAXDocumentBuilder::reset() + throw (RuntimeException) + { + ::osl::MutexGuard g(m_Mutex); + + m_aDocument = Reference< XDocument >(); + m_aFragment = Reference< XDocumentFragment >(); + while (!m_aNodeStack.empty()) m_aNodeStack.pop(); + while (!m_aNSStack.empty()) m_aNSStack.pop(); + m_aState = SAXDocumentBuilderState_READY; + } + + Reference< XDocument > SAL_CALL CSAXDocumentBuilder::getDocument() + throw (RuntimeException) + { + ::osl::MutexGuard g(m_Mutex); + + if (m_aState != SAXDocumentBuilderState_DOCUMENT_FINISHED) + throw RuntimeException(); + + return m_aDocument; + } + + Reference< XDocumentFragment > SAL_CALL CSAXDocumentBuilder::getDocumentFragment() + throw (RuntimeException) + { + ::osl::MutexGuard g(m_Mutex); + + if (m_aState != SAXDocumentBuilderState_FRAGMENT_FINISHED) + throw RuntimeException(); + return m_aFragment; + } + + void SAL_CALL CSAXDocumentBuilder::startDocumentFragment(const Reference< XDocument >& ownerDoc) + throw (RuntimeException) + { + ::osl::MutexGuard g(m_Mutex); + + // start a new document fragment and push it onto the stack + // we have to be in a clean state to do this + if (!m_aState == SAXDocumentBuilderState_READY) + throw RuntimeException(); + + m_aDocument = ownerDoc; + Reference< XDocumentFragment > aFragment = m_aDocument->createDocumentFragment(); + m_aNodeStack.push(Reference< XNode >(aFragment, UNO_QUERY)); + m_aFragment = aFragment; + m_aState = SAXDocumentBuilderState_BUILDING_FRAGMENT; + } + + void SAL_CALL CSAXDocumentBuilder::endDocumentFragment() + throw (RuntimeException) + { + ::osl::MutexGuard g(m_Mutex); + + // there should only be the document left on the node stack + if (m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) + throw RuntimeException(); + + Reference< XNode > aNode = m_aNodeStack.top(); + if ( aNode->getNodeType() != NodeType_DOCUMENT_FRAGMENT_NODE) + throw RuntimeException(); + m_aNodeStack.pop(); + m_aState = SAXDocumentBuilderState_FRAGMENT_FINISHED; + } + + // document handler + + void SAL_CALL CSAXDocumentBuilder::startDocument() throw (RuntimeException, SAXException) + { + ::osl::MutexGuard g(m_Mutex); + + // start a new document and push it onto the stack + // we have to be in a clean state to do this + if (!m_aState == SAXDocumentBuilderState_READY) + throw SAXException(); + + Reference< XDocumentBuilder > aBuilder(m_aServiceManager->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder"))), UNO_QUERY_THROW); + Reference< XDocument > aDocument = aBuilder->newDocument(); + m_aNodeStack.push(Reference< XNode >(aDocument, UNO_QUERY)); + m_aDocument = aDocument; + m_aState = SAXDocumentBuilderState_BUILDING_DOCUMENT; + } + + void SAL_CALL CSAXDocumentBuilder::endDocument() throw (RuntimeException, SAXException) + { + ::osl::MutexGuard g(m_Mutex); + + // there should only be the document left on the node stack + if (!m_aState == SAXDocumentBuilderState_BUILDING_DOCUMENT) + throw SAXException(); + + Reference< XNode > aNode = m_aNodeStack.top(); + if ( aNode->getNodeType() != NodeType_DOCUMENT_NODE) + throw SAXException(); + m_aNodeStack.pop(); + m_aState = SAXDocumentBuilderState_DOCUMENT_FINISHED; + } + + void SAL_CALL CSAXDocumentBuilder::startElement(const OUString& aName, const Reference< XAttributeList>& attribs) + throw (RuntimeException, SAXException) + { + ::osl::MutexGuard g(m_Mutex); + + if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && + m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) + { + throw SAXException(); + } + + // start with mappings in effect for last level + NSMap aNSMap; + if (!m_aNSStack.empty()) + aNSMap = NSMap(m_aNSStack.top()); + + // handle xmlns: attributes and add to mappings + OUString attr_qname; + OUString attr_value; + OUString newprefix; + AttrMap aAttrMap; + sal_Int32 idx=-1; + sal_Int16 nAttributes = attribs->getLength(); + for (sal_Int16 i=0; i<nAttributes; i++) + { + attr_qname = attribs->getNameByIndex(i); + attr_value = attribs->getValueByIndex(i); + // new prefix mapping + if (attr_qname.indexOf(OUString(RTL_CONSTASCII_USTRINGPARAM("xmlns:"))) == 0) + { + newprefix = attr_qname.copy(attr_qname.indexOf(':')+1); + aNSMap.insert(NSMap::value_type(newprefix, attr_value)); + } + else if (attr_qname == OUString(RTL_CONSTASCII_USTRINGPARAM("xmlns"))) + { + // new default prefix + aNSMap.insert(NSMap::value_type(OUString(), attr_value)); + } + else + { + aAttrMap.insert(AttrMap::value_type(attr_qname, attr_value)); + } + } + + // does the element have a prefix? + OUString aPrefix; + OUString aURI; + Reference< XElement > aElement; + idx = aName.indexOf(':'); + if (idx != -1) + { + aPrefix = aName.copy(0, idx); + } + else + aPrefix = OUString(); + + NSMap::const_iterator result = aNSMap.find(aPrefix); + if ( result != aNSMap.end()) + { + // found a URI for prefix + // qualified name + aElement = m_aDocument->createElementNS( result->second, aName); + } + else + { + // no URI for prefix + aElement = m_aDocument->createElement(aName); + } + aElement = Reference< XElement > ( + m_aNodeStack.top()->appendChild(Reference< XNode >(aElement, UNO_QUERY)), + UNO_QUERY); + m_aNodeStack.push(Reference< XNode >(aElement, UNO_QUERY)); + + // set non xmlns attributes + aPrefix = OUString(); + aURI = OUString(); + AttrMap::const_iterator a = aAttrMap.begin(); + while (a != aAttrMap.end()) + { + attr_qname = a->first; + attr_value = a->second; + idx = attr_qname.indexOf(':'); + if (idx != -1) + aPrefix = attr_qname.copy(0, idx); + else + aPrefix = OUString(); + + result = aNSMap.find(aPrefix); + if (result != aNSMap.end()) + { + // set attribute with namespace + aElement->setAttributeNS(result->second, attr_qname, attr_value); + } + else + { + // set attribute without namespace + aElement->setAttribute(attr_qname, attr_value); + } + ++a; + } + m_aNSStack.push(aNSMap); + } + + void SAL_CALL CSAXDocumentBuilder::endElement(const OUString& aName) + throw (RuntimeException, SAXException) + { + ::osl::MutexGuard g(m_Mutex); + + // pop the current element from the stack + if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && + m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) + throw SAXException(); + + Reference< XNode > aNode(m_aNodeStack.top()); + if (aNode->getNodeType() != NodeType_ELEMENT_NODE) + throw SAXException(); + + Reference< XElement > aElement(aNode, UNO_QUERY); + OUString aRefName; + OUString aPrefix = aElement->getPrefix(); + if (aPrefix.getLength() > 0) + aRefName = aPrefix + OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + aElement->getTagName(); + else + aRefName = aElement->getTagName(); + if (aRefName != aName) // consistency check + throw SAXException(); + + // pop it + m_aNodeStack.pop(); + m_aNSStack.pop(); + } + + void SAL_CALL CSAXDocumentBuilder::characters(const OUString& aChars) + throw (RuntimeException, SAXException) + { + ::osl::MutexGuard g(m_Mutex); + + // append text node to the current top element + if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && + m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) + throw SAXException(); + + Reference< XText > aText = m_aDocument->createTextNode(aChars); + m_aNodeStack.top()->appendChild(Reference< XNode >(aText, UNO_QUERY)); + } + + void SAL_CALL CSAXDocumentBuilder::ignorableWhitespace(const OUString& ) + throw (RuntimeException, SAXException) + { + ::osl::MutexGuard g(m_Mutex); + + // ignore ignorable whitespace + if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && + m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) + throw SAXException(); + } + + void SAL_CALL CSAXDocumentBuilder::processingInstruction(const OUString& aTarget, const OUString& aData) + throw (RuntimeException, SAXException) + { + ::osl::MutexGuard g(m_Mutex); + + // append PI node to the current top + if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && + m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) + throw SAXException(); + + Reference< XProcessingInstruction > aInstruction = m_aDocument->createProcessingInstruction( + aTarget, aData); + m_aNodeStack.top()->appendChild(Reference< XNode >(aInstruction, UNO_QUERY)); + } + + void SAL_CALL CSAXDocumentBuilder::setDocumentLocator(const Reference< XLocator >& aLocator) + throw (RuntimeException, SAXException) + { + ::osl::MutexGuard g(m_Mutex); + + // set the document locator... + m_aLocator = aLocator; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/saxbuilder.hxx b/unoxml/source/dom/saxbuilder.hxx new file mode 100644 index 000000000000..7c46b2eed2fb --- /dev/null +++ b/unoxml/source/dom/saxbuilder.hxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_SAXBUILDER_HXX +#define DOM_SAXBUILDER_HXX + +#include <stack> +#include <map> + +#include <sal/types.h> +#include <osl/mutex.hxx> +#include <cppuhelper/implbase3.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Sequence.h> + +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/xml/dom/XSAXDocumentBuilder.hpp> +#include <com/sun/star/xml/dom/SAXDocumentBuilderState.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XLocator.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::sax; + +using com::sun::star::lang::XServiceInfo; +using com::sun::star::lang::XSingleServiceFactory; +using com::sun::star::lang::XMultiServiceFactory; + +namespace DOM +{ + + typedef std::stack< Reference< XNode > > NodeStack; + typedef std::map< OUString, OUString > NSMap; + typedef std::map< OUString, OUString > AttrMap; + typedef std::stack< NSMap > NSStack; + + class CSAXDocumentBuilder + : public ::cppu::WeakImplHelper3< XDocumentHandler, XSAXDocumentBuilder, XServiceInfo > + { + + private: + ::osl::Mutex m_Mutex; + const Reference< XMultiServiceFactory > m_aServiceManager; + + SAXDocumentBuilderState m_aState; + NodeStack m_aNodeStack; + NSStack m_aNSStack; + + OUString resolvePrefix(const OUString& aPrefix); + + Reference< XDocument > m_aDocument; + Reference< XDocumentFragment > m_aFragment; + Reference< XLocator > m_aLocator; + + + public: + + // call for factory + static Reference< XInterface > getInstance(const Reference < XMultiServiceFactory >& xFactory); + + // static helpers for service info and component management + static const char* aImplementationName; + static const char* aSupportedServiceNames[]; + static OUString _getImplementationName(); + static Sequence< OUString > _getSupportedServiceNames(); + static Reference< XInterface > _getInstance(const Reference< XMultiServiceFactory >& rSMgr); + + CSAXDocumentBuilder(const Reference< XMultiServiceFactory >& mgr); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames () + throw (RuntimeException); + + // XDocumentHandler + virtual void SAL_CALL startDocument() + throw( RuntimeException, com::sun::star::xml::sax::SAXException ); + virtual void SAL_CALL endDocument() + throw( RuntimeException, com::sun::star::xml::sax::SAXException ); + virtual void SAL_CALL startElement( const OUString& aName, + const Reference< XAttributeList >& xAttribs ) + throw( RuntimeException, com::sun::star::xml::sax::SAXException ); + virtual void SAL_CALL endElement( const OUString& aName ) + throw( RuntimeException, com::sun::star::xml::sax::SAXException ); + virtual void SAL_CALL characters( const OUString& aChars ) + throw( RuntimeException, com::sun::star::xml::sax::SAXException ); + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) + throw( RuntimeException, com::sun::star::xml::sax::SAXException ); + virtual void SAL_CALL processingInstruction( const OUString& aTarget, + const OUString& aData ) + throw( RuntimeException, com::sun::star::xml::sax::SAXException ); + virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator ) + throw( RuntimeException, com::sun::star::xml::sax::SAXException ); + + + // XSAXDocumentBuilder + virtual SAXDocumentBuilderState SAL_CALL getState() + throw (RuntimeException); + virtual void SAL_CALL reset() + throw (RuntimeException); + virtual Reference< XDocument > SAL_CALL getDocument() + throw (RuntimeException); + virtual Reference< XDocumentFragment > SAL_CALL getDocumentFragment() + throw (RuntimeException); + virtual void SAL_CALL startDocumentFragment(const Reference< XDocument >& ownerDoc) + throw (RuntimeException); + virtual void SAL_CALL endDocumentFragment() + throw (RuntimeException); + + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/text.cxx b/unoxml/source/dom/text.cxx new file mode 100644 index 000000000000..198afcb34e3a --- /dev/null +++ b/unoxml/source/dom/text.cxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <text.hxx> + + +namespace DOM +{ + CText::CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : CText_Base(rDocument, rMutex, reNodeType, rpNode) + { + } + + CText::CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CText_Base(rDocument, rMutex, NodeType_TEXT_NODE, pNode) + { + } + + void CText::saxify( + const Reference< XDocumentHandler >& i_xHandler) { + if (!i_xHandler.is()) throw RuntimeException(); + i_xHandler->characters(getData()); + } + + void CText::fastSaxify( Context& io_rContext ) + { + if (io_rContext.mxCurrentHandler.is()) + { + try + { + io_rContext.mxCurrentHandler->characters( getData() ); + } + catch( Exception& ) + {} + } + } + + OUString SAL_CALL CText::getNodeName() throw (RuntimeException) + { + return OUString(RTL_CONSTASCII_USTRINGPARAM("#text")); + } + + Reference< XText > SAL_CALL CText::splitText(sal_Int32 /*offset*/) + throw (RuntimeException) + { + OSL_FAIL("CText::splitText: not implemented (#i113683#)"); + return Reference< XText >(this); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/dom/text.hxx b/unoxml/source/dom/text.hxx new file mode 100644 index 000000000000..be86624b0a64 --- /dev/null +++ b/unoxml/source/dom/text.hxx @@ -0,0 +1,250 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 DOM_TEXT_HXX +#define DOM_TEXT_HXX + +#include <libxml/tree.h> + +#include <sal/types.h> + +#include <cppuhelper/implbase1.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XText.hpp> + +#include <characterdata.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; + +namespace DOM +{ + typedef ::cppu::ImplInheritanceHelper1< CCharacterData, XText > CText_Base; + + class CText + : public CText_Base + { + private: + friend class CDocument; + + protected: + CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); + + public: + + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + virtual void fastSaxify( Context& io_rContext ); + + // Breaks this node into two nodes at the specified offset, keeping + // both in the tree as siblings. + virtual Reference< XText > SAL_CALL splitText(sal_Int32 offset) + throw (RuntimeException); + + + // --- delegations for XCharacterData + virtual void SAL_CALL appendData(const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::appendData(arg); + } + virtual void SAL_CALL deleteData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException) + { + CCharacterData::deleteData(offset, count); + } + virtual OUString SAL_CALL getData() throw (RuntimeException) + { + return CCharacterData::getData(); + } + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException) + { + return CCharacterData::getLength(); + } + virtual void SAL_CALL insertData(sal_Int32 offset, const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::insertData(offset, arg); + } + virtual void SAL_CALL replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg) + throw (RuntimeException, DOMException) + { + CCharacterData::replaceData(offset, count, arg); + } + virtual void SAL_CALL setData(const OUString& data) + throw (RuntimeException, DOMException) + { + CCharacterData::setData(data); + } + virtual OUString SAL_CALL subStringData(sal_Int32 offset, sal_Int32 count) + throw (RuntimeException, DOMException) + { + return CCharacterData::subStringData(offset, count); + } + + + // --- overrides for XNode base + virtual OUString SAL_CALL getNodeName() + throw (RuntimeException); + + // --- resolve uno inheritance problems... + // --- delegation for XNde base. + virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + throw (RuntimeException, DOMException) + { + return CCharacterData::appendChild(newChild); + } + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException) + { + return CCharacterData::cloneNode(deep); + } + virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() + throw (RuntimeException) + { + return CCharacterData::getAttributes(); + } + virtual Reference< XNodeList > SAL_CALL getChildNodes() + throw (RuntimeException) + { + return CCharacterData::getChildNodes(); + } + virtual Reference< XNode > SAL_CALL getFirstChild() + throw (RuntimeException) + { + return CCharacterData::getFirstChild(); + } + virtual Reference< XNode > SAL_CALL getLastChild() + throw (RuntimeException) + { + return CCharacterData::getLastChild(); + } + virtual OUString SAL_CALL getLocalName() + throw (RuntimeException) + { + return CCharacterData::getLocalName(); + } + virtual OUString SAL_CALL getNamespaceURI() + throw (RuntimeException) + { + return CCharacterData::getNamespaceURI(); + } + virtual Reference< XNode > SAL_CALL getNextSibling() + throw (RuntimeException) + { + return CCharacterData::getNextSibling(); + } + virtual NodeType SAL_CALL getNodeType() + throw (RuntimeException) + { + return CCharacterData::getNodeType(); + } + virtual OUString SAL_CALL getNodeValue() throw (RuntimeException) + { + return CCharacterData::getNodeValue(); + } + virtual Reference< XDocument > SAL_CALL getOwnerDocument() + throw (RuntimeException) + { + return CCharacterData::getOwnerDocument(); + } + virtual Reference< XNode > SAL_CALL getParentNode() + throw (RuntimeException) + { + return CCharacterData::getParentNode(); + } + virtual OUString SAL_CALL getPrefix() + throw (RuntimeException) + { + return CCharacterData::getPrefix(); + } + virtual Reference< XNode > SAL_CALL getPreviousSibling() + throw (RuntimeException) + { + return CCharacterData::getPreviousSibling(); + } + virtual sal_Bool SAL_CALL hasAttributes() + throw (RuntimeException) + { + return CCharacterData::hasAttributes(); + } + virtual sal_Bool SAL_CALL hasChildNodes() + throw (RuntimeException) + { + return CCharacterData::hasChildNodes(); + } + virtual Reference< XNode > SAL_CALL insertBefore( + const Reference< XNode >& newChild, const Reference< XNode >& refChild) + throw (RuntimeException, DOMException) + { + return CCharacterData::insertBefore(newChild, refChild); + } + virtual sal_Bool SAL_CALL isSupported(const OUString& feature, const OUString& ver) + throw (RuntimeException) + { + return CCharacterData::isSupported(feature, ver); + } + virtual void SAL_CALL normalize() + throw (RuntimeException) + { + CCharacterData::normalize(); + } + virtual Reference< XNode > SAL_CALL removeChild(const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CCharacterData::removeChild(oldChild); + } + virtual Reference< XNode > SAL_CALL replaceChild( + const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + throw (RuntimeException, DOMException) + { + return CCharacterData::replaceChild(newChild, oldChild); + } + virtual void SAL_CALL setNodeValue(const OUString& nodeValue) + throw (RuntimeException, DOMException) + { + return CCharacterData::setNodeValue(nodeValue); + } + virtual void SAL_CALL setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + return CCharacterData::setPrefix(prefix); + } + + }; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/event.cxx b/unoxml/source/events/event.cxx new file mode 100644 index 000000000000..b674156a9560 --- /dev/null +++ b/unoxml/source/events/event.cxx @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <event.hxx> + +namespace DOM { namespace events +{ + + CEvent::CEvent() + : m_canceled(sal_False) + , m_phase(PhaseType_CAPTURING_PHASE) + , m_bubbles(sal_False) + , m_cancelable(sal_True) + { + } + + CEvent::~CEvent() + { + } + + OUString SAL_CALL CEvent::getType() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_eventType; + } + + Reference< XEventTarget > SAL_CALL + CEvent::getTarget() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_target; + } + + Reference< XEventTarget > SAL_CALL + CEvent::getCurrentTarget() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_currentTarget; + } + + PhaseType SAL_CALL CEvent::getEventPhase() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_phase; + } + + sal_Bool SAL_CALL CEvent::getBubbles() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_bubbles; + } + + sal_Bool SAL_CALL CEvent::getCancelable() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_cancelable; + } + + com::sun::star::util::Time SAL_CALL + CEvent::getTimeStamp() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_time; + } + + void SAL_CALL CEvent::stopPropagation() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + if (m_cancelable) { m_canceled = sal_True; } + } + + void SAL_CALL CEvent::preventDefault() throw (RuntimeException) + { + } + + void SAL_CALL + CEvent::initEvent(OUString const& eventTypeArg, sal_Bool canBubbleArg, + sal_Bool cancelableArg) throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + m_eventType = eventTypeArg; + m_bubbles = canBubbleArg; + m_cancelable = cancelableArg; + } + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/event.hxx b/unoxml/source/events/event.hxx new file mode 100644 index 000000000000..719880bac13d --- /dev/null +++ b/unoxml/source/events/event.hxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 EVENT_EVENT_HXX +#define EVENT_EVENT_HXX + +#include <sal/types.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/events/XEvent.hpp> +#include <com/sun/star/xml/dom/events/XEventTarget.hpp> +#include <com/sun/star/util/Time.hpp> + +#include <cppuhelper/implbase1.hxx> + +#include "../dom/node.hxx" + + +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::dom::events; + + +namespace DOM {namespace events +{ +class CEvent : public cppu::WeakImplHelper1< XEvent > +{ +friend class CEventDispatcher; + +protected: + ::osl::Mutex m_Mutex; + sal_Bool m_canceled; + OUString m_eventType; + Reference< XEventTarget > m_target; + Reference< XEventTarget > m_currentTarget; + PhaseType m_phase; + sal_Bool m_bubbles; + sal_Bool m_cancelable; + com::sun::star::util::Time m_time; + +public: + + explicit CEvent(); + + virtual ~CEvent(); + virtual OUString SAL_CALL getType() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getTarget() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getCurrentTarget() throw (RuntimeException); + virtual PhaseType SAL_CALL getEventPhase() throw (RuntimeException); + virtual sal_Bool SAL_CALL getBubbles() throw (RuntimeException); + virtual sal_Bool SAL_CALL getCancelable() throw (RuntimeException); + virtual com::sun::star::util::Time SAL_CALL getTimeStamp() throw (RuntimeException); + virtual void SAL_CALL stopPropagation() throw (RuntimeException); + virtual void SAL_CALL preventDefault() throw (RuntimeException); + virtual void SAL_CALL initEvent( + const OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) throw (RuntimeException); +}; +}} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/eventdispatcher.cxx b/unoxml/source/events/eventdispatcher.cxx new file mode 100644 index 000000000000..be45adb09dce --- /dev/null +++ b/unoxml/source/events/eventdispatcher.cxx @@ -0,0 +1,246 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <eventdispatcher.hxx> + +#include <event.hxx> +#include <mutationevent.hxx> +#include <uievent.hxx> +#include <mouseevent.hxx> + +#include "../dom/document.hxx" + + +namespace DOM { namespace events { + + void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture) + { + TypeListenerMap *const pTMap = (bCapture) + ? (& m_CaptureListeners) : (& m_TargetListeners); + + // get the multimap for the specified type + ListenerMap *pMap = 0; + TypeListenerMap::const_iterator tIter = pTMap->find(aType); + if (tIter == pTMap->end()) { + // the map has to be created + pMap = new ListenerMap(); + pTMap->insert(TypeListenerMap::value_type(aType, pMap)); + } else { + pMap = tIter->second; + } + if (pMap !=0) + pMap->insert(ListenerMap::value_type(pNode, aListener)); + } + + void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture) + { + TypeListenerMap *const pTMap = (bCapture) + ? (& m_CaptureListeners) : (& m_TargetListeners); + + // get the multimap for the specified type + TypeListenerMap::const_iterator tIter = pTMap->find(aType); + if (tIter != pTMap->end()) { + ListenerMap *pMap = tIter->second; + // find listeners of specied type for specified node + ListenerMap::iterator iter = pMap->find(pNode); + while (iter != pMap->end() && iter->first == pNode) + { + // erase all references to specified listener + if ((iter->second).is() && iter->second == aListener) + { + ListenerMap::iterator tmp_iter = iter; + ++iter; + pMap->erase(tmp_iter); + } + else + ++iter; + } + } + } + + void CEventDispatcher::callListeners( + TypeListenerMap const& rTMap, + xmlNodePtr const pNode, + OUString aType, Reference< XEvent > const& xEvent) + { + // get the multimap for the specified type + TypeListenerMap::const_iterator tIter = rTMap.find(aType); + if (tIter != rTMap.end()) { + ListenerMap *pMap = tIter->second; + ListenerMap::const_iterator iter = pMap->lower_bound(pNode); + ListenerMap::const_iterator ibound = pMap->upper_bound(pNode); + for( ; iter != ibound; ++iter ) + { + if((iter->second).is()) + (iter->second)->handleEvent(xEvent); + } + } + } + + bool CEventDispatcher::dispatchEvent( + DOM::CDocument & rDocument, ::osl::Mutex & rMutex, + xmlNodePtr const pNode, Reference<XNode> const& xNode, + Reference< XEvent > const& i_xEvent) const + { + CEvent *pEvent = 0; // pointer to internal event representation + + OUString const aType = i_xEvent->getType(); + if (aType.compareToAscii("DOMSubtreeModified") == 0|| + aType.compareToAscii("DOMNodeInserted") == 0|| + aType.compareToAscii("DOMNodeRemoved") == 0|| + aType.compareToAscii("DOMNodeRemovedFromDocument") == 0|| + aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0|| + aType.compareToAscii("DOMAttrModified") == 0|| + aType.compareToAscii("DOMCharacterDataModified") == 0) + { + Reference< XMutationEvent > const aMEvent(i_xEvent, + UNO_QUERY_THROW); + // dispatch a mutation event + // we need to clone the event in order to have complete control + // over the implementation + CMutationEvent* pMEvent = new CMutationEvent; + pMEvent->initMutationEvent( + aType, aMEvent->getBubbles(), aMEvent->getCancelable(), + aMEvent->getRelatedNode(), aMEvent->getPrevValue(), + aMEvent->getNewValue(), aMEvent->getAttrName(), + aMEvent->getAttrChange()); + pEvent = pMEvent; + } else if ( // UIEvent + aType.compareToAscii("DOMFocusIn") == 0|| + aType.compareToAscii("DOMFocusOut") == 0|| + aType.compareToAscii("DOMActivate") == 0) + { + Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW); + CUIEvent* pUIEvent = new CUIEvent; + pUIEvent->initUIEvent(aType, + aUIEvent->getBubbles(), aUIEvent->getCancelable(), + aUIEvent->getView(), aUIEvent->getDetail()); + pEvent = pUIEvent; + } else if ( // MouseEvent + aType.compareToAscii("click") == 0|| + aType.compareToAscii("mousedown") == 0|| + aType.compareToAscii("mouseup") == 0|| + aType.compareToAscii("mouseover") == 0|| + aType.compareToAscii("mousemove") == 0|| + aType.compareToAscii("mouseout") == 0) + { + Reference< XMouseEvent > const aMouseEvent(i_xEvent, + UNO_QUERY_THROW); + CMouseEvent *pMouseEvent = new CMouseEvent; + pMouseEvent->initMouseEvent(aType, + aMouseEvent->getBubbles(), aMouseEvent->getCancelable(), + aMouseEvent->getView(), aMouseEvent->getDetail(), + aMouseEvent->getScreenX(), aMouseEvent->getScreenY(), + aMouseEvent->getClientX(), aMouseEvent->getClientY(), + aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(), + aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(), + aMouseEvent->getButton(), aMouseEvent->getRelatedTarget()); + pEvent = pMouseEvent; + } + else // generic event + { + pEvent = new CEvent; + pEvent->initEvent( + aType, i_xEvent->getBubbles(), i_xEvent->getCancelable()); + } + pEvent->m_target.set(xNode, UNO_QUERY_THROW); + pEvent->m_currentTarget = i_xEvent->getCurrentTarget(); + pEvent->m_time = i_xEvent->getTimeStamp(); + + // create the reference to the provate event implementation + // that will be dispatched to the listeners + Reference< XEvent > const xEvent(pEvent); + + // build the path from target node to the root + typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> > + NodeVector_t; + NodeVector_t captureVector; + TypeListenerMap captureListeners; + TypeListenerMap targetListeners; + { + ::osl::MutexGuard g(rMutex); + + xmlNodePtr cur = pNode; + while (cur != NULL) + { + Reference< XEventTarget > const xRef( + rDocument.GetCNode(cur).get()); + captureVector.push_back(::std::make_pair(xRef, cur)); + cur = cur->parent; + } + captureListeners = m_CaptureListeners; + targetListeners = m_TargetListeners; + } + + // the caputre vector now holds the node path from target to root + // first we must search for capture listernes in order root to + // to target. after that, any target listeners have to be called + // then bubbeling phase listeners are called in target to root + // order + // start at the root + NodeVector_t::const_reverse_iterator rinode = + const_cast<NodeVector_t const&>(captureVector).rbegin(); + if (rinode != const_cast<NodeVector_t const&>(captureVector).rend()) + { + // capturing phase: + pEvent->m_phase = PhaseType_CAPTURING_PHASE; + while (rinode != + const_cast<NodeVector_t const&>(captureVector).rend()) + { + pEvent->m_currentTarget = rinode->first; + callListeners(captureListeners, rinode->second, aType, xEvent); + if (pEvent->m_canceled) return sal_True; + ++rinode; + } + + NodeVector_t::const_iterator inode = captureVector.begin(); + + // target phase + pEvent->m_phase = PhaseType_AT_TARGET; + pEvent->m_currentTarget = inode->first; + callListeners(targetListeners, inode->second, aType, xEvent); + if (pEvent->m_canceled) return sal_True; + // bubbeling phase + ++inode; + if (i_xEvent->getBubbles()) { + pEvent->m_phase = PhaseType_BUBBLING_PHASE; + while (inode != captureVector.end()) + { + pEvent->m_currentTarget = inode->first; + callListeners(targetListeners, + inode->second, aType, xEvent); + if (pEvent->m_canceled) return sal_True; + ++inode; + } + } + } + return sal_True; + } +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/eventdispatcher.hxx b/unoxml/source/events/eventdispatcher.hxx new file mode 100644 index 000000000000..9f007ff25066 --- /dev/null +++ b/unoxml/source/events/eventdispatcher.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 EVENT_EVENT_DISPATCHER_HXX +#define EVENT_EVENT_DISPATCHER_HXX + +#include <map> +#include <vector> + +#include <libxml/tree.h> + +#include <rtl/ustring.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/events/EventType.hpp> +#include <com/sun/star/xml/dom/events/PhaseType.hpp> +#include <com/sun/star/xml/dom/events/XEvent.hpp> + + +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::dom::events; + +namespace DOM { + +class CDocument; + +namespace events { + +typedef std::multimap< xmlNodePtr, Reference< com::sun::star::xml::dom::events::XEventListener> > ListenerMap; +typedef std::map< ::rtl::OUString, ListenerMap*> TypeListenerMap; +typedef std::vector<ListenerMap::value_type> ListenerPairVector; + +class CEventDispatcher +{ +private: + TypeListenerMap m_CaptureListeners; + TypeListenerMap m_TargetListeners; + +public: + void addListener( + xmlNodePtr pNode, + ::rtl::OUString aType, + const Reference<com::sun::star::xml::dom::events::XEventListener>& aListener, + sal_Bool bCapture); + + void removeListener( + xmlNodePtr pNode, + ::rtl::OUString aType, + const Reference<com::sun::star::xml::dom::events::XEventListener>& aListener, + sal_Bool bCapture); + + static void callListeners( + TypeListenerMap const& rTMap, + xmlNodePtr const pNode, + ::rtl::OUString aType, + const Reference< XEvent >& xEvent); + + bool dispatchEvent( + DOM::CDocument & rDocument, + ::osl::Mutex & rMutex, + xmlNodePtr const pNode, + Reference<XNode> const& xNode, + Reference< XEvent > const& xEvent) const; +}; + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/mouseevent.cxx b/unoxml/source/events/mouseevent.cxx new file mode 100644 index 000000000000..6e60df7fd669 --- /dev/null +++ b/unoxml/source/events/mouseevent.cxx @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <mouseevent.hxx> + +namespace DOM { namespace events +{ + CMouseEvent::CMouseEvent() + : CMouseEvent_Base() + , m_screenX(0) + , m_screenY(0) + , m_clientX(0) + , m_clientY(0) + , m_ctrlKey(sal_False) + , m_shiftKey(sal_False) + , m_altKey(sal_False) + , m_metaKey(sal_False) + , m_button(0) + { + } + + sal_Int32 SAL_CALL CMouseEvent::getScreenX() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_screenX; + } + sal_Int32 SAL_CALL CMouseEvent::getScreenY() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_screenY; + } + sal_Int32 SAL_CALL CMouseEvent::getClientX() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_clientX; + } + sal_Int32 SAL_CALL CMouseEvent::getClientY() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_clientY; + } + sal_Bool SAL_CALL CMouseEvent::getCtrlKey() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_ctrlKey; + } + sal_Bool SAL_CALL CMouseEvent::getShiftKey() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_shiftKey; + } + sal_Bool SAL_CALL CMouseEvent::getAltKey() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_altKey; + } + sal_Bool SAL_CALL CMouseEvent::getMetaKey() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_metaKey; + } + sal_Int16 SAL_CALL CMouseEvent::getButton() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_button; + } + Reference< XEventTarget > SAL_CALL CMouseEvent::getRelatedTarget() throw(RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_relatedTarget; + } + + void SAL_CALL CMouseEvent::initMouseEvent( + const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, + sal_Int32 detailArg, + sal_Int32 screenXArg, + sal_Int32 screenYArg, + sal_Int32 clientXArg, + sal_Int32 clientYArg, + sal_Bool ctrlKeyArg, + sal_Bool altKeyArg, + sal_Bool shiftKeyArg, + sal_Bool metaKeyArg, + sal_Int16 buttonArg, + const Reference< XEventTarget >& /*relatedTargetArg*/) + throw(RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + CUIEvent::initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); + m_screenX = screenXArg; + m_screenY = screenYArg; + m_clientX = clientXArg; + m_clientY = clientYArg; + m_ctrlKey = ctrlKeyArg; + m_altKey = altKeyArg; + m_shiftKey = shiftKeyArg; + m_metaKey = metaKeyArg; + m_button = buttonArg; + } + + // delegate to CUIEvent, since we are inheriting from CUIEvent and XUIEvent + Reference< XAbstractView > SAL_CALL CMouseEvent::getView() throw(RuntimeException) + { + return CUIEvent::getView(); + } + + sal_Int32 SAL_CALL CMouseEvent::getDetail() throw(RuntimeException) + { + return CUIEvent::getDetail(); + } + + void SAL_CALL CMouseEvent::initUIEvent(const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, + sal_Int32 detailArg) throw(RuntimeException) + { + CUIEvent::initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); + } + + OUString SAL_CALL CMouseEvent::getType() throw (RuntimeException) + { + return CUIEvent::getType(); + } + + Reference< XEventTarget > SAL_CALL CMouseEvent::getTarget() throw (RuntimeException) + { + return CUIEvent::getTarget(); + } + + Reference< XEventTarget > SAL_CALL CMouseEvent::getCurrentTarget() throw (RuntimeException) + { + return CUIEvent::getCurrentTarget(); + } + + PhaseType SAL_CALL CMouseEvent::getEventPhase() throw (RuntimeException) + { + return CUIEvent::getEventPhase(); + } + + sal_Bool SAL_CALL CMouseEvent::getBubbles() throw (RuntimeException) + { + return CEvent::getBubbles(); + } + + sal_Bool SAL_CALL CMouseEvent::getCancelable() throw (RuntimeException) + { + return CUIEvent::getCancelable(); + } + + com::sun::star::util::Time SAL_CALL CMouseEvent::getTimeStamp() throw (RuntimeException) + { + return CUIEvent::getTimeStamp(); + } + + void SAL_CALL CMouseEvent::stopPropagation() throw (RuntimeException) + { + CUIEvent::stopPropagation(); + } + + void SAL_CALL CMouseEvent::preventDefault() throw (RuntimeException) + { + CUIEvent::preventDefault(); + } + + void SAL_CALL CMouseEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + sal_Bool cancelableArg) throw (RuntimeException) + { + // base initializer + CUIEvent::initEvent(eventTypeArg, canBubbleArg, cancelableArg); + } +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/mouseevent.hxx b/unoxml/source/events/mouseevent.hxx new file mode 100644 index 000000000000..18090b381126 --- /dev/null +++ b/unoxml/source/events/mouseevent.hxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 EVENT_MOUSEEVENT_HXX +#define EVENT_MOUSEEVENT_HXX + +#include <com/sun/star/xml/dom/events/PhaseType.hpp> +#include <com/sun/star/xml/dom/events/XMouseEvent.hpp> + +#include <cppuhelper/implbase1.hxx> + +#include "uievent.hxx" + + +using ::rtl::OUString; + +namespace DOM { namespace events { + +typedef ::cppu::ImplInheritanceHelper1< CUIEvent, XMouseEvent > + CMouseEvent_Base; + +class CMouseEvent + : public CMouseEvent_Base +{ +protected: + sal_Int32 m_screenX; + sal_Int32 m_screenY; + sal_Int32 m_clientX; + sal_Int32 m_clientY; + sal_Bool m_ctrlKey; + sal_Bool m_shiftKey; + sal_Bool m_altKey; + sal_Bool m_metaKey; + sal_Int16 m_button; + Reference< XEventTarget > m_relatedTarget; + +public: + explicit CMouseEvent(); + + virtual sal_Int32 SAL_CALL getScreenX() throw (RuntimeException); + virtual sal_Int32 SAL_CALL getScreenY() throw (RuntimeException); + virtual sal_Int32 SAL_CALL getClientX() throw (RuntimeException); + virtual sal_Int32 SAL_CALL getClientY() throw (RuntimeException); + virtual sal_Bool SAL_CALL getCtrlKey() throw (RuntimeException); + virtual sal_Bool SAL_CALL getShiftKey() throw (RuntimeException); + virtual sal_Bool SAL_CALL getAltKey() throw (RuntimeException); + virtual sal_Bool SAL_CALL getMetaKey() throw (RuntimeException); + virtual sal_Int16 SAL_CALL getButton() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getRelatedTarget() throw(RuntimeException); + + virtual void SAL_CALL initMouseEvent( + const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, + sal_Int32 detailArg, + sal_Int32 screenXArg, + sal_Int32 screenYArg, + sal_Int32 clientXArg, + sal_Int32 clientYArg, + sal_Bool ctrlKeyArg, + sal_Bool altKeyArg, + sal_Bool shiftKeyArg, + sal_Bool metaKeyArg, + sal_Int16 buttonArg, + const Reference< XEventTarget >& relatedTargetArg) + throw(RuntimeException); + + // delegate to CUIevent + virtual Reference< XAbstractView > SAL_CALL getView() throw (RuntimeException); + virtual sal_Int32 SAL_CALL getDetail() throw (RuntimeException); + virtual void SAL_CALL initUIEvent(const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, + sal_Int32 detailArg) throw (RuntimeException); + virtual OUString SAL_CALL getType() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getTarget() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getCurrentTarget() throw (RuntimeException); + virtual PhaseType SAL_CALL getEventPhase() throw (RuntimeException); + virtual sal_Bool SAL_CALL getBubbles() throw (RuntimeException); + virtual sal_Bool SAL_CALL getCancelable() throw (RuntimeException); + virtual com::sun::star::util::Time SAL_CALL getTimeStamp() throw (RuntimeException); + virtual void SAL_CALL stopPropagation() throw (RuntimeException); + virtual void SAL_CALL preventDefault() throw (RuntimeException); + virtual void SAL_CALL initEvent( + const OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) + throw (RuntimeException); +}; +}} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/mutationevent.cxx b/unoxml/source/events/mutationevent.cxx new file mode 100644 index 000000000000..a0cf02107e1d --- /dev/null +++ b/unoxml/source/events/mutationevent.cxx @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <mutationevent.hxx> + +namespace DOM { namespace events +{ + CMutationEvent::CMutationEvent() + : CMutationEvent_Base() + , m_attrChangeType(AttrChangeType_MODIFICATION) + { + } + + CMutationEvent::~CMutationEvent() + { + } + + Reference< XNode > SAL_CALL CMutationEvent::getRelatedNode() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_relatedNode; + } + + OUString SAL_CALL CMutationEvent::getPrevValue() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_prevValue; + } + + OUString SAL_CALL CMutationEvent::getNewValue() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_newValue; + } + + OUString SAL_CALL CMutationEvent::getAttrName() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_attrName; + } + + AttrChangeType SAL_CALL CMutationEvent::getAttrChange() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_attrChangeType; + } + + void SAL_CALL CMutationEvent::initMutationEvent(const OUString& typeArg, + sal_Bool canBubbleArg, sal_Bool cancelableArg, + const Reference< XNode >& relatedNodeArg, const OUString& prevValueArg, + const OUString& newValueArg, const OUString& attrNameArg, + AttrChangeType attrChangeArg) throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + CEvent::initEvent(typeArg, canBubbleArg, cancelableArg); + m_relatedNode = relatedNodeArg; + m_prevValue = prevValueArg; + m_newValue = newValueArg; + m_attrName = attrNameArg; + m_attrChangeType = attrChangeArg; + } + + // delegate to CEvent, since we are inheriting from CEvent and XEvent + OUString SAL_CALL CMutationEvent::getType() throw (RuntimeException) + { + return CEvent::getType(); + } + + Reference< XEventTarget > SAL_CALL CMutationEvent::getTarget() throw (RuntimeException) + { + return CEvent::getTarget(); + } + + Reference< XEventTarget > SAL_CALL CMutationEvent::getCurrentTarget() throw (RuntimeException) + { + return CEvent::getCurrentTarget(); + } + + PhaseType SAL_CALL CMutationEvent::getEventPhase() throw (RuntimeException) + { + return CEvent::getEventPhase(); + } + + sal_Bool SAL_CALL CMutationEvent::getBubbles() throw (RuntimeException) + { + return CEvent::getBubbles(); + } + + sal_Bool SAL_CALL CMutationEvent::getCancelable() throw (RuntimeException) + { + return CEvent::getCancelable(); + } + + com::sun::star::util::Time SAL_CALL CMutationEvent::getTimeStamp() throw (RuntimeException) + { + return CEvent::getTimeStamp(); + } + + void SAL_CALL CMutationEvent::stopPropagation() throw (RuntimeException) + { + CEvent::stopPropagation(); + } + void SAL_CALL CMutationEvent::preventDefault() throw (RuntimeException) + { + CEvent::preventDefault(); + } + + void SAL_CALL CMutationEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + sal_Bool cancelableArg) throw (RuntimeException) + { + // base initializer + CEvent::initEvent(eventTypeArg, canBubbleArg, cancelableArg); + } +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/mutationevent.hxx b/unoxml/source/events/mutationevent.hxx new file mode 100644 index 000000000000..85a8117c17d4 --- /dev/null +++ b/unoxml/source/events/mutationevent.hxx @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 EVENT_MUTATIONEVENT_HXX +#define EVENT_MUTATIONEVENT_HXX + +#include <sal/types.h> + +#include <com/sun/star/uno/Reference.h> + +#include <com/sun/star/xml/dom/events/PhaseType.hpp> +#include <com/sun/star/xml/dom/events/AttrChangeType.hpp> +#include <com/sun/star/xml/dom/events/XMutationEvent.hpp> + +#include <cppuhelper/implbase1.hxx> + +#include "event.hxx" + + +using ::rtl::OUString; + +namespace DOM { namespace events { + +typedef ::cppu::ImplInheritanceHelper1< CEvent, XMutationEvent > + CMutationEvent_Base; + +class CMutationEvent + : public CMutationEvent_Base +{ +protected: + Reference< XNode > m_relatedNode; + OUString m_prevValue; + OUString m_newValue; + OUString m_attrName; + AttrChangeType m_attrChangeType; + +public: + explicit CMutationEvent(); + + virtual ~CMutationEvent(); + + virtual Reference< XNode > SAL_CALL getRelatedNode() throw (RuntimeException); + virtual OUString SAL_CALL getPrevValue() throw (RuntimeException); + virtual OUString SAL_CALL getNewValue() throw (RuntimeException); + virtual OUString SAL_CALL getAttrName() throw (RuntimeException); + virtual AttrChangeType SAL_CALL getAttrChange() throw (RuntimeException); + virtual void SAL_CALL initMutationEvent( + const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XNode >& relatedNodeArg, + const OUString& prevValueArg, + const OUString& newValueArg, + const OUString& attrNameArg, + AttrChangeType attrChangeArg) throw (RuntimeException); + + // delegate to CEvent, since we are inheriting from CEvent and XEvent + virtual OUString SAL_CALL getType() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getTarget() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getCurrentTarget() throw (RuntimeException); + virtual PhaseType SAL_CALL getEventPhase() throw (RuntimeException); + virtual sal_Bool SAL_CALL getBubbles() throw (RuntimeException); + virtual sal_Bool SAL_CALL getCancelable() throw (RuntimeException); + virtual com::sun::star::util::Time SAL_CALL getTimeStamp() throw (RuntimeException); + virtual void SAL_CALL stopPropagation() throw (RuntimeException); + virtual void SAL_CALL preventDefault() throw (RuntimeException); + virtual void SAL_CALL initEvent( + const OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) + throw (RuntimeException); +}; +}} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/testlistener.cxx b/unoxml/source/events/testlistener.cxx new file mode 100644 index 000000000000..0b29277158eb --- /dev/null +++ b/unoxml/source/events/testlistener.cxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdio.h> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include "testlistener.hxx" + +#define U2S(s) OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr() + + +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::lang::IllegalArgumentException; + + +namespace DOM { namespace events +{ + + Reference< XInterface > CTestListener::_getInstance(const Reference< XMultiServiceFactory >& rSMgr) + { + // XXX + // return static_cast< XXPathAPI* >(new CTestListener()); + return Reference< XInterface >(static_cast<XEventListener*>(new CTestListener(rSMgr))); + } + + const char* CTestListener::aImplementationName = "com.sun.star.comp.xml.dom.events.TestListener"; + const char* CTestListener::aSupportedServiceNames[] = { + "com.sun.star.comp.xml.dom.events.TestListener", + NULL + }; + + OUString CTestListener::_getImplementationName() + { + return OUString::createFromAscii(aImplementationName); + } + Sequence<OUString> CTestListener::_getSupportedServiceNames() + { + Sequence<OUString> aSequence; + for (int i=0; aSupportedServiceNames[i]!=NULL; i++) { + aSequence.realloc(i+1); + aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i])); + } + return aSequence; + } + + Sequence< OUString > SAL_CALL CTestListener::getSupportedServiceNames() + throw (RuntimeException) + { + return CTestListener::_getSupportedServiceNames(); + } + + OUString SAL_CALL CTestListener::getImplementationName() + throw (RuntimeException) + { + return CTestListener::_getImplementationName(); + } + + sal_Bool SAL_CALL CTestListener::supportsService(const OUString& aServiceName) + throw (RuntimeException) + { + Sequence< OUString > supported = CTestListener::_getSupportedServiceNames(); + for (sal_Int32 i=0; i<supported.getLength(); i++) + { + if (supported[i] == aServiceName) return sal_True; + } + return sal_False; + } + + // --- XInitialize + + void SAL_CALL CTestListener::initialize(const Sequence< Any >& args) throw(RuntimeException) + { + if (args.getLength() < 3) throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("Wrong number of arguments")), Reference< XInterface >(), 0); + + Reference <XEventTarget> aTarget; + if(! (args[0] >>= aTarget)) throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("Illegal argument 1")), Reference< XInterface >(), 1); + + OUString aType; + if (! (args[1] >>= aType)) + throw IllegalArgumentException(OUString(RTL_CONSTASCII_USTRINGPARAM("Illegal argument 2")), Reference< XInterface >(), 2); + + sal_Bool bCapture = sal_False; + if(! (args[2] >>= bCapture)) throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("Illegal argument 3")), Reference< XInterface >(), 3); + + if(! (args[3] >>= m_name)) m_name = OUString(RTL_CONSTASCII_USTRINGPARAM("<unnamed listener>")); + + m_target = aTarget; + m_type = aType; + m_capture = bCapture; + + m_target->addEventListener(m_type, Reference< XEventListener >(this), m_capture); + + + } + + CTestListener::~CTestListener() + { + fprintf(stderr, "CTestListener::~CTestListener()\n"); + if( m_target.is()) + m_target->removeEventListener(m_type, Reference< XEventListener >(this), m_capture); + } + + // --- XEventListener + + void SAL_CALL CTestListener::handleEvent(const Reference< XEvent >& evt) throw (RuntimeException) + { + FILE* f = fopen("C:\\listener.out", "a"); + fprintf(f, "CTestListener::handleEvent in %s\n", U2S(m_name)); + fprintf(f, " type: %s\n\n", OUStringToOString(evt->getType(), RTL_TEXTENCODING_ASCII_US).getStr()); + fclose(f); + + } + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/testlistener.hxx b/unoxml/source/events/testlistener.hxx new file mode 100644 index 000000000000..117fca9c32c5 --- /dev/null +++ b/unoxml/source/events/testlistener.hxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 EVENT_TESTLISTENER_HXX +#define EVENT_TESTLISTENER_HXX + +#include <sal/types.h> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Sequence.h> + +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/xml/dom/events/XEventTarget.hpp> +#include <com/sun/star/xml/dom/events/XEventListener.hpp> +#include <com/sun/star/xml/dom/events/XEvent.hpp> + +#include <cppuhelper/implbase3.hxx> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::dom::events; + +namespace DOM { namespace events +{ + + typedef ::cppu::WeakImplHelper3 + < ::com::sun::star::xml::dom::events::XEventListener + , ::com::sun::star::lang::XInitialization + , ::com::sun::star::lang::XServiceInfo + > CTestListener_Base; + + class CTestListener + : public CTestListener_Base + { + + private: + Reference< ::com::sun::star::lang::XMultiServiceFactory > m_factory; + Reference <XEventTarget> m_target; + OUString m_type; + sal_Bool m_capture; + OUString m_name; + + public: + + // static helpers for service info and component management + static const char* aImplementationName; + static const char* aSupportedServiceNames[]; + static OUString _getImplementationName(); + static Sequence< OUString > _getSupportedServiceNames(); + static Reference< XInterface > _getInstance( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); + + CTestListener( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr) + : m_factory(rSMgr){}; + + virtual ~CTestListener(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames () + throw (RuntimeException); + + + // XEventListener + virtual void SAL_CALL initialize(const Sequence< Any >& args) throw (RuntimeException); + + virtual void SAL_CALL handleEvent(const Reference< XEvent >& evt) throw (RuntimeException); + + + }; +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/uievent.cxx b/unoxml/source/events/uievent.cxx new file mode 100644 index 000000000000..0a87b20482ed --- /dev/null +++ b/unoxml/source/events/uievent.cxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <uievent.hxx> + +namespace DOM { namespace events +{ + CUIEvent::CUIEvent() + : CUIEvent_Base() + , m_detail(0) + { + } + + Reference< XAbstractView > SAL_CALL + CUIEvent::getView() throw(RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_view; + } + + sal_Int32 SAL_CALL CUIEvent::getDetail() throw(RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + return m_detail; + } + + void SAL_CALL CUIEvent::initUIEvent(const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, + sal_Int32 detailArg) throw(RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + CEvent::initEvent(typeArg, canBubbleArg, cancelableArg); + m_view = viewArg; + m_detail = detailArg; + } + + + // delegate to CEvent, since we are inheriting from CEvent and XEvent + OUString SAL_CALL CUIEvent::getType() throw (RuntimeException) + { + return CEvent::getType(); + } + + Reference< XEventTarget > SAL_CALL CUIEvent::getTarget() throw (RuntimeException) + { + return CEvent::getTarget(); + } + + Reference< XEventTarget > SAL_CALL CUIEvent::getCurrentTarget() throw (RuntimeException) + { + return CEvent::getCurrentTarget(); + } + + PhaseType SAL_CALL CUIEvent::getEventPhase() throw (RuntimeException) + { + return CEvent::getEventPhase(); + } + + sal_Bool SAL_CALL CUIEvent::getBubbles() throw (RuntimeException) + { + return CEvent::getBubbles(); + } + + sal_Bool SAL_CALL CUIEvent::getCancelable() throw (RuntimeException) + { + // mutation events cannot be canceled + return sal_False; + } + + com::sun::star::util::Time SAL_CALL CUIEvent::getTimeStamp() throw (RuntimeException) + { + return CEvent::getTimeStamp(); + } + + void SAL_CALL CUIEvent::stopPropagation() throw (RuntimeException) + { + CEvent::stopPropagation(); + } + void SAL_CALL CUIEvent::preventDefault() throw (RuntimeException) + { + CEvent::preventDefault(); + } + + void SAL_CALL CUIEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + sal_Bool cancelableArg) throw (RuntimeException) + { + // base initializer + CEvent::initEvent(eventTypeArg, canBubbleArg, cancelableArg); + } +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/events/uievent.hxx b/unoxml/source/events/uievent.hxx new file mode 100644 index 000000000000..5ddd90152372 --- /dev/null +++ b/unoxml/source/events/uievent.hxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 EVENT_UIEVENT_HXX +#define EVENT_UIEVENT_HXX + +#include <sal/types.h> + +#include <com/sun/star/xml/dom/events/PhaseType.hpp> +#include <com/sun/star/xml/dom/events/XUIEvent.hpp> +#include <com/sun/star/xml/dom/views/XAbstractView.hpp> + +#include <cppuhelper/implbase1.hxx> + +#include "event.hxx" + + +using ::rtl::OUString; +using namespace com::sun::star::xml::dom::views; + +namespace DOM { namespace events { + +typedef ::cppu::ImplInheritanceHelper1< CEvent, XUIEvent > CUIEvent_Base; + +class CUIEvent + : public CUIEvent_Base +{ +protected: + sal_Int32 m_detail; + Reference< XAbstractView > m_view; + +public: + explicit CUIEvent(); + + virtual Reference< XAbstractView > SAL_CALL getView() throw(RuntimeException); + virtual sal_Int32 SAL_CALL getDetail() throw(RuntimeException); + virtual void SAL_CALL initUIEvent(const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, + sal_Int32 detailArg) throw(RuntimeException); + + // delegate to CEvent, since we are inheriting from CEvent and XEvent + virtual OUString SAL_CALL getType() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getTarget() throw (RuntimeException); + virtual Reference< XEventTarget > SAL_CALL getCurrentTarget() throw (RuntimeException); + virtual PhaseType SAL_CALL getEventPhase() throw (RuntimeException); + virtual sal_Bool SAL_CALL getBubbles() throw (RuntimeException); + virtual sal_Bool SAL_CALL getCancelable() throw (RuntimeException); + virtual com::sun::star::util::Time SAL_CALL getTimeStamp() throw (RuntimeException); + virtual void SAL_CALL stopPropagation() throw (RuntimeException); + virtual void SAL_CALL preventDefault() throw (RuntimeException); + virtual void SAL_CALL initEvent( + const OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) + throw (RuntimeException); +}; +}} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/rdf/CBlankNode.cxx b/unoxml/source/rdf/CBlankNode.cxx new file mode 100644 index 000000000000..62d5978b3846 --- /dev/null +++ b/unoxml/source/rdf/CBlankNode.cxx @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "CNodes.hxx" + +#include <cppuhelper/implbase3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/rdf/XBlankNode.hpp> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + + +/// anonymous implementation namespace +namespace { + +namespace css = ::com::sun::star; + +class CBlankNode: + public ::cppu::WeakImplHelper3< + css::lang::XServiceInfo, + css::lang::XInitialization, + css::rdf::XBlankNode> +{ +public: + explicit CBlankNode(css::uno::Reference< css::uno::XComponentContext > const & context); + virtual ~CBlankNode() {} + + // ::com::sun::star::lang::XServiceInfo: + virtual ::rtl::OUString SAL_CALL getImplementationName() throw (css::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService(const ::rtl::OUString & ServiceName) throw (css::uno::RuntimeException); + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (css::uno::RuntimeException); + + // ::com::sun::star::lang::XInitialization: + virtual void SAL_CALL initialize(const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments) throw (css::uno::RuntimeException, css::uno::Exception); + + // ::com::sun::star::rdf::XNode: + virtual ::rtl::OUString SAL_CALL getStringValue() throw (css::uno::RuntimeException); + +private: + CBlankNode(const CBlankNode &); // not defined + CBlankNode& operator=(const CBlankNode &); // not defined + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + + ::rtl::OUString m_NodeID; +}; + +CBlankNode::CBlankNode(css::uno::Reference< css::uno::XComponentContext > const & context) : + m_xContext(context), m_NodeID() +{} + +// com.sun.star.uno.XServiceInfo: +::rtl::OUString SAL_CALL CBlankNode::getImplementationName() throw (css::uno::RuntimeException) +{ + return comp_CBlankNode::_getImplementationName(); +} + +::sal_Bool SAL_CALL CBlankNode::supportsService(::rtl::OUString const & serviceName) throw (css::uno::RuntimeException) +{ + css::uno::Sequence< ::rtl::OUString > serviceNames = comp_CBlankNode::_getSupportedServiceNames(); + for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + if (serviceNames[i] == serviceName) + return sal_True; + } + return sal_False; +} + +css::uno::Sequence< ::rtl::OUString > SAL_CALL CBlankNode::getSupportedServiceNames() throw (css::uno::RuntimeException) +{ + return comp_CBlankNode::_getSupportedServiceNames(); +} + +// ::com::sun::star::lang::XInitialization: +void SAL_CALL CBlankNode::initialize(const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments) throw (css::uno::RuntimeException, css::uno::Exception) +{ + if (aArguments.getLength() != 1) { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CBlankNode::initialize: " + "must give exactly 1 argument")), *this, 1); + } + + ::rtl::OUString arg; + if (!(aArguments[0] >>= arg)) { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CBlankNode::initialize: " + "argument must be string")), *this, 0); + } + + //FIXME: what is legal? + if (arg.getLength() > 0) { + m_NodeID = arg; + } else { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CBlankNode::initialize: " + "argument is not valid blank node ID")), *this, 0); + } +} + +// ::com::sun::star::rdf::XNode: +::rtl::OUString SAL_CALL CBlankNode::getStringValue() throw (css::uno::RuntimeException) +{ + return m_NodeID; +} + +} // closing anonymous implementation namespace + + + +// component helper namespace +namespace comp_CBlankNode { + +::rtl::OUString SAL_CALL _getImplementationName() { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "CBlankNode")); +} + +css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames() +{ + css::uno::Sequence< ::rtl::OUString > s(1); + s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.rdf.BlankNode")); + return s; +} + +css::uno::Reference< css::uno::XInterface > SAL_CALL _create( + const css::uno::Reference< css::uno::XComponentContext > & context) + SAL_THROW((css::uno::Exception)) +{ + return static_cast< ::cppu::OWeakObject * >(new CBlankNode(context)); +} + +} // closing component helper namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/rdf/CLiteral.cxx b/unoxml/source/rdf/CLiteral.cxx new file mode 100644 index 000000000000..549cee2146f4 --- /dev/null +++ b/unoxml/source/rdf/CLiteral.cxx @@ -0,0 +1,223 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "CNodes.hxx" + +#include <cppuhelper/implbase3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/rdf/XLiteral.hpp> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <rtl/ustrbuf.hxx> + + +/// anonymous implementation namespace +namespace { + +namespace css = ::com::sun::star; + +class CLiteral: + public ::cppu::WeakImplHelper3< + css::lang::XServiceInfo, + css::lang::XInitialization, + css::rdf::XLiteral> +{ +public: + explicit CLiteral(css::uno::Reference< css::uno::XComponentContext > const & context); + virtual ~CLiteral() {} + + // ::com::sun::star::lang::XServiceInfo: + virtual ::rtl::OUString SAL_CALL getImplementationName() throw (css::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService(const ::rtl::OUString & ServiceName) throw (css::uno::RuntimeException); + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (css::uno::RuntimeException); + + // ::com::sun::star::lang::XInitialization: + virtual void SAL_CALL initialize(const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments) throw (css::uno::RuntimeException, css::uno::Exception); + + // ::com::sun::star::rdf::XNode: + virtual ::rtl::OUString SAL_CALL getStringValue() throw (css::uno::RuntimeException); + + // ::com::sun::star::rdf::XLiteral: + virtual ::rtl::OUString SAL_CALL getValue() throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getLanguage() throw (css::uno::RuntimeException); + virtual css::uno::Reference< css::rdf::XURI > SAL_CALL getDatatype() throw (css::uno::RuntimeException); + +private: + CLiteral(const CLiteral &); // not defined + CLiteral& operator=(const CLiteral &); // not defined + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + + ::rtl::OUString m_Value; + ::rtl::OUString m_Language; + css::uno::Reference< css::rdf::XURI > m_xDatatype; +}; + +CLiteral::CLiteral(css::uno::Reference< css::uno::XComponentContext > const & context) : + m_xContext(context), m_Value(), m_Language(), m_xDatatype() +{} + +// com.sun.star.uno.XServiceInfo: +::rtl::OUString SAL_CALL CLiteral::getImplementationName() throw (css::uno::RuntimeException) +{ + return comp_CLiteral::_getImplementationName(); +} + +::sal_Bool SAL_CALL CLiteral::supportsService(::rtl::OUString const & serviceName) throw (css::uno::RuntimeException) +{ + css::uno::Sequence< ::rtl::OUString > serviceNames = comp_CLiteral::_getSupportedServiceNames(); + for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + if (serviceNames[i] == serviceName) + return sal_True; + } + return sal_False; +} + +css::uno::Sequence< ::rtl::OUString > SAL_CALL CLiteral::getSupportedServiceNames() throw (css::uno::RuntimeException) +{ + return comp_CLiteral::_getSupportedServiceNames(); +} + +// ::com::sun::star::lang::XInitialization: +void SAL_CALL CLiteral::initialize(const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments) throw (css::uno::RuntimeException, css::uno::Exception) +{ + const sal_Int32 len( aArguments.getLength() ); + if (len < 1 || len > 2) { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CLiteral::initialize: " + "must give 1 or 2 argument(s)")), *this, 2); + } + + ::rtl::OUString arg0; + if (!(aArguments[0] >>= arg0)) { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CLiteral::initialize: " + "argument must be string")), *this, 0); + } + //FIXME: what is legal? + if (true) { + m_Value = arg0; + } else { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CLiteral::initialize: " + "argument is not valid literal value")), *this, 0); + } + + if (len > 1) { + ::rtl::OUString arg1; + css::uno::Reference< css::rdf::XURI > xURI; + if ((aArguments[1] >>= arg1)) { + if (arg1.getLength() > 0) { + m_Language = arg1; + } else { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CLiteral::initialize: " + "argument is not valid language")), *this, 1); + } + } else if ((aArguments[1] >>= xURI)) { + if (xURI.is()) { + m_xDatatype = xURI; + } else { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CLiteral::initialize: " + "argument is null")), *this, 1); + } + } else { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CLiteral::initialize: " + "argument must be string or URI")), *this, 1); + } + } +} + +// ::com::sun::star::rdf::XNode: +::rtl::OUString SAL_CALL CLiteral::getStringValue() throw (css::uno::RuntimeException) +{ + if (m_Language.getLength()) { + ::rtl::OUStringBuffer buf(m_Value); + buf.appendAscii("@"); + buf.append(m_Language); + return buf.makeStringAndClear(); + } else if (m_xDatatype.is()) { + ::rtl::OUStringBuffer buf(m_Value); + buf.appendAscii("^^"); + buf.append(m_xDatatype->getStringValue()); + return buf.makeStringAndClear(); + } else { + return m_Value; + } +} + +// ::com::sun::star::rdf::XLiteral: +::rtl::OUString SAL_CALL CLiteral::getValue() throw (css::uno::RuntimeException) +{ + return m_Value; +} + +::rtl::OUString SAL_CALL CLiteral::getLanguage() throw (css::uno::RuntimeException) +{ + return m_Language; +} + +css::uno::Reference< css::rdf::XURI > SAL_CALL CLiteral::getDatatype() throw (css::uno::RuntimeException) +{ + return m_xDatatype; +} + +} // closing anonymous implementation namespace + + + +// component helper namespace +namespace comp_CLiteral { + +::rtl::OUString SAL_CALL _getImplementationName() { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "CLiteral")); +} + +css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames() +{ + css::uno::Sequence< ::rtl::OUString > s(1); + s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.rdf.Literal")); + return s; +} + +css::uno::Reference< css::uno::XInterface > SAL_CALL _create( + const css::uno::Reference< css::uno::XComponentContext > & context) + SAL_THROW((css::uno::Exception)) +{ + return static_cast< ::cppu::OWeakObject * >(new CLiteral(context)); +} + +} // closing component helper namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/rdf/CNodes.hxx b/unoxml/source/rdf/CNodes.hxx new file mode 100644 index 000000000000..46e8daa3eb89 --- /dev/null +++ b/unoxml/source/rdf/CNodes.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _CNODES_HXX +#define _CNODES_HXX + +#include <sal/config.h> +#include <cppuhelper/factory.hxx> + + +// component helper namespace +namespace comp_CBlankNode { + +namespace css = ::com::sun::star; + +// component and service helper functions: +::rtl::OUString SAL_CALL _getImplementationName(); +css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames(); +css::uno::Reference< css::uno::XInterface > SAL_CALL _create( css::uno::Reference< css::uno::XComponentContext > const & context ); + +} // closing component helper namespace + + +// component helper namespace +namespace comp_CURI { + +namespace css = ::com::sun::star; + +// component and service helper functions: +::rtl::OUString SAL_CALL _getImplementationName(); +css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames(); +css::uno::Reference< css::uno::XInterface > SAL_CALL _create( css::uno::Reference< css::uno::XComponentContext > const & context ); + +} // closing component helper namespace + + +// component helper namespace +namespace comp_CLiteral { + +namespace css = ::com::sun::star; + +// component and service helper functions: +::rtl::OUString SAL_CALL _getImplementationName(); +css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames(); +css::uno::Reference< css::uno::XInterface > SAL_CALL _create( css::uno::Reference< css::uno::XComponentContext > const & context ); + +} // closing component helper namespace + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/rdf/CURI.cxx b/unoxml/source/rdf/CURI.cxx new file mode 100644 index 000000000000..414267ffe795 --- /dev/null +++ b/unoxml/source/rdf/CURI.cxx @@ -0,0 +1,869 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "CNodes.hxx" + +#include <cppuhelper/implbase3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/rdf/XURI.hpp> +#include <com/sun/star/rdf/URIs.hpp> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + + +/// anonymous implementation namespace +namespace { + +namespace css = ::com::sun::star; + +class CURI: + public ::cppu::WeakImplHelper3< + css::lang::XServiceInfo, + css::lang::XInitialization, + css::rdf::XURI> +{ +public: + explicit CURI(css::uno::Reference< css::uno::XComponentContext > const & context); + virtual ~CURI() {} + + // ::com::sun::star::lang::XServiceInfo: + virtual ::rtl::OUString SAL_CALL getImplementationName() throw (css::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService(const ::rtl::OUString & ServiceName) throw (css::uno::RuntimeException); + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (css::uno::RuntimeException); + + // ::com::sun::star::lang::XInitialization: + virtual void SAL_CALL initialize(const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments) throw (css::uno::RuntimeException, css::uno::Exception); + + // ::com::sun::star::rdf::XNode: + virtual ::rtl::OUString SAL_CALL getStringValue() throw (css::uno::RuntimeException); + + // ::com::sun::star::rdf::XURI: + virtual ::rtl::OUString SAL_CALL getLocalName() throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getNamespace() throw (css::uno::RuntimeException); + +private: + CURI(const CURI &); // not defined + CURI& operator=(const CURI &); // not defined + + /// handle css.rdf.URIs + void SAL_CALL initFromConstant(const sal_Int16 i_Constant); + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + + ::rtl::OUString m_Namespace; + ::rtl::OUString m_LocalName; +}; + +CURI::CURI(css::uno::Reference< css::uno::XComponentContext > const & context) : + m_xContext(context), m_Namespace(), m_LocalName() +{} + +// com.sun.star.uno.XServiceInfo: +::rtl::OUString SAL_CALL CURI::getImplementationName() throw (css::uno::RuntimeException) +{ + return comp_CURI::_getImplementationName(); +} + +::sal_Bool SAL_CALL CURI::supportsService(::rtl::OUString const & serviceName) throw (css::uno::RuntimeException) +{ + css::uno::Sequence< ::rtl::OUString > serviceNames = comp_CURI::_getSupportedServiceNames(); + for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + if (serviceNames[i] == serviceName) + return sal_True; + } + return sal_False; +} + +css::uno::Sequence< ::rtl::OUString > SAL_CALL CURI::getSupportedServiceNames() throw (css::uno::RuntimeException) +{ + return comp_CURI::_getSupportedServiceNames(); +} + +const char s_nsXS [] = "http://www.w3.org/2001/XMLSchema#"; +const char s_nsXSD [] = "http://www.w3.org/2001/XMLSchema-datatypes#"; +const char s_nsRDF [] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; +const char s_nsRDFs [] = "http://www.w3.org/2000/01/rdf-schema#"; +const char s_nsOWL [] = "http://www.w3.org/2002/07/owl#"; +const char s_nsPkg [] = + "http://docs.oasis-open.org/ns/office/1.2/meta/pkg#"; +const char s_nsODF [] = + "http://docs.oasis-open.org/ns/office/1.2/meta/odf#"; + +void SAL_CALL CURI::initFromConstant(const sal_Int16 i_Constant) +{ + const char *ns(0); + const char *ln(0); + switch (i_Constant) + { + case css::rdf::URIs::XSD_NCNAME: + ns = s_nsXSD; + ln = "NCName"; + break; + + case css::rdf::URIs::XSD_STRING: + ns = s_nsXSD; + ln = "string"; + break; + + case css::rdf::URIs::XSD_NORMALIZEDSTRING: + ns = s_nsXSD; + ln = "normalizedString"; + break; + + case css::rdf::URIs::XSD_BOOLEAN: + ns = s_nsXSD; + ln = "boolean"; + break; + + case css::rdf::URIs::XSD_DECIMAL: + ns = s_nsXSD; + ln = "decimal"; + break; + + case css::rdf::URIs::XSD_FLOAT: + ns = s_nsXSD; + ln = "float"; + break; + + case css::rdf::URIs::XSD_DOUBLE: + ns = s_nsXSD; + ln = "double"; + break; + + case css::rdf::URIs::XSD_INTEGER: + ns = s_nsXSD; + ln = "integer"; + break; + + case css::rdf::URIs::XSD_NONNEGATIVEINTEGER: + ns = s_nsXSD; + ln = "nonNegativeInteger"; + break; + + case css::rdf::URIs::XSD_POSITIVEINTEGER: + ns = s_nsXSD; + ln = "positiveInteger"; + break; + + case css::rdf::URIs::XSD_NONPOSITIVEINTEGER: + ns = s_nsXSD; + ln = "nonPositiveInteger"; + break; + + case css::rdf::URIs::XSD_NEGATIVEINTEGER: + ns = s_nsXSD; + ln = "negativeInteger"; + break; + + case css::rdf::URIs::XSD_LONG: + ns = s_nsXSD; + ln = "long"; + break; + + case css::rdf::URIs::XSD_INT: + ns = s_nsXSD; + ln = "int"; + break; + + case css::rdf::URIs::XSD_SHORT: + ns = s_nsXSD; + ln = "short"; + break; + + case css::rdf::URIs::XSD_BYTE: + ns = s_nsXSD; + ln = "byte"; + break; + + case css::rdf::URIs::XSD_UNSIGNEDLONG: + ns = s_nsXSD; + ln = "unsignedLong"; + break; + + case css::rdf::URIs::XSD_UNSIGNEDINT: + ns = s_nsXSD; + ln = "unsignedInt"; + break; + + case css::rdf::URIs::XSD_UNSIGNEDSHORT: + ns = s_nsXSD; + ln = "unsignedShort"; + break; + + case css::rdf::URIs::XSD_UNSIGNEDBYTE: + ns = s_nsXSD; + ln = "unsignedByte"; + break; + + case css::rdf::URIs::XSD_HEXBINARY: + ns = s_nsXSD; + ln = "hexBinary"; + break; + + case css::rdf::URIs::XSD_BASE64BINARY: + ns = s_nsXSD; + ln = "base64Binary"; + break; + + case css::rdf::URIs::XSD_DATETIME: + ns = s_nsXSD; + ln = "dateTime"; + break; + + case css::rdf::URIs::XSD_TIME: + ns = s_nsXSD; + ln = "time"; + break; + + case css::rdf::URIs::XSD_DATE: + ns = s_nsXSD; + ln = "date"; + break; + + case css::rdf::URIs::XSD_GYEARMONTH: + ns = s_nsXSD; + ln = "gYearMonth"; + break; + + case css::rdf::URIs::XSD_GYEAR: + ns = s_nsXSD; + ln = "gYear"; + break; + + case css::rdf::URIs::XSD_GMONTHDAY: + ns = s_nsXSD; + ln = "gMonthDay"; + break; + + case css::rdf::URIs::XSD_GDAY: + ns = s_nsXSD; + ln = "gDay"; + break; + + case css::rdf::URIs::XSD_GMONTH: + ns = s_nsXSD; + ln = "gMonth"; + break; + + case css::rdf::URIs::XSD_ANYURI: + ns = s_nsXSD; + ln = "anyURI"; + break; + + case css::rdf::URIs::XSD_TOKEN: + ns = s_nsXSD; + ln = "token"; + break; + + case css::rdf::URIs::XSD_LANGUAGE: + ns = s_nsXSD; + ln = "language"; + break; + + case css::rdf::URIs::XSD_NMTOKEN: + ns = s_nsXSD; + ln = "NMTOKEN"; + break; + + case css::rdf::URIs::XSD_NAME: + ns = s_nsXSD; + ln = "Name"; + break; + + case css::rdf::URIs::XSD_DURATION: + ns = s_nsXSD; + ln = "duration"; + break; + + case css::rdf::URIs::XSD_QNAME: + ns = s_nsXSD; + ln = "QName"; + break; + + case css::rdf::URIs::XSD_NOTATION: + ns = s_nsXSD; + ln = "NOTATION"; + break; + + case css::rdf::URIs::XSD_NMTOKENS: + ns = s_nsXSD; + ln = "NMTOKENS"; + break; + + case css::rdf::URIs::XSD_ID: + ns = s_nsXSD; + ln = "ID"; + break; + + case css::rdf::URIs::XSD_IDREF: + ns = s_nsXSD; + ln = "IDREF"; + break; + + case css::rdf::URIs::XSD_IDREFS: + ns = s_nsXSD; + ln = "IDREFS"; + break; + + case css::rdf::URIs::XSD_ENTITY: + ns = s_nsXSD; + ln = "ENTITY"; + break; + + case css::rdf::URIs::XSD_ENTITIES: + ns = s_nsXSD; + ln = "ENTITIES"; + break; + + case css::rdf::URIs::RDF_TYPE: + ns = s_nsRDF; + ln = "type"; + break; + + case css::rdf::URIs::RDF_SUBJECT: + ns = s_nsRDF; + ln = "subject"; + break; + + case css::rdf::URIs::RDF_PREDICATE: + ns = s_nsRDF; + ln = "predicate"; + break; + + case css::rdf::URIs::RDF_OBJECT: + ns = s_nsRDF; + ln = "object"; + break; + + case css::rdf::URIs::RDF_PROPERTY: + ns = s_nsRDF; + ln = "Property"; + break; + + case css::rdf::URIs::RDF_STATEMENT: + ns = s_nsRDF; + ln = "Statement"; + break; + + case css::rdf::URIs::RDF_VALUE: + ns = s_nsRDF; + ln = "value"; + break; + + case css::rdf::URIs::RDF_FIRST: + ns = s_nsRDF; + ln = "first"; + break; + + case css::rdf::URIs::RDF_REST: + ns = s_nsRDF; + ln = "rest"; + break; + + case css::rdf::URIs::RDF_NIL: + ns = s_nsRDF; + ln = "nil"; + break; + + case css::rdf::URIs::RDF_XMLLITERAL: + ns = s_nsRDF; + ln = "XMLLiteral"; + break; + + case css::rdf::URIs::RDF_ALT: + ns = s_nsRDF; + ln = "Alt"; + break; + + case css::rdf::URIs::RDF_BAG: + ns = s_nsRDF; + ln = "Bag"; + break; + + case css::rdf::URIs::RDF_LIST: + ns = s_nsRDF; + ln = "List"; + break; + + case css::rdf::URIs::RDF_SEQ: + ns = s_nsRDF; + ln = "Seq"; + break; + + case css::rdf::URIs::RDF_1: + ns = s_nsRDF; + ln = "_1"; + break; + + case css::rdf::URIs::RDFS_COMMENT: + ns = s_nsRDFs; + ln = "comment"; + break; + + case css::rdf::URIs::RDFS_LABEL: + ns = s_nsRDFs; + ln = "label"; + break; + + case css::rdf::URIs::RDFS_DOMAIN: + ns = s_nsRDFs; + ln = "domain"; + break; + + case css::rdf::URIs::RDFS_RANGE: + ns = s_nsRDFs; + ln = "range"; + break; + + case css::rdf::URIs::RDFS_SUBCLASSOF: + ns = s_nsRDFs; + ln = "subClassOf"; + break; + + case css::rdf::URIs::RDFS_LITERAL: + ns = s_nsRDFs; + ln = "Literal"; + break; + + case css::rdf::URIs::OWL_CLASS: + ns = s_nsOWL; + ln = "Class"; + break; + + case css::rdf::URIs::OWL_OBJECTPROPERTY: + ns = s_nsOWL; + ln = "ObjectProperty"; + break; + + case css::rdf::URIs::OWL_DATATYPEPROPERTY: + ns = s_nsOWL; + ln = "DatatypeProperty"; + break; + + case css::rdf::URIs::OWL_FUNCTIONALPROPERTY: + ns = s_nsOWL; + ln = "FunctionalProperty"; + break; + + case css::rdf::URIs::OWL_THING: + ns = s_nsOWL; + ln = "Thing"; + break; + + case css::rdf::URIs::OWL_NOTHING: + ns = s_nsOWL; + ln = "Nothing"; + break; + + case css::rdf::URIs::OWL_INDIVIDUAL: + ns = s_nsOWL; + ln = "Individual"; + break; + + case css::rdf::URIs::OWL_EQUIVALENTCLASS: + ns = s_nsOWL; + ln = "equivalentClass"; + break; + + case css::rdf::URIs::OWL_EQUIVALENTPROPERTY: + ns = s_nsOWL; + ln = "equivalentProperty"; + break; + + case css::rdf::URIs::OWL_SAMEAS: + ns = s_nsOWL; + ln = "sameAs"; + break; + + case css::rdf::URIs::OWL_DIFFERENTFROM: + ns = s_nsOWL; + ln = "differentFrom"; + break; + + case css::rdf::URIs::OWL_ALLDIFFERENT: + ns = s_nsOWL; + ln = "AllDifferent"; + break; + + case css::rdf::URIs::OWL_DISTINCTMEMBERS: + ns = s_nsOWL; + ln = "distinctMembers"; + break; + + case css::rdf::URIs::OWL_INVERSEOF: + ns = s_nsOWL; + ln = "inverseOf"; + break; + + case css::rdf::URIs::OWL_TRANSITIVEPROPERTY: + ns = s_nsOWL; + ln = "TransitiveProperty"; + break; + + case css::rdf::URIs::OWL_SYMMETRICPROPERTY: + ns = s_nsOWL; + ln = "SymmetricProperty"; + break; + + case css::rdf::URIs::OWL_INVERSEFUNCTIONALPROPERTY: + ns = s_nsOWL; + ln = "InverseFunctionalProperty"; + break; + + case css::rdf::URIs::OWL_RESTRICTION: + ns = s_nsOWL; + ln = "Restriction"; + break; + + case css::rdf::URIs::OWL_ONPROPERTY: + ns = s_nsOWL; + ln = "onProperty"; + break; + + case css::rdf::URIs::OWL_ALLVALUESFROM: + ns = s_nsOWL; + ln = "allValuesFrom"; + break; + + case css::rdf::URIs::OWL_SOMEVALUESFROM: + ns = s_nsOWL; + ln = "someValuesFrom"; + break; + + case css::rdf::URIs::OWL_MINCARDINALITY: + ns = s_nsOWL; + ln = "minCardinality"; + break; + + case css::rdf::URIs::OWL_MAXCARDINALITY: + ns = s_nsOWL; + ln = "maxCardinality"; + break; + + case css::rdf::URIs::OWL_CARDINALITY: + ns = s_nsOWL; + ln = "cardinality"; + break; + + case css::rdf::URIs::OWL_ONTOLOGY: + ns = s_nsOWL; + ln = "Ontology"; + break; + + case css::rdf::URIs::OWL_IMPORTS: + ns = s_nsOWL; + ln = "imports"; + break; + + case css::rdf::URIs::OWL_VERSIONINFO: + ns = s_nsOWL; + ln = "versionInfo"; + break; + + case css::rdf::URIs::OWL_PRIORVERSION: + ns = s_nsOWL; + ln = "priorVersion"; + break; + + case css::rdf::URIs::OWL_BACKWARDCOMPATIBLEWITH: + ns = s_nsOWL; + ln = "backwardCompatibleWith"; + break; + + case css::rdf::URIs::OWL_INCOMPATIBLEWITH: + ns = s_nsOWL; + ln = "incompatibleWith"; + break; + + case css::rdf::URIs::OWL_DEPRECATEDCLASS: + ns = s_nsOWL; + ln = "DeprecatedClass"; + break; + + case css::rdf::URIs::OWL_DEPRECATEDPROPERTY: + ns = s_nsOWL; + ln = "DeprecatedProperty"; + break; + + case css::rdf::URIs::OWL_ANNOTATIONPROPERTY: + ns = s_nsOWL; + ln = "AnnotationProperty"; + break; + + case css::rdf::URIs::OWL_ONTOLOGYPROPERTY: + ns = s_nsOWL; + ln = "OntologyProperty"; + break; + + case css::rdf::URIs::OWL_ONEOF: + ns = s_nsOWL; + ln = "oneOf"; + break; + + case css::rdf::URIs::OWL_DATARANGE: + ns = s_nsOWL; + ln = "dataRange"; + break; + + case css::rdf::URIs::OWL_DISJOINTWITH: + ns = s_nsOWL; + ln = "disjointWith"; + break; + + case css::rdf::URIs::OWL_UNIONOF: + ns = s_nsOWL; + ln = "unionOf"; + break; + + case css::rdf::URIs::OWL_COMPLEMENTOF: + ns = s_nsOWL; + ln = "complementOf"; + break; + + case css::rdf::URIs::OWL_INTERSECTIONOF: + ns = s_nsOWL; + ln = "intersectionOf"; + break; + + case css::rdf::URIs::OWL_HASVALUE: + ns = s_nsOWL; + ln = "hasValue"; + break; + + + case css::rdf::URIs::PKG_HASPART: + ns = s_nsPkg; + ln = "hasPart"; + break; + +/* REMOVED + case css::rdf::URIs::PKG_IDREF: + ns = s_nsPkg; + ln = "idref"; + break; + + case css::rdf::URIs::PKG_PATH: + ns = s_nsPkg; + ln = "path"; + break; +*/ + + case css::rdf::URIs::PKG_MIMETYPE: + ns = s_nsPkg; + ln = "mimeType"; + break; + + case css::rdf::URIs::PKG_PACKAGE: + ns = s_nsPkg; + ln = "Package"; + break; + + case css::rdf::URIs::PKG_ELEMENT: + ns = s_nsPkg; + ln = "Element"; + break; + + case css::rdf::URIs::PKG_FILE: + ns = s_nsPkg; + ln = "File"; + break; + + case css::rdf::URIs::PKG_METADATAFILE: + ns = s_nsPkg; + ln = "MetadataFile"; + break; + + case css::rdf::URIs::PKG_DOCUMENT: + ns = s_nsPkg; + ln = "Document"; + break; + + case css::rdf::URIs::ODF_PREFIX: + ns = s_nsODF; + ln = "prefix"; + break; + + case css::rdf::URIs::ODF_SUFFIX: + ns = s_nsODF; + ln = "suffix"; + break; + + case css::rdf::URIs::ODF_ELEMENT: + ns = s_nsODF; + ln = "Element"; + break; + + case css::rdf::URIs::ODF_CONTENTFILE: + ns = s_nsODF; + ln = "ContentFile"; + break; + + case css::rdf::URIs::ODF_STYLESFILE: + ns = s_nsODF; + ln = "StylesFile"; + break; + +/* REMOVED + case css::rdf::URIs::ODF_METADATAFILE: + ns = s_nsODF; + ln = "MetadataFile"; + break; +*/ + + default: + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CURI::initialize: " + "invalid URIs constant argument")), *this, 0); + } + m_Namespace = ::rtl::OUString::createFromAscii(ns).intern(); + m_LocalName = ::rtl::OUString::createFromAscii(ln).intern(); + return; +} + +// ::com::sun::star::lang::XInitialization: +void SAL_CALL CURI::initialize(const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments) throw (css::uno::RuntimeException, css::uno::Exception) +{ + sal_Int32 len = aArguments.getLength(); + if ((len < 1) || (len > 2)) { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CURI::initialize: " + "must give 1 or 2 argument(s)")), *this, 2); + } + + sal_Int16 arg(0); + ::rtl::OUString arg0; + ::rtl::OUString arg1; + if ((aArguments[0] >>= arg)) { + // integer argument: constant from rdf::URIs + if (len != 1) { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CURI::initialize: " + "must give 1 int argument")), *this, 1); + } + initFromConstant(arg); + return; + } + if (!(aArguments[0] >>= arg0)) { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CURI::initialize: " + "argument must be string or short")), *this, 0); + } + if (len > 1) { + if (!(aArguments[1] >>= arg1)) { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CURI::initialize: " + "argument must be string")), *this, 1); + } + // just append the parameters and then split them again; seems simplest + arg0 = arg0 + arg1; + arg1 = ::rtl::OUString(); + } + + // split parameter + sal_Int32 idx; + if ( ((idx = arg0.indexOf ('#')) >= 0) + || ((idx = arg0.lastIndexOf('/')) >= 0) + || ((idx = arg0.lastIndexOf(':')) >= 0)) + { + + if (idx < arg0.getLength() - 1) { + arg1 = arg0.copy(idx+1); + arg0 = arg0.copy(0, idx+1); + } + } else { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CURI::initialize: " + "argument not splittable: no separator [#/:]")), *this, 0); + } + + //FIXME: what is legal? + if (arg0.getLength() > 0) { + m_Namespace = arg0; + } else { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CURI::initialize: " + "argument is not valid namespace")), *this, 0); + } + //FIXME: what is legal? + if (true) { + m_LocalName = arg1; + } else { + throw css::lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CURI::initialize: " + "argument is not valid local name")), *this, 1); + } +} + +// ::com::sun::star::rdf::XNode: +::rtl::OUString SAL_CALL CURI::getStringValue() throw (css::uno::RuntimeException) +{ + return m_Namespace + m_LocalName; +} + +// ::com::sun::star::rdf::XURI: +::rtl::OUString SAL_CALL CURI::getNamespace() throw (css::uno::RuntimeException) +{ + return m_Namespace; +} + +::rtl::OUString SAL_CALL CURI::getLocalName() throw (css::uno::RuntimeException) +{ + return m_LocalName; +} + +} // closing anonymous implementation namespace + + + +// component helper namespace +namespace comp_CURI { + +::rtl::OUString SAL_CALL _getImplementationName() { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "CURI")); +} + +css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames() +{ + css::uno::Sequence< ::rtl::OUString > s(1); + s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.rdf.URI")); + return s; +} + +css::uno::Reference< css::uno::XInterface > SAL_CALL _create( + const css::uno::Reference< css::uno::XComponentContext > & context) + SAL_THROW((css::uno::Exception)) +{ + return static_cast< ::cppu::OWeakObject * >(new CURI(context)); +} + +} // closing component helper namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/rdf/librdf_repository.cxx b/unoxml/source/rdf/librdf_repository.cxx new file mode 100644 index 000000000000..644d283efc8f --- /dev/null +++ b/unoxml/source/rdf/librdf_repository.cxx @@ -0,0 +1,2236 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "librdf_repository.hxx" + +#include <string.h> + +#include <set> +#include <map> +#include <functional> +#include <algorithm> + +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/shared_array.hpp> +#include <boost/bind.hpp> + +#include <libxslt/security.h> + +#include <redland.h> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/io/XSeekableInputStream.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/rdf/XDocumentRepository.hpp> +#include <com/sun/star/rdf/XLiteral.hpp> +#include <com/sun/star/rdf/FileFormat.hpp> +#include <com/sun/star/rdf/URIs.hpp> +#include <com/sun/star/rdf/BlankNode.hpp> +#include <com/sun/star/rdf/URI.hpp> +#include <com/sun/star/rdf/Literal.hpp> + +#include <rtl/ref.hxx> +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <comphelper/stlunosequence.hxx> +#include <comphelper/sequenceasvector.hxx> +#include <comphelper/makesequence.hxx> + + +/** + Implementation of the service com.sun.star.rdf.Repository. + + This implementation uses the Redland RDF library (librdf). + + There are several classes involved: + librdf_TypeConverter: helper class to convert data types redland <-> uno + librdf_Repository: the main repository, does almost all the work + librdf_NamedGraph: the XNamedGraph, forwards everything to repository + librdf_GraphResult: an XEnumeration<Statement> + librdf_QuerySelectResult: an XEnumeration<sequence<XNode>> + + @author mst + */ + +/// anonymous implementation namespace +namespace { + +class librdf_NamedGraph; +class librdf_Repository; + +using namespace ::com::sun::star; + +typedef std::map< ::rtl::OUString, ::rtl::Reference<librdf_NamedGraph> > + NamedGraphMap_t; + +const char s_sparql [] = "sparql"; +const char s_nsRDFs [] = "http://www.w3.org/2000/01/rdf-schema#"; +const char s_label [] = "label"; +const char s_nsOOo [] = "http://openoffice.org/2004/office/rdfa/"; + +//////////////////////////////////////////////////////////////////////////// + +//FIXME: this approach is not ideal. can we use blind nodes instead? +bool isInternalContext(librdf_node *i_pNode) throw () +{ + OSL_ENSURE(i_pNode, "isInternalContext: context null"); + OSL_ENSURE(librdf_node_is_resource(i_pNode), + "isInternalContext: context not resource"); + if (i_pNode) { + librdf_uri *pURI(librdf_node_get_uri(i_pNode)); + OSL_ENSURE(pURI, "isInternalContext: URI null"); + if (pURI) { + unsigned char *pContextURI(librdf_uri_as_string(pURI)); + OSL_ENSURE(pContextURI, + "isInternalContext: URI string null"); + // if prefix matches reserved uri, it is RDFa context + if (!strncmp(reinterpret_cast<char *>(pContextURI), + s_nsOOo, sizeof(s_nsOOo)-1)) { + return true; + } + } + return false; + } + return true; +} + + +//////////////////////////////////////////////////////////////////////////// + +// n.b.: librdf destructor functions dereference null pointers! +// so they need to be wrapped to be usable with boost::shared_ptr. +static void safe_librdf_free_world(librdf_world *const world) +{ + if (world) { librdf_free_world(world); } +} +static void safe_librdf_free_model(librdf_model *const model) +{ + if (model) { librdf_free_model(model); } +} +static void safe_librdf_free_node(librdf_node* node) +{ + if (node) { librdf_free_node(node); } +} +static void safe_librdf_free_parser(librdf_parser *const parser) +{ + if (parser) { librdf_free_parser(parser); } +} +static void safe_librdf_free_query(librdf_query *const query) +{ + if (query) { librdf_free_query(query); } +} +static void +safe_librdf_free_query_results(librdf_query_results *const query_results) +{ + if (query_results) { librdf_free_query_results(query_results); } +} +static void safe_librdf_free_serializer(librdf_serializer *const serializer) +{ + if (serializer) { librdf_free_serializer(serializer); } +} +static void safe_librdf_free_statement(librdf_statement *const statement) +{ + if (statement) { librdf_free_statement(statement); } +} +static void safe_librdf_free_storage(librdf_storage *const storage) +{ + if (storage) { librdf_free_storage(storage); } +} +static void safe_librdf_free_stream(librdf_stream *const stream) +{ + if (stream) { librdf_free_stream(stream); } +} +static void safe_librdf_free_uri(librdf_uri *const uri) +{ + if (uri) { librdf_free_uri(uri); } +} + + +//////////////////////////////////////////////////////////////////////////// + +/** converts between librdf types and UNO API types. + */ +class librdf_TypeConverter +{ +public: + librdf_TypeConverter( + uno::Reference< uno::XComponentContext > const & i_xContext, + librdf_Repository &i_rRep) + : m_xContext(i_xContext) + , m_rRep(i_rRep) + { }; + + librdf_world *createWorld() const; + librdf_storage *createStorage(librdf_world *i_pWorld) const; + librdf_model *createModel(librdf_world *i_pWorld, + librdf_storage * i_pStorage) const; + librdf_uri* mkURI( librdf_world* i_pWorld, + const uno::Reference< rdf::XURI > & i_xURI) const; + librdf_node* mkResource( librdf_world* i_pWorld, + const uno::Reference< rdf::XResource > & i_xResource) const; + librdf_node* mkNode( librdf_world* i_pWorld, + const uno::Reference< rdf::XNode > & i_xNode) const; + librdf_statement* mkStatement( librdf_world* i_pWorld, + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) const; + uno::Reference<rdf::XURI> convertToXURI(librdf_uri* i_pURI) const; + uno::Reference<rdf::XURI> convertToXURI(librdf_node* i_pURI) const; + uno::Reference<rdf::XResource> + convertToXResource(librdf_node* i_pNode) const; + uno::Reference<rdf::XNode> convertToXNode(librdf_node* i_pNode) const; + rdf::Statement + convertToStatement(librdf_statement* i_pStmt, librdf_node* i_pContext) + const; + +private: + uno::Reference< uno::XComponentContext > m_xContext; + librdf_Repository & m_rRep; +}; + + +//////////////////////////////////////////////////////////////////////////// + +/** implements the repository service. + */ +class librdf_Repository: + private boost::noncopyable, +// private ::cppu::BaseMutex, + public ::cppu::WeakImplHelper3< + lang::XServiceInfo, + rdf::XDocumentRepository, + lang::XInitialization> +{ +public: + + explicit librdf_Repository( + uno::Reference< uno::XComponentContext > const & i_xContext); + virtual ~librdf_Repository(); + + // ::com::sun::star::lang::XServiceInfo: + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (uno::RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService( + const ::rtl::OUString & ServiceName) throw (uno::RuntimeException); + virtual uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (uno::RuntimeException); + + // ::com::sun::star::rdf::XRepository: + virtual uno::Reference< rdf::XBlankNode > SAL_CALL createBlankNode() + throw (uno::RuntimeException); + virtual uno::Reference<rdf::XNamedGraph> SAL_CALL importGraph( + ::sal_Int16 i_Format, + const uno::Reference< io::XInputStream > & i_xInStream, + const uno::Reference< rdf::XURI > & i_xGraphName, + const uno::Reference< rdf::XURI > & i_xBaseURI) + throw (uno::RuntimeException, lang::IllegalArgumentException, + datatransfer::UnsupportedFlavorException, + container::ElementExistException, rdf::ParseException, + rdf::RepositoryException, io::IOException); + virtual void SAL_CALL exportGraph(::sal_Int16 i_Format, + const uno::Reference< io::XOutputStream > & i_xOutStream, + const uno::Reference< rdf::XURI > & i_xGraphName, + const uno::Reference< rdf::XURI > & i_xBaseURI) + throw (uno::RuntimeException, lang::IllegalArgumentException, + datatransfer::UnsupportedFlavorException, + container::NoSuchElementException, rdf::RepositoryException, + io::IOException); + virtual uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL + getGraphNames() throw (uno::RuntimeException, rdf::RepositoryException); + virtual uno::Reference< rdf::XNamedGraph > SAL_CALL getGraph( + const uno::Reference< rdf::XURI > & i_xGraphName) + throw (uno::RuntimeException, lang::IllegalArgumentException, + rdf::RepositoryException); + virtual uno::Reference< rdf::XNamedGraph > SAL_CALL createGraph( + const uno::Reference< rdf::XURI > & i_xGraphName) + throw (uno::RuntimeException, lang::IllegalArgumentException, + container::ElementExistException, rdf::RepositoryException); + virtual void SAL_CALL destroyGraph( + const uno::Reference< rdf::XURI > & i_xGraphName) + throw (uno::RuntimeException, lang::IllegalArgumentException, + container::NoSuchElementException, rdf::RepositoryException); + virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) + throw (uno::RuntimeException, + rdf::RepositoryException); + virtual uno::Reference< rdf::XQuerySelectResult > SAL_CALL + querySelect(const ::rtl::OUString & i_rQuery) + throw (uno::RuntimeException, rdf::QueryException, + rdf::RepositoryException); + virtual uno::Reference< container::XEnumeration > SAL_CALL + queryConstruct(const ::rtl::OUString & i_rQuery) + throw (uno::RuntimeException, rdf::QueryException, + rdf::RepositoryException); + virtual ::sal_Bool SAL_CALL queryAsk(const ::rtl::OUString & i_rQuery) + throw (uno::RuntimeException, rdf::QueryException, + rdf::RepositoryException); + + // ::com::sun::star::rdf::XDocumentRepository: + virtual void SAL_CALL setStatementRDFa( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates, + const uno::Reference< rdf::XMetadatable > & i_xObject, + const ::rtl::OUString & i_rRDFaContent, + const uno::Reference< rdf::XURI > & i_xRDFaDatatype) + throw (uno::RuntimeException, lang::IllegalArgumentException, + rdf::RepositoryException); + virtual void SAL_CALL removeStatementRDFa( + const uno::Reference< rdf::XMetadatable > & i_xElement) + throw (uno::RuntimeException, lang::IllegalArgumentException, + rdf::RepositoryException); + virtual beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL + getStatementRDFa(uno::Reference< rdf::XMetadatable > const& i_xElement) + throw (uno::RuntimeException, lang::IllegalArgumentException, + rdf::RepositoryException); + virtual uno::Reference< container::XEnumeration > SAL_CALL + getStatementsRDFa( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) + throw (uno::RuntimeException, + rdf::RepositoryException); + + // ::com::sun::star::lang::XInitialization: + virtual void SAL_CALL initialize( + const uno::Sequence< ::com::sun::star::uno::Any > & i_rArguments) + throw (uno::RuntimeException, uno::Exception); + + // XNamedGraph forwards --------------------------------------------- + const NamedGraphMap_t::iterator SAL_CALL clearGraph( + const uno::Reference< rdf::XURI > & i_xName, + bool i_Internal = false ); + void SAL_CALL addStatementGraph( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject, + const uno::Reference< rdf::XURI > & i_xName, + bool i_Internal = false ); +// throw (uno::RuntimeException, lang::IllegalArgumentException, +// container::NoSuchElementException, rdf::RepositoryException); + void SAL_CALL removeStatementsGraph( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject, + const uno::Reference< rdf::XURI > & i_xName ); +// throw (uno::RuntimeException, lang::IllegalArgumentException, +// container::NoSuchElementException, rdf::RepositoryException); + uno::Reference< container::XEnumeration > SAL_CALL getStatementsGraph( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject, + const uno::Reference< rdf::XURI > & i_xName, + bool i_Internal = false ); +// throw (uno::RuntimeException, lang::IllegalArgumentException, +// container::NoSuchElementException, rdf::RepositoryException); + + const librdf_TypeConverter& getTypeConverter() { return m_TypeConverter; }; + +private: + + uno::Reference< uno::XComponentContext > m_xContext; + + /// librdf global data + /** N.B.: The redland documentation gives the impression that you can have + as many librdf_worlds as you like. This is true in the same sense + that you can physically be in as many places as you like. + Well, you can, just not at the same time. + The ugly truth is that destroying a librdf_world kills a bunch + of static variables; other librdf_worlds become very unhappy + when they access these. + And of course this is not documented anywhere that I could find. + So we allocate a single world, and refcount that. + */ + static boost::shared_ptr<librdf_world> m_pWorld; + /// refcount + static sal_uInt32 m_NumInstances; + /// mutex for m_pWorld - redland is not as threadsafe as is often claimed + static osl::Mutex m_aMutex; + + // NB: sequence of the shared pointers is important! + /// librdf repository storage + boost::shared_ptr<librdf_storage> m_pStorage; + /// librdf repository model + boost::shared_ptr<librdf_model> m_pModel; + + /// all named graphs + NamedGraphMap_t m_NamedGraphs; + + /// type conversion helper + librdf_TypeConverter m_TypeConverter; + + /// set of xml:ids of elements with xhtml:content + ::std::set< ::rtl::OUString > m_RDFaXHTMLContentSet; +}; + + +//////////////////////////////////////////////////////////////////////////// + +/** result of operations that return a graph, i.e., + an XEnumeration of statements. + */ +class librdf_GraphResult: + private boost::noncopyable, + public ::cppu::WeakImplHelper1< + container::XEnumeration> +{ +public: + + librdf_GraphResult(librdf_Repository *i_pRepository, + ::osl::Mutex & i_rMutex, + boost::shared_ptr<librdf_stream> const& i_pStream, + boost::shared_ptr<librdf_node> const& i_pContext, + boost::shared_ptr<librdf_query> const& i_pQuery = + boost::shared_ptr<librdf_query>() ) + : m_xRep(i_pRepository) + , m_rMutex(i_rMutex) + , m_pQuery(i_pQuery) + , m_pContext(i_pContext) + , m_pStream(i_pStream) + { }; + + virtual ~librdf_GraphResult() {} + + // ::com::sun::star::container::XEnumeration: + virtual ::sal_Bool SAL_CALL hasMoreElements() + throw (uno::RuntimeException); + virtual uno::Any SAL_CALL nextElement() + throw (uno::RuntimeException, container::NoSuchElementException, + lang::WrappedTargetException); + +private: + // NB: this is not a weak pointer: streams _must_ be deleted before the + // storage they point into, so we keep the repository alive here + // also, sequence is important: the stream must be destroyed first. + ::rtl::Reference< librdf_Repository > m_xRep; + // needed for synchronizing access to librdf (it doesnt do win32 threading) + ::osl::Mutex & m_rMutex; + // the query (in case this is a result of a graph query) + // not that the redland documentation spells this out explicity, but + // queries must be freed only after all the results are completely read + boost::shared_ptr<librdf_query> const m_pQuery; + boost::shared_ptr<librdf_node> const m_pContext; + boost::shared_ptr<librdf_stream> const m_pStream; + + librdf_node* getContext() const; +}; + + +// ::com::sun::star::container::XEnumeration: +::sal_Bool SAL_CALL +librdf_GraphResult::hasMoreElements() throw (uno::RuntimeException) +{ + ::osl::MutexGuard g(m_rMutex); + return m_pStream.get() && !librdf_stream_end(m_pStream.get()); +} + +librdf_node* librdf_GraphResult::getContext() const +{ + if (!m_pStream.get() || librdf_stream_end(m_pStream.get())) + return NULL; + librdf_node *pCtxt( static_cast<librdf_node *> + (librdf_stream_get_context(m_pStream.get())) ); + if (pCtxt) + return pCtxt; + return m_pContext.get(); +} + +::com::sun::star::uno::Any SAL_CALL +librdf_GraphResult::nextElement() +throw (uno::RuntimeException, container::NoSuchElementException, + lang::WrappedTargetException) +{ + ::osl::MutexGuard g(m_rMutex); + if (!m_pStream.get() || !librdf_stream_end(m_pStream.get())) { + librdf_node * pCtxt = getContext(); + + librdf_statement *pStmt( librdf_stream_get_object(m_pStream.get()) ); + if (!pStmt) { + rdf::QueryException e(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_GraphResult::nextElement: " + "librdf_stream_get_object failed")), *this); + throw lang::WrappedTargetException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_GraphResult::nextElement: " + "librdf_stream_get_object failed")), *this, + uno::makeAny(e)); + } + // NB: pCtxt may be null here if this is result of a graph query + if (pCtxt && isInternalContext(pCtxt)) { + pCtxt = 0; // XML ID context is implementation detail! + } + rdf::Statement Stmt( + m_xRep->getTypeConverter().convertToStatement(pStmt, pCtxt) ); + // NB: this will invalidate current item. + librdf_stream_next(m_pStream.get()); + return uno::makeAny(Stmt); + } else { + throw container::NoSuchElementException(); + } +} + + +//////////////////////////////////////////////////////////////////////////// + +/** result of tuple queries ("SELECT"). + */ +class librdf_QuerySelectResult: + private boost::noncopyable, + public ::cppu::WeakImplHelper1< + rdf::XQuerySelectResult> +{ +public: + + librdf_QuerySelectResult(librdf_Repository *i_pRepository, + ::osl::Mutex & i_rMutex, + boost::shared_ptr<librdf_query> const& i_pQuery, + boost::shared_ptr<librdf_query_results> const& i_pQueryResult, + uno::Sequence< ::rtl::OUString > const& i_rBindingNames ) + : m_xRep(i_pRepository) + , m_rMutex(i_rMutex) + , m_pQuery(i_pQuery) + , m_pQueryResult(i_pQueryResult) + , m_BindingNames(i_rBindingNames) + { }; + + virtual ~librdf_QuerySelectResult() {} + + // ::com::sun::star::container::XEnumeration: + virtual ::sal_Bool SAL_CALL hasMoreElements() + throw (uno::RuntimeException); + virtual uno::Any SAL_CALL nextElement() + throw (uno::RuntimeException, container::NoSuchElementException, + lang::WrappedTargetException); + + // ::com::sun::star::rdf::XQuerySelectResult: + virtual uno::Sequence< ::rtl::OUString > SAL_CALL getBindingNames() + throw (uno::RuntimeException); + +private: + + // NB: this is not a weak pointer: streams _must_ be deleted before the + // storage they point into, so we keep the repository alive here + // also, sequence is important: the stream must be destroyed first. + ::rtl::Reference< librdf_Repository > m_xRep; + // needed for synchronizing access to librdf (it doesnt do win32 threading) + ::osl::Mutex & m_rMutex; + // not that the redland documentation spells this out explicity, but + // queries must be freed only after all the results are completely read + boost::shared_ptr<librdf_query> m_pQuery; + boost::shared_ptr<librdf_query_results> m_pQueryResult; + uno::Sequence< ::rtl::OUString > m_BindingNames; +}; + + +// ::com::sun::star::container::XEnumeration: +::sal_Bool SAL_CALL +librdf_QuerySelectResult::hasMoreElements() throw (uno::RuntimeException) +{ + ::osl::MutexGuard g(m_rMutex); + return !librdf_query_results_finished(m_pQueryResult.get()); +} + +class NodeArrayDeleter : public std::unary_function<librdf_node**, void> +{ + const int m_Count; + +public: + NodeArrayDeleter(int i_Count) : m_Count(i_Count) { } + + void operator() (librdf_node** io_pArray) const throw () + { + std::for_each(io_pArray, io_pArray + m_Count, safe_librdf_free_node); + delete[] io_pArray; + } +}; + +::com::sun::star::uno::Any SAL_CALL +librdf_QuerySelectResult::nextElement() +throw (uno::RuntimeException, container::NoSuchElementException, + lang::WrappedTargetException) +{ + ::osl::MutexGuard g(m_rMutex); + if (!librdf_query_results_finished(m_pQueryResult.get())) { + sal_Int32 count(m_BindingNames.getLength()); + OSL_ENSURE(count >= 0, "negative length?"); + boost::shared_array<librdf_node*> pNodes( new librdf_node*[count], + NodeArrayDeleter(count)); + for (int i = 0; i < count; ++i) { + pNodes[i] = 0; + } + if (librdf_query_results_get_bindings(m_pQueryResult.get(), NULL, + pNodes.get())) + { + rdf::QueryException e(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_QuerySelectResult::nextElement: " + "librdf_query_results_get_bindings failed")), *this); + throw lang::WrappedTargetException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_QuerySelectResult::nextElement: " + "librdf_query_results_get_bindings failed")), *this, + uno::makeAny(e)); + } + uno::Sequence< uno::Reference< rdf::XNode > > ret(count); + for (int i = 0; i < count; ++i) { + ret[i] = m_xRep->getTypeConverter().convertToXNode(pNodes[i]); + } + // NB: this will invalidate current item. + librdf_query_results_next(m_pQueryResult.get()); + return uno::makeAny(ret); + } else { + throw container::NoSuchElementException(); + } +} + +// ::com::sun::star::rdf::XQuerySelectResult: +uno::Sequence< ::rtl::OUString > SAL_CALL +librdf_QuerySelectResult::getBindingNames() throw (uno::RuntimeException) +{ + return m_BindingNames; +} + + +//////////////////////////////////////////////////////////////////////////// + +/** represents a named graph, and forwards all the work to repository. + */ +class librdf_NamedGraph: + private boost::noncopyable, + public ::cppu::WeakImplHelper1< + rdf::XNamedGraph> +{ +public: + librdf_NamedGraph(librdf_Repository * i_pRep, + uno::Reference<rdf::XURI> const & i_xName) + : m_wRep(i_pRep) + , m_pRep(i_pRep) + , m_xName(i_xName) + { }; + + virtual ~librdf_NamedGraph() {} + + // ::com::sun::star::rdf::XNode: + virtual ::rtl::OUString SAL_CALL getStringValue() + throw (uno::RuntimeException); + + // ::com::sun::star::rdf::XURI: + virtual ::rtl::OUString SAL_CALL getNamespace() + throw (uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getLocalName() + throw (uno::RuntimeException); + + // ::com::sun::star::rdf::XNamedGraph: + virtual uno::Reference<rdf::XURI> SAL_CALL getName() + throw (uno::RuntimeException); + virtual void SAL_CALL clear() + throw (uno::RuntimeException, + container::NoSuchElementException, rdf::RepositoryException); + virtual void SAL_CALL addStatement( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) + throw (uno::RuntimeException, lang::IllegalArgumentException, + container::NoSuchElementException, rdf::RepositoryException); + virtual void SAL_CALL removeStatements( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) + throw (uno::RuntimeException, + container::NoSuchElementException, rdf::RepositoryException); + virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) + throw (uno::RuntimeException, + container::NoSuchElementException, rdf::RepositoryException); + +private: + + /// weak reference: this is needed to check if m_pRep is valid + uno::WeakReference< rdf::XRepository > m_wRep; + librdf_Repository *m_pRep; + uno::Reference< rdf::XURI > m_xName; +}; + + +// ::com::sun::star::rdf::XNode: +::rtl::OUString SAL_CALL librdf_NamedGraph::getStringValue() +throw (uno::RuntimeException) +{ + return m_xName->getStringValue(); +} + +// ::com::sun::star::rdf::XURI: +::rtl::OUString SAL_CALL librdf_NamedGraph::getNamespace() +throw (uno::RuntimeException) +{ + return m_xName->getNamespace(); +} + +::rtl::OUString SAL_CALL librdf_NamedGraph::getLocalName() +throw (uno::RuntimeException) +{ + return m_xName->getLocalName(); +} + +// ::com::sun::star::rdf::XNamedGraph: +uno::Reference< rdf::XURI > SAL_CALL librdf_NamedGraph::getName() +throw (uno::RuntimeException) +{ + return m_xName; +} + +void SAL_CALL librdf_NamedGraph::clear() +throw (uno::RuntimeException, + container::NoSuchElementException, rdf::RepositoryException) +{ + uno::Reference< rdf::XRepository > xRep( m_wRep ); + if (!xRep.is()) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_NamedGraph::clear: repository is gone")), *this); + } + try { + m_pRep->clearGraph(m_xName); + } catch (lang::IllegalArgumentException &) { + throw uno::RuntimeException(); + } +} + +void SAL_CALL librdf_NamedGraph::addStatement( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) +throw (uno::RuntimeException, lang::IllegalArgumentException, + container::NoSuchElementException, rdf::RepositoryException) +{ + uno::Reference< rdf::XRepository > xRep( m_wRep ); + if (!xRep.is()) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_NamedGraph::addStatement: repository is gone")), *this); + } + m_pRep->addStatementGraph(i_xSubject, i_xPredicate, i_xObject, m_xName); +} + +void SAL_CALL librdf_NamedGraph::removeStatements( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) +throw (uno::RuntimeException, + container::NoSuchElementException, rdf::RepositoryException) +{ + uno::Reference< rdf::XRepository > xRep( m_wRep ); + if (!xRep.is()) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_NamedGraph::removeStatements: repository is gone")), *this); + } + m_pRep->removeStatementsGraph(i_xSubject, i_xPredicate, i_xObject, m_xName); +} + +uno::Reference< container::XEnumeration > SAL_CALL +librdf_NamedGraph::getStatements( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) +throw (uno::RuntimeException, + container::NoSuchElementException, rdf::RepositoryException) +{ + uno::Reference< rdf::XRepository > xRep( m_wRep ); + if (!xRep.is()) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_NamedGraph::getStatements: repository is gone")), *this); + } + return m_pRep->getStatementsGraph( + i_xSubject, i_xPredicate, i_xObject, m_xName); +} + + +//////////////////////////////////////////////////////////////////////////// + +boost::shared_ptr<librdf_world> librdf_Repository::m_pWorld; +sal_uInt32 librdf_Repository::m_NumInstances = 0; +osl::Mutex librdf_Repository::m_aMutex; + +librdf_Repository::librdf_Repository( + uno::Reference< uno::XComponentContext > const & i_xContext) + : /*BaseMutex(),*/ m_xContext(i_xContext) +// m_pWorld (static_cast<librdf_world *>(0), safe_librdf_free_world ), + , m_pStorage(static_cast<librdf_storage*>(0), safe_librdf_free_storage) + , m_pModel (static_cast<librdf_model *>(0), safe_librdf_free_model ) + , m_NamedGraphs() + , m_TypeConverter(i_xContext, *this) +{ + OSL_ENSURE(i_xContext.is(), "librdf_Repository: null context"); + + ::osl::MutexGuard g(m_aMutex); + if (!m_NumInstances++) { + m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world); + } +} + +librdf_Repository::~librdf_Repository() +{ + // must destroy these before world! + m_pModel.reset(); + m_pStorage.reset(); + + // FIXME: so it turns out that calling librdf_free_world will + // (via raptor_sax2_finish) call xmlCleanupParser, which will + // free libxml2's globals! ARRRGH!!! => never call librdf_free_world +#if 0 + ::osl::MutexGuard g(m_aMutex); + if (!--m_NumInstances) { + m_pWorld.reset(); + } +#endif +} + +// com.sun.star.uno.XServiceInfo: +::rtl::OUString SAL_CALL librdf_Repository::getImplementationName() +throw (uno::RuntimeException) +{ + return comp_librdf_Repository::_getImplementationName(); +} + +::sal_Bool SAL_CALL librdf_Repository::supportsService( + ::rtl::OUString const & serviceName) throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > serviceNames + = comp_librdf_Repository::_getSupportedServiceNames(); + for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + if (serviceNames[i] == serviceName) + return sal_True; + } + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL +librdf_Repository::getSupportedServiceNames() throw (uno::RuntimeException) +{ + return comp_librdf_Repository::_getSupportedServiceNames(); +} + +// ::com::sun::star::rdf::XRepository: +uno::Reference< rdf::XBlankNode > SAL_CALL librdf_Repository::createBlankNode() +throw (uno::RuntimeException) +{ + ::osl::MutexGuard g(m_aMutex); + const boost::shared_ptr<librdf_node> pNode( + librdf_new_node_from_blank_identifier(m_pWorld.get(), NULL), + safe_librdf_free_node); + if (!pNode) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::createBlankNode: " + "librdf_new_node_from_blank_identifier failed")), *this); + } + const unsigned char * id (librdf_node_get_blank_identifier(pNode.get())); + if (!id) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::createBlankNode: " + "librdf_node_get_blank_identifier failed")), *this); + } + const ::rtl::OUString nodeID(::rtl::OUString::createFromAscii( + reinterpret_cast<const char *>(id))); + try { + return rdf::BlankNode::create(m_xContext, nodeID); + } catch (lang::IllegalArgumentException & iae) { + throw lang::WrappedTargetRuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::createBlankNode: " + "illegal blank node label")), *this, uno::makeAny(iae)); + } +} + +bool formatNeedsBaseURI(::sal_Int16 i_Format) +{ + (void) i_Format; //FIXME any which dont? + return true; +} + +//void SAL_CALL +uno::Reference<rdf::XNamedGraph> SAL_CALL +librdf_Repository::importGraph(::sal_Int16 i_Format, + const uno::Reference< io::XInputStream > & i_xInStream, + const uno::Reference< rdf::XURI > & i_xGraphName, + const uno::Reference< rdf::XURI > & i_xBaseURI) +throw (uno::RuntimeException, lang::IllegalArgumentException, + datatransfer::UnsupportedFlavorException, + container::ElementExistException, rdf::ParseException, + rdf::RepositoryException, io::IOException) +{ + ::osl::MutexGuard g(m_aMutex); + if (!i_xInStream.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::importGraph: " + "stream is null")), *this, 1); + } + //FIXME: other formats + if (i_Format != rdf::FileFormat::RDF_XML) { + throw datatransfer::UnsupportedFlavorException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::importGraph: " + "file format not supported")), *this); + } + if (!i_xGraphName.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::importGraph: " + "graph name is null")), *this, 2); + } + if (i_xGraphName->getStringValue().matchAsciiL(s_nsOOo, sizeof(s_nsOOo)-1)) + { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::importGraph: " + "URI is reserved")), *this, 0); + } + if (formatNeedsBaseURI(i_Format) && !i_xBaseURI.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::importGraph: " + "base URI is null")), *this, 3); + } + OSL_ENSURE(i_xBaseURI.is(), "no base uri"); + const ::rtl::OUString baseURIU( i_xBaseURI->getStringValue() ); + if (baseURIU.indexOf('#') >= 0) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::importGraph: " + "base URI is not absolute")), *this, 3); + } + + const ::rtl::OUString contextU( i_xGraphName->getStringValue() ); + if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) { + throw container::ElementExistException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::importGraph: " + "graph with given URI exists")), *this); + } + const ::rtl::OString context( + ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); + + const boost::shared_ptr<librdf_node> pContext( + librdf_new_node_from_uri_string(m_pWorld.get(), + reinterpret_cast<const unsigned char*> (context.getStr())), + safe_librdf_free_node); + if (!pContext) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::importGraph: " + "librdf_new_node_from_uri_string failed")), *this); + } + + const ::rtl::OString baseURI( + ::rtl::OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) ); + const boost::shared_ptr<librdf_uri> pBaseURI( + librdf_new_uri(m_pWorld.get(), + reinterpret_cast<const unsigned char*> (baseURI.getStr())), + safe_librdf_free_uri); + if (!pBaseURI) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::importGraph: " + "librdf_new_uri failed")), *this); + } + + const boost::shared_ptr<librdf_parser> pParser( + librdf_new_parser(m_pWorld.get(), "rdfxml", NULL, NULL), + safe_librdf_free_parser); + if (!pParser) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::importGraph: " + "librdf_new_parser failed")), *this); + } + + uno::Sequence<sal_Int8> buf; + uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY); + // UGLY: if only that redland junk could read streams... + const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 ); + // exceptions are propagated + i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) ); + const boost::shared_ptr<librdf_stream> pStream( + librdf_parser_parse_counted_string_as_stream(pParser.get(), + reinterpret_cast<const unsigned char*>(buf.getConstArray()), + buf.getLength(), pBaseURI.get()), + safe_librdf_free_stream); + if (!pStream) { + throw rdf::ParseException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::importGraph: " + "librdf_parser_parse_counted_string_as_stream failed")), *this); + } + m_NamedGraphs.insert(std::make_pair(contextU, + new librdf_NamedGraph(this, i_xGraphName))); + if (librdf_model_context_add_statements(m_pModel.get(), + pContext.get(), pStream.get())) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::importGraph: " + "librdf_model_context_add_statements failed")), *this); + } + return getGraph(i_xGraphName); +} + +void SAL_CALL +librdf_Repository::exportGraph(::sal_Int16 i_Format, + const uno::Reference< io::XOutputStream > & i_xOutStream, + const uno::Reference< rdf::XURI > & i_xGraphName, + const uno::Reference< rdf::XURI > & i_xBaseURI) +throw (uno::RuntimeException, lang::IllegalArgumentException, + datatransfer::UnsupportedFlavorException, + container::NoSuchElementException, rdf::RepositoryException, + io::IOException) +{ + ::osl::MutexGuard g(m_aMutex); + if (!i_xOutStream.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::exportGraph: " + "stream is null")), *this, 1); + } + // FIXME: other formats + if (i_Format != rdf::FileFormat::RDF_XML) { + throw datatransfer::UnsupportedFlavorException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::exportGraph: " + "file format not supported")), *this); + } + if (!i_xGraphName.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::exportGraph: " + "graph name is null")), *this, 2); + } + if (formatNeedsBaseURI(i_Format) && !i_xBaseURI.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::exportGraph: " + "base URI is null")), *this, 3); + } + OSL_ENSURE(i_xBaseURI.is(), "no base uri"); + const ::rtl::OUString baseURIU( i_xBaseURI->getStringValue() ); + if (baseURIU.indexOf('#') >= 0) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::exportGraph: " + "base URI is not absolute")), *this, 3); + } + + const ::rtl::OUString contextU( i_xGraphName->getStringValue() ); + if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) { + throw container::NoSuchElementException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::exportGraph: " + "no graph with given URI exists")), *this); + } + const ::rtl::OString context( + ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); + + const boost::shared_ptr<librdf_node> pContext( + librdf_new_node_from_uri_string(m_pWorld.get(), + reinterpret_cast<const unsigned char*> (context.getStr())), + safe_librdf_free_node); + if (!pContext) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::exportGraph: " + "librdf_new_node_from_uri_string failed")), *this); + } + const ::rtl::OString baseURI( + ::rtl::OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) ); + const boost::shared_ptr<librdf_uri> pBaseURI( + librdf_new_uri(m_pWorld.get(), + reinterpret_cast<const unsigned char*> (baseURI.getStr())), + safe_librdf_free_uri); + if (!pBaseURI) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::exportGraph: " + "librdf_new_uri failed")), *this); + } + + const boost::shared_ptr<librdf_stream> pStream( + librdf_model_context_as_stream(m_pModel.get(), pContext.get()), + safe_librdf_free_stream); + if (!pStream) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::exportGraph: " + "librdf_model_context_as_stream failed")), *this); + } + const char *format("rdfxml"); + // #i116443#: abbrev breaks when certain URIs are used as data types +// const char *format("rdfxml-abbrev"); + const boost::shared_ptr<librdf_serializer> pSerializer( + librdf_new_serializer(m_pWorld.get(), format, NULL, NULL), + safe_librdf_free_serializer); + if (!pSerializer) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::exportGraph: " + "librdf_new_serializer failed")), *this); + } + + const boost::shared_ptr<librdf_uri> pRelativeURI( + librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*> + ("http://feature.librdf.org/raptor-relativeURIs")), + safe_librdf_free_uri); + const boost::shared_ptr<librdf_uri> pWriteBaseURI( + librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*> + ("http://feature.librdf.org/raptor-writeBaseURI")), + safe_librdf_free_uri); + const boost::shared_ptr<librdf_node> p0( + librdf_new_node_from_literal(m_pWorld.get(), + reinterpret_cast<const unsigned char*> ("0"), NULL, 0), + safe_librdf_free_node); + const boost::shared_ptr<librdf_node> p1( + librdf_new_node_from_literal(m_pWorld.get(), + reinterpret_cast<const unsigned char*> ("1"), NULL, 0), + safe_librdf_free_node); + if (!pWriteBaseURI || !pRelativeURI || !p0 || !p1) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::exportGraph: " + "librdf_new_uri or librdf_new_node_from_literal failed")), *this); + } + + // make URIs relative to base URI + if (librdf_serializer_set_feature(pSerializer.get(), + pRelativeURI.get(), p1.get())) + { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::exportGraph: " + "librdf_serializer_set_feature relativeURIs failed")), *this); + } + // but do not write the base URI to the file! + if (librdf_serializer_set_feature(pSerializer.get(), + pWriteBaseURI.get(), p0.get())) + { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::exportGraph: " + "librdf_serializer_set_feature writeBaseURI failed")), *this); + } + + size_t length; + const boost::shared_ptr<unsigned char> pBuf( + librdf_serializer_serialize_stream_to_counted_string( + pSerializer.get(), pBaseURI.get(), pStream.get(), &length), free); + if (!pBuf) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::exportGraph: " + "librdf_serializer_serialize_stream_to_counted_string failed")), + *this); + } + const uno::Sequence<sal_Int8> buf( + reinterpret_cast<sal_Int8*>(pBuf.get()), length); + // exceptions are propagated + i_xOutStream->writeBytes(buf); +} + +uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL +librdf_Repository::getGraphNames() +throw (uno::RuntimeException, rdf::RepositoryException) +{ + ::osl::MutexGuard g(m_aMutex); + ::comphelper::SequenceAsVector< uno::Reference<rdf::XURI> > ret; + std::transform(m_NamedGraphs.begin(), m_NamedGraphs.end(), + std::back_inserter(ret), + boost::bind(&rdf::XNamedGraph::getName, + boost::bind(&NamedGraphMap_t::value_type::second, _1))); + return ret.getAsConstList(); +} + +uno::Reference< rdf::XNamedGraph > SAL_CALL +librdf_Repository::getGraph(const uno::Reference< rdf::XURI > & i_xGraphName) +throw (uno::RuntimeException, lang::IllegalArgumentException, + rdf::RepositoryException) +{ + ::osl::MutexGuard g(m_aMutex); + if (!i_xGraphName.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::getGraph: " + "URI is null")), *this, 0); + } + const NamedGraphMap_t::iterator iter( + m_NamedGraphs.find(i_xGraphName->getStringValue()) ); + if (iter != m_NamedGraphs.end()) { + return uno::Reference<rdf::XNamedGraph>(iter->second.get()); + } else { + return 0; + } +} + +uno::Reference< rdf::XNamedGraph > SAL_CALL +librdf_Repository::createGraph(const uno::Reference< rdf::XURI > & i_xGraphName) +throw (uno::RuntimeException, lang::IllegalArgumentException, + container::ElementExistException, rdf::RepositoryException) +{ + ::osl::MutexGuard g(m_aMutex); + if (!i_xGraphName.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::createGraph: " + "URI is null")), *this, 0); + } + if (i_xGraphName->getStringValue().matchAsciiL(s_nsOOo, sizeof(s_nsOOo)-1)) + { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::createGraph: " + "URI is reserved")), *this, 0); + } + + // NB: librdf does not have a concept of graphs as such; + // a librdf named graph exists iff the model contains a statement with + // the graph name as context + const ::rtl::OUString contextU( i_xGraphName->getStringValue() ); + if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) { + throw container::ElementExistException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::createGraph: " + "graph with given URI exists")), *this); + } + m_NamedGraphs.insert(std::make_pair(contextU, + new librdf_NamedGraph(this, i_xGraphName))); + return uno::Reference<rdf::XNamedGraph>( + m_NamedGraphs.find(contextU)->second.get()); +} + +void SAL_CALL +librdf_Repository::destroyGraph( + const uno::Reference< rdf::XURI > & i_xGraphName) +throw (uno::RuntimeException, lang::IllegalArgumentException, + container::NoSuchElementException, rdf::RepositoryException) +{ + ::osl::MutexGuard g(m_aMutex); + const NamedGraphMap_t::iterator iter( clearGraph(i_xGraphName) ); + m_NamedGraphs.erase(iter); +} + +static bool isMetadatableWithoutMetadata( + uno::Reference<uno::XInterface> const & i_xNode) +{ + const uno::Reference<rdf::XMetadatable> xMeta( i_xNode, uno::UNO_QUERY ); + return (xMeta.is() && !xMeta->getMetadataReference().Second.getLength()); +} + +uno::Reference< container::XEnumeration > SAL_CALL +librdf_Repository::getStatements( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) +throw (uno::RuntimeException, rdf::RepositoryException) +{ + if (isMetadatableWithoutMetadata(i_xSubject) || + isMetadatableWithoutMetadata(i_xPredicate) || + isMetadatableWithoutMetadata(i_xObject)) + { + return new librdf_GraphResult(this, m_aMutex, + ::boost::shared_ptr<librdf_stream>(), + ::boost::shared_ptr<librdf_node>()); + } + + ::osl::MutexGuard g(m_aMutex); + const boost::shared_ptr<librdf_statement> pStatement( + m_TypeConverter.mkStatement(m_pWorld.get(), + i_xSubject, i_xPredicate, i_xObject), + safe_librdf_free_statement); + OSL_ENSURE(pStatement, "mkStatement failed"); + + const boost::shared_ptr<librdf_stream> pStream( + librdf_model_find_statements(m_pModel.get(), pStatement.get()), + safe_librdf_free_stream); + if (!pStream) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::getStatements: " + "librdf_model_find_statements failed")), *this); + } + + return new librdf_GraphResult(this, m_aMutex, pStream, + ::boost::shared_ptr<librdf_node>()); +} + + +uno::Reference< rdf::XQuerySelectResult > SAL_CALL +librdf_Repository::querySelect(const ::rtl::OUString & i_rQuery) +throw (uno::RuntimeException, rdf::QueryException, rdf::RepositoryException) +{ + ::osl::MutexGuard g(m_aMutex); + const ::rtl::OString query( + ::rtl::OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) ); + const boost::shared_ptr<librdf_query> pQuery( + librdf_new_query(m_pWorld.get(), s_sparql, NULL, + reinterpret_cast<const unsigned char*> (query.getStr()), NULL), + safe_librdf_free_query); + if (!pQuery) { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::querySelect: " + "librdf_new_query failed")), *this); + } + const boost::shared_ptr<librdf_query_results> pResults( + librdf_model_query_execute(m_pModel.get(), pQuery.get()), + safe_librdf_free_query_results); + if (!pResults || !librdf_query_results_is_bindings(pResults.get())) { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::querySelect: " + "query result is null or not bindings")), *this); + } + + const int count( librdf_query_results_get_bindings_count(pResults.get()) ); + if (count >= 0) { + uno::Sequence< ::rtl::OUString > names(count); + for (int i = 0; i < count; ++i) { + const char* name( librdf_query_results_get_binding_name( + pResults.get(), i) ); + if (!name) { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::querySelect: " + "binding is null")), *this); + } + + names[i] = ::rtl::OUString::createFromAscii(name); + } + + return new librdf_QuerySelectResult(this, m_aMutex, + pQuery, pResults, names); + + } else { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::querySelect: " + "librdf_query_results_get_bindings_count failed")), *this); + } +} + +uno::Reference< container::XEnumeration > SAL_CALL +librdf_Repository::queryConstruct(const ::rtl::OUString & i_rQuery) +throw (uno::RuntimeException, rdf::QueryException, rdf::RepositoryException) +{ + ::osl::MutexGuard g(m_aMutex); + const ::rtl::OString query( + ::rtl::OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) ); + const boost::shared_ptr<librdf_query> pQuery( + librdf_new_query(m_pWorld.get(), s_sparql, NULL, + reinterpret_cast<const unsigned char*> (query.getStr()), NULL), + safe_librdf_free_query); + if (!pQuery) { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::queryConstruct: " + "librdf_new_query failed")), *this); + } + const boost::shared_ptr<librdf_query_results> pResults( + librdf_model_query_execute(m_pModel.get(), pQuery.get()), + safe_librdf_free_query_results); + if (!pResults || !librdf_query_results_is_graph(pResults.get())) { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::queryConstruct: " + "query result is null or not graph")), *this); + } + const boost::shared_ptr<librdf_stream> pStream( + librdf_query_results_as_stream(pResults.get()), + safe_librdf_free_stream); + if (!pStream) { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::queryConstruct: " + "librdf_query_results_as_stream failed")), *this); + } + + return new librdf_GraphResult(this, m_aMutex, pStream, + ::boost::shared_ptr<librdf_node>(), pQuery); +} + +::sal_Bool SAL_CALL +librdf_Repository::queryAsk(const ::rtl::OUString & i_rQuery) +throw (uno::RuntimeException, rdf::QueryException, rdf::RepositoryException) +{ + ::osl::MutexGuard g(m_aMutex); + + const ::rtl::OString query( + ::rtl::OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) ); + const boost::shared_ptr<librdf_query> pQuery( + librdf_new_query(m_pWorld.get(), s_sparql, NULL, + reinterpret_cast<const unsigned char*> (query.getStr()), NULL), + safe_librdf_free_query); + if (!pQuery) { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::queryAsk: " + "librdf_new_query failed")), *this); + } + const boost::shared_ptr<librdf_query_results> pResults( + librdf_model_query_execute(m_pModel.get(), pQuery.get()), + safe_librdf_free_query_results); + if (!pResults || !librdf_query_results_is_boolean(pResults.get())) { + throw rdf::QueryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::queryAsk: " + "query result is null or not boolean")), *this); + } + return librdf_query_results_get_boolean(pResults.get()) + ? sal_True : sal_False; +} + +// ::com::sun::star::rdf::XDocumentRepository: +void SAL_CALL librdf_Repository::setStatementRDFa( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates, + const uno::Reference< rdf::XMetadatable > & i_xObject, + const ::rtl::OUString & i_rRDFaContent, + const uno::Reference< rdf::XURI > & i_xRDFaDatatype) +throw (uno::RuntimeException, lang::IllegalArgumentException, + rdf::RepositoryException) +{ + static const ::rtl::OUString s_cell(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.Cell")); + static const ::rtl::OUString s_cellprops(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.CellProperties")); // for writer + static const ::rtl::OUString s_paragraph(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Paragraph")); + static const ::rtl::OUString s_bookmark(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Bookmark")); + static const ::rtl::OUString s_meta( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.text.InContentMetadata")); + + if (!i_xSubject.is()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::setStatementRDFa: Subject is null")), *this, 0); + } + if (!i_rPredicates.getLength()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::setStatementRDFa: no Predicates")), + *this, 1); + } + for (sal_Int32 i = 0; i < i_rPredicates.getLength(); ++i) { + if (!i_rPredicates[i].is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::setStatementRDFa: Predicate is null")), + *this, 1); + } + } + if (!i_xObject.is()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::setStatementRDFa: Object is null")), *this, 2); + } + const uno::Reference<lang::XServiceInfo> xService(i_xObject, + uno::UNO_QUERY_THROW); + uno::Reference<text::XTextRange> xTextRange; + if (xService->supportsService(s_cell) || + xService->supportsService(s_cellprops) || + xService->supportsService(s_paragraph)) + { + xTextRange.set(i_xObject, uno::UNO_QUERY_THROW); + } + else if (xService->supportsService(s_bookmark) || + xService->supportsService(s_meta)) + { + const uno::Reference<text::XTextContent> xTextContent(i_xObject, + uno::UNO_QUERY_THROW); + xTextRange = xTextContent->getAnchor(); + } + if (!xTextRange.is()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::setStatementRDFa: " + "Object does not support RDFa")), *this, 2); + } + // ensure that the metadatable has an XML ID + i_xObject->ensureMetadataReference(); + const beans::StringPair mdref( i_xObject->getMetadataReference() ); + if ((mdref.First.getLength() == 0) || (mdref.Second.getLength() == 0)) { + throw uno::RuntimeException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::setStatementRDFa: " + "ensureMetadataReference did not")), *this); + } + ::rtl::OUString const sXmlId(mdref.First + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("#")) + mdref.Second); + uno::Reference<rdf::XURI> xXmlId; + try { + xXmlId.set( rdf::URI::create(m_xContext, + ::rtl::OUString::createFromAscii(s_nsOOo) + sXmlId), + uno::UNO_QUERY_THROW); + } catch (lang::IllegalArgumentException & iae) { + throw lang::WrappedTargetRuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::setStatementRDFa: " + "cannot create URI for XML ID")), *this, uno::makeAny(iae)); + } + + ::osl::MutexGuard g(m_aMutex); + ::rtl::OUString const content( (i_rRDFaContent.getLength() == 0) + ? xTextRange->getString() + : i_rRDFaContent ); + uno::Reference<rdf::XNode> xContent; + try { + if (i_xRDFaDatatype.is()) { + xContent.set(rdf::Literal::createWithType(m_xContext, + content, i_xRDFaDatatype), + uno::UNO_QUERY_THROW); + } else { + xContent.set(rdf::Literal::create(m_xContext, content), + uno::UNO_QUERY_THROW); + } + } catch (lang::IllegalArgumentException & iae) { + throw lang::WrappedTargetRuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::setStatementRDFa: " + "cannot create literal")), *this, uno::makeAny(iae)); + } + removeStatementRDFa(i_xObject); + if (i_rRDFaContent.getLength() == 0) { + m_RDFaXHTMLContentSet.erase(sXmlId); + } else { + m_RDFaXHTMLContentSet.insert(sXmlId); + } + ::std::for_each(::comphelper::stl_begin(i_rPredicates), + ::comphelper::stl_end(i_rPredicates), + ::boost::bind( &librdf_Repository::addStatementGraph, + this, i_xSubject, _1, xContent, xXmlId, true)); +} + +void SAL_CALL librdf_Repository::removeStatementRDFa( + const uno::Reference< rdf::XMetadatable > & i_xElement) +throw (uno::RuntimeException, lang::IllegalArgumentException, + rdf::RepositoryException) +{ + if (!i_xElement.is()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::removeStatementRDFa: Element is null")), + *this, 0); + } + + const beans::StringPair mdref( i_xElement->getMetadataReference() ); + if ((mdref.First.getLength() == 0) || (mdref.Second.getLength() == 0)) { + return; // nothing to do... + } + uno::Reference<rdf::XURI> xXmlId; + try { + xXmlId.set( rdf::URI::create(m_xContext, + ::rtl::OUString::createFromAscii(s_nsOOo) + + mdref.First + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("#")) + + mdref.Second), + uno::UNO_QUERY_THROW); + } catch (lang::IllegalArgumentException & iae) { + throw lang::WrappedTargetRuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::removeStatementRDFa: " + "cannot create URI for XML ID")), *this, uno::makeAny(iae)); + } + // clearGraph does locking, not needed here + clearGraph(xXmlId, true); +} + +beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL +librdf_Repository::getStatementRDFa( + const uno::Reference< rdf::XMetadatable > & i_xElement) +throw (uno::RuntimeException, lang::IllegalArgumentException, + rdf::RepositoryException) +{ + if (!i_xElement.is()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::getStatementRDFa: Element is null")), *this, 0); + } + const beans::StringPair mdref( i_xElement->getMetadataReference() ); + if ((mdref.First.getLength() == 0) || (mdref.Second.getLength() == 0)) { + return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >(); + } + ::rtl::OUString const sXmlId(mdref.First + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("#")) + mdref.Second); + uno::Reference<rdf::XURI> xXmlId; + try { + xXmlId.set( rdf::URI::create(m_xContext, + ::rtl::OUString::createFromAscii(s_nsOOo) + sXmlId), + uno::UNO_QUERY_THROW); + } catch (lang::IllegalArgumentException & iae) { + throw lang::WrappedTargetRuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::getStatementRDFa: " + "cannot create URI for XML ID")), *this, uno::makeAny(iae)); + } + + ::osl::MutexGuard g(m_aMutex); + ::comphelper::SequenceAsVector< rdf::Statement > ret; + const uno::Reference<container::XEnumeration> xIter( + getStatementsGraph(0, 0, 0, xXmlId, true) ); + OSL_ENSURE(xIter.is(), "getStatementRDFa: no result?"); + if (!xIter.is()) throw uno::RuntimeException(); + while (xIter->hasMoreElements()) { + rdf::Statement stmt; + if (!(xIter->nextElement() >>= stmt)) { + OSL_FAIL("getStatementRDFa: result of wrong type?"); + } else { + ret.push_back(stmt); + } + } + return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >( + ret.getAsConstList(), 0 != m_RDFaXHTMLContentSet.count(sXmlId)); +} + +extern "C" +librdf_statement *rdfa_context_stream_map_handler( + librdf_stream *i_pStream, void *, librdf_statement *i_pStatement) +{ + OSL_ENSURE(i_pStream, "rdfa_context_stream_map_handler: stream null"); + if (i_pStream) { + librdf_node *pCtxt( static_cast<librdf_node *> + (librdf_stream_get_context(i_pStream)) ); + OSL_ENSURE(pCtxt, "rdfa_context_stream_map_handler: context null"); + if (pCtxt && isInternalContext(pCtxt)) { + return i_pStatement; + } + } + return 0; +}; + +uno::Reference< container::XEnumeration > SAL_CALL +librdf_Repository::getStatementsRDFa( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) +throw (uno::RuntimeException, rdf::RepositoryException) +{ + if (isMetadatableWithoutMetadata(i_xSubject) || + isMetadatableWithoutMetadata(i_xPredicate) || + isMetadatableWithoutMetadata(i_xObject)) + { + return new librdf_GraphResult(this, m_aMutex, + ::boost::shared_ptr<librdf_stream>(), + ::boost::shared_ptr<librdf_node>()); + } + + ::osl::MutexGuard g(m_aMutex); + const boost::shared_ptr<librdf_statement> pStatement( + m_TypeConverter.mkStatement(m_pWorld.get(), + i_xSubject, i_xPredicate, i_xObject), + safe_librdf_free_statement); + OSL_ENSURE(pStatement, "mkStatement failed"); + + const boost::shared_ptr<librdf_stream> pStream( + librdf_model_find_statements(m_pModel.get(), pStatement.get()), + safe_librdf_free_stream); + if (!pStream) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::getStatementsRDFa: " + "librdf_model_find_statements failed")), *this); + } + + if (librdf_stream_add_map(pStream.get(), rdfa_context_stream_map_handler, + 0, 0)) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::getStatementsRDFa: " + "librdf_stream_add_map failed")), *this); + } + + return new librdf_GraphResult(this, m_aMutex, pStream, + ::boost::shared_ptr<librdf_node>()); +} + +// ::com::sun::star::lang::XInitialization: +void SAL_CALL librdf_Repository::initialize( + const uno::Sequence< ::com::sun::star::uno::Any > & i_rArguments) +throw (uno::RuntimeException, uno::Exception) +{ + (void) i_rArguments; + + ::osl::MutexGuard g(m_aMutex); + +// m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world); + m_pStorage.reset(m_TypeConverter.createStorage(m_pWorld.get()), + safe_librdf_free_storage); + m_pModel.reset(m_TypeConverter.createModel( + m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model); +} + +const NamedGraphMap_t::iterator SAL_CALL librdf_Repository::clearGraph( + const uno::Reference< rdf::XURI > & i_xGraphName, bool i_Internal) +// throw (uno::RuntimeException, container::NoSuchElementException, +// rdf::RepositoryException) +{ + if (!i_xGraphName.is()) { + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::clearGraph: " + "URI is null")), *this, 0); + } + ::osl::MutexGuard g(m_aMutex); + const ::rtl::OUString contextU( i_xGraphName->getStringValue() ); + const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) ); + if (!i_Internal && iter == m_NamedGraphs.end()) { + throw container::NoSuchElementException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::clearGraph: " + "no graph with given URI exists")), *this); + } + const ::rtl::OString context( + ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); + + const boost::shared_ptr<librdf_node> pContext( + librdf_new_node_from_uri_string(m_pWorld.get(), + reinterpret_cast<const unsigned char*> (context.getStr())), + safe_librdf_free_node); + if (!pContext) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::clearGraph: " + "librdf_new_node_from_uri_string failed")), *this); + } + if (librdf_model_context_remove_statements(m_pModel.get(), pContext.get())) + { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::clearGraph: " + "librdf_model_context_remove_statements failed")), *this); + } + return iter; +} + +void SAL_CALL librdf_Repository::addStatementGraph( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject, + const uno::Reference< rdf::XURI > & i_xGraphName, + bool i_Internal) +//throw (uno::RuntimeException, lang::IllegalArgumentException, +// container::NoSuchElementException, rdf::RepositoryException) +{ + if (!i_xSubject.is()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::addStatement: Subject is null")), *this, 0); + } + if (!i_xPredicate.is()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::addStatement: Predicate is null")), + *this, 1); + } + if (!i_xObject.is()) { + throw lang::IllegalArgumentException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::addStatement: Object is null")), *this, 2); + } + + ::osl::MutexGuard g(m_aMutex); + const ::rtl::OUString contextU( i_xGraphName->getStringValue() ); + if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) { + throw container::NoSuchElementException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("librdf_Repository::addStatement: " + "no graph with given URI exists")), *this); + } + const ::rtl::OString context( + ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); + + const boost::shared_ptr<librdf_node> pContext( + librdf_new_node_from_uri_string(m_pWorld.get(), + reinterpret_cast<const unsigned char*> (context.getStr())), + safe_librdf_free_node); + if (!pContext) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::addStatement: " + "librdf_new_node_from_uri_string failed")), *this); + } + const boost::shared_ptr<librdf_statement> pStatement( + m_TypeConverter.mkStatement(m_pWorld.get(), + i_xSubject, i_xPredicate, i_xObject), + safe_librdf_free_statement); + OSL_ENSURE(pStatement, "mkStatement failed"); + + // Test for duplicate statement + // librdf_model_add_statement disallows duplicates while + // librdf_model_context_add_statement allows duplicates + { + const boost::shared_ptr<librdf_stream> pStream( + librdf_model_find_statements_in_context(m_pModel.get(), + pStatement.get(), pContext.get()), + safe_librdf_free_stream); + if (pStream && !librdf_stream_end(pStream.get())) + return; + } + + if (librdf_model_context_add_statement(m_pModel.get(), + pContext.get(), pStatement.get())) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::addStatement: " + "librdf_model_context_add_statement failed")), *this); + } +} + +void SAL_CALL librdf_Repository::removeStatementsGraph( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject, + const uno::Reference< rdf::XURI > & i_xGraphName) +//throw (uno::RuntimeException, lang::IllegalArgumentException, +// container::NoSuchElementException, rdf::RepositoryException) +{ + if (isMetadatableWithoutMetadata(i_xSubject) || + isMetadatableWithoutMetadata(i_xPredicate) || + isMetadatableWithoutMetadata(i_xObject)) + { + return; + } + + ::osl::MutexGuard g(m_aMutex); + const ::rtl::OUString contextU( i_xGraphName->getStringValue() ); + if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) { + throw container::NoSuchElementException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::removeStatements: " + "no graph with given URI exists")), *this); + } + const ::rtl::OString context( + ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); + + const boost::shared_ptr<librdf_node> pContext( + librdf_new_node_from_uri_string(m_pWorld.get(), + reinterpret_cast<const unsigned char*> (context.getStr())), + safe_librdf_free_node); + if (!pContext) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::removeStatements: " + "librdf_new_node_from_uri_string failed")), *this); + } + const boost::shared_ptr<librdf_statement> pStatement( + m_TypeConverter.mkStatement(m_pWorld.get(), + i_xSubject, i_xPredicate, i_xObject), + safe_librdf_free_statement); + OSL_ENSURE(pStatement, "mkStatement failed"); + + const boost::shared_ptr<librdf_stream> pStream( + librdf_model_find_statements_in_context(m_pModel.get(), + pStatement.get(), pContext.get()), + safe_librdf_free_stream); + if (!pStream) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::removeStatements: " + "librdf_model_find_statements_in_context failed")), *this); + } + + if (!librdf_stream_end(pStream.get())) { + do { + librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) ); + if (!pStmt) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::removeStatements: " + "librdf_stream_get_object failed")), *this); + } + if (librdf_model_context_remove_statement(m_pModel.get(), + pContext.get(), pStmt)) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::removeStatements: " + "librdf_model_context_remove_statement failed")), *this); + } + } while (!librdf_stream_next(pStream.get())); + } +} + +uno::Reference< container::XEnumeration > SAL_CALL +librdf_Repository::getStatementsGraph( + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject, + const uno::Reference< rdf::XURI > & i_xGraphName, + bool i_Internal) +//throw (uno::RuntimeException, lang::IllegalArgumentException, +// container::NoSuchElementException, rdf::RepositoryException) +{ + // N.B.: if any of subject, predicate, object is an XMetadatable, and + // has no metadata reference, then there cannot be any node in the graph + // representing it; in order to prevent side effect + // (ensureMetadataReference), check for this condition and return + if (isMetadatableWithoutMetadata(i_xSubject) || + isMetadatableWithoutMetadata(i_xPredicate) || + isMetadatableWithoutMetadata(i_xObject)) + { + return new librdf_GraphResult(this, m_aMutex, + ::boost::shared_ptr<librdf_stream>(), + ::boost::shared_ptr<librdf_node>()); + } + + ::osl::MutexGuard g(m_aMutex); + const ::rtl::OUString contextU( i_xGraphName->getStringValue() ); + if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) { + throw container::NoSuchElementException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::getStatements: " + "no graph with given URI exists")), *this); + } + const ::rtl::OString context( + ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); + + const boost::shared_ptr<librdf_node> pContext( + librdf_new_node_from_uri_string(m_pWorld.get(), + reinterpret_cast<const unsigned char*> (context.getStr())), + safe_librdf_free_node); + if (!pContext) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::getStatements: " + "librdf_new_node_from_uri_string failed")), *this); + } + const boost::shared_ptr<librdf_statement> pStatement( + m_TypeConverter.mkStatement(m_pWorld.get(), + i_xSubject, i_xPredicate, i_xObject), + safe_librdf_free_statement); + OSL_ENSURE(pStatement, "mkStatement failed"); + + const boost::shared_ptr<librdf_stream> pStream( + librdf_model_find_statements_in_context(m_pModel.get(), + pStatement.get(), pContext.get()), + safe_librdf_free_stream); + if (!pStream) { + throw rdf::RepositoryException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository::getStatements: " + "librdf_model_find_statements_in_context failed")), *this); + } + + // librdf_model_find_statements_in_context is buggy and does not put + // the context into result statements; pass it to librdf_GraphResult here + return new librdf_GraphResult(this, m_aMutex, pStream, pContext); +} + +librdf_world *librdf_TypeConverter::createWorld() const +{ + // create and initialize world + librdf_world *pWorld( librdf_new_world() ); + if (!pWorld) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::createWorld: librdf_new_world failed")), + m_rRep); + } + //FIXME logger, digest, features? + xsltSecurityPrefsPtr origprefs = xsltGetDefaultSecurityPrefs(); + librdf_world_open(pWorld); + xsltSecurityPrefsPtr newprefs = xsltGetDefaultSecurityPrefs(); + if (newprefs != origprefs) { + // #i110523# restore libxslt global configuration + // (gratuitously overwritten by raptor_init_parser_grddl_common) + // (this is the only reason unordf is linked against libxslt) + xsltSetDefaultSecurityPrefs(origprefs); + } + return pWorld; +} + +librdf_storage * +librdf_TypeConverter::createStorage(librdf_world *i_pWorld) const +{ + librdf_storage *pStorage( +// librdf_new_storage(i_pWorld, "memory", NULL, "contexts='yes'") ); + librdf_new_storage(i_pWorld, "hashes", NULL, + "contexts='yes',hash-type='memory'") ); + if (!pStorage) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::createStorage: librdf_new_storage failed")), + m_rRep); + } + return pStorage; +} + +librdf_model *librdf_TypeConverter::createModel( + librdf_world *i_pWorld, librdf_storage * i_pStorage) const +{ + librdf_model *pRepository( librdf_new_model(i_pWorld, i_pStorage, NULL) ); + if (!pRepository) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::createModel: librdf_new_model failed")), + m_rRep); + } + //FIXME +#if 0 + { + librdf_uri * ctxt = librdf_new_uri(i_pWorld, reinterpret_cast<const unsigned char *>(LIBRDF_MODEL_FEATURE_CONTEXTS)); + librdf_node * contexts = librdf_model_get_feature(repository, ctxt); + if (!contexts) + throw; + std::cout << "value of contexts feature: "; + prtNode(contexts); + std::cout << std::endl; + // librdf_model_set_feature(repository, LIBRDF_FEATURE_CONTEXTS, ...); + safe_librdf_free_node(contexts); + safe_librdf_free_uri(ctxt); + } +#endif + return pRepository; +} + +// this does NOT create a node, only URI +librdf_uri* librdf_TypeConverter::mkURI( librdf_world* i_pWorld, + const uno::Reference< rdf::XURI > & i_xURI) const +{ + const ::rtl::OString uri( + ::rtl::OUStringToOString(i_xURI->getStringValue(), + RTL_TEXTENCODING_UTF8) ); + librdf_uri *pURI( librdf_new_uri(i_pWorld, + reinterpret_cast<const unsigned char *>(uri.getStr()))); + if (!pURI) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::mkURI: librdf_new_uri failed")), 0); + } + return pURI; +} + +// create blank or URI node +librdf_node* librdf_TypeConverter::mkResource( librdf_world* i_pWorld, + const uno::Reference< rdf::XResource > & i_xResource) const +{ + if (!i_xResource.is()) return 0; + uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY); + if (xBlankNode.is()) { + const ::rtl::OString label( + ::rtl::OUStringToOString(xBlankNode->getStringValue(), + RTL_TEXTENCODING_UTF8) ); + librdf_node *pNode( + librdf_new_node_from_blank_identifier(i_pWorld, + reinterpret_cast<const unsigned char*> (label.getStr()))); + if (!pNode) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::mkResource: " + "librdf_new_node_from_blank_identifier failed")), 0); + } + return pNode; + } else { // assumption: everything else is URI + const ::rtl::OString uri( + ::rtl::OUStringToOString(i_xResource->getStringValue(), + RTL_TEXTENCODING_UTF8) ); + librdf_node *pNode( + librdf_new_node_from_uri_string(i_pWorld, + reinterpret_cast<const unsigned char*> (uri.getStr()))); + if (!pNode) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::mkResource: " + "librdf_new_node_from_uri_string failed")), 0); + } + return pNode; + } +} + +// create blank or URI or literal node +librdf_node* librdf_TypeConverter::mkNode( librdf_world* i_pWorld, + const uno::Reference< rdf::XNode > & i_xNode) const +{ + if (!i_xNode.is()) return 0; + uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY); + if (xResource.is()) { + return mkResource(i_pWorld, xResource); + } + uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY); + OSL_ENSURE(xLiteral.is(), + "mkNode: someone invented a new rdf.XNode and did not tell me"); + if (!xLiteral.is()) return 0; + const ::rtl::OString val( + ::rtl::OUStringToOString(xLiteral->getValue(), + RTL_TEXTENCODING_UTF8) ); + const ::rtl::OString lang( + ::rtl::OUStringToOString(xLiteral->getLanguage(), + RTL_TEXTENCODING_UTF8) ); + const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype()); + librdf_node * ret(0); + if (lang.getLength() == 0) { + if (!xType.is()) { + ret = librdf_new_node_from_literal(i_pWorld, + reinterpret_cast<const unsigned char*> (val.getStr()), + NULL, 0); + } else { + const boost::shared_ptr<librdf_uri> pDatatype( + mkURI(i_pWorld, xType), safe_librdf_free_uri); + ret = librdf_new_node_from_typed_literal(i_pWorld, + reinterpret_cast<const unsigned char*> (val.getStr()), + NULL, pDatatype.get()); + } + } else { + if (!xType.is()) { + ret = librdf_new_node_from_literal(i_pWorld, + reinterpret_cast<const unsigned char*> (val.getStr()), + (lang.getStr()), 0); + + } else { + OSL_FAIL("mkNode: invalid literal"); + return 0; + } + } + if (!ret) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::mkNode: " + "librdf_new_node_from_literal failed")), 0); + } + return ret; +} + +librdf_statement* librdf_TypeConverter::mkStatement( librdf_world* i_pWorld, + const uno::Reference< rdf::XResource > & i_xSubject, + const uno::Reference< rdf::XURI > & i_xPredicate, + const uno::Reference< rdf::XNode > & i_xObject) const +{ + librdf_node* pSubject( mkResource(i_pWorld, i_xSubject) ); + librdf_node* pPredicate(0); + librdf_node* pObject(0); + try { + const uno::Reference<rdf::XResource> xPredicate(i_xPredicate, + uno::UNO_QUERY); + pPredicate = mkResource(i_pWorld, xPredicate); + try { + pObject = mkNode(i_pWorld, i_xObject); + } catch (...) { + safe_librdf_free_node(pPredicate); + throw; + } + } catch (...) { + safe_librdf_free_node(pSubject); + throw; + } + // NB: this takes ownership of the nodes! (which is really ugly) + librdf_statement* pStatement( librdf_new_statement_from_nodes(i_pWorld, + pSubject, pPredicate, pObject) ); + if (!pStatement) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::mkStatement: " + "librdf_new_statement_from_nodes failed")), 0); + } + return pStatement; +} + +uno::Reference<rdf::XURI> +librdf_TypeConverter::convertToXURI(librdf_uri* i_pURI) const +{ + if (!i_pURI) return 0; + const unsigned char* uri( librdf_uri_as_string(i_pURI) ); + if (!uri) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::convertToXURI: " + "librdf_uri_as_string failed")), m_rRep); + } + ::rtl::OUString uriU( ::rtl::OStringToOUString( + ::rtl::OString(reinterpret_cast<const sal_Char*>(uri)), + RTL_TEXTENCODING_UTF8) ); + try { + return rdf::URI::create(m_xContext, uriU); + } catch (lang::IllegalArgumentException & iae) { + throw lang::WrappedTargetRuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::convertToXURI: " + "illegal uri")), m_rRep, uno::makeAny(iae)); + } +} + +uno::Reference<rdf::XURI> +librdf_TypeConverter::convertToXURI(librdf_node* i_pNode) const +{ + if (!i_pNode) return 0; + if (librdf_node_is_resource(i_pNode)) { + librdf_uri* pURI( librdf_node_get_uri(i_pNode) ); + if (!pURI) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::convertToXURI: " + "resource has no uri")), m_rRep); + } + return convertToXURI(pURI); + } else { + OSL_FAIL("convertToXURI: unknown librdf_node"); + return 0; + } +} + +uno::Reference<rdf::XResource> +librdf_TypeConverter::convertToXResource(librdf_node* i_pNode) const +{ + if (!i_pNode) return 0; + if (librdf_node_is_blank(i_pNode)) { + const unsigned char* label( librdf_node_get_blank_identifier(i_pNode) ); + if (!label) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::convertToXResource: " + "blank node has no label")), m_rRep); + } + ::rtl::OUString labelU( ::rtl::OStringToOUString( + ::rtl::OString(reinterpret_cast<const sal_Char*>(label)), + RTL_TEXTENCODING_UTF8) ); + try { + return uno::Reference<rdf::XResource>( + rdf::BlankNode::create(m_xContext, labelU), uno::UNO_QUERY); + } catch (lang::IllegalArgumentException & iae) { + throw lang::WrappedTargetRuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::convertToXResource: " + "illegal blank node label")), m_rRep, uno::makeAny(iae)); + } + } else { + return uno::Reference<rdf::XResource>(convertToXURI(i_pNode), + uno::UNO_QUERY); + } +} + +uno::Reference<rdf::XNode> +librdf_TypeConverter::convertToXNode(librdf_node* i_pNode) const +{ + if (!i_pNode) return 0; + if (!librdf_node_is_literal(i_pNode)) { + return uno::Reference<rdf::XNode>(convertToXResource(i_pNode), + uno::UNO_QUERY); + } + const unsigned char* value( librdf_node_get_literal_value(i_pNode) ); + if (!value) { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_TypeConverter::convertToXNode: " + "literal has no value")), m_rRep); + } + const char * lang( librdf_node_get_literal_value_language(i_pNode) ); + librdf_uri* pType( + librdf_node_get_literal_value_datatype_uri(i_pNode) ); + OSL_ENSURE(!lang || !pType, "convertToXNode: invalid literal"); + const ::rtl::OUString valueU( ::rtl::OStringToOUString( + ::rtl::OString(reinterpret_cast<const sal_Char*>(value)), + RTL_TEXTENCODING_UTF8) ); + if (lang) { + const ::rtl::OUString langU( ::rtl::OStringToOUString( + ::rtl::OString(reinterpret_cast<const sal_Char*>(lang)), + RTL_TEXTENCODING_UTF8) ); + return uno::Reference<rdf::XNode>( + rdf::Literal::createWithLanguage(m_xContext, valueU, langU), + uno::UNO_QUERY); + } else if (pType) { + uno::Reference<rdf::XURI> xType(convertToXURI(pType)); + OSL_ENSURE(xType.is(), "convertToXNode: null uri"); + return uno::Reference<rdf::XNode>( + rdf::Literal::createWithType(m_xContext, valueU, xType), + uno::UNO_QUERY); + } else { + return uno::Reference<rdf::XNode>( + rdf::Literal::create(m_xContext, valueU), + uno::UNO_QUERY); + } +} + +rdf::Statement +librdf_TypeConverter::convertToStatement(librdf_statement* i_pStmt, + librdf_node* i_pContext) const +{ + if (!i_pStmt) { + throw uno::RuntimeException(); + } + return rdf::Statement( + convertToXResource(librdf_statement_get_subject(i_pStmt)), + convertToXURI(librdf_statement_get_predicate(i_pStmt)), + convertToXNode(librdf_statement_get_object(i_pStmt)), + convertToXURI(i_pContext)); +} + +} // closing anonymous implementation namespace + + + +// component helper namespace +namespace comp_librdf_Repository { + +::rtl::OUString SAL_CALL _getImplementationName() { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "librdf_Repository")); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames() +{ + uno::Sequence< ::rtl::OUString > s(1); + s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.rdf.Repository")); + return s; +} + +uno::Reference< uno::XInterface > SAL_CALL _create( + const uno::Reference< uno::XComponentContext > & context) + SAL_THROW((uno::Exception)) +{ + return static_cast< ::cppu::OWeakObject * >(new librdf_Repository(context)); +} + +} // closing component helper namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/rdf/librdf_repository.hxx b/unoxml/source/rdf/librdf_repository.hxx new file mode 100644 index 000000000000..10bff77ac7a9 --- /dev/null +++ b/unoxml/source/rdf/librdf_repository.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _LIBRDF_REPOSITORY_HXX +#define _LIBRDF_REPOSITORY_HXX + +#include <sal/config.h> +#include <cppuhelper/factory.hxx> + + +// component helper namespace +namespace comp_librdf_Repository { + +namespace css = ::com::sun::star; + +// component and service helper functions: +::rtl::OUString SAL_CALL _getImplementationName(); +css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames(); +css::uno::Reference< css::uno::XInterface > SAL_CALL _create( css::uno::Reference< css::uno::XComponentContext > const & context ); + +} // closing component helper namespace + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/rdf/librdf_services.cxx b/unoxml/source/rdf/librdf_services.cxx new file mode 100644 index 000000000000..d1ff568a2369 --- /dev/null +++ b/unoxml/source/rdf/librdf_services.cxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> + +#include "CNodes.hxx" +#include "librdf_repository.hxx" + + +using namespace ::com::sun::star; + + +extern "C" +{ + +static ::cppu::ImplementationEntry const entries[] = { + { &comp_CBlankNode::_create, + &comp_CBlankNode::_getImplementationName, + &comp_CBlankNode::_getSupportedServiceNames, + &::cppu::createSingleComponentFactory, 0, 0 }, + { &comp_CURI::_create, + &comp_CURI::_getImplementationName, + &comp_CURI::_getSupportedServiceNames, + &::cppu::createSingleComponentFactory, 0, 0 }, + { &comp_CLiteral::_create, + &comp_CLiteral::_getImplementationName, + &comp_CLiteral::_getSupportedServiceNames, + &::cppu::createSingleComponentFactory, 0, 0 }, + { &comp_librdf_Repository::_create, + &comp_librdf_Repository::_getImplementationName, + &comp_librdf_Repository::_getSupportedServiceNames, + &::cppu::createSingleComponentFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } +}; + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL unordf_component_getFactory( + const char * implName, void * serviceManager, void * registryKey) +{ + return ::cppu::component_getFactoryHelper( + implName, serviceManager, registryKey, entries); +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/rdf/unordf.component b/unoxml/source/rdf/unordf.component new file mode 100644 index 000000000000..12a01ca6cf8c --- /dev/null +++ b/unoxml/source/rdf/unordf.component @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" prefix="unordf" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="CBlankNode"> + <service name="com.sun.star.rdf.BlankNode"/> + </implementation> + <implementation name="CLiteral"> + <service name="com.sun.star.rdf.Literal"/> + </implementation> + <implementation name="CURI"> + <service name="com.sun.star.rdf.URI"/> + </implementation> + <implementation name="librdf_Repository"> + <service name="com.sun.star.rdf.Repository"/> + </implementation> +</component> diff --git a/unoxml/source/service/services.cxx b/unoxml/source/service/services.cxx new file mode 100644 index 000000000000..f9c024f7392a --- /dev/null +++ b/unoxml/source/service/services.cxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <osl/mutex.hxx> +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Reference.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <cppuhelper/factory.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <cppuhelper/factory.hxx> + +#include "../dom/documentbuilder.hxx" +#include "../dom/saxbuilder.hxx" +#include "../xpath/xpathapi.hxx" +#include "../events/testlistener.hxx" + +using namespace ::DOM; +using namespace ::DOM::events; +using namespace ::XPath; +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +extern "C" +{ + +SAL_DLLPUBLIC_EXPORT void* SAL_CALL unoxml_component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void * /*pRegistryKey*/) +{ + void* pReturn = NULL ; + if ( pImplementationName && pServiceManager ) + { + // Define variables which are used in following macros. + Reference< XSingleServiceFactory > xFactory; + Reference< XMultiServiceFactory > xServiceManager( + reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); + + if (CDocumentBuilder::_getImplementationName().compareToAscii( pImplementationName ) == 0 ) + { + xFactory = Reference< XSingleServiceFactory >( + cppu::createOneInstanceFactory( + xServiceManager, CDocumentBuilder::_getImplementationName(), + CDocumentBuilder::_getInstance, CDocumentBuilder::_getSupportedServiceNames())); + } + else if (CSAXDocumentBuilder::_getImplementationName().compareToAscii( pImplementationName ) == 0 ) + { + xFactory = Reference< XSingleServiceFactory >( + cppu::createSingleFactory( + xServiceManager, CSAXDocumentBuilder::_getImplementationName(), + CSAXDocumentBuilder::_getInstance, CSAXDocumentBuilder::_getSupportedServiceNames())); + } + else if (CXPathAPI::_getImplementationName().compareToAscii( pImplementationName ) == 0 ) + { + xFactory = Reference< XSingleServiceFactory >( + cppu::createSingleFactory( + xServiceManager, CXPathAPI::_getImplementationName(), + CXPathAPI::_getInstance, CXPathAPI::_getSupportedServiceNames())); + } + else if (CTestListener::_getImplementationName().compareToAscii( pImplementationName ) == 0 ) + { + xFactory = Reference< XSingleServiceFactory >( + cppu::createSingleFactory( + xServiceManager, CTestListener::_getImplementationName(), + CTestListener::_getInstance, CTestListener::_getSupportedServiceNames())); + } + + // Factory is valid - service was found. + if ( xFactory.is() ) + { + xFactory->acquire(); + pReturn = xFactory.get(); + } + } + + // Return with result of this operation. + return pReturn ; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/service/unoxml.component b/unoxml/source/service/unoxml.component new file mode 100644 index 000000000000..889a755e22c5 --- /dev/null +++ b/unoxml/source/service/unoxml.component @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" prefix="unoxml" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.xml.dom.DocumentBuilder"> + <service name="com.sun.star.xml.dom.DocumentBuilder"/> + </implementation> + <implementation name="com.sun.star.comp.xml.dom.SAXDocumentBuilder"> + <service name="com.sun.star.xml.dom.SAXDocumentBuilder"/> + </implementation> + <implementation name="com.sun.star.comp.xml.dom.events.TestListener"> + <service name="com.sun.star.comp.xml.dom.events.TestListener"/> + </implementation> + <implementation name="com.sun.star.comp.xml.xpath.XPathAPI"> + <service name="com.sun.star.xml.xpath.XPathAPI"/> + </implementation> +</component> diff --git a/unoxml/source/xpath/nodelist.cxx b/unoxml/source/xpath/nodelist.cxx new file mode 100644 index 000000000000..6d9d4b78528f --- /dev/null +++ b/unoxml/source/xpath/nodelist.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <nodelist.hxx> + +#include "../dom/document.hxx" + +namespace XPath +{ + CNodeList::CNodeList( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + boost::shared_ptr<xmlXPathObject> const& rxpathObj) + : m_pDocument(pDocument) + , m_rMutex(rMutex) + , m_pNodeSet(0) + { + if (rxpathObj != NULL && rxpathObj->type == XPATH_NODESET) + { + m_pNodeSet = rxpathObj->nodesetval; + m_pXPathObj = rxpathObj; + } + } + + /** + The number of nodes in the list. + */ + sal_Int32 SAL_CALL CNodeList::getLength() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + sal_Int32 value = 0; + if (m_pNodeSet != NULL) + value = xmlXPathNodeSetGetLength(m_pNodeSet); + return value; + } + + /** + Returns the indexth item in the collection. + */ + Reference< XNode > SAL_CALL CNodeList::item(sal_Int32 index) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_pNodeSet) { + return 0; + } + xmlNodePtr const pNode = xmlXPathNodeSetItem(m_pNodeSet, index); + Reference< XNode > const xNode(m_pDocument->GetCNode(pNode).get()); + return xNode; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/xpath/nodelist.hxx b/unoxml/source/xpath/nodelist.hxx new file mode 100644 index 000000000000..ed3543ee815e --- /dev/null +++ b/unoxml/source/xpath/nodelist.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 XPATH_NODELIST_HXX +#define XPATH_NODELIST_HXX + +#include <sal/types.h> +#include <rtl/ref.hxx> + +#include <cppuhelper/implbase1.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> + +#include "libxml/tree.h" +#include "libxml/xpath.h" + +#include <boost/shared_ptr.hpp> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::xpath; + +namespace DOM { + class CDocument; +} + +namespace XPath +{ + + class CNodeList : public cppu::WeakImplHelper1< XNodeList > + { + private: + /// #i115995# keep document alive + ::rtl::Reference< DOM::CDocument > const m_pDocument; + ::osl::Mutex & m_rMutex; + /// retain the result set in case the CXPathObject is released + boost::shared_ptr<xmlXPathObject> m_pXPathObj; + xmlNodeSetPtr m_pNodeSet; + + public: + CNodeList( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + boost::shared_ptr<xmlXPathObject> const& rxpathObj); + /** + The number of nodes in the list. + */ + virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); + /** + Returns the indexth item in the collection. + */ + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/xpath/xpathapi.cxx b/unoxml/source/xpath/xpathapi.cxx new file mode 100644 index 000000000000..dac4b2e2ca9d --- /dev/null +++ b/unoxml/source/xpath/xpathapi.cxx @@ -0,0 +1,458 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <xpathapi.hxx> + +#include <stdarg.h> +#include <string.h> + +#include <libxml/tree.h> +#include <libxml/xmlerror.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> + +#include <rtl/ustrbuf.hxx> + +#include <nodelist.hxx> +#include <xpathobject.hxx> + +#include "../dom/node.hxx" +#include "../dom/document.hxx" + + +using ::com::sun::star::lang::XMultiServiceFactory; + + +namespace XPath +{ + // factory + Reference< XInterface > CXPathAPI::_getInstance(const Reference< XMultiServiceFactory >& rSMgr) + { + return Reference< XInterface >(static_cast<XXPathAPI*>(new CXPathAPI(rSMgr))); + } + + // ctor + CXPathAPI::CXPathAPI(const Reference< XMultiServiceFactory >& rSMgr) + : m_aFactory(rSMgr) + { + } + + const char* CXPathAPI::aImplementationName = "com.sun.star.comp.xml.xpath.XPathAPI"; + const char* CXPathAPI::aSupportedServiceNames[] = { + "com.sun.star.xml.xpath.XPathAPI", + NULL + }; + + OUString CXPathAPI::_getImplementationName() + { + return OUString::createFromAscii(aImplementationName); + } + + Sequence<OUString> CXPathAPI::_getSupportedServiceNames() + { + Sequence<OUString> aSequence; + for (int i=0; aSupportedServiceNames[i]!=NULL; i++) { + aSequence.realloc(i+1); + aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i])); + } + return aSequence; + } + + Sequence< OUString > SAL_CALL CXPathAPI::getSupportedServiceNames() + throw (RuntimeException) + { + return CXPathAPI::_getSupportedServiceNames(); + } + + OUString SAL_CALL CXPathAPI::getImplementationName() + throw (RuntimeException) + { + return CXPathAPI::_getImplementationName(); + } + + sal_Bool SAL_CALL CXPathAPI::supportsService(const OUString& aServiceName) + throw (RuntimeException) + { + Sequence< OUString > supported = CXPathAPI::_getSupportedServiceNames(); + for (sal_Int32 i=0; i<supported.getLength(); i++) + { + if (supported[i] == aServiceName) return sal_True; + } + return sal_False; + } + + // ------------------------------------------------------------------- + + void SAL_CALL CXPathAPI::registerNS( + const OUString& aPrefix, + const OUString& aURI) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + m_nsmap.insert(nsmap_t::value_type(aPrefix, aURI)); + } + + void SAL_CALL CXPathAPI::unregisterNS( + const OUString& aPrefix, + const OUString& aURI) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + if ((m_nsmap.find(aPrefix))->second.equals(aURI)) { + m_nsmap.erase(aPrefix); + } + } + + // register all namespaces stored in the namespace list for this object + // with the current xpath evaluation context + static void lcl_registerNamespaces( + xmlXPathContextPtr ctx, + const nsmap_t& nsmap) + { + nsmap_t::const_iterator i = nsmap.begin(); + OString oprefix, ouri; + xmlChar *p, *u; + while (i != nsmap.end()) + { + oprefix = OUStringToOString(i->first, RTL_TEXTENCODING_UTF8); + ouri = OUStringToOString(i->second, RTL_TEXTENCODING_UTF8); + p = (xmlChar*)oprefix.getStr(); + u = (xmlChar*)ouri.getStr(); + xmlXPathRegisterNs(ctx, p, u); + ++i; + } + } + + // get all ns decls on a node (and parent nodes, if any) + static void lcl_collectNamespaces( + nsmap_t & rNamespaces, Reference< XNode > const& xNamespaceNode) + { + DOM::CNode *const pCNode(DOM::CNode::GetImplementation(xNamespaceNode)); + if (!pCNode) { throw RuntimeException(); } + + ::osl::MutexGuard const g(pCNode->GetOwnerDocument().GetMutex()); + + xmlNodePtr pNode = pCNode->GetNodePtr(); + while (pNode != 0) { + xmlNsPtr curDef = pNode->nsDef; + while (curDef != 0) { + const xmlChar* xHref = curDef->href; + OUString aURI((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8); + const xmlChar* xPre = curDef->prefix; + OUString aPrefix((sal_Char*)xPre, strlen((char*)xPre), RTL_TEXTENCODING_UTF8); + // we could already have this prefix from a child node + if (rNamespaces.find(aPrefix) == rNamespaces.end()) + { + rNamespaces.insert(::std::make_pair(aPrefix, aURI)); + } + curDef = curDef->next; + } + pNode = pNode->parent; + } + } + + static void lcl_collectRegisterNamespaces( + CXPathAPI & rAPI, Reference< XNode > const& xNamespaceNode) + { + nsmap_t namespaces; + lcl_collectNamespaces(namespaces, xNamespaceNode); + for (nsmap_t::const_iterator iter = namespaces.begin(); + iter != namespaces.end(); ++iter) + { + rAPI.registerNS(iter->first, iter->second); + } + } + + // register function and variable lookup functions with the current + // xpath evaluation context + static void lcl_registerExtensions( + xmlXPathContextPtr ctx, + const extensions_t& extensions) + { + extensions_t::const_iterator i = extensions.begin(); + while (i != extensions.end()) + { + Libxml2ExtensionHandle aHandle = (*i)->getLibxml2ExtensionHandle(); + if ( aHandle.functionLookupFunction != 0 ) + { + xmlXPathRegisterFuncLookup(ctx, + reinterpret_cast<xmlXPathFuncLookupFunc>( + sal::static_int_cast<sal_IntPtr>(aHandle.functionLookupFunction)), + reinterpret_cast<void*>( + sal::static_int_cast<sal_IntPtr>(aHandle.functionData))); + } + if ( aHandle.variableLookupFunction != 0 ) + { + xmlXPathRegisterVariableLookup(ctx, + reinterpret_cast<xmlXPathVariableLookupFunc>( + sal::static_int_cast<sal_IntPtr>(aHandle.variableLookupFunction)), + reinterpret_cast<void*>( + sal::static_int_cast<sal_IntPtr>(aHandle.variableData))); + } + ++i; + } + } + + /** + * Use an XPath string to select a nodelist. + */ + Reference< XNodeList > SAL_CALL CXPathAPI::selectNodeList( + const Reference< XNode >& contextNode, + const OUString& expr) + throw (RuntimeException, XPathException) + { + Reference< XXPathObject > xobj = eval(contextNode, expr); + return xobj->getNodeList(); + } + + /** + * same as selectNodeList but registers all name space decalratiosn found on namespaceNode + */ + Reference< XNodeList > SAL_CALL CXPathAPI::selectNodeListNS( + const Reference< XNode >& contextNode, + const OUString& expr, + const Reference< XNode >& namespaceNode) + throw (RuntimeException, XPathException) + { + lcl_collectRegisterNamespaces(*this, namespaceNode); + return selectNodeList(contextNode, expr); + } + + /** + * Same as selectNodeList but returns the first node (if any) + */ + Reference< XNode > SAL_CALL CXPathAPI::selectSingleNode( + const Reference< XNode >& contextNode, + const OUString& expr) + throw (RuntimeException, XPathException) + { + Reference< XNodeList > aList = selectNodeList(contextNode, expr); + Reference< XNode > aNode = aList->item(0); + return aNode; + } + + /** + * Same as selectSingleNode but registers all namespaces declared on + * namespaceNode + */ + Reference< XNode > SAL_CALL CXPathAPI::selectSingleNodeNS( + const Reference< XNode >& contextNode, + const OUString& expr, + const Reference< XNode >& namespaceNode ) + throw (RuntimeException, XPathException) + { + lcl_collectRegisterNamespaces(*this, namespaceNode); + return selectSingleNode(contextNode, expr); + } + + static OUString make_error_message(xmlErrorPtr pError) + { + ::rtl::OUStringBuffer buf; + if (pError->message) { + buf.appendAscii(pError->message); + } + int line = pError->line; + if (line) { + buf.appendAscii("Line: "); + buf.append(static_cast<sal_Int32>(line)); + buf.appendAscii("\n"); + } + int column = pError->int2; + if (column) { + buf.appendAscii("Column: "); + buf.append(static_cast<sal_Int32>(column)); + buf.appendAscii("\n"); + } + OUString msg = buf.makeStringAndClear(); + return msg; + } + + extern "C" { + + static void generic_error_func(void *userData, const char *format, ...) + { + (void) userData; + char str[1000]; + va_list args; + + va_start(args, format); +#ifdef _WIN32 +#define vsnprintf _vsnprintf +#endif + vsnprintf(str, sizeof(str), format, args); + va_end(args); + + ::rtl::OUStringBuffer buf( + OUString(RTL_CONSTASCII_USTRINGPARAM("libxml2 error:\n"))); + buf.appendAscii(str); + OString msg = OUStringToOString(buf.makeStringAndClear(), + RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(msg.getStr()); + } + + static void structured_error_func(void * userData, xmlErrorPtr error) + { + (void) userData; + ::rtl::OUStringBuffer buf( + OUString(RTL_CONSTASCII_USTRINGPARAM("libxml2 error:\n"))); + if (error) { + buf.append(make_error_message(error)); + } else { + buf.append(OUString(RTL_CONSTASCII_USTRINGPARAM("no error argument!"))); + } + OString msg = OUStringToOString(buf.makeStringAndClear(), + RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(msg.getStr()); + } + + } // extern "C" + + /** + * evaluates an XPath string. relative XPath expressions are evaluated relative to + * the context Node + */ + Reference< XXPathObject > SAL_CALL CXPathAPI::eval( + Reference< XNode > const& xContextNode, + const OUString& expr) + throw (RuntimeException, XPathException) + { + if (!xContextNode.is()) { throw RuntimeException(); } + + nsmap_t nsmap; + extensions_t extensions; + + { + ::osl::MutexGuard const g(m_Mutex); + nsmap = m_nsmap; + extensions = m_extensions; + } + + // get the node and document + ::rtl::Reference<DOM::CDocument> const pCDoc( + dynamic_cast<DOM::CDocument*>( DOM::CNode::GetImplementation( + xContextNode->getOwnerDocument()))); + if (!pCDoc.is()) { throw RuntimeException(); } + + DOM::CNode *const pCNode = DOM::CNode::GetImplementation(xContextNode); + if (!pCNode) { throw RuntimeException(); } + + ::osl::MutexGuard const g(pCDoc->GetMutex()); // lock the document! + + xmlNodePtr const pNode = pCNode->GetNodePtr(); + if (!pNode) { throw RuntimeException(); } + xmlDocPtr pDoc = pNode->doc; + + /* NB: workaround for #i87252#: + libxml < 2.6.17 considers it an error if the context + node is the empty document (i.e. its xpathCtx->doc has no + children). libxml 2.6.17 does not consider it an error. + Unfortunately, old libxml prints an error message to stderr, + which (afaik) cannot be turned off in this case, so we handle it. + */ + if (!pDoc->children) { + throw XPathException(); + } + + /* Create xpath evaluation context */ + ::boost::shared_ptr<xmlXPathContext> const xpathCtx( + xmlXPathNewContext(pDoc), xmlXPathFreeContext); + if (xpathCtx == NULL) { throw XPathException(); } + + // set context node + xpathCtx->node = pNode; + // error handling + xpathCtx->error = structured_error_func; + xmlSetGenericErrorFunc(NULL, generic_error_func); + + // register namespaces and extension + lcl_registerNamespaces(xpathCtx.get(), nsmap); + lcl_registerExtensions(xpathCtx.get(), extensions); + + /* run the query */ + OString o1 = OUStringToOString(expr, RTL_TEXTENCODING_UTF8); + xmlChar *xStr = (xmlChar*)o1.getStr(); + ::boost::shared_ptr<xmlXPathObject> const xpathObj( + xmlXPathEval(xStr, xpathCtx.get()), xmlXPathFreeObject); + if (0 == xpathObj) { + // OSL_ENSURE(xpathCtx->lastError == NULL, xpathCtx->lastError->message); + throw XPathException(); + } + Reference<XXPathObject> const xObj( + new CXPathObject(pCDoc, pCDoc->GetMutex(), xpathObj)); + return xObj; + } + + /** + * same as eval but registers all namespace declarations found on namespaceNode + */ + Reference< XXPathObject > SAL_CALL CXPathAPI::evalNS( + const Reference< XNode >& contextNode, + const OUString& expr, + const Reference< XNode >& namespaceNode) + throw (RuntimeException, XPathException) + { + lcl_collectRegisterNamespaces(*this, namespaceNode); + return eval(contextNode, expr); + } + + /** + * uses the service manager to create an instance of the service denoted by aName. + * If the returned object implements the XXPathExtension interface, it is added to the list + * of extensions that are used when evaluating XPath strings with this XPathAPI instance + */ + void SAL_CALL CXPathAPI::registerExtension( + const OUString& aName) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_Mutex); + + // get extension from service manager + Reference< XXPathExtension > const xExtension( + m_aFactory->createInstance(aName), UNO_QUERY_THROW); + m_extensions.push_back(xExtension); + } + + /** + * registers the given extension instance to be used by XPath evaluations performed through this + * XPathAPI instance + */ + void SAL_CALL CXPathAPI::registerExtensionInstance( + Reference< XXPathExtension> const& xExtension) + throw (RuntimeException) + { + if (!xExtension.is()) { + throw RuntimeException(); + } + ::osl::MutexGuard const g(m_Mutex); + m_extensions.push_back( xExtension ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/xpath/xpathapi.hxx b/unoxml/source/xpath/xpathapi.hxx new file mode 100644 index 000000000000..dc8e0536656c --- /dev/null +++ b/unoxml/source/xpath/xpathapi.hxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 XPATH_XPATHAPI_HXX +#define XPATH_XPATHAPI_HXX + +#include <map> +#include <vector> + +#include <sal/types.h> + +#include <cppuhelper/implbase2.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Sequence.h> + +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/xml/xpath/XXPathAPI.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/xpath/XXPathAPI.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/xml/xpath/XXPathExtension.hpp> +#include <com/sun/star/xml/xpath/Libxml2ExtensionHandle.hpp> +#include <com/sun/star/xml/xpath/XPathException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::xpath; + +namespace XPath +{ + typedef std::map<OUString, OUString> nsmap_t; + typedef std::vector< Reference<XXPathExtension> > extensions_t; + + typedef ::cppu::WeakImplHelper2 + < XXPathAPI + , ::com::sun::star::lang::XServiceInfo + > CXPathAPI_Base; + + class CXPathAPI + : public CXPathAPI_Base + { + + private: + ::osl::Mutex m_Mutex; + nsmap_t m_nsmap; + const Reference< ::com::sun::star::lang::XMultiServiceFactory > m_aFactory; + extensions_t m_extensions; + + public: + // ctor + CXPathAPI( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); + + // call for factory + static Reference< XInterface > getInstance( + const Reference < ::com::sun::star::lang::XMultiServiceFactory >& + xFactory); + + // static helpers for service info and component management + static const char* aImplementationName; + static const char* aSupportedServiceNames[]; + static OUString _getImplementationName(); + static Sequence< OUString > _getSupportedServiceNames(); + static Reference< XInterface > _getInstance( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames () + throw (RuntimeException); + + + // --- XXPathAPI --- + + virtual void SAL_CALL registerNS(const OUString& aPrefix, const OUString& aURI) + throw (RuntimeException); + + virtual void SAL_CALL unregisterNS(const OUString& aPrefix, const OUString& aURI) + throw (RuntimeException); + + /** + Use an XPath string to select a nodelist. + */ + virtual Reference< XNodeList > SAL_CALL selectNodeList(const Reference< XNode >& contextNode, const OUString& str) + throw (RuntimeException, XPathException); + + /** + Use an XPath string to select a nodelist. + */ + virtual Reference< XNodeList > SAL_CALL selectNodeListNS(const Reference< XNode >& contextNode, const OUString& str, const Reference< XNode >& namespaceNode) + throw (RuntimeException, XPathException); + + /** + Use an XPath string to select a single node. + */ + virtual Reference< XNode > SAL_CALL selectSingleNode(const Reference< XNode >& contextNode, const OUString& str) + throw (RuntimeException, XPathException); + + /** + Use an XPath string to select a single node. + */ + virtual Reference< XNode > SAL_CALL selectSingleNodeNS(const Reference< XNode >& contextNode, const OUString& str, const Reference< XNode >& namespaceNode) + throw (RuntimeException, XPathException); + + virtual Reference< XXPathObject > SAL_CALL eval(const Reference< XNode >& contextNode, const OUString& str) + throw (RuntimeException, XPathException); + + virtual Reference< XXPathObject > SAL_CALL evalNS(const Reference< XNode >& contextNode, const OUString& str, const Reference< XNode >& namespaceNode) + throw (RuntimeException, XPathException); + + virtual void SAL_CALL registerExtension(const OUString& aName) throw (RuntimeException); + virtual void SAL_CALL registerExtensionInstance(const Reference< XXPathExtension>& aExtension) throw (RuntimeException); + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/xpath/xpathobject.cxx b/unoxml/source/xpath/xpathobject.cxx new file mode 100644 index 000000000000..c9d84bd4173f --- /dev/null +++ b/unoxml/source/xpath/xpathobject.cxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <xpathobject.hxx> + +#include <string.h> + +#include "../dom/document.hxx" +#include <nodelist.hxx> + + +namespace XPath +{ + static XPathObjectType lcl_GetType(xmlXPathObjectPtr const pXPathObj) + { + switch (pXPathObj->type) + { + case XPATH_UNDEFINED: + return XPathObjectType_XPATH_UNDEFINED; + case XPATH_NODESET: + return XPathObjectType_XPATH_NODESET; + case XPATH_BOOLEAN: + return XPathObjectType_XPATH_BOOLEAN; + case XPATH_NUMBER: + return XPathObjectType_XPATH_NUMBER; + case XPATH_STRING: + return XPathObjectType_XPATH_STRING; + case XPATH_POINT: + return XPathObjectType_XPATH_POINT; + case XPATH_RANGE: + return XPathObjectType_XPATH_RANGE; + case XPATH_LOCATIONSET: + return XPathObjectType_XPATH_LOCATIONSET; + case XPATH_USERS: + return XPathObjectType_XPATH_USERS; + case XPATH_XSLT_TREE: + return XPathObjectType_XPATH_XSLT_TREE; + default: + return XPathObjectType_XPATH_UNDEFINED; + } + } + + CXPathObject::CXPathObject( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + ::boost::shared_ptr<xmlXPathObject> const& pXPathObj) + : m_pDocument(pDocument) + , m_rMutex(rMutex) + , m_pXPathObj(pXPathObj) + , m_XPathObjectType(lcl_GetType(pXPathObj.get())) + { + } + + /** + get object type + */ + XPathObjectType CXPathObject::getObjectType() throw (RuntimeException) + { + return m_XPathObjectType; + } + + /** + get the nodes from a nodelist type object + */ + Reference< XNodeList > SAL_CALL + CXPathObject::getNodeList() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xRet( + new CNodeList(m_pDocument, m_rMutex, m_pXPathObj)); + return xRet; + } + + /** + get value of a boolean object + */ + sal_Bool SAL_CALL CXPathObject::getBoolean() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return (sal_Bool) xmlXPathCastToBoolean(m_pXPathObj.get()); + } + + /** + get number as byte + */ + sal_Int8 SAL_CALL CXPathObject::getByte() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return (sal_Int8) xmlXPathCastToNumber(m_pXPathObj.get()); + } + + /** + get number as short + */ + sal_Int16 SAL_CALL CXPathObject::getShort() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return (sal_Int16) xmlXPathCastToNumber(m_pXPathObj.get()); + } + + /** + get number as long + */ + sal_Int32 SAL_CALL CXPathObject::getLong() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return (sal_Int32) xmlXPathCastToNumber(m_pXPathObj.get()); + } + + /** + get number as hyper + */ + sal_Int64 SAL_CALL CXPathObject::getHyper() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return (sal_Int64) xmlXPathCastToNumber(m_pXPathObj.get()); + } + + /** + get number as float + */ + float SAL_CALL CXPathObject::getFloat() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return (float) xmlXPathCastToNumber(m_pXPathObj.get()); + } + + /** + get number as double + */ + double SAL_CALL CXPathObject::getDouble() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + return xmlXPathCastToNumber(m_pXPathObj.get()); + } + + /** + get string value + */ + OUString SAL_CALL CXPathObject::getString() throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + ::boost::shared_ptr<xmlChar const> str( + xmlXPathCastToString(m_pXPathObj.get()), xmlFree); + sal_Char const*const pS(reinterpret_cast<sal_Char const*>(str.get())); + return OUString(pS, strlen(pS), RTL_TEXTENCODING_UTF8); + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/source/xpath/xpathobject.hxx b/unoxml/source/xpath/xpathobject.hxx new file mode 100644 index 000000000000..8e507aa0c19b --- /dev/null +++ b/unoxml/source/xpath/xpathobject.hxx @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 XPATH_XPATHOBJECT_HXX +#define XPATH_XPATHOBJECT_HXX + +#include <boost/shared_ptr.hpp> + +#include <libxml/tree.h> +#include <libxml/xpath.h> + +#include <sal/types.h> +#include <rtl/ref.hxx> + +#include <cppuhelper/implbase1.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> + + +using ::rtl::OUString; +using namespace com::sun::star::uno; +using namespace com::sun::star::xml::dom; +using namespace com::sun::star::xml::xpath; + + +namespace DOM { + class CDocument; +} + +namespace XPath +{ + class CXPathObject : public cppu::WeakImplHelper1< XXPathObject > + { + private: + ::rtl::Reference< DOM::CDocument > const m_pDocument; + ::osl::Mutex & m_rMutex; + boost::shared_ptr<xmlXPathObject> const m_pXPathObj; + XPathObjectType const m_XPathObjectType; + + public: + CXPathObject( ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + ::boost::shared_ptr<xmlXPathObject> const& pXPathObj); + + /** + get object type + */ + virtual XPathObjectType SAL_CALL getObjectType() throw (RuntimeException); + + /** + get the nodes from a nodelist type object + */ + virtual Reference< XNodeList > SAL_CALL getNodeList() + throw (RuntimeException); + + /** + get value of a boolean object + */ + virtual sal_Bool SAL_CALL getBoolean() throw (RuntimeException); + + /** + get number as byte + */ + virtual sal_Int8 SAL_CALL getByte() throw (RuntimeException); + + /** + get number as short + */ + virtual sal_Int16 SAL_CALL getShort() throw (RuntimeException); + + /** + get number as long + */ + virtual sal_Int32 SAL_CALL getLong() throw (RuntimeException); + + /** + get number as hyper + */ + virtual sal_Int64 SAL_CALL getHyper() throw (RuntimeException); + + /** + get number as float + */ + virtual float SAL_CALL getFloat() throw (RuntimeException); + + /** + get number as double + */ + virtual double SAL_CALL getDouble() throw (RuntimeException); + + /** + get string value + */ + virtual OUString SAL_CALL getString() throw (RuntimeException); + + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/test/domtest.cxx b/unoxml/test/domtest.cxx new file mode 100644 index 000000000000..ff44e2b9dc3e --- /dev/null +++ b/unoxml/test/domtest.cxx @@ -0,0 +1,401 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include <testshl/simpleheader.hxx> + +#include <rtl/ref.hxx> +#include <osl/file.hxx> +#include <osl/process.h> +#include <comphelper/seqstream.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <com/sun/star/xml/sax/FastToken.hpp> +#include <com/sun/star/xml/sax/XSAXSerializable.hpp> +#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> + +#include "../source/dom/documentbuilder.hxx" + + +using namespace ::DOM; +using namespace ::comphelper; +using namespace ::com::sun::star; + +namespace +{ + +// valid xml +static const char validTestFile[] = +"<?xml version=\"1.0\" encoding=\"UTF-8\"?> \ + <office:document-content \ + xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" \ + xmlns:xlink=\"http://www.w3.org/1999/xlink\" \ + office:version=\"1.0\"> \ + <office:scripts/> \ + <xlink:test/> \ + <office:automatic-styles teststyle=\"test\"/> \ + <moretest/> \ + some text öäü \ + </office:document-content> \ +"; + +// generates a warning: unsupported xml version, unknown xml:space +// value +static const char warningTestFile[] = +"<?xml version=\"47-11.0\" encoding=\"UTF-8\"?> \ + <office:document-content \ + xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" \ + xml:space=\"blafasl\" \ + office:version=\"1.0\"> \ + <office:scripts/> \ + <office:automatic-styles/> \ + </office:document-content> \ +"; + +// <?xml not at start of file +static const char errorTestFile[] = +" <?xml version=\"1.0\" encoding=\"UTF-8\"?> \ + <office:document-content \ + xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" \ + office:version=\"1.0\"> \ + <office:scripts/> \ + <office:automatic-styles/> \ + </office:document-content> \ +"; + +// plain empty +static const char fatalTestFile[] = ""; + +struct ErrorHandler + : public ::cppu::WeakImplHelper1< xml::sax::XErrorHandler > +{ + sal_uInt32 mnErrCount; + sal_uInt32 mnFatalCount; + sal_uInt32 mnWarnCount; + + bool noErrors() const { return !mnErrCount && !mnFatalCount && !mnWarnCount; } + + ErrorHandler() : mnErrCount(0), mnFatalCount(0), mnWarnCount(0) + {} + + virtual void SAL_CALL error( const uno::Any& ) throw (xml::sax::SAXException, uno::RuntimeException) + { + ++mnErrCount; + } + + virtual void SAL_CALL fatalError( const uno::Any& ) throw (xml::sax::SAXException, uno::RuntimeException) + { + ++mnFatalCount; + } + + virtual void SAL_CALL warning( const uno::Any& ) throw (xml::sax::SAXException, uno::RuntimeException) + { + ++mnWarnCount; + } +}; + +struct DocumentHandler + : public ::cppu::WeakImplHelper1< xml::sax::XFastDocumentHandler > +{ + // XFastContextHandler + virtual void SAL_CALL startFastElement( ::sal_Int32 Element, const uno::Reference< xml::sax::XFastAttributeList >& Attribs ) throw (xml::sax::SAXException, uno::RuntimeException) + { + OSL_TRACE("Seen element: %c with namespace 0x%x", + Element & 0xFFFF, Element & 0xFFFF0000); + } + + virtual void SAL_CALL startUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, const uno::Reference< xml::sax::XFastAttributeList >& Attribs ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + + virtual void SAL_CALL endUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + + virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const uno::Reference< xml::sax::XFastAttributeList >& Attribs ) throw (xml::sax::SAXException, uno::RuntimeException) + { + return this; + } + + virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createUnknownChildContext( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, const uno::Reference< xml::sax::XFastAttributeList >& Attribs ) throw (xml::sax::SAXException, uno::RuntimeException) + { + return this; + } + + virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + + // XFastDocumentHandler + virtual void SAL_CALL startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + + virtual void SAL_CALL endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + + virtual void SAL_CALL setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } +}; + +struct TokenHandler + : public ::cppu::WeakImplHelper1< xml::sax::XFastTokenHandler > +{ + virtual ::sal_Int32 SAL_CALL getToken( const ::rtl::OUString& Identifier ) throw (uno::RuntimeException) + { + CPPUNIT_ASSERT_MESSAGE( "TokenHandler::getToken() unexpected call", + false ); + return -1; + } + + virtual ::rtl::OUString SAL_CALL getIdentifier( ::sal_Int32 Token ) throw (uno::RuntimeException) + { + CPPUNIT_ASSERT_MESSAGE( "TokenHandler::getIdentifier() unexpected call", + false ); + return rtl::OUString(); + } + + virtual ::sal_Int32 SAL_CALL getTokenFromUTF8( const uno::Sequence< ::sal_Int8 >& Identifier ) throw (uno::RuntimeException) + { + OSL_TRACE("getTokenFromUTF8() %s", (const char*)Identifier.getConstArray()); + return Identifier.getLength() ? Identifier[0] : 0; + } + + virtual uno::Sequence< ::sal_Int8 > SAL_CALL getUTF8Identifier( ::sal_Int32 Token ) throw (uno::RuntimeException) + { + CPPUNIT_ASSERT_MESSAGE( "TokenHandler::getUTF8Identifier() unexpected call", + false ); + return uno::Sequence<sal_Int8>(); + } +}; + +struct BasicTest : public CppUnit::TestFixture +{ + rtl::Reference<CDocumentBuilder> mxDomBuilder; + rtl::Reference<ErrorHandler> mxErrHandler; + rtl::Reference<SequenceInputStream> mxValidInStream; + rtl::Reference<SequenceInputStream> mxWarningInStream; + rtl::Reference<SequenceInputStream> mxErrorInStream; + rtl::Reference<SequenceInputStream> mxFatalInStream; + + void setUp() + { + // luckily, DOM builder doesn't use service fac, so we need + // not bootstrap uno here + mxErrHandler.set( new ErrorHandler() ); + mxDomBuilder.set( new CDocumentBuilder(Reference< XMultiServiceFactory >() )); + mxValidInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)validTestFile, + sizeof(validTestFile)/sizeof(*validTestFile))) ); + mxWarningInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)warningTestFile, + sizeof(warningTestFile)/sizeof(*warningTestFile))) ); + mxErrorInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)errorTestFile, + sizeof(errorTestFile)/sizeof(*errorTestFile))) ); + mxFatalInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)fatalTestFile, + sizeof(fatalTestFile)/sizeof(*fatalTestFile))) ); + mxDomBuilder->setErrorHandler(mxErrHandler.get()); + } + + void validInputTest() + { + CPPUNIT_ASSERT_MESSAGE( "Valid input file did not result in XDocument #1", + mxDomBuilder->parse( + uno::Reference<io::XInputStream>( + mxValidInStream.get())).is() ); + CPPUNIT_ASSERT_MESSAGE( "Valid input file resulted in parse errors", + mxErrHandler->noErrors() ); + } + + void warningInputTest() + { + CPPUNIT_ASSERT_MESSAGE( "Valid input file did not result in XDocument #2", + mxDomBuilder->parse( + uno::Reference<io::XInputStream>( + mxWarningInStream.get())).is() ); + CPPUNIT_ASSERT_MESSAGE( "No parse warnings in unclean input file", + mxErrHandler->mnWarnCount && !mxErrHandler->mnErrCount && !mxErrHandler->mnFatalCount ); + } + + void errorInputTest() + { + CPPUNIT_ASSERT_MESSAGE( "Valid input file did not result in XDocument #3", + mxDomBuilder->parse( + uno::Reference<io::XInputStream>( + mxErrorInStream.get())).is() ); + CPPUNIT_ASSERT_MESSAGE( "No parse errors in unclean input file", + !mxErrHandler->mnWarnCount && mxErrHandler->mnErrCount && !mxErrHandler->mnFatalCount ); + } + + void fatalInputTest() + { + CPPUNIT_ASSERT_MESSAGE( "Broken input file resulted in XDocument", + !mxDomBuilder->parse( + uno::Reference<io::XInputStream>( + mxFatalInStream.get())).is() ); + CPPUNIT_ASSERT_MESSAGE( "No fatal parse errors in unclean input file", + !mxErrHandler->mnWarnCount && !mxErrHandler->mnErrCount && mxErrHandler->mnFatalCount ); + }; + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + CPPUNIT_TEST_SUITE(BasicTest); + CPPUNIT_TEST(validInputTest); + CPPUNIT_TEST(warningInputTest); + CPPUNIT_TEST(errorInputTest); + CPPUNIT_TEST(fatalInputTest); + CPPUNIT_TEST_SUITE_END(); +}; + +struct SerializerTest : public CppUnit::TestFixture +{ + SerializerTest() : mbUnoInitialized(false) {} + + uno::Reference<uno::XComponentContext> mxCtx; + rtl::Reference<CDocumentBuilder> mxDomBuilder; + rtl::Reference<ErrorHandler> mxErrHandler; + rtl::Reference<SequenceInputStream> mxInStream; + rtl::Reference<DocumentHandler> mxHandler; + rtl::Reference<TokenHandler> mxTokHandler; + uno::Sequence< beans::Pair< rtl::OUString, sal_Int32 > > maRegisteredNamespaces; + bool mbUnoInitialized; + + void setUp() + { + // need working typelib, bootstrap UNO now + if( !mbUnoInitialized ) + { + const char* pArgs( getForwardString() ); + CPPUNIT_ASSERT_MESSAGE("Test file parameter", pArgs); + + const rtl::OUString sBaseDir=rtl::OUString::createFromAscii(pArgs); + + // bootstrap UNO + try + { + ::rtl::OUString aIniUrl; + CPPUNIT_ASSERT_MESSAGE( + "Converting ini file to URL", + osl_getFileURLFromSystemPath( + (sBaseDir+rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unoxml_unittest_test.ini"))).pData, + &aIniUrl.pData ) == osl_File_E_None ); + + mxCtx = ::cppu::defaultBootstrap_InitialComponentContext(aIniUrl); + CPPUNIT_ASSERT_MESSAGE("Getting component context", mxCtx.is()); + } + catch( uno::Exception& ) + { + CPPUNIT_ASSERT_MESSAGE("Bootstrapping UNO", false); + } + + mbUnoInitialized = true; + } + + mxErrHandler.set( new ErrorHandler() ); + mxDomBuilder.set( new CDocumentBuilder( + uno::Reference< lang::XMultiServiceFactory >( + mxCtx->getServiceManager(), + uno::UNO_QUERY ))); + mxInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)validTestFile, + sizeof(validTestFile)/sizeof(*validTestFile))) ); + mxDomBuilder->setErrorHandler(mxErrHandler.get()); + + mxHandler.set( new DocumentHandler() ); + mxTokHandler.set( new TokenHandler() ); + + maRegisteredNamespaces.realloc(2); + maRegisteredNamespaces[0] = beans::make_Pair( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "urn:oasis:names:tc:opendocument:xmlns:office:1.0") ), + xml::sax::FastToken::NAMESPACE); + maRegisteredNamespaces[1] = beans::make_Pair( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "http://www.w3.org/1999/xlink") ), + 2*xml::sax::FastToken::NAMESPACE); + } + + void serializerTest () + { + uno::Reference< xml::dom::XDocument > xDoc= + mxDomBuilder->parse( + uno::Reference<io::XInputStream>( + mxInStream.get())); + CPPUNIT_ASSERT_MESSAGE( "Valid input file did not result in XDocument", + xDoc.is() ); + CPPUNIT_ASSERT_MESSAGE( "Valid input file resulted in parse errors", + mxErrHandler->noErrors() ); + + uno::Reference< xml::sax::XSAXSerializable > xSaxSerializer( + xDoc, uno::UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE( "XSAXSerializable not supported", + xSaxSerializer.is() ); + + uno::Reference< xml::sax::XFastSAXSerializable > xFastSaxSerializer( + xDoc, uno::UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE( "XFastSAXSerializable not supported", + xSaxSerializer.is() ); + + xFastSaxSerializer->fastSerialize( mxHandler.get(), + mxTokHandler.get(), + uno::Sequence< beans::StringPair >(), + maRegisteredNamespaces ); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(SerializerTest); + CPPUNIT_TEST(serializerTest); + CPPUNIT_TEST_SUITE_END(); +}; + +// ----------------------------------------------------------------------------- +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(BasicTest, "BasicTest"); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SerializerTest, "SerializerTest"); +} + + +// ----------------------------------------------------------------------------- + +// this macro creates an empty function, which will called by the RegisterAllFunctions() +// to let the user the possibility to also register some functions by hand. +NOADDITIONAL; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoxml/test/export.map b/unoxml/test/export.map new file mode 100644 index 000000000000..7321bbca16ad --- /dev/null +++ b/unoxml/test/export.map @@ -0,0 +1,34 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +UDK_3_0_0 { + global: + registerAllTestFunction; + + local: + *; +}; diff --git a/unoxml/test/makefile.mk b/unoxml/test/makefile.mk new file mode 100644 index 000000000000..790a34a6a71b --- /dev/null +++ b/unoxml/test/makefile.mk @@ -0,0 +1,104 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +PRJ=.. + +PRJNAME=unoxml +TARGET=tests +TARGETTYPE=GUI + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +CFLAGSCXX += $(CPPUNIT_CFLAGS) + +# --- Common ---------------------------------------------------------- + +# BEGIN ---------------------------------------------------------------- +# auto generated Target:tests by codegen.pl +SHL1OBJS= \ + $(SLO)$/domtest.obj + +# the following three libs are a bit of a hack: cannot link against +# unoxml here, because not yet delivered (and does not export +# ~anything). Need the functionality to test, so we're linking it in +# statically. Need to keep this in sync with +# source/services/makefile.mk +SHL1LIBS= \ + $(SLB)$/domimpl.lib \ + $(SLB)$/xpathimpl.lib \ + $(SLB)$/eventsimpl.lib + +SHL1TARGET= tests +SHL1STDLIBS= \ + $(UCBHELPERLIB) \ + $(LIBXML2LIB) \ + $(TOOLSLIB) \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPUNITLIB) \ + $(CPPULIB) \ + $(SAXLIB) \ + $(SALLIB)\ + $(EXPATASCII3RDLIB) + +SHL1IMPLIB= i$(SHL1TARGET) + +DEF1NAME =$(SHL1TARGET) +SHL1VERSIONMAP = export.map + +# END ------------------------------------------------------------------ + +#------------------------------- All object files ------------------------------- +# do this here, so we get right dependencies +SLOFILES=$(SHL1OBJS) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk +.INCLUDE : _cppunit.mk + +# --- Fake uno bootstrap ------------------------ + +$(BIN)$/unoxml_unittest_test.ini : makefile.mk + rm -f $@ + @echo UNO_SERVICES= > $@ + @echo UNO_TYPES=$(UNOUCRRDB:s/\/\\/) >> $@ + +# --- Enable testshl2 execution in normal build ------------------------ + +$(MISC)$/unoxml_unittest_succeeded : $(SHL1TARGETN) $(BIN)$/unoxml_unittest_test.ini + @echo ---------------------------------------------------------- + @echo - start unit test on library $(SHL1TARGETN) + @echo ---------------------------------------------------------- + $(TESTSHL2) -forward $(BIN)$/ -sf $(mktmp ) $(SHL1TARGETN) + $(TOUCH) $@ + +ALLTAR : $(MISC)$/unoxml_unittest_succeeded |