Exemple #1
0
    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;
    }
Exemple #2
0
    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;
      }
    }
Exemple #3
0
 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;
 }
Exemple #4
0
 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;
 }
Exemple #5
0
 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));
   }
 }
Exemple #6
0
 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));
   }
 }
Exemple #7
0
 public virtual int ValidateElement(Identifier name, ValidationState context) {
   Debug.Assert(contentType != XmlSchemaContentType.ElementOnly);
   if (contentType == XmlSchemaContentType.Empty) {
     context.HandleError(this.RootNode, context.Name, Error.InvalidElementInEmpty, name.ToString(), context.Name.ToString());
   }
   else if (contentType == XmlSchemaContentType.TextOnly || !anyElement) {
     context.HandleError(this.RootNode, context.Name, Error.InvalidElementInTextOnly, name.ToString(), context.Name.ToString());
   }
   // we treat Mixed as Any
   return -1;
 }
Exemple #8
0
 public void ValidateWhitespace(ValidationState context) {
   if (contentType == XmlSchemaContentType.Empty) {
     context.HandleError(this.RootNode, context.Name, Error.InvalidWhitespaceInEmpty, context.Name.ToString());
   }
 }
Exemple #9
0
 public bool ValidateText(ValidationState context) {
   if (contentType == XmlSchemaContentType.ElementOnly) {
     ArrayList names = ExpectedElements(context, false, true);        
     if (names == null) {
       context.HandleError(this.RootNode, context.Name, Error.InvalidTextInElement, context.Name.ToString());
       return false;
     }
     else {
       Debug.Assert(names.Count > 0);
       context.HandleError(this.RootNode, context.Name, Error.InvalidTextInElementExpecting, context.Name.ToString(),  GetExpectedElements(names));
       return false;
     }
   }
   else if (contentType == XmlSchemaContentType.Empty) {
     context.HandleError(this.RootNode, context.Name, Error.InvalidTextInElement, context.Name.ToString());
     return false;
   }
   return true;
 }