/// <summary> /// Checks if the entities are IReferenceByHiveId and of the same type if so returns true if the Ids match, otherwise false. /// </summary> /// <param name="op"></param> /// <param name="objectToCompare"></param> /// <returns></returns> internal static bool EntitiesAreEqual(this LinearHiveIndexOperation op, object objectToCompare) { if (ReferenceEquals(op.Entity, objectToCompare)) { return(true); } var entityToCompare = objectToCompare as IReferenceByHiveId; if (entityToCompare == null) { return(false); } var entity = op.Entity as IReferenceByHiveId; if (entity == null) { return(false); } if (entity.GetType() != objectToCompare.GetType()) { return(false); } if (entityToCompare.Id.IsNullValueOrEmpty() || entity.Id.IsNullValueOrEmpty()) { return(false); } return(entity.Id.Value.Equals(entityToCompare.Id.Value)); }
/// <summary> /// Removes the relation. /// </summary> /// <param name="item">The item.</param> /// <param name="transaction"></param> public void PerformRemoveRelation(IRelationById item, ExamineTransaction transaction) { Mandate.ParameterNotNull(item, "item"); var delete = new LinearHiveIndexOperation() { OperationType = IndexOperationType.Delete, Id = new Lazy <string>(item.GetCompositeId) }; transaction.EnqueueIndexOperation(delete); }
/// <summary> /// Detects if the Entity of the operation already exists in the queue list, if it does and it has been changed /// then this removes that operation from the queue list and returns true so that the newer version is added to the /// end of the list. If the item already exists in the queue but the entity has not been changed then it leaves the /// original in the queue list. If the Entity doesn't exist in the queue then returns true so that it's added. /// </summary> /// <param name="indexOps"></param> /// <param name="op"></param> /// <returns> /// Returns true if the operation is a Delete operation. /// then Returns false if the Entity is null. /// then Returns false if the item was found in the queue list. /// then Returns false if the item was not found in the queue list but has not been changed (not IsDirty()) /// then Returns true if the item was not found in the queue list and either has been changed or does not implement ICanBeDirty. /// </returns> internal static bool ShouldAddNewQueueItem(this List<LinearHiveIndexOperation> indexOps, LinearHiveIndexOperation op) { //always add delete ops if (op.OperationType == IndexOperationType.Delete) return true; //if its not a Delete, the Entity should never be null if (op.Entity == null) return false; //if (op.IsRevision()) //{ // return true; //} //checks if the operation exists by reference or by id var existingOperation = indexOps.Where(x => op.OperationType == IndexOperationType.Add && (op.EntitiesAreEqual(x.Entity))).SingleOrDefault(); //the item already exists if (existingOperation != null) { var dirtyEntity = op.Entity as ICanBeDirty; //if the item has been updated then remove the original entry from the queue list so the new version can be //re-added . if (dirtyEntity != null && dirtyEntity.IsDirty()) { indexOps.Remove(existingOperation); return true; } //the item hasn't changed so leave the original return false; } return true; }
/// <summary> /// Detects if the Entity of the operation already exists in the queue list, if it does and it has been changed /// then this removes that operation from the queue list and returns true so that the newer version is added to the /// end of the list. If the item already exists in the queue but the entity has not been changed then it leaves the /// original in the queue list. If the Entity doesn't exist in the queue then returns true so that it's added. /// </summary> /// <param name="indexOps"></param> /// <param name="op"></param> /// <returns> /// Returns true if the operation is a Delete operation. /// then Returns false if the Entity is null. /// then Returns false if the item was found in the queue list. /// then Returns false if the item was not found in the queue list but has not been changed (not IsDirty()) /// then Returns true if the item was not found in the queue list and either has been changed or does not implement ICanBeDirty. /// </returns> internal static bool ShouldAddNewQueueItem(this List <LinearHiveIndexOperation> indexOps, LinearHiveIndexOperation op) { //always add delete ops if (op.OperationType == IndexOperationType.Delete) { return(true); } //if its not a Delete, the Entity should never be null if (op.Entity == null) { return(false); } //if (op.IsRevision()) //{ // return true; //} //checks if the operation exists by reference or by id var existingOperation = indexOps.Where(x => op.OperationType == IndexOperationType.Add && (op.EntitiesAreEqual(x.Entity))).SingleOrDefault(); //the item already exists if (existingOperation != null) { var dirtyEntity = op.Entity as ICanBeDirty; //if the item has been updated then remove the original entry from the queue list so the new version can be //re-added . if (dirtyEntity != null && dirtyEntity.IsDirty()) { indexOps.Remove(existingOperation); return(true); } //the item hasn't changed so leave the original return(false); } return(true); }
/// <summary> /// Checks if the operation is for a "Relation" /// </summary> /// <param name="op"></param> /// <returns></returns> internal static bool IsRelation(this LinearHiveIndexOperation op) { return(op.OperationType == IndexOperationType.Add && op.ItemCategory == "Relation"); }
/// <summary> /// Checks if the Entity assigned to the operation is a Revision{T} /// </summary> /// <param name="op"></param> /// <returns></returns> internal static bool IsRevision(this LinearHiveIndexOperation op) { return(op.OperationType == IndexOperationType.Add && op.Entity != null && op.Entity.GetType().IsOfGenericType(typeof(Revision <>))); }
/// <summary> /// Ensures all of the revision fields and data is stored in the index operation /// </summary> /// <param name="s"></param> /// <param name="t"></param> internal void EnsureRevisionDataForIndexOperation <TEntity>(Revision <TEntity> s, LinearHiveIndexOperation t) where TEntity : class, IVersionableEntity { //now we need to update the ids, NOTE: the __NodeId is a composite id! t.Id = new Lazy <string>(() => s.Item.Id.Value.ToString() + "," + s.MetaData.Id.Value.ToString()); t.AddOrUpdateField(FixedRevisionIndexFields.RevisionId, new Lazy <string>(() => s.MetaData.Id.Value.ToString())); //we also need to make sure the entity property is set to the Revision<TypedEntity> not just TypedEntity t.Entity = s; //ensure that the revision status type is stored in a document EnsureRevisionStatus(s.MetaData.StatusType); //add the revision status id t.AddOrUpdateField(FixedRevisionIndexFields.RevisionStatusId, s.MetaData.StatusType.Id.Value.ToString()); t.AddOrUpdateField(FixedRevisionIndexFields.RevisionStatusAlias, s.MetaData.StatusType.Alias); }
/// <summary> /// Performs the delete. /// </summary> /// <param name="id">The id.</param> /// <param name="transaction"></param> /// <remarks> /// This will lookup all all related entities and remove them from the index /// </remarks> public void PerformDelete(string id, ExamineTransaction transaction) { Mandate.ParameterNotNullOrEmpty(id, "id"); //NOTE: The below deletion process relies on having unique GUID ids across the board, // if you want to support int Ids, then we'll need to lookup the item type first // and delete different things based on that, i chose not to do that because // if for some reason the item with the Id that we're deleting isn't there then // any related instances will never be deleted whereas doing the below will delete all // related entities regardless. Action <IEnumerable <SearchResult> > addItemsToDeleteQueue = x => { foreach (var r in x) { var r1 = r; transaction.EnqueueIndexOperation(new LinearHiveIndexOperation { OperationType = IndexOperationType.Delete, Id = new Lazy <string>(() => r1.Id) }); } }; //First, check if there's relations for this id and remove any relations found var relations = ExamineManager.Search( ExamineManager.CreateSearchCriteria() .Should() .Id(id, FixedRelationIndexFields.SourceId) .Should() .Id(id, FixedRelationIndexFields.DestinationId).Compile()); addItemsToDeleteQueue(relations); //next, check if there's any items (TypedEntity, AttributeDefinition, AttributeGroup) assigned to a schema by this id, // this will also delete all revisions of TypedEntity too var entities = ExamineManager.Search( ExamineManager.CreateSearchCriteria() .Should() .Id(id, FixedIndexedFields.SchemaId) .Should() .Id(id, FixedIndexedFields.EntityId) .Compile()); addItemsToDeleteQueue(entities); //now, check if the item being deleted is an attribute type, if it is we need to remove all AttributeDefinitions associated // with it and then all TypedAttribute fields belonging to the TypedEntity that reference these AttributeDefinitions var attributeDefs = ExamineManager.Search( ExamineManager.CreateSearchCriteria() .Must() .Id(id, FixedIndexedFields.AttributeTypeId) .Must() .EntityType <AttributeDefinition>() .Compile()); addItemsToDeleteQueue(attributeDefs); //now that we have the attribute defintions related to the typed attribute being deleted, we need to actually create new revisions // for any entity that had a schemas with these definitions on them. var schemaIds = attributeDefs.Select(x => x.Fields[FixedIndexedFields.SchemaId]).Distinct(); foreach (var schemaId in schemaIds) { var criteria = ExamineManager.CreateSearchCriteria() .Must().EntityType <TypedEntity>() .Must().Id(schemaId, FixedIndexedFields.SchemaId) //need to lookup latest because when we're supporting revisions, we will have more than one version of a TypedEntity .Must().Range(FixedRevisionIndexFields.IsLatest, 1, 1); var latest = FilterLatestTypedEntities( ExamineManager.Search(criteria.Compile())); //now that we have the latest TypedEntity for any Schema that had an AttributeDefinition on it that we are deleting // because we are deleting it's TypedAttribute, we need to make a new revision of //NOTE: If for some reason Revisions are disabled, this wont work foreach (var l in latest) { //now that we have an entity, we'll loop through the attribute defs were removing an ensure it's fields are removed foreach (var d in attributeDefs) { //remove all attributes starting with the prefix and attribute def alias var d1 = d; l.Fields.RemoveAll(x => x.Key.StartsWith(FixedAttributeIndexFields.AttributePrefix + d1.Fields[FixedIndexedFields.Alias])); //conver the fields to be used in an index operation var opFields = l.Fields.ToLazyDictionary(x => new ItemField(x)); //update some manual fields like the dates and revision ids StoreDateTimeOffset(FixedIndexedFields.UtcModified, opFields, DateTimeOffset.UtcNow); var revId = Guid.NewGuid().ToString("N"); opFields.AddOrUpdate(FixedRevisionIndexFields.RevisionId, new Lazy <ItemField>(() => new ItemField(revId)), (key, o) => new Lazy <ItemField>(() => new ItemField(revId))); //need to generate a new id (which is composite) var l1 = l; var op = new LinearHiveIndexOperation { OperationType = IndexOperationType.Add, Id = new Lazy <string>(() => l1.Fields[FixedIndexedFields.EntityId] + "," + revId), Fields = opFields }; //create the new revision without the fields transaction.EnqueueIndexOperation(op); } } } //finally, lookup the item itself and remove it var item = ExamineManager.Search(ExamineManager.CreateSearchCriteria().Must().Id(id).Compile()); addItemsToDeleteQueue(item); }