/// <summary> /// Allow the construction of a complex property at a specified position. /// </summary> /// <param name="parent">Property's Parent</param> /// <param name="element">Property's XElement</param> /// <param name="insertPosition">Information where the property should be inserted to. If the parameter is null, the property will be placed as the last property of the entity.</param> internal ComplexConceptualProperty(EFElement parent, XElement element, InsertPropertyPosition insertPosition) : base(parent, element, insertPosition) { Debug.Assert( parent is ConceptualEntityType || parent is ComplexType || parent == null, "Parent of ConceptualProperty should be either ConceptualEntityType or ComplexType (or null for testing)"); }
/// <summary> /// Create a Conceptual property at a specified position. /// </summary> /// <param name="parent">Property's Parent. The value is either ConceptualEntityTYpe or a ComplexType.</param> /// <param name="element">Property's XElement</param> /// <param name="insertPosition">Information where the property should be inserted to. If the parameter is null, the property will be placed as the last property of the entity.</param> public ConceptualProperty(EFElement parent, XElement element, InsertPropertyPosition insertPosition) : base(parent, element, insertPosition) { Debug.Assert( parent is ConceptualEntityType || parent is ComplexType, "Parent of ConceptualProperty should be either ConceptualEntityType or ComplexType"); }
protected PropertyBase(EFElement parent, XElement element, InsertPropertyPosition insertPosition) : base(parent, element) { // Unfortunately, the XElement is created in the EFObject constructor. When the base class called EntityType's GetXLinqInsertPosition, // the Property's InsertPosition is not set. As a work around, we need to manually move the Property here. // This is not efficient as it could be because it involves removing and adding the property's XElement. // Currently, the only thing that use this functionality is CopyAndPaste. // We might want to consider change this when other scenarios depend on the functionality. if (insertPosition != null) { MoveTo(insertPosition); } }
/// <summary> /// Create a property at the a specified position. /// </summary> /// <param name="parent">Property's Parent.</param> /// <param name="element">Property's XElement</param> /// <param name="insertPosition">Information where the property should be inserted to. If the parameter is null, the property will be placed as the last property of the entity.</param> protected Property(EFElement parent, XElement element, InsertPropertyPosition insertPosition) : base(parent, element, insertPosition) { // nothing }
/// <summary> /// Move Property's XElement before the specified position. /// If position parameter is null, the property XElement will be moved to the last position. /// </summary> internal void MoveTo(InsertPropertyPosition position) { Debug.Assert( PreviousSiblingInPropertyXElementOrder != null || NextSiblingInPropertyXElementOrder != null, "Why do we need to move the property if it is the only property?"); Debug.Assert(position != null, "InsertPropertyPosition parameter is null."); if (position != null) { // Check if the InsertPropertyPosition's InsertAt is not null. Debug.Assert(position.InsertAtProperty != null, "Why InsertPropertyPosition's InsertAt is null?"); if (position.InsertAtProperty != null) { // Instead of re-parenting the property's XElement, we are going to clone the XElement, insert the clone and delete the old XElement. // This is a workaround for an XML editor bug where re-parenting an element causes asserts. // First create the new XElement. var tempDoc = XDocument.Parse(XElement.ToString(SaveOptions.None), LoadOptions.None); var newPropertyXElement = tempDoc.Root; newPropertyXElement.Remove(); // Remove known namespaces from the element since the namespaces are already set in the parent node. // This is workaround because XDocument automatically appends the default namespace in the property XElement. foreach (var a in newPropertyXElement.Attributes()) { if (a.IsNamespaceDeclaration && (a.Value == SchemaManager.GetCSDLNamespaceName(Artifact.SchemaVersion) || a.Value == SchemaManager.GetSSDLNamespaceName(Artifact.SchemaVersion) || a.Value == SchemaManager.GetAnnotationNamespaceName())) { a.Remove(); } } var toBeDeleteElement = XElement; // format the XML we just parsed so that the XElement will have the same indenting. Utils.FormatXML(newPropertyXElement, GetIndentLevel()); // Call method that will insert the XElement to the specified location. InsertPosition = position; AddXElementToParent(newPropertyXElement); // Re-establish the links between EFElement and XElement. SetXObject(newPropertyXElement); Debug.Assert( XElement == newPropertyXElement, "Unexpected XElement value. Expected:" + newPropertyXElement + " , Actual:" + XElement); ModelItemAnnotation.SetModelItem(newPropertyXElement, this); Debug.Assert( ModelItemAnnotation.GetModelItem(newPropertyXElement) == this, "The new XElement should contain annotation to the model property."); // Delete both old XElement and the preceding whitespace. // Preceding whitespace is preferred over trailing whitespace because we don't want to remove the last property's trailing white-space since // it has different indent level than the rest (see EFElement's EnsureFirstNodeWhitespaceSeparation method). var preceedingNewLine = toBeDeleteElement.PreviousNode as XText; while (preceedingNewLine != null && String.IsNullOrWhiteSpace(preceedingNewLine.Value)) { var toBeDeletedWhiteSpace = preceedingNewLine; preceedingNewLine = preceedingNewLine.PreviousNode as XText; toBeDeletedWhiteSpace.Remove(); } toBeDeleteElement.Remove(); #if DEBUG // Assert if the property is not moved to the correct location. if (position.InsertBefore) { Debug.Assert( position.InsertAtProperty == NextSiblingInPropertyXElementOrder, "Expected next sibling property: " + position.InsertAtProperty.DisplayName + " , Actual next sibling:" + NextSiblingInPropertyXElementOrder.DisplayName); } else { Debug.Assert( position.InsertAtProperty == PreviousSiblingInPropertyXElementOrder, "Expected previous sibling property: " + position.InsertAtProperty.DisplayName + " , Actual previous sibling:" + PreviousSiblingInPropertyXElementOrder.DisplayName); } #endif } } }
/// <summary> /// Create a Navigation property at a specified position. /// </summary> /// <param name="parent">Property's Parent. The value is either ConceptualEntityTYpe or a ComplexType.</param> /// <param name="element">Property's XElement</param> /// <param name="insertPosition">Information where the property should be inserted to. If the parameter is null, the property will be placed as the last property of the entity.</param> internal NavigationProperty(EntityType parent, XElement element, InsertPropertyPosition insertPostion) : base(parent, element, insertPostion) { // Nothing }