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
ConstraintStruct[] constraints = ((ValidationState)this.validationStack[ci]).Constr;
for (int i = 0; i < constraints.Length; ++i)
{
// EndChildren
// axisFields is not null, but may be empty
for (int j = 0; j < constraints[i].axisFields.Count; ++j)
{
LocatedActiveAxis laxis = (LocatedActiveAxis)constraints[i].axisFields[j];
// 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 (constraints[i].axisSelector.EndElement(reader.LocalName, reader.NamespaceURI))
{
// insert key sequence into hash (+ located active axis tuple leave for later)
KeySequence ks = constraints[i].axisSelector.PopKS();
// unqualified keysequence are not allowed
switch (constraints[i].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, constraints[i].constraint.name.ToString(), reader.BaseURI, ks.PosLine, ks.PosCol));
}
else if (constraints[i].qualifiedTable.Contains(ks))
{
// unique or key checking value confliction
// for redundant key, reporting both occurings
// doesn't work... how can i retrieve value out??
SendValidationEvent(new XmlSchemaException(Res.Sch_DuplicateKey,
new string[2] {
ks.ToString(), constraints[i].constraint.name.ToString()
},
reader.BaseURI, ks.PosLine, ks.PosCol));
}
else
{
constraints[i].qualifiedTable.Add(ks, ks);
}
break;
case CompiledIdentityConstraint.ConstraintRole.Unique:
if (!ks.IsQualified())
{
continue;
}
if (constraints[i].qualifiedTable.Contains(ks))
{
// unique or key checking confliction
SendValidationEvent(new XmlSchemaException(Res.Sch_DuplicateKey,
new string[2] {
ks.ToString(), constraints[i].constraint.name.ToString()
},
reader.BaseURI, ks.PosLine, ks.PosCol));
}
else
{
constraints[i].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 (constraints[i].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() || constraints[i].qualifiedTable.Contains(ks))
{
continue;
}
constraints[i].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...
for (int i = 0; i < vcs.Length; ++i)
{
if ((vcs[i].constraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref) ||
(vcs[i].keyrefTable == null))
{
continue;
}
foreach (KeySequence ks in vcs[i].keyrefTable.Keys)
{
if (!vcs[i].qualifiedTable.Contains(ks))
{
SendValidationEvent(new XmlSchemaException(Res.Sch_UnresolvedKeyref, new string[2] {
ks.ToString(), vcs[i].constraint.name.ToString()
},
reader.BaseURI, ks.PosLine, ks.PosCol));
}
}
}
}
}