indent = dealWithClosingGroupNodes(containedObj, outputstream, indent);
  public void toXMLOutputStream (                                   OutputStream outputstream,                                   Hashtable XMLDeclAttribs,                                   String indent,                                   boolean dontCloseNode,                                   String newNodeNameString,                                   String noChildObjectNodeName                                )  {    //while writing out, attribHash should not be changed    synchronized (attribHash) {      String nodeNameString = this.classXDFNodeName;      // Setup. Sometimes the name of the node we are opening is different from      // that specified in the classXDFNodeName (*sigh*)      if (newNodeNameString != null) nodeNameString = newNodeNameString;/*      // 0. To be valid XML, we always start an XML block with an      //    XML declaration (e.g. somehting like "<?xml standalone="no"?>").      //    Here we deal with  printing out XML Declaration && its attributes      if ((XMLDeclAttribs !=null) &&(!XMLDeclAttribs.isEmpty())) {        indent = "";        writeXMLDeclToOutputStream(outputstream, XMLDeclAttribs);      }*/      // 1. open this node, print its simple XML attributes      if (nodeNameString != null) {        if (Specification.getInstance().isPrettyXDFOutput())          writeOut(outputstream, indent); // indent node if desired        // For printing the opening statement we need to invoke a little        // Voodoo to keep the DTD happy: the first structure node is always        // called by the root node name instead of the usual nodeNameString        // We can tell this by checking if this object is derived from class        // Structure and if XMLDeclAttrib defined/populated with information        // NOTE: This isnt really the way to do this. We need to check if 'this' is        // is or has as a superclass xdf.Structure instead of the 'string check' below.        // check is class Strucuture & XMLDeclAttribs populated?/*        if ( nodeNameString.equals(Specification.getInstance().getXDFStructureNodeName())              && !XMLDeclAttribs.isEmpty() )          nodeNameString = Specification.getInstance().getXDFRootNodeName();*/        writeOut(outputstream,"<" + nodeNameString);   // print opening statement      }      // gather info about XMLAttributes in this object/node      Hashtable xmlInfo = getXMLInfo();      // 2. Print out string object XML attributes EXCEPT for the one that      //    matches PCDATAAttribute.      ArrayList attribs = (ArrayList) xmlInfo.get("attribList");      // is synchronized here correct?      synchronized(attribs) {        int size = attribs.size();        for (int i = 0; i < size; i++) {          Hashtable item = (Hashtable) attribs.get(i);          writeOut(outputstream, " " + item.get("name") + "=\"");          // this slows things down, should we use?          //writeOutAttribute(outputstream, (String) item.get("value"));          writeOut(outputstream, (String) item.get("value"));          writeOut(outputstream, "\"" );        }      }      // 3. Print out Node PCData or Child Nodes as specified by object ref      //    XML attributes. The way this stuff occurs will also affect how we      //    close the node.      ArrayList childObjs = (ArrayList) xmlInfo.get("childObjList");      String pcdata = (String) xmlInfo.get("PCDATA");     if ( childObjs.size() > 0 || pcdata != null || noChildObjectNodeName != null)      {        // close the opening tag        if (nodeNameString != null) {          writeOut(outputstream, ">");          if ((Specification.getInstance().isPrettyXDFOutput()) && (pcdata == null))             writeOut(outputstream, Constants.NEW_LINE);        }        // deal with object/list XML attributes, if any in our list        int size = childObjs.size();        for (int i = 0; i < size; i++) {          Hashtable item = (Hashtable) childObjs.get(i);          if (item.get("type") == Constants.LIST_TYPE)          {            List objectList = (List) item.get("value");            // Im not sure this synchronized wrapper is needed, we are            // only accessing stuff here.. Also, should synchronzied wrapper            // occur back in the getXMLInfo method instead where the orig            // access occured?!?            synchronized(objectList) {              Iterator iter = objectList.iterator(); // Must be in synchronized block              while (iter.hasNext()) {                BaseObject containedObj = (BaseObject) iter.next();                if (containedObj != null) { // can happen from pre-allocation of axis values, etc (?)                  indent = dealWithOpeningGroupNodes(containedObj, outputstream, indent);                  indent = dealWithClosingGroupNodes(containedObj, outputstream, indent);                  String newindent = indent + Specification.getInstance().getPrettyXDFOutputIndentation();                  containedObj.toXMLOutputStream(outputstream, new Hashtable(), newindent);                }              }            }          }          else if (item.get("type") == Constants.OBJECT_TYPE)          {            BaseObject containedObj = (BaseObject) item.get("value");            if (containedObj != null) { // can happen from pre-allocation of axis values, etc (?)              // shouldnt this be synchronized too??              synchronized(containedObj) {                indent = dealWithOpeningGroupNodes(containedObj, outputstream, indent);                indent = dealWithClosingGroupNodes(containedObj, outputstream, indent);                String newindent = indent + Specification.getInstance().getPrettyXDFOutputIndentation();                containedObj.toXMLOutputStream(outputstream, new Hashtable(), newindent);              }            }          } else {            // error: weird type, actually shouldnt occur. Is this needed??            Log.errorln("Weird error: unknown XML attribute type for item:"+item);          }        }        // print out PCDATA, if any        if(pcdata != null)  {          writeOut(outputstream, pcdata);        };        // if there are no PCDATA or child objects/nodes then        // we print out noChildObjectNodeName and close the node        if ( childObjs.size() == 0 && pcdata == null && noChildObjectNodeName != null)        {          if (Specification.getInstance().isPrettyXDFOutput())            writeOut(outputstream, indent + Specification.getInstance().getPrettyXDFOutputIndentation());          writeOut(outputstream, "<" + noChildObjectNodeName + "/>");          if (Specification.getInstance().isPrettyXDFOutput())            writeOut(outputstream, Constants.NEW_LINE);        }        // ok, now deal with closing the node        if (nodeNameString != null) {           indent = dealWithClosingGroupNodes((BaseObject) this, outputstream, indent);          if (Specification.getInstance().isPrettyXDFOutput() && pcdata == null)                writeOut(outputstream, indent);          if (!dontCloseNode)              writeOut(outputstream, "</"+nodeNameString+">");        }      } else {        if (nodeNameString != null) {	    if (dontCloseNode) {		// it may not have sub-objects, but we dont want to close it		// (happens for group objects)		writeOut(outputstream, ">");	    } else {		// no sub-objects, just close this node		writeOut(outputstream, "/>");	    }	}      }      if (Specification.getInstance().isPrettyXDFOutput()  && nodeNameString != null) 	  writeOut(outputstream, Constants.NEW_LINE);    }//synchronize  }