/*
* Copyright 2016 NAVER Corp.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.web.scatter;
import com.navercorp.pinpoint.web.vo.scatter.Dot;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* @Author Taejin Koo
*/
public class DotGroups {
private static final DotComparator DOT_COMPARATOR = new DotComparator();
private final long xCoordinates;
private final Map<Key, DotGroup> dotGroupMap = new HashMap<>();
public DotGroups(long xCoordinates) {
this.xCoordinates = xCoordinates;
}
void addDot(Coordinates coordinates, Dot dot) {
Key key = new Key(coordinates, dot.getSimpleExceptionCode());
DotGroup dotGroup = dotGroupMap.get(key);
if (dotGroup == null) {
dotGroup = new DotGroup(coordinates);
dotGroupMap.put(key, dotGroup);
}
dotGroup.addDot(dot);
}
void merge(DotGroups dotGroups) {
if (dotGroups == null) {
return;
}
Map<Key, DotGroup> dotGroupMap = dotGroups.getDotGroupMap();
for (Map.Entry<Key, DotGroup> entry : dotGroupMap.entrySet()) {
Key key = entry.getKey();
DotGroup dotGroup = this.dotGroupMap.get(key);
if (dotGroup == null) {
this.dotGroupMap.put(key, entry.getValue());
} else {
dotGroup.merge(entry.getValue());
}
}
}
public long getXCoordinates() {
return xCoordinates;
}
public Map<Key, DotGroup> getDotGroupMap() {
return dotGroupMap;
}
public Set<Dot> getSortedDotSet() {
Collection<DotGroup> dotGroupList = dotGroupMap.values();
int size = 0;
for (DotGroup dotGroup : dotGroupList) {
size += dotGroup.getDotSize();
}
List<Dot> dotList = new ArrayList<>(size);
for (DotGroup dotGroup : dotGroupList) {
dotList.addAll(dotGroup.getDotSet());
}
Set<Dot> sortedSet = new TreeSet<>(DOT_COMPARATOR);
sortedSet.addAll(dotList);
return sortedSet;
}
public Map<Dot, DotGroup> getDotGroupLeaders() {
Map<Dot, DotGroup> dotLeaderMap = new HashMap<>(dotGroupMap.size());
Collection<DotGroup> dotGroupList = dotGroupMap.values();
for (DotGroup dotGroup : dotGroupList) {
if (dotGroup.getDotLeader() != null) {
dotLeaderMap.put(dotGroup.getDotLeader(), dotGroup);
}
}
return dotLeaderMap;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DotGroups dotGroups = (DotGroups) o;
return xCoordinates == dotGroups.getXCoordinates();
}
@Override
public int hashCode() {
return (int) (xCoordinates ^ (xCoordinates >>> 32));
}
@Override
public String toString() {
return "DotGroups{" + "xCoordinates=" + xCoordinates + ", dotGroupMap=" + dotGroupMap + '}';
}
private static class DotComparator implements Comparator<Dot> {
@Override
public int compare(Dot o1, Dot o2) {
int compare = Long.compare(o2.getAcceptedTime(), o1.getAcceptedTime());
if (compare == 0) {
return -1;
}
return compare;
}
}
static class Key {
private final Coordinates coordinates;
private final int code;
private int hashCode = 0;
public Key(Coordinates coordinates, int code) {
this.coordinates = coordinates;
this.code = code;
hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Key that = (Key) obj;
if (!coordinates.equals(that.coordinates)) {
return false;
}
if (code != that.code) {
return false;
}
return true;
}
@Override
public int hashCode() {
if (hashCode == 0) {
int result = coordinates != null ? coordinates.hashCode() : 0;
result = 31 * result + code;
this.hashCode = result;
}
return hashCode;
}
@Override
public String toString() {
return "Key{" +
"coordinates=" + coordinates +
", code=" + code +
'}';
}
}
}