public void CloneWithOneToOneRelationship()
        {
            var x = DateTime.Now.ToUniversalTime().ToString("yyyyMMddHHmmss");

            #region Arrange

            var colour = new Definition();
            colour.Name = "Colour_" + x;
            colour.Save();
            var objectA = new Definition();
            objectA.Name = "ObjectA_" + x;
            objectA.Save();
            var objectB = new Definition();
            objectB.Name = "ObjectB_" + x;
            objectB.Inherits.Add(objectA.As <EntityType>());
            objectB.Save();

            var relationship = new Relationship();
            relationship.Name                    = "Object To Colour " + x;
            relationship.FromType                = objectA.As <EntityType>();
            relationship.ToType                  = colour.As <EntityType>();
            relationship.Cardinality_Enum        = CardinalityEnum_Enumeration.OneToOne;
            relationship.CloneAction_Enum        = CloneActionEnum_Enumeration.CloneEntities;
            relationship.ReverseCloneAction_Enum = CloneActionEnum_Enumeration.CloneEntities;
            relationship.Save();

            var red = Entity.Create(colour.Id);
            red.Save();
            red.SetField(new EntityRef("core", "name"), "Red." + red.Id);
            red.Save();
            var blue = Entity.Create(colour.Id);
            blue.Save();
            blue.SetField(new EntityRef("core", "name"), "Blue." + blue.Id);
            blue.Save();
            var green = Entity.Create(colour.Id);
            green.Save();
            green.SetField(new EntityRef("core", "name"), "Green." + green.Id);
            green.Save();

            var colours = new EntityRelationshipCollection <IEntity>();
            colours.Add(blue);

            var instanceA = Entity.Create(objectA.Id);
            instanceA.Save();
            instanceA.SetField(new EntityRef("core", "name"), "A." + instanceA.Id);
            instanceA.SetRelationships(relationship, colours);
            instanceA.Save();

            // Workflow Setup
            var cloneActivity = new CloneActivity();
            cloneActivity.Save();

            var nextActivity = (CloneImplementation)cloneActivity.As <WfActivity>().CreateWindowsActivity();
            var inputs       = new Dictionary <string, object>
            {
                { "Record", instanceA },
                { "Object", objectB } // core:newDefinitionCloneArgument
            };

            ToDelete.Add(cloneActivity.Id);
            ToDelete.Add(instanceA.Id);
            ToDelete.Add(red.Id);
            ToDelete.Add(blue.Id);
            ToDelete.Add(green.Id);
            ToDelete.Add(relationship.Id);
            ToDelete.Add(objectB.Id);
            ToDelete.Add(objectA.Id);
            ToDelete.Add(colour.Id);

            #endregion

            var result         = RunActivity(nextActivity, inputs);
            var clone          = ((IEntity)result["Record"]);
            var original       = Entity.Get(instanceA.Id);
            var originalColour = Entity.Get(blue.Id);

            clone.Id.Should().NotBe(original.Id);

            ToDelete.Add(clone.Id);

            clone.GetField(new EntityRef("core", "name")).Should().Be("A." + instanceA.Id);

            var related = clone.GetRelationships(relationship);
            related.Should().NotBeNull().And.NotBeEmpty();
            related.Count.Should().Be(1);

            var cloneColour = related.First();

            cloneColour.Id.Should().NotBe(originalColour.Id);

            ToDelete.Add(cloneColour.Id);

            cloneColour.GetField(new EntityRef("core", "name")).Should().Be("Blue." + blue.Id);
        }
Exemple #2
0
        /// <summary>
        /// Given a update ac
        /// </summary>
        /// <param name="activityAs"></param>
        /// <param name="inputs"></param>
        /// <param name="entityToUpdate"></param>
        public static void UpdateEntityFromArgs(EntityWithArgsAndExits activityAs, ActivityInputs inputs, IEntity entityToUpdate)
        {
            // This activity may also have its own input arguments (as opposed to those on its type)
            // and these are grouped so we can update multiple fields, relationships etc.


            // find the list of base names (indexes) of the argument groups
            Entity.GetField(activityAs.InputArguments, new EntityRef("core:name"));

            IOrderedEnumerable <int> argGroups = GetInputArgumentGroups(activityAs);

            // process each group

            foreach (var baseName in argGroups.Select(g => g.ToString()))
            {
                var arg = activityAs.InputArguments.FirstOrDefault(p => p.Name == baseName);

                if (arg == null)
                {
                    Log("Failed to find input argument for activity {0} with name {1}", activityAs.Name, baseName);
                    continue;
                }

                if (!inputs.ContainsKey(arg))
                {
                    Log("Failed to input argument expression for activity {0} with name {1}", activityAs.Name, baseName);
                    continue;
                }

                var memberEntity = (IEntity)inputs[arg];

                if (memberEntity != null)
                {
                    var fieldEntity = memberEntity.Is <Field>() ? memberEntity.Cast <Field>() : null;
                    var relEntity   = memberEntity.Is <Relationship>() ? memberEntity.Cast <Relationship>() : null;

                    if (fieldEntity != null)
                    {
                        var valueArg = activityAs.InputArguments.FirstOrDefault(p => p.Name == baseName + "_value");
                        if (valueArg == null || !inputs.ContainsKey(valueArg))
                        {
                            Log("Failed to find input argument for activity {0} with name {1}", activityAs.Name,
                                baseName + "_value");
                        }
                        else
                        {
                            //Log("Updating field {0} {1} with value {2}", fieldEntity.Id, fieldEntity.Name,
                            //    inputs[valueArg]);

                            entityToUpdate.SetField(fieldEntity, inputs[valueArg]);
                        }
                    }
                    else if (relEntity != null)
                    {
                        var reverseArg = activityAs.InputArguments.FirstOrDefault(p => p.Name == baseName + "_reverse");
                        var replaceArg = activityAs.InputArguments.FirstOrDefault(p => p.Name == baseName + "_replace");

                        var cardinality = relEntity.Cardinality_Enum ?? CardinalityEnum_Enumeration.ManyToMany;

                        var direction = reverseArg != null && inputs.ContainsKey(reverseArg)
                                            ? (((bool?)inputs[reverseArg] ?? false)
                                                   ? Direction.Reverse
                                                   : Direction.Forward)
                                            : Direction.Forward;
                        var replaceExisting = (replaceArg != null && inputs.ContainsKey(replaceArg) &&
                                               ((bool?)inputs[replaceArg] ?? false)) ||
                                              cardinality == CardinalityEnum_Enumeration.OneToOne
                                              ||
                                              (direction == Direction.Forward &&
                                               cardinality == CardinalityEnum_Enumeration.ManyToOne)
                                              ||
                                              (direction == Direction.Reverse &&
                                               cardinality == CardinalityEnum_Enumeration.OneToMany);

                        //Log("Updating relationship {0} {1} direction={2} replace={3}", relEntity.Id, relEntity.Name,
                        //    direction,
                        //    replaceExisting);

                        var oldRelCollection = entityToUpdate.GetRelationships(relEntity, direction);

                        //Log("Before: relationship {0} {1} has {2} related entities", relEntity.Id, relEntity.Name,
                        //    relCollection.Count());

                        var relCollection = new EntityRelationshipCollection <IEntity>();    // We need to create a new collection and set the relationship to it to deal with a bug that occurs when a resource is cloned and then modified with a relationship set to the same value.


                        if (!replaceExisting)
                        {
                            foreach (var e in oldRelCollection)
                            {
                                relCollection.Add(e);
                            }
                        }

                        foreach (
                            var valueArg in
                            activityAs.InputArguments.Where(p => p.Name.StartsWith(baseName + "_value_")))
                        {
                            var value = inputs.ContainsKey(valueArg) ? inputs[valueArg] : null;

                            IEnumerable <IEntity> entityRefs;

                            if (value is IEntity)
                            {
                                entityRefs = new List <IEntity> {
                                    (IEntity)value
                                };
                            }
                            else
                            {
                                entityRefs = (IEnumerable <IEntity>)value;
                            }

                            if (entityRefs != null)
                            {
                                foreach (var entity in entityRefs)
                                {
                                    if (entity != null)
                                    {
                                        var relatedEntity = entity.As <Resource>();

                                        if (relatedEntity != null)
                                        {
                                            //Log(">> adding to relationship {0} {1}, related {2} {3}", relEntity.Id,
                                            //    relEntity.Name,
                                            //    relatedEntity.Id, relatedEntity.Name);

                                            relCollection.Add(relatedEntity);
                                        }
                                    }
                                }
                            }
                        }

                        entityToUpdate.SetRelationships(relEntity, relCollection, direction);

                        //Log("After: relationship {0} {1} has {2} related entities", relEntity.Id, relEntity.Name,
                        //    relCollection.Count());
                    }
                }
            }
        }
        public void CloneRefsWithBaseDefinition()
        {
            var x = DateTime.Now.ToUniversalTime().ToString("yyyyMMddHHmmss");

            #region Arrange

            // Types
            var userResource     = Entity.Get <EntityType>(new EntityRef("core", "userResource"));
            var myBaseDefinition = new Definition {
                Name = "clonebasedefinition" + x, Inherits = new EntityCollection <EntityType>(userResource.ToEnumerable())
            };
            myBaseDefinition.Save();

            var myRelatedDefinition = new Definition {
                Name = "clonerelateddefinition" + x, Inherits = new EntityCollection <EntityType>(userResource.ToEnumerable())
            };
            myRelatedDefinition.Save();

            var myBaseType    = Entity.Get <EntityType>(myBaseDefinition);
            var myRelatedType = Entity.Get <EntityType>(myRelatedDefinition);
            var myBaseToRelatedRelationship = new Relationship
            {
                FromType                = myBaseType,
                ToType                  = myRelatedType,
                Name                    = "clonebaserelationship" + x,
                Description             = "Clone With Base Definition",
                Cardinality             = Entity.Get <CardinalityEnum>(new EntityRef("core", "manyToMany")),
                CascadeDelete           = false,
                CascadeDeleteTo         = false,
                CloneAction_Enum        = CloneActionEnum_Enumeration.CloneReferences,
                ReverseCloneAction_Enum = CloneActionEnum_Enumeration.CloneReferences
            };
            myBaseToRelatedRelationship.Save();

            var myDefinitionA = new Definition {
                Name = "clonedefinitionA" + x, Inherits = new EntityCollection <EntityType>(myBaseType.ToEnumerable())
            };
            myDefinitionA.Save();

            var myDefinitionB = new Definition {
                Name = "clonedefinitionB" + x, Inherits = new EntityCollection <EntityType>(myBaseType.ToEnumerable())
            };
            myDefinitionB.Save();

            // Instances
            var rOne = new Entity(myRelatedDefinition);
            rOne.SetField(new EntityRef("core", "name"), "Related 1." + x);
            rOne.Save();

            var rTwo = new Entity(myRelatedDefinition);
            rTwo.SetField(new EntityRef("core", "name"), "Related 2." + x);
            rTwo.Save();

            var rCollection = new EntityRelationshipCollection <IEntity>();
            rCollection.Add(rOne);
            rCollection.Add(rTwo);

            var cA = new Entity(myDefinitionA);
            cA.SetField(new EntityRef("core", "name"), "Clone Me A." + x);
            cA.SetRelationships(myBaseToRelatedRelationship, rCollection);
            cA.Save();

            // Workflow Setup
            var cloneActivity = new CloneActivity();
            cloneActivity.Save();

            var nextActivity = (CloneImplementation)cloneActivity.As <WfActivity>().CreateWindowsActivity();
            var inputs       = new Dictionary <string, object>
            {
                { "Record", cA },
                { "Object", myDefinitionB } // core:newDefinitionCloneArgument
            };

            ToDelete.Add(cloneActivity.Id);
            ToDelete.Add(cA.Id);
            ToDelete.Add(myDefinitionA.Id);
            ToDelete.Add(myDefinitionB.Id);
            ToDelete.Add(myRelatedDefinition.Id);
            ToDelete.Add(myBaseDefinition.Id);

            #endregion

            var result   = RunActivity(nextActivity, inputs);
            var clone    = ((IEntity)result["Record"]);
            var original = Entity.Get(cA.Id);

            clone.Id.Should().NotBe(original.Id);

            ToDelete.Add(clone.Id);

            var rid = myBaseToRelatedRelationship.Id;

            var cloneRels = clone.GetRelationships(rid, Direction.Forward).ToList();
            cloneRels.Count.Should().Be(2);
            foreach (var cloneRel in cloneRels)
            {
                var revs = cloneRel.GetRelationships(rid, Direction.Reverse);
                revs.Select(r => r.Id).Should().Contain(new [] { original.Id, clone.Id });
            }

            var originalRels = original.GetRelationships(rid, Direction.Forward).ToList();

            originalRels.Count.Should().Be(2);
            originalRels.Select(o => o.Id).Should().BeEquivalentTo(cloneRels.Select(c => c.Id));
        }