child = dont_AddRef(NS_STATIC_CAST (nsISchemaParticle*, all->ElementAt(i)));
nsAutoString name; rc = next->GetTagName(name); NS_ENSURE_SUCCESS(rc, rc);   groupParticles.Get(name, getter_AddRefs(child));  if (NS_FAILED(rc) || !child) { #ifdef DEBUG nsAutoString msg(NS_LITERAL_STRING("::DecodeStructParticle: ")); msg.AppendLiteral("Cannot find schema particle for \""); msg.Append(name); msg.AppendLiteral("\""); NS_ERROR(NS_ConvertUTF16toUTF8(msg).get()); #endif }
static nsresult DecodeStructParticle(nsISOAPEncoding* aEncoding, nsIDOMElement* aElement,                                nsISchemaParticle* aParticle,                                nsISOAPAttachments * aAttachments, nsISOAPPropertyBagMutator* aDestination,                               nsIDOMElement** _retElement){  nsresult rc;  *_retElement = nsnull;  if (aParticle) {    PRUint32 minOccurs;    rc = aParticle->GetMinOccurs(&minOccurs);    if (NS_FAILED(rc))      return rc;    PRUint32 maxOccurs;    rc = aParticle->GetMaxOccurs(&maxOccurs);    if (NS_FAILED(rc))      return rc;    PRUint16 particleType;    rc = aParticle->GetParticleType(&particleType);    if (NS_FAILED(rc))      return rc;    switch(particleType) {      case nsISchemaParticle::PARTICLE_TYPE_ELEMENT: {        if (maxOccurs > 1) {  //  Todo: Try to make this thing work as an array?          return NS_ERROR_NOT_AVAILABLE; //  For now, we just try something else if we can (recoverable)        }        nsCOMPtr<nsISchemaElement> element = do_QueryInterface(aParticle);        nsAutoString name;        rc = element->GetTargetNamespace(name);        if (NS_FAILED(rc))          return rc;        if (!name.IsEmpty()) {          rc = NS_ERROR_NOT_AVAILABLE; //  No known way to use namespace qualification in struct        }        else {          rc = element->GetName(name);          if (NS_FAILED(rc))            return rc;          nsAutoString ename;          if (aElement) {                //  Permits aElement to be null and fail recoverably            nsAutoString temp;            rc = aElement->GetNamespaceURI(ename);            if (NS_FAILED(rc))              return rc;            if (ename.IsEmpty()) {  //  Only get an ename if there is an empty namespaceURI              rc = aElement->GetLocalName(ename);              if (NS_FAILED(rc))                return rc;            }          }          if (!ename.Equals(name))            rc = NS_ERROR_NOT_AVAILABLE; //  The element must be a declaration of the next element        }        if (NS_SUCCEEDED(rc)) {          nsCOMPtr<nsISchemaType> type;          rc = element->GetType(getter_AddRefs(type));          if (NS_FAILED(rc))            return rc;          nsCOMPtr<nsIVariant> value;          rc = aEncoding->Decode(aElement, type, aAttachments, getter_AddRefs(value));          if (NS_FAILED(rc))            return rc;          if (!value) {            nsCOMPtr<nsIWritableVariant> nullVariant(do_CreateInstance("@mozilla.org/variant;1"));            if (nullVariant) {              nullVariant->SetAsISupports(nsnull);              value = do_QueryInterface(nullVariant);            }          }          rc = aDestination->AddProperty(name, value);          if (NS_FAILED(rc))            return rc;          nsSOAPUtils::GetNextSiblingElement(aElement, _retElement);        }        if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) { //  If we failed recoverably, but we were permitted to, then return success          *_retElement = aElement;          NS_IF_ADDREF(*_retElement);          rc = NS_OK;        }        return rc;      }      case nsISchemaParticle::PARTICLE_TYPE_MODEL_GROUP:       {        if (maxOccurs > 1) {  //  Todo: Try to make this thing work as an array?          return NS_ERROR_NOT_AVAILABLE; //  For now, we just try something else if we can (recoverable)        }        nsCOMPtr<nsISchemaModelGroup> modelGroup = do_QueryInterface(aParticle);        PRUint16 compositor;        rc = modelGroup->GetCompositor(&compositor);        if (NS_FAILED(rc))          return rc;        PRUint32 particleCount;        rc = modelGroup->GetParticleCount(&particleCount);        if (NS_FAILED(rc))          return rc;        PRUint32 i;        if (compositor == nsISchemaModelGroup::COMPOSITOR_ALL) {  //  This handles out-of-order appearances.          nsCOMPtr<nsISupportsArray> all = new nsSupportsArray(); //  Create something we can mutate          if (!all)            return NS_ERROR_OUT_OF_MEMORY;          all->SizeTo(particleCount);          nsCOMPtr<nsISchemaParticle> child;          PRBool mangled = PR_FALSE;          for (i = 0; i < particleCount; i++) {            rc = modelGroup->GetParticle(i, getter_AddRefs(child));            if (NS_FAILED(rc))              return rc;            rc = all->AppendElement(child);            if (NS_FAILED(rc))              return rc;          }          nsCOMPtr<nsIDOMElement> next = aElement;          while (particleCount > 0) {            for (i = 0; i < particleCount; i++) {              child = dont_AddRef(NS_STATIC_CAST                    (nsISchemaParticle*, all->ElementAt(i)));              nsCOMPtr<nsIDOMElement> after;              rc = DecodeStructParticle(aEncoding, next, child, aAttachments, aDestination, getter_AddRefs(after));              if (NS_SUCCEEDED(rc)) {                next = after;                mangled = PR_TRUE;                rc = all->RemoveElementAt(i);                particleCount--;                if (NS_FAILED(rc))                  return rc;                break;              }              if (rc != NS_ERROR_NOT_AVAILABLE) {                break;              }            }            if (mangled && rc == NS_ERROR_NOT_AVAILABLE) {  //  This detects ambiguous model (non-deterministic choice which fails after succeeding on first)              rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_AMBIGUOUS_DECODING","Cannot proceed due to ambiguity or error in content model");              //  Error is not considered recoverable due to partially-created output.            }            if (NS_FAILED(rc))              break;          }          if (NS_SUCCEEDED(rc)) {            *_retElement = next;            NS_IF_ADDREF(*_retElement);          }          if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) {  //  If we succeeded or failed recoverably, but we were permitted to, then return success            *_retElement = aElement;            NS_IF_ADDREF(*_retElement);            rc = NS_OK;          }        }        else {  //  This handles sequences and choices.          nsCOMPtr<nsIDOMElement> next = aElement;          for (i = 0; i < particleCount; i++) {            nsCOMPtr<nsISchemaParticle> child;            rc = modelGroup->GetParticle(i, getter_AddRefs(child));            if (NS_FAILED(rc))              return rc;            nsCOMPtr<nsIDOMElement> after;            rc = DecodeStructParticle(aEncoding, next, child, aAttachments, aDestination, getter_AddRefs(after));            if (NS_SUCCEEDED(rc)) {               next = after;            }            if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) {              if (rc == NS_ERROR_NOT_AVAILABLE) {                rc = NS_OK;              }              else {                if (NS_SUCCEEDED(rc)) {                  *_retElement = next;                  NS_IF_ADDREF(*_retElement);                }                return rc;              }            }            else if (i > 0 && rc == NS_ERROR_NOT_AVAILABLE) {  //  This detects ambiguous model (non-deterministic choice which fails after succeeding on first)              rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_AMBIGUOUS_DECODING","Cannot proceed due to ambiguity or error in content model");              //  Error is not considered recoverable due to partially-created output.            }            if (NS_FAILED(rc))              break;          }          if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE)            rc = NS_ERROR_NOT_AVAILABLE;          if (NS_SUCCEEDED(rc)) {            *_retElement = next;            NS_IF_ADDREF(*_retElement);          }          if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) {  //  If we succeeded or failed recoverably, but we were permitted to, then return success            *_retElement = aElement;            NS_IF_ADDREF(*_retElement);            rc = NS_OK;          }        }        return rc;                    //  Return status      }      case nsISchemaParticle::PARTICLE_TYPE_ANY://  No model available here (we may wish to handle strict versus lazy, but what does that mean with only local accessor names)      default:        break;    }  }  nsCOMPtr<nsIDOMElement> child = aElement;  while (child) {    nsAutoString name;    nsAutoString namespaceURI;    nsCOMPtr<nsIVariant>value;    rc = child->GetLocalName(name);    if (NS_FAILED(rc))      return rc;    rc = child->GetNamespaceURI(namespaceURI);    if (NS_FAILED(rc))      return rc;    if (!namespaceURI.IsEmpty()) {    //  If we ever figure out what to do with namespaces, get an internal one      return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_GLOBAL_ACCESSOR","Decoded struct contained global accessor, which does not map well into a property name.");    }    rc = aEncoding->Decode(child, nsnull, aAttachments, getter_AddRefs(value));    if (NS_FAILED(rc))      return rc;    if (!value) {      nsCOMPtr<nsIWritableVariant> nullVariant(do_CreateInstance("@mozilla.org/variant;1"));      if (nullVariant) {        nullVariant->SetAsISupports(nsnull);        value = do_QueryInterface(nullVariant);      }    }    rc = aDestination->AddProperty(name, value);    if (NS_FAILED(rc))      return rc;    nsCOMPtr<nsIDOMElement> nextchild;    nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(nextchild));    child = nextchild;  }  *_retElement = nsnull;  return NS_OK;}