1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {assertDefined} from 'common/assert_utils';
18import {PropertyFormatter} from 'trace/tree_node/formatters';
19import {
20  PropertySource,
21  PropertyTreeNode,
22} from 'trace/tree_node/property_tree_node';
23import {TreeBuilder} from './tree_builder';
24
25export class PropertyTreeBuilder extends TreeBuilder<
26  PropertyTreeNode,
27  ChildProperty
28> {
29  isRoot: boolean = false;
30  source = PropertySource.PROTO;
31  value: any;
32  formatter: PropertyFormatter | undefined;
33
34  setIsRoot(value: boolean): this {
35    this.isRoot = value;
36    return this;
37  }
38
39  setRootId(value: string): this {
40    this.id = value;
41    return this;
42  }
43
44  setSource(value: PropertySource): this {
45    this.source = value;
46    return this;
47  }
48
49  setValue(value: any): this {
50    this.value = value;
51    return this;
52  }
53
54  setFormatter(value: PropertyFormatter | undefined): this {
55    this.formatter = value;
56    return this;
57  }
58
59  protected override makeRootNode(): PropertyTreeNode {
60    const node = new PropertyTreeNode(
61      this.isRoot ? this.makeRootId() : this.makePropertyNodeId(),
62      assertDefined(this.name),
63      this.source,
64      this.value,
65    );
66    if (this.formatter) node.setFormatter(this.formatter);
67    return node;
68  }
69
70  protected override addOrReplaceChildNode(
71    rootNode: PropertyTreeNode,
72    child: ChildProperty,
73  ): void {
74    const childNode = new PropertyTreeBuilder()
75      .setRootId(rootNode.id)
76      .setName(child.name)
77      .setSource(child.source ?? assertDefined(this.source))
78      .setValue(child.value)
79      .setChildren(child.children ?? [])
80      .setFormatter(child.formatter)
81      .build();
82    rootNode.addOrReplaceChild(childNode);
83  }
84
85  private makePropertyNodeId() {
86    return `${this.id}.${this.name}`;
87  }
88
89  private makeRootId() {
90    return `${this.id} ${this.name}`;
91  }
92}
93
94export interface ChildProperty {
95  name: string;
96  value?: any;
97  children?: ChildProperty[];
98  source?: PropertySource;
99  formatter?: PropertyFormatter;
100}
101