Back to index

lightning-sunbird  0.9+nobinonly
nsSchemaLoader.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Vidur Apparao <vidur@netscape.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsSchemaPrivate.h"
00040 #include "nsSchemaLoader.h"
00041 #include "nsIWebServiceErrorHandler.h"
00042 
00043 // content includes
00044 #include "nsIContent.h"
00045 #include "nsIDocument.h"
00046 #include "nsINodeInfo.h"
00047 #include "nsIDOMDocument.h"
00048 #include "nsIDOM3Node.h"
00049 
00050 // loading includes
00051 #include "nsIXMLHttpRequest.h"
00052 #include "nsIDOMEvent.h"
00053 #include "nsIDOMEventListener.h"
00054 #include "nsIDOMEventTarget.h"
00055 #include "nsNetUtil.h"
00056 #include "nsIParserService.h"
00057 
00058 // string includes
00059 #include "nsReadableUtils.h"
00060 
00061 // XPConnect includes
00062 #include "nsIXPConnect.h"
00063 #include "nsIScriptSecurityManager.h"
00064 #include "nsIPrincipal.h"
00065 
00066 // XPCOM includes
00067 #include "nsIServiceManager.h"
00068 #include "nsIComponentManager.h"
00069 #include "nsStaticAtom.h"
00070 
00072 //
00073 // nsSchemaAtoms implementation
00074 //
00076 
00077 // define storage for all atoms
00078 #define SCHEMA_ATOM(_name, _value) nsIAtom* nsSchemaAtoms::_name;
00079 #include "nsSchemaAtomList.h"
00080 #undef SCHEMA_ATOM
00081 
00082 static const nsStaticAtom atomInfo[] = {
00083 #define SCHEMA_ATOM(_name, _value) { _value, &nsSchemaAtoms::_name },
00084 #include "nsSchemaAtomList.h"
00085 #undef SCHEMA_ATOM
00086 };
00087 
00088 nsresult
00089 nsSchemaAtoms::AddRefAtoms()
00090 {
00091   return NS_RegisterStaticAtoms(atomInfo, NS_ARRAY_LENGTH(atomInfo));
00092 }
00093 
00095 //
00096 // LoadListener implementation
00097 //
00099 
00100 class LoadListener : public nsIDOMEventListener {
00101 public:
00102   LoadListener(nsSchemaLoader* aLoader,
00103                nsISchemaLoadListener* aListener,
00104                nsIXMLHttpRequest* aRequest);
00105   virtual ~LoadListener();
00106 
00107   NS_DECL_ISUPPORTS
00108   NS_DECL_NSIDOMEVENTLISTENER
00109 
00110 private:
00111   nsSchemaLoader* mLoader;
00112   nsCOMPtr<nsISchemaLoadListener> mListener;
00113   nsCOMPtr<nsIXMLHttpRequest> mRequest;
00114   nsString mURI;
00115 };
00116 
00117 LoadListener::LoadListener(nsSchemaLoader* aLoader,
00118                            nsISchemaLoadListener* aListener,
00119                            nsIXMLHttpRequest* aRequest) 
00120 {
00121   mLoader = aLoader;
00122   NS_ADDREF(mLoader);
00123   mListener = aListener;
00124   mRequest = aRequest;
00125 }
00126   
00127 LoadListener::~LoadListener() 
00128 {
00129   NS_IF_RELEASE(mLoader);
00130 }
00131 
00132 NS_IMPL_ISUPPORTS1(LoadListener, nsIDOMEventListener)
00133 
00134 /* void handleEvent (in nsIDOMEvent event); */
00135 NS_IMETHODIMP 
00136 LoadListener::HandleEvent(nsIDOMEvent *event)
00137 {
00138   nsresult rv;
00139 
00140   PRUint32 httpStatus;
00141   mRequest->GetStatus(&httpStatus);
00142 
00143   nsCOMPtr<nsISchema> schema;
00144 
00145   nsAutoString eventType;
00146   event->GetType(eventType);
00147 
00148   PRBool succeeded = (httpStatus / 100 == 2);
00149 
00150   // if we loaded fine, and not http/https, we assume success in loaded the file.
00151   if (!succeeded && eventType.EqualsLiteral("load")) {
00152     nsCOMPtr<nsIChannel> channel;
00153     mRequest->GetChannel(getter_AddRefs(channel));
00154     if (channel) {
00155       nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
00156 
00157       // if qi to httpChannel fails, it isn't a http:// or https:// request
00158       if (!httpChannel) {
00159         succeeded = PR_TRUE;
00160       }
00161     }
00162   }
00163 
00164   if (succeeded && eventType.EqualsLiteral("load")) {
00165     nsCOMPtr<nsIDOMDocument> document;
00166 
00167     rv = mRequest->GetResponseXML(getter_AddRefs(document));
00168     if (NS_SUCCEEDED(rv)) {
00169       nsCOMPtr<nsIDOMElement> element;
00170 
00171       if (document)
00172         document->GetDocumentElement(getter_AddRefs(element));
00173 
00174       //XXXTelemac TODO Use an nsIWebServiceErrorHandler instead of nsnull
00175       if (element)
00176         rv = mLoader->ProcessSchemaElement(element, nsnull, getter_AddRefs(schema));
00177       else
00178         rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
00179     }
00180   }
00181   else {
00182     rv = NS_ERROR_SCHEMA_LOADING_ERROR;
00183   }
00184 
00185   //XXXTelemac OnError call replace by use of nsIWebServiceErrorHandler 
00186   //XXXTelemac in sub-processing methods.
00187 
00188   if (mListener) {
00189     if (NS_SUCCEEDED(rv))
00190       mListener->OnLoad(schema);
00191     else
00192       mListener->OnError(rv, NS_LITERAL_STRING("Failure loading"));
00193   }
00194 
00195   NS_IF_RELEASE(mLoader);
00196   mListener = nsnull;
00197   mRequest = nsnull;
00198 
00199   return NS_OK;
00200 }
00201 
00203 //
00204 // nsBuiltinSchemaCollection implementation
00205 //
00207 nsBuiltinSchemaCollection::nsBuiltinSchemaCollection()
00208 {
00209 }
00210 
00211 nsresult
00212 nsBuiltinSchemaCollection::Init()
00213 {
00214   return (mBuiltinTypesHash.Init() && mSOAPTypeHash.Init()) ? NS_OK
00215                                                             : NS_ERROR_FAILURE;
00216 }
00217 
00218 NS_IMPL_ISUPPORTS1(nsBuiltinSchemaCollection,
00219                    nsISchemaCollection)
00220 
00221 /* nsISchema getSchema (in AString targetNamespace); */
00222 NS_IMETHODIMP 
00223 nsBuiltinSchemaCollection::GetSchema(const nsAString & targetNamespace,
00224                                      nsISchema **_retval)
00225 {
00226   NS_ENSURE_ARG_POINTER(_retval);
00227   *_retval = nsnull;
00228   return NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
00229 }
00230 
00231 /* nsISchemaElement getElement (in AString name, in AString namespace); */
00232 NS_IMETHODIMP 
00233 nsBuiltinSchemaCollection::GetElement(const nsAString & aName, 
00234                                       const nsAString & aNamespace, 
00235                                       nsISchemaElement **_retval)
00236 {
00237   if (aNamespace.IsEmpty()) {
00238     NS_WARNING("nsSchemaLoader::GetSchema(nsAString,nsISchema): "
00239                "Invalid |targetNamespace| is empty");
00240     
00241     return NS_ERROR_INVALID_ARG;
00242   }
00243 
00244   NS_ENSURE_ARG_POINTER(_retval);
00245   *_retval = nsnull;
00246   return NS_ERROR_FAILURE;
00247 }
00248 
00249 /* nsISchemaAttribute getAttribute (in AString name, in AString namespace); */
00250 NS_IMETHODIMP 
00251 nsBuiltinSchemaCollection::GetAttribute(const nsAString & aName, 
00252                                         const nsAString & aNamespace, 
00253                                         nsISchemaAttribute **_retval)
00254 {
00255   NS_ENSURE_ARG_POINTER(_retval);
00256   *_retval = nsnull;
00257   return NS_ERROR_FAILURE;
00258 }
00259 
00260 static PRBool
00261 IsSchemaNamespace(const nsAString& aNamespace)
00262 {
00263   if (aNamespace.EqualsLiteral(NS_SCHEMA_2001_NAMESPACE) ||
00264       aNamespace.EqualsLiteral(NS_SCHEMA_1999_NAMESPACE)) {
00265     return PR_TRUE;
00266   }
00267   else {
00268     return PR_FALSE;
00269   }
00270 }
00271 
00272 static PRBool
00273 IsSOAPNamespace(const nsAString& aNamespace)
00274 {
00275   if (aNamespace.EqualsLiteral(NS_SOAP_1_1_ENCODING_NAMESPACE) ||
00276       aNamespace.EqualsLiteral(NS_SOAP_1_2_ENCODING_NAMESPACE)) {
00277     return PR_TRUE;
00278   }
00279   else {
00280     return PR_FALSE;
00281   }  
00282 }
00283 
00284 /* nsISchemaType getType (in AString name, in AString namespace); */
00285 NS_IMETHODIMP 
00286 nsBuiltinSchemaCollection::GetType(const nsAString & aName, 
00287                                    const nsAString & aNamespace, 
00288                                    nsISchemaType **_retval)
00289 {
00290   if (IsSchemaNamespace(aNamespace)) {
00291     return GetBuiltinType(aName, aNamespace, _retval);
00292   }
00293 
00294   if (IsSOAPNamespace(aNamespace)) {
00295     return GetSOAPType(aName, aNamespace, _retval);
00296   }
00297   
00298   return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
00299 }
00300 
00301 nsresult
00302 nsBuiltinSchemaCollection::GetBuiltinType(const nsAString& aName,
00303                                           const nsAString& aNamespace,
00304                                           nsISchemaType** aType)
00305 {
00306   if (!mBuiltinTypesHash.Get(aName, aType)) {
00307     nsCOMPtr<nsIAtom> typeName = do_GetAtom(aName);
00308     PRUint16 typeVal;
00309     if (typeName == nsSchemaAtoms::sAnyType_atom) {
00310       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ANYTYPE;
00311     }
00312     else if (typeName == nsSchemaAtoms::sString_atom) {
00313       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_STRING;
00314     }
00315     else if (typeName == nsSchemaAtoms::sNormalizedString_atom) {
00316       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING;
00317     }
00318     else if (typeName == nsSchemaAtoms::sToken_atom) {
00319       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN;
00320     }
00321     else if (typeName == nsSchemaAtoms::sByte_atom) {
00322       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BYTE;
00323     }
00324     else if (typeName == nsSchemaAtoms::sUnsignedByte_atom) {
00325       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE;
00326     }
00327     else if (typeName == nsSchemaAtoms::sBase64Binary_atom) {
00328       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY;
00329     }
00330     else if (typeName == nsSchemaAtoms::sHexBinary_atom) {
00331       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY;
00332     }
00333     else if (typeName == nsSchemaAtoms::sInteger_atom) {
00334       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER;
00335     }
00336     else if (typeName == nsSchemaAtoms::sPositiveInteger_atom) {
00337       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER;
00338     }
00339     else if (typeName == nsSchemaAtoms::sNegativeInteger_atom) {
00340       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER;
00341     }
00342     else if (typeName == nsSchemaAtoms::sNonnegativeInteger_atom) {
00343       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER;
00344     }
00345     else if (typeName == nsSchemaAtoms::sNonpositiveInteger_atom) {
00346       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER;
00347     }
00348     else if (typeName == nsSchemaAtoms::sInt_atom) {
00349       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_INT;
00350     }
00351     else if (typeName == nsSchemaAtoms::sUnsignedInt_atom) {
00352       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT;
00353     }
00354     else if (typeName == nsSchemaAtoms::sLong_atom) {
00355       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_LONG;
00356     }
00357     else if (typeName == nsSchemaAtoms::sUnsignedLong_atom) {
00358       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG;
00359     }
00360     else if (typeName == nsSchemaAtoms::sShort_atom) {
00361       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_SHORT;
00362     }
00363     else if (typeName == nsSchemaAtoms::sUnsignedShort_atom) {
00364       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT;
00365     }
00366     else if (typeName == nsSchemaAtoms::sDecimal_atom) {
00367       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL;
00368     }
00369     else if (typeName == nsSchemaAtoms::sFloat_atom) {
00370       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT;
00371     }
00372     else if (typeName == nsSchemaAtoms::sDouble_atom) {
00373       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE;
00374     }
00375     else if (typeName == nsSchemaAtoms::sBoolean_atom) {
00376       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN;
00377     }
00378     else if (typeName == nsSchemaAtoms::sTime_atom) {
00379       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_TIME;
00380     }
00381     else if (typeName == nsSchemaAtoms::sDateTime_atom) {
00382       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME;
00383     }
00384     else if (typeName == nsSchemaAtoms::sDuration_atom) {
00385       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DURATION;
00386     }
00387     else if (typeName == nsSchemaAtoms::sDate_atom) {
00388       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DATE;
00389     }
00390     else if (typeName == nsSchemaAtoms::sGMonth_atom) {
00391       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH;
00392     }
00393     else if (typeName == nsSchemaAtoms::sGYear_atom) {
00394       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR;
00395     }
00396     else if (typeName == nsSchemaAtoms::sGYearMonth_atom) {
00397       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH;
00398     }
00399     else if (typeName == nsSchemaAtoms::sGDay_atom) {
00400       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GDAY;
00401     }
00402     else if (typeName == nsSchemaAtoms::sGMonthDay_atom) {
00403       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY;
00404     }
00405     else if (typeName == nsSchemaAtoms::sName_atom) {
00406       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NAME;
00407     }
00408     else if (typeName == nsSchemaAtoms::sQName_atom) {
00409       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_QNAME;
00410     }
00411     else if (typeName == nsSchemaAtoms::sNCName_atom) {
00412       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME;
00413     }
00414     else if (typeName == nsSchemaAtoms::sAnyURI_atom) {
00415       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI;
00416     }
00417     else if (typeName == nsSchemaAtoms::sLanguage_atom) {
00418       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE;
00419     }
00420     else if (typeName == nsSchemaAtoms::sID_atom) {
00421       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ID;
00422     }
00423     else if (typeName == nsSchemaAtoms::sIDREF_atom) {
00424       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_IDREF;
00425     }
00426     else if (typeName == nsSchemaAtoms::sIDREFS_atom) {
00427       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS;
00428     }
00429     else if (typeName == nsSchemaAtoms::sENTITY_atom) {
00430       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY;
00431     }
00432     else if (typeName == nsSchemaAtoms::sENTITIES_atom) {
00433       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES;
00434     }
00435     else if (typeName == nsSchemaAtoms::sNOTATION_atom) {
00436       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION;
00437     }
00438     else if (typeName == nsSchemaAtoms::sNMTOKEN_atom) {
00439       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN;
00440     }
00441     else if (typeName == nsSchemaAtoms::sNMTOKENS_atom) {
00442       typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS;
00443     }
00444     else {
00445       NS_ERROR("Unknown builtin type");
00446       return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
00447     }
00448 
00449     nsCOMPtr<nsISchemaType> builtin = new nsSchemaBuiltinType(typeVal);
00450     if (!builtin) {
00451       return NS_ERROR_OUT_OF_MEMORY;
00452     }
00453 
00454     mBuiltinTypesHash.Put(aName, builtin);
00455     builtin.swap(*aType);
00456   }
00457 
00458   return NS_OK;
00459 }
00460 
00461 nsresult
00462 nsBuiltinSchemaCollection::GetSOAPType(const nsAString& aName,
00463                                        const nsAString& aNamespace,
00464                                        nsISchemaType** aType)
00465 {
00466   nsresult rv = NS_OK;
00467 
00468   if (!mSOAPTypeHash.Get(aName, aType)) {
00469     if (aName.EqualsLiteral("Array")) {
00470       nsCOMPtr<nsISchemaType> anyType;
00471       rv = GetBuiltinType(NS_LITERAL_STRING("anyType"),
00472                           NS_LITERAL_STRING(NS_SCHEMA_2001_NAMESPACE),
00473                           getter_AddRefs(anyType));
00474       if (NS_FAILED(rv)) {
00475         return rv;
00476       }
00477 
00478       nsSOAPArray* array = new nsSOAPArray(anyType);
00479       if (!array) {
00480         return NS_ERROR_OUT_OF_MEMORY;
00481       }
00482 
00483       mSOAPTypeHash.Put(aName, array);
00484 
00485       *aType = array;
00486       NS_ADDREF(*aType);
00487     }
00488     else if (aName.EqualsLiteral("arrayType")) {
00489       nsSOAPArrayType* arrayType = new nsSOAPArrayType();
00490       if (!arrayType) {
00491         return NS_ERROR_OUT_OF_MEMORY;
00492       }
00493 
00494       mSOAPTypeHash.Put(aName, arrayType);
00495 
00496       *aType = arrayType;
00497       NS_ADDREF(*aType);
00498     }
00499     else {
00500       rv = NS_ERROR_SCHEMA_UNKNOWN_TYPE;
00501     }
00502   }
00503 
00504   return rv;
00505 }
00506 
00508 //
00509 // nsSchemaLoader implementation
00510 //
00512 
00513 nsSchemaLoader::nsSchemaLoader()
00514 {
00515   mBuiltinCollection = do_GetService(NS_BUILTINSCHEMACOLLECTION_CONTRACTID);
00516 }
00517 
00518 nsresult
00519 nsSchemaLoader::Init()
00520 {
00521   return mSchemas.Init() ? NS_OK : NS_ERROR_FAILURE;
00522 }
00523 
00524 NS_IMPL_ISUPPORTS2_CI(nsSchemaLoader,
00525                       nsISchemaLoader,
00526                       nsISchemaCollection)
00527 
00528 
00529 /* nsISchema getSchema (in AString targetNamespace); */
00530 NS_IMETHODIMP 
00531 nsSchemaLoader::GetSchema(const nsAString & targetNamespace, 
00532                           nsISchema ** aResult)
00533 {
00534   NS_ENSURE_ARG_POINTER(aResult);
00535 
00536   return mSchemas.Get(targetNamespace, aResult) ? NS_OK :
00537            NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
00538 }
00539 
00540 /* nsISchemaElement getElement (in AString name, in AString namespace); */
00541 NS_IMETHODIMP 
00542 nsSchemaLoader::GetElement(const nsAString & aName, 
00543                            const nsAString & aNamespace, 
00544                            nsISchemaElement **_retval)
00545 {
00546   nsCOMPtr<nsISchema> schema;
00547   nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
00548   if (NS_FAILED(rv)) {
00549     return rv;
00550   }
00551 
00552   return schema->GetElementByName(aName, _retval);
00553 }
00554 
00555 /* nsISchemaAttribute getAttribute (in AString name, in AString namespace); */
00556 NS_IMETHODIMP 
00557 nsSchemaLoader::GetAttribute(const nsAString & aName, 
00558                              const nsAString & aNamespace, 
00559                              nsISchemaAttribute **_retval)
00560 {
00561   nsCOMPtr<nsISchema> schema;
00562   nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
00563   if (NS_FAILED(rv)) {
00564     return rv;
00565   }
00566 
00567   return schema->GetAttributeByName(aName, _retval);
00568 }
00569 
00570 /* nsISchemaType getType (in AString name, in AString namespace); */
00571 NS_IMETHODIMP 
00572 nsSchemaLoader::GetType(const nsAString & aName, 
00573                         const nsAString & aNamespace, 
00574                         nsISchemaType **_retval)
00575 {
00576   nsresult rv = NS_OK;
00577 
00578   if (IsSchemaNamespace(aNamespace) || IsSOAPNamespace(aNamespace)) {
00579     rv = mBuiltinCollection->GetType(aName, aNamespace, _retval);
00580 
00581     if (NS_FAILED(rv)) {
00582       nsAutoString errorMsg(NS_LITERAL_STRING("nsSchemaLoader::GetType: "));
00583       errorMsg.AppendLiteral("Failure processing schema: cannot get schema type \"");
00584       errorMsg.Append(aName);
00585       errorMsg.AppendLiteral("\"");
00586       NS_ERROR(NS_ConvertUTF16toUTF8(errorMsg).get());
00587 
00588       return rv;
00589     }
00590 
00591     return NS_OK;
00592   }
00593 
00594   nsCOMPtr<nsISchema> schema;
00595   rv = GetSchema(aNamespace, getter_AddRefs(schema));
00596   if (NS_FAILED(rv)) {
00597     return rv;
00598   }
00599 
00600   rv = schema->GetTypeByName(aName, _retval);
00601 
00602   if (NS_FAILED(rv)) {
00603     nsAutoString msg(NS_LITERAL_STRING("nsSchemaLoader::GetType: "));
00604     msg.AppendLiteral("Failure processing schema: ");
00605     msg.AppendLiteral("cannot get schema type \"");
00606     msg.Append(aName);
00607     msg.AppendLiteral("\"");
00608     NS_ERROR(NS_ConvertUTF16toUTF8(msg).get());
00609 
00610     return rv;
00611   }
00612 
00613   return NS_OK;
00614 }
00615 
00616 nsresult
00617 nsSchemaLoader::GetResolvedURI(const nsAString& aSchemaURI,
00618                                const char* aMethod,
00619                                nsIURI** aURI)
00620 {
00621   nsresult rv;
00622   nsCOMPtr<nsIXPCNativeCallContext> cc;
00623   nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
00624   if(NS_SUCCEEDED(rv)) {
00625     rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
00626   }
00627 
00628   if (NS_SUCCEEDED(rv) && cc) {
00629     JSContext* cx;
00630     rv = cc->GetJSContext(&cx);
00631     if (NS_FAILED(rv)) return rv;
00632 
00633     nsCOMPtr<nsIScriptSecurityManager> secMan(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
00634     if (NS_FAILED(rv)) return rv;
00635 
00636     nsCOMPtr<nsIURI> baseURI;
00637     nsCOMPtr<nsIPrincipal> principal;
00638     rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal));
00639     if (NS_SUCCEEDED(rv)) {
00640       principal->GetURI(getter_AddRefs(baseURI));
00641     }
00642 
00643     rv = NS_NewURI(aURI, aSchemaURI, nsnull, baseURI);
00644     if (NS_FAILED(rv)) return rv;
00645 
00646     rv = secMan->CheckLoadURIFromScript(cx, *aURI);
00647     if (NS_FAILED(rv))
00648     {
00649       // Security check failed. The above call set a JS exception. The
00650       // following lines ensure that the exception is propagated.
00651       cc->SetExceptionWasThrown(PR_TRUE);
00652       return rv;
00653     }
00654   }
00655   else {
00656     rv = NS_NewURI(aURI, aSchemaURI, nsnull);
00657     if (NS_FAILED(rv)) return rv;
00658   }
00659 
00660   return NS_OK;
00661 }
00662 
00663 /* nsISchema load (in AString schemaURI); */
00664 NS_IMETHODIMP 
00665 nsSchemaLoader::Load(const nsAString& schemaURI,
00666                      nsISchema **_retval)
00667 {
00668   NS_ENSURE_ARG_POINTER(_retval);
00669 
00670   nsCOMPtr<nsIDOMDocument> document;
00671   nsresult rv = GetDocumentFromURI(schemaURI, getter_AddRefs(document));
00672   NS_ENSURE_SUCCESS(rv, rv);
00673 
00674   if (!document)
00675     return NS_ERROR_SCHEMA_LOADING_ERROR;
00676 
00677   nsCOMPtr<nsIDOMElement> element;
00678   document->GetDocumentElement(getter_AddRefs(element));
00679   if (element) {
00680     //XXXTelemac TODO Have an error handler there instead or nsnull
00681     rv = ProcessSchemaElement(element, nsnull, _retval);
00682   }
00683   else {
00684     rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
00685   }
00686 
00687   return rv;
00688 }
00689 
00690 /* void loadAsync (in AString schemaURI, in nsISchemaLoadListener listener); */
00691 NS_IMETHODIMP 
00692 nsSchemaLoader::LoadAsync(const nsAString& schemaURI, 
00693                           nsISchemaLoadListener *aListener)
00694 {
00695   NS_ENSURE_ARG(aListener);
00696 
00697   nsCOMPtr<nsIURI> resolvedURI;
00698   nsresult rv = GetResolvedURI(schemaURI, "loadAsync", getter_AddRefs(resolvedURI));
00699   if (NS_FAILED(rv)) {
00700     return rv;
00701   }
00702   nsCAutoString spec;
00703   resolvedURI->GetSpec(spec);
00704 
00705   nsCOMPtr<nsIXMLHttpRequest> request(do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv));
00706   if (!request) {
00707     return rv;
00708   }
00709 
00710   const nsAString& empty = EmptyString();
00711   rv = request->OpenRequest(NS_LITERAL_CSTRING("GET"), spec, PR_TRUE, empty,
00712                             empty);
00713   if (NS_FAILED(rv)) {
00714     return rv;
00715   }
00716 
00717   // Force the mimetype of the returned stream to be xml.
00718   rv = request->OverrideMimeType(NS_LITERAL_CSTRING("application/xml"));
00719   if (NS_FAILED(rv)) {
00720     return rv;
00721   }
00722 
00723   nsCOMPtr<nsIDOMEventListener> listener;
00724   LoadListener* listenerInst = new LoadListener(this, aListener, request);
00725   if (!listenerInst) {
00726     return NS_ERROR_OUT_OF_MEMORY;
00727   }
00728   listener = listenerInst;
00729 
00730   nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(request));
00731   if (!target) {
00732     return NS_ERROR_UNEXPECTED;
00733   }
00734   
00735   rv = target->AddEventListener(NS_LITERAL_STRING("load"),
00736                                 listener, PR_FALSE);
00737   if (NS_FAILED(rv)) {
00738     return rv;
00739   }
00740 
00741   rv = target->AddEventListener(NS_LITERAL_STRING("error"),
00742                                 listener, PR_FALSE);
00743   if (NS_FAILED(rv)) {
00744     return rv;
00745   }
00746 
00747   // The listener keeps the request alive until its complete
00748   rv = request->Send(nsnull);
00749   
00750   return rv;
00751 }
00752 
00753 static const char* kSchemaNamespaces[] = {NS_SCHEMA_1999_NAMESPACE, 
00754                                           NS_SCHEMA_2001_NAMESPACE};
00755 static PRUint32 kSchemaNamespacesLength = sizeof(kSchemaNamespaces) / sizeof(const char*);
00756 
00757 /* nsISchema processSchemaElement (in nsIDOMElement element, in nsIWebServiceErrorHandler aErrorHandler); */
00758 NS_IMETHODIMP
00759 nsSchemaLoader::ProcessSchemaElement(nsIDOMElement* aElement,
00760                                      nsIWebServiceErrorHandler* aErrorHandler,
00761                                      nsISchema **aResult)
00762 {
00763   NS_ENSURE_ARG(aElement);
00764   NS_ENSURE_ARG_POINTER(aResult);
00765 
00766   nsRefPtr<nsSchema> schemaInst = new nsSchema(this, aElement);
00767   if (!schemaInst) {
00768     return NS_ERROR_OUT_OF_MEMORY;
00769   }
00770 
00771   nsresult rv = schemaInst->Init();
00772   NS_ENSURE_SUCCESS(rv, rv);
00773 
00774   nsAutoString targetNamespace;
00775   schemaInst->GetTargetNamespace(targetNamespace);
00776 
00777   nsISchema * os;
00778   if (mSchemas.Get(targetNamespace, &os)) {
00779     *aResult = os;
00780     return NS_OK;
00781   }
00782 
00783   nsChildElementIterator iterator(aElement,
00784                                   kSchemaNamespaces, kSchemaNamespacesLength);
00785   nsCOMPtr<nsIDOMElement> childElement;
00786   nsCOMPtr<nsIAtom> tagName;
00787 
00788   // For now, ignore the following
00789   // annotations
00790   // redefine
00791   // notation
00792   // identity-constraint elements
00793 
00794   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
00795                                             getter_AddRefs(tagName))) &&
00796          childElement) {
00797     if (tagName == nsSchemaAtoms::sElement_atom) {
00798       nsCOMPtr<nsISchemaElement> schemaElement;
00799       rv = ProcessElement(aErrorHandler, schemaInst, childElement,
00800                           getter_AddRefs(schemaElement));
00801       if (NS_SUCCEEDED(rv)) {
00802         rv = schemaInst->AddElement(schemaElement);
00803       }
00804     }
00805     else if (tagName == nsSchemaAtoms::sComplexType_atom) {
00806       nsCOMPtr<nsISchemaComplexType> complexType;
00807       rv = ProcessComplexType(aErrorHandler, schemaInst, childElement,
00808                               getter_AddRefs(complexType));
00809       if (NS_SUCCEEDED(rv)) {
00810         rv = schemaInst->AddType(complexType);
00811       }
00812     }
00813     else if (tagName == nsSchemaAtoms::sSimpleType_atom) {
00814       nsCOMPtr<nsISchemaSimpleType> simpleType;
00815       rv = ProcessSimpleType(aErrorHandler, schemaInst, childElement,
00816                              getter_AddRefs(simpleType));
00817       if (NS_SUCCEEDED(rv)) {
00818         rv = schemaInst->AddType(simpleType);
00819       }
00820     }
00821     else if (tagName == nsSchemaAtoms::sAttribute_atom) {
00822       nsCOMPtr<nsISchemaAttribute> attribute;
00823       rv = ProcessAttribute(aErrorHandler, schemaInst, childElement,
00824                             getter_AddRefs(attribute));
00825       if (NS_SUCCEEDED(rv)) {
00826         rv = schemaInst->AddAttribute(attribute);
00827       }
00828     }
00829     else if (tagName == nsSchemaAtoms::sAttributeGroup_atom) {
00830       nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
00831       rv = ProcessAttributeGroup(aErrorHandler, schemaInst, childElement,
00832                                  getter_AddRefs(attributeGroup));
00833       if (NS_SUCCEEDED(rv)) {
00834         rv = schemaInst->AddAttributeGroup(attributeGroup);
00835       }
00836     }
00837     else if (tagName == nsSchemaAtoms::sModelGroup_atom) {
00838       nsCOMPtr<nsISchemaModelGroup> modelGroup;
00839       rv = ProcessModelGroup(aErrorHandler, schemaInst, childElement,
00840                              tagName, nsnull, getter_AddRefs(modelGroup));
00841       if (NS_SUCCEEDED(rv)) {
00842         rv = schemaInst->AddModelGroup(modelGroup);
00843       }
00844     }
00845     else if (tagName == nsSchemaAtoms::sInclude_atom ||
00846              tagName == nsSchemaAtoms::sImport_atom) {
00847       /* Mixing the handling of <include> and <import> as they are very similar,
00848         other than a few requirements regarding namespaces.
00849 
00850         http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-include
00851          If we include a schema, it must either
00852            (a) have the same targetNamespace as the including schema document or
00853            (b) no targetNamespace at all
00854 
00855         http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-import
00856          When importing a schema, it must either
00857            (a) if namespace is defined, then namespace == imported
00858                targetNamespace
00859            (b) if namespace is not defined, then imported schema must NOT
00860                have a targetNamespace
00861 
00862          If the uri to load doesn't resolve, it isn't a error.  It is if its an
00863          invalid XML document or not a schema file
00864        */
00865 
00866       NS_NAMED_LITERAL_STRING(schemaLocationStr, "schemaLocation");
00867       PRBool hasSchemaLocationAttr = PR_FALSE;
00868       childElement->HasAttribute(schemaLocationStr, &hasSchemaLocationAttr);
00869 
00870       // no schema location attribute, skip it
00871       if (!hasSchemaLocationAttr)
00872         continue;
00873 
00874       nsAutoString schemalocation;
00875       childElement->GetAttribute(schemaLocationStr, schemalocation);
00876 
00877       // if empty, skip it
00878       if (schemalocation.IsEmpty())
00879         continue;
00880 
00881       nsCOMPtr<nsIIOService> ios = do_GetIOService();
00882       NS_ENSURE_STATE(ios);
00883 
00884       nsCOMPtr<nsIDOMDocument> document;
00885       aElement->GetOwnerDocument(getter_AddRefs(document));
00886 
00887       nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
00888       NS_ENSURE_STATE(doc);
00889 
00890       nsCOMPtr<nsIURI> uri;
00891 
00892       ios->NewURI(NS_ConvertUTF16toUTF8(schemalocation),
00893                   doc->GetDocumentCharacterSet().get(),
00894                   doc->GetDocumentURI(),
00895                   getter_AddRefs(uri));
00896       NS_ENSURE_STATE(uri);
00897 
00898       // since we could be going cross-domain, make sure we can load it by doing
00899       // a principal same origin check.
00900 
00901       // get the base document's principal
00902       nsIPrincipal *basePrincipal = doc->GetPrincipal();
00903       NS_ENSURE_STATE(basePrincipal);
00904 
00905       // check the security manager and do a same original check on the principal
00906       nsCOMPtr<nsIScriptSecurityManager> secMan =
00907         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
00908       NS_ENSURE_STATE(secMan);
00909 
00910       // get a principal for the uri we are testing
00911       nsCOMPtr<nsIPrincipal> testPrincipal;
00912       rv = secMan->GetCodebasePrincipal(uri, getter_AddRefs(testPrincipal));
00913       NS_ENSURE_SUCCESS(rv, rv);
00914 
00915       rv = secMan->CheckSameOriginPrincipal(basePrincipal, testPrincipal);
00916       // if not allowed, continue onwards
00917       if (NS_FAILED(rv))
00918         continue;
00919 
00920       // get the url
00921       nsCAutoString spec;
00922       uri->GetSpec(spec);
00923 
00924       nsCOMPtr<nsIDOMDocument> includedDocument;
00925       rv = GetDocumentFromURI(NS_ConvertUTF8toUTF16(spec), getter_AddRefs(includedDocument));
00926       NS_ENSURE_SUCCESS(rv, rv);
00927 
00928       // if no document, it is an error
00929       NS_ENSURE_STATE(includedDocument);
00930 
00931       // get the document element - it should be a xsd:schema
00932       nsCOMPtr<nsIDOMElement> element;
00933       includedDocument->GetDocumentElement(getter_AddRefs(element));
00934 
00935       nsAutoString localName, nsUri;
00936       element->GetLocalName(localName);
00937       element->GetNamespaceURI(nsUri);
00938 
00939       PRBool correctNamespace = PR_FALSE;
00940       PRUint32 i;
00941       for (i = 0; i < kSchemaNamespacesLength; i++) {
00942         if (nsUri.Equals(NS_ConvertASCIItoUTF16(kSchemaNamespaces[i]))) {
00943           correctNamespace = PR_TRUE;
00944           break;
00945         }
00946       }
00947 
00948       if (!correctNamespace || !localName.EqualsLiteral("schema")) {
00949         // not a valid schema file
00950         return NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
00951       }
00952 
00953       // XXX: check the target namespace requirements
00954 
00955       // If <import>, simply call self to do all the heavy lifting
00956       if (tagName == nsSchemaAtoms::sImport_atom) {
00957         rv = ProcessSchemaElement(element, nsnull, aResult);
00958         NS_ENSURE_SUCCESS(rv, rv);
00959         continue;
00960       }
00961 
00962       // import/append all elements in the included file to our schema element
00963       nsCOMPtr<nsIDOMDocument> ownerDoc;
00964       rv = childElement->GetOwnerDocument(getter_AddRefs(ownerDoc));
00965       NS_ENSURE_SUCCESS(rv, rv);
00966       NS_ENSURE_STATE(ownerDoc);
00967 
00968       nsCOMPtr<nsIDOMNode> tmpNode, importedNode, dummy;
00969       element->GetFirstChild(getter_AddRefs(tmpNode));
00970 
00971       // get the child element's next sibling so we have something to insert
00972       // before while we are appending to the current schema document
00973       unsigned short nodeType;
00974       nsCOMPtr<nsIDOMNode> nextSibling;
00975       childElement->GetNextSibling(getter_AddRefs(nextSibling));
00976 
00977       while (tmpNode) {
00978         tmpNode->GetNodeType(&nodeType);
00979 
00980         if (nodeType == nsIDOMNode::ELEMENT_NODE) {
00981           rv = ownerDoc->ImportNode(tmpNode, PR_TRUE,
00982                                     getter_AddRefs(importedNode));
00983           NS_ENSURE_SUCCESS(rv, rv);
00984 
00985           if (nextSibling) {
00986             rv = aElement->InsertBefore(importedNode, nextSibling,
00987                                         getter_AddRefs(dummy));
00988             NS_ENSURE_SUCCESS(rv, rv);
00989           } else {
00990             rv = aElement->AppendChild(importedNode, getter_AddRefs(dummy));
00991             NS_ENSURE_SUCCESS(rv, rv);
00992           }
00993         }
00994 
00995         tmpNode->GetNextSibling(getter_AddRefs(dummy));
00996         tmpNode = dummy;
00997       }
00998 
00999       // we twidle the iterator (reset), making sure to point it at the right
01000       // place.  We do this because the iterator takes a snapshot the DOMList,
01001       // so we tell it to reinit itself and then reset it to the original index.
01002       PRUint32 index = iterator.GetCurrentIndex();
01003       iterator.SetElement(aElement);
01004       iterator.Reset(index);
01005     } else if (tagName != nsSchemaAtoms::sAnnotation_atom &&
01006                tagName != nsSchemaAtoms::sRedefine_atom &&
01007                tagName != nsSchemaAtoms::sNotation_atom) {
01008       // if it is none of these, unexpected element.
01009       nsAutoString elementName;
01010       nsresult rc = aElement->GetTagName(elementName);
01011       NS_ENSURE_SUCCESS(rc, rc);
01012 
01013       nsAutoString errorMsg;
01014       errorMsg.AppendLiteral("Failure processing schema, unexpected element \"");
01015       errorMsg.Append(elementName);
01016       errorMsg.AppendLiteral("\" in <schema .../>");
01017 
01018       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01019 
01020       return NS_ERROR_UNEXPECTED;
01021     }
01022 
01023     if (NS_FAILED(rv)) {
01024       nsAutoString errorMsg;
01025       errorMsg.AppendLiteral("Failure processing schema");
01026       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01027 
01028       return rv;
01029     }
01030   }
01031 
01032   // We need to add this schema into the schema collection because resolving
01033   // forward references may require resolving types with namespace prefixes,
01034   // which could easily point back at this schema file.
01035   mSchemas.Put(targetNamespace, schemaInst);
01036 
01037   // Resolve all forward references 
01038   rv = schemaInst->Resolve(aErrorHandler);
01039   if (NS_FAILED(rv)) {
01040     return rv;
01041   }
01042 
01043   NS_ADDREF(*aResult = schemaInst);
01044 
01045   return NS_OK;
01046 }
01047 
01048 PRBool 
01049 ParseQualifiedName(nsIDOMElement* aContext,
01050                    const nsAString& aQualifiedName,
01051                    nsAString& aPrefix,
01052                    nsAString& aLocalName,
01053                    nsAString& aNamespaceURI) 
01054 {
01055   nsReadingIterator<PRUnichar> pos, begin, end;
01056   
01057   aQualifiedName.BeginReading(begin);
01058   aQualifiedName.EndReading(end); 
01059   pos = begin;
01060   
01061   if (FindCharInReadable(PRUnichar(':'), pos, end)) {
01062     CopyUnicodeTo(begin, pos, aPrefix);
01063     CopyUnicodeTo(++pos, end, aLocalName);
01064   }
01065   else {
01066     CopyUnicodeTo(begin, end, aLocalName);
01067   }
01068   
01069   nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(aContext));
01070   
01071   return node->LookupNamespaceURI(aPrefix, aNamespaceURI);
01072 }
01073 
01074 nsresult
01075 nsSchemaLoader::GetNewOrUsedType(nsSchema* aSchema,
01076                                  nsIDOMElement* aContext,
01077                                  const nsAString& aTypeName,
01078                                  nsISchemaType** aType)
01079 {
01080   nsresult rv = NS_OK;
01081   nsAutoString prefix, localName, namespaceURI;
01082 
01083   // See if there's a prefix and get the
01084   // namespace associated with the prefix
01085   rv = ParseQualifiedName(aContext, aTypeName, prefix, 
01086                           localName, namespaceURI);
01087   if (!prefix.IsEmpty() && NS_FAILED(rv)) {
01088     // Unknown prefix
01089     return NS_ERROR_SCHEMA_UNKNOWN_PREFIX;
01090   }
01091 
01092   *aType = nsnull;
01093   nsAutoString targetNamespace;
01094   aSchema->GetTargetNamespace(targetNamespace);
01095   if (namespaceURI.IsEmpty() || namespaceURI.Equals(targetNamespace)) {
01096     // It's a local type 
01097     rv = aSchema->GetTypeByName(localName, aType);
01098   }
01099   else {
01100     rv = GetType(localName, namespaceURI, aType);
01101     if (!*aType) {
01102       return NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
01103     }
01104   }
01105 
01106   // If we didn't get a type, we need to create a placeholder
01107   if (NS_SUCCEEDED(rv) && !*aType) {
01108     nsSchemaTypePlaceholder* placeholder = new nsSchemaTypePlaceholder(aSchema,
01109                                                                        localName);
01110     if (!placeholder) {
01111       return NS_ERROR_OUT_OF_MEMORY;
01112     }
01113     *aType = placeholder;
01114     NS_ADDREF(*aType);
01115   }
01116 
01117   return rv;
01118 }
01119 
01126 nsresult 
01127 nsSchemaLoader::ProcessElement(nsIWebServiceErrorHandler* aErrorHandler,
01128                                nsSchema* aSchema, 
01129                                nsIDOMElement* aElement,
01130                                nsISchemaElement** aSchemaElement)
01131 {
01132   nsresult rv = NS_OK;
01133 
01134   nsCOMPtr<nsISchemaElement> schemaElement;
01135   PRUint32 minOccurs, maxOccurs;
01136   GetMinAndMax(aElement, &minOccurs, &maxOccurs);
01137 
01138   // See if it's a reference or an actual element declaration
01139   nsAutoString ref;
01140   aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
01141   if (!ref.IsEmpty()) {
01142     nsSchemaElementRef* elementRef;
01143     nsAutoString refNS;
01144 
01145     // need to handle ns:type
01146     nsresult rv = ParseNameAndNS(ref, aElement, ref, refNS);
01147       NS_ENSURE_SUCCESS(rv, rv);
01148 
01149     elementRef = new nsSchemaElementRef(aSchema, ref, refNS);
01150     if (!elementRef) {
01151       return NS_ERROR_OUT_OF_MEMORY;
01152     }
01153     schemaElement = elementRef;
01154 
01155     elementRef->SetMinOccurs(minOccurs);
01156     elementRef->SetMaxOccurs(maxOccurs);
01157   }
01158   else {
01159     nsAutoString value;
01160     nsSchemaElement* elementInst;
01161     const nsAString& empty = EmptyString();
01162 
01163     rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("name"), value);
01164     
01165     if (NS_FAILED(rv)) {
01166       nsresult rc = aElement->GetTagName(value);
01167       NS_ENSURE_SUCCESS(rc, rc);
01168 
01169       nsAutoString errorMsg;
01170       errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
01171       errorMsg.AppendLiteral("attribute \"name\" of element \"");
01172       errorMsg.Append(value);
01173       errorMsg.AppendLiteral("\"");
01174 
01175       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01176 
01177       return rv;
01178     }
01179 
01180     value.Trim(" \r\n\t");
01181     elementInst = new nsSchemaElement(aSchema, value);
01182     if (!elementInst) {
01183       return NS_ERROR_OUT_OF_MEMORY;
01184     }
01185     schemaElement = elementInst;
01186 
01187     elementInst->SetMinOccurs(minOccurs);
01188     elementInst->SetMaxOccurs(maxOccurs);
01189 
01190     nsAutoString defaultValue, fixedValue;
01191     rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("default"),
01192                                   defaultValue);
01193     if (NS_FAILED(rv)) {
01194       nsresult rc = aElement->GetTagName(value);
01195       NS_ENSURE_SUCCESS(rc, rc);
01196 
01197       nsAutoString errorMsg;
01198       errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
01199       errorMsg.AppendLiteral("attribute \"default\" of element \"");
01200       errorMsg.Append(value);
01201       errorMsg.AppendLiteral("\"");
01202 
01203       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01204 
01205       return rv;
01206     }
01207     
01208     rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("fixed"), 
01209                                   fixedValue);
01210     if (NS_FAILED(rv)) {
01211       nsresult rc = aElement->GetTagName(value);
01212       NS_ENSURE_SUCCESS(rc, rc);
01213 
01214       nsAutoString errorMsg;
01215       errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
01216       errorMsg.AppendLiteral("attribute \"fixed\" of element \"");
01217       errorMsg.Append(value);
01218       errorMsg.AppendLiteral("\"");
01219 
01220       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01221 
01222       return rv;
01223     }
01224 
01225     elementInst->SetConstraints(defaultValue, fixedValue);
01226 
01227     rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("nillable"), value);
01228     if (NS_FAILED(rv)) {
01229       nsresult rc = aElement->GetTagName(value);
01230       NS_ENSURE_SUCCESS(rc, rc);
01231 
01232       nsAutoString errorMsg;
01233       errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
01234       errorMsg.AppendLiteral("attribute \"nillable\" of element \"");
01235       errorMsg.Append(value);
01236       errorMsg.AppendLiteral("\"");
01237 
01238       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01239 
01240       return rv;
01241     }
01242     value.Trim(" \r\n\t");
01243 
01244     PRInt32 flags = 0;
01245     if (value.EqualsLiteral("true"))
01246       flags |= nsSchemaElement::NILLABLE;
01247 
01248     rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("abstract"), value);
01249     if (NS_FAILED(rv)) {
01250       nsresult rc = aElement->GetTagName(value);
01251       NS_ENSURE_SUCCESS(rc, rc);
01252 
01253       nsAutoString errorMsg;
01254       errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
01255       errorMsg.AppendLiteral("attribute \"abstract\" of element \"");
01256       errorMsg.Append(value);
01257       errorMsg.AppendLiteral("\"");
01258 
01259       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01260 
01261       return rv;
01262     }
01263     value.Trim(" \r\n\t");
01264 
01265     if (value.EqualsLiteral("true"))
01266       flags |= nsSchemaElement::ABSTRACT;
01267 
01268     nsCOMPtr<nsIDOMNode> parent;
01269     rv = aElement->GetParentNode(getter_AddRefs(parent));
01270     if (NS_FAILED(rv))
01271       return rv;
01272     parent->GetLocalName(value);
01273     
01274     // Check if the schema element's targetNamespace applies to <element>.
01275     // Note: If the <element> element information item has <schema> as its 
01276     // parent,then the actual value of the targetNamespace is that of the
01277     // parent <schema> element information item, or absent if there is 
01278     // none. Otherwise if the <element> element information item has 
01279     // <schema> element as an ancestor then if "form" is present and its actual
01280     // value is qualified, or if "form" is absent and the actual value of 
01281     // elementFormDefault on the <schema> ancestor is qualified, then the
01282     // actual value of the  targetNamespace [attribute] is that of the ancestor
01283     // <schema> element information item, or absent if there is none.
01284     if (value.EqualsLiteral("schema")) {
01285       flags |= nsSchemaElement::FORM_QUALIFIED;
01286     }
01287     else {
01288       rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("form"), 
01289                                     value);
01290       if (NS_FAILED(rv)) {
01291         nsAutoString errorMsg;
01292         errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
01293         errorMsg.AppendLiteral("attribute \"form\" of element \"");
01294         errorMsg.Append(value);
01295         errorMsg.AppendLiteral("\"");
01296 
01297         NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01298 
01299         return rv;
01300       }
01301       value.Trim(" \r\n\t");
01302       if (value.IsEmpty()) {
01303         if (aSchema->IsElementFormQualified()) {
01304            flags |= nsSchemaElement::FORM_QUALIFIED;
01305         }
01306         else {
01307            flags &= ~nsSchemaElement::FORM_QUALIFIED;
01308         }
01309       }
01310       else if (value.EqualsLiteral("qualified")) {
01311         flags |= nsSchemaElement::FORM_QUALIFIED;
01312       }
01313       else {
01314          flags &= ~nsSchemaElement::FORM_QUALIFIED;
01315       }
01316     }
01317 
01318     elementInst->SetFlags(flags);
01319 
01320     nsCOMPtr<nsISchemaType> schemaType;
01321     nsAutoString typeStr;
01322     aElement->GetAttribute(NS_LITERAL_STRING("type"), typeStr);
01323     if (!typeStr.IsEmpty()) {
01324       rv = GetNewOrUsedType(aSchema, aElement, typeStr, 
01325                             getter_AddRefs(schemaType));
01326       if (NS_FAILED(rv)) {
01327         nsAutoString errorMsg;
01328         errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
01329         errorMsg.Append(typeStr);
01330         errorMsg.AppendLiteral("\"");
01331 
01332         NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01333 
01334         return rv;
01335       }
01336     }
01337     // Look for the type as a child of the element 
01338     else {
01339       nsChildElementIterator iterator(aElement, 
01340                                       kSchemaNamespaces, 
01341                                       kSchemaNamespacesLength);
01342       nsCOMPtr<nsIDOMElement> childElement;
01343       nsCOMPtr<nsIAtom> tagName;
01344 
01345       while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01346                                                 getter_AddRefs(tagName))) &&
01347              childElement) {
01348         if (tagName == nsSchemaAtoms::sSimpleType_atom) {
01349           nsCOMPtr<nsISchemaSimpleType> simpleType;
01350           
01351           rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
01352                                  getter_AddRefs(simpleType));
01353           if (NS_FAILED(rv)) {
01354             return rv;
01355           }
01356           schemaType = simpleType;
01357           break;
01358         }
01359         else if (tagName == nsSchemaAtoms::sComplexType_atom) {
01360           nsCOMPtr<nsISchemaComplexType> complexType;
01361           
01362           rv = ProcessComplexType(aErrorHandler, aSchema, childElement,
01363                                   getter_AddRefs(complexType));
01364           if (NS_FAILED(rv)) {
01365             return rv;
01366           }
01367           schemaType = complexType;
01368           break;
01369         }
01370       }
01371     }
01372 
01373     if (!schemaType) {
01374       nsAutoString ns;
01375       aElement->GetNamespaceURI(ns);
01376       rv = GetType(NS_LITERAL_STRING("anyType"),
01377                    ns,
01378                    getter_AddRefs(schemaType));
01379       if (NS_FAILED(rv)) {
01380         nsAutoString errorMsg;
01381         errorMsg.AppendLiteral("Failure processing schema, cannot find \'anyType\' ");
01382         errorMsg.AppendLiteral("placeholder type in namespace \"");
01383         errorMsg.Append(ns);
01384         errorMsg.AppendLiteral("\"");
01385 
01386         NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01387 
01388         return rv;
01389       }
01390     }
01391 
01392     rv = elementInst->SetType(schemaType);
01393     if (NS_FAILED(rv)) {
01394       return rv;
01395     }
01396   }
01397 
01398   *aSchemaElement = schemaElement;
01399   NS_ADDREF(*aSchemaElement);
01400 
01401   return NS_OK;
01402 }
01403 
01412 nsresult 
01413 nsSchemaLoader::ProcessComplexType(nsIWebServiceErrorHandler* aErrorHandler,
01414                                    nsSchema* aSchema, 
01415                                    nsIDOMElement* aElement,
01416                                    nsISchemaComplexType** aComplexType)
01417 {
01418   nsresult rv = NS_OK;
01419   nsCOMPtr<nsISchemaComplexType> complexType;
01420 
01421   nsAutoString abstract, name;
01422   aElement->GetAttribute(NS_LITERAL_STRING("abstract"), abstract);
01423   aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
01424 
01425   nsSchemaComplexType* typeInst;
01426   typeInst = new nsSchemaComplexType(aSchema, name, 
01427                                      abstract.EqualsLiteral("true"));
01428   if (!typeInst) {
01429     return NS_ERROR_OUT_OF_MEMORY;
01430   }
01431   complexType = typeInst;
01432 
01433   rv = typeInst->Init();
01434   NS_ENSURE_SUCCESS(rv, rv);
01435 
01436   nsChildElementIterator iterator(aElement, 
01437                                   kSchemaNamespaces, 
01438                                   kSchemaNamespacesLength);
01439   nsCOMPtr<nsIDOMElement> childElement;
01440   nsCOMPtr<nsIAtom> tagName;
01441 
01442   PRUint16 contentModel = nsISchemaComplexType::CONTENT_MODEL_EMPTY;
01443   PRUint16 derivation = nsISchemaComplexType::DERIVATION_SELF_CONTAINED;
01444   nsCOMPtr<nsISchemaType> baseType;
01445   nsCOMPtr<nsISchemaModelGroup> modelGroup;
01446 
01447   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01448                                             getter_AddRefs(tagName))) &&
01449          childElement) {
01450     if (tagName == nsSchemaAtoms::sSimpleContent_atom) {
01451       contentModel = nsISchemaComplexType::CONTENT_MODEL_SIMPLE;
01452 
01453       rv = ProcessSimpleContent(aErrorHandler, aSchema, childElement, typeInst,
01454                                 &derivation, getter_AddRefs(baseType));
01455       break;
01456     }
01457 
01458     if (tagName == nsSchemaAtoms::sComplexContent_atom) {
01459       rv = ProcessComplexContent(aErrorHandler, aSchema, childElement, typeInst,
01460                                  &contentModel, &derivation,
01461                                  getter_AddRefs(baseType));
01462       break;
01463     }
01464 
01465     if (tagName == nsSchemaAtoms::sModelGroup_atom ||
01466         tagName == nsSchemaAtoms::sAll_atom ||
01467         tagName == nsSchemaAtoms::sChoice_atom ||
01468         tagName == nsSchemaAtoms::sSequence_atom ||
01469         tagName == nsSchemaAtoms::sAttribute_atom ||
01470         tagName == nsSchemaAtoms::sAttributeGroup_atom ||
01471         tagName == nsSchemaAtoms::sAnyAttribute_atom) {
01472       rv = ProcessComplexTypeBody(aErrorHandler, aSchema,
01473                                   aElement, typeInst, nsnull,
01474                                   &contentModel);
01475       break;
01476     }
01477 
01478     if (tagName == nsSchemaAtoms::sAnnotation_atom) {
01479       // XXX: skipping for now
01480     }
01481     else {
01482       // Unexpected schema element
01483       nsAutoString elementName;
01484       rv = aElement->GetTagName(elementName);
01485       NS_ENSURE_SUCCESS(rv, rv);
01486       rv = NS_ERROR_UNEXPECTED;
01487 
01488       nsAutoString errorMsg;
01489       errorMsg.AppendLiteral("Failure processing schema, unexpected element \"");
01490       errorMsg.Append(elementName);
01491       errorMsg.AppendLiteral("\" in <complexType />, should be <simpleContent .../>");
01492       errorMsg.AppendLiteral(", <complexContent ../>, <annotation .../>");
01493 
01494       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01495 
01496       break;
01497     }
01498   }
01499 
01500   if (NS_FAILED(rv)) {
01501     return rv;
01502   }
01503 
01504   nsAutoString mixed;
01505   aElement->GetAttribute(NS_LITERAL_STRING("mixed"), mixed);
01506   if (mixed.EqualsLiteral("true")) {
01507     contentModel = nsISchemaComplexType::CONTENT_MODEL_MIXED;
01508   }
01509 
01510   typeInst->SetContentModel(contentModel);
01511   typeInst->SetDerivation(derivation, baseType);
01512 
01513   *aComplexType = complexType;
01514   NS_ADDREF(*aComplexType);
01515 
01516   return NS_OK;
01517 }
01518 
01519 void
01520 nsSchemaLoader::ConstructArrayName(nsISchemaType* aType,
01521                                    nsAString& aName)
01522 {
01523   nsAutoString typeName;
01524   
01525   aType->GetName(typeName);
01526   aName.Assign(NS_LITERAL_STRING("ArrayOf") + typeName);
01527 }
01528 
01529 nsresult
01530 nsSchemaLoader::ParseDimensions(nsSchema* aSchema,
01531                                 nsIDOMElement* aAttrElement,
01532                                 const nsAString& aStr,
01533                                 nsISchemaType* aBaseType,
01534                                 nsISchemaType** aArrayType,
01535                                 PRUint32* aDimension)
01536 {
01537   nsReadingIterator<PRUnichar> iter, done_reading;
01538   aStr.BeginReading(iter);
01539   aStr.EndReading(done_reading);
01540 
01541   PRUint32 dimension = 1;
01542   PRUnichar uc = *iter++;
01543   if (uc != PRUnichar('[')) {
01544     return NS_ERROR_UNEXPECTED;
01545   }
01546 
01547   while (iter != done_reading) {
01548     uc = *iter++;
01549     if (uc == PRUnichar(',')) {
01550       dimension++;
01551     }
01552     else if (uc == PRUnichar(']')) {
01553       break;
01554     }
01555   }
01556   *aDimension = dimension;
01557 
01558   while ((iter != done_reading) && (*iter == PRUnichar(' '))) {
01559     ++iter;
01560   }
01561 
01562   // If there's still more to go, then create an array type
01563   // based on the base and continue to parse
01564   if ((iter != done_reading) && (*iter == PRUnichar('['))) {
01565     nsAutoString name;
01566     nsCOMPtr<nsISchemaType> myArrayType;
01567     PRUint32 myDimension;
01568     
01569     nsresult rv = ParseDimensions(aSchema, aAttrElement,
01570                                   nsDependentSubstring(iter, done_reading),
01571                                   aBaseType, getter_AddRefs(myArrayType), 
01572                                   &myDimension);
01573     if (NS_FAILED(rv)) {
01574       return rv;
01575     }
01576 
01577     ConstructArrayName(myArrayType, name);
01578     nsSchemaComplexType* typeInst = new nsSchemaComplexType(aSchema,
01579                                                             name, 
01580                                                             PR_FALSE);
01581     if (!typeInst) {
01582       return NS_ERROR_OUT_OF_MEMORY;
01583     }
01584     nsCOMPtr<nsISchemaComplexType> complexType = typeInst;
01585 
01586     rv = typeInst->Init();
01587     NS_ENSURE_SUCCESS(rv, rv);
01588 
01589     nsCOMPtr<nsISchemaType> soapArray;
01590     rv = GetType(NS_LITERAL_STRING("Array"),
01591                  NS_LITERAL_STRING(NS_SOAP_1_2_ENCODING_NAMESPACE),
01592                  getter_AddRefs(soapArray));
01593     if (NS_FAILED(rv)) {
01594       return rv;
01595     }
01596 
01597     typeInst->SetContentModel(nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY);
01598     typeInst->SetDerivation(nsISchemaComplexType::DERIVATION_RESTRICTION_COMPLEX,
01599                             soapArray);
01600     typeInst->SetArrayInfo(myArrayType, myDimension);
01601 
01602     *aArrayType = typeInst;
01603   }
01604   else {
01605     *aArrayType = aBaseType;
01606   }
01607   NS_ADDREF(*aArrayType);
01608 
01609   return NS_OK;
01610 }
01611 
01612 nsresult
01613 nsSchemaLoader::ParseArrayType(nsSchema* aSchema,
01614                                nsIDOMElement* aAttrElement,
01615                                const nsAString& aStr,
01616                                nsISchemaType** aType,
01617                                PRUint32* aDimension)
01618 {
01619   PRInt32 offset;
01620   
01621   offset = aStr.FindChar(PRUnichar('['));
01622   if (offset == -1) {
01623     return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
01624   }
01625   nsDependentSubstring typeStr(aStr, 0, offset);
01626           
01627   nsCOMPtr<nsISchemaType> type;
01628   nsresult rv = GetNewOrUsedType(aSchema, aAttrElement, typeStr, 
01629                                  getter_AddRefs(type));
01630   if (NS_FAILED(rv)) {
01631     return rv;
01632   }
01633   
01634   nsDependentSubstring dimensionStr(aStr, offset, 
01635                                     aStr.Length() - offset);
01636   return ParseDimensions(aSchema, aAttrElement, dimensionStr, type,
01637                          aType, aDimension);
01638 }
01639 
01640 
01641 nsresult
01642 nsSchemaLoader::ProcessComplexTypeBody(nsIWebServiceErrorHandler* aErrorHandler,
01643                                        nsSchema* aSchema, 
01644                                        nsIDOMElement* aElement,
01645                                        nsSchemaComplexType* aComplexType,
01646                                        nsSchemaModelGroup* aSequence,
01647                                        PRUint16* aContentModel)
01648 {
01649   nsresult rv = NS_OK;
01650   nsChildElementIterator iterator(aElement, 
01651                                   kSchemaNamespaces, 
01652                                   kSchemaNamespacesLength);
01653   nsCOMPtr<nsIDOMElement> childElement;
01654   nsCOMPtr<nsIAtom> tagName;
01655 
01656   *aContentModel = nsISchemaComplexType::CONTENT_MODEL_EMPTY;
01657 
01658   nsCOMPtr<nsISchemaModelGroup> modelGroup;
01659   
01660   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01661                                             getter_AddRefs(tagName))) &&
01662          childElement) {
01663     if ((tagName == nsSchemaAtoms::sModelGroup_atom) ||
01664         (tagName == nsSchemaAtoms::sAll_atom) ||
01665         (tagName == nsSchemaAtoms::sChoice_atom) || 
01666         (tagName == nsSchemaAtoms::sSequence_atom)) {
01667 
01668       if (modelGroup) {
01669         // We shouldn't already have a model group
01670         nsAutoString elementName;
01671         nsresult rv = childElement->GetTagName(elementName);
01672         NS_ENSURE_SUCCESS(rv, rv);
01673 
01674         nsAutoString errorMsg;
01675         errorMsg.AppendLiteral("Failure processing schema, must have ");
01676         errorMsg.AppendLiteral("model group in <complexType .../>, ");
01677         errorMsg.AppendLiteral("unexpected element \"");
01678         errorMsg.Append(elementName);
01679         errorMsg.AppendLiteral("\"");
01680 
01681         NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
01682 
01683         return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
01684       }
01685       
01686       rv = ProcessModelGroup(aErrorHandler, aSchema, 
01687                              childElement, tagName,
01688                              aSequence, getter_AddRefs(modelGroup));
01689       if (NS_FAILED(rv)) {
01690         return rv;
01691       }
01692 
01693       PRUint32 particleCount;
01694       modelGroup->GetParticleCount(&particleCount);
01695       if (particleCount) {
01696         *aContentModel = nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY;
01697       }
01698       else {
01699         PRUint16 compositor;
01700         modelGroup->GetCompositor(&compositor);
01701         
01702         PRUint32 minOccurs;
01703         modelGroup->GetMinOccurs(&minOccurs);
01704         
01705         if ((compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) &&
01706             (minOccurs > 0)) {
01707           *aContentModel = nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY;
01708         }
01709       }
01710       
01711       if (aSequence) {
01712         // Check if we were collapsed
01713         if (modelGroup.get() != NS_STATIC_CAST(nsISchemaModelGroup*, 
01714                                                aSequence)) {
01715           rv = aSequence->AddParticle(modelGroup);
01716         }
01717       }
01718       else {
01719         rv = aComplexType->SetModelGroup(modelGroup);
01720       }
01721       if (NS_FAILED(rv)) {
01722         return rv;
01723       }        
01724     }
01725     else if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
01726              (tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
01727              (tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
01728       nsCOMPtr<nsISchemaAttributeComponent> attribute;
01729       
01730       rv = ProcessAttributeComponent(aErrorHandler, aSchema, 
01731                                      childElement, tagName,
01732                                      getter_AddRefs(attribute));
01733       if (NS_FAILED(rv)) {
01734         return rv;
01735       }
01736 
01737       rv = aComplexType->AddAttribute(attribute);
01738       if (NS_FAILED(rv)) {
01739         nsAutoString elementName;
01740         nsAutoString attributeName;
01741         nsresult rc = childElement->GetTagName(elementName);
01742         NS_ENSURE_SUCCESS(rc, rc);
01743 
01744         rc = attribute->GetName(attributeName);
01745         NS_ENSURE_SUCCESS(rc, rc);
01746 
01747         nsAutoString errorMsg;
01748         errorMsg.AppendLiteral("Failure processing schema, cannot process attribute \"");
01749         errorMsg.Append(attributeName);
01750         errorMsg.AppendLiteral("\" of element \"");
01751         errorMsg.Append(elementName);
01752         errorMsg.AppendLiteral("\"");
01753 
01754         NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01755 
01756         return rv;
01757       }
01758 
01759       // XXX WSDL ugliness making itself into schemas. Hopefully this
01760       // mechanism for specifying an array type in schemas will die
01761       // when the Schema WG address qualified names in attribute
01762       // default values.
01763       if (tagName == nsSchemaAtoms::sAttribute_atom) {
01764 #define NS_WSDL_NAMESPACE "http://schemas.xmlsoap.org/wsdl/"
01765         nsAutoString arrayType;
01766         childElement->GetAttributeNS(NS_LITERAL_STRING(NS_WSDL_NAMESPACE),
01767                                      NS_LITERAL_STRING("arrayType"), 
01768                                      arrayType);
01769         if (!arrayType.IsEmpty()) {
01770           nsCOMPtr<nsISchemaType> arraySchemaType;
01771           PRUint32 arrayDimension;
01772           rv = ParseArrayType(aSchema, 
01773                               childElement,
01774                               arrayType, 
01775                               getter_AddRefs(arraySchemaType),
01776                               &arrayDimension);
01777           if (NS_FAILED(rv)) {
01778             nsAutoString errorMsg;
01779             errorMsg.AppendLiteral("Failure processing schema, ");
01780             errorMsg.AppendLiteral("cannot process array type \"");
01781             errorMsg.Append(arrayType);
01782             errorMsg.AppendLiteral("\"");
01783 
01784             NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01785 
01786             return rv;
01787           }
01788 
01789           rv = aComplexType->SetArrayInfo(arraySchemaType, arrayDimension);
01790           if (NS_FAILED(rv)) {
01791             nsAutoString errorMsg;
01792             errorMsg.AppendLiteral("Failure processing schema, cannot set ");
01793             errorMsg.AppendLiteral("array information for array type \"");
01794             errorMsg.Append(arrayType);
01795             errorMsg.AppendLiteral("\"");
01796 
01797             NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01798 
01799             return rv;
01800           }
01801         }
01802       }
01803     }
01804   }
01805 
01806   return rv;
01807 }
01808 
01809 nsresult 
01810 nsSchemaLoader::ProcessSimpleContent(nsIWebServiceErrorHandler* aErrorHandler,
01811                                      nsSchema* aSchema, 
01812                                      nsIDOMElement* aElement,
01813                                      nsSchemaComplexType* aComplexType,
01814                                      PRUint16* aDerivation,
01815                                      nsISchemaType** aBaseType)
01816 {
01817   nsresult rv = NS_OK;
01818 
01819   nsCOMPtr<nsISchemaType> baseType;
01820 
01821   nsChildElementIterator iterator(aElement, 
01822                                   kSchemaNamespaces, 
01823                                   kSchemaNamespacesLength);
01824   nsCOMPtr<nsIDOMElement> childElement;
01825   nsCOMPtr<nsIAtom> tagName;
01826   
01827   // A simpleContent element must have children
01828   if (!iterator.HasChildNodes()) {
01829     nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing schema, "));
01830     errorMsg.AppendLiteral("<simpleContent .../> invalid structure, should contains ");
01831     errorMsg.AppendLiteral("<restriction .../> or <extension .../>");
01832 
01833     NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
01834 
01835     return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
01836   }
01837 
01838   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
01839                                             getter_AddRefs(tagName))) &&
01840          childElement) {       
01841     nsAutoString baseStr;
01842     if ((tagName == nsSchemaAtoms::sRestriction_atom) ||
01843         (tagName == nsSchemaAtoms::sExtension_atom)) {
01844       childElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
01845       if (baseStr.IsEmpty()) {
01846         nsAutoString elementName;
01847         rv = childElement->GetTagName(elementName);
01848         NS_ENSURE_SUCCESS(rv, rv);
01849 
01850         nsAutoString errorMsg;
01851         errorMsg.AppendLiteral("Failure processing schema, \"");
01852         errorMsg.Append(elementName);
01853         errorMsg.AppendLiteral("\" must have a \"base\" attribute in order ");
01854         errorMsg.AppendLiteral("to specify base type");
01855 
01856         NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
01857 
01858         return NS_ERROR_SCHEMA_MISSING_TYPE;
01859       }
01860       
01861       rv = GetNewOrUsedType(aSchema, childElement, baseStr, 
01862                             getter_AddRefs(baseType));
01863       if (NS_FAILED(rv)) {
01864         nsAutoString errorMsg;
01865         errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
01866         errorMsg.Append(baseStr);
01867         errorMsg.AppendLiteral("\"");
01868 
01869         NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01870 
01871         return rv;
01872       }
01873 
01874       nsCOMPtr<nsISchemaSimpleType> simpleBaseType;
01875       if (tagName == nsSchemaAtoms::sRestriction_atom) {
01876         *aDerivation = nsISchemaComplexType::DERIVATION_RESTRICTION_SIMPLE;
01877         rv = ProcessSimpleContentRestriction(aErrorHandler, aSchema, childElement,
01878                                              aComplexType, baseType,
01879                                              getter_AddRefs(simpleBaseType));
01880         if (NS_FAILED(rv)) {
01881           return rv;
01882         }
01883       }
01884       else {
01885         *aDerivation = nsISchemaComplexType::DERIVATION_EXTENSION_SIMPLE;
01886         
01887         nsCOMPtr<nsISchemaComplexType> complexBaseType(do_QueryInterface(baseType));
01888         if (complexBaseType) {
01889           // Copy over the attributes from the base type
01890           // XXX Should really be cloning
01891           PRUint32 attrIndex, attrCount;
01892           complexBaseType->GetAttributeCount(&attrCount);
01893           
01894           for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {
01895             nsCOMPtr<nsISchemaAttributeComponent> attribute;
01896             
01897             rv = complexBaseType->GetAttributeByIndex(attrIndex,
01898                                                       getter_AddRefs(attribute));
01899             if (NS_FAILED(rv)) {
01900               nsAutoString errorMsg;
01901               errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
01902               errorMsg.AppendLiteral("attributes from base type \"");
01903               errorMsg.Append(baseStr);
01904               errorMsg.AppendLiteral("\"");
01905 
01906               NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01907 
01908               return rv;
01909             }
01910 
01911             rv = aComplexType->AddAttribute(attribute);
01912             if (NS_FAILED(rv)) {
01913               nsAutoString errorMsg;
01914               errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
01915               errorMsg.AppendLiteral("attributes from base type \"");
01916               errorMsg.Append(baseStr);
01917               errorMsg.AppendLiteral("\"");
01918               
01919               NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
01920 
01921               return rv;
01922             }
01923           }
01924         }
01925         
01926         rv = ProcessSimpleContentExtension(aErrorHandler, aSchema, childElement,
01927                                            aComplexType, baseType,
01928                                            getter_AddRefs(simpleBaseType));
01929         if (NS_FAILED(rv)) {
01930           return rv;
01931         }
01932       }
01933 
01934       if (simpleBaseType) {
01935         rv = aComplexType->SetSimpleBaseType(simpleBaseType);
01936         if (NS_FAILED(rv)) {
01937           return rv;
01938         }
01939       }
01940       break;
01941     }
01942   }
01943 
01944   *aBaseType = baseType;
01945   NS_IF_ADDREF(*aBaseType);
01946 
01947   return NS_OK;
01948 }
01949 
01950 nsresult 
01951 nsSchemaLoader::ProcessSimpleContentRestriction(nsIWebServiceErrorHandler* aErrorHandler,
01952                                                 nsSchema* aSchema, 
01953                                                 nsIDOMElement* aElement,
01954                                                 nsSchemaComplexType* aComplexType, 
01955                                                 nsISchemaType* aBaseType,
01956                                                 nsISchemaSimpleType** aSimpleBaseType)
01957 {
01958   nsresult rv = NS_OK;
01959 
01960   nsChildElementIterator iterator(aElement, 
01961                                   kSchemaNamespaces, 
01962                                   kSchemaNamespacesLength);
01963   nsCOMPtr<nsIDOMElement> childElement;
01964   nsCOMPtr<nsIAtom> tagName;
01965   
01966   nsSchemaRestrictionType* restrictionInst;
01967   nsCOMPtr<nsISchemaSimpleType> simpleBase;
01968  
01969   restrictionInst = new nsSchemaRestrictionType(aSchema, EmptyString());
01970   if (!restrictionInst) {
01971     return NS_ERROR_OUT_OF_MEMORY;
01972   }
01973   simpleBase = restrictionInst;
01974   
01975   // The base type must actually be a complex type (which itself must
01976   // have a simple base type.
01977   nsCOMPtr<nsISchemaComplexType> complexBase = do_QueryInterface(aBaseType);
01978     if (!complexBase) {
01979     // if base type is a place holder, this is ok
01980     PRUint16 schemaType;
01981     aBaseType->GetSchemaType(&schemaType);
01982 
01983     if (schemaType == nsISchemaType::SCHEMA_TYPE_PLACEHOLDER) {
01984       simpleBase = do_QueryInterface(aBaseType);
01985     } else {
01986       nsAutoString baseStr;
01987       rv = aBaseType->GetName(baseStr);
01988       NS_ENSURE_SUCCESS(rv, rv);
01989 
01990       nsAutoString errorMsg;
01991       errorMsg.AppendLiteral("Failure processing schema, base type \"");
01992       errorMsg.Append(baseStr);
01993       errorMsg.AppendLiteral("\" of restriction must be a complex type ");
01994       errorMsg.AppendLiteral("which itself must be based on a simple type");
01995 
01996       NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
01997 
01998       return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
01999     }
02000   } else {
02001     nsCOMPtr<nsISchemaSimpleType> parentSimpleBase;
02002     complexBase->GetSimpleBaseType(getter_AddRefs(parentSimpleBase));
02003   
02004     if (parentSimpleBase) {
02005       rv = restrictionInst->SetBaseType(parentSimpleBase);
02006       if (NS_FAILED(rv)) {
02007         return rv;
02008       }
02009     }
02010   }
02011 
02012   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02013                                             getter_AddRefs(tagName))) &&
02014          childElement) {       
02015     if (tagName == nsSchemaAtoms::sSimpleType_atom) {
02016       nsCOMPtr<nsISchemaSimpleType> simpleType;
02017       
02018       rv = ProcessSimpleType(aErrorHandler, aSchema, childElement, 
02019                              getter_AddRefs(simpleType));
02020       if (NS_FAILED(rv)) {
02021         return rv;
02022       }
02023 
02024       rv = restrictionInst->SetBaseType(simpleType);
02025       if (NS_FAILED(rv)) {
02026         return rv;
02027       }
02028     }
02029     else if ((tagName == nsSchemaAtoms::sMinExclusive_atom) ||
02030              (tagName == nsSchemaAtoms::sMinInclusive_atom) ||
02031              (tagName == nsSchemaAtoms::sMaxExclusive_atom) ||
02032              (tagName == nsSchemaAtoms::sMaxInclusive_atom) ||
02033              (tagName == nsSchemaAtoms::sTotalDigits_atom) ||
02034              (tagName == nsSchemaAtoms::sFractionDigits_atom) ||
02035              (tagName == nsSchemaAtoms::sLength_atom) ||
02036              (tagName == nsSchemaAtoms::sMinLength_atom) ||
02037              (tagName == nsSchemaAtoms::sMaxLength_atom) ||
02038              (tagName == nsSchemaAtoms::sEnumeration_atom) ||
02039              (tagName == nsSchemaAtoms::sWhiteSpace_atom) ||
02040              (tagName == nsSchemaAtoms::sPattern_atom)) {
02041       nsCOMPtr<nsISchemaFacet> facet;
02042       
02043       rv = ProcessFacet(aErrorHandler, aSchema, childElement, 
02044                         tagName, getter_AddRefs(facet));
02045       if (NS_FAILED(rv)) {
02046         return rv;
02047       }
02048 
02049       rv = restrictionInst->AddFacet(facet);
02050       if (NS_FAILED(rv)) {
02051         return rv;
02052       }
02053     }
02054     else if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
02055              (tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
02056              (tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
02057       nsCOMPtr<nsISchemaAttributeComponent> attribute;
02058       
02059       rv = ProcessAttributeComponent(aErrorHandler, aSchema,
02060                                      childElement, tagName,
02061                                      getter_AddRefs(attribute));
02062       if (NS_FAILED(rv)) {
02063         return rv;
02064       }
02065 
02066       rv = aComplexType->AddAttribute(attribute);
02067       if (NS_FAILED(rv)) {
02068         return rv;
02069       }
02070     }
02071   }
02072   
02073   *aSimpleBaseType = simpleBase;
02074   NS_IF_ADDREF(*aSimpleBaseType);
02075 
02076   return NS_OK;
02077 }
02078  
02079 nsresult 
02080 nsSchemaLoader::ProcessSimpleContentExtension(nsIWebServiceErrorHandler* aErrorHandler,
02081                                               nsSchema* aSchema, 
02082                                               nsIDOMElement* aElement,
02083                                               nsSchemaComplexType* aComplexType,
02084                                               nsISchemaType* aBaseType,
02085                                               nsISchemaSimpleType** aSimpleBaseType)
02086 {
02087   nsresult rv = NS_OK;
02088 
02089   nsChildElementIterator iterator(aElement, 
02090                                   kSchemaNamespaces, 
02091                                   kSchemaNamespacesLength);
02092   nsCOMPtr<nsIDOMElement> childElement;
02093   nsCOMPtr<nsIAtom> tagName;
02094 
02095   // If the base type is a complex type, it must itself have a simple
02096   // base type
02097   nsCOMPtr<nsISchemaComplexType> complexBase = do_QueryInterface(aBaseType);
02098   if (complexBase) {
02099     complexBase->GetSimpleBaseType(aSimpleBaseType);
02100   }
02101   else {
02102     aBaseType->QueryInterface(NS_GET_IID(nsISchemaSimpleType),
02103                               (void**)aSimpleBaseType);
02104   }
02105 
02106   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02107                                             getter_AddRefs(tagName))) &&
02108          childElement) {       
02109     if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
02110         (tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
02111         (tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
02112       nsCOMPtr<nsISchemaAttributeComponent> attribute;
02113       
02114       rv = ProcessAttributeComponent(aErrorHandler, aSchema, 
02115                                      childElement, tagName,
02116                                      getter_AddRefs(attribute));
02117       if (NS_FAILED(rv)) {
02118         return rv;
02119       }
02120       
02121       rv = aComplexType->AddAttribute(attribute);
02122       if (NS_FAILED(rv)) {
02123         return rv;
02124       }
02125     }
02126   }
02127   
02128   return NS_OK;
02129 }
02130  
02131 nsresult 
02132 nsSchemaLoader::ProcessComplexContent(nsIWebServiceErrorHandler* aErrorHandler,
02133                                       nsSchema* aSchema, 
02134                                       nsIDOMElement* aElement,
02135                                       nsSchemaComplexType* aComplexType,
02136                                       PRUint16* aContentModel,
02137                                       PRUint16* aDerivation,
02138                                       nsISchemaType** aBaseType)
02139 {
02140   nsresult rv = NS_OK;
02141 
02142   nsCOMPtr<nsISchemaType> baseType;
02143   nsChildElementIterator iterator(aElement, 
02144                                   kSchemaNamespaces, 
02145                                   kSchemaNamespacesLength);
02146   nsCOMPtr<nsIDOMElement> childElement;
02147   nsCOMPtr<nsIAtom> tagName;
02148   
02149   // A complexContent element must have children
02150   if (!iterator.HasChildNodes()) {
02151     nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing schema, "));
02152     errorMsg.AppendLiteral("<complexContent .../> must contains ");
02153     errorMsg.AppendLiteral("<restriction .../> or <extension .../>");
02154     NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
02155 
02156     return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
02157   }
02158   
02159   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02160                                             getter_AddRefs(tagName))) &&
02161          childElement) {       
02162     nsAutoString baseStr;
02163     if ((tagName == nsSchemaAtoms::sRestriction_atom) ||
02164         (tagName == nsSchemaAtoms::sExtension_atom)) {
02165       childElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
02166       if (baseStr.IsEmpty()) {
02167         nsAutoString errorMsg;
02168         errorMsg.AppendLiteral("Failure processing schema, ");
02169         
02170         if (tagName == nsSchemaAtoms::sRestriction_atom) {
02171           errorMsg.AppendLiteral("restriction");
02172         }
02173         else {
02174           errorMsg.AppendLiteral("extension");
02175         }
02176         
02177         errorMsg.AppendLiteral(" must have a \"base\" attribute in order to ");
02178         errorMsg.AppendLiteral("specify base type");
02179         
02180         NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
02181         
02182         return NS_ERROR_SCHEMA_MISSING_TYPE;
02183       }
02184       
02185       rv = GetNewOrUsedType(aSchema, childElement, baseStr, 
02186                             getter_AddRefs(baseType));
02187       if (NS_FAILED(rv)) {
02188         nsAutoString errorMsg;
02189         errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
02190         errorMsg.Append(baseStr);
02191         errorMsg.AppendLiteral("\"");
02192 
02193         NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02194 
02195         return rv;
02196       }
02197 
02198       nsCOMPtr<nsISchemaComplexType> complexBaseType(do_QueryInterface(baseType));
02199 
02200       if (tagName == nsSchemaAtoms::sRestriction_atom) {
02201         *aDerivation = nsISchemaComplexType::DERIVATION_RESTRICTION_COMPLEX;
02202         rv = ProcessComplexTypeBody(aErrorHandler, aSchema, childElement,
02203                                     aComplexType, nsnull, aContentModel);
02204       }
02205       else {
02206         *aDerivation = nsISchemaComplexType::DERIVATION_EXTENSION_COMPLEX;
02207         
02208         nsCOMPtr<nsISchemaModelGroup> sequence;
02209         nsSchemaModelGroup* sequenceInst = nsnull;
02210         if (complexBaseType) {
02211           // XXX Should really be cloning
02212           nsCOMPtr<nsISchemaModelGroup> baseGroup;
02213           rv = complexBaseType->GetModelGroup(getter_AddRefs(baseGroup));
02214           if (NS_FAILED(rv)) {
02215             nsAutoString errorMsg;
02216             errorMsg.AppendLiteral("Failure processing schema, extension for type \"");
02217             errorMsg.Append(baseStr);
02218             errorMsg.AppendLiteral("\" does not contains any model group");
02219             errorMsg.AppendLiteral("such as <all>, <choice>, <sequence>, or <group>");
02220 
02221             NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02222 
02223             return rv;
02224           }
02225           
02226           if (baseGroup) {
02227             // Create a new model group that's going to be the a sequence
02228             // of the base model group and the content below
02229             sequenceInst = new nsSchemaModelGroup(aSchema, EmptyString());
02230             if (!sequenceInst) {
02231               return NS_ERROR_OUT_OF_MEMORY;
02232             }
02233             sequence = sequenceInst;
02234 
02235             PRUint16 compositor;
02236             baseGroup->GetCompositor(&compositor);
02237 
02238             PRUint32 minOccurs, maxOccurs;
02239             baseGroup->GetMinOccurs(&minOccurs);
02240             baseGroup->GetMaxOccurs(&maxOccurs);
02241 
02242             // If the base group also a sequence, we can collapse the 
02243             // two sequences.
02244             if ((compositor == nsISchemaModelGroup::COMPOSITOR_SEQUENCE) &&
02245                 (minOccurs == 1) && (maxOccurs == 1)) {
02246               PRUint32 pIndex, pCount;
02247               baseGroup->GetParticleCount(&pCount);
02248               for (pIndex = 0; pIndex < pCount; pIndex++) {
02249                 nsCOMPtr<nsISchemaParticle> particle;
02250                 
02251                 rv = baseGroup->GetParticle(pIndex, getter_AddRefs(particle));
02252                 if (NS_FAILED(rv)) {
02253                   nsAutoString errorMsg;
02254                   errorMsg.AppendLiteral("Failure processing schema, failure ");
02255                   errorMsg.AppendLiteral("processing model group for extension ");
02256                   errorMsg.AppendLiteral("of type \"");
02257                   errorMsg.Append(baseStr);
02258                   errorMsg.AppendLiteral("\"");
02259 
02260                   NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02261 
02262                   return rv;
02263                 }
02264                 
02265                 rv = sequenceInst->AddParticle(particle);
02266                 if (NS_FAILED(rv)) {
02267                   nsAutoString errorMsg;
02268                   errorMsg.AppendLiteral("Failure processing schema, failure ");
02269                   errorMsg.AppendLiteral("processing model group for extension ");
02270                   errorMsg.AppendLiteral("of type \"");
02271                   errorMsg.Append(baseStr);
02272                   errorMsg.AppendLiteral("\"");
02273 
02274                   NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02275 
02276                   return rv;
02277                 }
02278               }
02279             }
02280             else {
02281               sequenceInst->AddParticle(baseGroup);
02282             }
02283             
02284             aComplexType->SetModelGroup(sequence);
02285           }
02286         }
02287         
02288         PRUint16 explicitContent;
02289         rv = ProcessComplexTypeBody(aErrorHandler, aSchema, childElement,
02290                                     aComplexType, sequenceInst,
02291                                     &explicitContent);
02292         if (NS_FAILED(rv)) {
02293           return rv;
02294         }
02295         // If the explicit content is empty, get the content type
02296         // from the base
02297         if ((explicitContent == nsISchemaComplexType::CONTENT_MODEL_EMPTY) &&
02298             complexBaseType) {
02299           complexBaseType->GetContentModel(aContentModel);
02300         }
02301         else {
02302           *aContentModel = explicitContent;
02303         }
02304       }
02305 
02306       // Copy over the attributes from the base type
02307       // XXX Should really be cloning
02308       if (complexBaseType) {
02309         PRUint32 attrIndex, attrCount;
02310         complexBaseType->GetAttributeCount(&attrCount);
02311 
02312         for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {
02313           nsCOMPtr<nsISchemaAttributeComponent> attribute;
02314 
02315           rv = complexBaseType->GetAttributeByIndex(attrIndex,
02316                                                     getter_AddRefs(attribute));
02317           if (NS_FAILED(rv)) {
02318             nsAutoString errorMsg;
02319             errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
02320             errorMsg.AppendLiteral("attributes from base type \"");
02321             errorMsg.Append(baseStr);
02322             errorMsg.AppendLiteral("\"");
02323 
02324             NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02325 
02326             return rv;
02327           }
02328 
02329           rv = aComplexType->AddAttribute(attribute);
02330           if (NS_FAILED(rv)) {
02331             nsAutoString errorMsg;
02332             errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
02333             errorMsg.AppendLiteral("attributes from base type \"");
02334             errorMsg.Append(baseStr);
02335             errorMsg.AppendLiteral("\"");
02336 
02337             NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02338 
02339             return rv;
02340           }
02341         }
02342       }
02343 
02344       break;
02345     }
02346   }
02347 
02348   nsAutoString mixed;
02349   aElement->GetAttribute(NS_LITERAL_STRING("mixed"), mixed);
02350   if (mixed.EqualsLiteral("true")) {
02351     *aContentModel = nsISchemaComplexType::CONTENT_MODEL_MIXED;
02352   }
02353 
02354   *aBaseType = baseType;
02355   NS_IF_ADDREF(*aBaseType);
02356 
02357   return NS_OK;
02358 }
02359 
02360 nsresult 
02361 nsSchemaLoader::ProcessSimpleType(nsIWebServiceErrorHandler* aErrorHandler,
02362                                   nsSchema* aSchema, 
02363                                   nsIDOMElement* aElement,
02364                                   nsISchemaSimpleType** aSimpleType)
02365 {
02366   nsresult rv = NS_OK;
02367 
02368   nsAutoString name;
02369   aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
02370 
02371   nsChildElementIterator iterator(aElement, 
02372                                   kSchemaNamespaces, 
02373                                   kSchemaNamespacesLength);
02374   nsCOMPtr<nsIDOMElement> childElement;
02375   nsCOMPtr<nsIAtom> tagName;
02376 
02377   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02378                                             getter_AddRefs(tagName))) &&
02379          childElement) {
02380     if (tagName == nsSchemaAtoms::sRestriction_atom) {
02381       rv = ProcessSimpleTypeRestriction(aErrorHandler, aSchema, childElement,
02382                                         name, aSimpleType);
02383       break;
02384     }
02385     else if (tagName == nsSchemaAtoms::sList_atom) {
02386       rv = ProcessSimpleTypeList(aErrorHandler, aSchema, childElement,
02387                                  name, aSimpleType);
02388       break;
02389     }
02390     else if (tagName == nsSchemaAtoms::sUnion_atom) {
02391       rv = ProcessSimpleTypeUnion(aErrorHandler, aSchema, childElement,
02392                                   name, aSimpleType);
02393       break;
02394     }
02395   }  
02396   
02397   return rv;
02398 }
02399 
02400 nsresult 
02401 nsSchemaLoader::ProcessSimpleTypeRestriction(nsIWebServiceErrorHandler* aErrorHandler,
02402                                              nsSchema* aSchema, 
02403                                              nsIDOMElement* aElement,
02404                                              const nsAString& aName,
02405                                              nsISchemaSimpleType** aSimpleType)
02406 {
02407   nsresult rv = NS_OK;
02408 
02409   nsSchemaRestrictionType* restrictionInst;
02410   nsCOMPtr<nsISchemaSimpleType> restriction;
02411  
02412   restrictionInst = new nsSchemaRestrictionType(aSchema, aName);
02413   if (!restrictionInst) {
02414     return NS_ERROR_OUT_OF_MEMORY;
02415   }
02416   restriction = restrictionInst;
02417 
02418   nsCOMPtr<nsISchemaType> baseType;
02419   nsAutoString baseStr;
02420   aElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
02421   if (!baseStr.IsEmpty()) {
02422     rv = GetNewOrUsedType(aSchema, aElement, baseStr, 
02423                           getter_AddRefs(baseType));
02424     if (NS_FAILED(rv)) {
02425       nsAutoString errorMsg;
02426       errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
02427       errorMsg.Append(baseStr);
02428       errorMsg.AppendLiteral("\"");
02429 
02430       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02431 
02432       return rv;
02433     }
02434 
02435     nsCOMPtr<nsISchemaSimpleType> simpleBase(do_QueryInterface(baseType));
02436     if (!simpleBase) {
02437       nsAutoString errorMsg;
02438       errorMsg.AppendLiteral("Failure processing schema, base type \"");
02439       errorMsg.Append(baseStr);
02440       errorMsg.AppendLiteral("\" should be a simple type");
02441 
02442       NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
02443 
02444       return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
02445     }
02446     rv = restrictionInst->SetBaseType(simpleBase);
02447   }
02448 
02449   nsChildElementIterator iterator(aElement, 
02450                                   kSchemaNamespaces, 
02451                                   kSchemaNamespacesLength);
02452   nsCOMPtr<nsIDOMElement> childElement;
02453   nsCOMPtr<nsIAtom> tagName;
02454 
02455   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02456                                             getter_AddRefs(tagName))) &&
02457          childElement) {
02458     if ((tagName == nsSchemaAtoms::sSimpleType_atom) &&
02459         !baseType) {
02460       nsCOMPtr<nsISchemaSimpleType> simpleType;
02461       
02462       rv = ProcessSimpleType(aErrorHandler, aSchema, childElement, 
02463                              getter_AddRefs(simpleType));
02464       if (NS_FAILED(rv)) {
02465         return rv;
02466       }
02467 
02468       rv = restrictionInst->SetBaseType(simpleType);
02469       if (NS_FAILED(rv)) {
02470         return rv;
02471       }
02472       baseType = simpleType;
02473     }
02474     else if ((tagName == nsSchemaAtoms::sMinExclusive_atom) ||
02475              (tagName == nsSchemaAtoms::sMinInclusive_atom) ||
02476              (tagName == nsSchemaAtoms::sMaxExclusive_atom) ||
02477              (tagName == nsSchemaAtoms::sMaxInclusive_atom) ||
02478              (tagName == nsSchemaAtoms::sTotalDigits_atom) ||
02479              (tagName == nsSchemaAtoms::sFractionDigits_atom) ||
02480              (tagName == nsSchemaAtoms::sLength_atom) ||
02481              (tagName == nsSchemaAtoms::sMinLength_atom) ||
02482              (tagName == nsSchemaAtoms::sMaxLength_atom) ||
02483              (tagName == nsSchemaAtoms::sEnumeration_atom) ||
02484              (tagName == nsSchemaAtoms::sWhiteSpace_atom) ||
02485              (tagName == nsSchemaAtoms::sPattern_atom)) {
02486       nsCOMPtr<nsISchemaFacet> facet;
02487       
02488       rv = ProcessFacet(aErrorHandler, aSchema, childElement, 
02489                         tagName, getter_AddRefs(facet));
02490       if (NS_FAILED(rv)) {
02491         return rv;
02492       }
02493 
02494       rv = restrictionInst->AddFacet(facet);
02495       if (NS_FAILED(rv)) {
02496         return rv;
02497       }
02498     }
02499   }
02500 
02501   *aSimpleType = restriction;
02502   NS_ADDREF(*aSimpleType);
02503 
02504   return NS_OK;
02505 }
02506  
02507 nsresult 
02508 nsSchemaLoader::ProcessSimpleTypeList(nsIWebServiceErrorHandler* aErrorHandler,
02509                                       nsSchema* aSchema, 
02510                                       nsIDOMElement* aElement,
02511                                       const nsAString& aName,
02512                                       nsISchemaSimpleType** aSimpleType)
02513 {
02514   nsresult rv = NS_OK;
02515 
02516   nsSchemaListType* listInst;
02517   nsCOMPtr<nsISchemaSimpleType> list;
02518 
02519   listInst = new nsSchemaListType(aSchema, aName);
02520   if (!listInst) {
02521     return NS_ERROR_OUT_OF_MEMORY;
02522   }
02523   list = listInst;
02524 
02525   nsAutoString itemTypeStr;
02526   aElement->GetAttribute(NS_LITERAL_STRING("itemType"), itemTypeStr);
02527 
02528   nsCOMPtr<nsISchemaSimpleType> itemType;
02529   if (!itemTypeStr.IsEmpty()) {
02530     nsCOMPtr<nsISchemaType> type;
02531     rv = GetNewOrUsedType(aSchema, aElement, itemTypeStr, 
02532                           getter_AddRefs(type));
02533     if (NS_FAILED(rv)) {
02534       nsAutoString errorMsg;
02535       errorMsg.AppendLiteral("Failure processing schema, unknown item type \"");
02536       errorMsg.Append(itemTypeStr);
02537       errorMsg.AppendLiteral("\"");
02538 
02539       NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02540 
02541       return rv;
02542     }
02543 
02544     itemType = do_QueryInterface(type);
02545   }
02546   else {
02547     nsChildElementIterator iterator(aElement, 
02548                                     kSchemaNamespaces, 
02549                                     kSchemaNamespacesLength);
02550     nsCOMPtr<nsIDOMElement> childElement;
02551     nsCOMPtr<nsIAtom> tagName;
02552     
02553     while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02554                                               getter_AddRefs(tagName))) &&
02555            childElement) {
02556       if (tagName == nsSchemaAtoms::sSimpleType_atom) {
02557         rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
02558                                getter_AddRefs(itemType));
02559         if (NS_FAILED(rv)) {
02560           return rv;
02561         }
02562         break;
02563       }
02564     }
02565   }
02566 
02567   if (!itemType) {
02568     nsAutoString errorMsg;
02569     errorMsg.AppendLiteral("Failure processing schema, no item type ");
02570     errorMsg.AppendLiteral("for simple type \"");
02571     errorMsg.Append(aName);
02572     errorMsg.AppendLiteral("\"");
02573 
02574     NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
02575 
02576     return NS_ERROR_SCHEMA_MISSING_TYPE;
02577   }
02578   listInst->SetListType(itemType);
02579 
02580   *aSimpleType = list;
02581   NS_ADDREF(*aSimpleType);
02582 
02583   return NS_OK;
02584 }
02585 
02586 nsresult 
02587 nsSchemaLoader::ProcessSimpleTypeUnion(nsIWebServiceErrorHandler* aErrorHandler, 
02588                                        nsSchema* aSchema, 
02589                                        nsIDOMElement* aElement,
02590                                        const nsAString& aName,
02591                                        nsISchemaSimpleType** aSimpleType)
02592 {
02593   nsresult rv = NS_OK;
02594 
02595   nsSchemaUnionType* unionInst;
02596   nsCOMPtr<nsISchemaSimpleType> unionType;
02597 
02598   unionInst = new nsSchemaUnionType(aSchema, aName);
02599   if (!unionInst) {
02600     return NS_ERROR_OUT_OF_MEMORY;
02601   }
02602   unionType = unionInst;
02603 
02604   nsCOMPtr<nsISchemaSimpleType> memberType;
02605   nsAutoString memberTypes;
02606   aElement->GetAttribute(NS_LITERAL_STRING("memberTypes"), memberTypes);
02607   if (!memberTypes.IsEmpty()) {
02608     nsReadingIterator<PRUnichar> begin, end, tokenEnd;
02609 
02610     memberTypes.BeginReading(tokenEnd);
02611     memberTypes.EndReading(end);
02612 
02613     while (tokenEnd != end) {
02614       nsAutoString typeStr;
02615       begin = tokenEnd;
02616       if (FindCharInReadable(PRUnichar(' '), tokenEnd, end)) {
02617         CopyUnicodeTo(begin, tokenEnd, typeStr);
02618         ++tokenEnd;
02619       }
02620       else {
02621         CopyUnicodeTo(begin, end, typeStr);
02622       }
02623 
02624       nsCOMPtr<nsISchemaType> type;
02625       rv = GetNewOrUsedType(aSchema, aElement, typeStr, 
02626                             getter_AddRefs(type));
02627       if (NS_FAILED(rv)) {
02628         nsAutoString errorMsg;
02629         errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
02630         errorMsg.Append(typeStr);
02631         errorMsg.AppendLiteral("\"");
02632 
02633         NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
02634 
02635         return rv;
02636       }
02637       
02638       memberType = do_QueryInterface(type);
02639       if (!memberType) {
02640         nsAutoString errorMsg;
02641         errorMsg.AppendLiteral("Failure processing schema, invalid member type \"");
02642         errorMsg.Append(typeStr);
02643         errorMsg.AppendLiteral("\" for union about simple type \"");
02644         errorMsg.Append(aName);
02645         errorMsg.AppendLiteral("\"");
02646 
02647         NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
02648 
02649         return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
02650       }
02651 
02652       rv = unionInst->AddUnionType(memberType);
02653       if (NS_FAILED(rv)) {
02654         return rv;
02655       }            
02656     }
02657   }
02658   
02659   nsChildElementIterator iterator(aElement, 
02660                                   kSchemaNamespaces, 
02661                                   kSchemaNamespacesLength);
02662   nsCOMPtr<nsIDOMElement> childElement;
02663   nsCOMPtr<nsIAtom> tagName;
02664   
02665   while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02666                                             getter_AddRefs(tagName))) &&
02667          childElement) {
02668     if (tagName == nsSchemaAtoms::sSimpleType_atom) {
02669       rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
02670                              getter_AddRefs(memberType));
02671       if (NS_FAILED(rv)) {
02672         return rv;
02673       }
02674       
02675       rv = unionInst->AddUnionType(memberType);
02676       if (NS_FAILED(rv)) {
02677         return rv;
02678       }      
02679     }
02680   }
02681 
02682   *aSimpleType = unionType;
02683   NS_ADDREF(*aSimpleType);
02684 
02685   return NS_OK;
02686 }
02687 
02688 nsresult 
02689 nsSchemaLoader::ProcessModelGroup(nsIWebServiceErrorHandler* aErrorHandler,
02690                                   nsSchema* aSchema, 
02691                                   nsIDOMElement* aElement,
02692                                   nsIAtom* aTagName,
02693                                   nsSchemaModelGroup* aParentSequence,
02694                                   nsISchemaModelGroup** aModelGroup)
02695 {
02696   nsresult rv = NS_OK;
02697 
02698   nsCOMPtr<nsISchemaModelGroup> modelGroup;
02699   PRUint32 minOccurs, maxOccurs;
02700   GetMinAndMax(aElement, &minOccurs, &maxOccurs);
02701 
02702   // Check for a ref attribute
02703   nsAutoString ref, refNS;
02704   aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
02705   
02706   if ((aTagName == nsSchemaAtoms::sModelGroup_atom) &&
02707       !ref.IsEmpty()) {
02708 
02709     rv = ParseNameAndNS(ref, aElement, ref, refNS);
02710     NS_ENSURE_SUCCESS(rv, rv);
02711 
02712     nsSchemaModelGroupRef* modelGroupRef = new nsSchemaModelGroupRef(aSchema, 
02713                                                                      ref,
02714                                                                      refNS);
02715     if (!modelGroupRef) {
02716       return NS_ERROR_OUT_OF_MEMORY;
02717     }
02718     modelGroup = modelGroupRef;
02719     
02720     modelGroupRef->SetMinOccurs(minOccurs);
02721     modelGroupRef->SetMaxOccurs(maxOccurs);
02722   }
02723   else {
02724     nsAutoString name;
02725     aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
02726 
02727     nsChildElementIterator iterator(aElement, 
02728                                     kSchemaNamespaces, 
02729                                     kSchemaNamespacesLength);
02730     nsCOMPtr<nsIDOMElement> childElement;
02731     nsCOMPtr<nsIAtom> tagName = aTagName;
02732 
02733     // If this is a group element, find the first compositor
02734     // child and continue with that.
02735     if (aTagName == nsSchemaAtoms::sModelGroup_atom) {
02736       while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02737                                                 getter_AddRefs(tagName))) &&
02738              childElement) {
02739         if ((tagName == nsSchemaAtoms::sAll_atom) ||
02740             (tagName == nsSchemaAtoms::sChoice_atom) ||
02741             (tagName == nsSchemaAtoms::sSequence_atom)) {
02742           iterator.SetElement(childElement);
02743           break;
02744         }
02745       }
02746     }
02747 
02748     nsSchemaModelGroup* modelGroupInst;
02749 
02750     // If we have a parent sequence and we're a sequence that
02751     // only appears once, then collapse us.
02752     if (aParentSequence && 
02753         (tagName == nsSchemaAtoms::sSequence_atom) &&
02754         (minOccurs == 1) && (maxOccurs == 1)) {
02755       modelGroupInst = aParentSequence;
02756       modelGroup = modelGroupInst;
02757     }
02758     else {
02759       modelGroupInst = new nsSchemaModelGroup(aSchema, name);
02760       if (!modelGroupInst) {
02761         return NS_ERROR_OUT_OF_MEMORY;
02762       }
02763       modelGroup = modelGroupInst;
02764       
02765       modelGroupInst->SetMinOccurs(minOccurs);
02766       modelGroupInst->SetMaxOccurs(maxOccurs);
02767 
02768 
02769       if (tagName == nsSchemaAtoms::sAll_atom) {
02770         modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_ALL);
02771       }
02772       else if (tagName == nsSchemaAtoms::sChoice_atom) {
02773         modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_CHOICE);
02774       }
02775       else if (tagName == nsSchemaAtoms::sSequence_atom) {
02776         modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_SEQUENCE);
02777       }
02778     }
02779     
02780     while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02781                                               getter_AddRefs(tagName))) &&
02782            childElement) {
02783       if (tagName != nsSchemaAtoms::sAnnotation_atom) {
02784         nsCOMPtr<nsISchemaParticle> particle;
02785 
02786         rv = ProcessParticle(aErrorHandler, aSchema, childElement,
02787                              tagName, getter_AddRefs(particle));
02788         if (NS_FAILED(rv)) {
02789           return rv;
02790         }
02791 
02792         rv = modelGroupInst->AddParticle(particle);
02793         if (NS_FAILED(rv)) {
02794           return rv;
02795         }
02796       }
02797     }   
02798   }
02799 
02800   *aModelGroup = modelGroup;
02801   NS_ADDREF(*aModelGroup);
02802 
02803   return NS_OK;
02804 }
02805 
02806 nsresult 
02807 nsSchemaLoader::ProcessParticle(nsIWebServiceErrorHandler* aErrorHandler,
02808                                 nsSchema* aSchema, 
02809                                 nsIDOMElement* aElement,
02810                                 nsIAtom* aTagName,
02811                                 nsISchemaParticle** aParticle)
02812 {
02813   nsresult rv;
02814 
02815   if (aTagName == nsSchemaAtoms::sElement_atom) {
02816     nsCOMPtr<nsISchemaElement> element;
02817 
02818     rv = ProcessElement(aErrorHandler, aSchema, aElement, getter_AddRefs(element));
02819     if (NS_FAILED(rv)) {
02820       return rv;
02821     }
02822     *aParticle = element;
02823     NS_IF_ADDREF(*aParticle);
02824   }
02825   else if ((aTagName == nsSchemaAtoms::sModelGroup_atom) ||
02826            (aTagName == nsSchemaAtoms::sChoice_atom) ||
02827            (aTagName == nsSchemaAtoms::sSequence_atom)) {
02828     nsCOMPtr<nsISchemaModelGroup> modelGroup;
02829     
02830     rv = ProcessModelGroup(aErrorHandler, aSchema, aElement, 
02831                            aTagName, nsnull, getter_AddRefs(modelGroup));
02832     if (NS_FAILED(rv)) {
02833       return rv;
02834     }
02835     *aParticle = modelGroup;
02836     NS_IF_ADDREF(*aParticle);
02837   }
02838   else if (aTagName == nsSchemaAtoms::sAny_atom) {
02839 
02840     nsCOMPtr<nsISchemaParticle> anyParticle;
02841     nsSchemaAnyParticle* anyParticleInst = new nsSchemaAnyParticle(aSchema);
02842     if (!anyParticleInst) {
02843       return NS_ERROR_OUT_OF_MEMORY;
02844     }
02845     anyParticle = anyParticleInst;
02846 
02847     PRUint32 minOccurs, maxOccurs;
02848     GetMinAndMax(aElement, &minOccurs, &maxOccurs);
02849     anyParticleInst->SetMinOccurs(minOccurs);
02850     anyParticleInst->SetMaxOccurs(maxOccurs);
02851 
02852     PRUint16 process;
02853     GetProcess(aElement, &process);
02854     anyParticleInst->SetProcess(process);
02855 
02856     nsAutoString namespaceStr;
02857     aElement->GetAttribute(NS_LITERAL_STRING("namespace"), namespaceStr);
02858     anyParticleInst->SetNamespace(namespaceStr);
02859 
02860     *aParticle = anyParticle;
02861     NS_ADDREF(*aParticle);
02862   
02863   }
02864 
02865   return NS_OK;
02866 }
02867 
02868 nsresult 
02869 nsSchemaLoader::ProcessAttributeComponent(nsIWebServiceErrorHandler* aErrorHandler,
02870                                           nsSchema* aSchema, 
02871                                           nsIDOMElement* aElement,
02872                                           nsIAtom* aTagName,
02873                                           nsISchemaAttributeComponent** aAttribute)
02874 {
02875   nsresult rv;
02876 
02877   if (aTagName == nsSchemaAtoms::sAttribute_atom) {
02878     nsCOMPtr<nsISchemaAttribute> attribute;
02879 
02880     rv = ProcessAttribute(aErrorHandler, aSchema, aElement, 
02881                           getter_AddRefs(attribute));
02882     if (NS_FAILED(rv)) {
02883       return rv;
02884     }
02885     *aAttribute = attribute;
02886     NS_IF_ADDREF(*aAttribute);
02887   }
02888   else if (aTagName == nsSchemaAtoms::sAttributeGroup_atom) {
02889     nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
02890 
02891     rv = ProcessAttributeGroup(aErrorHandler, aSchema, aElement, 
02892                                getter_AddRefs(attributeGroup));
02893     if (NS_FAILED(rv)) {
02894       return rv;
02895     }
02896     *aAttribute = attributeGroup;
02897     NS_IF_ADDREF(*aAttribute);
02898   }
02899   else if (aTagName == nsSchemaAtoms::sAnyAttribute_atom) {
02900     nsCOMPtr<nsISchemaAttributeComponent> anyAttribute;
02901     nsSchemaAnyAttribute* anyAttributeInst = new nsSchemaAnyAttribute(aSchema);
02902     if (!anyAttributeInst) {
02903       return NS_ERROR_OUT_OF_MEMORY;
02904     }
02905     anyAttribute = anyAttributeInst;
02906 
02907     PRUint16 process;
02908     GetProcess(aElement, &process);
02909     anyAttributeInst->SetProcess(process);
02910 
02911     nsAutoString namespaceStr;
02912     aElement->GetAttribute(NS_LITERAL_STRING("namespace"), namespaceStr);
02913     anyAttributeInst->SetNamespace(namespaceStr);
02914     
02915     *aAttribute = anyAttribute;
02916     NS_ADDREF(*aAttribute);
02917 
02918   }
02919 
02920   return NS_OK;
02921 }
02922 
02923 nsresult 
02924 nsSchemaLoader::ProcessAttribute(nsIWebServiceErrorHandler* aErrorHandler,
02925                                  nsSchema* aSchema, 
02926                                  nsIDOMElement* aElement,
02927                                  nsISchemaAttribute** aAttribute)
02928 {
02929   nsresult rv;
02930 
02931   nsCOMPtr<nsISchemaAttribute> attribute;
02932 
02933   nsAutoString defaultValue, fixedValue;
02934   aElement->GetAttribute(NS_LITERAL_STRING("default"), defaultValue);
02935   aElement->GetAttribute(NS_LITERAL_STRING("fixed"), fixedValue);
02936 
02937   PRUint16 use;
02938   GetUse(aElement, &use);
02939 
02940   nsAutoString ref, refNS;
02941   aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
02942   if (!ref.IsEmpty()) {
02943     nsresult rv = ParseNameAndNS(ref, aElement, ref, refNS);
02944     NS_ENSURE_SUCCESS(rv, rv);
02945 
02946     nsSchemaAttributeRef* attributeRef = new nsSchemaAttributeRef(aSchema,
02947                                                                   ref, refNS);
02948     if (!attributeRef) {
02949       return NS_ERROR_OUT_OF_MEMORY;
02950     }
02951     attribute = attributeRef;
02952 
02953     attributeRef->SetConstraints(defaultValue, fixedValue);
02954     attributeRef->SetUse(use);
02955   }
02956   else {
02957     nsAutoString name;
02958     aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
02959     
02960     nsSchemaAttribute* attributeInst = new nsSchemaAttribute(aSchema,
02961                                                              name);
02962     if (!attributeInst) {
02963       return NS_ERROR_OUT_OF_MEMORY;
02964     }
02965     attribute = attributeInst;
02966 
02967     attributeInst->SetConstraints(defaultValue, fixedValue);
02968     attributeInst->SetUse(use);
02969 
02970     nsCOMPtr<nsISchemaSimpleType> simpleType;
02971 
02972     nsChildElementIterator iterator(aElement, 
02973                                     kSchemaNamespaces, 
02974                                     kSchemaNamespacesLength);
02975     nsCOMPtr<nsIDOMElement> childElement;
02976     nsCOMPtr<nsIAtom> tagName;
02977 
02978     while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
02979                                               getter_AddRefs(tagName))) &&
02980            childElement) {
02981       if (tagName == nsSchemaAtoms::sSimpleType_atom) {
02982         rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
02983                                getter_AddRefs(simpleType));
02984         if (NS_FAILED(rv)) {
02985           return rv;
02986         }
02987         break;
02988       }
02989     }
02990 
02991     if (!simpleType) {
02992       nsAutoString typeStr;
02993       aElement->GetAttribute(NS_LITERAL_STRING("type"), typeStr);
02994 
02995       if (!typeStr.IsEmpty()) {
02996         nsCOMPtr<nsISchemaType> schemaType;
02997         rv = GetNewOrUsedType(aSchema, aElement, typeStr, 
02998                               getter_AddRefs(schemaType));
02999         if (NS_FAILED(rv)) {
03000           nsAutoString errorMsg;
03001           errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
03002           errorMsg.Append(typeStr);
03003           errorMsg.AppendLiteral("\"");
03004 
03005           NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
03006 
03007           return rv;
03008         }
03009 
03010         simpleType = do_QueryInterface(schemaType);
03011         if (!simpleType) {
03012           nsAutoString errorMsg;
03013           errorMsg.AppendLiteral("Failure processing schema, invalid type \"");
03014           errorMsg.Append(typeStr);
03015           errorMsg.AppendLiteral("\" for attribute \"");
03016           errorMsg.Append(name);
03017           errorMsg.AppendLiteral("\"");
03018 
03019           NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
03020 
03021           return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
03022         }
03023       }
03024     }
03025 
03026     attributeInst->SetType(simpleType);
03027   }
03028 
03029   *aAttribute = attribute;
03030   NS_ADDREF(*aAttribute);
03031 
03032   return NS_OK;
03033 }
03034 
03035 nsresult 
03036 nsSchemaLoader::ProcessAttributeGroup(nsIWebServiceErrorHandler* aErrorHandler,
03037                                       nsSchema* aSchema, 
03038                                       nsIDOMElement* aElement,
03039                                       nsISchemaAttributeGroup** aAttributeGroup)
03040 {
03041   nsresult rv;
03042 
03043   nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
03044 
03045   nsAutoString ref, refNS;
03046   aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
03047 
03048   if (!ref.IsEmpty()) {
03049     // need to handle ns:type
03050     nsresult rv = ParseNameAndNS(ref, aElement, ref, refNS);
03051     NS_ENSURE_SUCCESS(rv, rv);
03052 
03053     nsSchemaAttributeGroupRef* attrRef = new nsSchemaAttributeGroupRef(aSchema,
03054                                                                        ref,
03055                                                                        refNS);
03056     if (!attrRef) {
03057       return NS_ERROR_OUT_OF_MEMORY;
03058     }
03059     attributeGroup = attrRef;
03060   }
03061   else {
03062     nsAutoString name;
03063     aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
03064     
03065     nsSchemaAttributeGroup* attrInst = new nsSchemaAttributeGroup(aSchema,
03066                                                                   name);
03067     if (!attrInst) {
03068       return NS_ERROR_OUT_OF_MEMORY;
03069     }
03070     attributeGroup = attrInst;
03071 
03072     rv = attrInst->Init();
03073     NS_ENSURE_SUCCESS(rv, rv);
03074 
03075     nsChildElementIterator iterator(aElement, 
03076                                     kSchemaNamespaces, 
03077                                     kSchemaNamespacesLength);
03078     nsCOMPtr<nsIDOMElement> childElement;
03079     nsCOMPtr<nsIAtom> tagName;
03080 
03081     while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
03082                                               getter_AddRefs(tagName))) &&
03083            childElement) {
03084       if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
03085           (tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
03086           (tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
03087         nsCOMPtr<nsISchemaAttributeComponent> attribute;
03088         
03089         rv = ProcessAttributeComponent(aErrorHandler, aSchema, 
03090                                        childElement, tagName,
03091                                        getter_AddRefs(attribute));
03092         if (NS_FAILED(rv)) {
03093           return rv;
03094         }
03095         
03096         rv = attrInst->AddAttribute(attribute);
03097         if (NS_FAILED(rv)) {
03098           return rv;
03099         }
03100       }    
03101     }
03102   }
03103 
03104   *aAttributeGroup = attributeGroup;
03105   NS_ADDREF(*aAttributeGroup);
03106 
03107   return NS_OK;
03108 }
03109  
03110 nsresult 
03111 nsSchemaLoader::ProcessFacet(nsIWebServiceErrorHandler* aErrorHandler,
03112                              nsSchema* aSchema, 
03113                              nsIDOMElement* aElement,
03114                              nsIAtom* aTagName,
03115                              nsISchemaFacet** aFacet)
03116 {
03117   PRInt32 rv;
03118 
03119   nsCOMPtr<nsISchemaFacet> facet;
03120   nsSchemaFacet* facetInst = new nsSchemaFacet(aSchema);
03121   if (!facetInst) {
03122     return NS_ERROR_OUT_OF_MEMORY;
03123   }
03124   facet = facetInst;
03125 
03126   PRUint16 facetType;
03127   if (aTagName == nsSchemaAtoms::sLength_atom) {
03128     facetType = nsISchemaFacet::FACET_TYPE_LENGTH;
03129   }
03130   else if (aTagName == nsSchemaAtoms::sMinLength_atom) {
03131     facetType = nsISchemaFacet::FACET_TYPE_MINLENGTH;
03132   }
03133   else if (aTagName == nsSchemaAtoms::sMaxLength_atom) {
03134     facetType = nsISchemaFacet::FACET_TYPE_MAXLENGTH;
03135   }
03136   else if (aTagName == nsSchemaAtoms::sPattern_atom) {
03137     facetType = nsISchemaFacet::FACET_TYPE_PATTERN;
03138   }
03139   else if (aTagName == nsSchemaAtoms::sEnumeration_atom) {
03140     facetType = nsISchemaFacet::FACET_TYPE_ENUMERATION;
03141   }
03142   else if (aTagName == nsSchemaAtoms::sWhiteSpace_atom) {
03143     facetType = nsISchemaFacet::FACET_TYPE_WHITESPACE;
03144   }
03145   else if (aTagName == nsSchemaAtoms::sMaxInclusive_atom) {
03146     facetType = nsISchemaFacet::FACET_TYPE_MAXINCLUSIVE;
03147   }
03148   else if (aTagName == nsSchemaAtoms::sMinInclusive_atom) {
03149     facetType = nsISchemaFacet::FACET_TYPE_MININCLUSIVE;
03150   }
03151   else if (aTagName == nsSchemaAtoms::sMaxExclusive_atom) {
03152     facetType = nsISchemaFacet::FACET_TYPE_MAXEXCLUSIVE;
03153   }
03154   else if (aTagName == nsSchemaAtoms::sMinExclusive_atom) {
03155     facetType = nsISchemaFacet::FACET_TYPE_MINEXCLUSIVE;
03156   }
03157   else if (aTagName == nsSchemaAtoms::sTotalDigits_atom) {
03158     facetType = nsISchemaFacet::FACET_TYPE_TOTALDIGITS;
03159   }
03160   else if (aTagName == nsSchemaAtoms::sFractionDigits_atom) {
03161     facetType = nsISchemaFacet::FACET_TYPE_FRACTIONDIGITS;
03162   }
03163   else {
03164     nsAutoString elementName;
03165     rv = aElement->GetTagName(elementName);
03166     NS_ENSURE_SUCCESS(rv, rv);
03167 
03168     nsAutoString errorMsg;
03169     errorMsg.AppendLiteral("Failure processing schema, unknown type of facet \"");
03170     errorMsg.Append(elementName);
03171     errorMsg.AppendLiteral("\"");
03172 
03173     NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_UNEXPECTED, errorMsg);
03174 
03175     return NS_ERROR_UNEXPECTED;
03176   }
03177   facetInst->SetFacetType(facetType);
03178 
03179   nsAutoString valueStr;
03180   aElement->GetAttribute(NS_LITERAL_STRING("value"), valueStr);
03181   if (valueStr.IsEmpty()) {
03182     nsAutoString elementName;
03183     rv = aElement->GetTagName(elementName);
03184     NS_ENSURE_SUCCESS(rv, rv);
03185 
03186     rv = NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
03187 
03188     nsAutoString errorMsg; 
03189     errorMsg.AppendLiteral("Failure processing schema, invalid empty value ");
03190     errorMsg.AppendLiteral("for facet \"");
03191     errorMsg.Append(elementName);
03192     errorMsg.AppendLiteral("\"");
03193 
03194     NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
03195 
03196     return rv;
03197   }
03198 
03199   if ((aTagName == nsSchemaAtoms::sLength_atom) ||
03200       (aTagName == nsSchemaAtoms::sMinLength_atom) ||
03201       (aTagName == nsSchemaAtoms::sMaxLength_atom) ||
03202       (aTagName == nsSchemaAtoms::sTotalDigits_atom) ||
03203       (aTagName == nsSchemaAtoms::sFractionDigits_atom)) {
03204     PRInt32 intVal = valueStr.ToInteger(&rv);
03205 
03206     if (NS_FAILED(rv) ||
03207         (intVal < 0) ||
03208         ((aTagName == nsSchemaAtoms::sTotalDigits_atom) && (intVal == 0))) {
03209       nsAutoString elementName;
03210       rv = aElement->GetTagName(elementName);
03211       NS_ENSURE_SUCCESS(rv, rv);
03212 
03213       nsAutoString errorMsg; 
03214       errorMsg.AppendLiteral("Failure processing schema, invalid value for facet \"");
03215       errorMsg.Append(elementName);
03216       errorMsg.AppendLiteral("\", <=0");
03217 
03218       NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_FACET_VALUE_ERROR, errorMsg);
03219 
03220       return NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
03221     }
03222 
03223     facetInst->SetUintValue((PRUint32)intVal);
03224   }
03225   else if (aTagName == nsSchemaAtoms::sWhiteSpace_atom) {
03226     PRUint16 whiteSpaceVal;
03227     if (valueStr.EqualsLiteral("collapse")) {
03228       whiteSpaceVal = nsSchemaFacet::WHITESPACE_COLLAPSE;
03229     }
03230     else if (valueStr.EqualsLiteral("preserve")) {
03231       whiteSpaceVal = nsSchemaFacet::WHITESPACE_PRESERVE;
03232     }
03233     else if (valueStr.EqualsLiteral("replace")) {
03234       whiteSpaceVal = nsSchemaFacet::WHITESPACE_REPLACE;
03235     }
03236     else {
03237       nsAutoString elementName;
03238       rv = aElement->GetTagName(elementName);
03239       NS_ENSURE_SUCCESS(rv, rv);
03240 
03241       nsAutoString errorMsg; 
03242       errorMsg.AppendLiteral("Failure processing schema, invalid value for facet \"");
03243       errorMsg.Append(elementName);
03244       errorMsg.AppendLiteral("\", should be \"collapse\", \"preserve\" or \"replace\"");
03245 
03246       NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_FACET_VALUE_ERROR, errorMsg);
03247 
03248       return NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
03249     }
03250 
03251     facetInst->SetWhitespaceValue(whiteSpaceVal);
03252   }
03253   else {
03254     facetInst->SetValue(valueStr);
03255   }
03256   
03257   nsAutoString isFixed;
03258   aElement->GetAttribute(NS_LITERAL_STRING("fixed"), isFixed);
03259   facetInst->SetIsFixed(isFixed.EqualsLiteral("true"));
03260 
03261   *aFacet = facet;
03262   NS_ADDREF(*aFacet);
03263 
03264   return NS_OK;
03265 }
03266 
03267 void
03268 nsSchemaLoader::GetUse(nsIDOMElement* aElement, 
03269                        PRUint16* aUse)
03270 {
03271   *aUse = nsISchemaAttribute::USE_OPTIONAL;
03272 
03273   nsAutoString use;
03274   aElement->GetAttribute(NS_LITERAL_STRING("use"), use);
03275   
03276   if (use.EqualsLiteral("prohibited")) {
03277     *aUse = nsISchemaAttribute::USE_PROHIBITED;
03278   }
03279   else if (use.EqualsLiteral("required")) {
03280     *aUse = nsISchemaAttribute::USE_REQUIRED;
03281   }
03282 }
03283 
03284 void
03285 nsSchemaLoader::GetProcess(nsIDOMElement* aElement, 
03286                            PRUint16* aProcess)
03287 {
03288   *aProcess = nsISchemaAnyParticle::PROCESS_STRICT;
03289 
03290   nsAutoString process;
03291   aElement->GetAttribute(NS_LITERAL_STRING("process"), process);
03292 
03293   if (process.EqualsLiteral("lax")) {
03294     *aProcess = nsISchemaAnyParticle::PROCESS_LAX;
03295   }
03296   else if (process.EqualsLiteral("skip")) {
03297     *aProcess = nsISchemaAnyParticle::PROCESS_SKIP;
03298   }
03299 }
03300 
03301 void
03302 nsSchemaLoader::GetMinAndMax(nsIDOMElement* aElement,
03303                              PRUint32* aMinOccurs,
03304                              PRUint32* aMaxOccurs)
03305 {
03306   *aMinOccurs = 1;
03307   *aMaxOccurs = 1;
03308 
03309   nsAutoString minStr, maxStr;
03310   aElement->GetAttribute(NS_LITERAL_STRING("minOccurs"), minStr);
03311   aElement->GetAttribute(NS_LITERAL_STRING("maxOccurs"), maxStr);
03312   
03313   PRInt32 rv;
03314   if (!minStr.IsEmpty()) {
03315     PRInt32 minVal = minStr.ToInteger(&rv);
03316     if (NS_SUCCEEDED(rv) && (minVal >= 0)) {
03317       *aMinOccurs = (PRUint32)minVal;
03318     }
03319   }
03320 
03321   if (!maxStr.IsEmpty()) {
03322     if (maxStr.EqualsLiteral("unbounded")) {
03323       *aMaxOccurs = nsISchemaParticle::OCCURRENCE_UNBOUNDED;
03324     }
03325     else {
03326       PRInt32 maxVal = maxStr.ToInteger(&rv);
03327       if (NS_SUCCEEDED(rv) && (maxVal >= 0)) {
03328         *aMaxOccurs = (PRUint32)maxVal;
03329       }
03330     }
03331   }
03332 }
03333 
03334 nsresult
03335 nsSchemaLoader::ParseNameAndNS(const nsAString& aName, nsIDOMElement* aElement,
03336                                nsAString& aTypeName, nsAString& aTypeNS)
03337 {
03338   nsresult rv;
03339   nsCOMPtr<nsIParserService> parserService =
03340     do_GetService("@mozilla.org/parser/parser-service;1", &rv);
03341   NS_ENSURE_SUCCESS(rv, rv);
03342 
03343   const nsAFlatString& qName = PromiseFlatString(aName);
03344   const PRUnichar *colon;
03345   rv = parserService->CheckQName(qName, PR_TRUE, &colon);
03346   NS_ENSURE_SUCCESS(rv, rv);
03347 
03348   if (colon) {
03349     const PRUnichar* end;
03350     qName.EndReading(end);
03351 
03352     nsAutoString schemaTypePrefix;
03353     schemaTypePrefix.Assign(Substring(qName.get(), colon));
03354     aTypeName.Assign(Substring(colon + 1, end));
03355 
03356     nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(aElement);
03357     NS_ENSURE_STATE(domNode3);
03358 
03359     // get the namespace url from the prefix
03360     rv = domNode3->LookupNamespaceURI(schemaTypePrefix, aTypeNS);
03361     NS_ENSURE_SUCCESS(rv, rv);
03362   }
03363 
03364   return rv;
03365 }
03366 
03367 nsresult
03368 nsSchemaLoader::GetDocumentFromURI(const nsAString& aUri,
03369                                    nsIDOMDocument** aDocument)
03370 {
03371   nsCOMPtr<nsIURI> resolvedURI;
03372   nsresult rv = GetResolvedURI(aUri, "load", getter_AddRefs(resolvedURI));
03373   NS_ENSURE_SUCCESS(rv, rv);
03374 
03375   nsCOMPtr<nsIXMLHttpRequest> request(do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv));
03376   NS_ENSURE_TRUE(request, rv);
03377 
03378   nsCAutoString spec;
03379   resolvedURI->GetSpec(spec);
03380 
03381   const nsAString& empty = EmptyString();
03382   rv = request->OpenRequest(NS_LITERAL_CSTRING("GET"), spec, PR_FALSE, empty,
03383                             empty);
03384   NS_ENSURE_SUCCESS(rv, rv);
03385 
03386   // Force the mimetype of the returned stream to be xml.
03387   rv = request->OverrideMimeType(NS_LITERAL_CSTRING("application/xml"));
03388   NS_ENSURE_SUCCESS(rv, rv);
03389 
03390   rv = request->Send(nsnull);
03391   NS_ENSURE_SUCCESS(rv, rv);
03392 
03393   nsCOMPtr<nsIDOMDocument> document;
03394   rv = request->GetResponseXML(getter_AddRefs(document));
03395   NS_ENSURE_SUCCESS(rv, rv);
03396 
03397   if (document) {
03398     document.swap(*aDocument);
03399   }
03400 
03401   return NS_OK;
03402 }