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); }
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 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; }
public override int ValidateExpression(ValidationState context, ContentValidator subExpr) { return -1; }
public virtual int ValidateExpression(ValidationState context, ContentValidator subExpr) { return -1; }