You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by kn...@apache.org on 2001/05/03 21:18:16 UTC
cvs commit: xml-xerces/c/src/validators/schema TraverseSchema.cpp TraverseSchema.hpp Makefile.in SchemaElementDecl.cpp SchemaElementDecl.hpp SchemaSymbols.cpp SchemaSymbols.hpp
knoaman 01/05/03 12:18:15
Modified: c/src/dom DOM_Element.hpp
c/src/util XMLString.cpp XMLString.hpp
c/src/validators/datatype DatatypeValidator.cpp
DatatypeValidator.hpp DatatypeValidatorFactory.cpp
DatatypeValidatorFactory.hpp
c/src/validators/schema Makefile.in SchemaElementDecl.cpp
SchemaElementDecl.hpp SchemaSymbols.cpp
SchemaSymbols.hpp
Added: c/src/validators/schema TraverseSchema.cpp
TraverseSchema.hpp
Log:
TraverseSchema Part II.
Revision Changes Path
1.8 +6 -1 xml-xerces/c/src/dom/DOM_Element.hpp
Index: DOM_Element.hpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/dom/DOM_Element.hpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- DOM_Element.hpp 2000/03/02 19:53:55 1.7
+++ DOM_Element.hpp 2001/05/03 19:17:26 1.8
@@ -56,6 +56,9 @@
/*
* $Log: DOM_Element.hpp,v $
+ * Revision 1.8 2001/05/03 19:17:26 knoaman
+ * TraverseSchema Part II.
+ *
* Revision 1.7 2000/03/02 19:53:55 roddey
* This checkin includes many changes done while waiting for the
* 1.1.0 code to be finished. I can't list them all here, but a list is
@@ -451,7 +454,7 @@
friend class DOM_Document;
friend class DOM_Attr;
-
+ friend class TraverseSchema;
};
#endif
1.16 +66 -1 xml-xerces/c/src/util/XMLString.cpp
Index: XMLString.cpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/util/XMLString.cpp,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- XMLString.cpp 2001/03/21 21:56:12 1.15
+++ XMLString.cpp 2001/05/03 19:17:33 1.16
@@ -55,7 +55,7 @@
*/
/*
- * $Id: XMLString.cpp,v 1.15 2001/03/21 21:56:12 tng Exp $
+ * $Id: XMLString.cpp,v 1.16 2001/05/03 19:17:33 knoaman Exp $
*/
@@ -827,6 +827,17 @@
{
const XMLCh* psz1 = str1;
const XMLCh* psz2 = str2;
+
+ if (psz1 == 0 || psz2 == 0) {
+
+ if (psz1 == 0) {
+ return 0 - XMLString::stringLen(psz2);
+ }
+ else if (psz2 == 0) {
+ return XMLString::stringLen(psz1);
+ }
+ }
+
while (true)
{
// If an inequality, then return the difference
@@ -1237,6 +1248,60 @@
index = skip;
}
return tokenStack;
+}
+
+//
+// This method is called when we get a notation or enumeration type attribute
+// to validate. We have to confirm that the passed value to find is one of
+// the values in the passed list. The list is a space separated string of
+// values to match against.
+//
+bool XMLString::isInList(const XMLCh* const toFind, const XMLCh* const enumList)
+{
+ //
+ // We loop through the values in the list via this outer loop. We end
+ // when we hit the end of the enum list or get a match.
+ //
+ const XMLCh* listPtr = enumList;
+ const unsigned int findLen = XMLString::stringLen(toFind);
+ while (*listPtr)
+ {
+ unsigned int testInd;
+ for (testInd = 0; testInd < findLen; testInd++)
+ {
+ //
+ // If they don't match, then reset and try again. Note that
+ // hitting the end of the current item will cause a mismatch
+ // because there can be no spaces in the toFind string.
+ //
+ if (listPtr[testInd] != toFind[testInd])
+ break;
+ }
+
+ //
+ // If we went the distance, see if we matched. If we did, the current
+ // list character has to be null or space.
+ //
+ if (testInd == findLen)
+ {
+ if ((listPtr[testInd] == chSpace) || !listPtr[testInd])
+ return true;
+ }
+
+ // Run the list pointer up to the next substring
+ while ((*listPtr != chSpace) && *listPtr)
+ listPtr++;
+
+ // If we hit the end, then we failed
+ if (!*listPtr)
+ return false;
+
+ // Else move past the space and try again
+ listPtr++;
+ }
+
+ // We never found it
+ return false;
}
// ---------------------------------------------------------------------------
1.18 +26 -0 xml-xerces/c/src/util/XMLString.hpp
Index: XMLString.hpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/util/XMLString.hpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- XMLString.hpp 2001/03/21 21:56:13 1.17
+++ XMLString.hpp 2001/05/03 19:17:35 1.18
@@ -56,6 +56,9 @@
/*
* $Log: XMLString.hpp,v $
+ * Revision 1.18 2001/05/03 19:17:35 knoaman
+ * TraverseSchema Part II.
+ *
* Revision 1.17 2001/03/21 21:56:13 tng
* Schema: Add Schema Grammar, Schema Validator, and split the DTDValidator into DTDValidator, DTDScanner, and DTDGrammar.
*
@@ -936,6 +939,19 @@
, const XMLCh* const prefix
);
+ /** Tells if the sub-string appears within a string at the end.
+ * @param toTest The string to test
+ * @param suffix The sub-string that needs to be checked
+ * @return Returns true if the sub-string was found at the end of
+ * <code>toTest</code>, else false
+ */
+ static bool endsWith
+ (
+ const XMLCh* const toTest
+ , const XMLCh* const prefix
+ );
+
+
/** Tells if a string has any occurance of another string within itself
* @param toSearch The string to be searched
* @param searchList The sub-string to be searched within the string
@@ -1204,6 +1220,16 @@
, const XMLCh* const prefix)
{
return (compareNIString(toTest, prefix, stringLen(prefix)) == 0);
+}
+
+inline bool XMLString::endsWith(const XMLCh* const toTest,
+ const XMLCh* const suffix)
+{
+
+ unsigned int suffixLen = XMLString::stringLen(suffix);
+
+ return regionMatches(toTest, XMLString::stringLen(toTest) - suffixLen,
+ suffix, 0, suffixLen);
}
inline XMLCh* XMLString::replicate(const XMLCh* const toRep)
1.2 +22 -17 xml-xerces/c/src/validators/datatype/DatatypeValidator.cpp
Index: DatatypeValidator.cpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/datatype/DatatypeValidator.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DatatypeValidator.cpp 2001/03/21 21:39:13 1.1
+++ DatatypeValidator.cpp 2001/05/03 19:17:43 1.2
@@ -1,37 +1,37 @@
/*
* The Apache Software License, Version 1.1
- *
+ *
* Copyright (c) 1999-2000 The Apache Software Foundation. All rights
* reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
+ * notice, this list of conditions and the following disclaimer.
+ *
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
- *
+ *
* 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
+ * if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
- *
+ *
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
- * software without prior written permission. For written
+ * software without prior written permission. For written
* permission, please contact apache\@apache.org.
- *
+ *
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -45,7 +45,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
- *
+ *
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 1999, International
@@ -56,6 +56,9 @@
/*
* $Log: DatatypeValidator.cpp,v $
+ * Revision 1.2 2001/05/03 19:17:43 knoaman
+ * TraverseSchema Part II.
+ *
* Revision 1.1 2001/03/21 21:39:13 knoaman
* Schema symbols and Datatype validator part I
*
@@ -72,9 +75,11 @@
// DatatypeValidator: Constructors and Destructor
// ---------------------------------------------------------------------------
DatatypeValidator::DatatypeValidator(DatatypeValidator* const baseValidator,
- RefHashTableOf<KVStringPair>* const facets)
- : fBaseValidator(baseValidator)
- , fFacets(facets)
+ RefHashTableOf<KVStringPair>* const facets,
+ const int finalSet)
+ : fFinalSet(finalSet)
+ , fBaseValidator(baseValidator)
+ , fFacets(facets)
{
}
@@ -87,7 +92,7 @@
// ---------------------------------------------------------------------------
// DatatypeValidators: Whitespace handling methods
// ---------------------------------------------------------------------------
-void
+void
DatatypeValidator::processWhiteSpace(RefHashTableOf<KVStringPair>* const facets)
{
KVStringPair* value = facets->get(SchemaSymbols::fgELT_WHITESPACE);
1.2 +71 -28 xml-xerces/c/src/validators/datatype/DatatypeValidator.hpp
Index: DatatypeValidator.hpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/datatype/DatatypeValidator.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DatatypeValidator.hpp 2001/03/21 21:39:14 1.1
+++ DatatypeValidator.hpp 2001/05/03 19:17:46 1.2
@@ -1,37 +1,37 @@
/*
* The Apache Software License, Version 1.1
- *
+ *
* Copyright (c) 1999-2000 The Apache Software Foundation. All rights
* reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
+ * notice, this list of conditions and the following disclaimer.
+ *
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
- *
+ *
* 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
+ * if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
- *
+ *
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
- * software without prior written permission. For written
+ * software without prior written permission. For written
* permission, please contact apache\@apache.org.
- *
+ *
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -45,7 +45,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
- *
+ *
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 1999, International
@@ -55,7 +55,7 @@
*/
/*
- * $Id: DatatypeValidator.hpp,v 1.1 2001/03/21 21:39:14 knoaman Exp $
+ * $Id: DatatypeValidator.hpp,v 1.2 2001/05/03 19:17:46 knoaman Exp $
*/
#if !defined(DATATYPEVALIDATOR_HPP)
@@ -65,9 +65,9 @@
#include <util/KVStringPair.hpp>
/**
- * DataTypeValidator defines the interface that data type validators must
+ * DataTypeValidator defines the interface that data type validators must
* obey. These validators can be supplied by the application writer and may
- * be useful as standalone code as well as plugins to the validator
+ * be useful as standalone code as well as plugins to the validator
* architecture.
*
* Notice:
@@ -90,7 +90,7 @@
FACET_LENGTH = 1,
FACET_MINLENGTH = 1<<1,
FACET_MAXLENGTH = 1<<2,
- FACET_PATTERN = 1<<3,
+ FACET_PATTERN = 1<<3,
FACET_ENUMERATION = 1<<4,
FACET_MAXINCLUSIVE = 1<<5,
FACET_MAXEXCLUSIVE = 1<<6,
@@ -104,14 +104,14 @@
FACET_WHITESPACE = 1<<14
};
- //2.4.2.6 whiteSpace - Datatypes
+ //2.4.2.6 whiteSpace - Datatypes
enum {
PRESERVE = 0,
REPLACE = 1,
COLLAPSE = 2
};
- // -----------------------------------------------------------------------
+ // -----------------------------------------------------------------------
// Public Destructor
// -----------------------------------------------------------------------
/** @name Destructor. */
@@ -128,8 +128,13 @@
//@{
/**
+ * Returns the final values of the simpleType
+ */
+ int getFinalSet() const;
+
+ /**
* Returns the datatype facet if any is set.
- */
+ */
RefHashTableOf<KVStringPair>* getFacets() const;
/**
@@ -151,7 +156,7 @@
/** @name Validation Function */
//@{
- /**
+ /**
* Checks that the "content" string is valid datatype.
* If invalid, a Datatype validation exception is thrown.
*
@@ -160,6 +165,14 @@
*/
virtual void validate(const XMLCh* const content) = 0;
+ /**
+ * Checks whether a given type can be used as a substitute
+ *
+ * @param toCheck A datatype validator of the type to be used as a
+ * substitute
+ */
+ bool isSubstitutableBy(const DatatypeValidator* const toCheck);
+
//@}
// -----------------------------------------------------------------------
@@ -170,7 +183,7 @@
/**
* Compares content in the Domain value vs. lexical value.
- *
+ *
* e.g. If type is a float then 1.0 may be equivalent to 1 even though
* both are lexically different.
*
@@ -192,16 +205,17 @@
/** @name Constructors */
//@{
- /**
+ /**
*
* @param baseValidator The base datatype validator for derived
* validators. Null if native validator.
*
* @param facets A hashtable of datatype facets.
- *
+ *
*/
DatatypeValidator(DatatypeValidator* const baseValidator,
- RefHashTableOf<KVStringPair>* const facets);
+ RefHashTableOf<KVStringPair>* const facets,
+ const int finalSet);
//@}
@@ -210,13 +224,14 @@
* Used by the DatatypeValidatorFactory.
*/
virtual DatatypeValidator* newInstance(DatatypeValidator* const,
- RefHashTableOf<KVStringPair>* const) = 0;
+ RefHashTableOf<KVStringPair>* const,
+ const int finalSet) = 0;
friend class DatatypeValidatorFactory;
/**
* Process the WHITESPACE facet if passed by user.
- * For all datatypes (exception of string), we don't need to pass
+ * For all datatypes (exception of string), we don't need to pass
* the WHITESPACE facet as its value is always 'collapse' and cannot
* be reset by user.
*
@@ -233,6 +248,9 @@
// -----------------------------------------------------------------------
// Private data members
//
+ // fFinalSet
+ // stores "final" values of simpleTypes
+ //
// fBaseValidator
// This is a pointer to a base datatype validator. If value is null,
// it means we have a native datatype validator not a derived one.
@@ -240,6 +258,7 @@
// fFacets
// This is a hashtable of dataype facets.
// -----------------------------------------------------------------------
+ int fFinalSet;
DatatypeValidator* fBaseValidator;
RefHashTableOf<KVStringPair>* fFacets;
};
@@ -248,6 +267,11 @@
// ---------------------------------------------------------------------------
// DatatypeValidator: Getters
// ---------------------------------------------------------------------------
+inline int DatatypeValidator::getFinalSet() const {
+
+ return fFinalSet;
+}
+
inline RefHashTableOf<KVStringPair>* DatatypeValidator::getFacets() const {
return fFacets;
@@ -263,7 +287,6 @@
return COLLAPSE;
}
-
// ---------------------------------------------------------------------------
// DatatypeValidator: CleanUp methods
// ---------------------------------------------------------------------------
@@ -276,10 +299,30 @@
// ---------------------------------------------------------------------------
// DatatypeValidators: Compare methods
// ---------------------------------------------------------------------------
-inline int DatatypeValidator::compare(const XMLCh* const value1,
+inline int DatatypeValidator::compare(const XMLCh* const value1,
const XMLCh* const value2)
{
return XMLString::compareString(value1, value2);
+}
+
+// ---------------------------------------------------------------------------
+// DatatypeValidators: Validation methods
+// ---------------------------------------------------------------------------
+inline bool
+DatatypeValidator::isSubstitutableBy(const DatatypeValidator* const toCheck)
+{
+ const DatatypeValidator* dv = toCheck;
+
+ while (dv != 0) {
+
+ if (dv == this) {
+ return true;
+ }
+
+ dv = dv->getBaseValidator();
+ }
+
+ return false;
}
#endif
1.2 +41 -40 xml-xerces/c/src/validators/datatype/DatatypeValidatorFactory.cpp
Index: DatatypeValidatorFactory.cpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/datatype/DatatypeValidatorFactory.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DatatypeValidatorFactory.cpp 2001/03/21 21:39:14 1.1
+++ DatatypeValidatorFactory.cpp 2001/05/03 19:17:47 1.2
@@ -56,6 +56,9 @@
/*
* $Log: DatatypeValidatorFactory.cpp,v $
+ * Revision 1.2 2001/05/03 19:17:47 knoaman
+ * TraverseSchema Part II.
+ *
* Revision 1.1 2001/03/21 21:39:14 knoaman
* Schema symbols and Datatype validator part I
*
@@ -70,10 +73,6 @@
#include <util/XMLUniDefs.hpp>
#include <util/Janitor.hpp>
-// ---------------------------------------------------------------------------
-// DatatypeValidatorFactory: Local declaration
-// ---------------------------------------------------------------------------
-typedef RefHashTableOf<KVStringPair> KVStringPairHashTable;
// ---------------------------------------------------------------------------
// DatatypeValidatorFactory: Local const data
@@ -365,7 +364,7 @@
Janitor<KVStringPairHashTable> janFacets(facets);
facets->put((void*) SchemaSymbols::fgELT_WHITESPACE,
- new KVStringPair(0, SchemaSymbols::fgWS_REPLACE));
+ new KVStringPair(SchemaSymbols::fgELT_WHITESPACE, SchemaSymbols::fgWS_REPLACE));
if (createDatatypeValidator(XMLUni::fgCDATAString,
getDatatypeValidator(SchemaSymbols::fgDT_STRING),
@@ -378,7 +377,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_WHITESPACE,
- new KVStringPair(0, SchemaSymbols::fgWS_COLLAPSE));
+ new KVStringPair(SchemaSymbols::fgELT_WHITESPACE, SchemaSymbols::fgWS_COLLAPSE));
if (createDatatypeValidator(SchemaSymbols::fgDT_TOKEN,
getDatatypeValidator(XMLUni::fgCDATAString),
@@ -391,7 +390,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_PATTERN,
- new KVStringPair(0, fgLangPattern));
+ new KVStringPair(SchemaSymbols::fgELT_PATTERN, fgLangPattern));
if (createDatatypeValidator(SchemaSymbols::fgDT_LANGUAGE,
getDatatypeValidator(SchemaSymbols::fgDT_TOKEN),
@@ -404,7 +403,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_PATTERN,
- new KVStringPair(0, fgNamePattern));
+ new KVStringPair(SchemaSymbols::fgELT_PATTERN, fgNamePattern));
if (createDatatypeValidator(SchemaSymbols::fgDT_NAME,
getDatatypeValidator(SchemaSymbols::fgDT_TOKEN),
@@ -417,7 +416,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_PATTERN,
- new KVStringPair(0, fgNCNamePattern));
+ new KVStringPair(SchemaSymbols::fgELT_PATTERN, fgNCNamePattern));
if (createDatatypeValidator(SchemaSymbols::fgDT_NCNAME,
getDatatypeValidator(SchemaSymbols::fgDT_TOKEN),
@@ -430,7 +429,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_SCALE,
- new KVStringPair(0, fgValueZero));
+ new KVStringPair(SchemaSymbols::fgELT_SCALE, fgValueZero));
if (createDatatypeValidator(SchemaSymbols::fgDT_INTEGER,
getDatatypeValidator(SchemaSymbols::fgDT_DECIMAL),
@@ -443,7 +442,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0, fgValueZero));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, fgValueZero));
if (createDatatypeValidator(SchemaSymbols::fgDT_NONPOSITIVEINTEGER,
getDatatypeValidator(SchemaSymbols::fgDT_INTEGER),
@@ -456,7 +455,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0,fgNegOne));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE,fgNegOne));
if (createDatatypeValidator(SchemaSymbols::fgDT_NEGATIVEINTEGER,
getDatatypeValidator(SchemaSymbols::fgDT_NONPOSITIVEINTEGER),
@@ -469,9 +468,9 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0,fgLongMaxInc));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE,fgLongMaxInc));
facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE,
- new KVStringPair(0,fgLongMinInc));
+ new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE,fgLongMinInc));
if (createDatatypeValidator(SchemaSymbols::fgDT_LONG,
getDatatypeValidator(SchemaSymbols::fgDT_INTEGER),
@@ -484,9 +483,9 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0, fgIntMaxInc));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, fgIntMaxInc));
facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE,
- new KVStringPair(0, fgIntMinInc));
+ new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, fgIntMinInc));
if (createDatatypeValidator(SchemaSymbols::fgDT_INT,
getDatatypeValidator(SchemaSymbols::fgDT_LONG),
@@ -499,9 +498,9 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0, fgShortMaxInc));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, fgShortMaxInc));
facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE,
- new KVStringPair(0, fgShortMinInc));
+ new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, fgShortMinInc));
if (createDatatypeValidator(SchemaSymbols::fgDT_SHORT,
getDatatypeValidator(SchemaSymbols::fgDT_INT),
@@ -514,9 +513,9 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0, fgByteMaxInc));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, fgByteMaxInc));
facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE,
- new KVStringPair(0, fgByteMinInc));
+ new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, fgByteMinInc));
if (createDatatypeValidator(SchemaSymbols::fgDT_BYTE,
getDatatypeValidator(SchemaSymbols::fgDT_SHORT),
@@ -529,7 +528,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE,
- new KVStringPair(0, fgValueZero));
+ new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, fgValueZero));
if (createDatatypeValidator(SchemaSymbols::fgDT_NONNEGATIVEINTEGER,
getDatatypeValidator(SchemaSymbols::fgDT_INTEGER),
@@ -542,7 +541,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0, fgULongMaxInc));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, fgULongMaxInc));
if (createDatatypeValidator(SchemaSymbols::fgDT_ULONG,
getDatatypeValidator(SchemaSymbols::fgDT_NONNEGATIVEINTEGER),
@@ -555,7 +554,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0, fgUIntMaxInc));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, fgUIntMaxInc));
if (createDatatypeValidator(SchemaSymbols::fgDT_UINT,
getDatatypeValidator(SchemaSymbols::fgDT_ULONG),
@@ -568,7 +567,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0, fgUShortMaxInc));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, fgUShortMaxInc));
if (createDatatypeValidator(SchemaSymbols::fgDT_USHORT,
getDatatypeValidator(SchemaSymbols::fgDT_UINT),
@@ -581,7 +580,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE,
- new KVStringPair(0, fgUByteMaxInc));
+ new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, fgUByteMaxInc));
if (createDatatypeValidator(SchemaSymbols::fgDT_UBYTE,
getDatatypeValidator(SchemaSymbols::fgDT_USHORT),
@@ -594,7 +593,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE,
- new KVStringPair(0, fgValueOne));
+ new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, fgValueOne));
if (createDatatypeValidator(SchemaSymbols::fgDT_POSITIVEINTEGER,
getDatatypeValidator(SchemaSymbols::fgDT_NONNEGATIVEINTEGER),
@@ -607,9 +606,9 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_DURATION,
- new KVStringPair(0, fgP0Y));
+ new KVStringPair(SchemaSymbols::fgELT_DURATION, fgP0Y));
facets->put((void*) SchemaSymbols::fgELT_PERIOD,
- new KVStringPair(0, fgP0Y));
+ new KVStringPair(SchemaSymbols::fgELT_PERIOD, fgP0Y));
if (createDatatypeValidator(SchemaSymbols::fgDT_TIMEINSTANT,
getDatatypeValidator(SchemaSymbols::fgDT_RECURRINGDURATION),
@@ -624,7 +623,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_PERIOD,
- new KVStringPair(0, fgP0Y));
+ new KVStringPair(SchemaSymbols::fgELT_PERIOD, fgP0Y));
if (createDatatypeValidator(SchemaSymbols::fgDT_TIMEPERIOD,
getDatatypeValidator(SchemaSymbols::fgDT_RECURRINGDURATION),
@@ -637,7 +636,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_DURATION,
- new KVStringPair(0, fgPT24H));
+ new KVStringPair(SchemaSymbols::fgELT_DURATION, fgPT24H));
if (createDatatypeValidator(SchemaSymbols::fgDT_DATE,
getDatatypeValidator(SchemaSymbols::fgDT_TIMEPERIOD),
@@ -650,7 +649,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_DURATION,
- new KVStringPair(0, fgP1M));
+ new KVStringPair(SchemaSymbols::fgELT_DURATION, fgP1M));
if (createDatatypeValidator(SchemaSymbols::fgDT_MONTH,
getDatatypeValidator(SchemaSymbols::fgDT_TIMEPERIOD),
@@ -663,7 +662,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_DURATION,
- new KVStringPair(0, fgP1Y));
+ new KVStringPair(SchemaSymbols::fgELT_DURATION, fgP1Y));
if (createDatatypeValidator(SchemaSymbols::fgDT_YEAR,
getDatatypeValidator(SchemaSymbols::fgDT_TIMEPERIOD),
@@ -676,7 +675,7 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_DURATION,
- new KVStringPair(0, fgP100Y));
+ new KVStringPair(SchemaSymbols::fgELT_DURATION, fgP100Y));
if (createDatatypeValidator(SchemaSymbols::fgDT_CENTURY,
getDatatypeValidator(SchemaSymbols::fgDT_TIMEPERIOD),
@@ -689,9 +688,9 @@
janFacets.reset(facets);
facets->put((void*) SchemaSymbols::fgELT_PERIOD,
- new KVStringPair(0, fgP1Y));
+ new KVStringPair(SchemaSymbols::fgELT_PERIOD, fgP1Y));
facets->put((void*) SchemaSymbols::fgELT_DURATION,
- new KVStringPair(0, fgPT24H));
+ new KVStringPair(SchemaSymbols::fgELT_DURATION, fgPT24H));
if (createDatatypeValidator(SchemaSymbols::fgDT_RECURRINGDATE,
getDatatypeValidator(SchemaSymbols::fgDT_RECURRINGDURATION),
@@ -713,7 +712,8 @@
DatatypeValidatorFactory::createDatatypeValidator(const XMLCh* const typeName,
DatatypeValidator* const baseValidator,
RefHashTableOf<KVStringPair>* const facets,
- const bool derivedByList)
+ const bool derivedByList,
+ const int finalSet)
{
if (baseValidator == 0) {
return 0;
@@ -728,7 +728,7 @@
else {
baseValidator->processWhiteSpace(facets);
- datatypeValidator = baseValidator->newInstance(baseValidator, facets);
+ datatypeValidator = baseValidator->newInstance(baseValidator, facets, finalSet);
}
if (datatypeValidator != 0) {
@@ -741,14 +741,15 @@
DatatypeValidator*
DatatypeValidatorFactory::createDatatypeValidator(const XMLCh* const typeName,
- RefVectorOf<DatatypeValidator>* const validators)
+ RefVectorOf<DatatypeValidator>* const validators,
+ const int finalSet)
{
if (validators == 0)
return 0;
DatatypeValidator* datatypeValidator = 0;
- //datatypeValidator = new UnionDatatypeValidator(validators);
+ //datatypeValidator = new UnionDatatypeValidator(validators, finalSet);
if (datatypeValidator != 0) {
fRegistry->put((void*) typeName, datatypeValidator);
1.2 +14 -4 xml-xerces/c/src/validators/datatype/DatatypeValidatorFactory.hpp
Index: DatatypeValidatorFactory.hpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/datatype/DatatypeValidatorFactory.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DatatypeValidatorFactory.hpp 2001/03/21 21:39:15 1.1
+++ DatatypeValidatorFactory.hpp 2001/05/03 19:17:49 1.2
@@ -55,7 +55,7 @@
*/
/*
- * $Id: DatatypeValidatorFactory.hpp,v 1.1 2001/03/21 21:39:15 knoaman Exp $
+ * $Id: DatatypeValidatorFactory.hpp,v 1.2 2001/05/03 19:17:49 knoaman Exp $
*/
#if !defined(DATATYPEVALIDATORFACTORY_HPP)
@@ -82,8 +82,14 @@
* to be checked. If no validation is necesary we should not instantiate a
* DatatypeValidatorFactory.
* If validation is needed, we need to instantiate a DatatypeValidatorFactory.
- */
+ */
+
+// ---------------------------------------------------------------------------
+// DatatypeValidatorFactory: Local declaration
+// ---------------------------------------------------------------------------
+typedef RefHashTableOf<KVStringPair> KVStringPairHashTable;
+
class VALIDATORS_EXPORT DatatypeValidatorFactory
{
public:
@@ -174,11 +180,14 @@
*
* @param derivedByList Indicates whether the datatype is derived by
* list or not
+ *
+ * @param finalSet 'final' values of the simpleType
*/
DatatypeValidator* createDatatypeValidator(const XMLCh* const,
DatatypeValidator* const,
RefHashTableOf<KVStringPair>* const,
- const bool);
+ const bool,
+ const int = 0);
/**
* Creates a new datatype validator of type UnionDatatypeValidator and
@@ -190,7 +199,8 @@
*
*/
DatatypeValidator* createDatatypeValidator(const XMLCh* const,
- RefVectorOf<DatatypeValidator>* const);
+ RefVectorOf<DatatypeValidator>* const,
+ const int finalSet);
//@}
1.7 +6 -2 xml-xerces/c/src/validators/schema/Makefile.in
Index: Makefile.in
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/schema/Makefile.in,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Makefile.in 2001/04/19 17:43:14 1.6
+++ Makefile.in 2001/05/03 19:17:57 1.7
@@ -55,8 +55,8 @@
#
#
# $Log: Makefile.in,v $
-# Revision 1.6 2001/04/19 17:43:14 knoaman
-# More schema implementation classes.
+# Revision 1.7 2001/05/03 19:17:57 knoaman
+# TraverseSchema Part II.
#
# Revision 1.4 2001/03/30 16:06:00 tng
# Schema: XUtil, added by Pei Yong Zhang
@@ -100,7 +100,9 @@
SchemaValidator.hpp \
XUtil.hpp \
NamespaceScope.hpp \
- ComplexTypeInfo.hpp
+ ComplexTypeInfo.hpp \
+ SubstitutionGroupComparator.hpp \
+ TraverseSchema.hpp
VALIDATORS_SCHEMA_CPP_PRIVHEADERS =
@@ -115,7 +117,9 @@
SchemaValidator.$(TO) \
XUtil.$(TO) \
NamespaceScope.$(TO) \
- ComplexTypeInfo.$(TO)
+ ComplexTypeInfo.$(TO) \
+ SubstitutionGroupComparator.$(TO) \
+ TraverseSchema.$(TO)
all:: includes $(VALIDATORS_SCHEMA_CPP_OBJECTS)
1.6 +7 -1 xml-xerces/c/src/validators/schema/SchemaElementDecl.cpp
Index: SchemaElementDecl.cpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/schema/SchemaElementDecl.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- SchemaElementDecl.cpp 2001/04/19 17:43:16 1.5
+++ SchemaElementDecl.cpp 2001/05/03 19:17:59 1.6
@@ -56,6 +56,9 @@
/*
* $Log: SchemaElementDecl.cpp,v $
+ * Revision 1.6 2001/05/03 19:17:59 knoaman
+ * TraverseSchema Part II.
+ *
* Revision 1.5 2001/04/19 17:43:16 knoaman
* More schema implementation classes.
*
@@ -94,12 +97,13 @@
fModelType(Any)
, fDatatypeValidator(0)
- , fEnclosingScope(-1)
+ , fEnclosingScope(Grammar::TOP_LEVEL_SCOPE)
, fBlockSet(0)
, fFinalSet(0)
, fMiscFlags(0)
, fDefaultValue(0)
, fSubstitutionGroupName(0)
+ , fTypeFromAnotherSchemaURI(0)
, fComplexTypeInfo(0)
{
}
@@ -118,6 +122,7 @@
, fMiscFlags(0)
, fDefaultValue(0)
, fSubstitutionGroupName(0)
+ , fTypeFromAnotherSchemaURI(0)
, fComplexTypeInfo(0)
{
setElementName(prefix, localPart, uriId);
@@ -135,6 +140,7 @@
, fMiscFlags(0)
, fDefaultValue(0)
, fSubstitutionGroupName(0)
+ , fTypeFromAnotherSchemaURI(0)
, fComplexTypeInfo(0)
{
setElementName(elementName);
1.5 +27 -2 xml-xerces/c/src/validators/schema/SchemaElementDecl.hpp
Index: SchemaElementDecl.hpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/schema/SchemaElementDecl.hpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SchemaElementDecl.hpp 2001/04/19 17:43:17 1.4
+++ SchemaElementDecl.hpp 2001/05/03 19:18:01 1.5
@@ -56,6 +56,9 @@
/*
* $Log: SchemaElementDecl.hpp,v $
+ * Revision 1.5 2001/05/03 19:18:01 knoaman
+ * TraverseSchema Part II.
+ *
* Revision 1.4 2001/04/19 17:43:17 knoaman
* More schema implementation classes.
*
@@ -75,6 +78,7 @@
#define SCHEMAELEMENTDECL_HPP
#include <util/QName.hpp>
+#include <validators/common/Grammar.hpp>
#include <validators/schema/ComplexTypeInfo.hpp>
class ContentSpecNode;
@@ -118,14 +122,14 @@
, const XMLCh* const localPart
, const int uriId
, const ModelTypes modelType = Any
- , const int enclosingScope = -1
+ , const int enclosingScope = Grammar::TOP_LEVEL_SCOPE
);
SchemaElementDecl
(
QName* const elementName
, const ModelTypes modelType = Any
- , const int enclosingScope = -1
+ , const int enclosingScope = Grammar::TOP_LEVEL_SCOPE
);
~SchemaElementDecl();
@@ -166,6 +170,7 @@
int getMiscFlags() const;
XMLCh* getDefaultValue() const;
XMLCh* getSubstitutionGroupName() const;
+ XMLCh* getTypeFromAnotherSchemaURI() const;
ComplexTypeInfo* getComplexTypeInfo() const;
@@ -181,6 +186,7 @@
void setMiscFlags(const int flags);
void setDefaultValue(const XMLCh* const value);
void setSubstitutionGroupName(const XMLCh* const name);
+ void setTypeFromAnotherSchemaURI(const XMLCh* const uriStr);
void setComplexTypeInfo(ComplexTypeInfo* const typeInfo);
@@ -231,6 +237,9 @@
// fSubstitutionGroupName
// The substitution group full name ("uristring','local")
//
+ // fTypeFromAnotherSchemaURI
+ // The URI of type if it belongs to a different schema
+ //
// fComplexTypeInfo
// Stores complex type information
// (no need to delete - handled by schema grammar)
@@ -244,6 +253,7 @@
int fMiscFlags;
XMLCh* fDefaultValue;
XMLCh* fSubstitutionGroupName;
+ XMLCh* fTypeFromAnotherSchemaURI;
ComplexTypeInfo* fComplexTypeInfo;
};
@@ -323,6 +333,11 @@
return fSubstitutionGroupName;
}
+inline XMLCh* SchemaElementDecl::getTypeFromAnotherSchemaURI() const {
+
+ return fTypeFromAnotherSchemaURI;
+}
+
inline ComplexTypeInfo* SchemaElementDecl::getComplexTypeInfo() const
{
return fComplexTypeInfo;
@@ -383,6 +398,16 @@
}
fSubstitutionGroupName = XMLString::replicate(name);
+}
+
+inline void
+SchemaElementDecl::setTypeFromAnotherSchemaURI(const XMLCh* const uriStr) {
+
+ if (fTypeFromAnotherSchemaURI) {
+ delete [] fTypeFromAnotherSchemaURI;
+ }
+
+ fTypeFromAnotherSchemaURI = XMLString::replicate(uriStr);
}
inline void
1.2 +30 -3 xml-xerces/c/src/validators/schema/SchemaSymbols.cpp
Index: SchemaSymbols.cpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/schema/SchemaSymbols.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- SchemaSymbols.cpp 2001/03/21 21:39:21 1.1
+++ SchemaSymbols.cpp 2001/05/03 19:18:03 1.2
@@ -56,6 +56,9 @@
/*
* $Log: SchemaSymbols.cpp,v $
+ * Revision 1.2 2001/05/03 19:18:03 knoaman
+ * TraverseSchema Part II.
+ *
* Revision 1.1 2001/03/21 21:39:21 knoaman
* Schema symbols and Datatype validator part I
*
@@ -488,9 +491,9 @@
chLatin_a, chLatin_c, chLatin_e, chNull
};
-const XMLCh SchemaSymbols::fgATT_NULLABLE[] =
+const XMLCh SchemaSymbols::fgATT_NILLABLE[] =
{
- chLatin_n, chLatin_u, chLatin_l, chLatin_l, chLatin_a, chLatin_b,
+ chLatin_n, chLatin_i, chLatin_l, chLatin_l, chLatin_a, chLatin_b,
chLatin_l, chLatin_e, chNull
};
@@ -570,6 +573,13 @@
chPound, chPound, chLatin_o, chLatin_o, chLatin_h, chLatin_e, chLatin_r, chNull
};
+const XMLCh SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE[] =
+{
+ chPound, chPound, chLatin_t, chLatin_a, chLatin_r, chLatin_g, chLatin_e,
+ chLatin_t, chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p,
+ chLatin_a, chLatin_c, chLatin_e, chNull
+};
+
const XMLCh SchemaSymbols::fgATTVAL_POUNDALL[] =
{
chPound, chLatin_a, chLatin_l, chLatin_l, chNull
@@ -696,6 +706,11 @@
chLatin_s, chLatin_k, chLatin_i, chLatin_p, chNull
};
+const XMLCh SchemaSymbols::fgATTVAL_STRICT[] =
+{
+ chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_c, chLatin_t, chNull
+};
+
const XMLCh SchemaSymbols::fgATTVAL_STRING[] =
{
chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_n, chLatin_g, chNull
@@ -740,6 +755,18 @@
chLatin_s, chLatin_u, chLatin_b, chLatin_s, chLatin_t, chLatin_i,
chLatin_t, chLatin_u, chLatin_t, chLatin_i, chLatin_o, chLatin_n,
chLatin_G, chLatin_r, chLatin_o, chLatin_u, chLatin_p, chNull
+};
+
+const XMLCh SchemaSymbols::fgATTVAL_SUBSTITUTION[] =
+{
+ chLatin_s, chLatin_u, chLatin_b, chLatin_s, chLatin_t, chLatin_i,
+ chLatin_t, chLatin_u, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull
+};
+
+const XMLCh SchemaSymbols::fgATTVAL_ANYTYPE[] =
+{
+ chLatin_a, chLatin_n, chLatin_y, chLatin_T, chLatin_y, chLatin_p,
+ chLatin_e, chNull
};
const XMLCh SchemaSymbols::fgWS_COLLAPSE[] =
1.2 +12 -8 xml-xerces/c/src/validators/schema/SchemaSymbols.hpp
Index: SchemaSymbols.hpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/validators/schema/SchemaSymbols.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- SchemaSymbols.hpp 2001/03/21 21:39:21 1.1
+++ SchemaSymbols.hpp 2001/05/03 19:18:04 1.2
@@ -55,7 +55,7 @@
*/
/*
- * $Id: SchemaSymbols.hpp,v 1.1 2001/03/21 21:39:21 knoaman Exp $
+ * $Id: SchemaSymbols.hpp,v 1.2 2001/05/03 19:18:04 knoaman Exp $
*/
#if !defined(SCHEMASYMBOLS_HPP)
@@ -143,7 +143,7 @@
static const XMLCh fgATT_MINOCCURS[];
static const XMLCh fgATT_NAME[];
static const XMLCh fgATT_NAMESPACE[];
- static const XMLCh fgATT_NULLABLE[];
+ static const XMLCh fgATT_NILLABLE[];
static const XMLCh fgATT_PROCESSCONTENTS[];
static const XMLCh fgATT_REF[];
static const XMLCh fgATT_REFER[];
@@ -158,6 +158,7 @@
static const XMLCh fgATTVAL_TWOPOUNDANY[];
static const XMLCh fgATTVAL_TWOPOUNDLOCAL[];
static const XMLCh fgATTVAL_TWOPOUNDOTHER[];
+ static const XMLCh fgATTVAL_TWOPOUNDTRAGETNAMESPACE[];
static const XMLCh fgATTVAL_POUNDALL[];
static const XMLCh fgATTVAL_BASE64[];
static const XMLCh fgATTVAL_BOOLEAN[];
@@ -181,6 +182,7 @@
static const XMLCh fgATTVAL_REQUIRED[];
static const XMLCh fgATTVAL_RESTRICTION[];
static const XMLCh fgATTVAL_SKIP[];
+ static const XMLCh fgATTVAL_STRICT[];
static const XMLCh fgATTVAL_STRING[];
static const XMLCh fgATTVAL_TEXTONLY[];
static const XMLCh fgATTVAL_TIMEDURATION[];
@@ -189,6 +191,8 @@
static const XMLCh fgATTVAL_URI[];
static const XMLCh fgATTVAL_URIREFERENCE[];
static const XMLCh fgATTVAL_SUBSTITUTIONGROUP[];
+ static const XMLCh fgATTVAL_SUBSTITUTION[];
+ static const XMLCh fgATTVAL_ANYTYPE[];
static const XMLCh fgWS_COLLAPSE[];
static const XMLCh fgWS_REPLACE[];
static const XMLCh fgDT_STRING[];
@@ -228,12 +232,12 @@
enum {
EMPTY_SET = 0,
- EXTENSION = 1,
- RESTRICTION = 2,
- REPRODUCTION = 4,
+ SUBSTITUTION = 1,
+ EXTENSION = 2,
+ RESTRICTION = 4,
LIST = 8,
- ENUMERATION = 16,
- SUBSTITUTIONGROUP = 32
+ UNION = 16,
+ ENUMERATION = 32
};
// group orders
@@ -245,7 +249,7 @@
enum {
INFINITY = -1,
- NULLABLE = 1,
+ NILLABLE = 1,
ABSTRACT = 2
};
1.1 xml-xerces/c/src/validators/schema/TraverseSchema.cpp
Index: TraverseSchema.cpp
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Log: TraverseSchema.cpp,v $
* Revision 1.1 2001/05/03 19:18:06 knoaman
* TraverseSchema Part II.
*
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <validators/schema/TraverseSchema.hpp>
#include <validators/datatype/DatatypeValidatorFactory.hpp>
#include <dom/DOM_NamedNodeMap.hpp>
#include <util/RefVectorOf.hpp>
#include <util/RefHashTableOf.hpp>
#include <util/Janitor.hpp>
#include <util/KVStringPair.hpp>
#include <util/StringTokenizer.hpp>
#include <util/QName.hpp>
#include <validators/schema/XUtil.hpp>
#include <validators/common/GrammarResolver.hpp>
#include <validators/schema/SchemaGrammar.hpp>
#include <validators/schema/SchemaAttDef.hpp>
#include <internal/XMLReader.hpp>
#include <validators/common/ContentSpecNode.hpp>
#include <validators/schema/ComplexTypeInfo.hpp>
#include <validators/schema/NamespaceScope.hpp>
#include <validators/schema/SchemaAttDefList.hpp>
#include <framework/XMLValidityCodes.hpp>
#include <framework/XMLErrorCodes.hpp>
#include <internal/XMLScanner.hpp>
#include <framework/XMLValidator.hpp>
#include <sax/EntityResolver.hpp>
#include <util/XMLURL.hpp>
#include <sax/InputSource.hpp>
#include <framework/LocalFileInputSource.hpp>
#include <framework/URLInputSource.hpp>
#include <parsers/DOMParser.hpp>
#include <dom/DOM_DOMException.hpp>
// ---------------------------------------------------------------------------
// TraverseSchema: Local declaration
// ---------------------------------------------------------------------------
typedef RefVectorOf<DatatypeValidator> DVRefVector;
// ---------------------------------------------------------------------------
// TraverseSchema: Static member data
// ---------------------------------------------------------------------------
XMLStringPool TraverseSchema::fStringPool;
// ---------------------------------------------------------------------------
// TraverseSchema: Local const data
// ---------------------------------------------------------------------------
const XMLCh fgXMLNS_Str[] =
{
chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chColon, chNull
};
const XMLCh fgAnonSNamePrefix[] =
{
chLatin_S, chNull
};
const XMLCh fgAnonCNamePrefix[] =
{
chLatin_C, chNull
};
const XMLCh fgUnbounded[] =
{
chLatin_u, chLatin_n, chLatin_b, chLatin_o, chLatin_u, chLatin_n, chLatin_d,
chLatin_e, chLatin_d, chNull
};
const XMLCh fgSkip[] =
{
chLatin_s, chLatin_k, chLatin_i, chLatin_p, chNull
};
const XMLCh fgLax[] =
{
chLatin_l, chLatin_a, chLatin_x, chNull
};
const XMLCh fgStrict[] =
{
chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_c, chLatin_t, chNull
};
// ---------------------------------------------------------------------------
// TraverseSchema: Constructors and Destructor
// ---------------------------------------------------------------------------
TraverseSchema::TraverseSchema( const DOM_Element& schemaRoot
, XMLStringPool* const uriStringPool
, SchemaGrammar* const schemaGrammar
, GrammarResolver* const grammarResolver
, XMLScanner* const xmlScanner
, XMLValidator* const xmlValidator
, const XMLCh* const schemaURL
, EntityResolver* const entityResolver)
: fElementDefaultQualified(false)
, fAttributeDefaultQualified(false)
, fTargetNSURI(-1)
, fCurrentScope(Grammar::TOP_LEVEL_SCOPE)
, fSimpleTypeAnonCount(0)
, fComplexTypeAnonCount(0)
, fFinalDefault(0)
, fBlockDefault(0)
, fScopeCount(0)
, fSchemaRootElement(schemaRoot)
, fTargetNSURIString(0)
, fCurrentSchemaURL(XMLString::replicate(schemaURL))
, fDatatypeRegistry(0)
, fGrammarResolver(grammarResolver)
, fSchemaGrammar(schemaGrammar)
, fEntityResolver(entityResolver)
, fURIStringPool(uriStringPool)
, fValidator(xmlValidator)
, fScanner(xmlScanner)
, fNamespaceScope(0)
, fAttributeDeclRegistry(0)
, fComplexTypeRegistry(0)
, fCurrentTypeNameStack(0)
{
try {
doTraverseSchema();
}
catch(...) {
cleanUp();
throw;
}
}
TraverseSchema::TraverseSchema( const DOM_Element& schemaRoot
, XMLStringPool* const stringPool
, SchemaGrammar* const schemaGrammar
, GrammarResolver* const grammarResolver
, XMLScanner* const xmlScanner
, XMLValidator* const xmlValidator
, const XMLCh* const schemaURL)
: fElementDefaultQualified(false)
, fAttributeDefaultQualified(false)
, fTargetNSURI(-1)
, fCurrentScope(Grammar::TOP_LEVEL_SCOPE)
, fSimpleTypeAnonCount(0)
, fComplexTypeAnonCount(0)
, fFinalDefault(0)
, fBlockDefault(0)
, fScopeCount(0)
, fSchemaRootElement(schemaRoot)
, fTargetNSURIString(0)
, fCurrentSchemaURL(XMLString::replicate(schemaURL))
, fDatatypeRegistry(0)
, fGrammarResolver(grammarResolver)
, fSchemaGrammar(schemaGrammar)
, fEntityResolver(0)
, fURIStringPool(stringPool)
, fValidator(xmlValidator)
, fScanner(xmlScanner)
, fNamespaceScope(0)
, fAttributeDeclRegistry(0)
, fComplexTypeRegistry(0)
, fCurrentTypeNameStack(0)
{
try {
doTraverseSchema();
}
catch(...) {
cleanUp();
throw;
}
}
TraverseSchema::TraverseSchema( const DOM_Element& schemaRoot
, XMLStringPool* const stringPool
, SchemaGrammar* const schemaGrammar
, GrammarResolver* const grammarResolver
, XMLScanner* const xmlScanner
, XMLValidator* const xmlValidator)
: fElementDefaultQualified(false)
, fAttributeDefaultQualified(false)
, fTargetNSURI(-1)
, fCurrentScope(Grammar::TOP_LEVEL_SCOPE)
, fSimpleTypeAnonCount(0)
, fComplexTypeAnonCount(0)
, fFinalDefault(0)
, fBlockDefault(0)
, fScopeCount(0)
, fSchemaRootElement(schemaRoot)
, fTargetNSURIString(0)
, fCurrentSchemaURL(0)
, fDatatypeRegistry(0)
, fGrammarResolver(grammarResolver)
, fSchemaGrammar(schemaGrammar)
, fEntityResolver(0)
, fURIStringPool(stringPool)
, fValidator(xmlValidator)
, fScanner(xmlScanner)
, fNamespaceScope(0)
, fAttributeDeclRegistry(0)
, fComplexTypeRegistry(0)
, fCurrentTypeNameStack(0)
{
try {
doTraverseSchema();
}
catch(...) {
cleanUp();
throw;
}
}
TraverseSchema::~TraverseSchema()
{
cleanUp();
}
// ---------------------------------------------------------------------------
// TraverseSchema: Traversal methods
// ---------------------------------------------------------------------------
void TraverseSchema::doTraverseSchema() {
fDatatypeRegistry = fGrammarResolver->getDatatypeRegistry();
fDatatypeRegistry->expandRegistryToFullSchemaSet();
fCurrentTypeNameStack = new RefStackOf<XMLCh>(16, true);
if (fSchemaRootElement.isNull()) {
// REVISIT: Anything to do?
return;
}
//Make sure namespace binding is defaulted
DOMString rootPrefix = fSchemaRootElement.getPrefix();
if (rootPrefix == 0 || rootPrefix.length() == 0) {
DOMString xmlns = fSchemaRootElement.getAttribute(XMLUni::fgXMLNSString);
if (xmlns.length() == 0) {
fSchemaRootElement.setAttribute(
XMLUni::fgXMLNSString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
}
}
//Retrieve the targetnamespace URI information
DOMString targetNSURIStr = fSchemaRootElement.getAttribute(
SchemaSymbols::fgATT_TARGETNAMESPACE);
if (targetNSURIStr == 0) {
fTargetNSURIString = XMLString::replicate(XMLUni::fgZeroLenString);
}
else {
fBuffer.set(targetNSURIStr.rawBuffer(), targetNSURIStr.length());
fTargetNSURIString = XMLString::replicate(fBuffer.getRawBuffer());
}
fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString);
// Set schemaGrammar data and add it to GrammarResolver
if (fGrammarResolver == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoGrammarResolver);
}
else{
// for complex type registry, attribute decl registry and
// namespace mapping, needs to check whether the passed in
// Grammar was a newly instantiated one.
fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry();
if (fComplexTypeRegistry == 0 ) {
fComplexTypeRegistry = new RefHashTableOf<ComplexTypeInfo>(109);
fSchemaGrammar->setComplexTypeRegistry(fComplexTypeRegistry);
}
fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry();
if (fAttributeDeclRegistry == 0) {
fAttributeDeclRegistry = new RefHashTableOf<XMLAttDef>(29, true);
fSchemaGrammar->setAttributeDeclRegistry(fAttributeDeclRegistry);
}
fNamespaceScope = fSchemaGrammar->getNamespaceScope();
if (fNamespaceScope == 0) {
fNamespaceScope = new NamespaceScope();
fNamespaceScope->reset(fURIStringPool->addOrFind(XMLUni::fgZeroLenString));
fNamespaceScope->increaseDepth();
fSchemaGrammar->setNamespaceScope(fNamespaceScope);
}
fSchemaGrammar->setDatatypeRegistry(fDatatypeRegistry);
fSchemaGrammar->setTargetNamespace(fTargetNSURIString);
fGrammarResolver->putGrammar(fSchemaGrammar->getTargetNamespace(),
fSchemaGrammar);
} // end else
retrieveNamespaceMapping();
fElementDefaultQualified =
fSchemaRootElement.getAttribute(SchemaSymbols::fgATT_ELEMENTFORMDEFAULT).equals(SchemaSymbols::fgATTVAL_QUALIFIED);
fAttributeDefaultQualified =
fSchemaRootElement.getAttribute(SchemaSymbols::fgATT_ATTRIBUTEFORMDEFAULT).equals(SchemaSymbols::fgATTVAL_QUALIFIED);
// Get finalDefault/blockDefault values
const XMLCh* defaultVal = getElementAttValue(fSchemaRootElement,
SchemaSymbols::fgATT_BLOCKDEFAULT);
const XMLCh* finalVal = getElementAttValue(fSchemaRootElement,
SchemaSymbols::fgATT_FINALDEFAULT);
fBlockDefault = defaultVal != 0 ? parseBlockSet(defaultVal) : 0;
fFinalDefault = finalVal != 0 ? parseFinalSet(finalVal) : 0;
// process children nodes
processChildren(fSchemaRootElement);
// Handle identity constraints
// TO DO
}
void TraverseSchema::traverseAnnotationDecl(const DOM_Element& childElem) {
//TO DO
}
void TraverseSchema::traverseInclude(const DOM_Element& childElem) {
//TO DO - work in progress
// ------------------------------------------------------------------
// Get 'schemLocation' attribute
// ------------------------------------------------------------------
const XMLCh* schemaLocation =
getElementAttValue(childElem,SchemaSymbols::fgATT_SCHEMALOCATION);
if (XMLString::stringLen(schemaLocation) == 0) {
reportSchemaError(0, 0); //'A schemaLocation attribute must be specified on an 'include' element."
}
// ------------------------------------------------------------------
// Create an input source
// ------------------------------------------------------------------
InputSource* srcToFill = 0;
if (fEntityResolver){
srcToFill = fEntityResolver->resolveEntity(0, schemaLocation);
}
// If they didn't create a source via the entity resolver, then we
// have to create one on our own.
try {
XMLURL urlTmp(fCurrentSchemaURL, schemaLocation);
if (urlTmp.isRelative()) {
ThrowXML(MalformedURLException,
XMLExcepts::URL_NoProtocolPresent);
}
srcToFill = new URLInputSource(urlTmp);
}
catch(const MalformedURLException&) {
// Its not a URL, so lets assume its a local file name.
srcToFill = new LocalFileInputSource(fCurrentSchemaURL,schemaLocation);
}
Janitor<InputSource> janSrc(srcToFill);
// ------------------------------------------------------------------
// Parse input source
// ------------------------------------------------------------------
DOMParser parser;
parser.setValidationScheme(DOMParser::Val_Never);
parser.setDoNamespaces(true);
// parser.setErrorHandler(fErrorHandler);
parser.setEntityResolver(fEntityResolver);
try {
parser.parse(*srcToFill);
}
catch (const XMLException& e) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::XMLException,
e.getType(), e.getMessage());
}
catch (const DOM_DOMException& e) {
throw e;
}
catch (...) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnexpectedError);
throw;
}
// ------------------------------------------------------------------
// Get root element
// ------------------------------------------------------------------
DOM_Document document = parser.getDocument();
if (!document.isNull()) {
DOM_Element root = document.getDocumentElement();
if (!root.isNull()) {
const XMLCh* targetNSURIString =
getElementAttValue(root,SchemaSymbols::fgATT_TARGETNAMESPACE);
if (XMLString::stringLen(targetNSURIString) != 0
&& XMLString::compareString(targetNSURIString,
fTargetNSURIString) != 0){
reportSchemaError(0,0);
}
else {
}
}
}
}
void TraverseSchema::traverseImport(const DOM_Element& childElem) {
//TO DO
}
void TraverseSchema::traverseRedefine(const DOM_Element& childElem) {
//TO DO
}
/**
* Traverse the Choice, Sequence declaration
*
* <choice-sequqnce
* id = ID
* maxOccurs = (nonNegativeInteger | unbounded) : 1
* minOccurs = nonNegativeInteger : 1
* Content: (annotation?, (element | group | choice | sequence | any)*)
* </choice-sequence>
*/
ContentSpecNode*
TraverseSchema::traverseChoiceSequence(const DOM_Element& elem,
const int modelGroupType)
{
DOM_Element child = checkContent(elem, XUtil::getFirstChildElement(elem), true);
ContentSpecNode* left = 0;
ContentSpecNode* right = 0;
bool hadContent = false;
for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
ContentSpecNode* contentSpecNode = 0;
bool seeParticle = false;
DOMString childName = child.getLocalName();
hadContent = true;
if (childName.equals(SchemaSymbols::fgELT_ELEMENT)) {
QName* eltQName = traverseElementDecl(child);
Janitor<QName> janQName(eltQName);
if (eltQName == 0) {
continue;
}
contentSpecNode = new ContentSpecNode(eltQName);
seeParticle = true;
}
else if (childName.equals(SchemaSymbols::fgELT_GROUP)) {
contentSpecNode = traverseGroupDecl(child);
if (contentSpecNode == 0)
continue;
seeParticle = true;
}
else if (childName.equals(SchemaSymbols::fgELT_CHOICE)) {
contentSpecNode =
traverseChoiceSequence(child,ContentSpecNode::Choice);
seeParticle = true;
}
else if (childName.equals(SchemaSymbols::fgELT_SEQUENCE)) {
contentSpecNode =
traverseChoiceSequence(child,ContentSpecNode::Sequence);
seeParticle = true;
}
else if (childName.equals(SchemaSymbols::fgELT_ANY)) {
contentSpecNode = traverseAny(child);
seeParticle = true;
}
else {
fBuffer.set(childName.rawBuffer(), childName.length());
reportSchemaError(XMLUni::fgValidityDomain, XMLValid::GroupContentRestricted,
fBuffer.getRawBuffer());
}
if (seeParticle) {
contentSpecNode = expandContentModel(contentSpecNode, child);
}
if (left == 0) {
left = contentSpecNode;
}
else if (right == 0) {
right = contentSpecNode;
}
else {
left = new ContentSpecNode((ContentSpecNode::NodeTypes) modelGroupType,
left, right);
right = contentSpecNode;
}
}
if (hadContent && right != 0) {
left = new ContentSpecNode((ContentSpecNode::NodeTypes) modelGroupType,
left, right);
}
return left;
}
/**
* Traverse SimpleType declaration:
* <simpleType
* id = ID
* name = NCName>
* Content: (annotation? , ((list | restriction | union)))
* </simpleType>
*
* traverse <list>|<restriction>|<union>
*/
int TraverseSchema::traverseSimpleTypeDecl(const DOM_Element& childElem)
{
const XMLCh* name = getElementAttValue(childElem,SchemaSymbols::fgATT_NAME);
if (XMLString::stringLen(fTargetNSURIString) != 0) {
fBuffer.set(fTargetNSURIString);
fBuffer.append(chComma);
fBuffer.append(name);
}
else {
fBuffer.set(name);
}
//check if we have already traversed the same simpleType decl
if (fDatatypeRegistry->getDatatypeValidator(fBuffer.getRawBuffer())!= 0) {
return fStringPool.addOrFind(fBuffer.getRawBuffer());
}
int newSimpleTypeName = -1;
if (XMLString::stringLen(name) == 0) { // anonymous simpleType
name = genAnonTypeName(fgAnonSNamePrefix, fSimpleTypeAnonCount);
}
newSimpleTypeName = fStringPool.addOrFind(name);
// Get 'final' values
const XMLCh* finalVal = getElementAttValue(childElem, SchemaSymbols::fgATT_FINAL);
int finalSet = parseFinalSet(finalVal);
// annotation?,(list|restriction|union)
DOM_Element content= checkContent(childElem,
XUtil::getFirstChildElement(childElem),
false);
if (content == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent);
return -1;
}
DOMString varietyName = content.getLocalName();
// Remark: some code will be repeated in list|restriction| union but it
// is cleaner that way
if (varietyName.equals(SchemaSymbols::fgELT_LIST)) { //traverse List
return traverseByList(childElem, content, newSimpleTypeName, finalSet);
}
else if (varietyName.equals(SchemaSymbols::fgELT_RESTRICTION)) { //traverse Restriction
return traverseByRestriction(childElem, content, newSimpleTypeName, finalSet);
}
else if (varietyName.equals(SchemaSymbols::fgELT_UNION)) { //traverse union
return traverseByUnion(childElem, content, newSimpleTypeName, finalSet);
}
else {
fBuffer.set(varietyName.rawBuffer(), varietyName.length());
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::FeatureUnsupported,fBuffer.getRawBuffer());
}
return -1;
}
/**
* Traverse ComplexType Declaration - CR Implementation.
*
* <complexType
* abstract = boolean
* block = #all or (possibly empty) subset of {extension, restriction}
* final = #all or (possibly empty) subset of {extension, restriction}
* id = ID
* mixed = boolean : false
* name = NCName>
* Content: (annotation? , (simpleContent | complexContent |
* ( (group | all | choice | sequence)? ,
* ( (attribute | attributeGroup)* , anyAttribute?))))
* </complexType>
*/
int TraverseSchema::traverseComplexTypeDecl(const DOM_Element& elem) {
// Get the attributes of the complexType
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
bool topLevel = isTopLevelComponent(elem);
if (XMLString::stringLen(name) == 0) {
if (topLevel) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameComplexType);
return -1;
}
name = genAnonTypeName(fgAnonCNamePrefix, fComplexTypeAnonCount);
}
if (!isValidNCName(name)) {
//REVISIT - Should we return or continue and save type with wrong name?
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexTypeName, name);
return -1;
}
// fCurrentTypeNameStack->push(XMLString::replicate(name));
// ------------------------------------------------------------------
// Check if the type has already been registered
// ------------------------------------------------------------------
fBuffer.set(fTargetNSURIString);
fBuffer.append(chComma);
fBuffer.append(name);
if (topLevel) {
ComplexTypeInfo* temp = fComplexTypeRegistry->get(fBuffer.getRawBuffer());
if (temp != 0 ) {
return fStringPool.addOrFind(fBuffer.getRawBuffer());
}
}
ComplexTypeInfo* typeInfo = new ComplexTypeInfo();
int typeNameIndex = fStringPool.addOrFind(fBuffer.getRawBuffer());
int scopeDefined = fScopeCount++;
int previousScope = fCurrentScope;
fCurrentScope = scopeDefined;
// ------------------------------------------------------------------
// First, handle any ANNOTATION declaration and get next child
// ------------------------------------------------------------------
DOM_Element child = checkContent(elem, XUtil::getFirstChildElement(elem),
true);
// ------------------------------------------------------------------
// Register the type
// ------------------------------------------------------------------
// Register the type first, so that in case of a recursive element type
// declaration, we can retrieve the complexType info (though the rest of
// complex type information has not been added).
fComplexTypeRegistry->put((void*) fStringPool.getValueForId(typeNameIndex),
typeInfo);
typeInfo->setTypeName(fBuffer.getRawBuffer());
// ------------------------------------------------------------------
// Process the content of the complex type declaration
// ------------------------------------------------------------------
try {
if (child == 0) {
// EMPTY complexType with complexContent
processComplexContent(name, child, typeInfo, 0,0,0, false);
}
else {
DOMString childName = child.getLocalName();
const XMLCh* mixedVal = getElementAttValue(elem,SchemaSymbols::fgATT_MIXED);
bool isMixed = false;
if (XMLString::stringLen(mixedVal) != 0
&& XMLString::compareString(SchemaSymbols::fgATTVAL_TRUE, mixedVal) == 0) {
isMixed = true;
}
if (childName.equals(SchemaSymbols::fgELT_SIMPLECONTENT)) {
// SIMPLE CONTENT element
traverseSimpleContentDecl(name, child, typeInfo);
if (XUtil::getNextSiblingElement(child) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingSimpleContent);
}
}
else if (childName.equals(SchemaSymbols::fgELT_COMPLEXCONTENT)) {
// COMPLEX CONTENT element
traverseComplexContentDecl(name, child, typeInfo, isMixed);
if (XUtil::getNextSiblingElement(child) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingConplexContent);
}
}
else {
// We must have ....
// GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes
// Note that it's possible that only attributes are specified.
processComplexContent(name, child, typeInfo, 0, 0, 0, isMixed);
}
}
}
catch(...) {
defaultComplexTypeInfo(typeInfo);
}
// ------------------------------------------------------------------
// Finish the setup of the typeInfo
// ------------------------------------------------------------------
const XMLCh* lBlock = getElementAttValue(elem, SchemaSymbols::fgATT_BLOCK);
const XMLCh* lFinal = getElementAttValue(elem, SchemaSymbols::fgATT_FINAL);
const XMLCh* lAbstract = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT);
int blockSet = lBlock != 0 ? parseBlockSet(lBlock) : fBlockDefault;
int finalSet = lFinal != 0 ? parseFinalSet(lFinal) : fFinalDefault;
int finalBlockValid = SchemaSymbols::RESTRICTION + SchemaSymbols::EXTENSION;
typeInfo->setBlockSet(blockSet);
typeInfo->setFinalSet(finalSet);
typeInfo->setScopeDefined(scopeDefined);
if (XMLString::stringLen(lBlock) != 0
&& XMLString::compareString(lBlock,SchemaSymbols::fgATTVAL_POUNDALL) != 0
&& ((blockSet & finalBlockValid) == 0)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexTypeBlockValue, lBlock);
}
if (XMLString::stringLen(lFinal) != 0
&& XMLString::compareString(lFinal,SchemaSymbols::fgATTVAL_POUNDALL) != 0
&& ((finalSet & finalBlockValid) == 0)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexTypeFinalValue, lFinal);
}
if (XMLString::stringLen(lAbstract) != 0
&& XMLString::compareString(lAbstract, SchemaSymbols::fgATTVAL_TRUE) == 0) {
typeInfo->setAbstract(true);
}
else {
typeInfo->setAbstract(false);
}
// ------------------------------------------------------------------
// Before exiting, restore the scope, mainly for nested anonymous types
// ------------------------------------------------------------------
fCurrentScope = previousScope;
//ArrayJanitor<XMLCh> janTypeName(fCurrentTypeNameStack->pop());
return typeNameIndex;
}
ContentSpecNode*
TraverseSchema::traverseGroupDecl(const DOM_Element& childElem) {
// TO DO
return 0;
}
/**
* Traverse Any declaration
*
* <any
* id = ID
* maxOccurs = (nonNegativeInteger | unbounded) : 1
* minOccurs = nonNegativeInteger : 1
* namespace = ((##any | ##other) | List of (anyURI |
* (##targetNamespace | ##local)) ) : ##any
* processContents = (lax | skip | strict) : strict
* {any attributes with non-schema namespace . . .}>
* Content: (annotation?)
* </any>
*/
ContentSpecNode*
TraverseSchema::traverseAny(const DOM_Element& elem) {
// ------------------------------------------------------------------
// First, handle any ANNOTATION declaration
// ------------------------------------------------------------------
if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) {
// reportSchemaError("<any> elements can contain at most one <annotation> element in their children");
}
// ------------------------------------------------------------------
// Get attributes
// ------------------------------------------------------------------
const XMLCh* const processContents =
getElementAttValue(elem, SchemaSymbols::fgATT_PROCESSCONTENTS);
const XMLCh* const nameSpace =
getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE);
// ------------------------------------------------------------------
// Set default node type based on 'processContents' value
// ------------------------------------------------------------------
ContentSpecNode::NodeTypes anyType = ContentSpecNode::Any;
ContentSpecNode::NodeTypes anyLocalType = ContentSpecNode::Any_Local;
ContentSpecNode::NodeTypes anyOtherType = ContentSpecNode::Any_Other;
if (XMLString::stringLen(processContents) != 0) {
if (XMLString::compareString(processContents, fgStrict) != 0) {
// Do nothing
}
else if (XMLString::compareString(processContents, fgLax) == 0) {
anyType = ContentSpecNode::Any_Lax;
anyOtherType = ContentSpecNode::Any_Other_Lax;
anyLocalType = ContentSpecNode::Any_Local_Lax;
}
else if (XMLString::compareString(processContents, fgSkip) == 0) {
anyType = ContentSpecNode::Any_Skip;
anyOtherType = ContentSpecNode::Any_Other_Skip;
anyLocalType = ContentSpecNode::Any_Local_Skip;
}
else {
reportSchemaError(0, 0, processContents); //"Invalid 'processContents' value: '{0}'
}
}
// ------------------------------------------------------------------
// Process 'namespace' attribute
// ------------------------------------------------------------------
int emptyURI = fURIStringPool->addOrFind(XMLUni::fgZeroLenString);
ContentSpecNode* retSpecNode = 0;
QName elemName(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString,
fTargetNSURI);
if (XMLString::stringLen(nameSpace) == 0
|| XMLString::compareString(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDANY) == 0) {
retSpecNode = new ContentSpecNode(&elemName);
retSpecNode->setType(anyType);
}
else if (XMLString::compareString(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER) == 0) {
retSpecNode = new ContentSpecNode(&elemName);
retSpecNode->setType(anyOtherType);
}
else {
RefVectorOf<XMLCh>* nameSpaceTokens = XMLString::tokenizeString(nameSpace);
ContentSpecNode* firstNode = 0;
ContentSpecNode* secondNode = 0;
unsigned int tokensSize = nameSpaceTokens->size();
for (unsigned int i=0; i < tokensSize; i++) {
const XMLCh* tokenElem = nameSpaceTokens->elementAt(i);
int uriIndex = emptyURI;
if (XMLString::compareString(tokenElem,
SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL) == 0) {
elemName.setURI(uriIndex);
firstNode = new ContentSpecNode(&elemName);
firstNode->setType(anyLocalType);
}
else {
if (XMLString::compareString(tokenElem,
SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE) == 0) {
uriIndex = fTargetNSURI;
}
uriIndex = fURIStringPool->addOrFind(tokenElem);
elemName.setURI(uriIndex);
firstNode = new ContentSpecNode(&elemName);
firstNode->setType(anyType);
}
if (secondNode == 0) {
secondNode = firstNode;
}
else {
secondNode = new ContentSpecNode(ContentSpecNode::Choice, secondNode, firstNode);
}
}
retSpecNode = secondNode;
delete nameSpaceTokens;
}
return retSpecNode;
}
ContentSpecNode*
TraverseSchema::traverseAll(const DOM_Element& allElem) {
// TO DO
return 0;
}
/**
* Traverses Schema attribute declaration.
*
* <attribute
* fixed = string
* default = string
* form = qualified | unqualified
* id = ID
* name = NCName
* ref = QName
* type = QName
* use = optional | prohibited | required : optional
* value = string>
* Content: (annotation? , simpleType?)
* <attribute/>
*
* @param elem: the declaration of the attribute under consideration
*
* @param typeInfo: Contains the complex type info of the element to which
* the attribute declaration is attached.
*
*/
void TraverseSchema::traverseAttributeDecl(const DOM_Element& elem,
ComplexTypeInfo* const typeInfo) {
bool topLevel = isTopLevelComponent(elem);
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
const XMLCh* defaultVal = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT);
const XMLCh* fixedVal = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED);
const XMLCh* useVal = getElementAttValue(elem, SchemaSymbols::fgATT_USE);
bool nameEmpty = (XMLString::stringLen(name) == 0) ? true : false;
bool refEmpty = (XMLString::stringLen(ref) == 0) ? true : false;
DOM_Element simpleType = checkContent(elem, XUtil::getFirstChildElement(elem), true);
if (nameEmpty && topLevel) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameAttribute);
return;
}
if (nameEmpty && refEmpty) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttribute);
return;
}
if(XMLString::stringLen(defaultVal) != 0) {
if (XMLString::stringLen(fixedVal) != 0) {
fixedVal = 0;
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeDefaultFixedValue);
}
if (XMLString::stringLen(useVal) != 0
&& XMLString::compareString(useVal, SchemaSymbols::fgATTVAL_OPTIONAL) != 0) {
useVal = 0;
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NotOptionalDefaultAttValue);
}
}
// processing ref
if (nameEmpty || (!refEmpty && !topLevel)) {
if (!nameEmpty) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeWithNameRef, name);
}
processAttributeDeclRef(elem, simpleType, typeInfo, ref, useVal);
return;
}
// processing 'name'
if (!isValidNCName(name)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttributeName, name);
return;
}
// Check for duplicate declaration
// REVISIT - need to add attributeGroup check
const XMLCh* attForm = getElementAttValue(elem, SchemaSymbols::fgATT_FORM);
const XMLCh* qualified = SchemaSymbols::fgATTVAL_QUALIFIED;
int uriIndex = fURIStringPool->addOrFind(XMLUni::fgZeroLenString);
if (XMLString::stringLen(fTargetNSURIString) != 0
&& (topLevel || XMLString::compareString(attForm, qualified) == 0
|| (fAttributeDefaultQualified
&& XMLString::stringLen(attForm) == 0))) {
uriIndex = fTargetNSURI;
}
if (topLevel) {
if (fAttributeDeclRegistry->containsKey(name)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name);
return;
}
}
else if (typeInfo != 0 && typeInfo->getAttDef(name, uriIndex) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name);
return;
}
const XMLCh* typeAttr = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE);
DatatypeValidator* dv = 0;
XMLAttDef::AttTypes attType;
if (simpleType != 0) {
if (XMLString::stringLen(typeAttr) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeWithTypeAndSimpleType);
}
int datatypeSymbol = traverseSimpleTypeDecl(simpleType);
attType = XMLAttDef::Simple;
if (datatypeSymbol != -1) {
dv = fDatatypeRegistry->getDatatypeValidator(
fStringPool.getValueForId(datatypeSymbol));
}
}
else if (XMLString::stringLen(typeAttr) == 0) {
attType = XMLAttDef::Simple;
dv = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_STRING);
}
else {
const XMLCh* localPart = getLocalPart(typeAttr);
const XMLCh* prefix = getPrefix(typeAttr);
const XMLCh* typeURI = resolvePrefixToURI(prefix);
if (XMLString::stringLen(typeURI) == 0
|| XMLString::compareString(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) == 0) {
dv = getDatatypeValidator(XMLUni::fgZeroLenString, localPart);
if (XMLString::compareString(localPart,XMLUni::fgIDString) == 0) {
attType = XMLAttDef::ID;
}
else if (XMLString::compareString(localPart,XMLUni::fgIDRefString) == 0) {
attType = XMLAttDef::IDRef;
}
else if (XMLString::compareString(localPart,XMLUni::fgIDRefsString) == 0) {
attType = XMLAttDef::IDRefs;
}
else if (XMLString::compareString(localPart,XMLUni::fgEntityString) == 0) {
attType = XMLAttDef::Entity;
}
else if (XMLString::compareString(localPart,XMLUni::fgEntitiesString) == 0) {
attType = XMLAttDef::Entities;
}
else if (XMLString::compareString(localPart,XMLUni::fgNmTokenString) == 0) {
attType = XMLAttDef::NmToken;
}
else if (XMLString::compareString(localPart,XMLUni::fgNmTokensString) == 0) {
attType = XMLAttDef::NmTokens;
}
else if (XMLString::compareString(localPart,XMLUni::fgNotationString) == 0) {
attType = XMLAttDef::Notation;
}
else {
attType = XMLAttDef::Simple;
if (dv == 0 && XMLString::stringLen(typeURI) == 0) {
DOM_Element topLevelType =
getTopLevelComponentByName(SchemaSymbols::fgELT_SIMPLETYPE, localPart);
if (topLevelType != 0) {
traverseSimpleTypeDecl(topLevelType);
dv = getDatatypeValidator(typeURI, localPart);
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeSimpleTypeNotFound,
typeURI, localPart, name);
}
}
}
}
else { //isn't of the schema for schemas namespace...
// check if the type is from the same Schema
dv = getDatatypeValidator(typeURI, localPart);
if (dv == 0
&& XMLString::compareString(typeURI, fTargetNSURIString) == 0) {
DOM_Element topLevelType =
getTopLevelComponentByName(SchemaSymbols::fgELT_SIMPLETYPE,
localPart);
if (topLevelType != 0) {
traverseSimpleTypeDecl(topLevelType);
dv = getDatatypeValidator(typeURI, localPart);
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeSimpleTypeNotFound,
typeURI, localPart, name);
}
}
attType = XMLAttDef::Simple;
}
}
bool required = false;
bool prohibited = false;
if (XMLString::stringLen(useVal) != 0) {
if (XMLString::compareString(useVal,
SchemaSymbols::fgATTVAL_REQUIRED) == 0) {
required = true;
}
else if (XMLString::compareString(useVal,
SchemaSymbols::fgATTVAL_PROHIBITED) == 0) {
prohibited = true;
}
}
// validate fixed/default values
const XMLCh* valueToCheck = XMLString::stringLen(defaultVal) != 0
? defaultVal : fixedVal;
if (attType == XMLAttDef::Simple && dv != 0
&& XMLString::stringLen(valueToCheck) != 0) {
try {
dv->validate(valueToCheck);
}
catch(...) {
reportSchemaError(XMLUni::fgXMLErrDomain,
XMLErrs::DatatypeValidationFailure, valueToCheck);
}
}
// create SchemaAttDef
SchemaAttDef* attDef =
new SchemaAttDef(XMLUni::fgZeroLenString, name, uriIndex, attType);
attDef->setDatatypeValidator(dv);
if (prohibited) {
attDef->setDefaultType(XMLAttDef::Prohibited);
}
else if (required) {
if (XMLString::stringLen(fixedVal) == 0) {
attDef->setDefaultType(XMLAttDef::Required);
}
else {
attDef->setDefaultType(XMLAttDef::Required_And_Fixed);
}
}
else {
if (XMLString::stringLen(fixedVal) != 0) {
attDef->setDefaultType(XMLAttDef::Fixed);
}
else if (XMLString::stringLen(defaultVal) != 0) {
attDef->setDefaultType(XMLAttDef::Default);
}
}
if (XMLString::stringLen(valueToCheck) != 0) {
attDef->setValue(valueToCheck);
}
if (topLevel) {
fAttributeDeclRegistry->put((void*) name, attDef);
}
else if (typeInfo != 0) {
typeInfo->addAttDef(attDef);
}
}
/**
* Traverses Schema element declaration.
*
* <element
* abstract = boolean : false
* block = (#all | List of (substitution | extension | restriction
* | list | union))
* default = string
* final = (#all | List of (extension | restriction))
* fixed = string
* form = (qualified | unqualified)
* id = ID
* maxOccurs = (nonNegativeInteger | unbounded) : 1
* minOccurs = nonNegativeInteger : 1
* name = NCName
* nillable = boolean : false
* ref = QName
* substitutionGroup = QName
* type = QName
* Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
* </element>
*
* @param elem: the declaration of the element under consideration
*/
QName* TraverseSchema::traverseElementDecl(const DOM_Element& elem) {
bool topLevel = isTopLevelComponent(elem);
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
const XMLCh* fixed = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED);
const XMLCh* deflt = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT);
bool nameEmpty = (XMLString::stringLen(name) == 0) ? true : false;
bool refEmpty = (XMLString::stringLen(ref) == 0) ? true : false;
if (nameEmpty && topLevel) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::GlobalNoNameElement);
return 0;
}
if (nameEmpty && refEmpty) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefElement);
return 0;
}
if(XMLString::stringLen(fixed) != 0 && XMLString::stringLen(deflt) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ElementWithFixedAndDefault);
}
if (nameEmpty || (!refEmpty && !topLevel)) {
if (!nameEmpty) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ElementWithNameRef, name);
}
if (!isValidRefDeclaration(elem)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::BadAttWithRef);
}
return processElementDeclRef(elem, ref);
}
// Name is notEmpty
if (!isValidNCName(name)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidElementName, name);
return 0;
}
const XMLCh* anotherSchemaURI = 0;
int scopeDefined = Grammar::UNKNOWN_SCOPE;
bool noErrorFound = true;
bool anonymousType = false;
DatatypeValidator* validator = 0;
DatatypeValidator* subGroupValidator = 0;
ComplexTypeInfo* typeInfo = 0;
ComplexTypeInfo* subGroupTypeInfo = 0;
ContentSpecNode* contentSpecNode = 0;
SchemaElementDecl::ModelTypes contentSpecType = SchemaElementDecl::Any;
if (topLevel) {
if (!refEmpty) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::GlobalElementWithRef, name);
}
if (fSchemaGrammar->getElemDecl(fTargetNSURI, name, 0, Grammar::TOP_LEVEL_SCOPE) != 0) {
return new QName(name, fTargetNSURI);
}
}
// Create element decl
SchemaElementDecl* elemDecl =
createSchemaElementDecl(elem, topLevel, contentSpecType);
if (elemDecl == 0) {
return 0;
}
fSchemaGrammar->putElemDecl(elemDecl);
// Resolve the type for the element
DOM_Element content = checkContent(elem, XUtil::getFirstChildElement(elem), true);
if (content != 0) {
DOMString contentName = content.getLocalName();
if (contentName.equals(SchemaSymbols::fgELT_COMPLEXTYPE)) {
if (content.getAttribute(SchemaSymbols::fgATT_NAME).length() > 0) {
// REVISIT - we are bypassing the complex type declaration.
// Is this the right way to go?
noErrorFound = false;
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AnonComplexTypeWithName, name);
}
else {
typeInfo = checkForComplexTypeInfo(content);
}
if (typeInfo == 0) {
noErrorFound = false;
}
else {
typeInfo->setElementId(elemDecl->getId());
}
anonymousType = true;
content = XUtil::getNextSiblingElement(content);
}
else if (contentName.equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
if (content.getAttribute(SchemaSymbols::fgATT_NAME).length() > 0) {
// REVISIT - we are bypassing the simple type declaration.
// Is this the right way to go?
noErrorFound = false;
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AnonSimpleTypeWithName, name);
}
else {
validator = checkForSimpleTypeValidator(content);
}
if (validator == 0) {
noErrorFound = false;
}
contentSpecType = SchemaElementDecl::Simple;
anonymousType = true;
content = XUtil::getNextSiblingElement(content);
}
// Check for identity constraints
if (content != 0) {
content = checkIdentityConstraintContent(content);
if (content != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidElementContent);
}
}
}
// Handle 'type' attribute
const XMLCh* typeStr = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE);
if (XMLString::stringLen(typeStr) > 0) {
if (anonymousType) {
noErrorFound = false;
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ElementWithTypeAndAnonType, name);
}
else {
anotherSchemaURI = checkTypeFromAnotherSchema(typeStr);
// REVISIT- get complex type info
typeInfo = getElementComplexTypeInfo(typeStr, noErrorFound,
anotherSchemaURI);
// get simple type validtor - if not a complex type
if (typeInfo == 0) {
validator = getElementTypeValidator(typeStr, noErrorFound,
anotherSchemaURI,true);
}
}
}
// Handle the substitutionGroup
const XMLCh* subsGroupName =
getElementAttValue(elem, SchemaSymbols::fgATT_SUBSTITUTIONGROUP);
if (XMLString::stringLen(subsGroupName) != 0) {
SchemaElementDecl* subsElemDecl =
getSubstituteGroupElemDecl(subsGroupName, noErrorFound);
if (subsElemDecl != 0) {
// Check for substitution validity constraint
// Substitution allowed (block and blockDefault) && same type
if (isSubstitutionGroupValid(subsElemDecl,typeInfo,validator,name)) {
if (typeInfo == 0 && validator == 0 && noErrorFound) {
typeInfo = subsElemDecl->getComplexTypeInfo();
validator = subsElemDecl->getDatatypeValidator();
}
// set element substitutionGroup full name
const XMLCh* uri = resolvePrefixToURI(getPrefix(subsGroupName));
const XMLCh* localPart = getLocalPart(subsGroupName);
fBuffer.set(uri);
fBuffer.append(chColon);
fBuffer.append(localPart);
elemDecl->setSubstitutionGroupName(fBuffer.getRawBuffer());
}
else {
noErrorFound = false;
}
}
}
if (typeInfo == 0 && validator == 0) {
if (noErrorFound) { // ur type
contentSpecType = SchemaElementDecl::Any;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UntypedElement, name);
}
}
// if element belongs to a compelx type
if (typeInfo != 0) {
contentSpecNode = typeInfo->getContentSpec();
contentSpecType = (SchemaElementDecl::ModelTypes) typeInfo->getContentType();
scopeDefined = typeInfo->getScopeDefined();
validator = typeInfo->getDatatypeValidator();
}
// if element belongs to a simple type
if (validator != 0) {
contentSpecType = SchemaElementDecl::Simple;
if (typeInfo == 0) {
anotherSchemaURI = 0; // not to switch schema in this case
}
}
// Now we can handle validation etc. of default and fixed attributes,
// since we finally have all the type information.
if(XMLString::stringLen(fixed) != 0) {
deflt = fixed;
}
if(XMLString::stringLen(deflt) != 0) {
try {
if(validator == 0) { // in this case validate according to xs:string
fDatatypeRegistry->getDatatypeValidator(
SchemaSymbols::fgDT_STRING)->validate(deflt);
} else {
validator->validate(deflt);
}
}
catch(...) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DatatypeValidationFailure, deflt);
}
if(typeInfo != 0 &&
(typeInfo->getContentType() != SchemaElementDecl::Mixed &&
typeInfo->getContentType() != SchemaElementDecl::Simple)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NotSimpleOrMixedElement, name);
}
}
// key/keyref/unique processing
// TO DO
// set element information
elemDecl->setDatatypeValidator(validator);
elemDecl->setComplexTypeInfo(typeInfo);
elemDecl->setDefaultValue(deflt);
elemDecl->setDefinedScope(scopeDefined);
elemDecl->setModelType(contentSpecType);
elemDecl->setContentSpec(contentSpecNode);
elemDecl->setTypeFromAnotherSchemaURI(anotherSchemaURI);
return new QName(elemDecl->getElementName());
}
XMLCh* TraverseSchema::traverseNotationDecl(const DOM_Element& childElem) {
//REVISIT
return 0;
}
int TraverseSchema::traverseByList(const DOM_Element& rootElem,
const DOM_Element& contentElem,
const int typeNameIndex,
const int finalSet) {
DatatypeValidator* baseValidator = 0;
DOM_Element content = contentElem;
const XMLCh* typeName = fStringPool.getValueForId(typeNameIndex);
const XMLCh* baseTypeName = getElementAttValue(content,
SchemaSymbols::fgATT_ITEMTYPE);
if (XUtil::getNextSiblingElement(content) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError);
}
if (XMLString::stringLen(baseTypeName) == 0) { // must 'see' <simpleType>
content = checkContent(rootElem, XUtil::getFirstChildElement(content), false);
if (content == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInList, typeName);
return -1;
}
if (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
baseValidator = checkForSimpleTypeValidator(content);
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
return -1;
}
content = XUtil::getNextSiblingElement(content);
}
else { // base was provided - get proper validator
baseValidator = findDTValidator(rootElem, baseTypeName,
SchemaSymbols::LIST);
content = checkContent(rootElem, XUtil::getFirstChildElement(content), true);
}
if (baseValidator == 0) {
return -1;
}
// 'content' should be empty
// If an annotation was encountered we have already traversed it in
// checkContent in the case of a base provided (only allowed child is
// an annotation).
if (content != 0) { // report an error and continue
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeDerivationByListError, typeName);
}
// create & register validator for "generated" type if it doesn't exist
XMLCh* qualifiedName = getQualifiedName(typeNameIndex);
try {
DatatypeValidator* newValidator =
fDatatypeRegistry->getDatatypeValidator(qualifiedName);
if (newValidator == 0) {
int strId = fStringPool.addOrFind(qualifiedName);
fDatatypeRegistry->createDatatypeValidator(
fStringPool.getValueForId(strId), baseValidator,0, true, finalSet);
}
}
catch(...) {
reportSchemaError(XMLUni::fgXMLErrDomain,
XMLErrs::DatatypeValidatorCreationError, typeName);
}
return fStringPool.addOrFind(qualifiedName);
}
int TraverseSchema::traverseByRestriction(const DOM_Element& rootElem,
const DOM_Element& contentElem,
const int typeNameIndex,
const int finalSet) {
DatatypeValidator* baseValidator = 0;
DOM_Element content = contentElem;
const XMLCh* typeName = fStringPool.getValueForId(typeNameIndex);
const XMLCh* baseTypeName = getElementAttValue(content,
SchemaSymbols::fgATT_BASE);
if (XUtil::getNextSiblingElement(content) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError);
}
if (XMLString::stringLen(baseTypeName) == 0) { // must 'see' <simpleType>
content = checkContent(rootElem, XUtil::getFirstChildElement(content), false);
if (content == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInRestriction);
return -1;
}
if (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
baseValidator = checkForSimpleTypeValidator(content);
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
return -1;
}
// Check for facets
content = XUtil::getNextSiblingElement(content);
}
else { // base was provided - get proper validator
baseValidator = findDTValidator(rootElem, baseTypeName,
SchemaSymbols::RESTRICTION);
content = checkContent(rootElem, XUtil::getFirstChildElement(content), true);
}
if (baseValidator == 0) {
return -1;
}
// Get facets if any existing
RefHashTableOf<KVStringPair>* facets = 0;
Janitor<KVStringPairHashTable> janFacets(0);
XMLBuffer enumData;
XMLBuffer pattern;
DOMString facetName;
bool isFirstPattern = true;
while (content != 0) {
if (content.getNodeType() == DOM_Node::ELEMENT_NODE) {
facetName = content.getLocalName();
fBuffer.set(facetName.rawBuffer(), facetName.length());
int facetId = fStringPool.addOrFind(fBuffer.getRawBuffer());
const XMLCh* facetStr = fStringPool.getValueForId(facetId);
DOMString attValue = content.getAttribute(SchemaSymbols::fgATT_VALUE);
int attValueLen = attValue.length();
if (facets == 0) {
facets = new RefHashTableOf<KVStringPair>(29, true);
janFacets.reset(facets);
}
if (XMLString::compareString(facetStr,
SchemaSymbols::fgELT_ENUMERATION) == 0) {
// REVISIT
// if validator is a notation datatype validator, we need
// to get the qualified name first before adding it to the
// enum buffer
enumData.append(attValue.rawBuffer(), attValueLen);
enumData.append(chSpace);
}
else if (XMLString::compareString(facetStr,
SchemaSymbols::fgELT_PATTERN) == 0) {
if (isFirstPattern) { // fBuffer.isEmpty() - overhead call
pattern.set(attValue.rawBuffer(), attValueLen);
}
else { //datatypes: 5.2.4 pattern
isFirstPattern = false;
pattern.append(chPipe);
pattern.append(attValue.rawBuffer(), attValueLen);
}
}
else if (XMLString::compareString(facetStr,
SchemaSymbols::fgELT_ANNOTATION) == 0
|| XMLString::compareString(facetStr,
SchemaSymbols::fgELT_SIMPLETYPE) == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
}
else {
if (facets->containsKey(facetStr)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetStr);
}
else {
fBuffer.set(attValue.rawBuffer(), attValueLen);
facets->put((void*) facetStr,
new KVStringPair(facetStr,fBuffer.getRawBuffer()));
}
}
// REVISIT
// check for annotation content - we are not checking whether the
// return is empty or not. If not empty we should report an error
checkContent(rootElem, XUtil::getFirstChildElement(content), true);
}
content = XUtil::getNextSiblingElement(content);
} // end while
if (!pattern.isEmpty()) {
facets->put((void*) SchemaSymbols::fgELT_PATTERN,
new KVStringPair(SchemaSymbols::fgELT_PATTERN, pattern.getRawBuffer()));
}
if (!enumData.isEmpty()) {
facets->put((void*) SchemaSymbols::fgELT_ENUMERATION,
new KVStringPair(SchemaSymbols::fgELT_ENUMERATION, enumData.getRawBuffer()));
}
XMLCh* qualifiedName = getQualifiedName(typeNameIndex);
try {
DatatypeValidator* newValidator =
fDatatypeRegistry->getDatatypeValidator(qualifiedName);
if (newValidator == 0) {
int strId = fStringPool.addOrFind(qualifiedName);
if (fDatatypeRegistry->createDatatypeValidator
(fStringPool.getValueForId(strId), baseValidator, facets,
false, finalSet) != 0) {
janFacets.orphan();
}
}
}
catch(...) {
reportSchemaError(XMLUni::fgXMLErrDomain,
XMLErrs::DatatypeValidatorCreationError, typeName);
}
return fStringPool.addOrFind(qualifiedName);
}
int TraverseSchema::traverseByUnion(const DOM_Element& rootElem,
const DOM_Element& contentElem,
const int typeNameIndex,
const int finalSet) {
int size = 1;
DOM_Element content = contentElem;
const XMLCh* const typeName =
fStringPool.getValueForId(typeNameIndex);
const XMLCh* baseTypeName = getElementAttValue(content,
SchemaSymbols::fgATT_MEMBERTYPES);
DatatypeValidator* baseValidator = 0;
RefVectorOf<DatatypeValidator>* validators =
new RefVectorOf<DatatypeValidator>(4, false);
Janitor<DVRefVector> janValidators(validators);
if (XUtil::getNextSiblingElement(content) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError);
}
if (XMLString::stringLen(baseTypeName) == 0) { // must 'see' <simpleType>
content = checkContent(rootElem, XUtil::getFirstChildElement(content), false);
if (content == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInUnion, typeName);
return -1;
}
if (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
baseValidator = checkForSimpleTypeValidator(content);
if (baseValidator == 0) {
return -1;
}
validators->addElement(baseValidator);
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
return -1;
}
content = XUtil::getNextSiblingElement(content);
}
else { //base was provided - get proper validator.
StringTokenizer unionMembers(baseTypeName);
int tokCount = unionMembers.countTokens();
for (int i = 0; i < tokCount; i++) {
const XMLCh* typeName = unionMembers.nextToken();
baseValidator = findDTValidator(rootElem, typeName,
SchemaSymbols::UNION);
if (baseValidator == 0) {
return -1;
}
validators->addElement(baseValidator);
}
content = checkContent(rootElem, XUtil::getFirstChildElement(content), true);
}
// process union content of simpleType children if any
while (content != 0) {
if (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
baseValidator = checkForSimpleTypeValidator(content);
if (baseValidator == 0) {
return -1;
}
validators->addElement(baseValidator);
}
else {
// REVISIT - should we return. For now, we will continue and move to
// the next sibling
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
}
content = XUtil::getNextSiblingElement(content);
} // end while
XMLCh* qualifiedName = getQualifiedName(typeNameIndex);
try {
DatatypeValidator* newValidator =
fDatatypeRegistry->getDatatypeValidator(qualifiedName);
if (newValidator == 0) {
int strId = fStringPool.addOrFind(qualifiedName);
if (fDatatypeRegistry->createDatatypeValidator(
fStringPool.getValueForId(strId), validators, finalSet) != 0) {
janValidators.orphan();
}
}
}
catch(...) {
reportSchemaError(XMLUni::fgXMLErrDomain,
XMLErrs::DatatypeValidatorCreationError, typeName);
}
return fStringPool.addOrFind(qualifiedName);
}
/**
* Traverse SimpleContent Declaration
*
* <simpleContent
* id = ID
* {any attributes with non-schema namespace...}>
*
* Content: (annotation? , (restriction | extension))
* </simpleContent>
*
* <restriction
* base = QNAME
* id = ID
* {any attributes with non-schema namespace...}>
*
* Content: (annotation?, (simpleType?, (minExclusive | minInclusive
* | maxExclusive | maxInclusive | totalDigits | fractionDigits
* | length | minLength | maxLength | enumeration | pattern
* | whiteSpace)*)?, ((attribute | attributeGroup)* , anyAttribute?))
* </restriction>
*
* <extension
* base = QNAME
* id = ID
* {any attributes with non-schema namespace...}>
* Content: (annotation? , ((attribute | attributeGroup)* , anyAttribute?))
* </extension>
*
*/
void TraverseSchema::traverseSimpleContentDecl(const XMLCh* const typeName,
const DOM_Element& contentDecl,
ComplexTypeInfo* const typeInfo)
{
// -----------------------------------------------------------------------
// Set the content type to be simple, and initialize content spec handle
// -----------------------------------------------------------------------
typeInfo->setContentType(SchemaElementDecl::Simple);
DOM_Element simpleContent =
checkContent(contentDecl, XUtil::getFirstChildElement(contentDecl),false);
// If there are no children, return
if (simpleContent == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent);
throw;
}
// -----------------------------------------------------------------------
// The content should be either "restriction" or "extension"
// -----------------------------------------------------------------------
DOMString contentName = simpleContent.getLocalName();
if (contentName.equals(SchemaSymbols::fgATTVAL_RESTRICTION)) {
typeInfo->setDerivedBy(SchemaSymbols::RESTRICTION);
}
else if (contentName.equals(SchemaSymbols::fgATTVAL_EXTENSION)) {
typeInfo->setDerivedBy(SchemaSymbols::EXTENSION);
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContent);
throw;
}
// -----------------------------------------------------------------------
// Handle the base type name
// -----------------------------------------------------------------------
const XMLCh* baseName =
getElementAttValue(simpleContent, SchemaSymbols::fgATT_BASE);
if (XMLString::stringLen(baseName) == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase);
throw;
}
const XMLCh* prefix = getPrefix(baseName);
const XMLCh* localPart = getLocalPart(baseName);
const XMLCh* uri = resolvePrefixToURI(prefix);
DatatypeValidator* baseValidator = getDatatypeValidator(uri, localPart);
if (baseValidator != 0
&& ((baseValidator->getFinalSet()
& SchemaSymbols::EXTENSION) == typeInfo->getDerivedBy())) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DisallowedSimpleTypeExtension,
baseName, typeName);
throw;
}
processBaseTypeInfo(baseName, localPart, uri, typeInfo);
// check that the base isn't a complex type with complex content
ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo();
if (baseTypeInfo != 0 && baseTypeInfo->getContentSpec() != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName);
throw;
}
// -----------------------------------------------------------------------
// Process the content of the derivation
// -----------------------------------------------------------------------
//Skip over any annotations in the restriction or extension elements
DOM_Element content = checkContent(simpleContent,
XUtil::getFirstChildElement(simpleContent), true);
if (typeInfo->getDerivedBy() == SchemaSymbols::RESTRICTION) {
//Schema Spec: 5.11: Complex Type Definition Properties Correct: 2
if (typeInfo->getBaseDatatypeValidator() != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexTypeBase, baseName);
throw;
}
else {
typeInfo->setBaseDatatypeValidator(
typeInfo->getBaseComplexTypeInfo()->getDatatypeValidator());
}
if (content != 0) {
// ---------------------------------------------------------------
// There may be a simple type definition in the restriction
// element. The data type validator will be based on it, if
// specified
// ---------------------------------------------------------------
if (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
int simpleTypeNameIndex = traverseSimpleTypeDecl(content);
if (simpleTypeNameIndex !=-1) {
typeInfo->setBaseDatatypeValidator(fDatatypeRegistry->getDatatypeValidator(
fStringPool.getValueForId(simpleTypeNameIndex)));
content = XUtil::getNextSiblingElement(content);
}
else {
throw;
}
}
// ---------------------------------------------------------------
// Build up the facet info
// ---------------------------------------------------------------
RefHashTableOf<KVStringPair>* facets = 0;
Janitor<KVStringPairHashTable> janFacets(0);
XMLBuffer enumData;
XMLBuffer pattern;
const XMLCh* facetName;
int facetId;
bool isFirstPattern = true;
while (content != 0) {
fBuffer.set(content.getLocalName().rawBuffer(), content.getLocalName().length());
facetId = fStringPool.addOrFind(fBuffer.getRawBuffer());
facetName = fStringPool.getValueForId(facetId);
// if not a valid facet, break from the loop
if (!isValidFacet(SchemaSymbols::fgELT_SIMPLECONTENT, facetName)) {
break;
}
if (content.getNodeType() == DOM_Node::ELEMENT_NODE) {
DOMString attValue =
content.getAttribute(SchemaSymbols::fgATT_VALUE);
if (facets == 0) {
facets = new RefHashTableOf<KVStringPair>(29, true);
janFacets.reset(facets);
}
fBuffer.set(attValue.rawBuffer(), attValue.length());
if (XMLString::compareString(facetName,
SchemaSymbols::fgELT_ENUMERATION) == 0) {
enumData.append(fBuffer.getRawBuffer());
enumData.append(chSpace);
}
else if (XMLString::compareString(facetName,
SchemaSymbols::fgELT_PATTERN) == 0) {
if (isFirstPattern) { // fBuffer.isEmpty() - overhead call
pattern.set(fBuffer.getRawBuffer());
}
else { //datatypes: 5.2.4 pattern
isFirstPattern = false;
pattern.append(chPipe);
pattern.append(fBuffer.getRawBuffer());
}
}
else {
if (facets->containsKey(facetName)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetName);
}
else {
facets->put((void*) facetName,
new KVStringPair(facetName,fBuffer.getRawBuffer()));
}
}
}
content = XUtil::getNextSiblingElement(content);
}
if (facets != 0) {
if (!pattern.isEmpty()) {
facets->put
(
(void*) SchemaSymbols::fgELT_PATTERN,
new KVStringPair
(
SchemaSymbols::fgELT_PATTERN,
pattern.getRawBuffer()
)
);
}
if (!enumData.isEmpty()) {
facets->put
(
(void*) SchemaSymbols::fgELT_ENUMERATION,
new KVStringPair
(
SchemaSymbols::fgELT_ENUMERATION,
enumData.getRawBuffer()
)
);
}
XMLCh* qualifiedName =
getQualifiedName(fStringPool.addOrFind(typeName));
try {
int nameId = fStringPool.addOrFind(qualifiedName);
typeInfo->setDatatypeValidator
(
fDatatypeRegistry->createDatatypeValidator
(
fStringPool.getValueForId(nameId),
typeInfo->getBaseDatatypeValidator(),
facets, false, 0
)
);
if (typeInfo->getDatatypeValidator() != 0) {
janFacets.orphan();
}
}
catch(...) {
reportSchemaError(XMLUni::fgXMLErrDomain,
XMLErrs::DatatypeValidatorCreationError, typeName);
}
}
else {
typeInfo->setDatatypeValidator(
typeInfo->getBaseDatatypeValidator());
}
}
else {
typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator());
}
} // end RESTRICTION
else { // EXTENSION
ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo();
if (baseTypeInfo!= 0) {
typeInfo->setBaseDatatypeValidator(baseTypeInfo->getDatatypeValidator());
}
typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator());
}
// -----------------------------------------------------------------------
// Process attributes if any
// -----------------------------------------------------------------------
if (content != 0 && isAttrOrAttrGroup(content)) {
processAttributes(content, baseName, localPart, uri, typeInfo);
}
if (XUtil::getNextSiblingElement(simpleContent) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInSimpleContent);
}
} // End of function traverseSimpleContentDecl
/**
* Traverse complexContent Declaration
*
* <complexContent
* id = ID
* mixed = boolean
* {any attributes with non-schema namespace...}>
*
* Content: (annotation? , (restriction | extension))
* </complexContent>
*
* <restriction
* base = QNAME
* id = ID
* {any attributes with non-schema namespace...}>
*
* Content: (annotation? , (group | all | choice | sequence)?,
* ((attribute | attributeGroup)* , anyAttribute?))
* </restriction>
*
* <extension
* base = QNAME
* id = ID
* {any attributes with non-schema namespace...}>
* Content: (annotation? , (group | all | choice | sequence)?,
* ((attribute | attributeGroup)* , anyAttribute?))
* </extension>
*/
void TraverseSchema::traverseComplexContentDecl(const XMLCh* const typeName,
const DOM_Element& contentDecl,
ComplexTypeInfo* const typeInfo,
const bool isMixed)
{
// -----------------------------------------------------------------------
// Determine whether the content is mixed, or element-only
// Setting here overrides any setting on the complex type decl
// -----------------------------------------------------------------------
const XMLCh* const mixed =
getElementAttValue(contentDecl, SchemaSymbols::fgATT_MIXED);
bool mixedContent = isMixed;
if (XMLString::compareString(mixed, SchemaSymbols::fgATTVAL_TRUE) == 0) {
mixedContent = true;
}
else if (XMLString::compareString(mixed, SchemaSymbols::fgATTVAL_FALSE) == 0) {
mixedContent = false;
}
// -----------------------------------------------------------------------
// Since the type must have complex content, set the simple type validators
// to null
// -----------------------------------------------------------------------
typeInfo->setDatatypeValidator(0);
typeInfo->setBaseDatatypeValidator(0);
DOM_Element complexContent =
checkContent(contentDecl,XUtil::getFirstChildElement(contentDecl),false);
// If there are no children, return
if (complexContent == 0) {
throw;
}
// -----------------------------------------------------------------------
// The content should be either "restriction" or "extension"
// -----------------------------------------------------------------------
DOMString complexContentName = complexContent.getLocalName();
if (complexContentName.equals(SchemaSymbols::fgELT_RESTRICTION)) {
typeInfo->setDerivedBy(SchemaSymbols::RESTRICTION);
}
else if (complexContentName.equals(SchemaSymbols::fgELT_EXTENSION)) {
typeInfo->setDerivedBy(SchemaSymbols::EXTENSION);
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexContent);
throw;
}
// -----------------------------------------------------------------------
// Handle the base type name
// -----------------------------------------------------------------------
const XMLCh* baseName =
getElementAttValue(contentDecl, SchemaSymbols::fgATT_BASE);
if (XMLString::stringLen(baseName) == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase);
throw;
}
const XMLCh* prefix = getPrefix(baseName);
const XMLCh* localPart = getLocalPart(baseName);
const XMLCh* uri = resolvePrefixToURI(prefix);
// -------------------------------------------------------------
// check if the base is "anyType"
// -------------------------------------------------------------
if (!(XMLString::compareString(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) == 0
&& XMLString::compareString(localPart, SchemaSymbols::fgATTVAL_ANYTYPE) == 0)) {
processBaseTypeInfo(baseName, localPart, uri, typeInfo);
//Check that the base is a complex type
if (typeInfo->getBaseComplexTypeInfo() == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain,
XMLErrs::BaseNotComplexType);
throw;
}
}
// -----------------------------------------------------------------------
// Process the content of the derivation
// -----------------------------------------------------------------------
//Skip over any annotations in the restriction or extension elements
DOM_Element content = checkContent(complexContent,
XUtil::getFirstChildElement(complexContent), true);
processComplexContent(typeName, content, typeInfo, baseName, localPart,
uri, mixedContent);
if (XUtil::getNextSiblingElement(complexContent) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexContent);
}
}
/**
* <anyAttribute
* id = ID
* namespace = ##any | ##other | ##local | list of {uri, ##targetNamespace}>
* processContents = (lax | skip | strict) : strict
* Content: (annotation?)
* </anyAttribute>
*/
SchemaAttDef* TraverseSchema::traverseAnyAttribute(const DOM_Element& elem) {
// ------------------------------------------------------------------
// First, handle any ANNOTATION declaration
// ------------------------------------------------------------------
if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) {
// reportSchemaError("anyAttribute elements can contain at most one 'annotation' element in their children");
}
// ------------------------------------------------------------------
// Get attributes
// ------------------------------------------------------------------
const XMLCh* const processContents =
getElementAttValue(elem, SchemaSymbols::fgATT_PROCESSCONTENTS);
const XMLCh* const nameSpace =
getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE);
// ------------------------------------------------------------------
// Set default att type based on 'processContents' value
// ------------------------------------------------------------------
XMLAttDef::DefAttTypes attDefType = XMLAttDef::ProcessContents_Strict;
if (XMLString::stringLen(processContents) == 0
|| XMLString::compareString(processContents, SchemaSymbols::fgATTVAL_STRICT) == 0) {
// Do nothing - defaulted already
}
else if (XMLString::compareString(processContents,
SchemaSymbols::fgATTVAL_SKIP) == 0) {
attDefType = XMLAttDef::ProcessContents_Skip;
}
else if (XMLString::compareString(processContents,
SchemaSymbols::fgATTVAL_LAX) == 0) {
attDefType = XMLAttDef::ProcessContents_Lax;
}
else {
reportSchemaError(0, 0, processContents); //"Invalid 'processContents' value: '{0}'
}
// ------------------------------------------------------------------
// Process 'namespace' attribute
// ------------------------------------------------------------------
int uriIndex = fURIStringPool->addOrFind(XMLUni::fgZeroLenString);
XMLAttDef::AttTypes attType = XMLAttDef::Any_Any;
fBuffer.reset();
if (XMLString::stringLen(nameSpace) == 0
|| XMLString::compareString(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDANY) == 0) {
// Do nothing - defaulted already
}
else if (XMLString::compareString(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER) == 0) {
attType = XMLAttDef::Any_Other;
uriIndex = fTargetNSURI;
}
else if (XMLString::compareString(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL) == 0) {
attType = XMLAttDef::Any_Local;
}
else {
StringTokenizer tokenizer(nameSpace);
XMLCh separator = chNull;
attType = XMLAttDef::Any_List;
// Will be using '|' as a separator to construct enumeration string.
// When the data is retrieved, a StringTokenizer construction with a delimeter
// string of "|" sould be used.
while (tokenizer.hasMoreTokens()) {
const XMLCh* token = tokenizer.nextToken();
if (separator != chNull) {
fBuffer.append(separator);
}
if (XMLString::compareString(token,
SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE) == 0) {
fBuffer.append(fTargetNSURIString);
}
else {
fBuffer.append(token);
}
separator = chPipe;
}
}
SchemaAttDef* attDef = new SchemaAttDef(XMLUni::fgZeroLenString,
XMLUni::fgZeroLenString,
uriIndex, attType, attDefType);
if (!fBuffer.isEmpty()){
attDef->setEnumeration(fBuffer.getRawBuffer());
}
return attDef;
}
// ---------------------------------------------------------------------------
// TraverseSchema: Helper methods
// ---------------------------------------------------------------------------
void TraverseSchema::retrieveNamespaceMapping() {
DOM_NamedNodeMap schemaEltAttrs = fSchemaRootElement.getAttributes();
bool seenXMLNS = false;
int attrCount = schemaEltAttrs.getLength();
for (int i = 0; i < attrCount; i++) {
DOM_Node attribute = schemaEltAttrs.item(i);
if (attribute.isNull()) {
break;
}
DOMString attName = attribute.getNodeName();
fBuffer.set(attName.rawBuffer(), attName.length());
int nameId = fStringPool.addOrFind(fBuffer.getRawBuffer());
// starts with 'xmlns:'
if (XMLString::startsWith(fBuffer.getRawBuffer(), fgXMLNS_Str)) {
const XMLCh* prefix = getPrefix(fStringPool.getValueForId(nameId));
DOMString attValue = attribute.getNodeValue();
fBuffer.set(attValue.rawBuffer(), attValue.length());
fNamespaceScope->addPrefix( prefix,
fURIStringPool->addOrFind(fBuffer.getRawBuffer()));
}
else if (attName.equals(XMLUni::fgXMLNSString)) { // == 'xmlns'
DOMString attValue = attribute.getNodeValue();
fBuffer.set(attValue.rawBuffer(), attValue.length());
fNamespaceScope->addPrefix( XMLUni::fgZeroLenString,
fURIStringPool->addOrFind(fBuffer.getRawBuffer()));
seenXMLNS = true;
}
} // end for
if (!seenXMLNS && XMLString::stringLen(fTargetNSURIString) == 0 ) {
fNamespaceScope->addPrefix( XMLUni::fgZeroLenString,
fURIStringPool->addOrFind(XMLUni::fgZeroLenString));
}
}
void TraverseSchema::extractTopLevel3Components(const DOM_Element& rootElem) {
// REVISIT - if necessary build list
}
void TraverseSchema::processChildren(const DOM_Element& root) {
// process <redefine>, <include> and <import> info items.
DOM_Element child = XUtil::getFirstChildElement(root);
for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
DOMString name = child.getLocalName();
if (name.equals(SchemaSymbols::fgELT_ANNOTATION)) {
traverseAnnotationDecl(child);
}
else if (name.equals(SchemaSymbols::fgELT_INCLUDE)) {
traverseInclude(child);
}
else if (name.equals(SchemaSymbols::fgELT_IMPORT)) {
traverseImport(child);
}
else if (name.equals(SchemaSymbols::fgELT_REDEFINE)) {
//fRedefineSucceeded = true; // presume worked until proven failed.
traverseRedefine(child);
}
else
break;
}
// child refers to the first info item which is not <annotation> or
// one of the schema inclusion/importation declarations.
for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
DOMString name = child.getLocalName();
if (name.equals(SchemaSymbols::fgELT_ANNOTATION)) {
traverseAnnotationDecl(child);
}
else if (name.equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
traverseSimpleTypeDecl(child);
}
else if (name.equals(SchemaSymbols::fgELT_COMPLEXTYPE)) {
traverseComplexTypeDecl(child);
}
else if (name.equals(SchemaSymbols::fgELT_ELEMENT)) {
traverseElementDecl(child);
}
else if (name.equals(SchemaSymbols::fgELT_ATTRIBUTEGROUP)) {
// traverseAttributeGroupDecl(child, 0, 0);
}
else if (name.equals(SchemaSymbols::fgELT_ATTRIBUTE ) ) {
traverseAttributeDecl( child, 0);
}
else if (name.equals(SchemaSymbols::fgELT_GROUP)) {
traverseGroupDecl(child);
}
else if (name.equals(SchemaSymbols::fgELT_NOTATION)) {
traverseNotationDecl(child); //TO DO
} else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SchemaElementContentError);
}
} // for each child node
}
DOM_Element TraverseSchema::checkContent(const DOM_Element& rootElem,
const DOM_Element& contentElem,
const bool isEmpty) {
DOM_Element content = contentElem;
const XMLCh* name = getElementAttValue(rootElem,SchemaSymbols::fgATT_NAME);
if (content == 0) {
if (!isEmpty) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ContentError, name);
}
return 0;
}
if (content.getLocalName().equals(SchemaSymbols::fgELT_ANNOTATION)) {
traverseAnnotationDecl(contentElem);
content = XUtil::getNextSiblingElement(content);
if (content == 0) { // must be followed by content
if (!isEmpty) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ContentError, name);
}
return 0;
}
if (content.getLocalName().equals(SchemaSymbols::fgELT_ANNOTATION)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AnnotationError, name);
return 0;
}
}
return content;
}
DatatypeValidator*
TraverseSchema::getDatatypeValidator(const XMLCh* const uriStr,
const XMLCh* const localPartStr) {
DatatypeValidator* dv = 0;
if (XMLString::stringLen(uriStr) == 0
|| XMLString::compareString(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) == 0) {
dv = fDatatypeRegistry->getDatatypeValidator(localPartStr);
}
else {
fBuffer.set(uriStr);
fBuffer.append(chComma);
fBuffer.append(localPartStr);
dv = fDatatypeRegistry->getDatatypeValidator(fBuffer.getRawBuffer());
}
return dv;
}
XMLCh* TraverseSchema::getQualifiedName(const int typeNameIndex) {
const XMLCh* typeName = fStringPool.getValueForId(typeNameIndex);
if (XMLString::stringLen(fTargetNSURIString) != 0) {
fBuffer.set(fTargetNSURIString);
fBuffer.append(chComma);
fBuffer.append(typeName);
}
else {
fBuffer.set(typeName);
}
return fBuffer.getRawBuffer();
}
DatatypeValidator*
TraverseSchema::checkForSimpleTypeValidator(const DOM_Element& content) {
int typeNameIndex = traverseSimpleTypeDecl(content);
DatatypeValidator* baseValidator = 0;
if (typeNameIndex != -1) {
baseValidator = fDatatypeRegistry->getDatatypeValidator(
fStringPool.getValueForId(typeNameIndex));
}
if (typeNameIndex == -1 || baseValidator == 0) {
const XMLCh* name = getElementAttValue(content,SchemaSymbols::fgATT_NAME);
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnknownSimpleType, name);
}
return baseValidator;
}
ComplexTypeInfo*
TraverseSchema::checkForComplexTypeInfo(const DOM_Element& content) {
int typeNameIndex = traverseComplexTypeDecl(content);
ComplexTypeInfo* baseTypeInfo = 0;
if (typeNameIndex != -1) {
baseTypeInfo = fComplexTypeRegistry->get(
fStringPool.getValueForId(typeNameIndex));
}
if (typeNameIndex == -1 || baseTypeInfo == 0) {
const XMLCh* name = getElementAttValue(content,SchemaSymbols::fgATT_NAME);
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnknownComplexType, name);
}
return baseTypeInfo;
}
DatatypeValidator*
TraverseSchema::findDTValidator(const DOM_Element& rootElem,
const XMLCh* const baseTypeStr,
const int baseRefContext) {
const XMLCh* prefix = getPrefix(baseTypeStr);
const XMLCh* localPart = getLocalPart(baseTypeStr);
const XMLCh* uri = resolvePrefixToURI(prefix);
DatatypeValidator* baseValidator = getDatatypeValidator(uri, localPart);
if (baseValidator == 0) {
DOM_Element baseTypeNode =
getTopLevelComponentByName(SchemaSymbols::fgELT_SIMPLETYPE, localPart);
if (baseTypeNode != 0) {
traverseSimpleTypeDecl(baseTypeNode);
baseValidator = getDatatypeValidator(uri, localPart);
}
}
if (baseValidator == 0) {
reportSchemaError(XMLUni::fgValidityDomain, XMLValid::UnknownBaseDatatype, baseTypeStr,
getElementAttValue(rootElem, SchemaSymbols::fgATT_NAME));
}
else {
int finalSet = baseValidator->getFinalSet();
if (finalSet !=0 && ((finalSet & baseRefContext) != 0)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DisallowedBaseDerivation, baseTypeStr);
return 0;
}
}
return baseValidator;
}
DOM_Element
TraverseSchema::getTopLevelComponentByName(const XMLCh* const compCategory,
const XMLCh* const name) {
// REVISIT - need to update to accomodate 'redefine'
DOM_Element child = XUtil::getFirstChildElement(fSchemaRootElement);
while (child != 0) {
if (child.getLocalName().equals(DOMString(compCategory))) {
if (child.getAttribute(SchemaSymbols::fgATT_NAME).equals(DOMString(name))) {
break;
}
}
else { // if redefine
// REVISIT
}
child = XUtil::getNextSiblingElement(child);
}
return child;
}
const XMLCh* TraverseSchema::resolvePrefixToURI(const XMLCh* const prefix) {
int nameSpaceIndex = fNamespaceScope->getNamespaceForPrefix(prefix);
const XMLCh* uriStr = fURIStringPool->getValueForId(nameSpaceIndex);
if (uriStr == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnresolvedPrefix, prefix);
return XMLUni::fgZeroLenString;
}
// REVISIT, !!!! a hack: needs to be updated later, cause now we only use
// localpart to key build-in datatype.
if (XMLString::stringLen(prefix) == 0 &&
XMLString::compareString(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) == 0
&& XMLString::stringLen(fTargetNSURIString) == 0) {
return XMLUni::fgZeroLenString;
}
return uriStr;
}
bool TraverseSchema::isTopLevelComponent(const DOM_Element& elem) {
DOMString parentName = elem.getParentNode().getLocalName();
fBuffer.set(parentName.rawBuffer(), parentName.length());
XMLCh* nameStr = fBuffer.getRawBuffer();
return (XMLString::endsWith(nameStr, SchemaSymbols::fgELT_SCHEMA))
|| (XMLString::endsWith(nameStr, SchemaSymbols::fgELT_REDEFINE));
}
QName* TraverseSchema::processElementDeclRef(const DOM_Element& elem,
const XMLCh* const refName) {
DOM_Element content = checkContent(elem, XUtil::getFirstChildElement(elem),
true);
if (content != 0) {
reportSchemaError(XMLUni::fgValidityDomain, XMLValid::NoContentForRef);
}
const XMLCh* prefix = getPrefix(refName);
const XMLCh* localPart = getLocalPart(refName);
const XMLCh* uriStr = resolvePrefixToURI(prefix);
QName* eltName = new QName(prefix , localPart, uriStr != 0
? fURIStringPool->addOrFind(uriStr)
: fURIStringPool->addOrFind(XMLUni::fgZeroLenString)); // StringPool.EMPTY_STRING == 0
//if from another schema, just return the element QName
if (XMLString::compareString(uriStr, fTargetNSURIString) != 0) {
return eltName;
}
unsigned int elemIndex = fSchemaGrammar->getElemId(eltName->getURI(),
localPart, 0,
Grammar::TOP_LEVEL_SCOPE);
//if not found, traverse the top level element that if referenced
if (elemIndex == XMLElementDecl::fgInvalidElemId) {
DOM_Element targetElem =
getTopLevelComponentByName(SchemaSymbols::fgELT_ELEMENT,
localPart);
if (targetElem == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::RefElementNotFound, localPart);
// REVISIT do we return 0 or what? for now we will return QName created
return eltName;
}
}
return eltName;
}
int TraverseSchema::parseBlockSet(const XMLCh* const blockStr) {
if (!blockStr) {
return fBlockDefault;
}
if (XMLString::compareString(blockStr, SchemaSymbols::fgATTVAL_POUNDALL) == 0) {
return SchemaSymbols::EXTENSION + SchemaSymbols::LIST +
SchemaSymbols::RESTRICTION + SchemaSymbols::UNION +
SchemaSymbols::SUBSTITUTION;
}
int blockSet = 0;
StringTokenizer tokenizer(blockStr);
while (tokenizer.hasMoreTokens()) {
XMLCh* token = tokenizer.nextToken();
if (XMLString::compareString(token, SchemaSymbols::fgATTVAL_SUBSTITUTION) == 0) {
if ((blockSet & SchemaSymbols::SUBSTITUTION) == 0 ) {
blockSet += SchemaSymbols::SUBSTITUTION;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SubstitutionRepeated);
}
}
else if (XMLString::compareString(token, SchemaSymbols::fgELT_UNION) == 0) {
if ((blockSet & SchemaSymbols::UNION) == 0) {
blockSet += SchemaSymbols::UNION;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnionRepeated);
}
}
else if (XMLString::compareString(token, SchemaSymbols::fgATTVAL_EXTENSION) == 0) {
if ((blockSet & SchemaSymbols::EXTENSION) == 0) {
blockSet += SchemaSymbols::EXTENSION;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ExtensionRepeated);
}
}
else if (XMLString::compareString(token, SchemaSymbols::fgELT_LIST) == 0) {
if ((blockSet & SchemaSymbols::LIST) == 0 ) {
blockSet += SchemaSymbols::LIST;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListRepeated);
}
}
else if (XMLString::compareString(token, SchemaSymbols::fgATTVAL_RESTRICTION) ) {
if ((blockSet & SchemaSymbols::RESTRICTION) == 0 ) {
blockSet += SchemaSymbols::RESTRICTION;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::RestrictionRepeated);
}
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidBlockValue, blockStr); //
}
} //end while
return (blockSet == 0 ? fBlockDefault : blockSet);
}
int TraverseSchema::parseFinalSet(const XMLCh* const finalStr) {
if (!finalStr) {
return fFinalDefault;
}
if (XMLString::compareString(finalStr, SchemaSymbols::fgATTVAL_POUNDALL) == 0) {
return SchemaSymbols::EXTENSION + SchemaSymbols::LIST +
SchemaSymbols::RESTRICTION + SchemaSymbols::UNION;
}
int finalSet = 0;
StringTokenizer tokenizer(finalStr);
while (tokenizer.hasMoreTokens()) {
XMLCh* token = tokenizer.nextToken();
if (XMLString::compareString(token, SchemaSymbols::fgELT_UNION) == 0) {
if ((finalSet & SchemaSymbols::UNION) == 0) {
finalSet += SchemaSymbols::UNION;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnionRepeated);
}
}
else if (XMLString::compareString(token, SchemaSymbols::fgATTVAL_EXTENSION) == 0) {
if ((finalSet & SchemaSymbols::EXTENSION) == 0) {
finalSet += SchemaSymbols::EXTENSION;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ExtensionRepeated);
}
}
else if (XMLString::compareString(token, SchemaSymbols::fgELT_LIST) == 0) {
if ((finalSet & SchemaSymbols::LIST) == 0 ) {
finalSet += SchemaSymbols::LIST;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListRepeated);
}
}
else if (XMLString::compareString(token, SchemaSymbols::fgATTVAL_RESTRICTION) ) {
if ((finalSet & SchemaSymbols::RESTRICTION) == 0 ) {
finalSet += SchemaSymbols::RESTRICTION;
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::RestrictionRepeated);
}
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidFinalValue, finalStr);
}
} //end while
return (finalSet == 0 ? fFinalDefault : finalSet);
}
DOM_Element
TraverseSchema::checkIdentityConstraintContent(const DOM_Element& content) {
DOM_Element child = content;
if (child != 0) {
do {
DOMString childName = child.getLocalName();
fBuffer.set(childName.rawBuffer(), childName.length());
if (!isIdentityConstraintName(fBuffer.getRawBuffer())) {
break;
}
child = XUtil::getNextSiblingElement(child);
} while (child != 0);
}
return child;
}
bool TraverseSchema::isIdentityConstraintName(const XMLCh* const name) {
return (XMLString::compareString(name, SchemaSymbols::fgELT_KEY) == 0
|| XMLString::compareString(name, SchemaSymbols::fgELT_KEYREF) == 0
|| XMLString::compareString(name, SchemaSymbols::fgELT_UNIQUE) == 0);
}
const XMLCh*
TraverseSchema::checkTypeFromAnotherSchema(const XMLCh* const typeStr) {
const XMLCh* prefix = getPrefix(typeStr);
const XMLCh* typeURI = resolvePrefixToURI(prefix);
if (XMLString::compareString(typeURI, fTargetNSURIString) != 0
&& XMLString::compareString(typeURI,
SchemaSymbols::fgURI_SCHEMAFORSCHEMA) != 0
&& XMLString::stringLen(typeURI) != 0) {
return typeURI;
}
return 0;
}
DatatypeValidator*
TraverseSchema::getElementTypeValidator(const XMLCh* const typeStr,
bool& noErrorDetected,
const XMLCh* const otherSchemaURI,
bool errorCheck)
{
const XMLCh* localPart = getLocalPart(typeStr);
const XMLCh* typeURI = otherSchemaURI;
DatatypeValidator* dv = 0;
if (otherSchemaURI != 0) {
dv = getDatatypeValidator(typeURI, localPart);
}
else {
const XMLCh* prefix = getPrefix(typeStr);
typeURI = resolvePrefixToURI(prefix);
dv = getDatatypeValidator(typeURI, localPart);
if (dv == 0) {
if (XMLString::compareString(typeURI,
SchemaSymbols::fgURI_SCHEMAFORSCHEMA) != 0
|| XMLString::compareString(fTargetNSURIString,
SchemaSymbols::fgURI_SCHEMAFORSCHEMA) == 0) {
DOM_Element elem = getTopLevelComponentByName(
SchemaSymbols::fgELT_SIMPLETYPE, localPart);
if (elem != 0 && traverseSimpleTypeDecl(elem) != -1) {
dv = getDatatypeValidator(typeURI, localPart);
}
}
}
}
if (dv == 0 && errorCheck) {
noErrorDetected = false;
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, typeURI, localPart);
}
return dv;
}
ComplexTypeInfo*
TraverseSchema::getElementComplexTypeInfo(const XMLCh* const typeStr,
bool& noErrorDetected,
const XMLCh* const otherSchemaURI)
{
const XMLCh* localPart = getLocalPart(typeStr);
const XMLCh* typeURI = otherSchemaURI;
ComplexTypeInfo* typeInfo = 0;
if (otherSchemaURI != 0) {
typeInfo = getTypeInfoFromNS(typeURI, localPart);
}
else {
const XMLCh* prefix = getPrefix(typeStr);
typeURI = resolvePrefixToURI(prefix);
fBuffer.set(typeURI);
fBuffer.append(chComma);
fBuffer.append(localPart);
typeInfo = fComplexTypeRegistry->get(fBuffer.getRawBuffer());
if (typeInfo == 0) {
if (XMLString::compareString(typeURI,
SchemaSymbols::fgURI_SCHEMAFORSCHEMA) != 0
|| XMLString::compareString(fTargetNSURIString,
SchemaSymbols::fgURI_SCHEMAFORSCHEMA) == 0) {
DOM_Element elem = getTopLevelComponentByName(
SchemaSymbols::fgELT_COMPLEXTYPE, localPart);
if (elem != 0) {
int typeIndex = traverseComplexTypeDecl(elem);
typeInfo = fComplexTypeRegistry->get(
fStringPool.getValueForId(typeIndex));
}
}
}
}
return typeInfo;
}
SchemaElementDecl*
TraverseSchema::getSubstituteGroupElemDecl(const XMLCh* const name,
bool& noErrorDetected) {
const XMLCh* nameURI = resolvePrefixToURI(getPrefix(name));
const XMLCh* localPart = getLocalPart(name);
SchemaElementDecl* elemDecl = 0;
if (XMLString::compareString(nameURI, fTargetNSURIString) != 0) {
elemDecl = getElementDeclFromNS(nameURI, localPart);
}
else {
elemDecl = (SchemaElementDecl*)
fSchemaGrammar->getElemDecl(fTargetNSURI, localPart,
0, Grammar::TOP_LEVEL_SCOPE);
if (elemDecl == 0) {
DOM_Element subsGroupElem =
getTopLevelComponentByName(SchemaSymbols::fgELT_ELEMENT,
localPart);
if (subsGroupElem != 0) {
QName* subsGroupQName = traverseElementDecl(subsGroupElem);
Janitor<QName> janQName(subsGroupQName);
if (subsGroupQName != 0) {
elemDecl = (SchemaElementDecl*)
fSchemaGrammar->getElemDecl(fTargetNSURI, localPart,
0, Grammar::TOP_LEVEL_SCOPE);
}
}
}
}
if (elemDecl == 0
|| (elemDecl->getDatatypeValidator() == 0
&& elemDecl->getComplexTypeInfo() == 0)) {
noErrorDetected = false;
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, nameURI, localPart);
}
return elemDecl;
}
SchemaElementDecl*
TraverseSchema::getElementDeclFromNS(const XMLCh* const nameUri,
const XMLCh* const localPart) {
// REVISIT:
Grammar* grammar = fGrammarResolver->getGrammar(nameUri);
unsigned int uriId = fURIStringPool->addOrFind(nameUri);
if (grammar != 0 && grammar->getGrammarType() == Grammar::SchemaGrammarType) {
return (SchemaElementDecl*)
grammar->getElemDecl(uriId, localPart, 0, Grammar::TOP_LEVEL_SCOPE);
}
reportSchemaError(XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, nameUri);
return 0;
}
bool
TraverseSchema::isSubstitutionGroupValid(const SchemaElementDecl* const subsElemDecl,
const ComplexTypeInfo* const typeInfo,
const DatatypeValidator* const validator,
const XMLCh* const elemName) {
// here we must do two things:
// 1. Make sure there actually *is* a relation between the types of
// the element being nominated and the element doing the nominating;
// (see PR 3.3.6 point #3 in the first tableau, for instance; this
// and the corresponding tableaux from 3.4.6 and 3.14.6 rule out the nominated
// element having an anonymous type declaration.
// 2. Make sure the nominated element allows itself to be nominated by
// an element with the given type-relation.
// Note: we assume that (complex|simple)Type processing checks
// whether the type in question allows itself to
// be modified as this element desires.
// Check for type relationship;
// that is, make sure that the type we're deriving has some relatoinship
// to substitutionGroupElt's type.
if (typeInfo != 0) { // do complexType case ...need testing
int derivationMethod = typeInfo->getDerivedBy();
if (typeInfo->getContentType() == SchemaElementDecl::Simple) { // take care of complexType based on simpleType case...
DatatypeValidator* elemDV = typeInfo->getDatatypeValidator();
DatatypeValidator* subsValidator = subsElemDecl->getDatatypeValidator();
if (subsValidator != 0 && subsValidator->isSubstitutableBy(elemDV)) {
if ((subsElemDecl->getFinalSet() & derivationMethod) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidSubstitutionGroupElement,
elemName, subsElemDecl->getBaseName());
return false;
}
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SubstitutionGroupTypeMismatch, elemName);
return false;
}
}
else { // complex content
ComplexTypeInfo* subsTypeInfo = subsElemDecl->getComplexTypeInfo();
const ComplexTypeInfo* elemTypeInfo = typeInfo;
for (; elemTypeInfo != subsTypeInfo;
elemTypeInfo = elemTypeInfo->getBaseComplexTypeInfo()) {
}
if (elemTypeInfo != 0) {
if ((subsElemDecl->getFinalSet() & derivationMethod) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidSubstitutionGroupElement,
elemName, subsElemDecl->getBaseName());
return false;
}
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SubstitutionGroupTypeMismatch, elemName);
return false;
}
}
}
else if (validator != 0) { // do simpleType case...
// first, check for type relation.
DatatypeValidator* subsValidator = subsElemDecl->getDatatypeValidator();
if (subsValidator != 0 && subsValidator->isSubstitutableBy(validator)) {
if ((subsElemDecl->getFinalSet() & SchemaSymbols::RESTRICTION) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidSubstitutionGroupElement,
elemName, subsElemDecl->getBaseName());
return false;
}
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SubstitutionGroupTypeMismatch, elemName);
return false;
}
}
return true;
}
SchemaElementDecl*
TraverseSchema::createSchemaElementDecl(const DOM_Element& elem,
const bool topLevel,
const unsigned short elemType)
{
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
const XMLCh* elemForm = getElementAttValue(elem, SchemaSymbols::fgATT_FORM);
int enclosingScope = fCurrentScope;
int uriIndex = fURIStringPool->addOrFind(XMLUni::fgZeroLenString);
//refer to 4.3.2 in "XML Schema Part 1: Structures"
if (topLevel) {
uriIndex = fTargetNSURI;
enclosingScope = Grammar::TOP_LEVEL_SCOPE;
}
else if ((XMLString::stringLen(elemForm) == 0 && fElementDefaultQualified)
|| XMLString::compareString(elemForm,SchemaSymbols::fgATTVAL_QUALIFIED) == 0) {
uriIndex = fTargetNSURI;
}
// Check for duplicate elements
const SchemaElementDecl* other = (SchemaElementDecl*)
fSchemaGrammar->getElemDecl(uriIndex, name, 0, enclosingScope);
if (other != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, name);
return 0;
}
const XMLCh* block = getElementAttValue(elem,SchemaSymbols::fgATT_BLOCK);
const XMLCh* final = getElementAttValue(elem,SchemaSymbols::fgATT_FINAL);
int blockSet = block != 0 ? parseBlockSet(block) : fBlockDefault;
int finalSet = final != 0 ? parseFinalSet(final) : fFinalDefault;
int elementMiscFlags = 0;
int finalValid = SchemaSymbols::RESTRICTION + SchemaSymbols::EXTENSION;
int blockValid = finalValid + SchemaSymbols::SUBSTITUTION;
if (XMLString::stringLen(block) != 0
&& XMLString::compareString(block,SchemaSymbols::fgATTVAL_POUNDALL) != 0
&& ((blockSet & blockValid) == 0)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidElementBlockValue, block);
}
if (XMLString::stringLen(final) != 0
&& XMLString::compareString(final,SchemaSymbols::fgATTVAL_POUNDALL) != 0
&& ((finalSet & finalValid) == 0)) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidElementFinalValue, final);
}
if (elem.getAttribute(SchemaSymbols::fgATT_NILLABLE).equals(SchemaSymbols::fgATTVAL_TRUE)) {
elementMiscFlags += SchemaSymbols::NILLABLE;
}
if (elem.getAttribute(SchemaSymbols::fgATT_ABSTRACT).equals(SchemaSymbols::fgATTVAL_TRUE)) {
elementMiscFlags += SchemaSymbols::ABSTRACT;
}
const XMLCh* prefix = getPrefix(name);
SchemaElementDecl* elemDecl =
new SchemaElementDecl(prefix, name, uriIndex,
(SchemaElementDecl::ModelTypes) elemType,
enclosingScope);
elemDecl->setFinalSet(finalSet);
elemDecl->setBlockSet(blockSet);
elemDecl->setMiscFlags(elementMiscFlags);
elemDecl->setCreateReason(XMLElementDecl::Declared);
return elemDecl;
}
void TraverseSchema::processAttributeDeclRef(const DOM_Element& elem,
const DOM_Element& simpleContent,
ComplexTypeInfo* const typeInfo,
const XMLCh* const refName,
const XMLCh* const useAttr) {
// REVISIT - fixedValue & defaultValue - is it valid to overwrite the 'ref'
// attribute. For now, we are keeping the actual attribute declaration info
// as is.
// Check ref representation OK - 3.2.3::3.2
if (!elem.getAttribute(SchemaSymbols::fgATT_FORM).equals("")
|| !elem.getAttribute(SchemaSymbols::fgATT_TYPE).equals("")
|| simpleContent != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeRefContentError);
}
// REVISIT - attributeGroup case
if (typeInfo == 0) {
return;
}
const XMLCh* prefix = getPrefix(refName);
const XMLCh* localPart = getLocalPart(refName);
const XMLCh* uriStr = resolvePrefixToURI(prefix);
if (XMLString::compareString(uriStr, fTargetNSURIString) != 0) {
addAttributeDeclFromAnotherSchema(localPart, uriStr, typeInfo);
return;
}
// Check for duplicate references
if (typeInfo->getAttDef(localPart,fURIStringPool->addOrFind(uriStr)) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateRefAttribute, uriStr, localPart);
return;
}
// if Global attribute registry does not contain the ref attribute, get
// the referred attribute declaration and traverse it.
if (fAttributeDeclRegistry->containsKey(localPart) == false) {
DOM_Element referredAttribute =
getTopLevelComponentByName(SchemaSymbols::fgELT_ATTRIBUTE, localPart);
if (referredAttribute == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TopLevelAttributeNotFound, refName);
return;
}
traverseAttributeDecl(referredAttribute, 0);
}
SchemaAttDef* refAttDef = (SchemaAttDef*)
fAttributeDeclRegistry->get(localPart);
if (refAttDef == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TopLevelAttributeNotFound, refName);
return;
}
bool required = (XMLString::compareString(useAttr,
SchemaSymbols::fgATTVAL_REQUIRED) == 0);
bool prohibited = (XMLString::compareString(useAttr,
SchemaSymbols::fgATTVAL_PROHIBITED) == 0);
QName* attQName = refAttDef->getAttName();
SchemaAttDef* attDef = new SchemaAttDef(attQName->getPrefix(),
attQName->getLocalPart(),
attQName->getURI(),
refAttDef->getType());
attDef->setValue(refAttDef->getValue());
attDef->setDatatypeValidator(refAttDef->getDatatypeValidator());
if (prohibited) {
attDef->setDefaultType(XMLAttDef::Prohibited);
}
else if (required){
if (refAttDef->getDefaultType() == XMLAttDef::Fixed) {
attDef->setDefaultType(XMLAttDef::Required_And_Fixed);
}
else {
attDef->setDefaultType(XMLAttDef::Required);
}
}
typeInfo->addAttDef(attDef);
}
/**
* isValidNCName
*
* NCName::= (Letter | '_') (NCNameChar)*
* NCNameChar ::= Letter | Digit | '.' | '-' | '_'
* | CombiningChar | Extender
*/
bool TraverseSchema::isValidNCName(const XMLCh* const name) {
if (XMLString::stringLen(name) == 0
|| XMLString::indexOf(name, chColon) != -1) {
return false;
}
const XMLCh* tempName = name;
XMLCh firstChar = *tempName++;
if (!XMLReader::isXMLLetter(firstChar) && firstChar != chUnderscore) {
return false;
}
while(*tempName) {
if (!XMLReader::isNameChar(*tempName++)) {
return false;
}
}
return true;
}
ContentSpecNode*
TraverseSchema::expandContentModel(ContentSpecNode* const specNode,
const DOM_Element& elem) {
unsigned int minOccurs = 0;
unsigned int maxOccurs = 0;
DOMString nOccurs = elem.getAttribute(SchemaSymbols::fgATT_MINOCCURS);
if (nOccurs.length() > 0) {
fBuffer.set(nOccurs.rawBuffer(), nOccurs.length());
XMLString::trim(fBuffer.getRawBuffer());
}
else {
fBuffer.reset();
}
if (XMLString::stringLen(fBuffer.getRawBuffer()) == 0) {
minOccurs = 1;
}
else {
XMLString::textToBin(fBuffer.getRawBuffer(), minOccurs);
}
nOccurs = elem.getAttribute(SchemaSymbols::fgATT_MAXOCCURS);
if (nOccurs.length() > 0) {
fBuffer.set(nOccurs.rawBuffer(), nOccurs.length());
}
else {
fBuffer.reset();
}
XMLCh* maxOccursStr = XMLString::replicate(fBuffer.getRawBuffer());
ArrayJanitor<XMLCh> janMaxOccur(maxOccursStr);
XMLString::trim(maxOccursStr);
bool isMaxUnbounded =
(XMLString::compareString(maxOccursStr, fgUnbounded) == 0);
if (XMLString::stringLen(maxOccursStr) == 0) {
maxOccurs = 1;
}
else {
XMLString::textToBin(maxOccursStr, maxOccurs);
}
if (minOccurs == 0 && maxOccurs == 0 && !isMaxUnbounded) {
return 0;
}
ContentSpecNode* saveNode = specNode;
ContentSpecNode* retNode = specNode;
if (minOccurs == 1 && maxOccurs == 1) {
}
else if (minOccurs == 0 && maxOccurs == 1) {
retNode = new ContentSpecNode(ContentSpecNode::ZeroOrOne,
retNode, 0);
}
else if (minOccurs == 0 && isMaxUnbounded) {
retNode = new ContentSpecNode(ContentSpecNode::ZeroOrMore,
retNode, 0);
}
else if (minOccurs == 1 && isMaxUnbounded) {
retNode = new ContentSpecNode(ContentSpecNode::OneOrMore,
retNode, 0);
}
else if (isMaxUnbounded) {
retNode = new ContentSpecNode(ContentSpecNode::OneOrMore,
retNode, 0);
for (int i=0; i < (int)(minOccurs-1); i++) {
retNode = new ContentSpecNode(ContentSpecNode::Sequence,
saveNode, retNode);
}
}
else {
if (minOccurs == 0) {
ContentSpecNode* optional =
new ContentSpecNode(ContentSpecNode::ZeroOrOne, saveNode, 0);
retNode = optional;
for (int i=0; i < (int)(maxOccurs-minOccurs-1); i++) {
retNode = new ContentSpecNode(ContentSpecNode::Sequence,
retNode, optional);
}
}
else {
for (int i=0; i < (int)(minOccurs-1); i++) {
retNode = new ContentSpecNode(ContentSpecNode::Sequence,
retNode, saveNode);
}
ContentSpecNode* optional =
new ContentSpecNode(ContentSpecNode::ZeroOrOne, saveNode, 0);
for (int j=0; j < (int)(maxOccurs-minOccurs); j++) {
retNode = new ContentSpecNode(ContentSpecNode::Sequence,
retNode, optional);
}
}
}
return retNode;
}
void TraverseSchema::processComplexContent(const XMLCh* const typeName,
const DOM_Element& childElem,
ComplexTypeInfo* const typeInfo,
const XMLCh* const baseRawName,
const XMLCh* const baseLocalPart,
const XMLCh* const baseURI,
const bool isMixed) {
ContentSpecNode* specNode = 0;
DOM_Element attrNode;
if (childElem != 0) {
// --------------------------------------------------------------------
// GROUP, ALL, SEQUENCE or CHOICE, followed by attributes, if specified.
// Note that it's possible that only attributes are specified.
// --------------------------------------------------------------------
DOMString childName = childElem.getLocalName();
if (childName.equals(SchemaSymbols::fgELT_GROUP)) {
specNode = expandContentModel(traverseGroupDecl(childElem),
childElem);
attrNode = XUtil::getNextSiblingElement(childElem);
}
else if (childName.equals(SchemaSymbols::fgELT_SEQUENCE)) {
specNode = expandContentModel(traverseChoiceSequence(childElem,
ContentSpecNode::Sequence),
childElem);
attrNode = XUtil::getNextSiblingElement(childElem);
}
else if (childName.equals(SchemaSymbols::fgELT_CHOICE)) {
specNode = expandContentModel(traverseChoiceSequence(childElem,
ContentSpecNode::Choice),
childElem);
attrNode = XUtil::getNextSiblingElement(childElem);
}
else if (childName.equals(SchemaSymbols::fgELT_ALL)) {
specNode = expandContentModel(traverseAll(childElem), childElem);
attrNode = XUtil::getNextSiblingElement(childElem);
//TO DO: REVISIT
//check that minOccurs = 1 and maxOccurs = 1
}
else if (isAttrOrAttrGroup(childElem)) {
// reset the contentType
typeInfo->setContentType(SchemaElementDecl::Any);
attrNode = childElem;
}
else {
fBuffer.set(childName.rawBuffer(), childName.length());
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType,
fBuffer.getRawBuffer());
}
}
if (isMixed) {
// TODO - check to see if we MUST have an element. What if only attributes
// were specified??
// add #PCDATA leaf
QName* tmpName = new QName(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, XMLElementDecl::fgPCDataElemId);
Janitor<QName> janQName(tmpName);
ContentSpecNode* pcdataNode = new ContentSpecNode(tmpName);
// If there was an element, the content spec becomes a choice of PCDATA and
// the element
if (specNode != 0) {
specNode = new ContentSpecNode(ContentSpecNode::Choice,
pcdataNode, specNode);
}
else {
specNode = pcdataNode;
}
}
typeInfo->setContentSpec(specNode);
// -----------------------------------------------------------------------
// Merge in information from base, if it exists
// -----------------------------------------------------------------------
ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo();
if (baseTypeInfo != 0) {
ContentSpecNode* baseSpecNode = baseTypeInfo->getContentSpec();
if (typeInfo->getDerivedBy() == SchemaSymbols::RESTRICTION) {
// check to see if the baseType permits derivation by restriction
if((baseTypeInfo->getFinalSet() & SchemaSymbols::RESTRICTION) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivationByRestriction,
baseLocalPart);
throw;
}
//REVISIT: !!!really hairy stuff to check the particle derivation OK in 5.10
}
else {
// check to see if the baseType permits derivation by extension
if((baseTypeInfo->getFinalSet() & SchemaSymbols::EXTENSION) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivationByExtension, baseLocalPart);
throw;
}
// Compose the final content model by concatenating the base and
// the current in sequence
if (baseSpecNode != 0) {
baseSpecNode = new ContentSpecNode(*baseSpecNode);
}
if (typeInfo->getContentSpec() == 0) {
typeInfo->setContentSpec(baseSpecNode);
}
else if (baseSpecNode != 0) {
typeInfo->setContentSpec(
new ContentSpecNode(ContentSpecNode::Sequence,baseSpecNode,
typeInfo->getContentSpec()));
}
}
}
else {
typeInfo->setDerivedBy(0);
}
// -------------------------------------------------------------
// Set the content type
// -------------------------------------------------------------
if (isMixed) {
typeInfo->setContentType(SchemaElementDecl::Mixed);
}
else if (typeInfo->getContentSpec() == 0) {
typeInfo->setContentType(SchemaElementDecl::Empty);
}
else {
typeInfo->setContentType(SchemaElementDecl::Children);
}
// -------------------------------------------------------------
// Now, check attributes and handle
// -------------------------------------------------------------
if (attrNode != 0) {
if (!isAttrOrAttrGroup(attrNode)) {
fBuffer.set(attrNode.getLocalName().rawBuffer(),
attrNode.getLocalName().length());
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType,
fBuffer.getRawBuffer());
}
else {
processAttributes(attrNode, baseRawName, baseLocalPart,
baseURI, typeInfo);
}
}
else if (baseTypeInfo != 0) {
processAttributes(0, baseRawName, baseLocalPart, baseURI, typeInfo);
}
}
void TraverseSchema::processBaseTypeInfo(const XMLCh* const baseName,
const XMLCh* const localPart,
const XMLCh* const uriStr,
ComplexTypeInfo* const typeInfo) {
ComplexTypeInfo* baseComplexTypeInfo = 0;
DatatypeValidator* baseDTValidator = 0;
// -------------------------------------------------------------
// check if the base type is from another schema
// -------------------------------------------------------------
if (isBaseFromAnotherSchema(uriStr)) {
baseComplexTypeInfo = getTypeInfoFromNS(uriStr, localPart);
if (baseComplexTypeInfo == 0) {
baseDTValidator = getDatatypeValidator(uriStr, localPart);
if (baseDTValidator == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uriStr, localPart);
throw;
}
}
}
// -------------------------------------------------------------
// type must be from same schema
// -------------------------------------------------------------
else {
fBuffer.set(uriStr);
fBuffer.append(chComma);
fBuffer.append(localPart);
// assume the base is a complexType and try to locate the base type first
baseComplexTypeInfo = fComplexTypeRegistry->get(fBuffer.getRawBuffer());
// if not found, 2 possibilities:
// 1: ComplexType in question has not been compiled yet;
// 2: base is SimpleTYpe;
if (baseComplexTypeInfo == 0) {
baseDTValidator = getDatatypeValidator(uriStr, localPart);
if (baseDTValidator == 0) {
int baseTypeSymbol;
DOM_Element baseTypeNode = getTopLevelComponentByName(
SchemaSymbols::fgELT_COMPLEXTYPE, localPart);
if (baseTypeNode != 0) {
baseTypeSymbol = traverseComplexTypeDecl(baseTypeNode);
baseComplexTypeInfo = fComplexTypeRegistry->get(
fStringPool.getValueForId(baseTypeSymbol));
}
else {
baseTypeNode = getTopLevelComponentByName(
SchemaSymbols::fgELT_SIMPLETYPE, localPart);
if (baseTypeNode != 0) {
baseTypeSymbol = traverseSimpleTypeDecl(baseTypeNode);
baseDTValidator = getDatatypeValidator(uriStr, localPart);
if (baseDTValidator == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uriStr, localPart, uriStr);
throw;
}
}
else {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::BaseTypeNotFound, baseName);
throw;
}
}
}
}
} // end else (type must be from same schema)
typeInfo->setBaseComplexTypeInfo(baseComplexTypeInfo);
typeInfo->setBaseDatatypeValidator(baseDTValidator);
}
ComplexTypeInfo* TraverseSchema::getTypeInfoFromNS(const XMLCh* const uriStr,
const XMLCh* const localPart)
{
Grammar* grammar = fGrammarResolver->getGrammar(uriStr);
if (grammar != 0 && grammar->getGrammarType() == Grammar::SchemaGrammarType) {
fBuffer.set(uriStr);
fBuffer.append(chComma);
fBuffer.append(localPart);
ComplexTypeInfo* typeInfo =
((SchemaGrammar*)grammar)->getComplexTypeRegistry()->get(fBuffer.getRawBuffer());
return typeInfo;
}
else {
reportSchemaError(XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr);
}
return 0;
}
bool TraverseSchema::isValidFacet(const XMLCh* const component,
const XMLCh* const name) {
// TO DO
return true;
}
void TraverseSchema::processAttributes(const DOM_Element& attElem,
const XMLCh* const baseRawName,
const XMLCh* const baseLocalPart,
const XMLCh* const baseURI,
ComplexTypeInfo* const typeInfo) {
// If we do not have a complexTypeInfo, then what is the point of
// processing.
if (typeInfo == 0) {
return;
}
DOM_Element child = attElem;
SchemaAttDef* attWildCard = 0;
Janitor<SchemaAttDef> janAttWildCard(0);
for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
DOMString childName = child.getLocalName();
if (childName.equals(SchemaSymbols::fgELT_ATTRIBUTE)) {
traverseAttributeDecl(child, typeInfo);
}
else if (childName.equals(SchemaSymbols::fgELT_ATTRIBUTEGROUP)) {
// TO DO
}
else if (childName.equals(SchemaSymbols::fgELT_ANYATTRIBUTE) ) {
attWildCard = traverseAnyAttribute(child);
janAttWildCard.reset(attWildCard);
}
else {
fBuffer.set(childName.rawBuffer(), childName.length());
reportSchemaError(XMLUni::fgXMLErrDomain,
XMLErrs::InvalidChildInComplexType,
fBuffer.getRawBuffer());
}
}
// -------------------------------------------------------------
// Handle wild card/any attribute
// -------------------------------------------------------------
// TO DO - based on attributeGroup
if (attWildCard != 0) {
}
else {
}
// -------------------------------------------------------------
// merge in base type's attribute decls
// -------------------------------------------------------------
ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo();
SchemaAttDef* baseAttWildCard = 0;
if (baseTypeInfo != 0 && baseTypeInfo->hasAttDefs()) {
SchemaAttDefList& baseAttList = (SchemaAttDefList&)
baseTypeInfo->getAttDefList();
while (baseAttList.hasMoreElements()) {
SchemaAttDef& attDef = (SchemaAttDef&) baseAttList.nextElement();
XMLAttDef::AttTypes attType = attDef.getType();
QName* attName = attDef.getAttName();
if (attType == XMLAttDef::Any_Any
|| attType == XMLAttDef::Any_List
|| attType == XMLAttDef::Any_Local
|| attType == XMLAttDef::Any_Other) {
// TO DO
if (attWildCard == 0) {
baseAttWildCard = &attDef;
}
continue;
}
// if found a duplicate, if it is derived by restriction,
// then skip the one from the base type
if (typeInfo->contains(attName->getLocalPart())) {
if (typeInfo->getDerivedBy() == SchemaSymbols::RESTRICTION) {
continue;
}
}
SchemaAttDef* newAttDef = new SchemaAttDef(attName->getPrefix(),
attName->getLocalPart(),
attName->getURI(),
attDef.getValue(),
attDef.getType(),
attDef.getDefaultType(),
attDef.getEnumeration());
newAttDef->setDatatypeValidator(attDef.getDatatypeValidator());
typeInfo->addAttDef(newAttDef);
}
}
// -------------------------------------------------------------
// insert wildcard attributes
// -------------------------------------------------------------
if (attWildCard != 0) {
if (attWildCard->getType() != XMLAttDef::AttTypes_Unknown) {
typeInfo->addAttDef(attWildCard);
janAttWildCard.orphan();
}
}
else if (baseAttWildCard != 0) {
QName* attName = baseAttWildCard->getAttName();
SchemaAttDef* newAttDef = new SchemaAttDef(attName->getPrefix(),
attName->getLocalPart(),
attName->getURI(),
baseAttWildCard->getValue(),
baseAttWildCard->getType(),
baseAttWildCard->getDefaultType(),
baseAttWildCard->getEnumeration());
newAttDef->setDatatypeValidator(baseAttWildCard->getDatatypeValidator());
typeInfo->addAttDef(newAttDef);
}
}
int
TraverseSchema::addAttributeDeclFromAnotherSchema(const XMLCh* const name,
const XMLCh* const uri,
ComplexTypeInfo* const typeInfo)
{
SchemaGrammar* aGrammar = (SchemaGrammar*)
fGrammarResolver->getGrammar(uri);
if (XMLString::stringLen(uri) == 0 || aGrammar == 0
|| aGrammar->getGrammarType() != Grammar::SchemaGrammarType) {
reportSchemaError(XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uri);
return -1;
}
if (aGrammar->getAttributeDeclRegistry() == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoAttributeInSchema, name, uri);
return -1;
}
SchemaAttDef* tempAtt = (SchemaAttDef*)
aGrammar->getAttributeDeclRegistry()->get(name);
if (tempAtt == 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoAttributeInSchema, name, uri);
return -1;
}
if (typeInfo!= 0) {
QName* attName = tempAtt->getAttName();
if (typeInfo->getAttDef(attName->getLocalPart(), attName->getURI()) != 0) {
reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateRefAttribute, uri, name);
return -1;
}
SchemaAttDef* newAtt = new SchemaAttDef(attName->getPrefix(),
attName->getLocalPart(),
attName->getURI(),
tempAtt->getValue(),
tempAtt->getType(),
tempAtt->getDefaultType(),
tempAtt->getEnumeration());
newAtt->setDatatypeValidator(tempAtt->getDatatypeValidator());
typeInfo->addAttDef(newAtt);
}
return 0;
}
void TraverseSchema::defaultComplexTypeInfo(ComplexTypeInfo* const typeInfo) {
if (typeInfo) {
typeInfo->setDerivedBy(0);
typeInfo->setContentType(SchemaElementDecl::Any);
typeInfo->setDatatypeValidator(0);
typeInfo->setContentSpec(0);
}
}
// ---------------------------------------------------------------------------
// TraverseSchema: Error reporting methods
// ---------------------------------------------------------------------------
void TraverseSchema::reportSchemaError(const XMLCh* const msgDomain,
const int errorCode) {
if (fScanner && XMLString::compareString(msgDomain, XMLUni::fgXMLErrDomain) == 0) {
fScanner->emitError((XMLErrs::Codes) errorCode);
}
else if (fValidator && fScanner->getDoValidation()
&& XMLString::compareString(msgDomain, XMLUni::fgValidityDomain) == 0) {
fValidator->emitError((XMLValid::Codes) errorCode);
}
}
void TraverseSchema::reportSchemaError(const XMLCh* const msgDomain,
const int errorCode,
const XMLCh* const text1,
const XMLCh* const text2,
const XMLCh* const text3,
const XMLCh* const text4) {
if (fScanner && XMLString::compareString(msgDomain, XMLUni::fgXMLErrDomain) == 0) {
fScanner->emitError((XMLErrs::Codes) errorCode,text1,text2,text3,text4);
}
else if (fValidator && fScanner->getDoValidation()
&& XMLString::compareString(msgDomain, XMLUni::fgValidityDomain) == 0) {
fValidator->emitError((XMLValid::Codes) errorCode,text1,text2,text3,text4);
}
}
/**
* End of file TraverseSchema.cpp
*/
1.1 xml-xerces/c/src/validators/schema/TraverseSchema.hpp
Index: TraverseSchema.hpp
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Id: TraverseSchema.hpp,v 1.1 2001/05/03 19:18:07 knoaman Exp $
*/
#if !defined(TRAVERSESCHEMA_HPP)
#define TRAVERSESCHEMA_HPP
/**
* Instances of this class get delegated to Traverse the Schema and
* to populate the SchemaGrammar internal representation.
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <util/XMLUniDefs.hpp>
#include <util/StringPool.hpp>
#include <dom/DOM_Element.hpp>
#include <framework/XMLBuffer.hpp>
#include <validators/schema/SchemaSymbols.hpp>
#include <util/RefStackOf.hpp>
// ---------------------------------------------------------------------------
// Forward Declarations
// ---------------------------------------------------------------------------
class GrammarResolver;
class SchemaGrammar;
class EntityResolver;
class XMLValidator;
class XMLScanner;
class DatatypeValidator;
class DatatypeValidatorFactory;
class QName;
class ComplexTypeInfo;
class SchemaElementDecl;
class XMLAttDef;
class ContentSpecNode;
class NamespaceScope;
class SchemaAttDef;
class VALIDATORS_EXPORT TraverseSchema
{
public:
// -----------------------------------------------------------------------
// Public Constructors/Destructor
// -----------------------------------------------------------------------
TraverseSchema
(
const DOM_Element& schemaRoot
, XMLStringPool* const stringPool
, SchemaGrammar* const schemaGrammar
, GrammarResolver* const grammarResolver
, XMLScanner* const xmlScanner
, XMLValidator* const xmlValidator
, const XMLCh* const schemaURL
, EntityResolver* const entityResolver
);
TraverseSchema
(
const DOM_Element& schemaRoot
, XMLStringPool* const stringPool
, SchemaGrammar* const schemaGrammar
, GrammarResolver* const grammarResolver
, XMLScanner* const xmlScanner
, XMLValidator* const xmlValidator
, const XMLCh* const schemaURL
);
TraverseSchema
(
const DOM_Element& schemaRoot
, XMLStringPool* const stringPool
, SchemaGrammar* const schemaGrammar
, GrammarResolver* const grammarResolver
, XMLScanner* const xmlScanner
, XMLValidator* const xmlValidator
);
~TraverseSchema();
private:
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
TraverseSchema();
TraverseSchema(const TraverseSchema&);
void operator=(const TraverseSchema&);
// -----------------------------------------------------------------------
// CleanUp methods
// -----------------------------------------------------------------------
void cleanUp();
// -----------------------------------------------------------------------
// Traversal methods
// -----------------------------------------------------------------------
/**
* Traverse the Schema DOM tree
*/
void doTraverseSchema();
void traverseAnnotationDecl(const DOM_Element& childElem);
void traverseInclude(const DOM_Element& childElem);
void traverseImport(const DOM_Element& childElem);
void traverseRedefine(const DOM_Element& childElem);
void traverseAttributeDecl(const DOM_Element& childElem,
ComplexTypeInfo* const typeInfo);
void traverseSimpleContentDecl(const XMLCh* const typeName,
const DOM_Element& contentDecl,
ComplexTypeInfo* const typeInfo);
void traverseComplexContentDecl(const XMLCh* const typeName,
const DOM_Element& contentDecl,
ComplexTypeInfo* const typeInfo,
const bool isMixed);
int traverseSimpleTypeDecl(const DOM_Element& childElem);
int traverseComplexTypeDecl(const DOM_Element& childElem);
int traverseByList(const DOM_Element& rootElem,
const DOM_Element& contentElem,
const int typeNameIndex,
const int finalSet);
int traverseByRestriction(const DOM_Element& rootElem,
const DOM_Element& contentElem,
const int typeNameIndex,
const int finalSet);
int traverseByUnion(const DOM_Element& rootElem,
const DOM_Element& contentElem,
const int typeNameIndex,
const int finalSet);
QName* traverseElementDecl(const DOM_Element& childElem);
XMLCh* traverseNotationDecl(const DOM_Element& childElem);
ContentSpecNode* traverseChoiceSequence(const DOM_Element& elemDecl,
const int modelGroupType);
ContentSpecNode* traverseAny(const DOM_Element& anyDecl);
ContentSpecNode* traverseGroupDecl(const DOM_Element& childElem);
ContentSpecNode* traverseAll(const DOM_Element& allElem);
SchemaAttDef* traverseAnyAttribute(const DOM_Element& elem);
// -----------------------------------------------------------------------
// Error Reporting methods
// -----------------------------------------------------------------------
void reportSchemaError(const XMLCh* const msgDomain, const int errorCode);
void reportSchemaError(const XMLCh* const msgDomain,
const int errorCode,
const XMLCh* const text1,
const XMLCh* const text2 = 0,
const XMLCh* const text3 = 0,
const XMLCh* const text4 = 0);
// -----------------------------------------------------------------------
// Private Helper methods
// -----------------------------------------------------------------------
/**
* Retrived the Namespace mapping from the schema element
*/
void retrieveNamespaceMapping();
/**
* Extract all top-level attribute, attributeGroup, and group Decls and
* put them in the 3 hash tables in the SchemaGrammar.
*/
void extractTopLevel3Components(const DOM_Element& rootElem);
/**
* Loop through the children, and traverse the corresponding schema type
* type declaration (simpleType, complexType, import, ....)
*/
void processChildren(const DOM_Element& root);
/**
* Parameters:
* rootElem - top element for a given type declaration
* contentElem - content must be annotation? or some other simple content
* isEmpty: - true if (annotation?, smth_else), false if (annotation?)
*
* Check for Annotation if it is present, traverse it. If a sibling is
* found and it is not an annotation return it, otherwise return 0.
* Used by traverseSimpleTypeDecl.
*/
DOM_Element checkContent(const DOM_Element& rootElem,
const DOM_Element& contentElem,
const bool isEmpty);
/**
* Parameters:
* contentElem - content element to check
*
* Check for identity constraints content.
*/
DOM_Element checkIdentityConstraintContent(const DOM_Element& contentElem);
DatatypeValidator* getDatatypeValidator(const XMLCh* const uriStr,
const XMLCh* const localPartStr);
/**
* Return qualified name of a given type name index from the string pool
* If a target name space exist, it is returned as part of the name
*
* The allocation will be handled internally, and the caller should not
* delete the returned pointer.
*/
XMLCh* getQualifiedName(const int typeNameIndex);
/**
* Process simpleType content of a list|restriction|union
* Return a dataype validator if valid type, otherwise 0.
*/
DatatypeValidator* checkForSimpleTypeValidator(const DOM_Element& content);
/**
* Process complexType content of an element
* Return a ComplexTypeInfo if valid type, otherwise 0.
*/
ComplexTypeInfo* checkForComplexTypeInfo(const DOM_Element& content);
/**
* Return DatatypeValidator available for the baseTypeStr.
*/
DatatypeValidator* findDTValidator(const DOM_Element& rootElem,
const XMLCh* const baseTypeStr,
const int baseRefContext);
/**
* Return a compenent defined as a top level in a schema grammar
*
* In redefine we've not only got to look at the space of the thing we
* are redefining but at the original schema too. The idea is to start
* from the top, then go down through our list of schemas until we find
* what we want. This should not often be necessary, because we've
* processed all redefined schemas, but there are conditions in which not
* all elements so redefined may have been promoted to the topmost level.
*/
DOM_Element getTopLevelComponentByName(const XMLCh* const compCategory,
const XMLCh* const name);
const XMLCh* resolvePrefixToURI(const XMLCh* const prefix);
/**
* Return whether an element is defined as a top level schema component
* or not.
*/
bool isTopLevelComponent(const DOM_Element& elem);
/**
* Return the prefix for a given rawname string
*
* Function allocated, caller managed (facm) - pointer to be deleted by
* caller.
*/
const XMLCh* getPrefix(const XMLCh* const rawName);
/**
* Return the local for a given rawname string
*
* caller allocated, caller managed (cacm)
*/
const XMLCh* getLocalPart(const XMLCh* const rawName);
/**
* Process a 'ref' of an Element declaration
*/
QName* processElementDeclRef(const DOM_Element& elem,
const XMLCh* const refName);
/**
* Process a 'ref' of an Attribute declaration
*/
void processAttributeDeclRef(const DOM_Element& elem,
const DOM_Element& simpleTypeContent,
ComplexTypeInfo* const typeInfo,
const XMLCh* const refName,
const XMLCh* const useVal);
/**
* Parse block & final items
*/
int parseBlockSet(const XMLCh* const blockStr);
int parseFinalSet(const XMLCh* const finalStr);
/**
* Return true if a name is an identity constraint, otherwise false
*/
bool isIdentityConstraintName(const XMLCh* const constraintName);
/**
* Check a 'ref' declaration representation constraint
*/
bool isValidRefDeclaration(const DOM_Element& elem);
/**
* If 'typeStr' belongs to a different schema, return that schema URI,
* otherwise return 0;
*/
const XMLCh* checkTypeFromAnotherSchema(const XMLCh* const typeStr);
/**
* Return the datatype validator for a given element type attribute if
* the type is a simple type
*/
DatatypeValidator* getElementTypeValidator(const XMLCh* const typeStr,
bool& noErrorDetected,
const XMLCh* const otherSchemaURI,
bool errorCheck = false);
/**
* Return the complexType info for a given element type attribute if
* the type is a complex type
*/
ComplexTypeInfo* getElementComplexTypeInfo(const XMLCh* const typeStr,
bool& noErrorDetected,
const XMLCh* const otherSchemaURI);
/**
* Return schema element declaration for a given substituteGroup element
* name
*/
SchemaElementDecl* getSubstituteGroupElemDecl(const XMLCh* const name,
bool& noErrorDetected);
/**
* Return a Schema element declared in another schema
*/
SchemaElementDecl* getElementDeclFromNS(const XMLCh* const nameUri,
const XMLCh* const localPart);
/**
* Check validity constraint of a substitutionGroup attribute in
* an element declaration
*/
bool isSubstitutionGroupValid(const SchemaElementDecl* const elemDecl,
const ComplexTypeInfo* const typeInfo,
const DatatypeValidator* const validator,
const XMLCh* const elemName);
/**
* Create a 'SchemaElementDecl' object and add it to SchemaGrammar
*/
SchemaElementDecl* createSchemaElementDecl(const DOM_Element& elem,
const bool topLevel,
const unsigned short elemType);
/**
* Return the value of a given attribute name from an element node
*/
const XMLCh* getElementAttValue(const DOM_Element& elem,
const XMLCh* const attName);
/**
* Checks whether an name is a valid NCName.
*/
bool isValidNCName(const XMLCh* const name);
ContentSpecNode* expandContentModel(ContentSpecNode* const specNode,
const DOM_Element& elem);
/**
* Process complex content for a complexType
*/
void processComplexContent(const XMLCh* const typeName,
const DOM_Element& childElem,
ComplexTypeInfo* const typeInfo,
const XMLCh* const baseRawName,
const XMLCh* const baseLocalPart,
const XMLCh* const baseURI,
const bool isMixed);
/**
* Process "base" information for a complexType
*/
void processBaseTypeInfo(const XMLCh* const baseName,
const XMLCh* const localPart,
const XMLCh* const uriStr,
ComplexTypeInfo* const typeInfo);
/**
* Check if base is from another schema
*/
bool isBaseFromAnotherSchema(const XMLCh* const baseURI);
/**
* Get complexType infp from another schema
*/
ComplexTypeInfo* getTypeInfoFromNS(const XMLCh* const uriStr,
const XMLCh* const localPart);
/**
* Returns true if 'name' is a valid facet for a given 'component',
* otherwise false
*/
bool isValidFacet(const XMLCh* const component, const XMLCh* const name);
bool isAttrOrAttrGroup(const DOM_Element& elem);
/**
* Process attributes of a complex type
*/
void processAttributes(const DOM_Element& elem,
const XMLCh* const baseRawName,
const XMLCh* const baseLocalPart,
const XMLCh* const baseURI,
ComplexTypeInfo* const typeInfo);
/**
* Generate a name for an anonymous type
*/
const XMLCh* genAnonTypeName(const XMLCh* const prefix,
int& anonCount);
int addAttributeDeclFromAnotherSchema(const XMLCh* const name,
const XMLCh* const uri,
ComplexTypeInfo* const typeInfo);
void defaultComplexTypeInfo(ComplexTypeInfo* const typeInfo);
// -----------------------------------------------------------------------
// Private data members
// -----------------------------------------------------------------------
bool fElementDefaultQualified;
bool fAttributeDefaultQualified;
int fTargetNSURI;
int fCurrentScope;
int fSimpleTypeAnonCount;
int fComplexTypeAnonCount;
int fFinalDefault;
int fBlockDefault;
int fScopeCount;
DOM_Element fSchemaRootElement;
XMLCh* fTargetNSURIString;
XMLCh* fCurrentSchemaURL;
DatatypeValidatorFactory* fDatatypeRegistry;
GrammarResolver* fGrammarResolver;
SchemaGrammar* fSchemaGrammar;
EntityResolver* fEntityResolver;
XMLStringPool* fURIStringPool;
XMLBuffer fBuffer;
XMLValidator* fValidator;
XMLScanner* fScanner;
NamespaceScope* fNamespaceScope;
RefHashTableOf<XMLAttDef>* fAttributeDeclRegistry;
RefHashTableOf<ComplexTypeInfo>* fComplexTypeRegistry;
RefStackOf<XMLCh>* fCurrentTypeNameStack;
static XMLStringPool fStringPool;
};
// ---------------------------------------------------------------------------
// TraverseSchema: CleanUp methods
// ---------------------------------------------------------------------------
inline void TraverseSchema::cleanUp() {
delete [] fTargetNSURIString;
delete [] fCurrentSchemaURL;
delete fCurrentTypeNameStack;
}
// ---------------------------------------------------------------------------
// TraverseSchema: Helper methods
// ---------------------------------------------------------------------------
inline const XMLCh* TraverseSchema::getPrefix(const XMLCh* const rawName) {
int colonIndex = XMLString::indexOf(rawName, chColon);
if (colonIndex == -1 || colonIndex == 0) {
return XMLUni::fgZeroLenString;
}
fBuffer.set(rawName, colonIndex + 1);
XMLString::subString(fBuffer.getRawBuffer(), rawName, 0, colonIndex);
unsigned int nameId = fStringPool.addOrFind(fBuffer.getRawBuffer());
return fStringPool.getValueForId(nameId);
}
inline const XMLCh* TraverseSchema::getLocalPart(const XMLCh* const rawName) {
int colonIndex = XMLString::indexOf(rawName, chColon);
int rawNameLen = XMLString::stringLen(rawName);
if (colonIndex + 1 == rawNameLen) {
return XMLUni::fgZeroLenString;
}
if (colonIndex == -1) {
fBuffer.set(rawName, rawNameLen);
}
else {
fBuffer.set(rawName, rawNameLen - colonIndex);
XMLString::subString(fBuffer.getRawBuffer(), rawName,
colonIndex + 1, rawNameLen);
}
unsigned int nameId = fStringPool.addOrFind(fBuffer.getRawBuffer());
return fStringPool.getValueForId(nameId);
}
inline bool
TraverseSchema::isValidRefDeclaration(const DOM_Element& elem) {
return !(elem.getAttribute(SchemaSymbols::fgATT_ABSTRACT).length() != 0
|| elem.getAttribute(SchemaSymbols::fgATT_NILLABLE).length() != 0
|| elem.getAttribute(SchemaSymbols::fgATT_BLOCK).length() != 0
|| elem.getAttribute(SchemaSymbols::fgATT_FINAL).length() != 0
|| elem.getAttribute(SchemaSymbols::fgATT_TYPE).length() != 0
|| elem.getAttribute(SchemaSymbols::fgATT_DEFAULT).length() != 0
|| elem.getAttribute(SchemaSymbols::fgATT_FIXED).length() != 0
|| elem.getAttribute(SchemaSymbols::fgATT_SUBSTITUTIONGROUP).length() != 0);
}
inline
const XMLCh* TraverseSchema::getElementAttValue(const DOM_Element& elem,
const XMLCh* const attName) {
DOMString attValue = elem.getAttribute(attName);
if (attValue.length() > 0) {
fBuffer.set(attValue.rawBuffer(), attValue.length());
unsigned int elemId = fStringPool.addOrFind(fBuffer.getRawBuffer());
return fStringPool.getValueForId(elemId);
}
return 0;
}
inline bool TraverseSchema::isBaseFromAnotherSchema(const XMLCh* const baseURI)
{
if (XMLString::compareString(baseURI,fTargetNSURIString) != 0
&& XMLString::compareString(baseURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) != 0
&& XMLString::stringLen(baseURI) != 0) {
//REVISIT, !!!! a hack: for schema that has no
//target namespace, e.g. personal-schema.xml
return true;
}
return false;
}
inline bool TraverseSchema::isAttrOrAttrGroup(const DOM_Element& elem) {
DOMString elementName = elem.getLocalName();
if (elementName.equals(SchemaSymbols::fgELT_ATTRIBUTE) ||
elementName.equals(SchemaSymbols::fgELT_ATTRIBUTEGROUP) ||
elementName.equals(SchemaSymbols::fgELT_ANYATTRIBUTE)) {
return true;
}
return false;
}
inline const XMLCh* TraverseSchema::genAnonTypeName(const XMLCh* const prefix,
int& anonCount) {
XMLCh anonCountStr[16]; // a count of 15 digits should be enough
XMLString::binToText(anonCount++, anonCountStr, 15, 10);
fBuffer.set(prefix);
fBuffer.append(anonCountStr);
int anonTypeId = fStringPool.addOrFind(fBuffer.getRawBuffer());
return fStringPool.getValueForId(anonTypeId);
}
#endif
/**
* End of file TraverseSchema.hpp
*/
---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org