예제 #1
0
            /// <summary>
            /// AddRule: typeof(ORMSolutions.ORMArchitect.Core.ObjectModel.ValueTypeHasDataType)
            /// </summary>
            private static void DataTypeAddedRule(ElementAddedEventArgs e)
            {
                ValueTypeHasDataType link = (ValueTypeHasDataType)e.ModelElement;

                if (link.DataType is AutoCounterNumericDataType)
                {
                    SignificantObjectTypeChange(link.ValueType);
                }
            }
예제 #2
0
            /// <summary>
            /// DeleteRule: typeof(ORMSolutions.ORMArchitect.Core.ObjectModel.ValueTypeHasDataType)
            /// </summary>
            private static void DataTypeDeletedRule(ElementDeletedEventArgs e)
            {
                ValueTypeHasDataType link = (ValueTypeHasDataType)e.ModelElement;
                ObjectType           objectType;

                if (link.DataType is AutoCounterNumericDataType &&
                    !(objectType = link.ValueType).IsDeleted)
                {
                    SignificantObjectTypeChange(objectType);
                }
            }
예제 #3
0
        private static void UpdateTablesOnDataTypeChange(ValueTypeHasDataType link)
        {
            InformationTypeFormat format;
            LinkedElementCollection <ConceptType> conceptTypes;

            if (null != (format = InformationTypeFormatIsForValueType.GetInformationTypeFormat(link.ValueType)) &&
                0 != (conceptTypes = InformationType.GetConceptTypeCollection(format)).Count)
            {
                foreach (ConceptType conceptType in conceptTypes)
                {
                    UpdateTablesForConceptType(conceptType, null, null);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// AddRule: typeof(ValueTypeHasDataType)
        /// Stop the ValueTypeHasDataType relationship from being
        /// added if an ObjectType participates in a subtyping relationship
        /// </summary>
        private static void EnsureConsistentDataTypesAddRule(ElementAddedEventArgs e)
        {
            ValueTypeHasDataType           link        = e.ModelElement as ValueTypeHasDataType;
            ObjectType                     objectType  = link.ValueType;
            LinkedElementCollection <Role> playedRoles = objectType.PlayedRoleCollection;
            int playedRoleCount = playedRoles.Count;

            for (int i = 0; i < playedRoleCount; ++i)
            {
                Role testRole = playedRoles[i];
                if (testRole is SubtypeMetaRole ||
                    testRole is SupertypeMetaRole)
                {
                    if (null != testRole.FactType)
                    {
                        ThrowMixedRolePlayerTypesException();
                    }
                }
            }
        }
예제 #5
0
		private static void UpdateTablesOnDataTypeChange(ValueTypeHasDataType link)
		{
			InformationTypeFormat format;
			LinkedElementCollection<ConceptType> conceptTypes;
			if (null != (format = InformationTypeFormatIsForValueType.GetInformationTypeFormat(link.ValueType)) &&
				0 != (conceptTypes = InformationType.GetConceptTypeCollection(format)).Count)
			{
				foreach (ConceptType conceptType in conceptTypes)
				{
					UpdateTablesForConceptType(conceptType, null, null);
				}
			}
		}
예제 #6
0
        /// <summary>
        /// Test if an instance of one value type can be always be assigned to
        /// an instance of another value type.
        /// </summary>
        /// <param name="targetValueType">The type of the value being assigned to.</param>
        /// <param name="sourceValueType">The type of the value being assigned from.</param>
        /// <returns><see langword="true"/> if the source value can be assigned to the target value.</returns>
        /// <remarks>If either data type is unspecified, then the assumption is made that there is an error
        /// for this condition elsewhere and that the user will fix it, so this method returns true in these
        /// cases. Autogenerated values are assumed to be incompatible if they come from different value types
        /// because assigning autogenerated values to each other is also meaningingless.</remarks>
        public static bool IsAssignableValueType(ObjectType targetValueType, ObjectType sourceValueType)
        {
            if (targetValueType == sourceValueType)
            {
                return(true);
            }
            ValueTypeHasDataType targetUse;
            ValueTypeHasDataType sourceUse;

            if (null == (targetUse = ValueTypeHasDataType.GetLinkToDataType(targetValueType)) ||
                null == (sourceUse = ValueTypeHasDataType.GetLinkToDataType(sourceValueType)))
            {
                return(false);
            }
            PortableDataType targetType = targetUse.DataType.PortableDataType;
            PortableDataType sourceType = sourceUse.DataType.PortableDataType;

            if (sourceType == PortableDataType.Unspecified)
            {
                // Give user the benefit of the doubt that the types will be made compatible
                // if this choice is made.
                return(true);
            }
            int targetLength;
            int sourceLength;
            int targetScale;
            int sourceScale;

            switch (targetType)
            {
            case PortableDataType.Unspecified:
                // Let user fix
                return(true);

            case PortableDataType.TextFixedLength:
            case PortableDataType.TextVariableLength:
            case PortableDataType.TextLargeLength:
                switch (sourceType)
                {
                case PortableDataType.TextFixedLength:
                case PortableDataType.TextVariableLength:
                case PortableDataType.TextLargeLength:
                    targetLength = targetUse.Length;
                    sourceLength = sourceUse.Length;
                    return((targetLength == 0 ? int.MaxValue : targetLength) >= (sourceLength == 0 ? int.MaxValue : sourceLength));
                }
                break;

            case PortableDataType.NumericSignedInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericSignedInteger:
                case PortableDataType.NumericSignedSmallInteger:
                    return(true);

                case PortableDataType.NumericDecimal:
                    if (sourceUse.Scale == 0)
                    {
                        sourceLength = sourceUse.Length;
                        if (sourceLength != 0 && sourceLength <= 9)                                         // 10 might be too big
                        {
                            return(true);
                        }
                    }
                    break;
                }
                break;

            case PortableDataType.NumericSignedSmallInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericSignedSmallInteger:
                    return(true);

                case PortableDataType.NumericDecimal:
                    if (sourceUse.Scale == 0)
                    {
                        sourceLength = sourceUse.Length;
                        if (sourceLength != 0 && sourceLength <= 4)                                         // 5 might be too big
                        {
                            return(true);
                        }
                    }
                    break;
                }
                break;

            case PortableDataType.NumericSignedLargeInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericSignedInteger:
                case PortableDataType.NumericSignedSmallInteger:
                case PortableDataType.NumericSignedLargeInteger:
                    return(true);

                case PortableDataType.NumericDecimal:
                    if (sourceUse.Scale == 0)
                    {
                        sourceLength = sourceUse.Length;
                        if (sourceLength != 0 && sourceLength <= 18)                                         // 19 might be too big
                        {
                            return(true);
                        }
                    }
                    break;
                }
                break;

            case PortableDataType.NumericUnsignedInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericUnsignedInteger:
                case PortableDataType.NumericUnsignedTinyInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                    return(true);
                }
                break;

            case PortableDataType.NumericUnsignedTinyInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericUnsignedTinyInteger:
                    return(true);
                }
                break;

            case PortableDataType.NumericUnsignedSmallInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericUnsignedTinyInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                    return(true);
                }
                break;

            case PortableDataType.NumericUnsignedLargeInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericUnsignedInteger:
                case PortableDataType.NumericUnsignedTinyInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                case PortableDataType.NumericUnsignedLargeInteger:
                    return(true);
                }
                break;

            //case PortableDataType.NumericAutoCounter:
            // Only support this if the value types are the same. Otherwise, we're mapping different
            // counters to each other, which is meaningless.
            case PortableDataType.NumericFloatingPoint:
            case PortableDataType.NumericSinglePrecisionFloatingPoint:
            case PortableDataType.NumericDoublePrecisionFloatingPoint:
                switch (sourceType)
                {
                case PortableDataType.NumericFloatingPoint:
                    sourceLength = sourceUse.Length;
                    if (sourceLength == 0)
                    {
                        sourceLength = 53;
                    }
                    break;

                case PortableDataType.NumericSinglePrecisionFloatingPoint:
                    sourceLength = 24;
                    break;

                case PortableDataType.NumericDoublePrecisionFloatingPoint:
                    sourceLength = 53;
                    break;

                default:
                    sourceLength = -1;
                    break;
                }
                if (sourceLength != -1)
                {
                    switch (targetType)
                    {
                    case PortableDataType.NumericSinglePrecisionFloatingPoint:
                        targetLength = 24;
                        break;

                    case PortableDataType.NumericDoublePrecisionFloatingPoint:
                        targetLength = 53;
                        break;

                    //case PortableDataType.NumericFloatingPoint:
                    default:
                        targetLength = targetUse.Length;
                        if (targetLength == 0)
                        {
                            targetLength = 53;
                        }
                        break;
                    }
                    if (targetLength >= sourceLength)
                    {
                        return(true);
                    }
                }
                break;

            case PortableDataType.NumericDecimal:
            case PortableDataType.NumericMoney:
                sourceScale = 0;
                switch (sourceType)
                {
                case PortableDataType.NumericDecimal:
                    sourceLength = sourceUse.Length;
                    if (sourceLength == 0)
                    {
                        sourceLength = 18;
                    }
                    else
                    {
                        sourceScale = sourceUse.Scale;
                    }
                    break;

                case PortableDataType.NumericMoney:
                    sourceLength = 19;
                    sourceScale  = 4;
                    break;

                case PortableDataType.NumericSignedInteger:
                case PortableDataType.NumericUnsignedInteger:
                    sourceLength = 10;
                    break;

                case PortableDataType.NumericSignedSmallInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                    sourceLength = 5;
                    break;

                case PortableDataType.NumericSignedLargeInteger:
                    sourceLength = 19;
                    break;

                case PortableDataType.NumericUnsignedLargeInteger:
                    sourceLength = 20;
                    break;

                case PortableDataType.NumericUnsignedTinyInteger:
                    sourceLength = 3;
                    break;

                default:
                    sourceLength = -1;
                    break;
                }
                if (sourceLength != -1)
                {
                    if (targetType == PortableDataType.NumericMoney)
                    {
                        targetLength = 19;
                        targetScale  = 4;
                    }
                    else
                    {
                        targetLength = targetUse.Length;                                 // Length maps to precision, verify precision first, then scale
                        if (targetLength == 0)
                        {
                            targetLength = 18;
                            targetScale  = 0;
                        }
                        else
                        {
                            targetScale = targetUse.Scale;
                        }
                    }
                    if (targetLength >= sourceLength && targetScale >= sourceScale)
                    {
                        return(true);
                    }
                }
                break;

            case PortableDataType.RawDataFixedLength:
            case PortableDataType.RawDataVariableLength:
            case PortableDataType.RawDataLargeLength:
                switch (sourceType)
                {
                case PortableDataType.RawDataFixedLength:
                case PortableDataType.RawDataVariableLength:
                case PortableDataType.RawDataLargeLength:
                    targetLength = targetUse.Length;
                    sourceLength = sourceUse.Length;
                    return((targetLength == 0 ? int.MaxValue : targetLength) >= (sourceLength == 0 ? int.MaxValue : sourceLength));
                }
                break;

            case PortableDataType.RawDataPicture:
            case PortableDataType.RawDataOleObject:
            case PortableDataType.TemporalTime:
            case PortableDataType.TemporalDate:
            case PortableDataType.OtherRowId:
            case PortableDataType.OtherObjectId:
                if (sourceType == targetType)
                {
                    return(true);
                }
                break;

            case PortableDataType.TemporalAutoTimestamp:
            case PortableDataType.TemporalDateAndTime:
                switch (sourceType)
                {
                case PortableDataType.TemporalAutoTimestamp:
                case PortableDataType.TemporalTime:
                case PortableDataType.TemporalDate:
                case PortableDataType.TemporalDateAndTime:
                    return(true);
                }
                break;

            case PortableDataType.LogicalTrueOrFalse:
            case PortableDataType.LogicalYesOrNo:
                switch (sourceType)
                {
                case PortableDataType.LogicalTrueOrFalse:
                case PortableDataType.LogicalYesOrNo:
                    return(true);
                }
                break;
            }
            return(false);
        }
예제 #7
0
파일: Role.cs 프로젝트: cjheath/NORMA
		/// <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;
		}