Beispiel #1
0
        /// <summary>
        /// Attach a master
        /// </summary>
        public object Add(Type scopingType, object scopingKey, object item)
        {
            var dataManager = MdmDataManagerFactory.GetDataManager(scopingType);

            if (dataManager == null)
            {
                throw new NotSupportedException($"MDM is not configured for {scopingType}");
            }

            // Detach
            if (scopingKey is Guid scopedKey && item is IdentifiedDataReference childObject)
            {
                try
                {
                    var transaction = new Bundle(dataManager.MdmTxMasterLink(scopedKey, childObject.Key.Value, new IdentifiedData[0], true));

                    var retVal = this.m_batchService.Insert(transaction, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                    return(retVal);
                }
                catch (Exception e)
                {
                    this.m_tracer.TraceError("Error attaching master- {0}", e);
                    throw new MdmException($"Error detaching {scopingKey} from {childObject.Key}", e);
                }
            }
Beispiel #2
0
        /// <summary>
        /// Search for the specified entity
        /// </summary>
        public IEnumerable <TEntity> Search <TEntity>(string[] term, Guid queryId, int offset, int?count, out int totalResults, ModelSort <TEntity>[] orderBy) where TEntity : IdentifiedData, new()
        {
            var searchTerm = String.Join(" and ", term);

            // Perform the queries on the terms
            if (this.m_configuration.ResourceTypes.Any(rt => rt.Type == typeof(TEntity))) // Under MDM control
            {
                var principal = AuthenticationContext.Current.Principal;
                // HACK: Change this method to detect the type
                var idps = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Entity> >();
                if (idps == null)
                {
                    throw new InvalidOperationException("Cannot find a query repository service");
                }

                var expression = QueryExpressionParser.BuildLinqExpression <Entity>(new NameValueCollection()
                {
                    { "classConcept", MdmConstants.MasterRecordClassification.ToString() },
                    { "relationship[97730a52-7e30-4dcd-94cd-fd532d111578].source.id", $":(freetext|{searchTerm})" }
                });
                var results        = idps.Query(expression, offset, count, out totalResults, principal);
                var mdmDataManager = MdmDataManagerFactory.GetDataManager <TEntity>();
                if (Environment.ProcessorCount > 4)
                {
                    return(results.AsParallel().AsOrdered().Select(o => mdmDataManager.CreateMasterContainerForMasterEntity(o).Synthesize(principal)).OfType <TEntity>().ToList());
                }
                else
                {
                    return(results.Select(o => mdmDataManager.CreateMasterContainerForMasterEntity(o).Synthesize(principal)).OfType <TEntity>().ToList());
                }
            }
            else
            {
                // Does the provider support freetext search clauses?
                var idps = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >();
                if (idps == null)
                {
                    throw new InvalidOperationException("Cannot find a query repository service");
                }

                return(idps.Query(o => o.FreetextSearch(searchTerm), offset, count, out totalResults, AuthenticationContext.Current.Principal, orderBy));
            }
        }
        /// <summary>
        /// Perform  the operation
        /// </summary>
        public override object Invoke(Type scopingType, object scopingKey, ParameterCollection parameters)
        {
            var dataManager = MdmDataManagerFactory.GetDataManager(scopingType);

            if (dataManager == null)
            {
                throw new NotSupportedException($"MDM is not configured for {scopingType}");
            }

            if (scopingKey == null)
            {
                parameters.TryGet <bool>("clear", out bool clear);
                this.m_jobManager.StartJob(typeof(MdmMatchJob <>).MakeGenericType(scopingType), new object[] { clear });
                return(null);
            }
            else if (scopingKey is Guid scopingObjectKey)
            {
                // Load the current master from @scopingKey
                if (!dataManager.IsMaster(scopingObjectKey))
                {
                    throw new KeyNotFoundException($"{scopingObjectKey} is not an MDM Master");
                }

                // Now - we want to prepare a transaction
                Bundle retVal = new Bundle();

                if (parameters.TryGet <bool>("clear", out bool clear) && clear)
                {
                    foreach (var itm in dataManager.GetCandidateLocals(scopingObjectKey).Where(o => o.ClassificationKey == MdmConstants.AutomagicClassification))
                    {
                        if (itm is EntityRelationship er)
                        {
                            er.BatchOperation = Core.Model.DataTypes.BatchOperationType.Delete;
                            retVal.Add(er);
                        }
                        else if (itm is ActRelationship ar)
                        {
                            ar.BatchOperation = Core.Model.DataTypes.BatchOperationType.Delete;
                            retVal.Add(ar);
                        }
                    }
                }

                retVal.AddRange(dataManager.MdmTxDetectCandidates(dataManager.MdmGet(scopingObjectKey).Synthesize(AuthenticationContext.Current.Principal) as Entity, retVal.Item));

                // Now we want to save?
                try
                {
                    retVal = this.m_batchService.Insert(retVal, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                }
                catch (Exception e)
                {
                    this.m_tracer.TraceError("Error persisting re-match: {0}", e.Message);
                    throw new MdmException("Error persisting re-match operation", e);
                }
                return(retVal);
            }
            else
            {
                throw new InvalidOperationException("Cannot determine the operation");
            }
        }
        /// <summary>
        /// Start the daemon
        /// </summary>
        public bool Start()
        {
            this.Starting?.Invoke(this, EventArgs.Empty);

            // Pre-register types for serialization
            foreach (var itm in this.m_configuration.ResourceTypes)
            {
                if (itm.Type == typeof(Entity))
                {
                    throw new InvalidOperationException("Cannot bind MDM control to Entity or Act , only sub-classes");
                }

                var    rt       = itm.Type;
                string typeName = $"{rt.Name}Master";
                if (typeof(Entity).IsAssignableFrom(rt))
                {
                    rt = typeof(EntityMaster <>).MakeGenericType(rt);
                }
                else if (typeof(Act).IsAssignableFrom(rt))
                {
                    rt = typeof(ActMaster <>).MakeGenericType(rt);
                }
                ModelSerializationBinder.RegisterModelType(typeName, rt);
            }

            // Wait until application context is started
            ApplicationServiceContext.Current.Started += (o, e) =>
            {
                if (this.m_matchingService == null)
                {
                    this.m_traceSource.TraceWarning("The MDM Service should be using a record matching service");
                }

                // Replace matching
                var mdmMatcher = this.m_serviceManager.CreateInjected <MdmRecordMatchingService>();
                this.m_serviceManager.AddServiceProvider(mdmMatcher);
                var mdmMatchConfig = this.m_serviceManager.CreateInjected <MdmMatchConfigurationService>();
                this.m_serviceManager.AddServiceProvider(mdmMatchConfig);
                if (this.m_matchingService != null)
                {
                    this.m_serviceManager.RemoveServiceProvider(this.m_matchingService.GetType());
                }
                if (this.m_matchConfigurationService != null)
                {
                    this.m_serviceManager.RemoveServiceProvider(this.m_matchConfigurationService.GetType());
                }

                foreach (var itm in this.m_configuration.ResourceTypes)
                {
                    this.m_traceSource.TraceInfo("Adding MDM listener for {0}...", itm.Type.Name);
                    MdmDataManagerFactory.RegisterDataManager(itm.Type);
                    var idt = typeof(MdmResourceHandler <>).MakeGenericType(itm.Type);
                    var ids = this.m_serviceManager.CreateInjected(idt) as IDisposable;
                    this.m_listeners.Add(ids);
                    this.m_serviceManager.AddServiceProvider(ids);
                    this.m_serviceManager.AddServiceProvider(MdmDataManagerFactory.CreateMerger(itm.Type));

                    // Add job
                    var jobType = typeof(MdmMatchJob <>).MakeGenericType(itm.Type);
                    var job     = this.m_serviceManager.CreateInjected(jobType) as IJob;
                    this.m_jobManager?.AddJob(job, JobStartType.Never);
                }

                // Add an entity relationship and act relationship watcher to the persistence layer for after update
                // this will ensure that appropriate cleanup is performed on successful processing of data
                this.m_entityRelationshipService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <EntityRelationship> >();
                this.m_entityService             = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Entity> >();

                ApplicationServiceContext.Current.GetService <IDataPersistenceService <Bundle> >().Inserted  += RecheckBundleTrigger;
                ApplicationServiceContext.Current.GetService <IDataPersistenceService <Bundle> >().Updated   += RecheckBundleTrigger;
                ApplicationServiceContext.Current.GetService <IDataPersistenceService <Bundle> >().Obsoleted += RecheckBundleTrigger;
                this.m_entityRelationshipService.Inserted  += RecheckRelationshipTrigger;
                this.m_entityRelationshipService.Updated   += RecheckRelationshipTrigger;
                this.m_entityRelationshipService.Obsoleted += RecheckRelationshipTrigger;

                // Add an MDM listener for subscriptions
                if (this.m_subscriptionExecutor != null)
                {
                    m_subscriptionExecutor.Executing += MdmSubscriptionExecuting;
                    m_subscriptionExecutor.Executed  += MdmSubscriptionExecuted;
                }
                this.m_listeners.Add(new BundleResourceInterceptor(this.m_listeners));

                // Slipstream the MdmEntityProvider
                //EntitySource.Current = new EntitySource(new MdmEntityProvider());

                // HACK: Replace any freetext service with our own
                this.m_serviceManager.RemoveServiceProvider(typeof(IFreetextSearchService));
                m_serviceManager.AddServiceProvider(new MdmFreetextSearchService());
            };

            this.Started?.Invoke(this, EventArgs.Empty);
            return(true);
        }