package com.thaiopensource.relaxng.pattern; import com.thaiopensource.xml.util.Name; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Base class for normalizing name classes. */ public abstract class AbstractNameClassNormalizer { private static final String IMPOSSIBLE = "\u0000"; protected abstract boolean contains(Name name); protected abstract void accept(NameClassVisitor visitor); public NormalizedNameClass normalize() { final List<Name> mentionedNames = new ArrayList<Name>(); final List<String> mentionedNamespaces = new ArrayList<String>(); accept(new NameClassVisitor() { public void visitChoice(NameClass nc1, NameClass nc2) { nc1.accept(this); nc2.accept(this); } public void visitNsName(String ns) { mentionedNamespaces.add(ns); } public void visitNsNameExcept(String ns, NameClass nc) { mentionedNamespaces.add(ns); nc.accept(this); } public void visitAnyName() { } public void visitAnyNameExcept(NameClass nc) { nc.accept(this); } public void visitName(Name name) { mentionedNames.add(name); } public void visitNull() { } public void visitError() { } }); if (contains(new Name(IMPOSSIBLE, IMPOSSIBLE))) { Set<Name> includedNames = new HashSet<Name>(); Set<String> excludedNamespaces = new HashSet<String>(); Set<Name> excludedNames = new HashSet<Name>(); for (String ns : mentionedNamespaces) { if (!contains(new Name(ns, IMPOSSIBLE))) excludedNamespaces.add(ns); } for (Name name : mentionedNames) { boolean in = contains(name); if (excludedNamespaces.contains(name.getNamespaceUri())) { if (in) includedNames.add(name); } else if (!in) excludedNames.add(name); } return new NormalizedAnyNameClass(includedNames, excludedNamespaces, excludedNames); } Map<String, HashSet<String>> nsMap = new HashMap<String, HashSet<String>>(); for (String ns : mentionedNamespaces) { if (contains(new Name(ns, IMPOSSIBLE)) && nsMap.get(ns) == null) nsMap.put(ns, new HashSet<String>()); } Set<Name> includedNames = new HashSet<Name>(); for (Name name : mentionedNames) { boolean in = contains(name); Set<String> excluded = nsMap.get(name.getNamespaceUri()); if (excluded == null) { if (in) includedNames.add(name); } else if (!in) excluded.add(name.getLocalName()); } return new NormalizedNsNameClass(includedNames, nsMap); } }