@itwin/core-backend 5.3.0-dev.7 → 5.3.0-dev.9

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/lib/cjs/IModelHost.d.ts +1 -2
  3. package/lib/cjs/IModelHost.d.ts.map +1 -1
  4. package/lib/cjs/IModelHost.js +9 -17
  5. package/lib/cjs/IModelHost.js.map +1 -1
  6. package/lib/cjs/TileStorage.d.ts +1 -1
  7. package/lib/cjs/TileStorage.d.ts.map +1 -1
  8. package/lib/cjs/TileStorage.js.map +1 -1
  9. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts +7 -1
  10. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -1
  11. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js +25 -0
  12. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js.map +1 -1
  13. package/lib/cjs/annotations/TextAnnotationElement.d.ts +20 -1
  14. package/lib/cjs/annotations/TextAnnotationElement.d.ts.map +1 -1
  15. package/lib/cjs/annotations/TextAnnotationElement.js +84 -2
  16. package/lib/cjs/annotations/TextAnnotationElement.js.map +1 -1
  17. package/lib/cjs/internal/annotations/fields.d.ts.map +1 -1
  18. package/lib/cjs/internal/annotations/fields.js +1 -0
  19. package/lib/cjs/internal/annotations/fields.js.map +1 -1
  20. package/lib/esm/IModelHost.d.ts +1 -2
  21. package/lib/esm/IModelHost.d.ts.map +1 -1
  22. package/lib/esm/IModelHost.js +10 -18
  23. package/lib/esm/IModelHost.js.map +1 -1
  24. package/lib/esm/TileStorage.d.ts +1 -1
  25. package/lib/esm/TileStorage.d.ts.map +1 -1
  26. package/lib/esm/TileStorage.js.map +1 -1
  27. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts +7 -1
  28. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -1
  29. package/lib/esm/annotations/ElementDrivesTextAnnotation.js +25 -0
  30. package/lib/esm/annotations/ElementDrivesTextAnnotation.js.map +1 -1
  31. package/lib/esm/annotations/TextAnnotationElement.d.ts +20 -1
  32. package/lib/esm/annotations/TextAnnotationElement.d.ts.map +1 -1
  33. package/lib/esm/annotations/TextAnnotationElement.js +86 -5
  34. package/lib/esm/annotations/TextAnnotationElement.js.map +1 -1
  35. package/lib/esm/internal/annotations/fields.d.ts.map +1 -1
  36. package/lib/esm/internal/annotations/fields.js +1 -0
  37. package/lib/esm/internal/annotations/fields.js.map +1 -1
  38. package/lib/esm/test/IModelHost.test.js +17 -11
  39. package/lib/esm/test/IModelHost.test.js.map +1 -1
  40. package/lib/esm/test/annotations/Fields.test.js +146 -51
  41. package/lib/esm/test/annotations/Fields.test.js.map +1 -1
  42. package/lib/esm/test/annotations/TextAnnotation.test.js +227 -2
  43. package/lib/esm/test/annotations/TextAnnotation.test.js.map +1 -1
  44. package/package.json +17 -19
@@ -4,9 +4,9 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import { expect } from "chai";
6
6
  import { Angle, Point3d, Range2d, Range3d, YawPitchRollAngles } from "@itwin/core-geometry";
7
- import { FractionRun, SubCategoryAppearance, TextAnnotation, TextBlock, TextRun, TextStyleSettings } from "@itwin/core-common";
7
+ import { FieldRun, FractionRun, SubCategoryAppearance, TextAnnotation, TextBlock, TextRun, TextStyleSettings } from "@itwin/core-common";
8
8
  import { StandaloneDb } from "../../IModelDb";
9
- import { AnnotationTextStyle, TEXT_ANNOTATION_JSON_VERSION, TEXT_STYLE_SETTINGS_JSON_VERSION, TextAnnotation2d, TextAnnotation3d } from "../../annotations/TextAnnotationElement";
9
+ import { AnnotationTextStyle, parseTextAnnotationData, TEXT_ANNOTATION_JSON_VERSION, TEXT_STYLE_SETTINGS_JSON_VERSION, TextAnnotation2d, TextAnnotation3d } from "../../annotations/TextAnnotationElement";
10
10
  import { IModelTestUtils } from "../IModelTestUtils";
11
11
  import { Subject } from "../../Element";
12
12
  import { Guid, Id64 } from "@itwin/core-bentley";
@@ -19,6 +19,7 @@ import { computeTextRangeAsStringLength, MockBuilder } from "../AnnotationTestUt
19
19
  import { TextAnnotationUsesTextStyleByDefault } from "../../annotations/ElementDrivesTextAnnotation";
20
20
  import { layoutTextBlock, TextStyleResolver } from "../../annotations/TextBlockLayout";
21
21
  import { appendTextAnnotationGeometry } from "../../annotations/TextAnnotationGeometry";
22
+ import { IModelElementCloneContext } from "../../IModelElementCloneContext";
22
23
  function mockIModel() {
23
24
  const iModel = {
24
25
  fonts: {
@@ -212,6 +213,58 @@ describe("TextAnnotation element", () => {
212
213
  expect(elem.getAnnotation().toJSON()).not.to.equal(annotation.toJSON());
213
214
  });
214
215
  });
216
+ describe("getReferenceIds", () => {
217
+ function expectReferenceIds(expected, element) {
218
+ const actual = Array.from(element.getReferenceIds()).sort();
219
+ // reference Ids get a prefix indicating their type ('e' for 'element')
220
+ expected = expected.map((id) => `e${id}`);
221
+ // the superclasses provide some reference Ids (code spec, model, category)
222
+ const baseIds = ["e0x12", "e0x78", "m0x34"];
223
+ expected.push(...baseIds);
224
+ expected = expected.sort();
225
+ expect(actual).to.deep.equal(expected);
226
+ }
227
+ it("reports default text style and field hosts", () => {
228
+ // makeElement sets defaultTextStyle to "0x21"
229
+ const elem = makeElement();
230
+ expectReferenceIds(["0x21"], elem);
231
+ elem.defaultTextStyle = new TextAnnotationUsesTextStyleByDefault("0x123");
232
+ expectReferenceIds(["0x123"], elem);
233
+ const textBlock = TextBlock.create();
234
+ textBlock.appendRun(FieldRun.create({
235
+ propertyHost: { elementId: "0x456", schemaName: "BisCore", className: "GeometricElement3d" },
236
+ propertyPath: { propertyName: "CodeValue" },
237
+ }));
238
+ textBlock.appendRun(FieldRun.create({
239
+ propertyHost: { elementId: "0x789", schemaName: "BisCore", className: "GeometricElement3d" },
240
+ propertyPath: { propertyName: "LastMod" },
241
+ }));
242
+ elem.setAnnotation(TextAnnotation.create({ textBlock }));
243
+ expectReferenceIds(["0x123", "0x456", "0x789"], elem);
244
+ elem.defaultTextStyle = undefined;
245
+ expectReferenceIds(["0x456", "0x789"], elem);
246
+ elem.setAnnotation(TextAnnotation.create());
247
+ expectReferenceIds([], elem);
248
+ });
249
+ it("does not report invalid Ids", () => {
250
+ const elem = makeElement();
251
+ elem.defaultTextStyle = undefined;
252
+ expectReferenceIds([], elem);
253
+ elem.defaultTextStyle = new TextAnnotationUsesTextStyleByDefault("0");
254
+ expectReferenceIds([], elem);
255
+ const textBlock = TextBlock.create();
256
+ textBlock.appendRun(FieldRun.create({
257
+ propertyHost: { elementId: "0", schemaName: "BisCore", className: "GeometricElement3d" },
258
+ propertyPath: { propertyName: "CodeValue" },
259
+ }));
260
+ textBlock.appendRun(FieldRun.create({
261
+ propertyHost: { elementId: "0x123", schemaName: "BisCore", className: "GeometricElement3d" },
262
+ propertyPath: { propertyName: "LastMod" },
263
+ }));
264
+ elem.setAnnotation(TextAnnotation.create({ textBlock }));
265
+ expectReferenceIds(["0x123"], elem);
266
+ });
267
+ });
215
268
  describe("TextAnnotation3d Persistence", () => {
216
269
  let imodel;
217
270
  let createElement3dArgs;
@@ -399,6 +452,178 @@ describe("TextAnnotation element", () => {
399
452
  expect(el1 instanceof TextAnnotation2d).to.be.true;
400
453
  expect(el1.defaultTextStyle).to.be.undefined;
401
454
  });
455
+ describe("onCloned", () => {
456
+ function insertStyledElement(styleId, db) {
457
+ const args = { ...createElement2dArgs, defaultTextStyleId: styleId };
458
+ const elem = createElement2d(db, args);
459
+ elem.insert();
460
+ imodel.saveChanges();
461
+ return elem;
462
+ }
463
+ describe("within a single iModel", () => {
464
+ it("leaves property hosts intact", () => {
465
+ const textBlock = TextBlock.create({
466
+ children: [{
467
+ children: [{
468
+ type: "field",
469
+ propertyHost: {
470
+ elementId: "0x123",
471
+ schemaName: "Fields",
472
+ className: "TestElement",
473
+ },
474
+ propertyPath: { propertyName: "intProp" },
475
+ }, {
476
+ type: "field",
477
+ propertyHost: {
478
+ elementId: "0xabc",
479
+ schemaName: "BisCore",
480
+ className: "Element",
481
+ },
482
+ propertyPath: { propertyName: "CodeValue" },
483
+ }],
484
+ }],
485
+ });
486
+ const annotation = TextAnnotation.create({ textBlock });
487
+ const elem = createElement2d(imodel, { ...createElement2dArgs, textAnnotationProps: annotation.toJSON() });
488
+ elem.insert();
489
+ imodel.saveChanges();
490
+ const context = new IModelElementCloneContext(imodel);
491
+ context.remapElement("0x123", "0x456");
492
+ context.remapElement("0xabc", "0xdef");
493
+ context.remapElement(createElement2dArgs.model, createElement2dArgs.model);
494
+ const props = context.cloneElement(elem);
495
+ expect(props.textAnnotationData).not.to.be.undefined;
496
+ const anno = TextAnnotation.fromJSON(parseTextAnnotationData(props.textAnnotationData)?.data);
497
+ const para = anno.textBlock.children[0];
498
+ expect(para.children[0].propertyHost.elementId).to.equal("0x123");
499
+ expect(para.children[1].propertyHost.elementId).to.equal("0xabc");
500
+ });
501
+ it("leaves default text style intact", () => {
502
+ function clone(styleId, expectedStyleId) {
503
+ const elem = insertStyledElement(styleId, imodel);
504
+ const context = new IModelElementCloneContext(imodel);
505
+ context.remapElement(createElement2dArgs.model, createElement2dArgs.model);
506
+ const props = context.cloneElement(elem);
507
+ expect(props.defaultTextStyle?.id).to.equal(expectedStyleId);
508
+ if (styleId) {
509
+ // Even an explicit remapping is ignored when cloning within a single iModel
510
+ // (per the examples set by most other elements, excluding RenderMaterial).
511
+ context.remapElement(styleId, "0x99887");
512
+ const props2 = context.cloneElement(elem);
513
+ expect(props2.defaultTextStyle?.id).to.equal(expectedStyleId);
514
+ }
515
+ }
516
+ clone(seedStyleId, seedStyleId);
517
+ clone(undefined, undefined);
518
+ clone("0x12345", "0x12345");
519
+ clone(Id64.invalid, undefined);
520
+ });
521
+ });
522
+ describe("between iModels", () => {
523
+ let dstDb;
524
+ let dstDefModel;
525
+ let dstElemArgs;
526
+ before(async () => {
527
+ dstDb = await createIModel("CloneTarget");
528
+ const jobSubjectId = createJobSubjectElement(dstDb, "Job").insert();
529
+ dstDefModel = DefinitionModel.insert(dstDb, jobSubjectId, "Definition");
530
+ const { category, model } = insertDrawingModel(dstDb, jobSubjectId, dstDefModel);
531
+ expect(category).not.to.equal(createElement2dArgs.category);
532
+ expect(model).not.to.equal(createElement2dArgs.model);
533
+ dstElemArgs = { category, model };
534
+ });
535
+ after(() => dstDb.close());
536
+ it("remaps property hosts", () => {
537
+ const textBlock = TextBlock.create({
538
+ children: [{
539
+ children: [{
540
+ type: "field",
541
+ propertyHost: {
542
+ elementId: "0x123",
543
+ schemaName: "Fields",
544
+ className: "TestElement",
545
+ },
546
+ propertyPath: { propertyName: "intProp" },
547
+ }, {
548
+ type: "field",
549
+ propertyHost: {
550
+ elementId: "0xabc",
551
+ schemaName: "BisCore",
552
+ className: "Element",
553
+ },
554
+ propertyPath: { propertyName: "CodeValue" },
555
+ }],
556
+ }],
557
+ });
558
+ const annotation = TextAnnotation.create({ textBlock });
559
+ const elem = createElement2d(imodel, { ...createElement2dArgs, textAnnotationProps: annotation.toJSON() });
560
+ elem.insert();
561
+ imodel.saveChanges();
562
+ const context = new IModelElementCloneContext(imodel, dstDb);
563
+ context.remapElement("0x123", "0x456");
564
+ context.remapElement("0xabc", "0xdef");
565
+ context.remapElement(createElement2dArgs.model, dstElemArgs.model);
566
+ const props = context.cloneElement(elem);
567
+ expect(props.textAnnotationData).not.to.be.undefined;
568
+ const anno = TextAnnotation.fromJSON(parseTextAnnotationData(props.textAnnotationData)?.data);
569
+ const para = anno.textBlock.children[0];
570
+ expect(para.children[0].propertyHost.elementId).to.equal("0x456");
571
+ expect(para.children[1].propertyHost.elementId).to.equal("0xdef");
572
+ });
573
+ it("sets default text style to undefined if source style does not exist", () => {
574
+ const elem = insertStyledElement("0x12345", imodel);
575
+ const context = new IModelElementCloneContext(imodel, dstDb);
576
+ context.remapElement(createElement2dArgs.model, dstElemArgs.model);
577
+ const props = context.cloneElement(elem);
578
+ expect(props.defaultTextStyle).to.be.undefined;
579
+ });
580
+ it("remaps to an existing text style with the same code if present", () => {
581
+ const dstStyleId = createAnnotationTextStyle(dstDb, dstDefModel, "test", { font: { name: "Karla" } }).insert();
582
+ expect(dstStyleId).not.to.equal(seedStyleId);
583
+ const srcElem = insertStyledElement(seedStyleId, imodel);
584
+ const context = new IModelElementCloneContext(imodel, dstDb);
585
+ context.remapElement(createElement2dArgs.model, dstElemArgs.model);
586
+ const props = context.cloneElement(srcElem);
587
+ expect(props.defaultTextStyle?.id).to.equal(dstStyleId);
588
+ });
589
+ it("throws an error if definition model is not remapped", () => {
590
+ const srcElem = insertStyledElement(seedStyleId2, imodel);
591
+ const context = new IModelElementCloneContext(imodel, dstDb);
592
+ context.remapElement(createElement2dArgs.model, dstElemArgs.model);
593
+ expect(() => context.cloneElement(srcElem)).to.throw("Invalid target model");
594
+ });
595
+ it("imports default text style if necessary", () => {
596
+ const srcElem = insertStyledElement(seedStyleId2, imodel);
597
+ const context = new IModelElementCloneContext(imodel, dstDb);
598
+ context.remapElement(createElement2dArgs.model, dstElemArgs.model);
599
+ context.remapElement(seedDefinitionModelId, dstDefModel);
600
+ const props = context.cloneElement(srcElem);
601
+ const dstStyleId = props.defaultTextStyle.id;
602
+ expect(dstStyleId).not.to.be.undefined;
603
+ expect(dstStyleId).not.to.equal(seedStyleId2);
604
+ expect(dstDb.elements.tryGetElement(dstStyleId)).not.to.be.undefined;
605
+ });
606
+ it("remaps multiple occurrences of same style to same Id", () => {
607
+ const srcStyleId = createAnnotationTextStyle(imodel, seedDefinitionModelId, "styyyle", { font: { name: "Karla" } }).insert();
608
+ const srcElem1 = insertStyledElement(srcStyleId, imodel);
609
+ const srcElem2 = insertStyledElement(srcStyleId, imodel);
610
+ const srcElem3 = insertStyledElement(srcStyleId, imodel);
611
+ const context = new IModelElementCloneContext(imodel, dstDb);
612
+ context.remapElement(createElement2dArgs.model, dstElemArgs.model);
613
+ context.remapElement(seedDefinitionModelId, dstDefModel);
614
+ const props1 = context.cloneElement(srcElem1);
615
+ const props2 = context.cloneElement(srcElem2);
616
+ expect(props1.defaultTextStyle).not.to.be.undefined;
617
+ expect(props1.defaultTextStyle?.id).not.to.equal(srcStyleId);
618
+ expect(props2.defaultTextStyle?.id).to.equal(props1.defaultTextStyle?.id);
619
+ const context2 = new IModelElementCloneContext(imodel, dstDb);
620
+ context2.remapElement(createElement2dArgs.model, dstElemArgs.model);
621
+ context2.remapElement(seedDefinitionModelId, dstDefModel);
622
+ const props3 = context2.cloneElement(srcElem3);
623
+ expect(props3.defaultTextStyle?.id).to.equal(props1.defaultTextStyle?.id);
624
+ });
625
+ });
626
+ });
402
627
  });
403
628
  describe("TextAnnotation3d", () => {
404
629
  let createElement3dArgs;