diff --git a/src/xercesc/validators/common/ContentSpecNode.cpp b/src/xercesc/validators/common/ContentSpecNode.cpp
index 3da2c08b3d728c21d28877450231b0ee80297abe..b7fb41ba3b2a1d010d5131eaf5e89fb7d784a0d4 100644
--- a/src/xercesc/validators/common/ContentSpecNode.cpp
+++ b/src/xercesc/validators/common/ContentSpecNode.cpp
@@ -69,6 +69,7 @@
 #include <xercesc/framework/XMLBuffer.hpp>
 #include <xercesc/validators/common/ContentSpecNode.hpp>
 #include <xercesc/validators/DTD/DTDValidator.hpp>
+#include <xercesc/validators/schema/SchemaSymbols.hpp>
 
 // ---------------------------------------------------------------------------
 //  ContentSpecNode: Copy Constructor
@@ -228,3 +229,75 @@ void ContentSpecNode::formatSpec(XMLBuffer&      bufToFill) const
     if (fType == ContentSpecNode::Leaf)
         bufToFill.append(chCloseParen);
 }
+
+int ContentSpecNode::getMinTotalRange() const {
+
+    int min = fMinOccurs;
+
+    if (fType == ContentSpecNode::Sequence
+        || fType == ContentSpecNode::All
+        || fType == ContentSpecNode::Choice) {
+
+        int minFirst = fFirst->getMinTotalRange();
+
+        if (fSecond) {
+
+            int minSecond = fSecond->getMinTotalRange();
+
+            if (fType == ContentSpecNode::Choice) {
+                min = min * ((minFirst < minSecond)? minFirst : minSecond);
+            }
+            else {
+                min = min * (minFirst + minSecond);
+            }
+        }
+        else
+            min = min * minFirst;
+    }
+
+    return min;
+}
+
+int ContentSpecNode::getMaxTotalRange() const {
+
+    int max = fMaxOccurs;
+
+    if (max == SchemaSymbols::UNBOUNDED) {
+         return SchemaSymbols::UNBOUNDED;
+    }
+
+    if (fType == ContentSpecNode::Sequence
+        || fType == ContentSpecNode::All
+        || fType == ContentSpecNode::Choice) {
+
+        int maxFirst = fFirst->getMaxTotalRange();
+
+        if (maxFirst == SchemaSymbols::UNBOUNDED) {
+             return SchemaSymbols::UNBOUNDED;
+        }
+
+        if (fSecond) {
+
+            int maxSecond = fSecond->getMaxTotalRange();
+
+            if (maxSecond == SchemaSymbols::UNBOUNDED) {
+                return SchemaSymbols::UNBOUNDED;
+            }
+            else {
+
+                if (fType == ContentSpecNode::Choice) {
+                    max = max * (maxFirst > maxSecond) ? maxFirst : maxSecond;
+                }
+                else {
+                    max = max * (maxFirst + maxSecond);
+                }
+            }
+        }
+        else {
+            max = max * maxFirst;
+        }
+    }
+
+    return max;
+}
+
diff --git a/src/xercesc/validators/common/ContentSpecNode.hpp b/src/xercesc/validators/common/ContentSpecNode.hpp
index e09d938ee1bbcfb1bc832e6e38894f4cfdd9e6cd..52a0e1353eac609f61b59db1af086f694e56abfc 100644
--- a/src/xercesc/validators/common/ContentSpecNode.hpp
+++ b/src/xercesc/validators/common/ContentSpecNode.hpp
@@ -56,8 +56,11 @@
 
 /*
  * $Log$
- * Revision 1.1  2002/02/01 22:22:38  peiyongz
- * Initial revision
+ * Revision 1.2  2002/03/21 15:41:48  knoaman
+ * Move behavior from TraverseSchema.
+ *
+ * Revision 1.1.1.1  2002/02/01 22:22:38  peiyongz
+ * sane_include
  *
  * Revision 1.19  2001/12/06 17:50:42  tng
  * Performance Enhancement. The ContentSpecNode constructor always copied the QName
@@ -234,6 +237,9 @@ public :
     //  Miscellaneous
     // -----------------------------------------------------------------------
     void formatSpec (XMLBuffer&      bufToFill)   const;
+    bool hasAllContent();
+    int  getMinTotalRange() const;
+    int  getMaxTotalRange() const;
 
 
 private :
@@ -501,4 +507,16 @@ inline void ContentSpecNode::setAdoptSecond(bool newState)
     fAdoptSecond = newState;
 }
 
+// ---------------------------------------------------------------------------
+//  ContentSpecNode: Miscellaneous
+// ---------------------------------------------------------------------------
+inline bool ContentSpecNode::hasAllContent() {
+
+    if (fType == ContentSpecNode::ZeroOrOne) {
+        return (fFirst->getType() == ContentSpecNode::All);
+    }
+
+    return (fType == ContentSpecNode::All);
+}
+
 #endif