public void CheckSemantics(IDslModel concepts)
        {
            if (Module.Name != Source.Module.Name)
                throw new DslSyntaxException(
                    string.Format("Browse should be created in same module as referenced entity. Expecting {0} instead of {1}.",
                        Source.Module,
                        Module));

            var properties = concepts.FindByReference<PropertyInfo>(p => p.DataStructure, this);

            var propertyWithoutSelector = properties
                .Where(p => concepts.FindByReference<BrowseFromPropertyInfo>(bfp => bfp.PropertyInfo, p).Count() == 0)
                .FirstOrDefault();

            if (propertyWithoutSelector != null)
                throw new DslSyntaxException(
                    string.Format("Browse property {0} does not have a source selected. Probably missing '{1}'.",
                        propertyWithoutSelector.GetUserDescription(),
                        ConceptInfoHelper.GetKeywordOrTypeName(typeof(BrowseFromPropertyInfo))));
        }
        public void CheckSemantics(IDslModel concepts)
        {
            if (ReferenceFromMe.DataStructure != Source)
                throw new DslSyntaxException("'" + this.GetUserDescription()
                    + "' must use a reference property that is a member of it's own data structure. Try using FilterByLinkedItems instead.");

            var availableFilters = concepts.FindByReference<ComposableFilterByInfo>(f => f.Source, ReferenceFromMe.Referenced)
                .Select(f => f.Parameter).OrderBy(f => f).ToList();

            if (!availableFilters.Contains(Parameter))
                throw new DslSyntaxException(this, string.Format(
                    "There is no {0} '{1}' on {2}. Available {0} filters are: {3}.",
                    ConceptInfoHelper.GetKeywordOrTypeName(typeof(ComposableFilterByInfo)),
                    Parameter,
                    ReferenceFromMe.Referenced.GetUserDescription(),
                    string.Join(", ", availableFilters.Select(parameter => "'" + parameter + "'"))));
        }
        public void CheckSemantics(IDslModel existingConcepts)
        {
            if (ReferenceFromMe.DataStructure != Source)
            {
                throw new DslSyntaxException("'" + this.GetUserDescription()
                                             + "' must use a reference property that is a member of it's own data structure. Try using FilterByLinkedItems instead.");
            }

            var availableFilters = existingConcepts.FindByReference <ItemFilterInfo>(f => f.Source, ReferenceFromMe.Referenced)
                                   .Select(f => f.FilterName).OrderBy(f => f).ToList();

            if (!availableFilters.Contains(FilterName))
            {
                throw new DslSyntaxException(this, string.Format(
                                                 "There is no {0} '{1}' on {2}. Available {0} filters are: {3}.",
                                                 ConceptInfoHelper.GetKeywordOrTypeName(typeof(ItemFilterInfo)),
                                                 FilterName,
                                                 ReferenceFromMe.Referenced.GetUserDescription(),
                                                 string.Join(", ", availableFilters.Select(name => "'" + name + "'"))));
            }
        }
Beispiel #4
0
        public IEnumerable <IConceptInfo> CreateNewConcepts(SqlDependsOnDataStructureInfo conceptInfo, IDslModel existingConcepts)
        {
            var newConcepts = new List <IConceptInfo>();

            if (conceptInfo.DependsOn is PolymorphicInfo)
            {
                newConcepts.Add(new SqlDependsOnSqlObjectInfo {
                    Dependent = conceptInfo.Dependent,
                    DependsOn = ((PolymorphicInfo)conceptInfo.DependsOn).GetUnionViewPrototype()
                });
            }

            newConcepts.AddRange(
                existingConcepts.FindByReference <PropertyInfo>(p => p.DataStructure, conceptInfo.DependsOn)
                .Where(p => p != conceptInfo.Dependent)
                .Select(p => new SqlDependsOnPropertyInfo {
                Dependent = conceptInfo.Dependent, DependsOn = p
            })
                .ToList());

            return(newConcepts);
        }
        public IEnumerable <IConceptInfo> CreateNewConcepts(ChangesOnLinkedItemsInfo conceptInfo, IDslModel existingConcepts)
        {
            var extendsConcept = existingConcepts.FindByReference <UniqueReferenceInfo>(extends => extends.Extension, conceptInfo.Computation).FirstOrDefault();

            if (extendsConcept == null)
            {
                throw new DslSyntaxException("ChangesOnLinkedItems is used on '" + conceptInfo.Computation.GetUserDescription()
                                             + "' which does not extend another base data structure. Consider adding 'Extends' concept.");
            }

            if (conceptInfo.LinkedItemsReference.Referenced != extendsConcept.Base)
            {
                throw new DslSyntaxException("ChangesOnLinkedItems used on '" + conceptInfo.Computation.GetUserDescription()
                                             + "' declares reference '" + conceptInfo.LinkedItemsReference.GetKeyProperties()
                                             + "'. The reference should point to computation's base data structure '" + extendsConcept.Base.GetUserDescription()
                                             + "'. Instead it points to '" + conceptInfo.LinkedItemsReference.Referenced.GetUserDescription() + "'.");
            }

            if (!typeof(EntityInfo).IsAssignableFrom(conceptInfo.LinkedItemsReference.DataStructure.GetType()))
            {
                throw new DslSyntaxException("ChangesOnLinkedItems is used on '" + conceptInfo.Computation.GetUserDescription()
                                             + "', but the data structure it depends on '" + conceptInfo.LinkedItemsReference.DataStructure.GetUserDescription()
                                             + "' is not Entity. Currently only entities are supported in automatic handling of dependencies.");
            }

            return(new[]
            {
                new ChangesOnChangedItemsInfo
                {
                    Computation = conceptInfo.Computation,
                    DependsOn = (EntityInfo)conceptInfo.LinkedItemsReference.DataStructure,
                    FilterType = "Guid[]",
                    FilterFormula = @"changedItems => changedItems.Where(item => item."
                                    + conceptInfo.LinkedItemsReference.Name + "ID != null).Select(item => item."
                                    + conceptInfo.LinkedItemsReference.Name + "ID.Value).Distinct().ToArray()"
                }
            });
        }
Beispiel #6
0
 private UniqueReferenceInfo MyExtendsConceptInfo(IDslModel existingConcepts)
 {
     return(existingConcepts.FindByReference <UniqueReferenceInfo>(extends => extends.Extension, Persisted)
            .FirstOrDefault());
 }
Beispiel #7
0
 private DataStructureInfo GetBaseDataStructure(FilterByBaseInfo conceptInfo, IDslModel concepts)
 {
     return(concepts.FindByReference <UniqueReferenceInfo>(ci => ci.Extension, conceptInfo.Source)
            .Select(ci => ci.Base)
            .SingleOrDefault());
 }
Beispiel #8
0
        /// <summary>
        /// Returns a writable data structure that can be used to monitor data changes (intercepting its Save function), in order to update a persisted data.
        /// Returns empty array if a required data structure is not found.
        /// </summary>
        public static IEnumerable<DataStructureInfo> GetBaseChangesOnDependency(DataStructureInfo dependsOn, IDslModel existingConcepts)
        {
            if (dependsOn.Name.EndsWith("_History"))
            {
                var history = existingConcepts.FindByReference<EntityHistoryInfo>(h => h.Dependency_HistorySqlQueryable, dependsOn).SingleOrDefault();
                if (history != null)
                    return new DataStructureInfo[] { history.Entity, history.Dependency_ChangesEntity };
            }

            if (dependsOn is IWritableOrmDataStructure)
                return new[] { dependsOn };

            if (existingConcepts.FindByReference<WriteInfo>(write => write.DataStructure, dependsOn).Any())
                return new[] { dependsOn };

            var baseDataStructure = existingConcepts.FindByReference<DataStructureExtendsInfo>(ex => ex.Extension, dependsOn)
                .Select(ex => ex.Base).SingleOrDefault();
            if (baseDataStructure != null)
                return GetBaseChangesOnDependency(baseDataStructure, existingConcepts);

            return Enumerable.Empty<DataStructureInfo>();
        }
 public RowPermissionsWriteInfo GetRowPermissionsWrite(IDslModel existingConcepts)
 {
     return(existingConcepts.FindByReference <RowPermissionsWriteInfo>(rp => rp.Source, Source)
            .SingleOrDefault());
 }
Beispiel #10
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 ReferencePropertyInfo
            {
                DataStructure = conceptInfo.Supertype,
                Referenced    = conceptInfo.Subtype,
                Name          = conceptInfo.GetSubtypeReferenceName()
            };

            newConcepts.Add(subtypeReference);
            newConcepts.Add(new PolymorphicPropertyInfo {
                Property = subtypeReference, SubtypeReference = conceptInfo.Subtype.GetKeyProperties()
            });

            // 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):

            string hashId = conceptInfo.ImplementationName == "" ? "item.ID"
                : "DomUtility.GetSubtypeImplementationId(item.ID, " + DomUtility.GetSubtypeImplementationHash(conceptInfo.ImplementationName) + ")";

            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(item => " + hashId + @").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(existingConcepts.FindByReference <SqlDependsOnDataStructureInfo>(dep => dep.Dependent, conceptInfo)
                                 .Select(dep => new SqlDependsOnDataStructureInfo {
                Dependent = implementationView, DependsOn = dep.DependsOn
            }));

            newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnModuleInfo>(dep => dep.Dependent, conceptInfo)
                                 .Select(dep => new SqlDependsOnModuleInfo {
                Dependent = implementationView, DependsOn = dep.DependsOn
            }));

            newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnPropertyInfo>(dep => dep.Dependent, conceptInfo)
                                 .Select(dep => new SqlDependsOnPropertyInfo {
                Dependent = implementationView, DependsOn = dep.DependsOn
            }));

            newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnSqlFunctionInfo>(dep => dep.Dependent, conceptInfo)
                                 .Select(dep => new SqlDependsOnSqlFunctionInfo {
                Dependent = implementationView, DependsOn = dep.DependsOn
            }));

            newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnSqlIndexInfo>(dep => dep.Dependent, conceptInfo)
                                 .Select(dep => new SqlDependsOnSqlIndexInfo {
                Dependent = implementationView, DependsOn = dep.DependsOn
            }));

            newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnSqlObjectInfo>(dep => dep.Dependent, conceptInfo)
                                 .Select(dep => new SqlDependsOnSqlObjectInfo {
                Dependent = implementationView, DependsOn = dep.DependsOn
            }));

            newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnSqlViewInfo>(dep => dep.Dependent, conceptInfo)
                                 .Select(dep => new SqlDependsOnSqlViewInfo {
                Dependent = implementationView, DependsOn = dep.DependsOn
            }));

            return(newConcepts);
        }