Skip to content

Element is duplicated when Federation Guid is updated. #281

@JulijaRamoskiene

Description

@JulijaRamoskiene

Describe the bug

iModel transformer is not handling Federation Guid update.
Federation Guid is used to map elements between source and target iModels. When Federation Guid is updated and process change is executed, transformer:

  1. Leaves element with old Federation Guid in target
  2. Adds new element with new Federation Guid

To Reproduce

    it.only("should handle federation guid update", async () => {
      // Arrange
      const sourceSubjectId = Subject.insert(
        sourceDb,
        IModel.rootSubjectId,
        "S1"
      );
      // Create physical model
      const physicalModel1Id = PhysicalModel.insert(
        sourceDb,
        sourceSubjectId,
        "PM1"
      );
      const categoryId1 = SpatialCategory.insert(
        sourceDb,
        IModel.dictionaryId,
        "C1",
        {}
      );
      // Create element with null code value to make sure that code value is not used to map elements between source and target
      const oldGuid = Guid.createValue();
      const code = new Code({ scope: "0x1", spec: "0x1", value: undefined });
      const element: PhysicalElementProps = {
        classFullName: PhysicalObject.classFullName,
        model: physicalModel1Id,
        category: categoryId1,
        code,
        userLabel: "PhysicalElement1",
        federationGuid: oldGuid,
      };

      var physicalElemId= sourceDb.elements.insertElement(element);
      await pushChanges(sourceDb, "Initial changes");

      // === Transformation 1: Run `process all` transformation ===
      let transformer = new IModelTransformer(sourceDb, targetDb);
      await transformer.process();
      transformer.updateSynchronizationVersion({
        initializeReverseSyncVersion: true,
      });
      await pushChanges(targetDb, "Transformation 1: Process All");

      // Assert
      expect(
        IModelTestUtils.count(targetDb, PhysicalElement.classFullName)
      ).to.be.equal(1);
      targetDb.elements.getElement(oldGuid); // throws if element not found


      // === Transformation 2: `process changes` transformation to insert excluded parent model ===

      // Update physical element's federation guid in source
      const updatedElementProps = sourceDb.elements.getElementProps(physicalElemId);
      const newGuid = Guid.createValue();
      updatedElementProps.federationGuid = newGuid;
      sourceDb.elements.updateElement(updatedElementProps);
      await pushChanges(sourceDb, "Updated federation guid");

      transformer = new IModelTransformer(sourceDb, targetDb, {argsForProcessChanges: {}});
      await transformer.process();
      await pushChanges(
        targetDb,
        "Transformation 2: inserted previously excluded model"
      );
      // Assert
      expect(
        IModelTestUtils.count(targetDb, PhysicalElement.classFullName)
      ).to.be.equal(1);
      expect(targetDb.elements.getElement(newGuid)).to.not.be.undefined; // throws if element not found
      expect(targetDb.elements.tryGetElement(oldGuid)).to.be.undefined;
    });

Expected behavior
Target should have only one element with new Federation Guid. Element with old Federation Guid should not exist.

Additional context

This issue was discovered while investigating https://github.com/iTwin/itwinjs-backlog/issues/1762
PR: #279

In the issue, element that re-used Instance ID was marked as updated. Which showed up as update of all properties such as class and Federation Guid.
Not sure if there are any other use - cases where it would make sense to update Federation Guid, but since it is supported by iTwinjs API, transformer should also handle it without corrupting target iModel (duplicating elements).

Versions used:

  • @itwin/imodel-transformer 1.2.1-dev.1
  • iTwin.js Version 4.11.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions