/// <summary> /// Constructor /// Creates a UniquenessConstraintIncludesColumn link in the same Partition as the given UniquenessConstraint /// </summary> /// <param name="source">UniquenessConstraint to use as the source of the relationship.</param> /// <param name="target">Column to use as the target of the relationship.</param> public UniquenessConstraintIncludesColumn(UniquenessConstraint source, Column target) : base((source != null ? source.Partition : null), new DslModeling::RoleAssignment[]{new DslModeling::RoleAssignment(UniquenessConstraintIncludesColumn.UniquenessConstraintDomainRoleId, source), new DslModeling::RoleAssignment(UniquenessConstraintIncludesColumn.ColumnDomainRoleId, target)}, null) { }
public static DslModeling::LinkedElementCollection<UniquenessConstraint> GetUniquenessConstraints(Column element) { return new DslModeling::LinkedElementCollection<UniquenessConstraint>(element, ColumnDomainRoleId); }
public static PredefinedDataType GetPredefinedDataType(Column element) { return DslModeling::DomainRoleInfo.GetLinkedElement(element, ColumnDomainRoleId) as PredefinedDataType; }
public static void SetPredefinedDataType(Column element, PredefinedDataType newPredefinedDataType) { DslModeling::DomainRoleInfo.SetLinkedElement(element, ColumnDomainRoleId, newPredefinedDataType); }
/// <summary> /// Constructor /// Creates a ColumnHasPredefinedDataType link in the same Partition as the given Column /// </summary> /// <param name="source">Column to use as the source of the relationship.</param> /// <param name="target">PredefinedDataType to use as the target of the relationship.</param> public ColumnHasPredefinedDataType(Column source, PredefinedDataType target) : base((source != null ? source.Partition : null), new DslModeling::RoleAssignment[]{new DslModeling::RoleAssignment(ColumnHasPredefinedDataType.ColumnDomainRoleId, source), new DslModeling::RoleAssignment(ColumnHasPredefinedDataType.PredefinedDataTypeDomainRoleId, target)}, null) { }
public static void SetColumn(PredefinedDataType element, Column newColumn) { DslModeling::DomainRoleInfo.SetLinkedElement(element, PredefinedDataTypeDomainRoleId, newColumn); }
public static Domain GetDomain(Column element) { return DslModeling::DomainRoleInfo.GetLinkedElement(element, ColumnDomainRoleId) as Domain; }
string IDatabaseNameGenerator.GenerateColumnName(Column column, int phase) { return GenerateColumnName(column, phase); }
public static void SetTable(Column element, Table newTable) { DslModeling::DomainRoleInfo.SetLinkedElement(element, ColumnDomainRoleId, newTable); }
/// <summary> /// Constructor /// Creates a ColumnHasDomain link in the same Partition as the given Column /// </summary> /// <param name="source">Column to use as the source of the relationship.</param> /// <param name="target">Domain to use as the target of the relationship.</param> public ColumnHasDomain(Column source, Domain target) : base((source != null ? source.Partition : null), new DslModeling::RoleAssignment[]{new DslModeling::RoleAssignment(ColumnHasDomain.ColumnDomainRoleId, source), new DslModeling::RoleAssignment(ColumnHasDomain.DomainDomainRoleId, target)}, null) { }
public static Table GetTable(Column element) { return DslModeling::DomainRoleInfo.GetLinkedElement(element, ColumnDomainRoleId) as Table; }
/// <summary> /// Constructor /// Creates a TableContainsColumn link in the same Partition as the given Table /// </summary> /// <param name="source">Table to use as the source of the relationship.</param> /// <param name="target">Column to use as the target of the relationship.</param> public TableContainsColumn(Table source, Column target) : base((source != null ? source.Partition : null), new DslModeling::RoleAssignment[]{new DslModeling::RoleAssignment(TableContainsColumn.TableDomainRoleId, source), new DslModeling::RoleAssignment(TableContainsColumn.ColumnDomainRoleId, target)}, null) { }
private string GenerateColumnName(Column column, int phase) { if (phase > 1) { return null; } bool decorateWithPredicateText = phase == 1; LinkedNode<ColumnPathStep> currentNode = GetColumnPath(column); NameGenerator generator = ColumnNameGenerator; if (currentNode == null) { return GetFinalName(ResourceStrings.NameGenerationValueTypeValueColumn, null, generator); } // Prepare for adding name parts. The single NamePart string is used when // possible to avoid using the list for a single entry NamePart singleName = default(NamePart); List<NamePart> nameCollection = null; AddNamePart addPart = delegate(NamePart newPart, int? insertIndex) { AddToNameCollection(ref singleName, ref nameCollection, newPart, insertIndex.HasValue ? insertIndex.Value : -1, true); }; ObjectType previousResolvedSupertype = null; ObjectType previousResolvedObjectType = null; ConceptType primaryConceptType = TableIsPrimarilyForConceptType.GetConceptType(column.Table); if (primaryConceptType != null) { previousResolvedSupertype = previousResolvedObjectType = ConceptTypeIsForObjectType.GetObjectType(primaryConceptType); } ObjectType previousPreviousResolvedSupertype = null; ObjectType previousPreviousResolvedObjectType = null; bool firstPass = true; bool treatNextIdentifierAsFirstStep = false; bool lastStepConsumedNextNode = false; bool lastStepUsedExplicitRoleName = false; do { LinkedNode<ColumnPathStep> nextLoopNode = currentNode.Next; ColumnPathStep step = currentNode.Value; ColumnPathStepFlags stepFlags = step.Flags; if (treatNextIdentifierAsFirstStep) { treatNextIdentifierAsFirstStep = false; if (0 != (stepFlags & ColumnPathStepFlags.IsIdentifier)) { firstPass = true; } } if (0 != (stepFlags & ColumnPathStepFlags.ForwardAssimilation)) { if (!(lastStepConsumedNextNode || lastStepUsedExplicitRoleName) || currentNode.Previous.Value.TargetObjectType != step.StartingObjectType) { ReferenceModeNaming.SeparateObjectTypeParts(step.ResolvedSupertype, generator, addPart); lastStepConsumedNextNode = false; lastStepUsedExplicitRoleName = false; } // Note that there is no else clause to reset the flags, keep them with their current values } else if (0 != (stepFlags & ColumnPathStepFlags.ReverseAssimilation)) { // Don't add names for reverse path types lastStepConsumedNextNode = false; lastStepUsedExplicitRoleName = false; treatNextIdentifierAsFirstStep = firstPass; if (nextLoopNode == null) { // Unusual, but can happen with a ValueType with its own table ReferenceModeNaming.SeparateObjectTypeParts(step.ResolvedSupertype, generator, addPart); } } else { bool decorate = 0 != (stepFlags & ColumnPathStepFlags.RequiresDecoration); ColumnPathStep nextAssimilationStep; bool incorporateNextAssimilation = nextLoopNode != null && (0 != (ColumnPathStepFlags.ForwardAssimilation & (nextAssimilationStep = nextLoopNode.Value).Flags)) && nextAssimilationStep.StartingObjectType == step.TargetObjectType; if (decorate || incorporateNextAssimilation || (nextLoopNode == null && (0 == (stepFlags & ColumnPathStepFlags.IsIdentifier) || !(lastStepConsumedNextNode || lastStepUsedExplicitRoleName)))) { LinkedNode<ColumnPathStep> nextNode = nextLoopNode; if (!decorate && nextNode == null && 0 != (stepFlags & ColumnPathStepFlags.IsIdentifier)) { LinkedNode<ColumnPathStep> previousNode = currentNode.Previous; if (previousNode != null) { ColumnPathStep previousStep = previousNode.Value; ColumnPathStepFlags previousFlags = previousStep.Flags; if (0 == (previousFlags & (ColumnPathStepFlags.RequiresDecoration | ColumnPathStepFlags.ForwardAssimilation | ColumnPathStepFlags.ReverseAssimilation)) && previousResolvedSupertype.ReferenceModePattern != null) { // Special condition when the last node is a simple identifier: // Back up one step to enable picking up the role or hyphen-bound // name instead of just the predicate text. stepFlags = previousFlags; step = previousStep; nextNode = currentNode; previousResolvedSupertype = previousPreviousResolvedSupertype; previousResolvedObjectType = previousPreviousResolvedObjectType; } } } Role nearRole = step.FromRole; Role farRole = (0 == (stepFlags & ColumnPathStepFlags.ObjectifiedFactType)) ? nearRole.OppositeRoleAlwaysResolveProxy.Role : nearRole.OppositeRole.Role; string explicitFarRoleName = farRole.Name; FactType factType = nearRole.FactType; LinkedElementCollection<RoleBase> factTypeRoles = factType.RoleCollection; int? unaryRoleIndex = FactType.GetUnaryRoleIndex(factTypeRoles); bool isUnary = unaryRoleIndex.HasValue; LinkedElementCollection<ReadingOrder> readingOrders = null; IReading reading = null; if ((decorate && decorateWithPredicateText) || (isUnary && string.IsNullOrEmpty(explicitFarRoleName))) { readingOrders = factType.ReadingOrderCollection; reading = factType.GetMatchingReading(readingOrders, null, nearRole, null, factTypeRoles, MatchingReadingOptions.NoFrontText | (isUnary ? MatchingReadingOptions.AllowAnyOrder : MatchingReadingOptions.None)); } lastStepConsumedNextNode = false; lastStepUsedExplicitRoleName = false; if (reading != null && !reading.IsDefault) { string readingText = string.Format(CultureInfo.CurrentCulture, reading.Text, isUnary ? "\x1" : "", "\x1"); int splitPosition = readingText.LastIndexOf('\x1'); if (splitPosition > 0) { addPart(readingText.Substring(0, splitPosition), null); } if (!isUnary) { if (nextNode != null) { ColumnPathStep nextStep = nextNode.Value; ColumnPathStepFlags nextFlags; if (incorporateNextAssimilation || (0 != ((nextFlags = nextStep.Flags) & ColumnPathStepFlags.RequiresDecoration) && 0 != (nextFlags & (ColumnPathStepFlags.ForwardAssimilation | ColumnPathStepFlags.ReverseAssimilation)) && step.TargetObjectType == nextStep.StartingObjectType)) { // Note that this does not interfere with the earlier 'back up one step' // because the checked flags are different. nextLoopNode = nextNode.Next; lastStepConsumedNextNode = ReferenceModeNaming.ResolveObjectTypeName( nextStep.ResolvedObjectType, (nextLoopNode != null) ? nextLoopNode.Value.TargetObjectType : null, nextStep.ResolvedSupertypeVerifyPreferred, true, ReferenceModeNamingUse.ReferenceToEntityType, generator, addPart); } else { lastStepConsumedNextNode = ReferenceModeNaming.ResolveObjectTypeName( step.ResolvedObjectType, nextNode.Value.TargetObjectType, step.ResolvedSupertypeVerifyPreferred, true, ReferenceModeNamingUse.ReferenceToEntityType, generator, addPart); } } else { ReferenceModeNaming.ResolveObjectTypeName( (!firstPass || 0 != (stepFlags & ColumnPathStepFlags.IsIdentifier)) ? previousResolvedSupertype : null, step.TargetObjectType, previousResolvedObjectType, false, firstPass ? ReferenceModeNamingUse.PrimaryIdentifier : ReferenceModeNamingUse.ReferenceToEntityType, // Ignored if first parameter is null generator, addPart); } } if ((readingText.Length - splitPosition) > 1) { addPart(readingText.Substring(splitPosition + 1), null); } } else if (!string.IsNullOrEmpty(explicitFarRoleName)) { addPart(explicitFarRoleName, null); lastStepUsedExplicitRoleName = true; } else { // Find an appropriate hyphen bind in the available readings string hyphenBoundFormatString = null; if (readingOrders == null) { readingOrders = factType.ReadingOrderCollection; } ReadingOrder readingOrder; if (0 != (readingOrders ?? (readingOrders = factType.ReadingOrderCollection)).Count && null != (readingOrder = isUnary ? readingOrders[0] : FactType.FindMatchingReadingOrder(readingOrders, new RoleBase[] { nearRole, farRole }))) { foreach (Reading testReading in readingOrder.ReadingCollection) { hyphenBoundFormatString = VerbalizationHyphenBinder.GetFormatStringForHyphenBoundRole(testReading, farRole, unaryRoleIndex); if (hyphenBoundFormatString != null) { break; } } } int splitPosition = 0; if (hyphenBoundFormatString != null) { hyphenBoundFormatString = string.Format(CultureInfo.CurrentCulture, hyphenBoundFormatString, "\x1"); splitPosition = hyphenBoundFormatString.IndexOf('\x1'); if (splitPosition != 0) { addPart(hyphenBoundFormatString.Substring(0, splitPosition), null); } } if (nextNode != null) { ColumnPathStep nextStep = nextNode.Value; ColumnPathStepFlags nextFlags; if (incorporateNextAssimilation || (0 != ((nextFlags = nextStep.Flags) & ColumnPathStepFlags.RequiresDecoration) && 0 != (nextFlags & (ColumnPathStepFlags.ForwardAssimilation | ColumnPathStepFlags.ReverseAssimilation)) && step.TargetObjectType == nextStep.StartingObjectType)) { // Note that this does not interfere with the earlier 'back up one step' // because the checked flags are different. // Advance the loop one step previousPreviousResolvedSupertype = previousResolvedSupertype; previousPreviousResolvedObjectType = previousResolvedObjectType; previousResolvedSupertype = (0 != (step.Flags & ColumnPathStepFlags.ReverseAssimilation)) ? step.ResolvedSupertypeVerifyPreferred : step.ResolvedSupertype; previousResolvedObjectType = step.ResolvedObjectTypeVerifyPreferred; nextLoopNode = nextNode.Next; step = nextStep; lastStepConsumedNextNode = ReferenceModeNaming.ResolveObjectTypeName( nextStep.ResolvedObjectType, (nextLoopNode != null) ? nextLoopNode.Value.TargetObjectType : null, nextStep.ResolvedSupertypeVerifyPreferred, true, ReferenceModeNamingUse.ReferenceToEntityType, generator, addPart); } else { lastStepConsumedNextNode = ReferenceModeNaming.ResolveObjectTypeName( step.ResolvedObjectType, nextNode.Value.TargetObjectType, step.ResolvedSupertypeVerifyPreferred, true, ReferenceModeNamingUse.ReferenceToEntityType, generator, addPart); } } else { ReferenceModeNaming.ResolveObjectTypeName( (!firstPass || 0 != (stepFlags & ColumnPathStepFlags.IsIdentifier)) ? previousResolvedObjectType : null, step.TargetObjectType, previousResolvedSupertype, false, firstPass ? ReferenceModeNamingUse.PrimaryIdentifier : ReferenceModeNamingUse.ReferenceToEntityType, // Ignored if first parameter is null generator, addPart); } if (hyphenBoundFormatString != null && (hyphenBoundFormatString.Length - splitPosition) > 1) { addPart(hyphenBoundFormatString.Substring(splitPosition + 1), null); } } } else { lastStepConsumedNextNode = false; lastStepUsedExplicitRoleName = false; } } previousPreviousResolvedSupertype = previousResolvedSupertype; previousPreviousResolvedObjectType = previousResolvedObjectType; previousResolvedSupertype = (0 != (step.Flags & ColumnPathStepFlags.ReverseAssimilation)) ? step.ResolvedSupertypeVerifyPreferred : step.ResolvedSupertype; previousResolvedObjectType = step.ResolvedObjectTypeVerifyPreferred; currentNode = nextLoopNode; firstPass = false; } while (currentNode != null); string finalName = GetFinalName(singleName, nameCollection, generator); if (string.IsNullOrEmpty(finalName)) { return (phase == 0) ? "COLUMN" : null; } return finalName; }
/// <summary> /// Constructor /// Creates a ColumnReference link in the same Partition as the given Column /// </summary> /// <param name="source">Column to use as the source of the relationship.</param> /// <param name="target">Column to use as the target of the relationship.</param> public ColumnReference(Column source, Column target) : base((source != null ? source.Partition : null), new DslModeling::RoleAssignment[]{new DslModeling::RoleAssignment(ColumnReference.SourceColumnDomainRoleId, source), new DslModeling::RoleAssignment(ColumnReference.TargetColumnDomainRoleId, target)}, null) { }
public static void SetDomain(Column element, Domain newDomain) { DslModeling::DomainRoleInfo.SetLinkedElement(element, ColumnDomainRoleId, newDomain); }
public static DslModeling::LinkedElementCollection<Column> GetTargetColumnCollection(Column element) { return new DslModeling::LinkedElementCollection<Column>(element, SourceColumnDomainRoleId); }
private LinkedNode<ColumnPathStep> GetColumnPath(Column column) { Table table = column.Table; if (myColumnStepTable == table) { return myColumnSteps[column]; } Dictionary<Column, LinkedNode<ColumnPathStep>> columnSteps = myColumnSteps; if (myColumnStepTable == null) { myColumnSteps = columnSteps = new Dictionary<Column, LinkedNode<ColumnPathStep>>(); } else { columnSteps.Clear(); } myColumnStepTable = table; #if DEBUGCOLUMNPATH Debug.WriteLine("Table: " + table.Name); Debug.Indent(); Debug.Indent(); #endif // DEBUGCOLUMNPATH // Seed the cross-cutting dictionary and seed it with the main represented // ObjectTypes to force decorations on columns that loop back into this table. Dictionary<ObjectType, LinkedNode<LinkedNode<ColumnPathStep>>> objectTypeToSteps = new Dictionary<ObjectType, LinkedNode<LinkedNode<ColumnPathStep>>>(); ConceptType primaryConceptType = TableIsPrimarilyForConceptType.GetConceptType(table); if (primaryConceptType != null) { ObjectType targetObjectType = ConceptTypeIsForObjectType.GetObjectType(primaryConceptType); objectTypeToSteps[targetObjectType] = new LinkedNode<LinkedNode<ColumnPathStep>>(new LinkedNode<ColumnPathStep>(new ColumnPathStep(null, targetObjectType, null, ColumnPathStepFlags.None))); } foreach (ConceptType secondaryConceptType in TableIsAlsoForConceptType.GetConceptType(table)) { ObjectType targetObjectType = ConceptTypeIsForObjectType.GetObjectType(secondaryConceptType); objectTypeToSteps[targetObjectType] = new LinkedNode<LinkedNode<ColumnPathStep>>(new LinkedNode<ColumnPathStep>(new ColumnPathStep(null, targetObjectType, null, ColumnPathStepFlags.None))); } LinkedElementCollection<Column> columns = table.ColumnCollection; int columnCount = columns.Count; for (int iColumn = 0; iColumn < columnCount; ++iColumn) { Column currentColumn = columns[iColumn]; #if DEBUGCOLUMNPATH Debug.Unindent(); Debug.WriteLine("Column: " + currentColumn.Name); Debug.Indent(); #endif // DEBUGCOLUMNPATH LinkedElementCollection<ConceptTypeChild> childPath = ColumnHasConceptTypeChild.GetConceptTypeChildPath(currentColumn); int childPathCount = childPath.Count; LinkedNode<ColumnPathStep> headNode = null; LinkedNode<ColumnPathStep> tailNode = null; bool passedIdentifier = false; bool processTailDelayed = false; ConceptType nextComingFromConceptType = primaryConceptType; Objectification assimilationObjectification = null; for (int iChild = 0; iChild < childPathCount; ++iChild) { ConceptType comingFromConceptType = nextComingFromConceptType; ConceptTypeChild child = childPath[iChild]; ConceptTypeAssimilatesConceptType assimilation = child as ConceptTypeAssimilatesConceptType; bool reverseAssimilation = false; bool forwardToReverseTransition = false; bool towardsSubtype = false; if (assimilation != null) { if (comingFromConceptType == assimilation.Parent) { nextComingFromConceptType = assimilation.ReferencedConceptType; } else { towardsSubtype = true; nextComingFromConceptType = assimilation.Parent; } #if DEBUGCOLUMNPATH Debug.WriteLine("From: " + comingFromConceptType.Name + " To: " + nextComingFromConceptType.Name + "(" + (assimilation.RefersToSubtype && assimilation.IsPreferredForTarget).ToString() + ")"); #endif // DEBUGCOLUMNPATH if (tailNode != null) { // If we're already moving down an assimilation path in a specific direction then keep // going that direction ColumnPathStep pathStep = tailNode.Value; ColumnPathStepFlags stepFlags = pathStep.Flags; if (0 != (stepFlags & ColumnPathStepFlags.ForwardAssimilation)) { // Keep going forward if (0 != (stepFlags & ColumnPathStepFlags.AssimilationIsSubtype) && AssimilationMapping.GetAbsorptionChoiceFromAssimilation(assimilation) != AssimilationAbsorptionChoice.Absorb && comingFromConceptType == (0 == (stepFlags & ColumnPathStepFlags.AssimilationTowardsSubtype) ? assimilation.AssimilatedConceptType : assimilation.AssimilatorConceptType)) { forwardToReverseTransition = true; } } else if (0 != (stepFlags & ColumnPathStepFlags.ReverseAssimilation)) { // Keep going backward reverseAssimilation = true; } else { // Figure it out from this step reverseAssimilation = AssimilationMapping.GetAbsorptionChoiceFromAssimilation(assimilation) != AssimilationAbsorptionChoice.Absorb; } } else { reverseAssimilation = AssimilationMapping.GetAbsorptionChoiceFromAssimilation(assimilation) != AssimilationAbsorptionChoice.Absorb; } } else { nextComingFromConceptType = child.Target as ConceptType; #if DEBUGCOLUMNPATH Debug.WriteLine("From: " + comingFromConceptType.Name + " To: " + ((nextComingFromConceptType != null) ? nextComingFromConceptType.Name : ((InformationTypeFormat)child.Target).Name)); #endif // DEBUGCOLUMNPATH } LinkedElementCollection<FactType> factTypes = ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(child); int factTypeCount = factTypes.Count; for (int iFactType = 0; iFactType < factTypeCount; ++iFactType) { FactType factType = factTypes[iFactType]; Role targetRole = FactTypeMapsTowardsRole.GetTowardsRole(factType).Role; ColumnPathStepFlags flags = passedIdentifier ? ColumnPathStepFlags.PassedIdentifier : 0; ColumnPathStep pathStep = default(ColumnPathStep); bool processPreviousTail = false; Objectification previousAssimilationObjectification = assimilationObjectification; assimilationObjectification = null; bool processAsFactType = true; if (assimilation != null) { Role nonAssimilationTargetRole = targetRole; if (!towardsSubtype) { targetRole = targetRole.OppositeRoleAlwaysResolveProxy.Role; } processAsFactType = false; Objectification objectification; bool assimilationIsSubtype = assimilation.RefersToSubtype; bool secondarySubtype = assimilationIsSubtype && !assimilation.IsPreferredForTarget; if (!assimilationIsSubtype && null != (objectification = factType.ImpliedByObjectification) && objectification.NestingType == targetRole.RolePlayer) { assimilationObjectification = objectification; } if (tailNode != null) { pathStep = tailNode.Value; ColumnPathStepFlags tailFlags = pathStep.Flags; if (0 != (tailFlags & (ColumnPathStepFlags.ForwardAssimilation | ColumnPathStepFlags.ReverseAssimilation))) { bool tailIsSubtype = 0 != (tailFlags & ColumnPathStepFlags.AssimilationIsSubtype); if (tailIsSubtype && assimilationIsSubtype) { if (forwardToReverseTransition) { flags |= ColumnPathStepFlags.DeclinedAssimilation; targetRole = towardsSubtype ? targetRole.OppositeRoleAlwaysResolveProxy.Role : nonAssimilationTargetRole; processAsFactType = true; } else { if (secondarySubtype && 0 == (tailFlags & ColumnPathStepFlags.NonPreferredSubtype)) { tailNode.Value = new ColumnPathStep(pathStep.FromRole, pathStep.ObjectType, pathStep.AlternateObjectType, tailFlags | ColumnPathStepFlags.NonPreferredSubtype); } // If this is a subtype chain, then keep going, using the first // subtype in the chain as a node used in the final name. continue; } } else if (assimilationObjectification != null) { // The type of assimilation has changed, but we have an objectifying object type, // so we treat it like a separate link in the chain, or the previous element was // also not a subtype. tailNode.Value = new ColumnPathStep(pathStep.FromRole, pathStep.ObjectType, nonAssimilationTargetRole.RolePlayer, pathStep.Flags); processPreviousTail = processTailDelayed; } else { flags |= ColumnPathStepFlags.DeclinedAssimilation; targetRole = towardsSubtype ? targetRole.OppositeRoleAlwaysResolveProxy.Role : nonAssimilationTargetRole; processAsFactType = true; } } } else if (!assimilationIsSubtype && assimilationObjectification == null) { flags |= ColumnPathStepFlags.DeclinedAssimilation; targetRole = towardsSubtype ? targetRole.OppositeRoleAlwaysResolveProxy.Role : nonAssimilationTargetRole; processAsFactType = true; } if (!processAsFactType) { if (reverseAssimilation) { flags |= ColumnPathStepFlags.ReverseAssimilation; } else { flags |= ColumnPathStepFlags.ForwardAssimilation; } if (assimilationIsSubtype) { flags |= ColumnPathStepFlags.AssimilationIsSubtype; if (secondarySubtype) { flags |= ColumnPathStepFlags.NonPreferredSubtype; } if (towardsSubtype) { flags |= ColumnPathStepFlags.AssimilationTowardsSubtype; } } pathStep = new ColumnPathStep( null, towardsSubtype ? ConceptTypeIsForObjectType.GetObjectType(comingFromConceptType) : targetRole.RolePlayer, towardsSubtype ? targetRole.RolePlayer : null, flags); processTailDelayed = true; } } if (processAsFactType) { bool haveStep = false; if (tailNode != null) { pathStep = tailNode.Value; ColumnPathStepFlags tailFlags = pathStep.Flags; if (0 != (tailFlags & (ColumnPathStepFlags.ForwardAssimilation | ColumnPathStepFlags.ReverseAssimilation))) { RoleProxy oppositeProxy; Role objectifiedResolvedProxyRole; Role objectifiedOppositeRole; if (previousAssimilationObjectification != null && factType.ImpliedByObjectification == previousAssimilationObjectification && null != (oppositeProxy = targetRole.OppositeRole as RoleProxy) && null != (objectifiedOppositeRole = (objectifiedResolvedProxyRole = oppositeProxy.Role).OppositeRole as Role)) { flags |= ColumnPathStepFlags.ObjectifiedFactType; // Replace both factTypes with the original unobjectified FactType ObjectType fromObjectType = objectifiedOppositeRole.RolePlayer; if (pathStep.ObjectType == previousAssimilationObjectification.NestingType) { // Trivial path leading in, remove the subtype completely processTailDelayed = false; tailNode.Value = new ColumnPathStep(objectifiedOppositeRole, objectifiedResolvedProxyRole.RolePlayer, null, flags); ProcessTailNode(tailNode, objectTypeToSteps); continue; } tailNode.Value = new ColumnPathStep(pathStep.FromRole, pathStep.ObjectType, fromObjectType, pathStep.Flags); pathStep = new ColumnPathStep(objectifiedOppositeRole, objectifiedResolvedProxyRole.RolePlayer, null, flags); haveStep = true; } else { // Add a resolved supertype to the forward subtype to // allow later steps to be compared to this one. tailNode.Value = new ColumnPathStep(pathStep.FromRole, pathStep.ObjectType, targetRole.RolePlayer, pathStep.Flags); } } else if (!processTailDelayed && 0 != (tailFlags & ColumnPathStepFlags.DeclinedAssimilation)) { // Add a resolved supertype to the previous step tailNode.Value = new ColumnPathStep(pathStep.FromRole, pathStep.ObjectType, targetRole.RolePlayer, pathStep.Flags); } } if (!haveStep) { Role oppositeRole = targetRole.OppositeRoleAlwaysResolveProxy.Role; ORMUniquenessConstraint pid = targetRole.RolePlayer.PreferredIdentifier; if (pid != null && pid.RoleCollection.Contains(oppositeRole)) { flags |= ColumnPathStepFlags.IsIdentifier; passedIdentifier = true; } pathStep = new ColumnPathStep(targetRole, oppositeRole.RolePlayer, null, flags); } processPreviousTail = processTailDelayed; processTailDelayed = false; } if (processPreviousTail && tailNode != null) { ProcessTailNode(tailNode, objectTypeToSteps); } LinkedNode<ColumnPathStep> newNode = new LinkedNode<ColumnPathStep>(pathStep); if (tailNode == null) { headNode = tailNode = newNode; } else { tailNode.SetNext(newNode, ref headNode); tailNode = newNode; } if (!processTailDelayed) { ProcessTailNode(tailNode, objectTypeToSteps); } } } if (processTailDelayed) { ProcessTailNode(tailNode, objectTypeToSteps); } columnSteps.Add(currentColumn, headNode); } Debug.Unindent(); Debug.Unindent(); return columnSteps[column]; }