private void EndElementIdentityConstraints() {
for (int ci = this.validationStack.Length - 1; ci >= this.startIDConstraint; ci --) {
// no constraint for this level
if (((ValidationState)(this.validationStack[ci])).Constr == null) {
continue;
}
// else
foreach (ConstraintStruct conuct in ((ValidationState)(this.validationStack[ci])).Constr) {
// EndChildren
// axisFields is not null, but may be empty
foreach (LocatedActiveAxis laxis in conuct.axisFields) {
// check field from here
// isMatched is false when nextElement is null. so needn't change this part.
if (laxis.isMatched) {
Debug.WriteLine("Element Field Filling Value!");
Debug.WriteLine("Name: " + reader.LocalName + "\t|\tURI: " + reader.NamespaceURI + "\t|\tValue: " + reader.TypedValueObject + "\n");
// fill value
laxis.isMatched = false;
if (laxis.Ks[laxis.Column] != null) {
// [field...] should be evaluated to either an empty node-set or a node-set with exactly one member
// two matches... already existing field value in the table.
SendValidationEvent (Res.Sch_FieldSingleValueExpected, reader.LocalName);
}
else {
// for element, reader.Value = "";
string stringValue = !hasSibling ? textString : textValue.ToString(); // only for identity-constraint exception reporting
if(reader.TypedValueObject != null && stringValue.Length != 0) {
laxis.Ks[laxis.Column] = new TypedObject(reader.TypedValueObject,stringValue,context.ElementDecl.Datatype);
}
}
}
// EndChildren
laxis.EndElement(reader.LocalName, reader.NamespaceURI);
}
if (conuct.axisSelector.EndElement(reader.LocalName, reader.NamespaceURI)) {
// insert key sequence into hash (+ located active axis tuple leave for later)
KeySequence ks = conuct.axisSelector.PopKS();
// unqualified keysequence are not allowed
switch (conuct.constraint.Role) {
case CompiledIdentityConstraint.ConstraintRole.Key:
if (! ks.IsQualified()) {
//Key's fields can't be null... if we can return context node's line info maybe it will be better
//only keymissing & keyduplicate reporting cases are necessary to be dealt with... 3 places...
SendValidationEvent(new XmlSchemaException(Res.Sch_MissingKey, conuct.constraint.name.ToString(), reader.BaseURI, ks.PosLine, ks.PosCol));
}
else if (conuct.qualifiedTable.Contains (ks)) {
SendValidationEvent(new XmlSchemaException(Res.Sch_DuplicateKey,
new string[2] {ks.ToString(), conuct.constraint.name.ToString()},
reader.BaseURI, ks.PosLine, ks.PosCol));
}
else {
conuct.qualifiedTable.Add (ks, ks);
}
break;
case CompiledIdentityConstraint.ConstraintRole.Unique:
if (! ks.IsQualified()) {
continue;
}
if (conuct.qualifiedTable.Contains (ks)) {
// unique or key checking confliction
SendValidationEvent(new XmlSchemaException(Res.Sch_DuplicateKey,
new string[2] {ks.ToString(), conuct.constraint.name.ToString()},
reader.BaseURI, ks.PosLine, ks.PosCol));
}
else {
conuct.qualifiedTable.Add (ks, ks);
}
break;
case CompiledIdentityConstraint.ConstraintRole.Keyref:
// is there any possibility:
// 2 keyrefs: value is equal, type is not
// both put in the hashtable, 1 reference, 1 not
if (conuct.qualifiedTable != null) { //Will be null in cases when the keyref is outside the scope of the key, that is not allowed by our impl
if (! ks.IsQualified() || conuct.qualifiedTable.Contains (ks)) {
continue;
}
conuct.qualifiedTable.Add (ks, ks);
}
break;
}
}
}
}
// current level's constraint struct
ConstraintStruct[] vcs = ((ValidationState)(this.validationStack[this.validationStack.Length - 1])).Constr;
if ( vcs != null) {
// validating all referencing tables...
foreach (ConstraintStruct conuct in vcs) {
if (( conuct.constraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref)
|| (conuct.keyrefTable == null)) {
continue;
}
foreach (KeySequence ks in conuct.keyrefTable.Keys) {
if (! conuct.qualifiedTable.Contains (ks)) {
SendValidationEvent(new XmlSchemaException(Res.Sch_UnresolvedKeyref, ks.ToString(),
reader.BaseURI, ks.PosLine, ks.PosCol));
}
}
}
}
}