/// <summary>
 /// Same subtype may implement same supertype multiple time. Since ID of the supertype is usually same as subtype's ID,
 /// that might result with multiple supertype records with the same ID. To avoid duplicate IDs and still keep the
 /// deterministic ID values, the supertype's ID is XORed by a hash code taken from the ImplementationName.
 /// </summary>
 private string GetSubtypeImplementationIdSnippet()
 {
     if (IsSubtypeOf.ImplementationName == "")
     {
         return("");
     }
     else if (IsSubtypeOf.SupportsPersistedSubtypeImplementationColum())
     {
         return(",\r\n    SubtypeImplementationID = " + PersistedSubtypeImplementationIdInfo.GetComputedColumnName(IsSubtypeOf.ImplementationName));
     }
     else
     {
         int hash = DomUtility.GetSubtypeImplementationHash(IsSubtypeOf.ImplementationName);
         return(",\r\n    SubtypeImplementationID = CONVERT(UNIQUEIDENTIFIER, CONVERT(BINARY(4), CONVERT(INT, CONVERT(BINARY(4), ID)) ^ " + hash + ") + SUBSTRING(CONVERT(BINARY(16), ID), 5, 12))");
     }
 }
Exemple #2
0
        public IEnumerable <IConceptInfo> CreateNewConcepts(IsSubtypeOfInfo conceptInfo, IDslModel existingConcepts)
        {
            var newConcepts = new List <IConceptInfo>();

            // Add a subtype reference (for each subtype) to the supertype data structure:

            var subtypeReference = new PolymorphicSubtypeReferenceInfo
            {
                DataStructure = conceptInfo.Supertype,
                Referenced    = conceptInfo.Subtype,
                Name          = conceptInfo.GetSubtypeReferenceName()
            };

            newConcepts.Add(subtypeReference);
            newConcepts.Add(new PolymorphicPropertyInfo {
                Property = subtypeReference
            });                                                                           // Minor optimization to reduce the number of macro evaluations.

            // Append subtype implementation to the supertype union:

            newConcepts.Add(new SubtypeExtendPolymorphicInfo
            {
                IsSubtypeOf = conceptInfo,
                SubtypeImplementationView = conceptInfo.GetImplementationViewPrototype(),
                PolymorphicUnionView      = conceptInfo.Supertype.GetUnionViewPrototype()
            });

            var filterBySubtypePrototype = new FilterByInfo {
                Source = conceptInfo.Supertype, Parameter = "Rhetos.Dom.DefaultConcepts.FilterSubtype"
            };

            newConcepts.Add(new SubtypeExtendFilterInfo
            {
                IsSubtypeOf     = conceptInfo,
                FilterBySubtype = filterBySubtypePrototype
            });

            // Add metadata for supertype computation (union):

            foreach (DataStructureInfo dependsOn in DslUtility.GetBaseChangesOnDependency(conceptInfo.Subtype, existingConcepts))
            {
                newConcepts.Add(new ChangesOnChangedItemsInfo
                {
                    Computation   = conceptInfo.Supertype,
                    DependsOn     = dependsOn,
                    FilterType    = "Rhetos.Dom.DefaultConcepts.FilterSubtype",
                    FilterFormula = @"changedItems => new Rhetos.Dom.DefaultConcepts.FilterSubtype
                        {
                            Ids = changedItems.Select(" + GetComputeHashIdSelector(conceptInfo) + @").ToArray(),
                            Subtype = " + CsUtility.QuotedString(conceptInfo.Subtype.Module.Name + "." + conceptInfo.Subtype.Name) + @",
                            ImplementationName = " + CsUtility.QuotedString(conceptInfo.ImplementationName) + @"
                        }"
                });
            }

            // Add metadata for subtype implementation:

            PersistedSubtypeImplementationIdInfo subtypeImplementationColumn = null;

            if (conceptInfo.SupportsPersistedSubtypeImplementationColum())
            {
                subtypeImplementationColumn = new PersistedSubtypeImplementationIdInfo {
                    Subtype = conceptInfo.Subtype, ImplementationName = conceptInfo.ImplementationName
                };
                newConcepts.Add(subtypeImplementationColumn);
            }

            // Automatic interface implementation:

            var implementationView = (SqlViewInfo)existingConcepts.FindByKey(conceptInfo.GetImplementationViewPrototype().GetKey());

            if (implementationView == null)
            {
                implementationView = new ExtensibleSubtypeSqlViewInfo {
                    IsSubtypeOf = conceptInfo
                };
                newConcepts.Add(implementationView);

                if (subtypeImplementationColumn != null)
                {
                    newConcepts.Add(new SqlDependsOnSqlObjectInfo
                    {
                        // The subtype implementation view will use the PersistedSubtypeImplementationColumn.
                        DependsOn = subtypeImplementationColumn.GetSqlObjectPrototype(),
                        Dependent = implementationView
                    });
                }
            }

            // Redirect the developer-provided SQL dependencies from the "Is" concept to the implementation view:

            newConcepts.AddRange(DslUtility.CopySqlDependencies(conceptInfo, implementationView, existingConcepts));

            return(newConcepts);
        }