1 /* 2 * Copyright 2019 Google LLC 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 17 package io.perfmark.impl; 18 19 import java.util.AbstractList; 20 import java.util.ArrayList; 21 import java.util.Arrays; 22 import java.util.Collections; 23 import java.util.List; 24 import java.util.ListIterator; 25 26 /** MarkList is collection of Marks, in the order they were recorded. */ 27 public final class MarkList extends AbstractList<Mark> { newBuilder()28 public static Builder newBuilder() { 29 return new Builder(); 30 } 31 32 private final List<Mark> marks; 33 private final long threadId; 34 private final long markListId; 35 private final String threadName; 36 MarkList(Builder builder)37 MarkList(Builder builder) { 38 if (builder.marks == null) { 39 throw new NullPointerException("marks"); 40 } 41 this.marks = builder.marks; 42 if (builder.threadName == null) { 43 throw new NullPointerException("threadName"); 44 } 45 this.threadName = builder.threadName; 46 this.threadId = builder.threadId; 47 this.markListId = builder.markListId; 48 } 49 50 /** 51 * Gets the Thread name of the thread that recorded the Marks. 52 * 53 * @return the Thread name. 54 */ getThreadName()55 public String getThreadName() { 56 return threadName; 57 } 58 59 /** 60 * Thread IDs can be recycled, so this is not unique. 61 * 62 * @return the id of the thread, as returned by {@link Thread#getId()}. 63 */ getThreadId()64 public long getThreadId() { 65 return threadId; 66 } 67 68 /** 69 * The globally unique ID for this Mark list. Unlike {@link #getThreadId()}, this value is never 70 * recycled. 71 * 72 * @return the id of this list. 73 */ getMarkListId()74 public long getMarkListId() { 75 return markListId; 76 } 77 78 @Override get(int index)79 public Mark get(int index) { 80 return marks.get(index); 81 } 82 83 @Override equals(Object obj)84 public boolean equals(Object obj) { 85 if (!(obj instanceof MarkList)) { 86 return false; 87 } 88 MarkList that = (MarkList) obj; 89 return Mark.equal(this.marks, that.marks) 90 && this.threadId == that.threadId 91 && this.markListId == that.markListId 92 && Mark.equal(this.threadName, that.threadName); 93 } 94 95 @Override hashCode()96 public int hashCode() { 97 return Arrays.hashCode(new Object[] {marks, threadId, markListId, threadName}); 98 } 99 100 @Override size()101 public int size() { 102 return marks.size(); 103 } 104 105 @Override toString()106 public String toString() { 107 return "MarkList{" 108 + "marks=" 109 + marks 110 + ", " 111 + "threadId=" 112 + threadId 113 + ", " 114 + "markListId=" 115 + markListId 116 + ", " 117 + "threadName=" 118 + threadName 119 + "}"; 120 } 121 toBuilder()122 public Builder toBuilder() { 123 Builder builder = newBuilder(); 124 builder.marks = marks; 125 return builder.setThreadName(threadName).setThreadId(threadId).setMarkListId(markListId); 126 } 127 128 public static final class Builder { 129 130 List<Mark> marks; 131 String threadName; 132 long threadId; 133 long markListId; 134 build()135 public MarkList build() { 136 return new MarkList(this); 137 } 138 139 /** 140 * Sets the marks for this MarkList builder. 141 * 142 * @throws NullPointerException if any element in this list is {@code null}. 143 * @param marks the marks to set. 144 * @return this 145 */ setMarks(List<Mark> marks)146 public Builder setMarks(List<Mark> marks) { 147 if (marks == null) { 148 throw new NullPointerException("marks"); 149 } 150 ArrayList<Mark> copy = new ArrayList<Mark>(marks.size()); 151 ListIterator<Mark> it = marks.listIterator(); 152 while (it.hasNext()) { 153 Mark mark = it.next(); 154 if (mark == null) { 155 throw new NullPointerException("mark is null at pos " + (it.nextIndex() - 1)); 156 } 157 copy.add(mark); 158 } 159 this.marks = Collections.unmodifiableList(copy); 160 return this; 161 } 162 163 /** 164 * Sets the thread name for this MarkList builder. 165 * 166 * @param threadName the Thread Name 167 * @return this 168 */ setThreadName(String threadName)169 public Builder setThreadName(String threadName) { 170 this.threadName = threadName; 171 return this; 172 } 173 174 /** 175 * Sets the thread ID for this MarkList builder. 176 * 177 * @param threadId the Thread Id 178 * @return this 179 */ setThreadId(long threadId)180 public Builder setThreadId(long threadId) { 181 this.threadId = threadId; 182 return this; 183 } 184 185 /** 186 * Sets the mark list ID for this MarkList builder. 187 * 188 * @param markListId the mark list ID 189 * @return this 190 */ setMarkListId(long markListId)191 public Builder setMarkListId(long markListId) { 192 this.markListId = markListId; 193 return this; 194 } 195 } 196 } 197