package com.dbgen; import org.w3c.dom.Element; import java.io.PrintStream; import java.util.*; import java.util.concurrent.ConcurrentHashMap; public abstract class Naming { static Map child2Parent = new ConcurrentHashMap<>(); public static class Root extends Naming { private final TreeMap symbols; private int counter = 0; public Root() { super(); symbols = new TreeMap<>(new Comparator() { @Override public int compare(String[] o1, String[] o2) { int l1 = o1.length; int l2 = o2.length; int c; while ((c = o1[--l1].compareTo(o2[--l2])) == 0 && l1 > 0 && l2 > 0) ; return c != 0 ? c : l1 - l2; } }); } public T search(String ref[], Class clazz) { T r = null; for (Map.Entry e : symbols.tailMap(ref).entrySet()) { String[] key = e.getKey(); int l1 = ref.length; int l2 = key.length; int c; while ((c = ref[--l1].compareTo(key[--l2])) == 0 && l1 > 0 && l2 > 0) ; if (c != 0 || l1 != 0) break; Naming n = e.getValue(); if (clazz.isInstance(n)) { if (r != null) { dump(System.err); throw new RuntimeException("Ambiguous symbol\n" + r + "\r------------------\n\n" + n); } r = clazz.cast(n); } } return r; } public Collection compile() { Set unresolved = new LinkedHashSet<>(); compile(unresolved); for (int target = 0; target != unresolved.size();) { target = unresolved.size(); List items = new ArrayList<>(unresolved); unresolved.clear(); items.forEach(i -> i.compile(unresolved)); } return unresolved; } } public final static Root typeRoot = new Root(); private static String prefix = "com.dbgen."; public static void setPrefix(String s) { prefix = s; } private final String name; private final String fullname[]; private Object att; private Naming parent; public String baseclass = ""; private Root root; private Set children = new LinkedHashSet<>(); public Naming() { this.parent = null; root = (Root) this; this.name = ""; this.fullname = new String[] { Integer.toHexString(root.counter++), "" }; } public Naming(Naming parent, String name) { this.parent = parent; this.root = parent.root; this.name = name; List list = new ArrayList<>(); for (Naming p = parent; p != null; p = p.parent) list.add(0, p.name); list.add(0, Integer.toHexString(root.counter++)); list.add(name); this.fullname = list.toArray(new String[0]); parent.children.stream().filter(i -> !name.isEmpty() && name.equals(i.name)).findAny().ifPresent(n -> { throw new RuntimeException("Duplicate name " + this); }); parent.children.add(this); root.symbols.put(this.fullname, this); } public Naming(Naming parent, Element self, String key) throws Exception { this(parent, self.getAttribute(key).trim()); String basebean = self.getAttribute("base"); if (basebean != null && !basebean.isEmpty()) { child2Parent.put(this, basebean); this.baseclass = basebean; } for (Element e : XMLUtils.getChildElements(self)) Class.forName(prefix + e.getNodeName()).getConstructor(getClass(), Element.class) .newInstance(this, e); } public Naming(Naming parent, Element self) throws Exception { this(parent, self, "name"); } public String getName() { return name; } T search(String ref[], Class clazz) { return root.search(ref, clazz); } final void compile(Set symbolList) { for (int target = 0; target != children.size();) { target = children.size(); for (Naming child : new ArrayList(children)) child.compile(symbolList); } } public final Set getChildren() { return children; } public final List getChildren(Class clazz) { return getChildren(clazz, false); } public final List getChildren(Class clazz, boolean ignorBaseBean) { List list = new ArrayList<>(); if (ignorBaseBean) { for (Naming child : children){ if ((!child.getParent().getName().equals(baseclass)) && clazz.isInstance(child)) list.add(clazz.cast(child)); } } else { for (Naming child : children) if (clazz.isInstance(child)) list.add(clazz.cast(child)); } return list; } public final T getChild(Class clazz, String name) { for (Naming child : children) if (clazz.isInstance(child) && child.name.equals(name)) return clazz.cast(child); return null; } private final void getDescendants(List list, Class clazz) { for (Naming child : children) { if (clazz.isInstance(child)) list.add(clazz.cast(child)); child.getDescendants(list, clazz); } } public final Naming getParent() { return parent; } public final Root getRoot() { return root; } private final void dump(PrintStream ps, String tab) { ps.println(tab + "[" + getClass().getSimpleName() + "]" + name + ""); for (Naming child : children) child.dump(ps, tab + "\t"); } public final void dump(PrintStream ps) { if (parent == null) for (Naming child : children) child.dump(ps, ""); else dump(ps, ""); } public Object attachment() { return this.att; } }