private void AddReferences(XElement parentElement, bool attributeReferences, XsdNodeTranslationInfo nodeInfo, bool inChoice) { #region SR if (nodeInfo.Node is PSMClass) { PSMClass psmClass = (PSMClass)nodeInfo.Node; // HACK: nodeInfos.ContainsKey(psmClass.RepresentedClass) -- this prevents references to cross-schema representatives, // for now, but should be fixed in the future if (psmClass.IsStructuralRepresentative && nodeInfos.ContainsKey(psmClass.RepresentedClass)) { XsdNodeTranslationInfo srInfo = nodeInfos[psmClass.RepresentedClass]; if (srInfo.DefinesElements && !attributeReferences) { parentElement.XsdGroupRef(srInfo.ContentGroupName); } if (srInfo.DefinesAttributes && attributeReferences) { parentElement.XsdAttributeGroupRef(inChoice? srInfo.OptAttributeGroupName : srInfo.NonOptAttributeGroupName); } } } #endregion #region attributes if (nodeInfo.Node is PSMClass) { PSMClass psmClass = (PSMClass)nodeInfo.Node; foreach (PSMAttribute psmAttribute in psmClass.PSMAttributes) { string attributeName = NamingSupport.SuggestName(psmAttribute, attribute: true); if (psmAttribute.Element && !attributeReferences) { parentElement.XsdAttributeAsElement(attributeName, psmAttribute); } if (!psmAttribute.Element && attributeReferences) { parentElement.XsdAttribute(attributeName, psmAttribute, inChoice); } if (psmAttribute.AttributeType == null) { Log.AddWarningFormat("Type of attribute '{0}' is not specified. ", psmAttribute); } else if (!psmAttribute.AttributeType.IsSealed) { if (psmAttribute.AttributeType.BaseType == Guid.Empty || string.IsNullOrEmpty(psmAttribute.AttributeType.XSDDefinition)) { Log.AddWarningFormat("Can not translate type of attribute '{0}' - '{1}'. Define base type and XSD definition via Data Type Manager.", psmAttribute, psmAttribute.AttributeType); } else { usedNonDefaultAttributTypes.AddIfNotContained(psmAttribute.AttributeType); } } } } #endregion #region associations if (nodeInfo.Node is PSMAssociationMember) { PSMAssociationMember psmAssociationMember = (PSMAssociationMember)nodeInfo.Node; // associations XElement element = parentElement; foreach (PSMAssociation psmAssociation in psmAssociationMember.ChildPSMAssociations) { XsdNodeTranslationInfo childInfo = nodeInfos[psmAssociation.Child]; if (!attributeReferences) { element = parentElement; if (psmAssociation.IsNamed && childInfo.ComplexTypeRequired) { XElement wrappingLiteral = element.XsdElement(psmAssociation.Name); if (childInfo.ComplexTypeRequired) { wrappingLiteral.TypeAttribute(childInfo.ComplexTypeName); } element = wrappingLiteral; } if (!psmAssociation.IsNamed && childInfo.GroupsRequired && childInfo.DefinesElements) { element = element.XsdGroupRef(childInfo.ContentGroupName); } if (childInfo.Node is PSMContentModel) { /* * association name is ignored in this case, * normalized schemas do not have content models * with named parent associations */ if (psmAssociation.IsNamed) { Log.AddErrorFormat("Name of '{0}' is ignored. Associations leading to content models should not have names (this violates rules for normalized schemas).", psmAssociation); } switch (((PSMContentModel)childInfo.Node).Type) { case PSMContentModelType.Sequence: element = element.XsdSequence(); break; case PSMContentModelType.Choice: element = element.XsdChoice(); break; case PSMContentModelType.Set: // do nothing break; } AddReferences(element, false, childInfo, false); } if (element != parentElement || ContentIsSet(nodeInfo.Node)) { element.CardinalityAttributes(psmAssociation); } } else { if (childInfo.GroupsRequired && childInfo.DefinesAttributes) { parentElement.XsdAttributeGroupRef(inChoice ? childInfo.OptAttributeGroupName : childInfo.NonOptAttributeGroupName); } if (childInfo.Node is PSMContentModel) { AddReferences(element, true, childInfo, ((PSMContentModel)childInfo.Node).Type.IsAmong(PSMContentModelType.Choice, PSMContentModelType.Set)); } } } } #endregion }
public void GenerateXSDStructure() { foreach (PSMAssociationMember node in PSMSchema.PSMNodes) { if (node is PSMSchemaClass) { continue; } XsdNodeTranslationInfo nodeInfo = new XsdNodeTranslationInfo(); nodeInfo.Node = node; nodeInfos[node] = nodeInfo; if (node.DownCastSatisfies <PSMClass>(c => c.ParentAssociation == null) || node.DownCastSatisfies <PSMClass>(c => c.ParentAssociation != null && c.ParentAssociation.IsNamed) || node.DownCastSatisfies <PSMClass>(c => c.GeneralizationsAsGeneral.Count > 0) || node.DownCastSatisfies <PSMClass>(c => c.GetIncomingNonTreeAssociations().Count(a => a.IsNamed) > 0)) { nodeInfo.ComplexTypeRequired = true; nodeInfo.ComplexTypeName = NamingSupport.SuggestName(node, complexType: true); } if (node.DownCastSatisfies <PSMClass>(c => c.HasStructuralRepresentatives)) { nodeInfo.GroupsRequired = true; } if (node.DownCastSatisfies <PSMClass>(c => c.ParentAssociation != null && !c.ParentAssociation.IsNamed) || node.DownCastSatisfies <PSMClass>(c => c.GetIncomingNonTreeAssociations().Count(a => !a.IsNamed) > 0)) { nodeInfo.GroupsRequired = true; } nodeInfo.DefinesAttributes = TestNodeDefinesAttributes(node); nodeInfo.DefinesElements = TestNodeDefinesElements(node); if (nodeInfo.DefinesElements && nodeInfo.GroupsRequired) { nodeInfo.ContentGroupName = NamingSupport.SuggestName(node, contentGroup: true); } // find all structural representatives of a class if (node is PSMClass && nodeInfo.DefinesAttributes) { IList <PSMClass> referencing = ((PSMClass)node).GetReferencingStructuralRepresentatives(true); referencing.Add((PSMClass)node); foreach (PSMClass psmClass in referencing) { if (psmClass.PropagatesToChoice()) { nodeInfo.OptAttributeReference = true; nodeInfo.OptAttributeGroupName = NamingSupport.SuggestName(node, optGroup: true); Log.AddErrorFormat("Class '{0}' defines attributes which propagate to choice/set content model(s). Consider giving name to the parent association of the class or representing attributes of '{0}' as elements. ", node); } else { nodeInfo.NonOptAttributeReference = true; nodeInfo.NonOptAttributeGroupName = NamingSupport.SuggestName(node, attributeGroup: true); } } } } }
private void TranslateClass(XElement parentElement, PSMClass psmClass) { XsdNodeTranslationInfo nodeInfo = nodeInfos[psmClass]; if (nodeInfo.ComplexTypeRequired) { XElement complexType = parentElement.XsdComplexType(nodeInfo.ComplexTypeName); XElement complexTypeContent; if (psmClass.SuperClass != null) { XsdNodeTranslationInfo generalInfo = nodeInfos[psmClass.SuperClass]; XElement complexContent = complexType.XsdComplexContent(); XElement extension = complexContent.XsdExtension(generalInfo.ComplexTypeName); complexTypeContent = !ContentIsSet(psmClass) ? extension.XsdSequence() : extension.XsdAll(); } else { complexTypeContent = !ContentIsSet(psmClass) ? complexType.XsdSequence() : complexType.XsdAll(); } if (ContentIsSet(psmClass) && CountContentForSet(psmClass) > 1) { Log.AddErrorFormat("Class '{0}' has a content model of type 'set' in its content. Such classes can not have other content except this content model. ", psmClass); } if (nodeInfo.GroupsRequired) { if (nodeInfo.DefinesAttributes) { complexTypeContent.XsdAttributeGroupRef(nodeInfo.NonOptAttributeGroupName); } if (nodeInfo.DefinesElements) { complexTypeContent.XsdGroupRef(nodeInfo.ContentGroupName); } } else { AddReferences(complexType, true, nodeInfo, false); AddReferences(complexTypeContent, false, nodeInfo, false); } } if (nodeInfo.GroupsRequired) { if (nodeInfo.DefinesElements) { XElement group = parentElement.XsdGroup(nodeInfo.ContentGroupName); XElement groupSequence = group.XsdSequence(); AddReferences(groupSequence, false, nodeInfo, false); } if (nodeInfo.DefinesAttributes) { if (nodeInfo.NonOptAttributeReference) { XElement attributeGroup = parentElement.XsdAttributeGroup(nodeInfo.NonOptAttributeGroupName); AddReferences(attributeGroup, true, nodeInfo, false); } if (nodeInfo.OptAttributeReference) { XElement attributeGroup = parentElement.XsdAttributeGroup(nodeInfo.OptAttributeGroupName); AddReferences(attributeGroup, true, nodeInfo, true); } } } }