/bundles/plugins-trunk/XML/xml/translate/BufferDtdConverter.java
Java | 1164 lines | 955 code | 125 blank | 84 comment | 206 complexity | d9030a86396cbd4e7c3725ae8c628f0b MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
- /*
- Copyright (c) 2001-2003 Thai Open Source Software Center Ltd
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
- Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- Neither the name of the Thai Open Source Software Center Ltd nor
- the names of its contributors may be used to endorse or promote
- products derived from this software without specific prior written
- permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- package xml.translate;
- import com.thaiopensource.relaxng.edit.Annotated;
- import com.thaiopensource.relaxng.edit.AnyNameNameClass;
- import com.thaiopensource.relaxng.edit.AttributeAnnotation;
- import com.thaiopensource.relaxng.edit.AttributePattern;
- import com.thaiopensource.relaxng.edit.ChoicePattern;
- import com.thaiopensource.relaxng.edit.Combine;
- import com.thaiopensource.relaxng.edit.Comment;
- import com.thaiopensource.relaxng.edit.Component;
- import com.thaiopensource.relaxng.edit.CompositePattern;
- import com.thaiopensource.relaxng.edit.DataPattern;
- import com.thaiopensource.relaxng.edit.DefineComponent;
- import com.thaiopensource.relaxng.edit.ElementPattern;
- import com.thaiopensource.relaxng.edit.EmptyPattern;
- import com.thaiopensource.relaxng.edit.GrammarPattern;
- import com.thaiopensource.relaxng.edit.GroupPattern;
- import com.thaiopensource.relaxng.edit.IncludeComponent;
- import com.thaiopensource.relaxng.edit.NameClass;
- import com.thaiopensource.relaxng.edit.NameNameClass;
- import com.thaiopensource.relaxng.edit.NotAllowedPattern;
- import com.thaiopensource.relaxng.edit.OneOrMorePattern;
- import com.thaiopensource.relaxng.edit.OptionalPattern;
- import com.thaiopensource.relaxng.edit.Pattern;
- import com.thaiopensource.relaxng.edit.RefPattern;
- import com.thaiopensource.relaxng.edit.SchemaCollection;
- import com.thaiopensource.relaxng.edit.SchemaDocument;
- import com.thaiopensource.relaxng.edit.TextPattern;
- import com.thaiopensource.relaxng.edit.ValuePattern;
- import com.thaiopensource.relaxng.edit.ZeroOrMorePattern;
- import com.thaiopensource.relaxng.input.CommentTrimmer;
- import com.thaiopensource.relaxng.output.common.ErrorReporter;
- import com.thaiopensource.xml.dtd.om.AttributeDefault;
- import com.thaiopensource.xml.dtd.om.AttributeGroup;
- import com.thaiopensource.xml.dtd.om.AttributeGroupMember;
- import com.thaiopensource.xml.dtd.om.AttributeGroupVisitor;
- import com.thaiopensource.xml.dtd.om.Datatype;
- import com.thaiopensource.xml.dtd.om.DatatypeVisitor;
- import com.thaiopensource.xml.dtd.om.Def;
- import com.thaiopensource.xml.dtd.om.Dtd;
- import com.thaiopensource.xml.dtd.om.EnumGroup;
- import com.thaiopensource.xml.dtd.om.EnumGroupVisitor;
- import com.thaiopensource.xml.dtd.om.Flag;
- import com.thaiopensource.xml.dtd.om.ModelGroup;
- import com.thaiopensource.xml.dtd.om.ModelGroupVisitor;
- import com.thaiopensource.xml.dtd.om.NameSpec;
- import com.thaiopensource.xml.dtd.om.TokenizedDatatype;
- import com.thaiopensource.xml.dtd.om.TopLevel;
- import com.thaiopensource.xml.dtd.om.TopLevelVisitor;
- import com.thaiopensource.xml.em.ExternalId;
- import com.thaiopensource.xml.util.WellKnownNamespaces;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.Vector;
- /* copy of http://jing-trang.googlecode.com/svn/tags/V20091111/mod/convert-from-dtd/src/main/com/thaiopensource/relaxng/input/dtd/Converter.java
- * it is necessary since the Options class is package protected and I need to create one in BufferDtdInputFormat
- */
- public class BufferDtdConverter {
- static class Options {
- boolean inlineAttlistDecls;
- boolean generateStart = true;
- boolean strictAny;
- String elementDeclPattern;
- String attlistDeclPattern;
- String colonReplacement;
- String anyName;
- String annotationPrefix;
- String defaultNamespace;
- final Map<String, String> prefixMap = new HashMap<String, String>();
- }
- private final Dtd dtd;
- private final ErrorReporter er;
- private final SchemaCollection sc = new SchemaCollection();
- private final Options options;
- /**
- * true if any uses of ANY have been encountered in the DTD
- */
- private boolean hadAny = false;
- /**
- * true if any default values have been encountered in the DTD
- */
- private boolean hadDefaultValue = false;
- /**
- * Maps each element name to an Integer containing a set of flags.
- */
- private final Map<String, Integer> elementNameTable = new HashMap<String, Integer>();
- /**
- * Maps each element name to a List of attribute groups of each attlist declaration.
- */
- private final Map<String, List<AttributeGroup>> attlistDeclTable = new HashMap<String, List<AttributeGroup>>();
- /**
- * Set of strings representing names for which there are definitions in the DTD.
- */
- private final Set<String> definedNames = new HashSet<String>();
- /**
- * Maps prefixes to namespace URIs.
- */
- private final Map<String, String> prefixTable = new HashMap<String, String>();
- /**
- * Maps a string representing an element name to the set of names of attributes
- * that have been declated for that element.
- */
- private final Map<String, Set<String>> attributeNamesTable = new HashMap<String, Set<String>>();
- /**
- * Contains the set of attribute names that have already been output in the current scope.
- */
- private Set<String> attributeNames = null;
- private String defaultNamespace = null;
- private String annotationPrefix = null;
- // These variables control the names use for definitions.
- private String colonReplacement = null;
- private String elementDeclPattern = null;
- private String attlistDeclPattern = null;
- private String anyName = null;
- /**
- * Flags for element names used in elementDeclTable.
- */
- private static final int ELEMENT_DECL = 01;
- private static final int ATTLIST_DECL = 02;
- private static final int ELEMENT_REF = 04;
- /**
- * Characters that will be considered for use as a replacement for colon in
- * a QName. Also used as separators in constructing names of definitions
- * corresponding to element declarations and attlist declarations,
- */
- private static final String SEPARATORS = ".-_";
- // # is the category; % is the name in the category
- private static final String DEFAULT_PATTERN = "#.%";
- private final String[] ELEMENT_KEYWORDS = {
- "element", "elem", "e"
- };
- private final String[] ATTLIST_KEYWORDS = {
- "attlist", "attributes", "attribs", "atts", "a"
- };
- private final String[] ANY_KEYWORDS = {
- "any", "ANY", "anyElement"
- };
- private static abstract class VisitorBase implements TopLevelVisitor {
- public void processingInstruction(String target, String value) throws Exception { }
- public void comment(String value) throws Exception { }
- public void flagDef(String name, Flag flag) throws Exception { }
- public void includedSection(Flag flag, TopLevel[] contents)
- throws Exception {
- for (int i = 0; i < contents.length; i++)
- contents[i].accept(this);
- }
- public void ignoredSection(Flag flag, String contents) throws Exception { }
- public void internalEntityDecl(String name, String value) throws Exception { }
- public void externalEntityDecl(String name, ExternalId externalId) throws Exception { }
- public void notationDecl(String name, ExternalId externalId) throws Exception { }
- public void nameSpecDef(String name, NameSpec nameSpec) throws Exception { }
- public void overriddenDef(Def def, boolean isDuplicate) throws Exception { }
- public void externalIdDef(String name, ExternalId externalId) throws Exception { }
- public void externalIdRef(String name, ExternalId externalId,
- String uri, String encoding, TopLevel[] contents)
- throws Exception {
- for (int i = 0; i < contents.length; i++)
- contents[i].accept(this);
- }
- public void paramDef(String name, String value) throws Exception { }
- public void attributeDefaultDef(String name, AttributeDefault ad) throws Exception { }
- }
- private class Analyzer extends VisitorBase implements ModelGroupVisitor,
- AttributeGroupVisitor {
- public void elementDecl(NameSpec nameSpec, ModelGroup modelGroup)
- throws Exception {
- noteElementName(nameSpec.getValue(), ELEMENT_DECL);
- modelGroup.accept(this);
- }
- public void attlistDecl(NameSpec nameSpec, AttributeGroup attributeGroup)
- throws Exception {
- noteElementName(nameSpec.getValue(), ATTLIST_DECL);
- noteAttlist(nameSpec.getValue(), attributeGroup);
- attributeGroup.accept(this);
- }
- public void modelGroupDef(String name, ModelGroup modelGroup)
- throws Exception {
- noteDef(name);
- modelGroup.accept(this);
- }
- public void attributeGroupDef(String name, AttributeGroup attributeGroup)
- throws Exception {
- noteDef(name);
- attributeGroup.accept(this);
- }
- public void enumGroupDef(String name, EnumGroup enumGroup) {
- noteDef(name);
- }
- public void datatypeDef(String name, Datatype datatype) {
- noteDef(name);
- }
- public void choice(ModelGroup[] members) throws Exception {
- for (int i = 0; i < members.length; i++)
- members[i].accept(this);
- }
- public void sequence(ModelGroup[] members) throws Exception {
- for (int i = 0; i < members.length; i++)
- members[i].accept(this);
- }
- public void oneOrMore(ModelGroup member) throws Exception {
- member.accept(this);
- }
- public void zeroOrMore(ModelGroup member) throws Exception {
- member.accept(this);
- }
- public void optional(ModelGroup member) throws Exception {
- member.accept(this);
- }
- public void modelGroupRef(String name, ModelGroup modelGroup) {
- }
- public void elementRef(NameSpec name) {
- noteElementName(name.getValue(), ELEMENT_REF);
- }
- public void pcdata() {
- }
- public void any() {
- hadAny = true;
- }
- public void attribute(NameSpec nameSpec,
- Datatype datatype,
- AttributeDefault attributeDefault) {
- noteAttribute(nameSpec.getValue(), attributeDefault.getDefaultValue());
- }
- public void attributeGroupRef(String name, AttributeGroup attributeGroup) {
- }
- }
- private class ComponentOutput extends VisitorBase {
- private final List<Component> components;
- private final Annotated grammar;
- private List<Comment> comments = null;
- ComponentOutput(GrammarPattern grammar) {
- components = grammar.getComponents();
- this.grammar = grammar;
- }
- void finish() {
- if (comments != null)
- grammar.getFollowingElementAnnotations().addAll(comments);
- }
- private void addComponent(Component c) {
- if (comments != null) {
- if (components.isEmpty())
- grammar.getLeadingComments().addAll(comments);
- else
- c.getLeadingComments().addAll(comments);
- comments = null;
- }
- components.add(c);
- }
- public void elementDecl(NameSpec nameSpec, ModelGroup modelGroup) throws Exception {
- GroupPattern gp = new GroupPattern();
- if (options.inlineAttlistDecls) {
- List<AttributeGroup> groups = attlistDeclTable.get(nameSpec.getValue());
- if (groups != null) {
- attributeNames = new HashSet<String>();
- AttributeGroupVisitor agv = new AttributeGroupOutput(gp);
- for (AttributeGroup group : groups)
- group.accept(agv);
- }
- }
- else
- gp.getChildren().add(ref(attlistDeclName(nameSpec.getValue())));
- Pattern pattern = convert(modelGroup);
- if (gp.getChildren().size() > 0) {
- if (pattern instanceof GroupPattern)
- gp.getChildren().addAll(((GroupPattern)pattern).getChildren());
- else
- gp.getChildren().add(pattern);
- pattern = gp;
- }
- addComponent(new DefineComponent(elementDeclName(nameSpec.getValue()),
- new ElementPattern(convertQName(nameSpec.getValue(), true),
- pattern)));
- if (!options.inlineAttlistDecls && (nameFlags(nameSpec.getValue()) & ATTLIST_DECL) == 0) {
- DefineComponent dc = new DefineComponent(attlistDeclName(nameSpec.getValue()), new EmptyPattern());
- dc.setCombine(Combine.INTERLEAVE);
- addComponent(dc);
- }
- if (anyName != null && options.strictAny) {
- DefineComponent dc = new DefineComponent(anyName, ref(elementDeclName(nameSpec.getValue())));
- dc.setCombine(Combine.CHOICE);
- addComponent(dc);
- }
- }
- public void attlistDecl(NameSpec nameSpec, AttributeGroup attributeGroup) throws Exception {
- if (options.inlineAttlistDecls)
- return;
- String name = nameSpec.getValue();
- attributeNames
- = attributeNamesTable.get(name);
- if (attributeNames == null) {
- attributeNames = new HashSet<String>();
- attributeNamesTable.put(name, attributeNames);
- }
- Pattern pattern = convert(attributeGroup);
- if (pattern instanceof EmptyPattern) {
- // Only keep an empty definition if this is the first attlist for this element,
- // and all attlists are also empty. In this case, if we didn't keep the
- // definition, we would have no definition for the attlist.
- List<AttributeGroup> decls = attlistDeclTable.get(name);
- if (decls.get(0) != attributeGroup)
- return;
- attributeNames = new HashSet<String>();
- for (int i = 1, len = decls.size(); i < len; i++)
- if (!(convert(decls.get(i)) instanceof EmptyPattern))
- return;
- }
- DefineComponent dc = new DefineComponent(attlistDeclName(name), pattern);
- dc.setCombine(Combine.INTERLEAVE);
- addComponent(dc);
- }
- public void modelGroupDef(String name, ModelGroup modelGroup)
- throws Exception {
- addComponent(new DefineComponent(name, convert(modelGroup)));
- }
- public void attributeGroupDef(String name, AttributeGroup attributeGroup)
- throws Exception {
- // This takes care of duplicates within the group
- attributeNames = new HashSet<String>();
- Pattern pattern;
- AttributeGroupMember[] members = attributeGroup.getMembers();
- GroupPattern group = new GroupPattern();
- AttributeGroupVisitor agv = new AttributeGroupOutput(group);
- for (int i = 0; i < members.length; i++)
- members[i].accept(agv);
- switch (group.getChildren().size()) {
- case 0:
- pattern = new EmptyPattern();
- break;
- case 1:
- pattern = group.getChildren().get(0);
- break;
- default:
- pattern = group;
- break;
- }
- addComponent(new DefineComponent(name, pattern));
- }
- public void enumGroupDef(String name, EnumGroup enumGroup) throws Exception {
- ChoicePattern choice = new ChoicePattern();
- enumGroup.accept(new EnumGroupOutput(choice));
- Pattern pattern;
- switch (choice.getChildren().size()) {
- case 0:
- pattern = new NotAllowedPattern();
- break;
- case 1:
- pattern = choice.getChildren().get(0);
- break;
- default:
- pattern = choice;
- break;
- }
- addComponent(new DefineComponent(name, pattern));
- }
- public void datatypeDef(String name, Datatype datatype) throws Exception {
- addComponent(new DefineComponent(name, convert(datatype)));
- }
- public void comment(String value) {
- if (comments == null)
- comments = new Vector<Comment>();
- comments.add(new Comment(CommentTrimmer.trimComment(value)));
- }
- public void externalIdRef(String name, ExternalId externalId,
- String uri, String encoding, TopLevel[] contents)
- throws Exception {
- if (uri == null) {
- // I don't think this can happen
- super.externalIdRef(name, externalId, uri, encoding, contents);
- return;
- }
- SignificanceDetector sd = new SignificanceDetector();
- try {
- sd.externalIdRef(name, externalId, uri, encoding, contents);
- if (!sd.significant)
- return;
- }
- catch (Exception e) {
- throw (RuntimeException)e;
- }
- if (sc.getSchemaDocumentMap().get(uri) != null) {
- // I don't think this can happen because the second and subsequent inclusions
- // will never pass the SignificanceDetector, but just in case
- super.externalIdRef(name, externalId, uri, encoding, contents);
- return;
- }
- IncludeComponent ic = new IncludeComponent(uri);
- ic.setNs(defaultNamespace);
- addComponent(ic);
- GrammarPattern included = new GrammarPattern();
- ComponentOutput co = new ComponentOutput(included);
- for (int i = 0; i < contents.length; i++)
- contents[i].accept(co);
- co.finish();
- sc.getSchemaDocumentMap().put(uri, new SchemaDocument(included, encoding));
- }
- }
- private class AttributeGroupOutput implements AttributeGroupVisitor {
- final List<Pattern> group;
- AttributeGroupOutput(GroupPattern gp) {
- group = gp.getChildren();
- }
- public void attribute(NameSpec nameSpec,
- Datatype datatype,
- AttributeDefault attributeDefault) throws Exception {
- String name = nameSpec.getValue();
- if (attributeNames.contains(name))
- return;
- attributeNames.add(name);
- if (name.equals("xmlns") || name.startsWith("xmlns:"))
- return;
- String dv = attributeDefault.getDefaultValue();
- String fv = attributeDefault.getFixedValue();
- Pattern dt;
- if (fv != null) {
- String[] typeName = valueType(datatype);
- dt = new ValuePattern(typeName[0], typeName[1], fv);
- }
- else if (datatype.getType() != Datatype.CDATA)
- dt = convert(datatype);
- else
- dt = new TextPattern();
- AttributePattern pattern = new AttributePattern(convertQName(name, false), dt);
- if (dv != null) {
- AttributeAnnotation anno = new AttributeAnnotation(WellKnownNamespaces.RELAX_NG_COMPATIBILITY_ANNOTATIONS, "defaultValue", dv);
- anno.setPrefix(annotationPrefix);
- pattern.getAttributeAnnotations().add(anno);
- }
- if (!attributeDefault.isRequired())
- group.add(new OptionalPattern(pattern));
- else
- group.add(pattern);
- }
- public void attributeGroupRef(String name, AttributeGroup attributeGroup)
- throws Exception {
- DuplicateAttributeDetector detector = new DuplicateAttributeDetector();
- attributeGroup.accept(detector);
- if (detector.containsDuplicate)
- attributeGroup.accept(this);
- else {
- group.add(ref(name));
- attributeNames.addAll(detector.names);
- }
- }
- }
- private class DatatypeOutput implements DatatypeVisitor {
- Pattern pattern;
- public void cdataDatatype() {
- pattern = new DataPattern("", "string");
- }
- public void tokenizedDatatype(String typeName) {
- pattern = new DataPattern(WellKnownNamespaces.XML_SCHEMA_DATATYPES, typeName);
- }
- public void enumDatatype(EnumGroup enumGroup) throws Exception {
- if (enumGroup.getMembers().length == 0)
- pattern = new NotAllowedPattern();
- else {
- ChoicePattern tem = new ChoicePattern();
- pattern = tem;
- enumGroup.accept(new EnumGroupOutput(tem));
- }
- }
- public void notationDatatype(EnumGroup enumGroup) throws Exception {
- enumDatatype(enumGroup);
- }
- public void datatypeRef(String name, Datatype datatype) {
- pattern = ref(name);
- }
- }
- private class EnumGroupOutput implements EnumGroupVisitor {
- final private List<Pattern> list;
- EnumGroupOutput(ChoicePattern choice) {
- list = choice.getChildren();
- }
- public void enumValue(String value) {
- list.add(new ValuePattern("", "token", value));
- }
- public void enumGroupRef(String name, EnumGroup enumGroup) {
- list.add(ref(name));
- }
- }
- private class ModelGroupOutput implements ModelGroupVisitor {
- private Pattern pattern;
- public void choice(ModelGroup[] members) throws Exception {
- if (members.length == 0)
- pattern = new NotAllowedPattern();
- else if (members.length == 1)
- members[0].accept(this);
- else {
- ChoicePattern tem = new ChoicePattern();
- pattern = tem;
- List<Pattern> children = tem.getChildren();
- for (int i = 0; i < members.length; i++)
- children.add(convert(members[i]));
- }
- }
- public void sequence(ModelGroup[] members) throws Exception {
- if (members.length == 0)
- pattern = new EmptyPattern();
- else if (members.length == 1)
- members[0].accept(this);
- else {
- GroupPattern tem = new GroupPattern();
- pattern = tem;
- List<Pattern> children = tem.getChildren();
- for (int i = 0; i < members.length; i++)
- children.add(convert(members[i]));
- }
- }
- public void oneOrMore(ModelGroup member) throws Exception {
- pattern = new OneOrMorePattern(convert(member));
- }
- public void zeroOrMore(ModelGroup member) throws Exception {
- pattern = new ZeroOrMorePattern(convert(member));
- }
- public void optional(ModelGroup member) throws Exception {
- pattern = new OptionalPattern(convert(member));
- }
- public void modelGroupRef(String name, ModelGroup modelGroup) {
- pattern = ref(name);
- }
- public void elementRef(NameSpec name) {
- pattern = ref(elementDeclName(name.getValue()));
- }
- public void pcdata() {
- pattern = new TextPattern();
- }
- public void any() {
- pattern = ref(anyName);
- if (options.strictAny)
- pattern = new ZeroOrMorePattern(pattern);
- }
- }
- private class DuplicateAttributeDetector implements AttributeGroupVisitor {
- private boolean containsDuplicate = false;
- private final List<String> names = new Vector<String>();
- public void attribute(NameSpec nameSpec,
- Datatype datatype,
- AttributeDefault attributeDefault) {
- String name = nameSpec.getValue();
- if (attributeNames.contains(name))
- containsDuplicate = true;
- names.add(name);
- }
- public void attributeGroupRef(String name, AttributeGroup attributeGroup) throws Exception {
- attributeGroup.accept(this);
- }
- }
- private class SignificanceDetector extends VisitorBase {
- boolean significant = false;
- public void elementDecl(NameSpec nameSpec, ModelGroup modelGroup)
- throws Exception {
- significant = true;
- }
- public void attlistDecl(NameSpec nameSpec, AttributeGroup attributeGroup)
- throws Exception {
- significant = true;
- }
- public void modelGroupDef(String name, ModelGroup modelGroup)
- throws Exception {
- significant = true;
- }
- public void attributeGroupDef(String name, AttributeGroup attributeGroup)
- throws Exception {
- significant = true;
- }
- public void enumGroupDef(String name, EnumGroup enumGroup) {
- significant = true;
- }
- public void datatypeDef(String name, Datatype datatype) {
- significant = true;
- }
- }
- public BufferDtdConverter(Dtd dtd, ErrorReporter er, Options options) {
- this.dtd = dtd;
- this.er = er;
- this.options = options;
- }
- public SchemaCollection convert() {
- try {
- dtd.accept(new Analyzer());
- chooseNames();
- GrammarPattern grammar = new GrammarPattern();
- sc.setMainUri(dtd.getUri());
- sc.getSchemaDocumentMap().put(dtd.getUri(),
- new SchemaDocument(grammar, dtd.getEncoding()));
- ComponentOutput co = new ComponentOutput(grammar);
- dtd.accept(co);
- outputUndefinedElements(grammar.getComponents());
- if (options.generateStart)
- outputStart(grammar.getComponents());
- outputAny(grammar.getComponents());
- co.finish();
- return sc;
- }
- catch (Exception e) {
- throw (RuntimeException)e;
- }
- }
- private void chooseNames() {
- chooseAny();
- chooseColonReplacement();
- chooseDeclPatterns();
- choosePrefixes();
- chooseAnnotationPrefix();
- }
- private void chooseAny() {
- if (!hadAny)
- return;
- if (options.anyName != null) {
- if (!definedNames.contains(options.anyName)) {
- anyName = options.anyName;
- definedNames.add(anyName);
- return;
- }
- warning("cannot_use_any_name");
- }
- for (int n = 0;; n++) {
- for (int i = 0; i < ANY_KEYWORDS.length; i++) {
- anyName = repeatChar('_', n) + ANY_KEYWORDS[i];
- if (!definedNames.contains(anyName)) {
- definedNames.add(anyName);
- return;
- }
- }
- }
- }
- private void choosePrefixes() {
- if (options.defaultNamespace != null) {
- if (defaultNamespace != null && !defaultNamespace.equals(options.defaultNamespace))
- warning("default_namespace_conflict");
- defaultNamespace = options.defaultNamespace;
- }
- else if (defaultNamespace == null)
- defaultNamespace = NameClass.INHERIT_NS;
- for (Map.Entry<String, String> entry : options.prefixMap.entrySet()) {
- String prefix = entry.getKey();
- String ns = entry.getValue();
- String s = prefixTable.get(prefix);
- if (s == null)
- warning("irrelevant_prefix", prefix);
- else {
- if (!s.equals("") && !s.equals(ns))
- warning("prefix_conflict", prefix);
- prefixTable.put(prefix, ns);
- }
- }
- }
- private void chooseAnnotationPrefix() {
- if (!hadDefaultValue)
- return;
- if (options.annotationPrefix != null) {
- if (prefixTable.get(options.annotationPrefix) == null) {
- annotationPrefix = options.annotationPrefix;
- return;
- }
- warning("cannot_use_annotation_prefix");
- }
- for (int n = 0;; n++) {
- annotationPrefix = repeatChar('_', n) + "a";
- if (prefixTable.get(annotationPrefix) == null)
- return;
- }
- }
- private void chooseColonReplacement() {
- if (options.colonReplacement != null) {
- colonReplacement = options.colonReplacement;
- if (colonReplacementOk())
- return;
- warning("cannot_use_colon_replacement");
- colonReplacement = null;
- }
- if (colonReplacementOk())
- return;
- for (int n = 1;; n++) {
- for (int i = 0; i < SEPARATORS.length(); i++) {
- colonReplacement = repeatChar(SEPARATORS.charAt(i), n);
- if (colonReplacementOk())
- return;
- }
- }
- }
- private boolean colonReplacementOk() {
- Set<String> names = new HashSet<String>();
- for (String s : elementNameTable.keySet()) {
- String name = mungeQName(s);
- if (names.contains(name))
- return false;
- names.add(name);
- }
- return true;
- }
- private void chooseDeclPatterns() {
- if (options.elementDeclPattern != null) {
- if (patternOk(options.elementDeclPattern, null))
- elementDeclPattern = options.elementDeclPattern;
- else
- warning("cannot_use_element_decl_pattern");
- }
- if (options.attlistDeclPattern != null) {
- if (patternOk(options.attlistDeclPattern, elementDeclPattern))
- attlistDeclPattern = options.attlistDeclPattern;
- else
- warning("cannot_use_attlist_decl_pattern");
- }
- if (elementDeclPattern != null && attlistDeclPattern != null)
- return;
- // XXX Try to match length and case of best prefix
- String pattern = namingPattern();
- if (elementDeclPattern == null) {
- if (patternOk("%", attlistDeclPattern))
- elementDeclPattern = "%";
- else
- elementDeclPattern = choosePattern(pattern, ELEMENT_KEYWORDS, attlistDeclPattern);
- }
- if (attlistDeclPattern == null)
- attlistDeclPattern = choosePattern(pattern, ATTLIST_KEYWORDS, elementDeclPattern);
- }
- private String choosePattern(String metaPattern, String[] keywords, String otherPattern) {
- for (;;) {
- for (int i = 0; i < keywords.length; i++) {
- String pattern = substitute(metaPattern, '#', keywords[i]);
- if (patternOk(pattern, otherPattern))
- return pattern;
- }
- // add another separator
- metaPattern = (metaPattern.substring(0, 1)
- + metaPattern.substring(1, 2)
- + metaPattern.substring(1, 2)
- + metaPattern.substring(2));
- }
- }
- private String namingPattern() {
- Map<String, Integer> patternTable = new HashMap<String, Integer>();
- for (String name : definedNames) {
- for (int i = 0; i < SEPARATORS.length(); i++) {
- char sep = SEPARATORS.charAt(i);
- int k = name.indexOf(sep);
- if (k > 0)
- inc(patternTable, name.substring(0, k + 1) + "%");
- k = name.lastIndexOf(sep);
- if (k >= 0 && k < name.length() - 1)
- inc(patternTable, "%" + name.substring(k));
- }
- }
- String bestPattern = null;
- int bestCount = 0;
- for (Map.Entry<String, Integer> entry : patternTable.entrySet()) {
- int count = entry.getValue();
- if (bestPattern == null || count > bestCount) {
- bestCount = count;
- bestPattern = entry.getKey();
- }
- }
- if (bestPattern == null)
- return DEFAULT_PATTERN;
- if (bestPattern.charAt(0) == '%')
- return bestPattern.substring(0, 2) + "#";
- else
- return "#" + bestPattern.substring(bestPattern.length() - 2);
- }
- private static void inc(Map<String, Integer> table, String str) {
- Integer n = table.get(str);
- if (n == null)
- table.put(str, 1);
- else
- table.put(str, n + 1);
- }
- private boolean patternOk(String pattern, String otherPattern) {
- Set<String> usedNames = new HashSet<String>();
- for (String s : elementNameTable.keySet()) {
- String name = mungeQName(s);
- String declName = substitute(pattern, '%', name);
- if (definedNames.contains(declName))
- return false;
- if (otherPattern != null) {
- String otherDeclName = substitute(otherPattern, '%', name);
- if (usedNames.contains(declName)
- || usedNames.contains(otherDeclName)
- || declName.equals(otherDeclName))
- return false;
- usedNames.add(declName);
- usedNames.add(otherDeclName);
- }
- }
- return true;
- }
- private void noteDef(String name) {
- definedNames.add(name);
- }
- private void noteElementName(String name, int flags) {
- Integer n = elementNameTable.get(name);
- if (n != null) {
- flags |= n;
- if (n == flags)
- return;
- }
- else
- noteNamePrefix(name);
- elementNameTable.put(name, flags);
- }
- private void noteAttlist(String name, AttributeGroup group) {
- List<AttributeGroup> groups = attlistDeclTable.get(name);
- if (groups == null) {
- groups = new Vector<AttributeGroup>();
- attlistDeclTable.put(name, groups);
- }
- groups.add(group);
- }
- private void noteAttribute(String name, String defaultValue) {
- if (name.equals("xmlns")) {
- if (defaultValue != null) {
- if (defaultNamespace != null
- && !defaultNamespace.equals(defaultValue))
- error("INCONSISTENT_DEFAULT_NAMESPACE");
- else
- defaultNamespace = defaultValue;
- }
- }
- else if (name.startsWith("xmlns:")) {
- if (defaultValue != null) {
- String prefix = name.substring(6);
- String ns = prefixTable.get(prefix);
- if (ns != null
- && !ns.equals("")
- && !ns.equals(defaultValue))
- error("INCONSISTENT_PREFIX", prefix);
- else if (!prefix.equals("xml"))
- prefixTable.put(prefix, defaultValue);
- }
- }
- else {
- if (defaultValue != null)
- hadDefaultValue = true;
- noteNamePrefix(name);
- }
- }
- private void noteNamePrefix(String name) {
- int i = name.indexOf(':');
- if (i < 0)
- return;
- String prefix = name.substring(0, i);
- if (prefixTable.get(prefix) == null && !prefix.equals("xml"))
- prefixTable.put(prefix, "");
- }
- private int nameFlags(String name) {
- Integer n = elementNameTable.get(name);
- if (n == null)
- return 0;
- return n;
- }
- private String elementDeclName(String name) {
- return substitute(elementDeclPattern, '%', mungeQName(name));
- }
- private String attlistDeclName(String name) {
- return substitute(attlistDeclPattern, '%', mungeQName(name));
- }
- private String mungeQName(String name) {
- if (colonReplacement == null) {
- int i = name.indexOf(':');
- if (i < 0)
- return name;
- return name.substring(i + 1);
- }
- return substitute(name, ':', colonReplacement);
- }
- private static String repeatChar(char c, int n) {
- char[] buf = new char[n];
- for (int i = 0; i < n; i++)
- buf[i] = c;
- return new String(buf);
- }
- /* Replace the first occurrence of ch in pattern by value. */
- private static String substitute(String pattern, char ch, String value) {
- int i = pattern.indexOf(ch);
- if (i < 0)
- return pattern;
- StringBuffer buf = new StringBuffer();
- buf.append(pattern.substring(0, i));
- buf.append(value);
- buf.append(pattern.substring(i + 1));
- return buf.toString();
- }
- private void outputStart(List<Component> components) {
- ChoicePattern choice = new ChoicePattern();
- // Use the defined but unreferenced elements.
- // If there aren't any, use all defined elements.
- int mask = ELEMENT_REF|ELEMENT_DECL;
- for (;;) {
- boolean gotOne = false;
- for (Map.Entry<String, Integer> entry : elementNameTable.entrySet()) {
- if ((entry.getValue() & mask) == ELEMENT_DECL) {
- gotOne = true;
- choice.getChildren().add(ref(elementDeclName(entry.getKey())));
- }
- }
- if (gotOne)
- break;
- if (mask == ELEMENT_DECL)
- return;
- mask = ELEMENT_DECL;
- }
- components.add(new DefineComponent(DefineComponent.START, choice));
- }
- private void outputAny(List<Component> components) {
- if (!hadAny)
- return;
- if (options.strictAny) {
- DefineComponent dc = new DefineComponent(anyName, new TextPattern());
- dc.setCombine(Combine.CHOICE);
- components.add(dc);
- }
- else {
- // any = (element * { attribute * { text }*, any } | text)*
- CompositePattern group = new GroupPattern();
- group.getChildren().add(new ZeroOrMorePattern(new AttributePattern(new AnyNameNameClass(),
- new TextPattern())));
- group.getChildren().add(ref(anyName));
- CompositePattern choice = new ChoicePattern();
- choice.getChildren().add(new ElementPattern(new AnyNameNameClass(), group));
- choice.getChildren().add(new TextPattern());
- components.add(new DefineComponent(anyName, new ZeroOrMorePattern(choice)));
- }
- }
- private void outputUndefinedElements(List<Component> components) {
- List<String> elementNames = new Vector<String>();
- elementNames.addAll(elementNameTable.keySet());
- Collections.sort(elementNames);
- for (String elementName : elementNames) {
- if ((elementNameTable.get(elementName) & ELEMENT_DECL) == 0) {
- DefineComponent dc = new DefineComponent(elementDeclName(elementName), new NotAllowedPattern());
- dc.setCombine(Combine.CHOICE);
- components.add(dc);
- }
- }
- }
- static private Pattern ref(String name) {
- return new RefPattern(name);
- }
- private void error(String key) {
- er.error(key, null);
- }
- private void error(String key, String arg) {
- er.error(key, arg, null);
- }
- private void warning(String key) {
- er.warning(key, null);
- }
- private void warning(String key, String arg) {
- er.warning(key, arg, null);
- }
- private static String[] valueType(Datatype datatype) {
- datatype = datatype.deref();
- switch (datatype.getType()) {
- case Datatype.CDATA:
- return new String[] { "", "string" };
- case Datatype.TOKENIZED:
- return new String[] { WellKnownNamespaces.XML_SCHEMA_DATATYPES, ((TokenizedDatatype)datatype).getTypeName() };
- }
- return new String[] { "", "token" };
- }
- private Pattern convert(ModelGroup mg) throws Exception {
- ModelGroupOutput mgo = new ModelGroupOutput();
- mg.accept(mgo);
- return mgo.pattern;
- }
- private Pattern convert(Datatype dt) throws Exception {
- DatatypeOutput dto = new DatatypeOutput();
- dt.accept(dto);
- return dto.pattern;
- }
- private Pattern convert(AttributeGroup ag) throws Exception {
- GroupPattern group = new GroupPattern();
- ag.accept(new AttributeGroupOutput(group));
- switch (group.getChildren().size()) {
- case 0:
- return new EmptyPattern();
- case 1:
- return group.getChildren().get(0);
- }
- return group;
- }
- private NameClass convertQName(String name, boolean useDefault) {
- int i = name.indexOf(':');
- if (i < 0)
- return new NameNameClass(useDefault ? defaultNamespace : "", name);
- String prefix = name.substring(0, i);
- String localName = name.substring(i + 1);
- String ns;
- if (prefix.equals("xml"))
- ns = WellKnownNamespaces.XML;
- else {
- ns = prefixTable.get(prefix);
- if (ns.equals("")) {
- error("UNDECLARED_PREFIX", prefix);
- ns = "##" + prefix;
- prefixTable.put(prefix, ns);
- }
- }
- NameNameClass nnc = new NameNameClass(ns, localName);
- nnc.setPrefix(prefix);
- return nnc;
- }
- }