public void genXMLIO()

in ide/schema2beans/src/org/netbeans/modules/schema2beansdev/JavaBeanClass.java [1282:2219]


    public void genXMLIO() throws IOException {
        select(BODY_SECTION);
        String beanName = beanElement.node.getName();
        if (beanElement.isRoot) {
            if (!config.isStandalone()) {
                jw.beginMethod("write", "org.openide.filesystems.FileObject fo",
                               "java.io.IOException", "void", jw.PUBLIC | jw.IO);
                jw.writeEol("org.openide.filesystems.FileLock lock = fo.lock()");
                jw.beginTry();
                jw.writeEol("java.io.OutputStream out = fo.getOutputStream(lock)");
                jw.writeEol("write(out)");
                jw.writeEol("out.close()");
                jw.endFinallyBegin();
                jw.writeEol("lock.releaseLock()");
                jw.end();
                jw.endMethod();

                jw.beginMethod("write", "final org.openide.filesystems.FileObject dir, final String filename",
                               "java.io.IOException", "void", jw.PUBLIC | jw.IO);
                jw.writeEol("org.openide.filesystems.FileSystem fs = dir.getFileSystem()");                
                jw.write("fs.runAtomicAction(new org.openide.filesystems.FileSystem.AtomicAction()\n");
                jw.begin();
                jw.write("public void run() throws java.io.IOException {\n");
                jw.writeEol("org.openide.filesystems.FileObject file = dir.getFileObject(filename)");
                jw.beginIf("file == null");
                jw.writeEol("file = dir.createData(filename)");
                jw.end();
                jw.writeEol("write(file)");
                jw.end();
                jw.end();
                jw.writeEol(")");
                jw.endMethod();
            }

            jw.beginMethod("write", "java.io.File f",
                           "java.io.IOException", "void", jw.PUBLIC | jw.IO);
            jw.writeEol("java.io.OutputStream out = new java.io.FileOutputStream(f)");
            jw.beginTry();
            jw.writeEol("write(out)");
            jw.endFinallyBegin();
            jw.writeEol("out.close()");
            jw.end();
            jw.endMethod();

            jw.beginMethod("write", "java.io.OutputStream out",
                           "java.io.IOException", "void", jw.PUBLIC | jw.IO);
            geneol("write(out, null)");
            jw.endMethod();

            jw.beginMethod("write", "java.io.OutputStream out, String encoding",
                           "java.io.IOException", "void", jw.PUBLIC | jw.IO);
            geneol("java.io.Writer w");
            jw.beginIf("encoding == null");
            gen("encoding = \"UTF-8\"");
            eolNoI18N();
            end();
            gen("w = new java.io.BufferedWriter(new java.io.OutputStreamWriter(out, encoding))");
            eol();
            geneol("write(w, encoding)");
            geneol("w.flush()");
            jw.endMethod();

            jw.bigComment("Print this Java Bean to @param out including an XML header.\n@param encoding is the encoding style that @param out was opened with.");
            jw.beginMethod("write", "java.io.Writer out, String encoding",
                           "java.io.IOException", "void", jw.PUBLIC | jw.IO);
            gen("out.write(\"<?xml version='1.0'\")");
            eolNoI18N();
            gen("if (encoding != null)");
            cr();
            tabIn();
            gen("out.write(\" encoding='\"+encoding+\"'\")");
            eolNoI18N();
            gen("out.write(\" ?>\\n\")");
            eolNoI18N();
            if (config.isProcessDocType()) {
                jw.beginIf("docType != null");
                jw.writeEol("out.write(docType.toString())");
                jw.writeEol("out.write(\"\\n\")");
                jw.end();
            }
            jw.write("writeNode(out, \"", beanName, "\", \"\")");
            eolNoI18N();
            jw.endMethod();
        }

        jw.beginMethod("writeNode", "java.io.Writer out",
                       "java.io.IOException", "void", jw.PUBLIC | jw.IO);
        jw.writeEol("String myName");
        if (config.isGenerateParentRefs())
            jw.beginIf("parent == null");
        jw.writeEol("myName = \"", beanName, "\"");
        if (config.isGenerateParentRefs()) {
            jw.endElseBegin();
            jw.writeEol("myName = parent.nameChild(this, false, true)");
            jw.beginIf("myName == null");
            jw.writeEol("myName = \"", beanName, "\"");
            jw.end();
            jw.end();
        }
        jw.write("writeNode(out, myName, \"\")");
        eolNoI18N();
        jw.endMethod();

        jw.beginMethod("writeNode",
                       "java.io.Writer out, String nodeName, String indent",
                       "java.io.IOException", "void", jw.PUBLIC | jw.IO);
        jw.write("writeNode(out, nodeName, null, indent, new java.util.HashMap");
        if (config.jdkTarget >= 150)
            jw.write("<String, String>");
        jw.writeEol("())");
        jw.endMethod();

        jw.bigComment("It's not recommended to call this method directly.");
        String writeNodeArgs = "java.io.Writer out, String nodeName, String namespace, String indent, java.util.Map";
        if (config.jdkTarget >= 150)
            writeNodeArgs += "<String, String>";
        writeNodeArgs += " namespaceMap";
        jw.beginMethod("writeNode", writeNodeArgs,
                       "java.io.IOException", "void", jw.PUBLIC | jw.IO | jw.UNSUPPORTED);
        int size = attrList.size();
        Map namespaceToPrefixTable = new HashMap();
        geneol("out.write(indent)");
        outWrite("<");
        jw.beginIf("namespace != null");
        jw.writeEol("out.write((String)namespaceMap.get(namespace))");
        outWrite(":");
        jw.end();
        geneol("out.write(nodeName)");
        if (beanElement.isRoot && getDefaultNamespace() != null) {
            jw.writeEolNoI18N("out.write(\" xmlns='\")");
            jw.writeEolNoI18N("out.write("+JavaUtil.instanceFrom("java.lang.String", getDefaultNamespace())+")");
            jw.writeEolNoI18N("out.write(\"'\")");
        }
        if (beanElement.isRoot) {
            jw.beginIf("schemaLocation != null");
            jw.writeEol("namespaceMap.put(\"http://www.w3.org/2001/XMLSchema-instance\", \"xsi\")");
            namespaceToPrefixTable.put("http://www.w3.org/2001/XMLSchema-instance",
                                       "xsi");
            jw.writeEol("out.write(\" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='\")");
            jw.writeEol("out.write(schemaLocation)");
            jw.writeEolNoI18N("out.write(\"'\")");
            jw.end();
        }

        // Deal with namespaces
        boolean firstNS = true;
        for (int i = 0; i < size; i++) {
            Property a = (Property) attrList.get(i);
            boolean indexed = a.isIndexed();
            String attr = "_" + a.name;
            String type = a.getType().intern();
            String baseType = type;
            if (indexed)
                type = (baseType + "[]").intern();
            if (isTypeQName(baseType)) {
                if (firstNS) {
                    firstNS = false;
                    jw.comment("Work out any namespaces.");
                    jw.writeEol("boolean firstNSAddition = true");
                }
                if (indexed) {
                    beginAttrIterator(attr, a, "element");
                    attr = "element";
                }
                jw.beginIf(attr+" != null && "+
                           attr+".getNamespaceURI() != null && !\"\".equals(",
                           attr, ".getNamespaceURI())");
                jw.writeEol("String prefix = (String) namespaceMap.get(", attr, ".getNamespaceURI())");
                jw.beginIf("prefix == null || \"\".equals(prefix)");
                jw.writeEol("prefix = ", attr, ".getPrefix()");
                jw.beginIf("prefix == null || \"\".equals(prefix)");
                jw.writeEol("prefix = \"", a.dtdName, "_ns__\"");
                jw.end();
                jw.comment("Need to make sure it's a unique prefix too.");
                jw.writeEol("boolean changed");
                jw.write("do ");
                jw.begin();
                jw.writeEol("changed = false");
                jw.beginFor("java.util.Iterator valueIt = namespaceMap.values().iterator()",
                            "valueIt.hasNext()", "");
                jw.writeEol("String otherPrefix = (String) valueIt.next()");
                jw.beginIf("prefix.equals(otherPrefix)");
                jw.writeEol("prefix += \"_\"");
                jw.writeEol("changed = true");
                jw.end();
                jw.end();
                jw.end(false);
                jw.writeEol(" while (changed)");
                jw.beginIf("firstNSAddition");
                jw.writeEol("firstNSAddition = false");
                jw.comment("Copy on write");
                jw.writeEol("namespaceMap = new java.util.HashMap(namespaceMap)");
                jw.end();
                jw.writeEol("namespaceMap.put(", attr,
                            ".getNamespaceURI(), prefix)");
                jw.writeEol("out.write(\" xmlns:\")");
                jw.writeEol("out.write(prefix)");
                jw.writeEol("out.write(\"='\")");
                jw.writeEol("out.write(", attr, ".getNamespaceURI())");
                jw.writeEol("out.write(\"'\")");
                jw.end();
                jw.end();
                if (indexed)
                    jw.end();
            } else if (a.getNamespace() != null && !a.getNamespace().equals(getDefaultNamespace()) && !a.getNamespace().equals("http://www.w3.org/XML/1998/namespace")) {
                if (namespaceToPrefixTable.containsKey(a.getNamespace()))
                    continue;
                if (firstNS) {
                    firstNS = false;
                    jw.comment("Work out any namespaces.");
                    jw.writeEol("boolean firstNSAddition = true");
                }
                String prefix;
                prefix = SchemaRep.prefixOf(a.dtdName);
                if (prefix == null) {
                    prefix = prefixGuesser.guessPrefixFromURI(a.getNamespace());
                    //config.messageOut.println("Guessing prefix for "+a.getNamespace()+" is "+prefix);
                }
                jw.beginIf("namespaceMap.get(",
                           JavaUtil.instanceFrom("String",
                                                 a.getNamespace()),
                           ") == null");
                jw.beginIf("firstNSAddition");
                jw.writeEol("firstNSAddition = false");
                jw.comment("Copy on write");
                jw.write("namespaceMap = new java.util.HashMap");
                if (config.jdkTarget >= 150)
                    jw.write("<String, String>");
                jw.writeEol("(namespaceMap)");
                jw.end();
                jw.writeEol("namespaceMap.put(",
                            JavaUtil.instanceFrom("String",
                                                  a.getNamespace()),
                            ", \"", prefix+"\")");
                outWrite(" xmlns:"+prefix+"='");
                outWrite(a.getNamespace());
                outWrite("'");
                jw.end();
                namespaceToPrefixTable.put(a.getNamespace(), prefix);
            }
        }
        List directAttributes = new LinkedList();       // List<Property>
        List nonDirectAttributes = new LinkedList();	// List<Property>
        boolean hasSubElements = false;
        if (size > 0) {
            // Go over the attributes
            for (int i = 0; i < size; i++) {
                Property a = (Property) attrList.get(i);
                if (!a.isAttribute()) {
                    hasSubElements = true;
                    continue;
                }
                if (!a.isDirectChild()) {
                    nonDirectAttributes.add(a);
                    continue;
                }
                directAttributes.add(a);
            }
        }
        jw.writeEol("writeNodeAttributes(out, nodeName, namespace, indent, namespaceMap)");

        if (hasSubElements) {
            geneol("out.write(\">\\n\")");
        } else {
        }                
            
        jw.writeEol("writeNodeChildren(out, nodeName, namespace, indent, namespaceMap)");
        if (hasSubElements) {
            geneol("out.write(indent)");
            outWrite("</");
            jw.beginIf("namespace != null");
            jw.writeEol("out.write((String)namespaceMap.get(namespace))");
            outWrite(":");
            jw.end();
            jw.writeEol("out.write(nodeName)");
            outWrite(">\n");
        } else {
            geneol("out.write(\"/>\\n\")");
        }
        jw.endMethod();  // writeNode
        
        jw.beginMethod("writeNodeAttributes", writeNodeArgs,
                       "java.io.IOException", "void", jw.PROTECTED | jw.IO | jw.UNSUPPORTED);
        for (Iterator it = directAttributes.iterator(); it.hasNext(); ) {
            Property prop = (Property) it.next();
            genWriteAttr(prop);
        }
        if (config.isRespectExtension() && beanElement.getExtension() != null) {
            comment("extension is: "+beanElement.getExtension());
            jw.writeEol("super.writeNodeAttributes(out, nodeName, namespace, indent, namespaceMap)");
        }
        jw.endMethod();
        
        /*
        String writeNodeArgs = "java.io.Writer out, String nodeName, String namespace, String indent, java.util.Map";
        if (config.jdkTarget >= 150)
            writeNodeArgs += "<String, String>";
        writeNodeArgs += " namespaceMap";
         */
        jw.beginMethod("writeNodeChildren", writeNodeArgs,
                       "java.io.IOException", "void", jw.PROTECTED | jw.IO | jw.UNSUPPORTED);
        if (config.isRespectExtension() && beanElement.getExtension() != null) {
            jw.writeEol("super.writeNodeChildren(out, nodeName, namespace, indent, namespaceMap)");
        }
        if (hasSubElements) {
            geneol("String nextIndent = indent + \""+jw.getIndent()+"\"");
            if (config.isKeepElementPositions()) {
                jw.beginFor("int position = 0, count = fetchChildCount()",
                            "position < count", "++position");
                jw.writeEol("java.lang.Object child = elementsByPosition[position]");
                jw.writeEol("int elementType = elementTypesByPosition[position]");
                jw.write("switch (elementType) ");
                jw.begin();
            }
            boolean firstUseOfIndex = true;
            for (int i = 0; i < size; i++) {
                Property a = (Property)attrList.get(i);
                if (a.isAttribute())
                    continue;
                boolean indexed = a.isIndexed();
                String attr = "_" + a.name;
                String baseAttr = attr;
	    
                boolean isScalar = a.isScalar();
                boolean isNamespaceSignificant = (a.getNamespace() != null && !a.getNamespace().equals(getDefaultNamespace()) && !a.getNamespace().equals("http://www.w3.org/XML/1998/namespace"));

                String type = a.getType().intern();
                String baseType = type;
                if (indexed)
                    type = (baseType + "[]").intern();

                if (config.isKeepElementPositions()) {
                    jw.writecr("case "+i+":");
                    jw.indentRight();
                    jw.writeEol(baseType+" a"+a.name+" = "+JavaUtil.fromObject(baseType, "child"));
                    attr = "a"+a.name;
                } else {
                    if (indexed) {
                        if (!a.isBean && a.attributes != null && a.attributes.length > 0) {
                            if (firstUseOfIndex) {
                                firstUseOfIndex = false;
                                jw.writeEol("int index = 0");
                            } else {
                                jw.writeEol("index = 0");
                            }
                        }
                        beginAttrIterator(attr, a, "element");
                        attr = "element";
                    }
                    if (!isScalar) {
                        jw.beginIf(attr, " != null");
                    } else if (!indexed && config.isOptionalScalars() && isScalar) {
                        jw.beginIf(a.getScalarIsSet());
                    }
                }
                if (a.isBean) {
                    jw.write(attr, ".writeNode(out, \"", a.dtdName);
                    jw.write("\", ");
                    if (isNamespaceSignificant)
                        jw.write(JavaUtil.instanceFrom("String",
                                                       a.getNamespace()));
                    else
                        jw.write("null");
                    jw.writeEol(", nextIndent, namespaceMap)");
                } else if (a.type == Common.TYPE_COMMENT) {
                    jw.writeEol("out.write(nextIndent)");
                    jw.writeEol("out.write(\"<!--\")");
                    jw.writeEol("out.write(", attr, ")");
                    jw.writeEol("out.write(\"-->\\n\")");
                } else if ("org.w3c.dom.Element".equals(type)) {
                    jw.writeEol("out.write(nextIndent)");
                    if (config.isUseRuntime()) {
                        jw.writeEol("org.netbeans.modules.schema2beans.XMLUtil.DOMWriter domWriter = new org.netbeans.modules.schema2beans.XMLUtil.DOMWriter()");
                        jw.writeEol("domWriter.setWriter(out)");
                        jw.writeEol("domWriter.write(", attr, ")");
                    } else {
                        jw.writeEol("out.write(", attr, ".toString())");
                    }
                    outWrite("\n");
                } else {
                    boolean needEndTag = true;
                    if (baseType == "boolean" && a.getCanBeEmpty()) {
                        jw.beginIf(attr);
                        needEndTag = false;
                    }
                    if (!a.dtdName.equals("#PCDATA")) {
                        jw.writeEol("out.write(nextIndent)");
                        if (isNamespaceSignificant) {
                            outWrite("<");
                            jw.writeEol("out.write((String)namespaceMap.get(",
                                        JavaUtil.instanceFrom("String",
                                                              a.getNamespace()),
                                        "))");
                            jw.write("out.write(\":", a.dtdName, "\")");
                        } else {
                            jw.write("out.write(\"<", a.dtdName, "\")");
                        }
                        eolNoI18N();
                        if (isTypeQName(baseType)) {
                            jw.writeEol("String nsPrefix", attr, " = null");
                            jw.beginIf(attr+".getNamespaceURI() != null && !\"\".equals(",
                                        attr, ".getNamespaceURI())");
                            jw.write("nsPrefix", attr, " = (String) namespaceMap.get(");
                            jw.writeEol(attr, ".getNamespaceURI())");
                            jw.end();
                        }
                        for (int attrNum = 0; attrNum < a.attributes.length; ++attrNum) {
                            AttrProp myAttrProp = a.attributes[attrNum];
                            //jw.comment("myAttrProp="+myAttrProp);
                            for (Iterator it = nonDirectAttributes.iterator(); it.hasNext(); ) {
                                Property attrProperty = (Property) it.next();
                                AttrProp attrProp = attrProperty.getAttrProp();
                                if (myAttrProp == attrProp) {
                                    String varName;
                                    if (attrProperty.isIndexed()) {
                                        jw.beginIf("index < size"+attrProperty.name+"()");
                                        varName = attrProperty.getReadMethod(true)+"(index)";
                                    } else
                                        varName = "_"+attrProperty.name;
                                    genWriteAttr(attrProperty, varName);
                                    if (attrProperty.isIndexed()) {
                                        jw.end();
                                    }
                                }
                            }
                        }
                        if (needEndTag) {
                            gen("out.write(\">\")");
                            eolNoI18N();
                        }
                    }
                    if (!needEndTag) {
                        // no end tag, then no contents
                    } else {
                        genWriteType(a, attr, false);
                    }
                    if (!needEndTag) {
                        gen("out.write(\"/>\\n\")");
                        eolNoI18N();
                        end();
                    } else if (!a.dtdName.equals("#PCDATA")) {
                        if (isNamespaceSignificant) {
                            outWrite("</");
                            jw.writeEol("out.write((String)namespaceMap.get(",
                                        JavaUtil.instanceFrom("String",
                                                              a.getNamespace()),
                                        "))");
                            jw.write("out.write(\":", a.dtdName, ">\\n\")");
                        } else {
                            jw.write("out.write(\"</"+a.dtdName, ">\\n\")");
                        }
                        eolNoI18N();
                    }
                }
                if (config.isKeepElementPositions()) {
                    jw.writeEol("break");
                    jw.indentLeft();
                } else {
                    if (a.isNillable()) {
                        if (!isScalar) {
                            jw.endElseBegin();
                            jw.writeEol("out.write(nextIndent)");
                            jw.writeEol("out.write(\"<", a.dtdName, " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:nil='true'/>\\n\")");
                        }
                    }
                    if (!isScalar || (!indexed && config.isOptionalScalars() && isScalar))
                        end();
                    if (indexed) {
                        if (!a.isBean && a.attributes != null && a.attributes.length > 0) {
                            jw.writeEol("++index");
                        }
                        end();
                    }
                }
            }
            if (config.isKeepElementPositions()) {
                jw.end();
                jw.end();
            }
        }
        jw.endMethod(); // writeNodeChildren

        // Generate for reading
        if (beanElement.isRoot) {
            String exceps = "javax.xml.parsers.ParserConfigurationException, org.xml.sax.SAXException, java.io.IOException";
            if (config.isVetoable())
                exceps += ", java.beans.PropertyVetoException";

            if (!config.isStandalone()) {
                jw.beginMethod("read", "org.openide.filesystems.FileObject fo",
                               exceps, className, jw.PUBLIC | jw.STATIC | jw.IO);
                jw.writeEol("java.io.InputStream in = fo.getInputStream()");
                jw.beginTry();
                jw.writeEol("return read(in)");
                jw.endFinallyBegin();
                jw.writeEol("in.close()");
                jw.end();
                jw.endMethod();
            }

            jw.beginMethod("read", "java.io.File f",
                           exceps, className, jw.PUBLIC | jw.STATIC | jw.IO);
            jw.writeEol("java.io.InputStream in = new java.io.FileInputStream(f)");
            jw.beginTry();
            jw.writeEol("return read(in)");
            jw.endFinallyBegin();
            jw.writeEol("in.close()");
            jw.end();
            jw.endMethod();

            jw.beginMethod("read", "java.io.InputStream in", exceps, className,
                           jw.PUBLIC | jw.STATIC | jw.IO);
            geneol("return read(new org.xml.sax.InputSource(in), false, null, null)");
            end();
            cr();

            jw.bigComment("Warning: in readNoEntityResolver character and entity references will\nnot be read from any DTD in the XML source.\nHowever, this way is faster since no DTDs are looked up\n(possibly skipping network access) or parsed.");
            jw.beginMethod("readNoEntityResolver", "java.io.InputStream in",
                           exceps, className,
                           jw.PUBLIC | jw.STATIC | jw.IO);
            gencr("return read(new org.xml.sax.InputSource(in), false,");
            tabIn();
            gen("new org.xml.sax.EntityResolver() ");
            begin();
            gen("public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) ");
            begin();
            geneol("java.io.ByteArrayInputStream bin = new java.io.ByteArrayInputStream(new byte[0])");
            geneol("return new org.xml.sax.InputSource(bin)");
            end();
            end();
            tabIn();
            geneol(", null)");
            end();
            cr();

            jw.beginMethod("read",
                           "org.xml.sax.InputSource in, boolean validate, org.xml.sax.EntityResolver er, org.xml.sax.ErrorHandler eh",
                           exceps, className,
                           jw.PUBLIC | jw.STATIC | jw.IO);
            geneol("javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance()");
            geneol("dbf.setValidating(validate)");
            geneol("dbf.setNamespaceAware(true)");
            geneol("javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder()");
            gen("if (er != null)");
            tabIn();
            geneol("db.setEntityResolver(er)");
            gen("if (eh != null)");
            tabIn();
            geneol("db.setErrorHandler(eh)");
            geneol("org.w3c.dom.Document doc = db.parse(in)");
            geneol("return read(doc)");
            end();
            cr();

            exceps = null;
            if (config.isVetoable())
                exceps = "java.beans.PropertyVetoException";
            jw.beginMethod("read", "org.w3c.dom.Document document",
                           exceps, className, jw.PUBLIC | jw.STATIC | jw.IO);
            jw.writeEol(className, " a", className, " = new "+className+"()");
            jw.writeEol("a", className, ".readFromDocument(document)");
            jw.writeEol("return a", className);
            jw.endMethod();
            
            jw.beginMethod("readFromDocument", "org.w3c.dom.Document document",
                           exceps, "void", jw.PROTECTED);
            if (config.isProcessDocType()) {
                String fullDocTypeName;
                if (packageName == null)
                    fullDocTypeName = className+".DocType";
                else
                    fullDocTypeName = packageName+"."+className+".DocType";
                jw.writeEol("org.w3c.dom.NodeList children = document.getChildNodes()");
                jw.writeEol("int length = children.getLength()");
                jw.beginFor("int i = 0", "i < length", "++i");
                jw.beginIf("children.item(i) instanceof org.w3c.dom.DocumentType");
                jw.writeEol("docType = new "+fullDocTypeName+"((org.w3c.dom.DocumentType)children.item(i))");
                jw.writeEol("break");
                jw.end();
                jw.end();
            }
            geneol("readNode(document.getDocumentElement())");
            end();
            cr();
        }

        if (beanElement.isRoot) {
            jw.write("protected static class ReadState ");
            jw.begin();
            jw.writeEol("int lastElementType");
            jw.writeEol("int elementPosition");
            jw.end();
            jw.cr();
        }

        jw.beginMethod("readNode", "org.w3c.dom.Node node",
                       config.isVetoable() ? "java.beans.PropertyVetoException" : null,
                       "void", jw.PUBLIC | jw.IO);
        jw.write("readNode(node, new java.util.HashMap");
        if (config.jdkTarget >= 150)
            jw.write("<String, String>");
        jw.writeEol("())");
        jw.endMethod();

        String namespacePrefixesFormalParameter;
        if (config.jdkTarget >= 150)
            namespacePrefixesFormalParameter = "java.util.Map<String, String> namespacePrefixes";
        else
            namespacePrefixesFormalParameter = "java.util.Map namespacePrefixes";
        
        String readNodeArgs = "org.w3c.dom.Node node, "+namespacePrefixesFormalParameter;
        jw.beginMethod("readNode", readNodeArgs,
                       config.isVetoable() ? "java.beans.PropertyVetoException" : null,
                       "void", jw.PUBLIC | jw.IO);
        // Go over attributes
        beginAttrProcessing("node");
        jw.writeEol("boolean firstNamespaceDef = true");
        genUpdateNamespaces("namespacePrefixes", "firstNamespaceDef");
        
        int attrCount = 0;
        if (beanElement.isRoot) {
            ++attrCount;
            jw.writeEol("String xsiPrefix = \"xsi\"");
            jw.beginFor("java.util.Iterator it = namespacePrefixes.entrySet().iterator()",
                        "it.hasNext()", "");
            jw.writeEol("java.util.Map.Entry entry = (java.util.Map.Entry) it.next()");
            jw.writeEol("String prefix = (String) entry.getKey()");
            jw.writeEol("String ns = (String) entry.getValue()");
            jw.beginIf("\"http://www.w3.org/2001/XMLSchema-instance\".equals(ns)");
            jw.writeEol("xsiPrefix = prefix");
            jw.writeEol("break");
            jw.end();
            jw.end();
            genReadAttr("schemaLocation", "String",
                        "\"+xsiPrefix+\":schemaLocation",
                        "node", null, false, null, false, null);
        }
        jw.writeEol("readNodeAttributes(node, namespacePrefixes, attrs)");
        jw.end();
        jw.writeEol("readNodeChildren(node, namespacePrefixes)");
        jw.endMethod();
        
        jw.beginMethod("readNodeAttributes", readNodeArgs+", org.w3c.dom.NamedNodeMap attrs",
                       config.isVetoable() ? "java.beans.PropertyVetoException" : null,
                       "void", jw.PROTECTED | jw.IO);
        if (config.isRespectExtension() && beanElement.getExtension() != null)
            jw.writeEol("super.readNodeAttributes(node, namespacePrefixes, attrs)");
        jw.writeEol("org.w3c.dom.Attr attr");
        jw.writeEol("java.lang.String attrValue");
        boolean hasNillableElement = false;
        for (int i = 0; i < size; i++) {
            Property a = (Property)attrList.get(i);
            if (a.isNillable())
                hasNillableElement = true;
            if (!a.isAttribute())
                continue;
            if (!a.isDirectChild())
                continue;
            ++attrCount;
            genReadAttr(a, "node");
        }
        jw.endMethod();
        
        jw.beginMethod("readNodeChildren", readNodeArgs,
                       config.isVetoable() ? "java.beans.PropertyVetoException" : null,
                       "void", jw.PROTECTED | jw.IO);
        if (hasSubElements) {
            // FIXME: Should deal with the situation where we get 2 "foo" elements
            //        and the schema only mentioned 1.
            Map dtdNames = new HashMap();
            boolean hasDuplicateDtdNames = config.isKeepElementPositions();
            boolean hasQNameType = false;
            boolean hasNonElementTypes = false;
            for (int i = 0; i < size; i++) {
                Property a = (Property)attrList.get(i);
                if (isTypeQName(a.getType()))
                    hasQNameType = true;
                if (a.type == Common.TYPE_COMMENT || a.dtdName.equals("#PCDATA")) {
                    hasNonElementTypes = true;
                    continue;
                }
                if (a.isAttribute())
                    continue;
                if (dtdNames.containsKey(a.dtdName)) {
                    //jw.comment(a.dtdName+" has duplicates");
                    hasDuplicateDtdNames = true;
                }
                dtdNames.put(a.dtdName, a);
            }
            geneol("org.w3c.dom.NodeList children = node.getChildNodes()");
            boolean hasReadState = false;
            if (hasDuplicateDtdNames || config.isKeepElementPositions()) {
                hasReadState = true;
                jw.writeEol(getRootClassName(), ".ReadState readState = new ",
                            getRootClassName(),".ReadState()");
            }
            if (hasDuplicateDtdNames)
                jw.writeEol("readState.lastElementType = -1");
            if (config.isKeepElementPositions()) {
                jw.writeEol("readState.elementPosition = 0");
                jw.writeEol("elementsByPosition = new java.lang.Object[children.getLength()]");
                jw.writeEol("elementTypesByPosition = new int[children.getLength()]");
            }
            jw.beginFor("int i = 0, size = children.getLength()",
                        "i < size", "++i");
            geneol("org.w3c.dom.Node childNode = children.item(i)");
            if (!hasNonElementTypes &&
                !(config.isRespectExtension() && beanElement.getExtension() != null)) {
                jw.beginIf("!(childNode instanceof org.w3c.dom.Element)");
                jw.writeEol("continue");
                jw.end();
            }
            geneol("String childNodeName = (childNode.getLocalName() == null ? childNode.getNodeName().intern() : childNode.getLocalName().intern())");
            geneol("String childNodeValue = \"\"");
            jw.beginIf("childNode.getFirstChild() != null");
            geneol("childNodeValue = childNode.getFirstChild().getNodeValue()");
            jw.end();
            jw.write("boolean recognized = readNodeChild(childNode, childNodeName, childNodeValue, namespacePrefixes");
            if (hasReadState)
                jw.write(", readState");
            jw.writeEol(")");
            jw.beginIf("!recognized");
            if (!config.isLogSuspicious()) {
                comment("Found extra unrecognized childNode");
            } else {
                jw.beginIf("childNode instanceof org.w3c.dom.Element");
                declareLogger();
                jw.writeEol("_logger.info(\"Found extra unrecognized childNode '\"+childNodeName+\"'\")");
                jw.end();
            }
            jw.end();
            jw.end();
            if (config.isKeepElementPositions()) {
                jw.beginFor("", "readState.elementPosition < elementTypesByPosition.length",
                            "++readState.elementPosition");
                jw.writeEol("elementTypesByPosition[readState.elementPosition] = "+elementTypeSetnull);
                jw.end();
            }
            jw.endMethod();

            jw.beginMethod("readNodeChild", "org.w3c.dom.Node childNode, String childNodeName, String childNodeValue, "+namespacePrefixesFormalParameter+(hasReadState ? ", "+getRootClassName()+".ReadState readState" : ""),
                           config.isVetoable() ? "java.beans.PropertyVetoException" : null,
                           "boolean", jw.PROTECTED | jw.IO);
           jw.comment("assert childNodeName == childNodeName.intern()");
           if (hasNillableElement || hasQNameType ||
                nonDirectAttributes.size() > 0)
                declareAttrsForRead("childNode");
            boolean first = true;
            Property anyProp = null; // Is this an any property?
            for (int i = 0; i < size; i++) {
                Property a = (Property)attrList.get(i);
                if (a.isAttribute())
                    continue;
                boolean   	indexed = a.isIndexed();
                String attr = "_" + a.name;
                String baseAttr = attr;
                boolean isScalar = a.isScalar();

                String type = a.getType().intern();
                String baseType = type;
                if (indexed)
                    type = (baseType + "[]").intern();

                if (baseType == "org.w3c.dom.Element") {
                    anyProp = a;
                    continue;
                }
                if (first) first = false; else gen("else ");
                jw.write("if (");
                if (hasDuplicateDtdNames && dtdNames.get(a.dtdName) != a) {
                    int alwaysBeforeElementType;
                    if (indexed) {
                        // Keep reading in elements into this slot, until
                        // there's another element that says to go on.
                        alwaysBeforeElementType = i + 1;
                    } else {
                        // Force it to goto the next slot.
                        alwaysBeforeElementType = i;
                    }
                    jw.write("readState.lastElementType < "+alwaysBeforeElementType,
                             " && ");
                }
                if (a.dtdName.equals("#PCDATA"))
                    jw.write("childNode instanceof org.w3c.dom.CharacterData");
                else if (a.type == Common.TYPE_COMMENT)
                    jw.write("childNode instanceof org.w3c.dom.Comment");
                else
                    jw.write("\""+a.dtdName+"\".equals(childNodeName)");
                jw.write(") ");
                begin();
                String var;
                if (a.isNillable()) {
                    jw.writeEol("org.w3c.dom.Attr nilAttr = (org.w3c.dom.Attr) attrs.getNamedItem(\"xsi:nil\")");
                    jw.beginIf("nilAttr == null || !\"true\".equals(nilAttr.getValue())");
                }
                if (indexed) {
                    var = "a"+a.name;
                    if (a.isBean) {
                        jw.write(baseType, " ");
                    } else {
                        geneol(baseType+" "+var);
                    }
                } else {
                    var = attr;
                }
                if (a.isBean) {
                    jw.write(var, " = ");
                    genNewDefault(a, true);
                    jw.eol();
                    if (config.isGeneratePropertyEvents()) {
                        geneol(var+"._setPropertyChangeSupport(eventListeners)");
                        if (config.isVetoable())
                            geneol(var+"._setVetoableChangeSupport(vetos)");
                    }
                    if (config.isGenerateParentRefs())
                        jw.writeEol(var+"._setParent(this)");
                }
                boolean generatedSet = true;
                if (a.isBean)
                    geneol(var+".readNode(childNode, namespacePrefixes)");
                else if (a.dtdName.equals("#PCDATA")) {
                    geneol(var+" = ((org.w3c.dom.CharacterData)childNode).getData()");
                } else if (a.type == Common.TYPE_COMMENT) {
                    geneol(var+" = ((org.w3c.dom.CharacterData)childNode).getData()");
                } else {
                    if (config.isTrimNonStrings() &&
                        baseType != "String" && baseType != "java.lang.String") {
                        jw.writeEol("childNodeValue = childNodeValue.trim()");
                    }
                    List exceps = JavaUtil.exceptionsFromParsingText(baseType);
                    if (!exceps.isEmpty()) {
                        jw.beginTry();
                    }
                    if (baseType == "boolean" || baseType == "java.lang.Boolean") {
                        gencr("if (childNode.getFirstChild() == null)");
                        tabIn();
                        if (baseType == "boolean")
                            geneol(var+" = true");
                        else
                            geneol(var+" = Boolean.TRUE");
                        gencr("else");
                        tabIn();
                    }
                    generatedSet = genReadType(baseType, var, "childNodeValue",
                                               false, null,
                                               isScalar,
                                               (SchemaRep.EncodingStyle) a.searchExtraData(SchemaRep.EncodingStyle.class));
                        SchemaRep.WhiteSpace ws = (SchemaRep.WhiteSpace) a.searchExtraData(SchemaRep.WhiteSpace.class);
                        if (ws != null)
                            genWhiteSpaceRestriction(ws, var, baseType);
                        //}
                    if (!indexed && config.isOptionalScalars() && isScalar) {
                        jw.writeEol(a.getScalarIsSet(), " = true");
                    }
                    int directAttrCount = 0;
                    for (int attrNum = 0; attrNum < a.attributes.length; ++attrNum) {
                        AttrProp myAttrProp = a.attributes[attrNum];
                        //jw.comment("myAttrProp="+myAttrProp);
                        for (Iterator it = nonDirectAttributes.iterator(); it.hasNext(); ) {
                            Property attrProperty = (Property) it.next();
                            AttrProp attrProp = attrProperty.getAttrProp();
                            if (myAttrProp == attrProp) {
                                ++directAttrCount;
                                genReadAttr(attrProperty, "childNode");
                            }
                        }
                    }
                
                    if (!exceps.isEmpty()) {
                        end();
                        genRethrowExceptions(exceps);
                    }
                }
                if (indexed && generatedSet)
                    jw.writeEol(attr, ".add(",
                                JavaUtil.toObject(var, baseType,
                                                  config.isForME(), config.isJava5()),
                                ")");
                if (a.isNillable()) {
                    jw.endElseBegin();
                    if (indexed)
                        jw.writeEol(attr, ".add(null)");
                    else
                        jw.writeEol(var, " = ", JavaUtil.nullValueForType(baseType));
                    jw.end();
                }
                if (hasDuplicateDtdNames)
                    jw.writeEol("readState.lastElementType = "+i);
                if (config.isKeepElementPositions()) {
                    jw.writeEol("elementsByPosition[readState.elementPosition] = "+JavaUtil.toObject(var, type, config.isForME(), config.isJava5()));
                    jw.writeEol("elementTypesByPosition[readState.elementPosition++] = "+i);
                }
                end();
            }
            if (anyProp != null) {
                String attr = "_" + anyProp.name;
                boolean	indexed = anyProp.isIndexed();
                if (first) first = false; else gen("else ");
                jw.beginIf("childNode instanceof org.w3c.dom.Element");
                if (indexed)
                    jw.writeEol(attr, ".add((org.w3c.dom.Element)childNode)");
                else
                    jw.writeEol(attr, " = (org.w3c.dom.Element) childNode");
                jw.end();
            }
            if (!first) {
                gen("else ");
                begin();
                if (config.isRespectExtension() && beanElement.getExtension() != null) {
                    jw.write("return super.readNodeChild(childNode, childNodeName, childNodeValue, namespacePrefixes");
                    if (hasReadState)
                        jw.write(", readState");
                    jw.writeEol(")");
                } else
                    jw.writeEol("return false");
                /*
                jw.writeEol("System.out.println(\"Found extra unrecognized childNode: \"+childNodeName)");
                jw.writeEol("System.out.println(\"namespaceURI=\"+childNode.getNamespaceURI())");
                jw.writeEol("System.out.println(\"prefix=\"+childNode.getPrefix())");
                jw.writeEol("System.out.println(\"localName=\"+childNode.getLocalName())");
                jw.writeEol("System.out.println(\"nodeName=\"+childNode.getNodeName())");
                */
                end();
            }
            jw.writeEol("return true");
        } else {
            if (config.isRespectExtension() && beanElement.getExtension() != null) {
                jw.writeEol("super.readNodeChildren(node, namespacePrefixes)");
            }
        }
        jw.endMethod();
        
        if (beanElement.isRoot) {
            if (!config.isUseRuntime())
                genPrintXML();
            genSpecialTypes();
        }
    }