@itwin/imodel-transformer 1.0.0 → 1.0.1-customchanges.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Change Log - @itwin/imodel-transformer
2
2
 
3
- <!-- This log was last generated on Mon, 04 Nov 2024 14:45:39 GMT and should not be manually modified. -->
3
+ <!-- This log was last generated on Mon, 04 Nov 2024 14:45:46 GMT and should not be manually modified. -->
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
7
  ## 1.0.0
8
8
 
9
- Mon, 04 Nov 2024 14:45:39 GMT
9
+ Mon, 04 Nov 2024 14:45:46 GMT
10
10
 
11
11
  ### Patches
12
12
 
@@ -7,7 +7,7 @@ import { EntityReference } from "@itwin/core-common";
7
7
  import { ConcreteEntity, ConcreteEntityProps, IModelDb } from "@itwin/core-backend";
8
8
  /** @internal */
9
9
  export declare namespace EntityUnifier {
10
- export function getReadableType(entity: ConcreteEntity): "element" | "element aspect" | "relationship" | "unknown entity type";
10
+ export function getReadableType(entity: ConcreteEntity): "element" | "relationship" | "element aspect" | "unknown entity type";
11
11
  type EntityUpdater = (entityProps: ConcreteEntityProps) => void;
12
12
  /** needs to return a widened type otherwise typescript complains when result is used with a narrow type */
13
13
  export function updaterFor(db: IModelDb, entity: ConcreteEntity): EntityUpdater;
@@ -1,7 +1,7 @@
1
1
  /** @packageDocumentation
2
2
  * @module iModels
3
3
  */
4
- import { BriefcaseDb, ChangedECInstance, Element, ElementAspect, ElementMultiAspect, ElementUniqueAspect, IModelDb, IModelJsNative, Model, Relationship } from "@itwin/core-backend";
4
+ import { BriefcaseDb, ChangedECInstance, Element, ElementAspect, ElementMultiAspect, ElementUniqueAspect, IModelDb, IModelJsNative, Model, Relationship, SqliteChangeOp } from "@itwin/core-backend";
5
5
  import { Id64String } from "@itwin/core-bentley";
6
6
  import { ChangesetFileProps, CodeSpec, FontProps } from "@itwin/core-common";
7
7
  import { Schema, SchemaKey } from "@itwin/ecschema-metadata";
@@ -198,7 +198,7 @@ export declare class IModelExporter {
198
198
  private _sourceDbChanges?;
199
199
  /**
200
200
  * Retrieve the cached entity change information.
201
- * @note This will only be initialized after [IModelExporter.exportChanges] is invoked.
201
+ * @note This will only be initialized after [IModelExporter.exportChanges] is invoked or [IModelExporter.initialize] is called.
202
202
  */
203
203
  get sourceDbChanges(): ChangedInstanceIds | undefined;
204
204
  /** The handler called by this IModelExporter. */
@@ -230,6 +230,16 @@ export declare class IModelExporter {
230
230
  * you pass to [[IModelExporter.exportChanges]]
231
231
  */
232
232
  initialize(options: ExporterInitOptions): Promise<void>;
233
+ /**
234
+ * This function is called by the transformer as it is about to process the changesets passed to it in [[IModelTransformOptions.argsForProcessChanges]].
235
+ * This would be after the exporter has already processed the same set of changesets passed to the transformer in [[IModelTransformOptions.argsForProcessChanges]].
236
+ * This function should be used to modify the exporter's sourceDbChanges, if necessary, using [[ChangedInstanceIds.addCustomChange]]. See [[ChangedInstanceIds.addCustomChange]] for more information.
237
+ * @note [[IModelExporter.sourceDbChanges]] will only be defined if the transformer was called with [[IModelTransformOptions.argsForProcessChanges]].
238
+ * @note If defined, sourceDbChanges will already be populated with the changesets passed to the transformer, if any when this function is called by the transformer.
239
+ * @note The transformer will have built up the remap table between the source and target iModels before calling this function. This means that functions like [[IModelTransformer.context.findTargetElementId]] will return meaningful results.
240
+ * @note Its expected that this function be overridden by a subclass of exporter if it needs to modify sourceDbChanges.
241
+ */
242
+ addCustomChanges(): void;
233
243
  /** Register the handler that will be called by IModelExporter. */
234
244
  registerHandler(handler: IModelExportHandler): void;
235
245
  /** Add a rule to exclude a CodeSpec */
@@ -346,6 +356,18 @@ export declare class ChangedInstanceOps {
346
356
  deleteIds: Set<string>;
347
357
  /** Initializes the object from IModelJsNative.ChangedInstanceOpsProps. */
348
358
  addFromJson(val: IModelJsNative.ChangedInstanceOpsProps | undefined): void;
359
+ get isEmpty(): boolean;
360
+ }
361
+ export type ChangedInstanceType = "codeSpec" | "model" | "element" | "aspect" | "relationship" | "font";
362
+ /**
363
+ * Interface to describe a 'custom' change. A custom change is one which isn't found by reading changesets, but instead added by a user calling the 'addCustomChange' API on the ChangedInstanceIds instance.
364
+ * The purpose a custom change would serve is to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
365
+ */
366
+ export interface ChangedInstanceCustomRelationshipData {
367
+ sourceIdOfRelationship: Id64String;
368
+ targetIdOfRelationship: Id64String;
369
+ ecClassId: Id64String;
370
+ classFullName: string;
349
371
  }
350
372
  /**
351
373
  * Class for discovering modified elements between 2 versions of an iModel.
@@ -363,6 +385,11 @@ export declare class ChangedInstanceIds {
363
385
  private _elementSubclassIds?;
364
386
  private _aspectSubclassIds?;
365
387
  private _relationshipSubclassIds?;
388
+ private _relationshipSubclassIdsToSkip?;
389
+ private _ecClassIdsToClassFullNames?;
390
+ /** c${string} is used to represent codeSpecs since they do not currently have a representation in the EntityReference class. This map holds information passed to the 'addCustom' functions. */
391
+ private _entityReferenceToCustomDataMap;
392
+ private _hasCustomChanges;
366
393
  private _db;
367
394
  constructor(db: IModelDb);
368
395
  private setupECClassIds;
@@ -372,6 +399,8 @@ export declare class ChangedInstanceIds {
372
399
  private isAspect;
373
400
  private isModel;
374
401
  private isElement;
402
+ get hasCustomChanges(): boolean;
403
+ get isEmpty(): boolean;
375
404
  /**
376
405
  * Adds the provided [[ChangedECInstance]] to the appropriate set of changes by class type (codeSpec, model, element, aspect, or relationship) maintained by this instance of ChangedInstanceIds.
377
406
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
@@ -379,6 +408,66 @@ export declare class ChangedInstanceIds {
379
408
  * @param change ChangedECInstance which has the ECInstanceId, changeType (insert, update, delete) and ECClassId of the changed entity
380
409
  */
381
410
  addChange(change: ChangedECInstance): Promise<void>;
411
+ /**
412
+ * Adds the provided change to the element changes maintained by this instance of ChangedInstanceIds
413
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
414
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
415
+ * @note element changes will also cause the element's model to be marked as updated in [[ChangedInstanceIds.model]], so that the element does not get skipped by the transformer.
416
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact an element.
417
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
418
+ */
419
+ addCustomElementChange(changeType: SqliteChangeOp, id: Id64String): void;
420
+ /**
421
+ * Adds the provided change to the codespec changes maintained by this instance of ChangedInstanceIds
422
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
423
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
424
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact a codespec.
425
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
426
+ */
427
+ addCustomCodeSpecChange(changeType: SqliteChangeOp, id: Id64String): void;
428
+ /**
429
+ * Adds the provided change to the model changes maintained by this instance of ChangedInstanceIds
430
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
431
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
432
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact a model.
433
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
434
+ */
435
+ addCustomModelChange(changeType: SqliteChangeOp, id: Id64String): void;
436
+ /**
437
+ * Adds the provided change to the aspect changes maintained by this instance of ChangedInstanceIds
438
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
439
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
440
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact an aspect.
441
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
442
+ */
443
+ addCustomAspectChange(changeType: SqliteChangeOp, id: Id64String): void;
444
+ /**
445
+ * TODO: Think more about permutations of model updated / inserted / deleted. Can you delete a model without deleting its elements?
446
+ * What if model delete but custom change si to insert element into target?
447
+ * // It is possible and apparently occasionally sensical to delete a model without deleting its underlying element.
448
+ // - If only the model is deleted, [[initFromExternalSourceAspects]] will have already remapped the underlying element since it still exists.
449
+ // - If both were deleted, [[remapDeletedSourceEntities]] will find and remap the deleted element making this operation valid
450
+ * TODO: If the element is a custom delete we probably shouldnt be calling this?
451
+ * There is an optimization in [IModelExporter.exportModelContents] which doesn't try to export elements within a model unless the model itself is part of
452
+ * the sourceDbChanges. This method is used in addCustomChange to add the model to the updatedIds set so that the custom element changes are exported.
453
+ */
454
+ private addModelToUpdated;
455
+ /** TODO: Maybe relationships only? maybe not. */
456
+ getCustomRelationshipDataFromId(id: Id64String, type: ChangedInstanceType): ChangedInstanceCustomRelationshipData | undefined;
457
+ /**
458
+ * Adds the provided change to the set of relationship changes maintained by this instance of ChangedInstanceIds.
459
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
460
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
461
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
462
+ * @throws if the ecClassId is NOT a relationship classId
463
+ * @param ecClassId class id of the custom change
464
+ * @param changeType insert, update or delete
465
+ * @param id ECInstanceID of the custom change
466
+ * @param sourceECInstanceId source ECInstanceId of the relationship
467
+ * @param targetECInstanceId target ECInstanceId of the relationship
468
+ */
469
+ addCustomRelationshipChange(ecClassId: string, changeType: SqliteChangeOp, id: Id64String, sourceECInstanceId: Id64String, targetECInstanceId: Id64String): Promise<void>;
470
+ private getClassFullNameFromECClassId;
382
471
  private handleChange;
383
472
  /**
384
473
  * Initializes a new ChangedInstanceIds object with information taken from a range of changesets.
@@ -1 +1 @@
1
- {"version":3,"file":"IModelExporter.d.ts","sourceRoot":"","sources":["../../src/IModelExporter.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EACL,WAAW,EAEX,iBAAiB,EAKjB,OAAO,EACP,aAAa,EACb,kBAAkB,EAElB,mBAAmB,EAEnB,QAAQ,EAER,cAAc,EACd,KAAK,EAGL,YAAY,EAGb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,UAAU,EAIX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,QAAQ,EACR,SAAS,EAGV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,MAAM,EACN,SAAS,EAEV,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,qBAAqB,EACrB,4BAA4B,EAC7B,MAAM,gCAAgC,CAAC;AAKxC;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AAEvD;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,kCAAkC,CAAC,EAAE,OAAO,CAAC;CAC9C,CAAC;;;GAGC,GAAG,CACF;IAAE,WAAW,EAAE,kBAAkB,EAAE,CAAA;CAAE;AACvC;;;;;GAKG;GACD;IAAE,kBAAkB,EAAE,kBAAkB,CAAA;CAAE;AAC5C;;;GAGG;GACD;IAAE,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;CAAE;AACzC;;;;;GAKG;GACD;IAAE,cAAc,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACnD,EAAE,CACL,CAAC;AAEF;;;;;GAKG;AACH,8BAAsB,mBAAmB;IACvC;;OAEG;IACI,oBAAoB,CAAC,SAAS,EAAE,QAAQ,GAAG,OAAO;IAIzD;;;;OAIG;IACI,gBAAgB,CACrB,SAAS,EAAE,QAAQ,EACnB,SAAS,EAAE,OAAO,GAAG,SAAS,GAC7B,IAAI;IAEP;;;;OAIG;IACI,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAE3E;;;;OAIG;IACI,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAEzE,6CAA6C;IACtC,aAAa,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI;IAEhD;;OAEG;IACI,mBAAmB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;IAItD;;OAEG;IACI,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAElD;;;;OAIG;IACI,eAAe,CACpB,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,OAAO,GAAG,SAAS,GAC7B,IAAI;IAEP;;;;;OAKG;IACU,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/D,gDAAgD;IACzC,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAEpD;;OAEG;IACI,yBAAyB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO;IAIjE;;;;OAIG;IACI,2BAA2B,CAChC,OAAO,EAAE,mBAAmB,EAC5B,SAAS,EAAE,OAAO,GAAG,SAAS,GAC7B,IAAI;IAEP;;OAEG;IACI,2BAA2B,CAAC,QAAQ,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAExE;;OAEG;IACI,wBAAwB,CAAC,aAAa,EAAE,YAAY,GAAG,OAAO;IAIrE;;;;OAIG;IACI,oBAAoB,CACzB,aAAa,EAAE,YAAY,EAC3B,SAAS,EAAE,OAAO,GAAG,SAAS,GAC7B,IAAI;IAEP,oDAAoD;IAC7C,oBAAoB,CAAC,cAAc,EAAE,UAAU,GAAG,IAAI;IAE7D;;OAEG;IACI,kBAAkB,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO;IAIzD;;;;;OAKG;IACU,cAAc,CACzB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,GAAG,kBAAkB,CAAC;IAErC;;;OAGG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CACzC;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,mCAAmC;IACnC,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IACnC;;;;;OAKG;IACI,YAAY,EAAE,OAAO,CAAQ;IACpC;;;OAGG;IACI,kBAAkB,EAAE,OAAO,CAAQ;IAC1C;;;OAGG;IACI,iBAAiB,EAAE,OAAO,CAAQ;IACzC;;OAEG;IACI,aAAa,EAAE,OAAO,CAAQ;IACrC;;OAEG;IACI,kBAAkB,EAAE,OAAO,CAAQ;IAC1C,sHAAsH;IAC/G,gBAAgB,EAAE,MAAM,CAAQ;IACvC,4DAA4D;IAC5D,OAAO,CAAC,gBAAgB,CAAa;IACrC,kDAAkD;IAClD,OAAO,CAAC,gBAAgB,CAAC,CAAqB;IAC9C;;;OAGG;IACH,IAAW,eAAe,IAAI,kBAAkB,GAAG,SAAS,CAE3D;IACD,iDAAiD;IACjD,OAAO,CAAC,QAAQ,CAAkC;IAClD,iDAAiD;IACjD,SAAS,KAAK,OAAO,IAAI,mBAAmB,CAM3C;IAED,uDAAuD;IACvD,OAAO,CAAC,sBAAsB,CAAqB;IACnD,+DAA+D;IAC/D,OAAO,CAAC,mBAAmB,CAAyB;IACpD,uHAAuH;IACvH,OAAO,CAAC,2BAA2B,CAAyB;IAC5D,uHAAuH;IACvH,OAAO,CAAC,uBAAuB,CAA6B;IAC5D,4HAA4H;IAC5H,OAAO,CAAC,4BAA4B,CAAkC;IAEtE,mDAAmD;IACnD,OAAO,CAAC,6BAA6B,CAA+B;IAEpE;;;OAGG;gBAED,QAAQ,EAAE,QAAQ,EAClB,sBAAsB,GAAE,KACtB,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,qBAAqB,KAC3B,4BAAuE;IAiB9E;;;;;;OAMG;IACU,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpE,kEAAkE;IAC3D,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAI1D,uCAAuC;IAChC,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAIlD,gDAAgD;IACzC,cAAc,CAAC,SAAS,EAAE,UAAU,GAAG,IAAI;IAIlD,kEAAkE;IAC3D,yBAAyB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAI9D,+DAA+D;IACxD,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAMvD,qEAAqE;IAC9D,yBAAyB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAI7D,oEAAoE;IAC7D,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAM5D;;OAEG;IACU,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IASvC;;;;;;OAMG;IACU,aAAa,CAAC,IAAI,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2EtE,OAAO,CAAC,wBAAwB,CAAQ;IAExC;;OAEG;IACU,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IA8C3C,sDAAsD;IACtD,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACU,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAc7C;;OAEG;IACU,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BtE;;OAEG;IACU,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtE;;OAEG;IACU,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAOzC;;OAEG;IACU,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9D;;OAEG;IACU,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBlE;;OAEG;IACU,WAAW,CAAC,gBAAgB,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBrE,oEAAoE;YACtD,oBAAoB;IAgBlC,OAAO,CAAC,aAAa,CAAsB;IAE3C;;;;;OAKG;IACU,mBAAmB,CAC9B,OAAO,EAAE,UAAU,EACnB,oBAAoB,GAAE,MAA8B,EACpD,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAAC,IAAI,CAAC;IA4ChB;;OAEG;IACU,eAAe,CAAC,aAAa,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BtE;;;OAGG;IACI,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAqCrD;;OAEG;IACU,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDhE;;OAEG;IACU,mBAAmB,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBtE;OACG;YACW,gBAAgB;IAI9B;;OAEG;IACU,mBAAmB,CAC9B,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC,IAAI,CAAC;IA+BhB,oDAAoD;IACvC,kBAAkB,CAC7B,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,UAAU,GACxB,OAAO,CAAC,IAAI,CAAC;IA8ChB,kCAAkC;YACpB,aAAa;CAM5B;AAED;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,oBAAoB,GAAG;IACjE,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,qBAAa,kBAAkB;IACtB,SAAS,cAAyB;IAClC,SAAS,cAAyB;IAClC,SAAS,cAAyB;IAEzC,0EAA0E;IACnE,WAAW,CAChB,GAAG,EAAE,cAAc,CAAC,uBAAuB,GAAG,SAAS,GACtD,IAAI;CAYR;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IACtB,QAAQ,qBAA4B;IACpC,KAAK,qBAA4B;IACjC,OAAO,qBAA4B;IACnC,MAAM,qBAA4B;IAClC,YAAY,qBAA4B;IACxC,IAAI,qBAA4B;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAc;IAC3C,OAAO,CAAC,iBAAiB,CAAC,CAAc;IACxC,OAAO,CAAC,mBAAmB,CAAC,CAAc;IAC1C,OAAO,CAAC,kBAAkB,CAAC,CAAc;IACzC,OAAO,CAAC,wBAAwB,CAAC,CAAc;IAC/C,OAAO,CAAC,GAAG,CAAW;gBACH,EAAE,EAAE,QAAQ;YAIjB,eAAe;IAkC7B,OAAO,KAAK,sBAAsB,GAQjC;IAED,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,SAAS;IAIjB;;;;;OAKG;IACU,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBhE,OAAO,CAAC,YAAY;IAyBpB;;;OAGG;WACiB,UAAU,CAC5B,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;CAoF3C"}
1
+ {"version":3,"file":"IModelExporter.d.ts","sourceRoot":"","sources":["../../src/IModelExporter.ts"],"names":[],"mappings":"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"}
@@ -132,7 +132,7 @@ exports.IModelExportHandler = IModelExportHandler;
132
132
  class IModelExporter {
133
133
  /**
134
134
  * Retrieve the cached entity change information.
135
- * @note This will only be initialized after [IModelExporter.exportChanges] is invoked.
135
+ * @note This will only be initialized after [IModelExporter.exportChanges] is invoked or [IModelExporter.initialize] is called.
136
136
  */
137
137
  get sourceDbChanges() {
138
138
  return this._sourceDbChanges;
@@ -216,6 +216,16 @@ class IModelExporter {
216
216
  return;
217
217
  this._exportElementAspectsStrategy.setAspectChanges(this._sourceDbChanges.aspect);
218
218
  }
219
+ /**
220
+ * This function is called by the transformer as it is about to process the changesets passed to it in [[IModelTransformOptions.argsForProcessChanges]].
221
+ * This would be after the exporter has already processed the same set of changesets passed to the transformer in [[IModelTransformOptions.argsForProcessChanges]].
222
+ * This function should be used to modify the exporter's sourceDbChanges, if necessary, using [[ChangedInstanceIds.addCustomChange]]. See [[ChangedInstanceIds.addCustomChange]] for more information.
223
+ * @note [[IModelExporter.sourceDbChanges]] will only be defined if the transformer was called with [[IModelTransformOptions.argsForProcessChanges]].
224
+ * @note If defined, sourceDbChanges will already be populated with the changesets passed to the transformer, if any when this function is called by the transformer.
225
+ * @note The transformer will have built up the remap table between the source and target iModels before calling this function. This means that functions like [[IModelTransformer.context.findTargetElementId]] will return meaningful results.
226
+ * @note Its expected that this function be overridden by a subclass of exporter if it needs to modify sourceDbChanges.
227
+ */
228
+ addCustomChanges() { }
219
229
  /** Register the handler that will be called by IModelExporter. */
220
230
  registerHandler(handler) {
221
231
  this._handler = handler;
@@ -268,7 +278,8 @@ class IModelExporter {
268
278
  await this.exportAll(); // no changesets, so revert to exportAll
269
279
  return;
270
280
  }
271
- const startChangeset = args && "startChangeset" in args ? args.startChangeset : undefined;
281
+ const startChangeset = // TODO: This is weird.. why is this needed? I suspect we can remove this and just pass args to initialize?
282
+ args && "startChangeset" in args ? args.startChangeset : undefined;
272
283
  const initOpts = {
273
284
  startChangeset: { id: startChangeset?.id },
274
285
  };
@@ -384,7 +395,7 @@ class IModelExporter {
384
395
  async exportCodeSpecByName(codeSpecName) {
385
396
  const codeSpec = this.sourceDb.codeSpecs.getByName(codeSpecName);
386
397
  let isUpdate;
387
- if (undefined !== this._sourceDbChanges) {
398
+ if (this._sourceDbChanges !== undefined) {
388
399
  // is changeset information available?
389
400
  if (this._sourceDbChanges.codeSpec.insertIds.has(codeSpec.id)) {
390
401
  isUpdate = false;
@@ -476,7 +487,7 @@ class IModelExporter {
476
487
  /** Export the model (the container only) from the source iModel. */
477
488
  async exportModelContainer(model) {
478
489
  let isUpdate;
479
- if (undefined !== this._sourceDbChanges) {
490
+ if (this._sourceDbChanges !== undefined) {
480
491
  // is changeset information available?
481
492
  if (this._sourceDbChanges.model.insertIds.has(model.id)) {
482
493
  isUpdate = false;
@@ -507,7 +518,7 @@ class IModelExporter {
507
518
  core_bentley_1.Logger.logTrace(loggerCategory, `visitElements=false, skipping exportModelContents(${modelId})`);
508
519
  return;
509
520
  }
510
- if (undefined !== this._sourceDbChanges) {
521
+ if (this._sourceDbChanges !== undefined) {
511
522
  // is changeset information available?
512
523
  if (!this._sourceDbChanges.model.insertIds.has(modelId) &&
513
524
  !this._sourceDbChanges.model.updateIds.has(modelId)) {
@@ -681,7 +692,7 @@ class IModelExporter {
681
692
  return;
682
693
  }
683
694
  let isUpdate;
684
- if (undefined !== this._sourceDbChanges) {
695
+ if (this._sourceDbChanges !== undefined) {
685
696
  // is changeset information available?
686
697
  if (this._sourceDbChanges.relationship.insertIds.has(relInstanceId)) {
687
698
  isUpdate = false;
@@ -737,6 +748,11 @@ class ChangedInstanceOps {
737
748
  val.delete.forEach((id) => this.deleteIds.add(id));
738
749
  }
739
750
  }
751
+ get isEmpty() {
752
+ return (0 === this.insertIds.size &&
753
+ 0 === this.updateIds.size &&
754
+ 0 === this.deleteIds.size);
755
+ }
740
756
  }
741
757
  exports.ChangedInstanceOps = ChangedInstanceOps;
742
758
  /**
@@ -752,6 +768,8 @@ class ChangedInstanceIds {
752
768
  this.relationship = new ChangedInstanceOps();
753
769
  this.font = new ChangedInstanceOps();
754
770
  this._db = db;
771
+ this._hasCustomChanges = false;
772
+ this._entityReferenceToCustomDataMap = new Map();
755
773
  }
756
774
  async setupECClassIds() {
757
775
  this._codeSpecSubclassIds = new Set();
@@ -759,9 +777,12 @@ class ChangedInstanceIds {
759
777
  this._elementSubclassIds = new Set();
760
778
  this._aspectSubclassIds = new Set();
761
779
  this._relationshipSubclassIds = new Set();
780
+ this._relationshipSubclassIdsToSkip = new Set();
781
+ this._ecClassIdsToClassFullNames = new Map();
762
782
  const addECClassIdsToSet = async (setToModify, baseClass) => {
763
- for await (const row of this._db.createQueryReader(`SELECT ECInstanceId FROM ECDbMeta.ECClassDef where ECInstanceId IS (${baseClass})`)) {
764
- setToModify.add(row.ECInstanceId);
783
+ for await (const row of this._db.createQueryReader(`SELECT c.ECInstanceId ECClassId, c.Name className, s.Name schemaName FROM ECDbMeta.ECClassDef c JOIN ECDbMeta.ECSchemaDef s ON s.ECInstanceId = c.Schema.Id WHERE c.ECInstanceId IS (${baseClass})`)) {
784
+ setToModify.add(row.ECClassId);
785
+ this._ecClassIdsToClassFullNames?.set(row.ECClassId, `${row.schemaName}:${row.className}`);
765
786
  }
766
787
  };
767
788
  const promises = [
@@ -771,6 +792,7 @@ class ChangedInstanceIds {
771
792
  addECClassIdsToSet(this._aspectSubclassIds, "BisCore.ElementUniqueAspect"),
772
793
  addECClassIdsToSet(this._aspectSubclassIds, "BisCore.ElementMultiAspect"),
773
794
  addECClassIdsToSet(this._relationshipSubclassIds, "BisCore.ElementRefersToElements"),
795
+ addECClassIdsToSet(this._relationshipSubclassIdsToSkip, "BisCore.ElementDrivesElement"),
774
796
  ];
775
797
  await Promise.all(promises);
776
798
  }
@@ -779,7 +801,8 @@ class ChangedInstanceIds {
779
801
  this._modelSubclassIds &&
780
802
  this._elementSubclassIds &&
781
803
  this._aspectSubclassIds &&
782
- this._relationshipSubclassIds);
804
+ this._relationshipSubclassIds &&
805
+ this._relationshipSubclassIdsToSkip);
783
806
  }
784
807
  isRelationship(ecClassId) {
785
808
  return this._relationshipSubclassIds?.has(ecClassId);
@@ -796,6 +819,17 @@ class ChangedInstanceIds {
796
819
  isElement(ecClassId) {
797
820
  return this._elementSubclassIds?.has(ecClassId);
798
821
  }
822
+ get hasCustomChanges() {
823
+ return this._hasCustomChanges;
824
+ }
825
+ get isEmpty() {
826
+ return (this.codeSpec.isEmpty &&
827
+ this.model.isEmpty &&
828
+ this.element.isEmpty &&
829
+ this.aspect.isEmpty &&
830
+ this.relationship.isEmpty &&
831
+ this.font.isEmpty);
832
+ }
799
833
  /**
800
834
  * Adds the provided [[ChangedECInstance]] to the appropriate set of changes by class type (codeSpec, model, element, aspect, or relationship) maintained by this instance of ChangedInstanceIds.
801
835
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
@@ -811,6 +845,8 @@ class ChangedInstanceIds {
811
845
  const changeType = change.$meta?.op;
812
846
  if (changeType === undefined)
813
847
  throw new Error(`ChangeType was undefined for id: ${change.ECInstanceId}.`);
848
+ if (this._relationshipSubclassIdsToSkip?.has(ecClassId))
849
+ return;
814
850
  if (this.isRelationship(ecClassId))
815
851
  this.handleChange(this.relationship, changeType, change.ECInstanceId);
816
852
  else if (this.isCodeSpec(ecClassId))
@@ -822,6 +858,104 @@ class ChangedInstanceIds {
822
858
  else if (this.isElement(ecClassId))
823
859
  this.handleChange(this.element, changeType, change.ECInstanceId);
824
860
  }
861
+ /**
862
+ * Adds the provided change to the element changes maintained by this instance of ChangedInstanceIds
863
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
864
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
865
+ * @note element changes will also cause the element's model to be marked as updated in [[ChangedInstanceIds.model]], so that the element does not get skipped by the transformer.
866
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact an element.
867
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
868
+ */
869
+ addCustomElementChange(changeType, id // TODO: Support bulk adds
870
+ ) {
871
+ // if delete unnecessary?
872
+ this.addModelToUpdated(id);
873
+ this.handleChange(this.element, changeType, id);
874
+ }
875
+ /**
876
+ * Adds the provided change to the codespec changes maintained by this instance of ChangedInstanceIds
877
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
878
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
879
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact a codespec.
880
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
881
+ */
882
+ addCustomCodeSpecChange(changeType, id) {
883
+ this.handleChange(this.codeSpec, changeType, id);
884
+ }
885
+ /**
886
+ * Adds the provided change to the model changes maintained by this instance of ChangedInstanceIds
887
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
888
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
889
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact a model.
890
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
891
+ */
892
+ addCustomModelChange(changeType, id) {
893
+ this.handleChange(this.model, changeType, id);
894
+ }
895
+ /**
896
+ * Adds the provided change to the aspect changes maintained by this instance of ChangedInstanceIds
897
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
898
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
899
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact an aspect.
900
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
901
+ */
902
+ addCustomAspectChange(changeType, id) {
903
+ this.handleChange(this.aspect, changeType, id);
904
+ }
905
+ /**
906
+ * TODO: Think more about permutations of model updated / inserted / deleted. Can you delete a model without deleting its elements?
907
+ * What if model delete but custom change si to insert element into target?
908
+ * // It is possible and apparently occasionally sensical to delete a model without deleting its underlying element.
909
+ // - If only the model is deleted, [[initFromExternalSourceAspects]] will have already remapped the underlying element since it still exists.
910
+ // - If both were deleted, [[remapDeletedSourceEntities]] will find and remap the deleted element making this operation valid
911
+ * TODO: If the element is a custom delete we probably shouldnt be calling this?
912
+ * There is an optimization in [IModelExporter.exportModelContents] which doesn't try to export elements within a model unless the model itself is part of
913
+ * the sourceDbChanges. This method is used in addCustomChange to add the model to the updatedIds set so that the custom element changes are exported.
914
+ */
915
+ addModelToUpdated(elementId) {
916
+ const modelId = this._db.elements.getElement(elementId).model;
917
+ this.handleChange(this.model, "Updated", modelId);
918
+ }
919
+ /** TODO: Maybe relationships only? maybe not. */
920
+ getCustomRelationshipDataFromId(id, type) {
921
+ if (type === "relationship") {
922
+ return this._entityReferenceToCustomDataMap.get(core_backend_1.EntityReferences.fromEntityType(id, core_common_1.ConcreteEntityTypes.Relationship));
923
+ }
924
+ return undefined;
925
+ }
926
+ /**
927
+ * Adds the provided change to the set of relationship changes maintained by this instance of ChangedInstanceIds.
928
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
929
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
930
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
931
+ * @throws if the ecClassId is NOT a relationship classId
932
+ * @param ecClassId class id of the custom change
933
+ * @param changeType insert, update or delete
934
+ * @param id ECInstanceID of the custom change
935
+ * @param sourceECInstanceId source ECInstanceId of the relationship
936
+ * @param targetECInstanceId target ECInstanceId of the relationship
937
+ */
938
+ async addCustomRelationshipChange(ecClassId, changeType, id, sourceECInstanceId, targetECInstanceId) {
939
+ if (!this._ecClassIdsInitialized)
940
+ await this.setupECClassIds();
941
+ if (this._relationshipSubclassIdsToSkip?.has(ecClassId))
942
+ return;
943
+ if (!this._relationshipSubclassIds?.has(ecClassId))
944
+ throw new Error(`Misuse. id: ${id}, ecClassId: ${ecClassId} is not a relationship class. Use 'addCustomChange' instead.`);
945
+ this._hasCustomChanges = true;
946
+ const classFullName = this._ecClassIdsToClassFullNames?.get(ecClassId);
947
+ (0, core_bentley_1.assert)(classFullName !== undefined); // setupECClassIds adds an entry to the above map for every single ECClassId.
948
+ this._entityReferenceToCustomDataMap.set(core_backend_1.EntityReferences.fromEntityType(id, core_common_1.ConcreteEntityTypes.Relationship), {
949
+ sourceIdOfRelationship: sourceECInstanceId,
950
+ targetIdOfRelationship: targetECInstanceId,
951
+ ecClassId,
952
+ classFullName,
953
+ });
954
+ this.handleChange(this.relationship, changeType, id);
955
+ }
956
+ getClassFullNameFromECClassId(ecClassid) {
957
+ return this._ecClassIdsToClassFullNames?.get(ecClassid);
958
+ }
825
959
  handleChange(changedInstanceOps, changeType, id) {
826
960
  // if changeType is a delete and we already have the id in the inserts then we can remove the id from the inserts.
827
961
  // if changeType is a delete and we already have the id in the updates then we can remove the id from the updates AND add it to the deletes.
@@ -885,10 +1019,6 @@ class ChangedInstanceIds {
885
1019
  if (csFileProps === undefined)
886
1020
  return undefined;
887
1021
  const changedInstanceIds = new ChangedInstanceIds(opts.iModel);
888
- const relationshipECClassIdsToSkip = new Set();
889
- for await (const row of opts.iModel.createQueryReader("SELECT ECInstanceId FROM ECDbMeta.ECClassDef where ECInstanceId IS (BisCore.ElementDrivesElement)")) {
890
- relationshipECClassIdsToSkip.add(row.ECInstanceId);
891
- }
892
1022
  for (const csFile of csFileProps) {
893
1023
  const csReader = core_backend_1.SqliteChangesetReader.openFile({
894
1024
  fileName: csFile.pathname,
@@ -902,9 +1032,6 @@ class ChangedInstanceIds {
902
1032
  }
903
1033
  const changes = [...ecChangeUnifier.instances];
904
1034
  for (const change of changes) {
905
- if (change.ECClassId !== undefined &&
906
- relationshipECClassIdsToSkip.has(change.ECClassId))
907
- continue;
908
1035
  await changedInstanceIds.addChange(change);
909
1036
  }
910
1037
  csReader.close();