From 27d48271a59dcb1cc99c59efc1e356f68161f1e2 Mon Sep 17 00:00:00 2001 From: Carsten Hiesserich Date: Thu, 10 Oct 2013 18:41:03 +0200 Subject: cleanup document type handling and doctypes in docbook plugin Change-Id: Ieae7693a39f1837cba4b822e316c08f6b3dd3864 Signed-off-by: Carsten Hiesserich --- org.eclipse.vex.core.tests/plugin.xml | 8 + .../org/eclipse/vex/core/internal/css/CssTest.java | 7 + .../eclipse/vex/core/internal/css/testCatalog.css | 2 + .../core/internal/io/DocumentContentModelTest.java | 37 ++- .../core/internal/validator/DTDValidatorTest.java | 11 - .../vex/core/internal/io/DocumentBuilder.java | 2 +- .../core/internal/validator/WTPVEXValidator.java | 64 ++--- .../core/provisional/dom/DocumentContentModel.java | 144 +++++++---- org.eclipse.vex.docbook/plugin.properties | 4 +- org.eclipse.vex.docbook/plugin.xml | 138 +++------- org.eclipse.vex.ui.tests/plugin.xml | 38 +++ .../config/tests/ConfigurationRegistryTest.java | 48 +++- .../ui/internal/config/tests/PreferencesTest.java | 52 ++++ .../config/tests/VexDocumentContentModelTest.java | 106 ++++++++ .../org/eclipse/vex/ui/tests/VexUiTestSuite.java | 4 +- .../testdata/test-doctype-id.css | 53 ++++ org.eclipse.vex.ui.tests/testdata/test-schema.css | 53 ++++ org.eclipse.vex.ui/schema/doctype.exsd | 282 +++++++++++---------- org.eclipse.vex.ui/schema/style.exsd | 55 ++-- .../eclipse/vex/ui/internal/VexPreferences.java | 22 +- .../vex/ui/internal/config/ConfigLoaderJob.java | 2 +- .../ui/internal/config/ConfigurationRegistry.java | 42 +-- .../internal/config/ConfigurationRegistryImpl.java | 46 +++- .../vex/ui/internal/config/ConfigurationView.java | 4 +- .../vex/ui/internal/config/DoctypeFactory.java | 24 +- .../vex/ui/internal/config/DocumentType.java | 38 ++- .../internal/config/DomConfigurationElement.java | 2 +- .../vex/ui/internal/config/StylePropertyPage.java | 2 +- .../internal/editor/DocumentTypeSelectionPage.java | 2 +- .../internal/editor/VexDocumentContentModel.java | 27 +- .../eclipse/vex/ui/internal/editor/VexEditor.java | 12 +- .../vex/ui/internal/handlers/StyleMenu.java | 5 +- .../vex/ui/internal/wizards/NewDocumentWizard.java | 4 +- 33 files changed, 900 insertions(+), 440 deletions(-) create mode 100644 org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/testCatalog.css create mode 100644 org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/PreferencesTest.java create mode 100644 org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/VexDocumentContentModelTest.java create mode 100644 org.eclipse.vex.ui.tests/testdata/test-doctype-id.css create mode 100644 org.eclipse.vex.ui.tests/testdata/test-schema.css diff --git a/org.eclipse.vex.core.tests/plugin.xml b/org.eclipse.vex.core.tests/plugin.xml index a23c4162..17a8faaf 100644 --- a/org.eclipse.vex.core.tests/plugin.xml +++ b/org.eclipse.vex.core.tests/plugin.xml @@ -13,10 +13,18 @@ name="http://www.eclipse.org/vex/test/content" uri="testResources/content.xsd"> + + + + diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java index a0e2cc3c..33892320 100644 --- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java +++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java @@ -12,6 +12,7 @@ package org.eclipse.vex.core.internal.css; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import java.net.URL; @@ -582,4 +583,10 @@ public class CssTest { element.setAttribute("attribute", "After"); assertEquals("After", styles.getContent(element).get(0)); } + + @Test + public void testCatalogImport() throws Exception { + final StyleSheet ss = parseStyleSheetResource("testCatalog.css"); + assertTrue(ss.getRules().size() > 0); + } } diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/testCatalog.css b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/testCatalog.css new file mode 100644 index 00000000..d9fc6871 --- /dev/null +++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/testCatalog.css @@ -0,0 +1,2 @@ +/* Stylesheet for unit testing */ +@import url(urn:org:eclipse:vex:styles:test:test.css) diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java index e643210e..52e3aa7a 100644 --- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java +++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java @@ -16,8 +16,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import java.net.URL; - import org.eclipse.core.runtime.QualifiedName; import org.eclipse.vex.core.internal.dom.Element; import org.eclipse.vex.core.provisional.dom.DocumentContentModel; @@ -99,17 +97,24 @@ public class DocumentContentModelTest { } @Test - public void resolveSchemaIdentifier() throws Exception { - final URL resolvedUrl = model.resolveSchemaIdentifier(TestResources.TEST_DTD); + public void resolveSchemaBySchemaLocation() throws Exception { + final String resolvedUrl = model.resolveResourceURI(null, "http://www.eclipse.org/vex/test/content.xsd"); assertNotNull(resolvedUrl); - assertTrue(resolvedUrl.toString().contains(VEXCoreTestPlugin.PLUGIN_ID)); + assertTrue(resolvedUrl.contains(VEXCoreTestPlugin.PLUGIN_ID) && resolvedUrl.endsWith("testResources/content.xsd")); + } + + @Test + public void resolveSchemaByNamespace() throws Exception { + final String resolvedUrl = model.resolveResourceURI(null, "http://www.eclipse.org/vex/test/content"); + assertNotNull(resolvedUrl); + assertTrue(resolvedUrl.contains(VEXCoreTestPlugin.PLUGIN_ID) && resolvedUrl.endsWith("testResources/content.xsd")); } @Test public void onlySystemId() throws Exception { model.initialize(null, null, TestResources.get("test1.dtd").toString(), null); assertTrue(model.isDtdAssigned()); - assertNotNull(model.getDTD()); + assertNotNull(model.getContentModelDocument()); } @Test @@ -117,8 +122,26 @@ public class DocumentContentModelTest { final String baseUri = TestResources.get("test.css").toString(); model.initialize(baseUri, null, "test1.dtd", null); assertTrue(model.isDtdAssigned()); - final CMDocument dtd = model.getDTD(); + final CMDocument dtd = model.getContentModelDocument(); assertNotNull(dtd); assertEquals(11, dtd.getElements().getLength()); } + + @Test + public void onlyNamespace() throws Exception { + model.initialize(null, null, null, new Element(new QualifiedName("http://www.eclipse.org/vex/test/content", "rootElement"))); + assertFalse(model.isDtdAssigned()); + final CMDocument schema = model.getContentModelDocument(); + assertNotNull(schema); + assertEquals(1, schema.getElements().getLength()); + } + + @Test + public void testExplicitNamespace() throws Exception { + model.setSchemaId(null, "http://www.eclipse.org/vex/test/content"); + assertFalse(model.isDtdAssigned()); + final CMDocument schema = model.getContentModelDocument(); + assertNotNull(schema); + assertEquals(1, schema.getElements().getLength()); + } } diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java index 76d60b16..df646ed4 100644 --- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java +++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java @@ -166,17 +166,6 @@ public class DTDValidatorTest { assertInvalidSequence("document", "preface", "index"); } - @Test - public void testValidateDocumentWithDTDAndNamespaces() throws Exception { - final IDocument doc = new Document(new QualifiedName("http://namespace/uri/is/not/registered", "section")); - doc.setValidator(validator); - doc.insertElement(2, new QualifiedName(null, "title")); - doc.insertText(3, "ab"); - doc.insertElement(6, new QualifiedName(null, "para")); - - validator.getAttributeDefinitions(doc.getRootElement()); - } - private void assertFullyValidSequence(final String element, final String... sequence) { // fully includes partially assertValidSequence(true, element, true, true, sequence); diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java index 056c86dc..689761b1 100644 --- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java +++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java @@ -272,7 +272,7 @@ public class DocumentBuilder implements ContentHandler, LexicalHandler { if (dtdPublicID != null && dtdSystemID != null || previousDocTypeID == null) { // The content model is initialized only if the input document defines a DocType // or if it has not been initialized already. - // This way, a user selected is reapplied when the document is reloaded. + // This way, a user selected doctype is reapplied when the document is reloaded. documentContentModel.initialize(baseUri, dtdPublicID, dtdSystemID, rootElement); } final StyleSheet styleSheet = styleSheetProvider.getStyleSheet(documentContentModel); diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/validator/WTPVEXValidator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/validator/WTPVEXValidator.java index 5153b9ab..7e374dcf 100644 --- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/validator/WTPVEXValidator.java +++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/validator/WTPVEXValidator.java @@ -41,7 +41,6 @@ import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup; import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap; import org.eclipse.wst.xml.core.internal.contentmodel.CMNode; import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList; -import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager; import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator; import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator.ElementContentComparator; import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator.ElementPathRecordingResult; @@ -64,9 +63,7 @@ public class WTPVEXValidator implements IValidator { private final DocumentContentModel documentContentModel; - private CMDocument dtd; - - private final Map contentModelCache = new HashMap(); + private final Map contentModelCache = new HashMap(); private final CMValidator validator = new CMValidator(); @@ -90,46 +87,27 @@ public class WTPVEXValidator implements IValidator { return documentContentModel; } - private CMDocument getSchema(final String namespaceURI) { - if (isDTDDefined()) { - return getDTD(); - } - if (namespaceURI == null) { - /* - * This can be the case if the document does neither contain a doctype declaration nor a default namespace - * declaration. - */ - return getSchema((URL) null); + private CMDocument getContentModelDoc(final String schemaURI) { + if (contentModelCache.containsKey(schemaURI)) { + return contentModelCache.get(schemaURI); } - final URL resolved = documentContentModel.resolveSchemaIdentifier(namespaceURI); - return getSchema(resolved); - } - private CMDocument getSchema(final URL schemaUrl) { - if (contentModelCache.containsKey(schemaUrl)) { - return contentModelCache.get(schemaUrl); - } + CMDocument contentModel; - final CMDocument contentModel; - if (schemaUrl != null) { - final ContentModelManager modelManager = ContentModelManager.getInstance(); - contentModel = modelManager.createCMDocument(schemaUrl.toString(), null); + if (schemaURI == null) { + contentModel = documentContentModel.getContentModelDocument(); } else { + contentModel = documentContentModel.getContentModelDocument(schemaURI); + } + + if (contentModel == null) { + // Schema could not be resolved - create a dummy instance contentModel = new UnknownCMDocument(null); } - contentModelCache.put(schemaUrl, contentModel); - return contentModel; - } - private boolean isDTDDefined() { - return documentContentModel.isDtdAssigned(); - } + contentModelCache.put(schemaURI, contentModel); - private CMDocument getDTD() { - if (dtd == null && documentContentModel.isDtdAssigned()) { - dtd = documentContentModel.getDTD(); - } - return dtd; + return contentModel; } public AttributeDefinition getAttributeDefinition(final IAttribute attribute) { @@ -190,7 +168,7 @@ public class WTPVEXValidator implements IValidator { return null; } final String localName = element.getLocalName(); - final CMElementDeclaration declarationFromRoot = (CMElementDeclaration) getSchema(element.getQualifiedName().getQualifier()).getElements().getNamedItem(localName); + final CMElementDeclaration declarationFromRoot = (CMElementDeclaration) getContentModelDoc(element.getQualifiedName().getQualifier()).getElements().getNamedItem(localName); if (declarationFromRoot != null) { return declarationFromRoot; } @@ -346,7 +324,7 @@ public class WTPVEXValidator implements IValidator { private Set getValidRootElements(final String namespaceURI) { final HashSet result = new HashSet(); - final Iterator iter = getSchema(namespaceURI).getElements().iterator(); + final Iterator iter = getContentModelDoc(namespaceURI).getElements().iterator(); while (iter.hasNext()) { final CMElementDeclaration element = (CMElementDeclaration) iter.next(); result.add(element); @@ -368,7 +346,13 @@ public class WTPVEXValidator implements IValidator { return true; } - final CMNode parent = getSchema(element.getQualifier()).getElements().getNamedItem(element.getLocalName()); + final CMDocument document = getContentModelDoc(element.getQualifier()); + if (document == null) { + System.out.println("Unable to resolve validation schema for " + element.getQualifier()); + return true; + } + CMNode parent = null; + parent = document.getElements().getNamedItem(element.getLocalName()); if (!(parent instanceof CMElementDeclaration)) { return true; } @@ -425,7 +409,7 @@ public class WTPVEXValidator implements IValidator { private Set getRequiredNamespaces(final String namespaceUri, final Set visitedNodes) { final HashSet result = new HashSet(); result.add(namespaceUri); - final CMDocument mainSchema = getSchema(namespaceUri); + final CMDocument mainSchema = getContentModelDoc(namespaceUri); for (final Iterator iter = mainSchema.getElements().iterator(); iter.hasNext();) { final CMElementDeclaration elementDeclaration = (CMElementDeclaration) iter.next(); result.addAll(getRequiredNamespaces(elementDeclaration, visitedNodes)); diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/DocumentContentModel.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/DocumentContentModel.java index e74650f8..e8823aa2 100644 --- a/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/DocumentContentModel.java +++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/DocumentContentModel.java @@ -11,8 +11,6 @@ package org.eclipse.vex.core.provisional.dom; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; import java.text.MessageFormat; import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver; @@ -42,17 +40,45 @@ public class DocumentContentModel implements EntityResolver { initialize(baseUri, publicId, systemId, rootElement); } + /** + * Initialize the content model. + * + * @param baseUri + * The base uri of the loaded document + * @param publicId + * The PublicID of the DocumentTypeDefinition (DTD) + * @param systemId + * The SystemID of the DocumentTypeDefinition (DTD) + * @param rootElement + * If no DTD is defined (publicId and systemId are both null) the namespace of the root element is used + * to define the document type. + */ public void initialize(final String baseUri, final String publicId, final String systemId, final IElement rootElement) { this.baseUri = baseUri; this.publicId = publicId; this.systemId = systemId; - if (rootElement != null) { + if (publicId == null && systemId == null && rootElement != null) { schemaId = rootElement.getQualifiedName().getQualifier(); } else { schemaId = null; } } + /** + * Sets an explicit namespace. + * + * @param baseUri + * The base uri of the loaded document + * @param rootNamespace + * The default namespace to resolve the XML-Schema for validation. + */ + public void setSchemaId(final String baseUri, final String rootNamespace) { + this.baseUri = baseUri; + publicId = null; + systemId = null; + schemaId = rootNamespace; + } + public String getMainDocumentTypeIdentifier() { if (publicId != null) { return publicId; @@ -71,29 +97,76 @@ public class DocumentContentModel implements EntityResolver { return systemId; } + public String getSchemaId() { + return schemaId; + } + public boolean isDtdAssigned() { return publicId != null || systemId != null; } - public CMDocument getDTD() { - final URL resolvedPublicId = resolveSchemaIdentifier(publicId); - if (resolvedPublicId != null) { - return createCMDocument(resolvedPublicId); + /** + * Create and return the WTP CMDocument for the DTD or schema defined by this ContentModel. + * + * @return The resolved CMDocument. + */ + public CMDocument getContentModelDocument() { + if (schemaId != null) { + return getContentModelDocument(schemaId); + } + + String resolvedURI = null; + try { + resolvedURI = resolveResourceURI(publicId, systemId); + if (resolvedURI == null) { + return null; + } + return createCMDocument(resolvedURI); + } catch (final Exception e) { + throw new AssertionError(MessageFormat.format("Resolution of systemId ''{0}'' resulted in a exception:{1}. {2}", systemId, resolvedURI, e.getMessage())); + } + } + + /** + * Create and return the WTP CMDocument for the XML-Schema at the given URI or namespace. The XML catalog is used to + * resolve the schema URI. + * + * @param schemaID + * The URI or the namespace of the XML-Schema. + * @return The resolved CMDocument. + */ + public CMDocument getContentModelDocument(final String schemaId) { + String resolvedUri = null; + try { + resolvedUri = resolveResourceURI(null, schemaId); + if (resolvedUri == null) { + return null; + } + return createCMDocument(resolvedUri); + } catch (final Exception e) { + throw new AssertionError(MessageFormat.format("Resolution of resource URI ''{0}'' resulted in a exception:{1}. {2}", schemaId, resolvedUri, e.getMessage())); } - return createCMDocument(resolveSystemId(systemId)); } - private CMDocument createCMDocument(final URL resolvedDtdUrl) { - if (resolvedDtdUrl == null) { + /** + * Create a new CMDocument from the DTD or XML-Schema at the given URI. + * + * @param resourceURI + * The URI containing the schema or dtd. + * @return + */ + private CMDocument createCMDocument(final String resourceURI) { + if (resourceURI == null) { return null; } final ContentModelManager modelManager = ContentModelManager.getInstance(); - return modelManager.createCMDocument(resolvedDtdUrl.toString(), null); + final CMDocument cmDocument = modelManager.createCMDocument(resourceURI, null); + return cmDocument; } public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException { - final String resolved = URI_RESOLVER.resolve(baseUri, publicId, systemId); - System.out.println("Resolved " + publicId + " " + systemId + " -> " + resolved); + final String resolved = resolveResourceURI(publicId, systemId); + if (resolved == null) { return null; } @@ -103,36 +176,19 @@ public class DocumentContentModel implements EntityResolver { return result; } - public URL resolveSchemaIdentifier(final String schemaIdentifier) { - if (schemaIdentifier == null) { - return null; - } - final String schemaLocation = URI_RESOLVER.resolve(baseUri, schemaIdentifier, null); - if (schemaLocation == null) { - /* - * TODO this is a common case that should be handled somehow - a hint should be shown: the schema is not - * available, the schema should be added to the catalog by the user - an inferred schema should be used, to - * allow to at least display the document in the editor - this is not the right place to either check or - * handle this - */ - return null; - } - try { - return new URL(schemaLocation); - } catch (final MalformedURLException e) { - throw new AssertionError(MessageFormat.format("Resolution of schema ''{0}'' resulted in a malformed URL: ''{1}''. {2}", schemaIdentifier, schemaLocation, e.getMessage())); - } - } - - public URL resolveSystemId(final String systemId) { - final String schemaLocation = URI_RESOLVER.resolve(baseUri, null, systemId); - if (schemaLocation == null) { - return null; - } - try { - return new URL(schemaLocation); - } catch (final MalformedURLException e) { - throw new AssertionError(MessageFormat.format("Resolution of systemId ''{0}'' resulted in a malformed URL: ''{1}''. {2}", systemId, schemaLocation, e.getMessage())); - } + /** + * Resolve the URI for a given Resource with the XML-Catalog. + * + * @param publicId + * The public identifier (DTD) of the resource being referenced, may be null + * @param systemId + * The system identifier (DTD) or the namespace (XML-Schema) of the resource being referenced, may be + * null. + * @return A String containing the resolved URI. + * @throws IOException + */ + public String resolveResourceURI(final String publicId, final String systemId) throws IOException { + final String resolved = URI_RESOLVER.resolve(baseUri, publicId, systemId); + return resolved; } } diff --git a/org.eclipse.vex.docbook/plugin.properties b/org.eclipse.vex.docbook/plugin.properties index 050fe5ad..6750db3c 100644 --- a/org.eclipse.vex.docbook/plugin.properties +++ b/org.eclipse.vex.docbook/plugin.properties @@ -13,9 +13,7 @@ providerName= Eclipse.org doctype.docbook4_5=DocBook v4.5 doctype.docbook5_0_DTD=DocBook v5.0 (DTD) -doctype.docbook5_0_XSD1=DocBook v5.0 (http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd) -doctype.docbook5_0_XSD2=DocBook v5.0 (http://docbook.org/xml/5.0/xsd/docbook.xsd) -doctype.docbook5_0_XSD3=DocBook v5.0 (http://docbook.org/ns/docbook) +doctype.docbook5_0_XSD2=DocBook v5.0 (XML Schema) style.docbook-plain=DocBook Plain contentType.name=DocBook XML Document diff --git a/org.eclipse.vex.docbook/plugin.xml b/org.eclipse.vex.docbook/plugin.xml index 1079b51e..7dae25e1 100644 --- a/org.eclipse.vex.docbook/plugin.xml +++ b/org.eclipse.vex.docbook/plugin.xml @@ -16,6 +16,14 @@ uri="4.5/docbookx.dtd" webURL="http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> + + + + @@ -33,33 +41,41 @@ webURL="http://www.oasis-open.org/docbook/xml/5.0/docbook.dtd"> - - - + - + - - + + + - - + + + @@ -145,54 +161,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -224,49 +199,9 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/org.eclipse.vex.ui.tests/plugin.xml b/org.eclipse.vex.ui.tests/plugin.xml index 657600e1..dd04ca3b 100644 --- a/org.eclipse.vex.ui.tests/plugin.xml +++ b/org.eclipse.vex.ui.tests/plugin.xml @@ -25,6 +25,14 @@ publicId="-//Vex//DTD Test//EN"> + + + + + + + + + + + + + + diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/ConfigurationRegistryTest.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/ConfigurationRegistryTest.java index 933f56dc..83d6e9b7 100644 --- a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/ConfigurationRegistryTest.java +++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/ConfigurationRegistryTest.java @@ -1,15 +1,17 @@ /******************************************************************************* - * Copyright (c) 2010 Florian Thienel and others. + * Copyright (c) 2013 Florian Thienel and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Florian Thienel - initial API and implementation + * Carsten Hiesserich - additional tests *******************************************************************************/ package org.eclipse.vex.ui.internal.config.tests; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -20,10 +22,12 @@ import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.vex.ui.internal.config.ConfigEvent; +import org.eclipse.vex.ui.internal.config.ConfigLoaderJob; import org.eclipse.vex.ui.internal.config.ConfigSource; import org.eclipse.vex.ui.internal.config.ConfigurationLoader; import org.eclipse.vex.ui.internal.config.ConfigurationRegistry; import org.eclipse.vex.ui.internal.config.ConfigurationRegistryImpl; +import org.eclipse.vex.ui.internal.config.DocumentType; import org.eclipse.vex.ui.internal.config.IConfigListener; import org.eclipse.vex.ui.internal.config.PluginProject; import org.junit.After; @@ -116,6 +120,46 @@ public class ConfigurationRegistryTest { assertNotNull(registry.getPluginProject(project)); } + @Test + public void testPluginDoctypeDefinition() throws Exception { + final ConfigurationRegistry configurationRegistry = new ConfigurationRegistryImpl(new ConfigLoaderJob()); + configurationRegistry.loadConfigurations(); + + final DocumentType doctype = configurationRegistry.getDocumentType("-//Vex//DTD Test//EN", null); + assertNotNull(doctype); + assertEquals("test.dtd", doctype.getSystemId()); + } + + @Test + public void testPluginNamespaceDefinition() throws Exception { + final ConfigurationRegistry configurationRegistry = new ConfigurationRegistryImpl(new ConfigLoaderJob()); + configurationRegistry.loadConfigurations(); + + final DocumentType doctype = configurationRegistry.getDocumentType("http://org.eclipse.vex/namespace", null); + assertNotNull(doctype); + assertEquals("test schema doctype", doctype.getName()); + } + + @Test + public void testGetDocumentTypesWithStyles() throws Exception { + final ConfigurationRegistry configurationRegistry = new ConfigurationRegistryImpl(new ConfigLoaderJob()); + configurationRegistry.loadConfigurations(); + + final DocumentType[] doctypes = configurationRegistry.getDocumentTypesWithStyles(); + boolean dtdFound = false; + boolean schemaFound = false; + for (final DocumentType doctype : doctypes) { + if ("test doctype".equals(doctype.getName())) { + dtdFound = true; + } + if ("test schema doctype".equals(doctype.getName())) { + schemaFound = true; + } + } + assertTrue("DoctypeWithStyles should return Doctype with DTD ", dtdFound); + assertTrue("DoctypeWithStyles should return Docype with namespace ", schemaFound); + } + private static class MockConfigurationLoader implements ConfigurationLoader { private final List loadedConfigSources; diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/PreferencesTest.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/PreferencesTest.java new file mode 100644 index 00000000..de9b323d --- /dev/null +++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/PreferencesTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2013 Carsten Hiesserich and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Carsten Hiesserich - initial API and implementation + *******************************************************************************/ +package org.eclipse.vex.ui.internal.config.tests; + +import static org.junit.Assert.assertEquals; + +import java.net.URL; + +import org.eclipse.vex.ui.internal.VexPlugin; +import org.eclipse.vex.ui.internal.VexPreferences; +import org.eclipse.vex.ui.internal.config.ConfigSource; +import org.eclipse.vex.ui.internal.config.DocumentType; +import org.eclipse.vex.ui.internal.config.Style; +import org.junit.Test; + +@SuppressWarnings("restriction") +public class PreferencesTest { + + @Test + public void testStylesheetPreference() throws Exception { + final VexPreferences preferences = VexPlugin.getDefault().getPreferences(); + final DocumentType doctype = new DocumentType(new MockConfigSource()); + doctype.setSimpleId("vex_test_doctype"); + final Style style = new Style(new MockConfigSource()); + style.setSimpleId("vex-test-style"); + preferences.setPreferredStyleId(doctype, style.getUniqueId()); + + final String preferredStyleId = preferences.getPreferredStyleId(doctype); + assertEquals(style.getUniqueId(), preferredStyleId); + } + + private class MockConfigSource extends ConfigSource { + + public MockConfigSource() { + super("test_config"); + } + + @Override + public URL getBaseUrl() { + return null; + } + + } +} diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/VexDocumentContentModelTest.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/VexDocumentContentModelTest.java new file mode 100644 index 00000000..59dafeda --- /dev/null +++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/VexDocumentContentModelTest.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2013 Carsten Hiesserich and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Carsten Hiesserich - initial API and implementation + *******************************************************************************/ +package org.eclipse.vex.ui.internal.config.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.vex.core.internal.dom.Element; +import org.eclipse.vex.ui.internal.config.Style; +import org.eclipse.vex.ui.internal.editor.NoStyleForDoctypeException; +import org.eclipse.vex.ui.internal.editor.VexDocumentContentModel; +import org.junit.Before; +import org.junit.Test; + +@SuppressWarnings("restriction") +public class VexDocumentContentModelTest { + + private VexDocumentContentModel model; + + @Before + public void setUp() throws Exception { + model = new VexDocumentContentModel(); + } + + @Test + public void resolveDoctypeByPublicId() throws Exception { + try { + model.initialize(null, "-//Vex//DTD Test//EN", null, new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement"))); + } catch (final NoStyleForDoctypeException e) { + // We are not interested in the StyleSheet here + } + assertTrue(model.isDtdAssigned()); + assertNotNull(model.getDocumentType()); + assertEquals("test doctype", model.getDocumentType().getName()); + } + + @Test + public void resolveDoctypeBySystemId() throws Exception { + try { + model.initialize(null, "UnknownPublicId", "test.dtd", new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement"))); + } catch (final NoStyleForDoctypeException e) { + // We are not interested in the StyleSheet here + } + assertTrue(model.isDtdAssigned()); + assertNotNull(model.getDocumentType()); + assertEquals("test doctype", model.getDocumentType().getName()); + } + + @Test + public void resolveDoctypeByNamespace() throws Exception { + try { + model.initialize(null, null, null, new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement"))); + } catch (final NoStyleForDoctypeException e) { + // We are not interested in the StyleSheet here + } + assertFalse(model.isDtdAssigned()); + assertNotNull(model.getDocumentType()); + assertEquals("test schema doctype", model.getDocumentType().getName()); + } + + @Test + public void resolveCSSByPublicId() throws Exception { + model.initialize(null, "-//Vex//DTD Test//EN", null, new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement"))); + assertTrue(model.isDtdAssigned()); + final Style style = model.getStyle(); + assertNotNull(style); + assertTrue(style.getResourceUri().toString().endsWith("test.css")); + } + + @Test + public void resolveCSSBySystemId() throws Exception { + model.initialize(null, null, "test.dtd", new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement"))); + assertTrue(model.isDtdAssigned()); + final Style style = model.getStyle(); + assertNotNull(style); + assertTrue(style.getResourceUri().toString().endsWith("test.css")); + } + + @Test + public void resolveCSSByPluginId() throws Exception { + model.initialize(null, null, null, new Element(new QualifiedName("http://org.eclipse.vex/namespace2", "rootElement"))); + final Style style = model.getStyle(); + assertNotNull(style); + assertTrue(style.getResourceUri().toString().endsWith("test-doctype-id.css")); + } + + @Test + public void resolveCSSByNamespace() throws Exception { + model.initialize(null, null, null, new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement"))); + assertFalse(model.isDtdAssigned()); + final Style style = model.getStyle(); + assertNotNull(style); + assertTrue(style.getResourceUri().toString().endsWith("test-schema.css")); + } +} diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/tests/VexUiTestSuite.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/tests/VexUiTestSuite.java index e2fd051d..c97a42a0 100644 --- a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/tests/VexUiTestSuite.java +++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/tests/VexUiTestSuite.java @@ -13,6 +13,8 @@ package org.eclipse.vex.ui.tests; import org.eclipse.vex.ui.internal.config.tests.ConfigLoaderJobTest; import org.eclipse.vex.ui.internal.config.tests.ConfigurationRegistryTest; +import org.eclipse.vex.ui.internal.config.tests.PreferencesTest; +import org.eclipse.vex.ui.internal.config.tests.VexDocumentContentModelTest; import org.eclipse.vex.ui.internal.editor.tests.FindReplaceTargetTest; import org.eclipse.vex.ui.internal.editor.tests.HandlerUtilTest; import org.eclipse.vex.ui.internal.namespace.tests.EditNamespacesControllerTest; @@ -23,6 +25,6 @@ import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ ConfigLoaderJobTest.class, ConfigurationRegistryTest.class, EditNamespacesControllerTest.class, FindReplaceTargetTest.class, OutlineProviderTest.class, OutlineFilterTest.class, - HandlerUtilTest.class }) + HandlerUtilTest.class, VexDocumentContentModelTest.class, PreferencesTest.class }) public class VexUiTestSuite { } diff --git a/org.eclipse.vex.ui.tests/testdata/test-doctype-id.css b/org.eclipse.vex.ui.tests/testdata/test-doctype-id.css new file mode 100644 index 00000000..9a830317 --- /dev/null +++ b/org.eclipse.vex.ui.tests/testdata/test-doctype-id.css @@ -0,0 +1,53 @@ + +html { + display: block; +} + +body { + display: block; +} + +p { + display: block; +} + +block { + display: block; +} + +pre { + display: block; + white-space: pre; +} + + +/* Styles for positioning tests */ +root { + border: 3px 7px 11px 13px; + padding: 17px 19px 23px 29px; +} + +small { + border-width: 1px 2px 3px 4px; + border-style: solid; + margin: 100px 200px 300px 400px; + padding: 10px 20px 30px 40px; + display: block; +} + +medium { + border-width: 2px 4px 6px 8px; + border-style: solid; + margin: 200px 400px 600px 800px; + padding: 20px 40px 60px 80px; + display: block; +} + +large { + border-width: 3px 6px 9px 12px; + border-style: solid; + margin: 300px 600px 900px 1200px; + padding: 30px 60px 90px 120px; + display: block; +} + diff --git a/org.eclipse.vex.ui.tests/testdata/test-schema.css b/org.eclipse.vex.ui.tests/testdata/test-schema.css new file mode 100644 index 00000000..9a830317 --- /dev/null +++ b/org.eclipse.vex.ui.tests/testdata/test-schema.css @@ -0,0 +1,53 @@ + +html { + display: block; +} + +body { + display: block; +} + +p { + display: block; +} + +block { + display: block; +} + +pre { + display: block; + white-space: pre; +} + + +/* Styles for positioning tests */ +root { + border: 3px 7px 11px 13px; + padding: 17px 19px 23px 29px; +} + +small { + border-width: 1px 2px 3px 4px; + border-style: solid; + margin: 100px 200px 300px 400px; + padding: 10px 20px 30px 40px; + display: block; +} + +medium { + border-width: 2px 4px 6px 8px; + border-style: solid; + margin: 200px 400px 600px 800px; + padding: 20px 40px 60px 80px; + display: block; +} + +large { + border-width: 3px 6px 9px 12px; + border-style: solid; + margin: 300px 600px 900px 1200px; + padding: 30px 60px 90px 120px; + display: block; +} + diff --git a/org.eclipse.vex.ui/schema/doctype.exsd b/org.eclipse.vex.ui/schema/doctype.exsd index 3846319e..1d2aa3bf 100644 --- a/org.eclipse.vex.ui/schema/doctype.exsd +++ b/org.eclipse.vex.ui/schema/doctype.exsd @@ -1,133 +1,149 @@ - - - - - - - - - Registers a new document type with Vex. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [Enter the first release in which this extension point appears.] - - - - - - - - - [Enter extension point usage example here.] - - - - - - - - - [Enter API information here.] - - - - - - - - - [Enter information about supplied implementation of this extension point.] - - - - - + + + + + + + + + Registers a new document type with Vex. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The namespace name that is the target of the defined XML-Schema + + + + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/org.eclipse.vex.ui/schema/style.exsd b/org.eclipse.vex.ui/schema/style.exsd index 26a3933c..5ce16ad3 100644 --- a/org.eclipse.vex.ui/schema/style.exsd +++ b/org.eclipse.vex.ui/schema/style.exsd @@ -1,16 +1,21 @@ - + - + - + - Registers a new document type with Vex. + Registers a new CSS Stylesheet type with Vex. + + + + + @@ -49,9 +54,9 @@ - + - + @@ -62,7 +67,7 @@ - + The PublicID (DTD) or namespace (XML-Schema) of the referenced document type. @@ -70,48 +75,40 @@ - - - + + + - [Enter the first release in which this extension point appears.] + [Enter API information here.] - - - + + + - [Enter extension point usage example here.] + [Enter the first release in which this extension point appears.] - - - + + + - [Enter API information here.] + [Enter extension point usage example here.] - + - + [Enter information about supplied implementation of this extension point.] - - - - - - - - diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/VexPreferences.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/VexPreferences.java index a7599d0a..056b959c 100644 --- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/VexPreferences.java +++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/VexPreferences.java @@ -19,7 +19,9 @@ import org.eclipse.vex.core.internal.css.IStyleSheetProvider; import org.eclipse.vex.core.internal.css.StyleSheet; import org.eclipse.vex.core.provisional.dom.DocumentContentModel; import org.eclipse.vex.ui.internal.config.ConfigurationRegistry; +import org.eclipse.vex.ui.internal.config.DocumentType; import org.eclipse.vex.ui.internal.config.Style; +import org.eclipse.vex.ui.internal.editor.VexDocumentContentModel; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; @@ -49,9 +51,9 @@ public class VexPreferences implements IStyleSheetProvider { this.configurationRegistry = configurationRegistry; } - public void setPreferredStyleId(final String publicId, final String styleId) { + public void setPreferredStyleId(final DocumentType doctype, final String styleId) { final Preferences preferences = InstanceScope.INSTANCE.getNode(VexPlugin.ID); - final String key = getStylePreferenceKey(publicId); + final String key = getStylePreferenceKey(doctype.getUniqueId()); preferences.put(key, styleId); try { preferences.flush(); @@ -60,9 +62,9 @@ public class VexPreferences implements IStyleSheetProvider { } } - public String getPreferredStyleId(final String publicId) { + public String getPreferredStyleId(final DocumentType doctype) { final Preferences preferences = InstanceScope.INSTANCE.getNode(VexPlugin.ID); - final String preferredStyleId = preferences.get(getStylePreferenceKey(publicId), null); + final String preferredStyleId = preferences.get(getStylePreferenceKey(doctype.getUniqueId()), null); return preferredStyleId; } @@ -70,8 +72,8 @@ public class VexPreferences implements IStyleSheetProvider { return publicId + PREFERRED_STYLE_SUFFIX; } - public Style getPreferredStyle(final String publicId) { - return configurationRegistry.getStyle(publicId, getPreferredStyleId(publicId)); + public Style getPreferredStyle(final DocumentType doctype) { + return configurationRegistry.getStyle(doctype, getPreferredStyleId(doctype)); } public String getIndentationPattern() { @@ -87,7 +89,13 @@ public class VexPreferences implements IStyleSheetProvider { } public StyleSheet getStyleSheet(final DocumentContentModel documentContentModel) { - final Style style = getPreferredStyle(documentContentModel.getMainDocumentTypeIdentifier()); + Style style = null; + if (documentContentModel instanceof VexDocumentContentModel) { + // We only support the VexDocumentContentModel + // If there will ever be another DocumentContentModel implememntation, it will + // have to define it's own method for resolving styles + style = getPreferredStyle(((VexDocumentContentModel) documentContentModel).getDocumentType()); + } if (style == null) { return StyleSheet.NULL; } diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigLoaderJob.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigLoaderJob.java index e80e0873..a979bab9 100644 --- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigLoaderJob.java +++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigLoaderJob.java @@ -108,7 +108,7 @@ public class ConfigLoaderJob extends Job implements ConfigurationLoader { } public boolean isLoading() { - return getState() == Job.RUNNING; + return getState() == Job.RUNNING || getState() == Job.WAITING; } public void load(final Runnable whenDone) { diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistry.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistry.java index ea8b2786..0b73b9f7 100644 --- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistry.java +++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistry.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Florian Thienel - initial API and implementation *******************************************************************************/ @@ -35,15 +35,17 @@ public interface ConfigurationRegistry { boolean isLoaded(); /** - * The document type configuration for the given public identifier, or null if there is no configuration for the - * given public identifier. + * The document type configuration for the given identifier.
+ * This method tries to resolve by PublicId or namespace first. If this does not yield as result, a doctype with a + * matching SystemId is returned. * - * @param publicId - * the public identifier - * @return the document type configuration for the given public identifier, or null if there is no configuration for - * the given public identifier. + * @param id + * the public/system identifier or namespace + * @param systemId + * the system id, only used when resolving the public id fails. May be null. + * @return the document type configuration for the identifier, or null if there is no doctype found. */ - DocumentType getDocumentType(final String publicId); + DocumentType getDocumentType(final String id, final String systemId); /** * @return all document type configurations @@ -56,13 +58,18 @@ public interface ConfigurationRegistry { DocumentType[] getDocumentTypesWithStyles(); /** - * All styles for the document type with the given public identifier. + * All styles for the given document type. The returned styles are ordered by the way they are resolved: + *
    + *
  • 1. document type id
  • + *
  • 2. Public ID (DTD) or Namespace (XML-Schema)
  • + *
  • 3. System ID (DTD)
  • + *
* - * @param publicId - * the document type's public identifier - * @return all styles for the document type with the given public identifier + * @param doctype + * the document type + * @return all styles for the given document type */ - Style[] getStyles(final String publicId); + Style[] getStyles(final DocumentType doctype); /** * The style with the given id, or null if there is no style with this id. @@ -74,16 +81,15 @@ public interface ConfigurationRegistry { Style getStyle(final String styleId); /** - * An arbitrary style for the document type with the given public identifier. If available, the style with the given - * style id is preferred. + * An arbitrary style for the given document type. If available, the style with the given style id is preferred. * - * @param publicId - * the document type's public identifier + * @param pdoctype + * the document type * @param preferredStyleId * the preferred style's id * @return a style for the given document type, or null if no style is configured for the given document type */ - Style getStyle(final String publicId, final String preferredStyleId); + Style getStyle(final DocumentType doctype, final String preferredStyleId); /** * The representation of the given plug-in project in the workspace. diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistryImpl.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistryImpl.java index 2317d580..971e8cd0 100644 --- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistryImpl.java +++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistryImpl.java @@ -187,15 +187,22 @@ public class ConfigurationRegistryImpl implements ConfigurationRegistry { configListeners.fireEvent("configLoaded", e); //$NON-NLS-1$ } - public DocumentType getDocumentType(final String publicId) { + public DocumentType getDocumentType(final String id, final String systemId) { final List configItems = getAllConfigItems(DocumentType.EXTENSION_POINT); + DocumentType systemDoctype = null; + // Try to resolve by PublicId or namespace first for (final ConfigItem configItem : configItems) { final DocumentType doctype = (DocumentType) configItem; - if (doctype.getPublicId().equals(publicId)) { + if (id.equals(doctype.getPublicId()) || id.equals(doctype.getNamespaceName())) { return doctype; } + if (systemId != null && systemId.equals(doctype.getSystemId())) { + // Save the doctype resolved by SystemID + systemDoctype = doctype; + } } - return null; + + return systemDoctype; // May be null } public DocumentType[] getDocumentTypes() { @@ -210,21 +217,40 @@ public class ConfigurationRegistryImpl implements ConfigurationRegistry { final List result = new ArrayList(); for (final ConfigItem configItem : getAllConfigItems(DocumentType.EXTENSION_POINT)) { final DocumentType doctype = (DocumentType) configItem; - if (getStyles(doctype.getPublicId()).length > 0) { + if (getStyles(doctype).length > 0) { result.add(doctype); } } return result.toArray(new DocumentType[result.size()]); } - public Style[] getStyles(final String publicId) { - final ArrayList