From 39ef6890457072c80185012b972be85ea6796c20 Mon Sep 17 00:00:00 2001
From: azerr
Date: Sat, 16 May 2020 20:04:13 +0200
Subject: [PATCH] Grammar generator from XML
Fixes #778
Signed-off-by: azerr
---
.../AbstractXML2GrammarGenerator.java | 164 ++++++++++++++++++
.../generators/AttributeDeclaration.java | 34 ++++
.../generators/ChildrenProperties.java | 107 ++++++++++++
.../generators/ChildrenPropertiesTest.java | 22 +++
.../generators/ContainerDeclaration.java | 61 +++++++
.../generators/ElementDeclaration.java | 122 +++++++++++++
.../FileContentGeneratorManager.java | 92 ++++++++++
.../FileContentGeneratorSettings.java | 20 +++
.../extensions/generators/Grammar.java | 40 +++++
.../generators/IFileContentGenerator.java | 41 +++++
.../xml2dtd/DTDGeneratorSettings.java | 22 +++
.../generators/xml2dtd/XML2DTDGenerator.java | 112 ++++++++++++
.../xml2xsd/XML2XMLSchemaGenerator.java | 98 +++++++++++
.../xml2xsd/XMLSchemaGeneratorSettings.java | 22 +++
.../lemminx/services/IXMLFullFormatter.java | 37 ++++
.../lemminx/services/XMLLanguageService.java | 17 +-
.../org/eclipse/lemminx/utils/XMLBuilder.java | 10 ++
.../java/org/eclipse/lemminx/XMLAssert.java | 33 +++-
.../generators/ChildrenPropertiesTest.java | 23 +++
.../xml2dtd/XML2DTDGeneratorTest.java | 141 +++++++++++++++
.../xml2xsd/XML2XMLSchemaGeneratorTest.java | 117 +++++++++++++
21 files changed, 1321 insertions(+), 14 deletions(-)
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/AbstractXML2GrammarGenerator.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/AttributeDeclaration.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ChildrenProperties.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ChildrenPropertiesTest.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ContainerDeclaration.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ElementDeclaration.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/FileContentGeneratorManager.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/FileContentGeneratorSettings.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/Grammar.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/IFileContentGenerator.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/xml2dtd/DTDGeneratorSettings.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/xml2dtd/XML2DTDGenerator.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/xml2xsd/XML2XMLSchemaGenerator.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/xml2xsd/XMLSchemaGeneratorSettings.java
create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/IXMLFullFormatter.java
create mode 100644 org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/generators/ChildrenPropertiesTest.java
create mode 100644 org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/generators/xml2dtd/XML2DTDGeneratorTest.java
create mode 100644 org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/generators/xml2xsd/XML2XMLSchemaGeneratorTest.java
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/AbstractXML2GrammarGenerator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/AbstractXML2GrammarGenerator.java
new file mode 100644
index 0000000000..dbf2c1f841
--- /dev/null
+++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/AbstractXML2GrammarGenerator.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+* Copyright (c) 2020 Red Hat Inc. and others.
+* All rights reserved. This program and the accompanying materials
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v20.html
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Red Hat Inc. - initial API and implementation
+*******************************************************************************/
+package org.eclipse.lemminx.extensions.generators;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.lemminx.commons.TextDocument;
+import org.eclipse.lemminx.dom.DOMAttr;
+import org.eclipse.lemminx.services.IXMLFullFormatter;
+import org.eclipse.lemminx.settings.SharedSettings;
+import org.eclipse.lemminx.utils.StringUtils;
+import org.eclipse.lemminx.utils.XMLBuilder;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Abstract class to generate a grammar (XSD, DTD, etcc) from a given XML
+ * source.
+ *
+ *
+ * The process is to build a generic {@link Grammar} instance from the XML
+ * source and each implementation uses this grammar information to generate the
+ * proper grammar.
+ *
+ *
+ * @param the grammar generator settings.
+ */
+public abstract class AbstractXML2GrammarGenerator
+ implements IFileContentGenerator {
+
+ @Override
+ public String generate(Document document, SharedSettings sharedSettings, T generatorSettings,
+ IXMLFullFormatter formatter) {
+ String newText = doGenerate(document, sharedSettings, generatorSettings);
+ if (formatter == null) {
+ return newText;
+ }
+ return formatter.formatFull(new TextDocument(newText, "grammar." + getFileExtension()), sharedSettings);
+ }
+
+ protected abstract String getFileExtension();
+
+ private String doGenerate(Document document, SharedSettings sharedSettings, T generatorSettings) {
+ // Create the generic grammar information from the XML source document.
+ Grammar grammar = createGrammar(document, isFlat());
+ XMLBuilder builder = new XMLBuilder(sharedSettings, "", "");
+ // Generate the grammar content from the grammar information.
+ generate(grammar, generatorSettings, builder);
+ return builder.toString();
+ }
+
+ protected boolean isFlat() {
+ return false;
+ }
+
+ /**
+ * Generate the grammar content from the given grammr information into the given
+ * builder.
+ *
+ * @param grammar the grammar information.
+ * @param grammarSettings the grammar settings
+ * @param out the XML builder to update.
+ */
+ protected abstract void generate(Grammar grammar, T grammarSettings, XMLBuilder out);
+
+ private Grammar createGrammar(Document document, boolean flat) {
+ Grammar grammar = new Grammar();
+ // Update default namespace
+ String defaultNamespace = null;
+ Element documentElement = document.getDocumentElement();
+ if (documentElement != null) {
+ defaultNamespace = document.getDocumentElement().getAttribute(DOMAttr.XMLNS_ATTR);
+ }
+ grammar.setDefaultNamespace(defaultNamespace);
+ // Update elements information
+ fillElements(document, grammar, grammar, flat);
+ return grammar;
+ }
+
+ private static void fillElements(Node node, Grammar grammar, ContainerDeclaration parent, boolean flat) {
+ if (!node.hasChildNodes()) {
+ return;
+ }
+ NodeList children = node.getChildNodes();
+
+ // Parent
+ if (parent instanceof ElementDeclaration) {
+ List tags = new ArrayList<>();
+ ElementDeclaration parentDecl = (ElementDeclaration) parent;
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ Element element = (Element) child;
+ String localName = element.getLocalName();
+ if (!StringUtils.isEmpty(localName)) {
+ tags.add(localName);
+ }
+ }
+ }
+ parentDecl.addChildHierarchy(tags);
+
+ // ((ElementDeclaration) container).addTagName(element.getTagName());
+ }
+
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ Element element = (Element) child;
+ ElementDeclaration elementDecl = getElementDecl(grammar, parent, flat, element);
+ // Update count occurrences
+ elementDecl.incrementOccurrences();
+ // Update has text
+ if (!elementDecl.hasCharacterContent()) {
+ elementDecl.setHasCharacterContent(hasCharacterContent(element));
+ }
+ // Update attributes
+ NamedNodeMap attributes = element.getAttributes();
+ if (attributes != null) {
+ for (int j = 0; j < attributes.getLength(); j++) {
+ Attr attr = (Attr) attributes.item(i);
+ elementDecl.getAttribute(attr.getName());
+ }
+ }
+ fillElements(element, grammar, elementDecl, flat);
+ }
+ }
+ }
+
+ private static ElementDeclaration getElementDecl(Grammar grammar, ContainerDeclaration container, boolean flat,
+ Element element) {
+ String name = element.getLocalName();
+ if (flat) {
+ ElementDeclaration elementDecl = grammar.getElement(name);
+ container.addElement(elementDecl);
+ return elementDecl;
+ }
+ return container.getElement(element.getLocalName());
+ }
+
+ private static boolean hasCharacterContent(Element element) {
+ NodeList children = element.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.TEXT_NODE) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/AttributeDeclaration.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/AttributeDeclaration.java
new file mode 100644
index 0000000000..502ccd8eb6
--- /dev/null
+++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/AttributeDeclaration.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+* Copyright (c) 2020 Red Hat Inc. and others.
+* All rights reserved. This program and the accompanying materials
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v20.html
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Red Hat Inc. - initial API and implementation
+*******************************************************************************/
+package org.eclipse.lemminx.extensions.generators;
+
+/**
+ * Attribute declaration.
+ *
+ */
+public class AttributeDeclaration {
+
+ private final String name;
+
+ public AttributeDeclaration(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the attribute name.
+ *
+ * @return the attribute name.
+ */
+ public String getName() {
+ return name;
+ }
+}
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ChildrenProperties.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ChildrenProperties.java
new file mode 100644
index 0000000000..10f56b109d
--- /dev/null
+++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ChildrenProperties.java
@@ -0,0 +1,107 @@
+package org.eclipse.lemminx.extensions.generators;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+// TODO : cleanup this class!!!
+public class ChildrenProperties {
+
+ private List firstSequence;
+
+ public static class Cardinality {
+
+ private long min;
+
+ private long max;
+
+ public void setMin(long min) {
+ this.min = min;
+ }
+
+ public void setMax(long max) {
+ this.max = max;
+ }
+
+ public long getMin() {
+ return min;
+ }
+
+ public long getMax() {
+ return max;
+ }
+ }
+
+ private boolean sequenced;
+
+ private Map cardinalities;
+
+ public ChildrenProperties() {
+ this.cardinalities = new LinkedHashMap<>();
+ this.sequenced = true;
+ }
+
+ public void addChildHierarchy(List tags) {
+ boolean first = firstSequence == null;
+ Map tagsCount = tags.stream().collect( //
+ Collectors.groupingBy( //
+ Function.identity(), LinkedHashMap::new, Collectors.counting() //
+ ));
+ List filteredTags = new LinkedList<>(tagsCount.keySet());
+ if (firstSequence == null) {
+ firstSequence = filteredTags;
+ }
+ for (Map.Entry entry : cardinalities.entrySet()) {
+ String tag = entry.getKey();
+ Cardinality cardinality = entry.getValue();
+ Long count = tagsCount.remove(tag);
+ if (count != null) {
+ cardinality.setMin(Math.min(count, cardinality.getMin()));
+ cardinality.setMax(Math.max(count, cardinality.getMax()));
+ } else {
+ cardinality.setMin(0);
+ }
+ }
+
+ for (Map.Entry entry : tagsCount.entrySet()) {
+ String tag = entry.getKey();
+ Cardinality cardinality = cardinalities.get(tag);
+ if (cardinality == null) {
+ cardinality = new Cardinality();
+ cardinalities.put(tag, cardinality);
+ }
+ Long count = tagsCount.get(tag);
+ if (first) {
+ cardinality.setMin(count);
+ cardinality.setMax(count);
+ } else {
+ cardinality.setMin(Math.min(count, cardinality.getMin()));
+ cardinality.setMax(Math.max(count, cardinality.getMax()));
+ }
+ }
+
+ for (Map.Entry entry : cardinalities.entrySet()) {
+ String tag = entry.getKey();
+ Cardinality cardinality = entry.getValue();
+ if (cardinality.getMin() == 0) {
+ firstSequence.remove(tag);
+ filteredTags.remove(tag);
+ }
+ }
+
+ if (sequenced) {
+ sequenced = filteredTags.equals(firstSequence);
+ }
+ }
+
+ public Map getCardinalities() {
+ return cardinalities;
+ }
+
+ public boolean isSequenced() {
+ return sequenced;
+ }
+}
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ChildrenPropertiesTest.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ChildrenPropertiesTest.java
new file mode 100644
index 0000000000..4941a15874
--- /dev/null
+++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ChildrenPropertiesTest.java
@@ -0,0 +1,22 @@
+package org.eclipse.lemminx.extensions.generators;
+
+import java.util.Arrays;
+import java.util.Map.Entry;
+
+import org.eclipse.lemminx.extensions.generators.ChildrenProperties.Cardinality;
+
+public class ChildrenPropertiesTest {
+
+ public static void main(String[] args) {
+ ChildrenProperties properties = new ChildrenProperties();
+ properties.addChildHierarchy(Arrays.asList("a", "c"));
+ //properties.addChildHierarchy(Arrays.asList("c", "a"));
+ properties.addChildHierarchy(Arrays.asList("a", "c", "c"));
+ properties.addChildHierarchy(Arrays.asList("a", "b", "c"));
+ System.err.println("Sequenced:" + properties.isSequenced());
+ for (Entry entry : properties.getCardinalities().entrySet()) {
+ System.err
+ .println(entry.getKey() + " [" + entry.getValue().getMin() + "-" + entry.getValue().getMax() + "]");
+ }
+ }
+}
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ContainerDeclaration.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ContainerDeclaration.java
new file mode 100644
index 0000000000..9c2cd3350c
--- /dev/null
+++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ContainerDeclaration.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+* Copyright (c) 2020 Red Hat Inc. and others.
+* All rights reserved. This program and the accompanying materials
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v20.html
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Red Hat Inc. - initial API and implementation
+*******************************************************************************/
+package org.eclipse.lemminx.extensions.generators;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Children information.
+ *
+ */
+public class ContainerDeclaration {
+
+ private final Map container;
+
+ public ContainerDeclaration() {
+ this.container = new LinkedHashMap<>();
+ }
+
+ /**
+ * Returns the element information for the given name and create it if not
+ * found.
+ *
+ * @param name the element name
+ * @return the element information for the given name and create it if not
+ * found.
+ */
+ public ElementDeclaration getElement(String name) {
+ ElementDeclaration element = container.get(name);
+ if (element != null) {
+ return element;
+ }
+ element = new ElementDeclaration(name);
+ addElement(element);
+ return element;
+ }
+
+ public void addElement(ElementDeclaration element) {
+ container.put(element.getName(), element);
+ }
+
+ /**
+ * Returns the elements information of the node.
+ *
+ * @return the elements information of the node.
+ */
+ public Collection getElements() {
+ return container.values();
+ }
+
+}
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ElementDeclaration.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ElementDeclaration.java
new file mode 100644
index 0000000000..0c4c8dbb63
--- /dev/null
+++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/ElementDeclaration.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+* Copyright (c) 2020 Red Hat Inc. and others.
+* All rights reserved. This program and the accompanying materials
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v20.html
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Red Hat Inc. - initial API and implementation
+*******************************************************************************/
+package org.eclipse.lemminx.extensions.generators;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.lemminx.extensions.generators.ChildrenProperties.Cardinality;
+
+/**
+ * Element information.
+ *
+ */
+public class ElementDeclaration extends ContainerDeclaration {
+
+ private final String name;
+
+ private ElementDeclaration parent;
+
+ private final Map attributes;
+
+ private boolean hasCharacterContent;
+
+ private int occurrences;
+
+ // Children information
+
+ private ChildrenProperties childrenProperties;
+
+ public ElementDeclaration(String name) {
+ this.name = name;
+ this.attributes = new HashMap<>();
+ this.occurrences = 0;
+ this.childrenProperties = new ChildrenProperties();
+ }
+
+ /**
+ * Returns the element name.
+ *
+ * @return the element name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the attribute information for the given name and create it if not
+ * found.
+ *
+ * @param name the attribute name
+ * @return the attribute information for the given name and create it if not
+ * found.
+ */
+ public AttributeDeclaration getAttribute(String name) {
+ AttributeDeclaration attribute = attributes.get(name);
+ if (attribute != null) {
+ return attribute;
+ }
+ attribute = new AttributeDeclaration(name);
+ attributes.put(name, attribute);
+ return attribute;
+ }
+
+ public Collection getAttributes() {
+ return attributes.values();
+ }
+
+ /**
+ * Returns true if element has character content and false otherwise.
+ *
+ * @return true if element has character content and false otherwise.
+ */
+ public boolean hasCharacterContent() {
+ return hasCharacterContent;
+ }
+
+ void setHasCharacterContent(boolean hasCharacterContent) {
+ this.hasCharacterContent = hasCharacterContent;
+ }
+
+ public void incrementOccurrences() {
+ occurrences++;
+ }
+
+ public int getOccurrences() {
+ return occurrences;
+ }
+
+ @Override
+ public void addElement(ElementDeclaration element) {
+ super.addElement(element);
+ element.setParent(this);
+ }
+
+ public ElementDeclaration getParent() {
+ return parent;
+ }
+
+ void setParent(ElementDeclaration parent) {
+ this.parent = parent;
+ }
+
+ public void addChildHierarchy(List tags) {
+ childrenProperties.addChildHierarchy(tags);
+ }
+
+ public ChildrenProperties getChildrenProperties() {
+ return childrenProperties;
+ }
+}
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/FileContentGeneratorManager.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/FileContentGeneratorManager.java
new file mode 100644
index 0000000000..ab94683139
--- /dev/null
+++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/generators/FileContentGeneratorManager.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+* Copyright (c) 2020 Red Hat Inc. and others.
+* All rights reserved. This program and the accompanying materials
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v20.html
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Red Hat Inc. - initial API and implementation
+*******************************************************************************/
+package org.eclipse.lemminx.extensions.generators;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.lemminx.extensions.generators.xml2dtd.DTDGeneratorSettings;
+import org.eclipse.lemminx.extensions.generators.xml2dtd.XML2DTDGenerator;
+import org.eclipse.lemminx.extensions.generators.xml2xsd.XML2XMLSchemaGenerator;
+import org.eclipse.lemminx.extensions.generators.xml2xsd.XMLSchemaGeneratorSettings;
+import org.eclipse.lemminx.services.IXMLFullFormatter;
+import org.eclipse.lemminx.settings.SharedSettings;
+
+/**
+ * Generic file generator.
+ *
+ *
+ * By default the manager is able to generate :
+ *
+ *
+ *
XML Schema from a given XML.
+ *
DTD from a given XML.
+ *
+ *
+ */
+public class FileContentGeneratorManager {
+
+ private static final FileContentGeneratorManager INSTANCE = new FileContentGeneratorManager();
+ private final Map, IFileContentGenerator, ?>> generators;
+
+ private FileContentGeneratorManager() {
+ generators = new HashMap<>();
+ registerDefaultGenerators();
+ }
+
+ /**
+ * Register default generators.
+ */
+ private void registerDefaultGenerators() {
+ registerGenerator(new XML2DTDGenerator(), DTDGeneratorSettings.class);
+ registerGenerator(new XML2XMLSchemaGenerator(), XMLSchemaGeneratorSettings.class);
+ }
+
+ public static FileContentGeneratorManager getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Register the given generator by using settings class as key generator.
+ *
+ * @param generator the generator.
+ * @param generatorKey the key of the generator identified by the settings
+ * class.
+ */
+ public void registerGenerator(IFileContentGenerator, ?> generator,
+ Class extends FileContentGeneratorSettings> generatorKey) {
+ generators.put(generatorKey, generator);
+ }
+
+ /**
+ * Generates a file content (ex : XSD, DTD) from the given document source
+ * document (ex: XML) by using the given settings
+ * generatorSettings.
+ *
+ * @param document the document source (ex : XML).
+ * @param sharedSettings the shared settings.
+ * @param generatorSettings the generator settings.
+ * @param formatter the formatter.
+ * @return the result of the generation of the file content (ex : XSD, DTD) from
+ * the given document source document (ex: XML) by using
+ * the given settings generatorSettings.
+ */
+ public