private void processDTD()

in src/com/intellij/idea/plugin/hybris/system/type/model/generator/DTDModelLoader.java [74:295]


    private void processDTD(final String namespace, final DTD dtd, final Map<String, TypeDesc> jtMap, final Map<String, NamespaceDesc> nsdMap) {
        final NamespaceDesc nsd = ensureNamespaceExists(namespace);
        if (nsd.skip) {
            return;
        }
        final ArrayList<String> resultQNames = new ArrayList<>();
        final DTDElement[] elements = new DTDElement[dtd.elements.size()];
        int ptr = 1;

        final HashSet<DTDElement> visitedElements = new HashSet<>();
        elements[0] = dtd.rootElement;

        while (--ptr > -1) {
            final DTDElement el = elements[ptr];
            visitedElements.add(el);
            final String typeName = model.toJavaTypeName(el.name, namespace);
            final String typeQName = model.toJavaQualifiedTypeName(namespace, typeName, false);
            if (resultQNames.contains(typeQName)) {
                continue;
            } else {
                resultQNames.add(typeQName);
            }
            final TypeDesc td = new TypeDesc(el.name, namespace, typeName, TypeDesc.TypeEnum.CLASS);
            boolean duplicates = false;
            if ((el.content instanceof DTDAny) || (el.content instanceof DTDMixed)) {
                final FieldDesc fd = new FieldDesc(FieldDesc.SIMPLE, "value", "String", null, "null", false);
                fd.realIndex = td.fdMap.size();
                td.fdMap.put(fd.name, fd);
            }
            for (Object o : el.attributes.keySet()) {
                final String attrName = (String) o;
                final DTDAttribute attr = (DTDAttribute) el.attributes.get(attrName);
                if (attr.decl == DTDDecl.FIXED || "ID".equals(attr.type)) {
                    continue;
                }
                final boolean required = attr.decl == DTDDecl.REQUIRED;
                final FieldDesc fd1 = new FieldDesc(
                    FieldDesc.ATTR,
                    Util.toJavaFieldName(attrName),
                    "String",
                    null,
                    "\"\"",
                    required
                );
                fd1.tagName = attrName;
                fd1.documentation = "Attribute " + attrName + "";
                fd1.realIndex = td.fdMap.size();
                duplicates = Util.addToNameMap(td.fdMap, fd1, false) || duplicates;
            }
            final ArrayList<List<DTDItem>> choiceList = new ArrayList<>();
            final LinkedList<Entry> plist = new LinkedList<>();
            if (el.content instanceof DTDContainer) {
                //if ((el.content instanceof DTDChoice) || (el.content instanceof DTDSequence)) {
                plist.add(new Entry(el.content, false, true));
            }
            while (!plist.isEmpty()) {
                final Entry pentry = plist.removeFirst();

                final DTDItem p = pentry.p;

                if (p instanceof final DTDName n) {
                    final DTDElement nel = (DTDElement) dtd.elements.get(n.value);
                    final String pName = n.value;
                    final FieldDesc fd1 = new FieldDesc(
                        FieldDesc.STR,
                        Util.toJavaFieldName(pName),
                        pName,
                        null,
                        "null",
                        pentry.required && (n.cardinal == DTDCardinal.ONEMANY || n.cardinal == DTDCardinal.NONE)
                    );
                    fd1.tagName = pName;
                    if (nel != null) {
                        fd1.documentation = parseDTDItemDocumentation(dtd, nel, "Type " + nel.name + " documentation");
                    }
                    if (nel == null) {
                        fd1.type = model.toJavaTypeName(fd1.tagName, namespace);
                    } else if (nel.content instanceof DTDEmpty || nel.content instanceof DTDAny) {
                        boolean hasAttrFields = false;
                        final boolean hasTextContents = nel.content instanceof DTDAny;
                        for (Object o : nel.attributes.values()) {
                            final DTDAttribute attr = (DTDAttribute) o;
                            if (attr.decl != DTDDecl.FIXED && !"ID".equals(attr.type)) {
                                hasAttrFields = true;
                                break;
                            }
                        }
                        if (hasAttrFields || hasTextContents) {
                            fd1.clType = FieldDesc.OBJ;
                            fd1.type = model.toJavaTypeName(fd1.tagName, namespace);
                            fd1.contentQualifiedName = model.toJavaQualifiedTypeName(namespace, fd1.name, false);
                            fd1.def = "null";
                            // next type
                            if (!visitedElements.contains(nel)) {
                                elements[ptr++] = nel;
                            }
                        } else {
                            fd1.clType = FieldDesc.BOOL;
                            fd1.type = "boolean";
                            fd1.def = "false";
                        }
                    } else if (nel.content instanceof DTDContainer) {
                        boolean hasAttrFields = false;
                        boolean hasTextField = false;
                        if ((nel.content instanceof DTDMixed) && ((DTDMixed) nel.content).getItemsVec().size() == 1) {
                            hasTextField = true;
                            for (Object o : nel.attributes.values()) {
                                final DTDAttribute attr = (DTDAttribute) o;
                                if (attr.decl != DTDDecl.FIXED && !"ID".equals(attr.type)) {
                                    hasAttrFields = true;
                                    break;
                                }
                            }
                        }
                        if (hasTextField && !hasAttrFields) {
                            fd1.clType = FieldDesc.STR;
                            fd1.type = "String";
                            fd1.def = "null";
                        } else {
                            fd1.clType = FieldDesc.OBJ;
                            fd1.type = model.toJavaTypeName(fd1.tagName, namespace);
                            fd1.contentQualifiedName = model.toJavaQualifiedTypeName(namespace, fd1.tagName, false);
                            // next type
                            if (!visitedElements.contains(nel)) {
                                elements[ptr++] = nel;
                            }
                        }
                    } else {
                        fd1.type = "ERROR:Name";
                    }
                    if ((pentry.many || n.cardinal.type >= 2) && fd1.clType != FieldDesc.BOOL) {
                        fd1.elementType = fd1.type;
                        fd1.elementName = fd1.name;
                        fd1.type = "List<" + fd1.elementType + '>';
                        fd1.name = Util.pluralize(fd1.name);
                        fd1.def = "new ArrayList(0)";
                        fd1.clType = -fd1.clType;
                        fd1.comment = "array of " + fd1.elementType;
                    }
                    fd1.realIndex = td.fdMap.size();
                    duplicates = Util.addToNameMap(td.fdMap, fd1, false) || duplicates;
                } else if (p instanceof final DTDContainer cont) {
                    final boolean isChoice = cont instanceof DTDChoice;
                    // 0 - NONE, 1 - OPT, 2 - ZEROMANY, 3 - ONEMANY
                    final boolean required = !isChoice && pentry.required && p.cardinal != DTDCardinal.ZEROMANY && p.cardinal != DTDCardinal.OPTIONAL;
                    final boolean many = p.cardinal == DTDCardinal.ONEMANY || p.cardinal == DTDCardinal.ZEROMANY;
                    final List<DTDItem> l = cont.getItemsVec();
                    if (!many && isChoice) {
                        choiceList.add(l);
                    }
                    for (DTDItem aL : l) {
                        plist.add(new Entry(aL, many, required));
                    }
                } else {
                    Util.logerr("unknown item " + p);
                }
            }
            td.duplicates = duplicates;
            td.documentation = parseDTDItemDocumentation(dtd, el, "Type " + el.name + " documentation");
            jtMap.put(model.toJavaQualifiedTypeName(namespace, td.name, false), td);
            int i = 0;
            for (FieldDesc fd : td.fdMap.values()) {
                fd.idx = i++;
            }
            for (List<DTDItem> l : choiceList) {
                final ArrayList<DTDItem> clist = new ArrayList<>();
                final LinkedList<DTDItem> elist = new LinkedList<>();
                for (i = 0; i < l.size(); i++) {
                    elist.add(l.get(i));
                }
                while (!elist.isEmpty()) {
                    final DTDItem p = elist.removeFirst();
                    if (p instanceof DTDContainer) {
                        final List<DTDItem> l2 = ((DTDContainer) p).getItemsVec();
                        for (DTDItem aL2 : l2) {
                            elist.addFirst(aL2);
                        }
                    } else if (p instanceof DTDName) {
                        clist.add(p);
                    }
                }
                boolean choiceOpt = true;
                final FieldDesc[] choice = new FieldDesc[clist.size()];
                for (i = 0; i < choice.length; i++) {
                    final DTDName p = (DTDName) clist.get(i);
                    final String s = Util.toJavaFieldName(p.value);
                    FieldDesc fd = td.fdMap.get(s);
                    if (fd == null) {
                        fd = td.fdMap.get(Util.pluralize(s));
                        if (fd == null) {
                            Util.logerr("uknown choice element: " + s);
                            continue;
                        }
                    }
                    choice[i] = fd;
                    choice[i].choice = choice;
                    if (fd.required) {
                        choiceOpt = false;
                    }
                }
                for (i = 0; i < choice.length; i++) {
                    choice[i].choiceOpt = choiceOpt;
                }
            }
        }
        final List<DTDEntity> entList = dtd.getItemsByType(DTDEntity.class);
        for (DTDEntity entity : entList) {
            final String value = entity.value;
            if (!value.startsWith("(") || !value.endsWith(")")) {
                continue;
            }
            final String typeName = model.toJavaTypeName(entity.name, namespace);
            final TypeDesc td = new TypeDesc(entity.name, namespace, typeName, TypeDesc.TypeEnum.ENUM);
            final StringTokenizer st = new StringTokenizer(value, "(|)");
            while (st.hasMoreTokens()) {
                final String s = st.nextToken();
                td.fdMap.put(s, new FieldDesc(Util.computeEnumConstantName(s, td.name), s));
            }
            td.documentation = parseDTDItemDocumentation(dtd, entity, "Type " + entity.name + " documentation");
            jtMap.put(model.toJavaQualifiedTypeName(namespace, td.name, true), td);
        }
    }