Ejemplo n.º 1
0
		/// <summary>
		/// Helper method to recursively walk value roles. A value role
		/// is any role that is allowed to have a value constraint.
		/// </summary>
		/// <param name="playedRoles">Roles from an ObjectType to walk. The assumption is made that the
		/// owning ObjectType is either a value type or has a preferred identifier with exactly one role</param>
		/// <param name="dataTypeLink">The data type information for the constraint</param>
		/// <param name="pathRoots">The <see cref="RolePathObjectTypeRoot"/> relationships from a role path associated
		/// with the root path.</param>
		/// <param name="previousValueConstraint">The value constraint nearest this value role.
		/// Any value constraint on the current set of roles must be a subset of the previousValueConstraint.</param>
		/// <param name="skipRole">A role to skip. If the playedRoles came from a preferred identifier,
		/// then the skipRole is the opposite role.</param>
		/// <param name="walkSubtypes">true to walk subtypes. Should be true if the playedRoles come from an
		/// EntityType and false if they come from a ValueType</param>
		/// <param name="visitor">The callback delegate</param>
		/// <returns>true to continue iteration</returns>
		private static bool WalkDescendedValueRoles(IList<Role> playedRoles, IList<RolePathObjectTypeRoot> pathRoots, ValueTypeHasDataType dataTypeLink, ValueConstraint previousValueConstraint, Role skipRole, bool walkSubtypes, ValueRoleVisitor visitor)
		{
			int count = pathRoots.Count;
			for (int i = 0; i < count; ++i)
			{
				RolePathObjectTypeRoot pathRoot = pathRoots[i];
				if (!visitor(null, null, pathRoot, dataTypeLink, pathRoot.ValueConstraint, previousValueConstraint))
				{
					return false;
				}
			}
			count = playedRoles.Count;
			for (int i = 0; i < count; ++i)
			{
				Role role = playedRoles[i];
				SupertypeMetaRole supertypeRole;
				if (role == skipRole)
				{
					// Nothing to do
				}
				else if (null != (supertypeRole = role as SupertypeMetaRole))
				{
					if (walkSubtypes)
					{
						SubtypeFact subtypeFact = (SubtypeFact)role.FactType;
						ObjectType subtype;
						if (subtypeFact.ProvidesPreferredIdentifier &&
							null != (subtype = subtypeFact.Subtype) &&
							subtype.PreferredIdentifier == null)
						{
							if (!WalkDescendedValueRoles(subtype.PlayedRoleCollection, RolePathObjectTypeRoot.GetLinksToRolePathCollection(subtype), dataTypeLink, previousValueConstraint, null, true, visitor))
							{
								return false;
							}
						}
					}
				}
				else if (!(role is SubtypeMetaRole))
				{
					RoleValueConstraint currentValueConstraint = role.ValueConstraint;
					if (!visitor(role, null, null, dataTypeLink, currentValueConstraint, previousValueConstraint))
					{
						return false;
					}
					if (currentValueConstraint != null && !currentValueConstraint.IsDeleted)
					{
						previousValueConstraint = currentValueConstraint;
					}
					foreach (PathedRole pathedRole in PathedRole.GetLinksToRolePathCollection(role))
					{
						// UNDONE: VALUEROLE This does not correctly report a value constraint from a previous
						// path node. Note that this, as well as allowing value restrictions on supertype roles
						// (and possibly other patterns), can result in multiple previous value constraints, so
						// the callback signature may possibly need to be modified here. As of changeset 1442,
						// none of the callbacks use the previousValueConstraint information, so we can ignore
						// this for now.

						// Note that we visit for the pathed role even if no value constraint is present
						// to allow processing for this pathed role.
						if (!visitor(role, pathedRole, null, dataTypeLink, pathedRole.ValueConstraint, previousValueConstraint))
						{
							return false;
						}
					}

					// Walk sequences to find a single-role preferred identifier so
					// we can get to the next link.
					LinkedElementCollection<ConstraintRoleSequence> sequences = role.ConstraintRoleSequenceCollection;
					int sequencesCount = sequences.Count;
					for (int j = 0; j < sequencesCount; ++j)
					{
						UniquenessConstraint constraint = sequences[j] as UniquenessConstraint;
						ObjectType identifierFor;
						if (null != (constraint = sequences[j] as UniquenessConstraint) &&
							null != (identifierFor = constraint.PreferredIdentifierFor) &&
							constraint.RoleCollection.Count == 1)
						{
							RoleBase nextSkipRole = role.OppositeRoleAlwaysResolveProxy;
							if (nextSkipRole == null)
							{
								return false;
							}
							if (!WalkDescendedValueRoles(identifierFor.PlayedRoleCollection, RolePathObjectTypeRoot.GetLinksToRolePathCollection(identifierFor), dataTypeLink, previousValueConstraint, nextSkipRole.Role, true, visitor))
							{
								return false;
							}
						}
					}
				}
			}
			return true;
		}
Ejemplo n.º 2
0
		/// <summary>
		/// Get all value roles including all roles directly attached to the provided
		/// object type and any roles descended from this one through prefererred identifiers.
		/// Walks the opposite direction of <see cref="Role.GetValueRoles()"/>
		/// </summary>
		/// <param name="anchorType">The <see cref="ObjectType"/> to walk descended roles for</param>
		/// <param name="unattachedRole">A role to test that is not currently attached to the anchorType.
		/// If unattachedRole is not null, then only this role will be tested. Otherwise, all current played
		/// roles will be walked.</param>
		/// <param name="unattachedPreferredIdentifier">A preferred identifier to test that is not currently
		/// attached to the anchorType.</param>
		/// <param name="visitor">A <see cref="ValueRoleVisitor"/> callback delegate.</param>
		public static void WalkDescendedValueRoles(ObjectType anchorType, Role unattachedRole, UniquenessConstraint unattachedPreferredIdentifier, ValueRoleVisitor visitor)
		{
			ValueTypeHasDataType dataTypeLink = anchorType.GetDataTypeLink();
			if (null == unattachedPreferredIdentifier &&
				null != (dataTypeLink = anchorType.GetDataTypeLink()))
			{
				ObjectType unattachedRolePlayer;
				WalkDescendedValueRoles(
					(unattachedRole != null) ? new Role[] { unattachedRole } as IList<Role> : anchorType.PlayedRoleCollection,
					RolePathObjectTypeRoot.GetLinksToRolePathCollection(anchorType),
					dataTypeLink,
					anchorType.ValueConstraint,
					null,
					(null == unattachedRole || null == (unattachedRolePlayer = unattachedRole.RolePlayer)) ? false : !unattachedRolePlayer.IsValueType,
					visitor);
			}
			else
			{
				LinkedElementCollection<Role> roles;
				UniquenessConstraint preferredIdentifier;
				if (null != (preferredIdentifier = unattachedPreferredIdentifier ?? anchorType.ResolvedPreferredIdentifier) &&
					(roles = preferredIdentifier.RoleCollection).Count == 1)
				{
					Role currentRole = roles[0];
					Role[] valueRoles = currentRole.GetValueRoles();
					if (valueRoles != null)
					{
						ValueConstraint nearestValueConstraint = null;
						int valueRolesCount = valueRoles.Length;
						for (int i = valueRolesCount - 1; i >= 0; --i)
						{
							nearestValueConstraint = valueRoles[i].ValueConstraint;
							if (nearestValueConstraint != null)
							{
								break;
							}
						}
						ObjectType valueType = valueRoles[0].RolePlayer;
						dataTypeLink = valueType.GetDataTypeLink();
						if (nearestValueConstraint == null)
						{
							nearestValueConstraint = valueType.ValueConstraint;
						}
						RoleBase nextSkipRole = currentRole.OppositeRoleAlwaysResolveProxy;
						if (nextSkipRole != null)
						{
							WalkDescendedValueRoles(
								(unattachedRole != null) ? new Role[] { unattachedRole } as IList<Role> : anchorType.PlayedRoleCollection,
								RolePathObjectTypeRoot.GetLinksToRolePathCollection(anchorType),
								dataTypeLink,
								nearestValueConstraint,
								nextSkipRole.Role,
								true,
								visitor);
						}
					}
				}
			}
		}