1 /*
2  * Copyright 2017 Google Inc.
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  *     https://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 
17 package trebuchet.model.fragments
18 
19 import trebuchet.model.base.SliceGroup
20 
21 class SliceGroupBuilder {
22     val slices: MutableList<MutableSliceGroup> = mutableListOf()
23     val openSlices: MutableList<MutableSliceGroup> = mutableListOf()
24 
hasOpenSlicesnull25     fun hasOpenSlices() = openSlices.isNotEmpty()
26 
27     inline fun beginSlice(action: (MutableSliceGroup) -> Unit): Unit {
28         val builder = MutableSliceGroup()
29         action(builder)
30         openSlices.add(builder)
31     }
32 
endSlicenull33     inline fun endSlice(action: (MutableSliceGroup) -> Unit): SliceGroup? {
34         if (!hasOpenSlices()) return null // silently ignore unmatched endSlice calls
35 
36         val builder = openSlices.removeAt(openSlices.lastIndex)
37         action(builder)
38         builder.validate()
39         if (openSlices.isNotEmpty()) {
40             openSlices.last().add(builder)
41         } else {
42             slices.add(builder)
43         }
44         return builder
45     }
46 
autoCloseOpenSlicesnull47     fun autoCloseOpenSlices(maxTimestamp: Double) {
48         while (hasOpenSlices()) {
49             endSlice {
50                 it.endTime = maxTimestamp
51                 it.didNotFinish = true
52             }
53         }
54     }
55 
56     companion object {
57         val EmptyChildren = mutableListOf<MutableSliceGroup>()
58     }
59 
60     class MutableSliceGroup(override var startTime: Double = Double.NaN,
61                             override var endTime: Double = Double.NaN,
62                             override var didNotFinish: Boolean = false,
63                             var _name: String? = null,
64                             var _children: MutableList<MutableSliceGroup>? = null) : SliceGroup {
65         override var name: String
66             get() = _name!!
67             set(value) { _name = value }
68 
69         override val children: List<SliceGroup>
70             get() = _children!!
71 
validatenull72         fun validate() {
73             if (!startTime.isFinite() || startTime < 0) {
74                 throw IllegalStateException("Invalid startTime $startTime")
75             }
76             if (!endTime.isFinite() || endTime < 0) {
77                 throw IllegalStateException("Invalid endTime $endTime")
78             }
79             if (endTime < startTime) {
80                 throw IllegalStateException("endTime $endTime cannot be before startTime $startTime")
81             }
82             if (_name == null) {
83                 throw IllegalStateException("name cannot be null")
84             }
85             if (_children == null) {
86                 _children = EmptyChildren
87             }
88         }
89 
addnull90         fun add(child: MutableSliceGroup) {
91             if (_children == null) _children = mutableListOf()
92             _children!!.add(child)
93         }
94     }
95 }