示例#1
0
文件: Gatherer.cs 项目: 24418863/rdm
        /// <summary>
        /// Gathers dependencies of ColumnInfo, this includes all [Sql] properties on any object in data export / catalogue databases
        /// which references the fully qualified name of the ColumnInfo as well as it's immediate network friends that should share it's
        /// runtime name e.g. CatalogueItem and ExtractionInformation.
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public GatheredObject GatherDependencies(ColumnInfo c)
        {
            var allObjects = GetAllObjectsInAllDatabases();

            var propertyFinder = new AttributePropertyFinder <SqlAttribute>(allObjects);

            var root = new GatheredObject(c);

            foreach (var o in allObjects)
            {
                //don't add a reference to the thing we are gathering dependencies on!
                if (Equals(o, c))
                {
                    continue;
                }

                foreach (var propertyInfo in propertyFinder.GetProperties(o))
                {
                    var sql = (string)propertyInfo.GetValue(o);

                    if (sql != null && sql.Contains(c.Name))
                    {
                        root.Children.Add(new GatheredObject(o));
                    }
                }
            }

            return(root);
        }
示例#2
0
        /// <summary>
        /// Copies all properties not marked with [NoMappingToDatabase] or [Relationship] from the this object to the <paramref name="to"/> object.
        /// Also skips 'Name' and 'ID'
        /// </summary>
        /// <param name="to"></param>
        /// <param name="copyName"></param>
        /// <param name="save"></param>
        protected void CopyShallowValuesTo(DatabaseEntity to, bool copyName = false, bool save = true)
        {
            if (GetType() != to.GetType())
            {
                throw new NotSupportedException(string.Format("Object to must be the same Type as us, we were '{0}' and it was '{1}'", GetType().Name, to.GetType().Name));
            }

            var noMappingFinder = new AttributePropertyFinder <NoMappingToDatabase>(to);
            var relationsFinder = new AttributePropertyFinder <RelationshipAttribute>(to);

            foreach (var p in GetType().GetProperties())
            {
                if (p.Name.Equals("ID"))
                {
                    continue;
                }

                if (p.Name.Equals("Name") && !copyName)
                {
                    continue;
                }

                if (noMappingFinder.GetAttribute(p) != null || relationsFinder.GetAttribute(p) != null)
                {
                    continue;
                }

                p.SetValue(to, p.GetValue(this));
            }

            if (save)
            {
                to.SaveToDatabase();
            }
        }
示例#3
0
        /// <summary>
        /// Updates the user configurable (non ID) properties of the object <pararef name="o"/> to match the <paramref name="shareDefinition"/>
        /// </summary>
        /// <param name="o"></param>
        /// <param name="shareDefinition"></param>
        public void ImportPropertiesOnly(IMapsDirectlyToDatabaseTable o, ShareDefinition shareDefinition)
        {
            if (shareDefinition.Type != o.GetType())
            {
                throw new Exception("Share Definition is not for a " + o.GetType());
            }

            AttributePropertyFinder <RelationshipAttribute>            relationshipPropertyFinder = new AttributePropertyFinder <RelationshipAttribute>(o);
            AttributePropertyFinder <DoNotImportDescriptionsAttribute> skipPropertyFinder         = new AttributePropertyFinder <DoNotImportDescriptionsAttribute>(o);


            //for each property that isn't [NoMappingToDatabase]
            foreach (var kvp in shareDefinition.GetDictionaryForImport())
            {
                if (kvp.Key == "Name")
                {
                    continue;
                }

                var prop = o.GetType().GetProperty(kvp.Key);

                //If the property is a relationship e.g. _ID skip it
                if (relationshipPropertyFinder.GetAttribute(prop) != null)
                {
                    continue;
                }

                //do we skip this property?
                var skip = skipPropertyFinder.GetAttribute(prop);
                if (skip != null)
                {
                    //yes but only if blank
                    if (skip.AllowOverwriteIfBlank)
                    {
                        //is it currently not null? (if so skip)
                        var oldVal = prop.GetValue(o);

                        if (!(oldVal == DBNull.Value || oldVal == null || string.IsNullOrWhiteSpace(oldVal.ToString())))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        continue; //always skip
                    }
                }

                SetValue(prop, kvp.Value, o);
            }
        }
示例#4
0
        /// <summary>
        /// Creates a sharing export (<see cref="ObjectExport"/>) for the current <see cref="GatheredObject.Object"/> and then serializes it as a <see cref="ShareDefinition"/>.
        /// This includes mapping any [<see cref="RelationshipAttribute"/>] properties on the <see cref="GatheredObject.Object"/> to the relevant Share Guid (which must
        /// exist in branchParents).
        ///
        /// <para>ToShareDefinitionWithChildren if you want a full list of shares for the whole tree</para>
        /// </summary>
        /// <param name="shareManager"></param>
        /// <param name="branchParents"></param>
        /// <returns></returns>
        public ShareDefinition ToShareDefinition(ShareManager shareManager, List <ShareDefinition> branchParents)
        {
            var export = shareManager.GetNewOrExistingExportFor(Object);

            Dictionary <string, object> properties = new Dictionary <string, object>();
            Dictionary <RelationshipAttribute, Guid> relationshipProperties = new Dictionary <RelationshipAttribute, Guid>();

            AttributePropertyFinder <RelationshipAttribute> relationshipFinder = new AttributePropertyFinder <RelationshipAttribute>(Object);
            AttributePropertyFinder <NoMappingToDatabase>   noMappingFinder    = new AttributePropertyFinder <NoMappingToDatabase>(Object);


            //for each property in the Object class
            foreach (PropertyInfo property in Object.GetType().GetProperties())
            {
                //if it's the ID column skip it
                if (property.Name == "ID")
                {
                    continue;
                }

                //skip [NoMapping] columns
                if (noMappingFinder.GetAttribute(property) != null)
                {
                    continue;
                }

                //skip IRepositories (these tell you where the object came from)
                if (typeof(IRepository).IsAssignableFrom(property.PropertyType))
                {
                    continue;
                }

                RelationshipAttribute attribute = relationshipFinder.GetAttribute(property);

                //if it's a relationship to a shared object
                if (attribute != null && (attribute.Type == RelationshipType.SharedObject || attribute.Type == RelationshipType.OptionalSharedObject))
                {
                    var  idOfParent   = property.GetValue(Object);
                    Type typeOfParent = attribute.Cref;

                    var parent = branchParents.SingleOrDefault(d => d.Type == typeOfParent && d.ID.Equals(idOfParent));

                    //if the parent is not being shared along with us
                    if (parent == null)
                    {
                        //if a reference is required (i.e. not optional)
                        if (attribute.Type != RelationshipType.OptionalSharedObject)
                        {
                            throw new SharingException("Property " + property + " on Type " + Object.GetType() + " is marked [Relationship] but we found no ShareDefinition amongst the current objects parents to satisfy this property");
                        }
                    }
                    else
                    {
                        relationshipProperties.Add(attribute, parent.SharingGuid);
                    }
                }
                else
                {
                    properties.Add(property.Name, property.GetValue(Object));
                }
            }

            return(new ShareDefinition(export.SharingUIDAsGuid, Object.ID, Object.GetType(), properties, relationshipProperties));
        }
示例#5
0
        public void UpsertAndHydrate <T>(T toCreate, ShareDefinition shareDefinition) where T : class, IMapsDirectlyToDatabaseTable
        {
            IRepository repo;

            if (RepositoryLocator.CatalogueRepository.SupportsObjectType(typeof(T)))
            {
                repo = RepositoryLocator.CatalogueRepository;
            }
            else if (RepositoryLocator.DataExportRepository.SupportsObjectType(typeof(T)))
            {
                repo = RepositoryLocator.DataExportRepository;
            }
            else
            {
                throw new NotSupportedException("No Repository supported object type '" + typeof(T) + "'");
            }

            //Make a dictionary of the normal properties we are supposed to be importing
            Dictionary <string, object> propertiesDictionary = shareDefinition.GetDictionaryForImport();

            //for finding properties decorated with [Relationship]
            var finder = new AttributePropertyFinder <RelationshipAttribute>(toCreate);

            //If we have already got a local copy of this shared object?
            //either as an import or as an export
            T actual = (T)GetExistingImportObject(shareDefinition.SharingGuid) ?? (T)GetExistingExportObject(shareDefinition.SharingGuid);

            //we already have a copy imported of the shared object
            if (actual != null)
            {
                //It's an UPDATE i.e. take the new shared properties and apply them to the database copy / memory copy

                //copy all the values out of the share definition / database copy
                foreach (PropertyInfo prop in TableRepository.GetPropertyInfos(typeof(T)))
                {
                    //don't update any ID columns or any with relationships on UPDATE
                    if (propertiesDictionary.ContainsKey(prop.Name) && finder.GetAttribute(prop) == null)
                    {
                        SetValue(prop, propertiesDictionary[prop.Name], toCreate);
                    }
                    else
                    {
                        prop.SetValue(toCreate, prop.GetValue(actual)); //or use the database one if it isn't shared (e.g. ID, MyParent_ID etc)
                    }
                }

                toCreate.Repository = actual.Repository;

                //commit the updated values to the database
                repo.SaveToDatabase(toCreate);
            }
            else
            {
                //It's an INSERT i.e. create a new database copy with the correct foreign key values and update the memory copy

                //for each relationship property on the class we are trying to hydrate
                foreach (PropertyInfo property in TableRepository.GetPropertyInfos(typeof(T)))
                {
                    RelationshipAttribute relationshipAttribute = finder.GetAttribute(property);

                    //if it has a relationship attribute then we would expect the ShareDefinition to include a dependency relationship with the sharing UID of the parent
                    //and also that we had already imported it since dependencies must be imported in order
                    if (relationshipAttribute != null)
                    {
                        int?newValue;

                        switch (relationshipAttribute.Type)
                        {
                        case RelationshipType.OptionalSharedObject:
                        case RelationshipType.SharedObject:

                            //Confirm that the share definition includes the knowledge that theres a parent class to this object
                            if (!shareDefinition.RelationshipProperties.ContainsKey(relationshipAttribute))
                            {
                                //if it doesn't but the field is optional, ignore it
                                if (relationshipAttribute.Type == RelationshipType.OptionalSharedObject)
                                {
                                    newValue = null;
                                    break;
                                }
                                else
                                {
                                    //otherwise we are missing a required shared object being referenced. That's bad news.
                                    throw new Exception("Share Definition for object of Type " + typeof(T) + " is missing an expected RelationshipProperty called " + property.Name);
                                }
                            }

                            //Get the SharingUID of the parent for this property
                            Guid importGuidOfParent = shareDefinition.RelationshipProperties[relationshipAttribute];

                            //Confirm that we have a local import of the parent
                            var parentImport = GetExistingImport(importGuidOfParent);

                            //if we don't have a share reference
                            if (parentImport == null)
                            {
                                //and it isn't optional
                                if (relationshipAttribute.Type == RelationshipType.SharedObject)
                                {
                                    throw new Exception("Cannot import an object of type " + typeof(T) +
                                                        " because the ShareDefinition specifies a relationship to an object that has not yet been imported (A " +
                                                        relationshipAttribute.Cref + " with a SharingUID of " +
                                                        importGuidOfParent);
                                }
                                else
                                {
                                    newValue = null;     //it was optional and missing so just set to null
                                }
                            }
                            else
                            {
                                newValue = parentImport.ReferencedObjectID;     //we have the shared object
                            }
                            break;

                        case RelationshipType.LocalReference:
                            newValue = GetLocalReference(property, relationshipAttribute, shareDefinition);
                            break;

                        case RelationshipType.IgnoreableLocalReference:
                            newValue = null;
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        //get the ID of the local import of the parent
                        if (propertiesDictionary.ContainsKey(property.Name))
                        {
                            propertiesDictionary[property.Name] = newValue;
                        }
                        else
                        {
                            propertiesDictionary.Add(property.Name, newValue);
                        }
                    }
                }

                //insert the full dictionary into the database under the Type
                repo.InsertAndHydrate(toCreate, propertiesDictionary);

                //document that a local import of the share now exists and should be updated/reused from now on when that same GUID comes in / gets used by child objects
                GetImportAs(shareDefinition.SharingGuid.ToString(), toCreate);
            }
        }
示例#6
0
        public NavigateToObjectUI(IActivateItems activator, string initialSearchQuery = null, RDMPCollection focusedCollection = RDMPCollection.None) : base(activator)
        {
            _coreIconProvider  = activator.CoreIconProvider;
            _favouriteProvider = Activator.FavouritesProvider;
            _magnifier         = FamFamFamIcons.magnifier;
            InitializeComponent();

            CompletionAction = Emphasise;

            activator.Theme.ApplyTo(toolStrip1);

            _searchables = Activator.CoreChildProvider.GetAllSearchables();

            _usefulPropertyFinder = new AttributePropertyFinder <UsefulPropertyAttribute>(_searchables.Keys);

            textBox1.Focus();
            textBox1.Text = initialSearchQuery;

            textBox1.TextChanged += tbFind_TextChanged;
            textBox1.KeyUp       += _scintilla_KeyUp;

            FetchMatches(initialSearchQuery, CancellationToken.None);
            StartPosition  = FormStartPosition.CenterScreen;
            DoubleBuffered = true;

            _types     = _searchables.Keys.Select(k => k.GetType()).Distinct().ToArray();
            _typeNames = new HashSet <string>(_types.Select(t => t.Name));

            foreach (Type t in StartingEasyFilters.SelectMany(v => v.Value))
            {
                if (!_typeNames.Contains(t.Name))
                {
                    _typeNames.Add(t.Name);
                }
            }

            //autocomplete is all Type names (e.g. "Catalogue") + all short codes (e.g. "c")
            textBox1.AutoCompleteMode   = AutoCompleteMode.Append;
            textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
            textBox1.AutoCompleteCustomSource.AddRange(
                _typeNames.Union(ShortCodes.Select(kvp => kvp.Key)).ToArray());

            Type[] startingFilters = null;

            if (focusedCollection != RDMPCollection.None && StartingEasyFilters.ContainsKey(focusedCollection))
            {
                startingFilters = StartingEasyFilters[focusedCollection];
            }

            BackColorProvider backColorProvider = new BackColorProvider();

            foreach (Type t in EasyFilterTypesAndAssociatedCollections.Keys)
            {
                var b = new ToolStripButton();
                b.Image        = activator.CoreIconProvider.GetImage(t);
                b.CheckOnClick = true;
                b.Tag          = t;
                b.DisplayStyle = ToolStripItemDisplayStyle.Image;

                string shortCode = ShortCodes.Single(kvp => kvp.Value == t).Key;

                b.Text            = $"{t.Name} ({shortCode})";
                b.CheckedChanged += CollectionCheckedChanged;
                b.Checked         = startingFilters != null && startingFilters.Contains(t);

                b.BackgroundImage = backColorProvider.GetBackgroundImage(b.Size, EasyFilterTypesAndAssociatedCollections[t]);

                toolStrip1.Items.Add(b);
            }
        }