protected void ValidateElementError(Identifier name, ValidationState context) { ArrayList names = ExpectedElements(context, false, true); if (names == null) { context.HandleError(this.RootNode, name, Error.InvalidElementContentNone, context.Name.ToString(), name.ToString()); } else { Debug.Assert(names.Count > 0); context.HandleError(this.RootNode, name, Error.InvalidContentExpecting, context.Name.ToString(), name.ToString(), GetExpectedElements(names)); } }
public override bool CheckDeterministic(ValidationState context, NamedNode[] namedTerminals, out BitSet bitset, out SchemaNamespaceList wildcard) { BitSet lset = null, rset = null; bitset = null; wildcard = null; SchemaNamespaceList lany = null, rany = null; if (!LeftChild.CheckDeterministic(context, namedTerminals, out lset, out lany)) return false; if (!RightChild.CheckDeterministic(context, namedTerminals, out rset, out rany)) return false; return Join(context, namedTerminals, lset, lany, rset, rany, out bitset, out wildcard); }
public SchemaValidator CreateValidator(ErrorHandler errorHandler) { ValidationState newContext = new ValidationState(); newContext.ErrorHandler = errorHandler; newContext.ProcessContents = XmlSchemaContentProcessing.Strict; newContext.Name = context.Name; return new SchemaValidator(targetModule, newContext, schemaType, attributes, validator); }
public override bool CheckDeterministic(ValidationState context, NamedNode[] namedTerminals, out BitSet bitset, out SchemaNamespaceList wildcard) { bitset = null; wildcard = this.wildcard; wildcard.AddType(this.TypeNode); return true; }
protected bool Join(ValidationState context, NamedNode[] namedTerminals, BitSet lset, SchemaNamespaceList lany, BitSet rset, SchemaNamespaceList rany, out BitSet bitset, out SchemaNamespaceList wildcard) { wildcard = null; if (lset != null) { if (rset != null) { bitset = lset.Clone(); bitset.And(rset); if (!bitset.IsEmpty) { Identifier id = (context.Name == null) ? Identifier.Empty : context.Name; context.HandleError(this, id, Error.NonDeterministicAny, id.ToString()); return false; } bitset.Or(lset); bitset.Or(rset); } else { bitset = lset; } } else { bitset = rset; } if (lany != null) { if (rany != null) { SchemaNamespaceList list = SchemaNamespaceList.Intersection(rany, lany); if (list == null || list.IsEmpty()) { wildcard = SchemaNamespaceList.Union(rany, lany); } else { Identifier id = (context.Name == null) ? Identifier.Empty : context.Name; context.HandleError(this, id, Error.NonDeterministicAny, id.ToString()); return false; } } else { wildcard = lany; } } else { wildcard = rany; } if (wildcard != null && bitset != null) { for (int i = 0; i < bitset.Count; i++) { NamedNode node = namedTerminals[i]; if (bitset.Get(i) && wildcard.Allows(node)) { Identifier id = (context.Name == null ? node.Name : context.Name); context.HandleError(this, id, Error.NonDeterministicAny, id.ToString()); return false; } } } return true; }
public override void CompleteValidation(ValidationState context) { if (context.AllElementsRequired == countRequired || IsEmptiable && context.AllElementsRequired == -1) { return; } CompleteValidationError(context); }
public abstract bool CheckDeterministic(ValidationState context, NamedNode[] namedTerminals, out BitSet bitset, out SchemaNamespaceList wildcard);
public override void CompleteValidation(ValidationState context) { TerminalNode terminal = endMarker; if (contentRoot != null) { if (context.CurrentNode == null) { terminal = contentRoot.Accept(endMarker, null, true, namedTerminals, context.RangeNodeCounters); } else { terminal = context.CurrentNode.Parent.Accept(endMarker, context.CurrentNode, true, namedTerminals, context.RangeNodeCounters); } } if (terminal != endMarker) { CompleteValidationError(context); } }
public override ArrayList ExpectedElements(ValidationState context, bool isRequiredOnly, bool unique) { ArrayList list = new ArrayList(); AddExpectedElements(list, context.CurrentNode == null ? contentRoot : context.CurrentNode); return list; }
public override int ValidateExpression(ValidationState context, ContentValidator subExpr) { ParticleContentValidator subval = subExpr as ParticleContentValidator; if (subval != null) { ContentNode node = this.contentRoot.LeftChild; ContentNode root = subval.contentRoot.LeftChild; if (context.CurrentNode != null) { node = context.CurrentNode; if (node.Parent is SequenceNode) { // then we are in the middle of a content model and we have to try and match // the next expected thing node = ((SequenceNode)context.CurrentNode.Parent).RightChild; } } // walk to left most leaf node (which is the next expected thing). while (node is InternalNode) { node = ((InternalNode)node).LeftChild; } // Now see if the expression matches this node or one of the parent nodes // (like perhaps a StarNode and so on). while (node != null) { if (node.Matches(root)) { // "match" all the terminal nodes in "root" so that we advance the // state machine accordingly. AdvanceState(root, context); context.CurrentNode = node; return 1; } node = node.Parent; } return -1; } if (contentRoot.LeftChild is WildcardNode) { context.CurrentNode = contentRoot.LeftChild; return 1; } return -1; }
void AdvanceState(ContentNode node, ValidationState context) { if (node is NamedNode) { this.ValidateElement(((NamedNode)node).Name, context); } else if (node is NopNode) { AdvanceState(((NopNode)node).Child, context); } else if (node is InternalNode) { InternalNode inode = (InternalNode)node; AdvanceState(inode.LeftChild, context); if (inode.RightChild != null) AdvanceState(inode.RightChild, context); } }
public override int ValidateElement(Identifier name, ValidationState context) { TerminalNode terminal = null; NamedNodeList lookup = (NamedNodeList)symbols[name.UniqueKey]; bool isTerminal = true; if (lookup == null) { isTerminal = false; lookup = new NamedNodeList(); lookup.Add(new NamedNode(name, null, null)); // fake it } foreach (NamedNode node in lookup) { if (contentRoot != null) { if (context.CurrentNode == null) { if (contentRoot.CanAccept(node)) { terminal = contentRoot.Accept(node, null, isTerminal, namedTerminals, context.RangeNodeCounters); break; } } else if (context.CurrentNode.CanAccept(node)) { terminal = context.CurrentNode.Parent.Accept(node, context.CurrentNode, isTerminal, namedTerminals, context.RangeNodeCounters); break; } } } if (terminal == null) { context.NeedValidateChildren = false; ValidateElementError(name, context); } context.CurrentNode = terminal; if (terminal != null) { context.ProcessContents = terminal.ProcessContents; } // result just indicates success or failure. return (terminal == null) ? -1 : 1; }
public override void InitValidation(ValidationState context) { context.CurrentNode = null; context.RangeNodeCounters = new Hashtable(); // or do we want to do this on the fly??? BitSet bitset; SchemaNamespaceList any; contentRoot.LeftChild.CheckDeterministic(context, this.namedTerminals, out bitset, out any); }
protected void CompleteValidationError(ValidationState context) { ArrayList names = ExpectedElements(context, true, true); if (names == null) { context.HandleError(this.RootNode, context.Name, Error.InvalidElementContent, context.Name.ToString()); } else { Debug.Assert(names.Count > 0); context.HandleError(this.RootNode, context.Name, Error.IncompleteContentExpecting, context.Name.ToString(), GetExpectedElements(names)); } }
public override int ValidateElement(Identifier name, ValidationState context) { object lookup = elements[name.UniqueKey]; if (lookup == null) { context.NeedValidateChildren = false; ValidateElementError(name, context); return -1; } int index = (int)lookup; if (context.AllElementsSet[index]) { context.HandleError(this.RootNode, name, Error.DuplicateMemberInLiteral, name.Name); return index; } if (context.AllElementsRequired == -1) { context.AllElementsRequired = 0; } context.AllElementsSet.Set(index); if (isRequired[index]) { context.AllElementsRequired ++; } NamedNode n = (NamedNode)namedNodes[index]; context.CurrentNode = n; return index; }
internal CompiledParticleContentValidator(ValidationState context, InternalNode contentRoot, NamedNode[] namedTerminals, Hashtable symbols, int symCount, bool isOpen, XmlSchemaContentType contentType, Member mixed, NamedNode endMarker) : base(contentType, namedTerminals, symbols, contentRoot, endMarker, symCount, mixed) { // keep these this.isOpen = isOpen; this.isEmptiable = contentRoot.LeftChild.IsNullable; int terminalsCount = namedTerminals.Length; int endMarkerPos = terminalsCount - 1; // calculate followpos BitSet[] followpos = new BitSet[terminalsCount]; for (int i = 0; i < terminalsCount; i++) { followpos[i] = new BitSet(terminalsCount); } contentRoot.CalcFollowpos(followpos); // transition table ArrayList transitionTable = new ArrayList(); // state lookup table Hashtable stateTable = new Hashtable(); // lists unmarked states ArrayList unmarked = new ArrayList(); stateTable.Add(new BitSet(terminalsCount), -1); // add empty // start with firstpos at the root BitSet firstpos = contentRoot.Firstpos; stateTable.Add(firstpos, 0); unmarked.Add(firstpos); int[] a = new int[symbolCount + 1]; transitionTable.Add(a); if (firstpos[endMarkerPos]) { a[symbolCount] = 1; // accepting } // current state processed int state = 0; // check all unmarked states while (unmarked.Count > 0) { int[] t = (int[])transitionTable[state]; firstpos = (BitSet)unmarked[0]; if (!isNonDeterministic && !CheckDeterministic(firstpos, namedTerminals, context)) { isNonDeterministic = true; } unmarked.RemoveAt(0); // check all input symbols foreach (NamedNodeList list in symbols.Values){ foreach (NamedNode node in list) { BitSet newset = new BitSet(terminalsCount); // if symbol is in the set add followpos to new set for (int i = 0; i < terminalsCount; i++) { if (firstpos[i] && node == namedTerminals[i]) { newset.Or(followpos[i]); } } object lookup = stateTable[newset]; // this state will transition to int transitionTo; // if new set is not in states add it if (lookup == null) { transitionTo = stateTable.Count - 1; stateTable.Add(newset, transitionTo); unmarked.Add(newset); a = new int[symbolCount + 1]; transitionTable.Add(a); if (newset[endMarkerPos]) { a[symbolCount] = 1; // accepting } } else { transitionTo = (int)lookup; } // set the transition for the symbol t[node.Symbol] = transitionTo; } } state++; } // now convert transition table to array this.transitionTable = (int[][])transitionTable.ToArray(typeof(int[])); }
public override int ValidateExpression(ValidationState context, ContentValidator subExpr) { return -1; }
public override void InitValidation(ValidationState context) { context.State = 0; context.HasMatched = transitionTable[0][symbolCount] > 0; }
public override ArrayList ExpectedElements(ValidationState context, bool isRequiredOnly, bool unique) { ArrayList names = null; for (int i = 0; i < elements.Count; i++) { if (!context.AllElementsSet[i] && (!isRequiredOnly || isRequired[i])) { if (names == null) { names = new ArrayList(); } names.Add(namedNodes[i]); } } return names; }
public override int ValidateElement(Identifier name, ValidationState context) { NamedNodeList list = (NamedNodeList)symbols[name.UniqueKey]; if (list != null) { foreach (NamedNode n in list) { int symbol = n.Symbol; if (symbol != -1) { int state = transitionTable[context.State][symbol]; if (state != -1) { context.State = state; context.HasMatched = transitionTable[context.State][symbolCount] > 0; context.CurrentNode = n; return symbol; // OK } //bugbug: check for ambiguous names. } } } if (isOpen && context.HasMatched) { // XDR allows any well-formed contents after matched. return -1; } context.NeedValidateChildren = false; ValidateElementError(name, context); return -1; // will never be here }
public override bool CheckDeterministic(ValidationState context, NamedNode[] namedTerminals, out BitSet bitset, out SchemaNamespaceList wildcard) { bitset = Firstpos; wildcard = null; return true; }
public override void CompleteValidation(ValidationState context) { if (!context.HasMatched && !context.HasErrors && !isNonDeterministic) { CompleteValidationError(context); } }
public override bool CheckDeterministic(ValidationState context, NamedNode[] namedTerminals, out BitSet bitset, out SchemaNamespaceList wildcard) { return LeftChild.CheckDeterministic(context, namedTerminals, out bitset, out wildcard); }
private bool CheckDeterministic(BitSet bitset, NamedNode[] namedTerminals, ValidationState context) { TrivialHashtable nodeTable = new TrivialHashtable(); for (int i = 0; i < namedTerminals.Length; i++) { if (bitset[i]) { NamedNode node = namedTerminals[i]; Identifier n = node.Name; if (n != Identifier.Empty) { if (nodeTable[n.UniqueKey] == null) { nodeTable[n.UniqueKey] = n; } else { Node offendingNode = (node.Member is Method) ? node.Name : node.Member.Name; context.HandleError(this.RootNode, offendingNode, Error.NonDeterministic, context.Name.ToString(), n.Name.ToString()); return false; } } } } return true; }
public override bool CheckDeterministic(ValidationState context, NamedNode[] namedTerminals, out BitSet bitset, out SchemaNamespaceList wildcard) { bitset = null; BitSet lset = null, rset = null; wildcard = null; SchemaNamespaceList lany = null, rany = null; if (!LeftChild.CheckDeterministic(context, namedTerminals, out lset, out lany)) return false; if (!RightChild.CheckDeterministic(context, namedTerminals, out rset, out rany)) return false; if (LeftChild.HasRange || LeftChild.IsNullable) { return Join(context, namedTerminals, lset, lany, rset, rany, out bitset, out wildcard); } else { bitset = lset; wildcard = lany; } return true; }
public override ArrayList ExpectedElements(ValidationState context, bool isRequiredOnly, bool unique) { ArrayList names = null; Hashtable uniqueNames = new Hashtable(); int[] t = transitionTable[context.State]; if (t != null) { foreach (NamedNode node in this.namedTerminals) { Identifier name = node.Name; if (name != Identifier.Empty && t[node.Symbol] != -1 && (!unique || uniqueNames[name.UniqueKey] == null)) { if (names == null) { names = new ArrayList(); } names.Add(node); if (unique) uniqueNames[name.UniqueKey] = name; } } } return names; }
protected SchemaElementDecl(Module targetModule, TypeNode schemaType, TypeNode elementType, ErrorHandler errorHandler) { this.context = new ValidationState(); this.context.ProcessContents = XmlSchemaContentProcessing.Strict; this.context.ErrorHandler = errorHandler; this.context.Name = schemaType.Name; this.targetModule = targetModule; this.schemaType = schemaType; TypeNode scheType = schemaType; if (scheType is TypeAlias) { TypeAlias alias = (TypeAlias)scheType; scheType = alias.AliasedType; } if (scheType.IsPrimitive || scheType == SystemTypes.String) return; ArrayList allElements = new ArrayList(); // for "all" content model. ArrayList attdefs = new ArrayList(); this.builder = new ContentModelBuilder(XmlSchemaContentType.ElementOnly); this.builder.Start(); // start building. if (schemaType.Template == SystemTypes.GenericList || schemaType.Template == SystemTypes.GenericIEnumerable || schemaType.Template == SystemTypes.GenericList || schemaType.Template == SystemTypes.GenericIList || Checker.IsList(schemaType)) { // then this is a collection which is modelled as a star group. CompileGenericList(elementType, 0, Int32.MaxValue, null); goto FinishUp;// finish building & compile it. } else if (schemaType.Template == SystemTypes.GenericNonEmptyIEnumerable) { CompileGenericList(schemaType, 1, Int32.MaxValue, null); goto FinishUp;// finish building & compile it. } else if (schemaType.Template == SystemTypes.GenericBoxed) { CompileGenericList(schemaType, 0, 1, null); goto FinishUp;// finish building & compile it. } else if (schemaType is TypeUnion) { CompileTypeUnion(schemaType as TypeUnion, null); goto FinishUp;// finish building & compile it. } else if (schemaType is TupleType) { CompileTuple(schemaType as TupleType, null); goto FinishUp;// finish building & compile it. } builder.OpenGroup(); // assemble all base types so we can walk them in parent-to-child order. ArrayList scheTypes = new ArrayList(); while (scheType != null) { scheTypes.Add(scheType); scheType = scheType.BaseType; } // walk from top most base class to child class, since that's the // order of the content model. for (int typeindex = scheTypes.Count-1; typeindex>=0; typeindex--) { scheType = (TypeNode)scheTypes[typeindex]; // Now walk all our members, and look for custom attributes that indicate // whether those members are elements or attributes (the default is // to make it an element). MemberList members = scheType.Members; for (int i = 0, n = members == null ? 0 : members.Length; i < n; i++) { Member mem = members[i]; if (mem == null) continue; // type resolution error. Field f = mem as Field; Property p = mem as Property; Identifier memName = mem.Name; if (f == null && p == null) continue; TypeNode memType = f != null ? f.Type : p.Type; if (memType == null) continue; // must be a type error. // Rule out members that are not public, static if ((f == null || f.IsStatic || !f.IsPublic) && (p == null || p.IsStatic || !p.IsPublic)) continue; if (p != null && p.Setter == null) { // Property has no setter, perhaps it is a collection in which case // we can "add" to the collection without constructing it, which is fine. if (!Checker.IsList(memType)) continue; } TypeNode ceType = Checker.GetCollectionElementType(memType); TypeNode originalElementType = ceType; AttributeList attrs = mem.Attributes; int m = attrs == null ? 0 : attrs.Length; bool isList = (Checker.GetListInterface(memType) != null) || memType is ArrayType; if (isList) { // Calculate the real TypeUnion for the list element types // from the list of XmlElementAttributes. TypeNodeList types = new TypeNodeList(); for (int j = m-1; j >= 0; j--) { AttributeNode attr = attrs[j]; if (attr == null) continue; TypeNode attrType = GetAttributeType(attr); if (attrType == null) continue;// must be a type error. if (attrType == Runtime.XmlElementAttributeClass) { TypeNode aType = GetAttrType(attr, 1, SchemaElementDecl.TypeId); if (aType != null) { types.Add(aType); } } } if (types.Length > 1) { ceType = TypeUnion.For(types, this.targetModule); } else if (types.Length == 1) { ceType = types[0]; } } // The attributes repeat the content structure for each field. bool handled = false; bool hasElementGroup = false; TypeNodeList elementTypes = new TypeNodeList(); // Walk the attributes backwards because the outer contains (e.g. sequence) // is listed last in the IL. for (int j = m-1; j >= 0; j--) { AttributeNode attr = attrs[j]; if (attr == null) continue; TypeNode attrType = GetAttributeType(attr); if (attrType == null) continue;// must be a type error. if (attrType == Runtime.XmlAttributeAttributeClass) { // pick up the XML attribute name from the custom attribute, if any Identifier id = GetXmlName(mem.Name, attr); attdefs.Add(new SchemaAttDef(id, mem)); handled = true; break; } else if (attrType == Runtime.XmlElementAttributeClass) { // This is for element renaming and support for legacy XmlSerializer collections TypeNode aType = GetAttrType(attr, 1, SchemaElementDecl.TypeId); if (aType == null) aType = ceType; else if (ceType != null && (memType is ArrayType) && ! aType.IsAssignableTo(originalElementType)) context.HandleError(null, attr, Error.NoImplicitConversion, ErrorHandler.GetTypeNameFor(aType), ErrorHandler.GetTypeNameFor(originalElementType)); memName = GetXmlName(memName, attr); if (isList) { // eg: // [XmlElement("f", typeof(int)), // XmlElement("g", typeof(string))] // public ArrayList children; // which is modelled as (f|g)* if (!hasElementGroup) { builder.OpenGroup(); builder.AddNamedTerminal(memName, new Method(), aType); hasElementGroup = true; } else { builder.AddChoice(new Method(), ceType); builder.AddNamedTerminal(memName, new Method(), aType); } handled = true; } else { // then just drop through to adding this element to the allElements group. ceType = aType; } } else if (attrType == Runtime.XmlIgnoreAttributeClass) { handled = true; break; } else if (attrType == Runtime.XmlTextAttributeClass) { // this is a hack implementation of mixed content. builder.MixedMember = mem; handled = true; } } if (hasElementGroup) { builder.CloseGroup(); builder.AddStar(mem, memType); hasElementGroup = false; } if (!handled) { if (mem.IsAnonymous) { TypeNode type = Unwrap(memType); if (type is TupleType) { CompileTuple(type as TupleType, mem); } else if (type.Template == SystemTypes.GenericList || type.Template == SystemTypes.GenericIList || type.Template == SystemTypes.GenericList || type.Template == SystemTypes.GenericIEnumerable) { CompileGenericList(type, 0, Int32.MaxValue, mem); } else if (type.Template == SystemTypes.GenericNonEmptyIEnumerable) { CompileGenericList(type,1, Int32.MaxValue, mem); } else if (type is TypeUnion) { CompileTypeUnion(type as TypeUnion, mem); } else if (type.Template == SystemTypes.GenericBoxed) { CompileGenericList(type, 0, 1, mem); } else if (memType is TypeAlias) { TypeAlias alias = memType as TypeAlias; builder.AddNamedTerminal(alias.Name, mem, alias.AliasedType); } else { builder.AddNamedTerminal(Checker.GetDefaultElementName(type), mem, type); } } else { // Then we treat this as part of an all group instead. // bugbug: how do we pass the ceType information along? if (memType is TypeAlias) { TypeAlias alias = memType as TypeAlias; allElements.Add(new NamedNode(alias.Name, mem, alias.AliasedType)); } else { allElements.Add(new NamedNode(memName, mem, memType)); } } } } // endfor } builder.CloseGroup(); FinishUp: validator = builder.Finish(context, true); // finish building & compile it. if (attdefs.Count>0) { attributes = (SchemaAttDef[])attdefs.ToArray(typeof(SchemaAttDef)); } if (allElements.Count>0) { // todo: handle the case where there is a mix of fields and real content model? if (!(validator.ContentType == XmlSchemaContentType.Empty || validator.ContentType == XmlSchemaContentType.TextOnly)) { NamedNode n = (NamedNode)allElements[0]; this.context.HandleError(null, n.Member, Error.ContentModelNotSupported, ErrorHandler.GetTypeNameFor(schemaType)); } AllElementsContentValidator allValidator = new AllElementsContentValidator(builder.MixedMember, allElements.Count, true); foreach (NamedNode node in allElements) { allValidator.AddElement(node, true); } validator = allValidator; } }
public override void InitValidation(ValidationState context) { Debug.Assert(elements.Count > 0); context.AllElementsSet = new BitSet(elements.Count); context.AllElementsRequired = -1; // no elements at all }
public SchemaValidator(Module targetModule, ValidationState context, TypeNode schemaType, SchemaAttDef[] attributes, ContentValidator validator){ this.context = context; this.schemaType = schemaType; this.attributes = attributes; this.targetModule = targetModule; if (attributes != null) { attrSpecified = new bool[attributes.Length]; } this.validator = validator; if (this.validator != null) this.validator.InitValidation(context); }
public virtual ArrayList ExpectedElements(ValidationState context, bool isRequiredOnly, bool unique) { return null; // returns list of NamedNodes. }