/*
* Copyright 2014 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.common.trace;
import com.navercorp.pinpoint.common.util.apache.IntHashMap;
import com.navercorp.pinpoint.common.util.apache.IntHashMapUtils;
import java.util.*;
/**
* @author emeroad
*/
public class ServiceTypeRegistry {
private final IntHashMap<ServiceType> codeLookupTable;
private final Map<String, ServiceType> nameLookupTable;
private final Map<String, List<ServiceType>> descLookupTable;
private ServiceTypeRegistry() {
this.codeLookupTable = new IntHashMap<ServiceType>();
this.nameLookupTable = new HashMap<String, ServiceType>();
this.descLookupTable = new HashMap<String, List<ServiceType>>();
}
private ServiceTypeRegistry(HashMap<Integer, ServiceType> buildMap) {
if (buildMap == null) {
throw new NullPointerException("codeLookupTable must not be null");
}
this.codeLookupTable = IntHashMapUtils.copy(buildMap);
this.nameLookupTable = buildNameLookupTable(buildMap.values());
this.descLookupTable = buildDescLookupTable(buildMap.values());
}
private Map<String, ServiceType> buildNameLookupTable(Collection<ServiceType> serviceTypes) {
final Map<String, ServiceType> copy = new HashMap<String, ServiceType>();
for (ServiceType serviceType : serviceTypes) {
final ServiceType duplicated = copy.put(serviceType.getName(), serviceType);
if (duplicated != null) {
throw new IllegalStateException("duplicated ServiceType " + serviceType + " / " + duplicated);
}
}
return copy;
}
public ServiceType findServiceType(short code) {
final ServiceType serviceType = this.codeLookupTable.get(code);
if (serviceType == null) {
return ServiceType.UNDEFINED;
}
return serviceType;
}
public ServiceType findServiceTypeByName(String name) {
final ServiceType serviceType = this.nameLookupTable.get(name);
if (serviceType == null) {
return ServiceType.UNDEFINED;
}
return serviceType;
}
@Deprecated
public List<ServiceType> findDesc(String desc) {
if (desc == null) {
throw new NullPointerException("desc must not be null");
}
return descLookupTable.get(desc);
}
private Map<String, List<ServiceType>> buildDescLookupTable(Collection<ServiceType> serviceTypes) {
final Map<String, List<ServiceType>> table = new HashMap<String, List<ServiceType>>();
for (ServiceType serviceType : serviceTypes) {
if (serviceType.isRecordStatistics()) {
List<ServiceType> serviceTypeList = table.get(serviceType.getDesc());
if (serviceTypeList == null) {
serviceTypeList = new ArrayList<ServiceType>();
table.put(serviceType.getDesc(), serviceTypeList);
}
serviceTypeList.add(serviceType);
}
}
return unmodifiableMap(table);
}
private static Map<String, List<ServiceType>> unmodifiableMap(Map<String, List<ServiceType>> table) {
// value of this table will be exposed. so make them unmodifiable.
final Map<String, List<ServiceType>> copy = new HashMap<String, List<ServiceType>>(table.size());
for (Map.Entry<String, List<ServiceType>> entry : table.entrySet()) {
List<ServiceType> newValue = Collections.unmodifiableList(entry.getValue());
copy.put(entry.getKey(), newValue);
}
return copy;
}
public static class Builder {
private final HashMap<Integer, ServiceType> buildMap = new HashMap<Integer, ServiceType>();
public void addServiceType(ServiceType serviceType) {
if (serviceType == null) {
throw new NullPointerException("serviceType must not be null");
}
int code = serviceType.getCode();
final ServiceType exist = this.buildMap.put(code, serviceType);
if (exist != null) {
throw new IllegalStateException("already exist. serviceType:" + serviceType + ", exist:" + exist);
}
}
public ServiceTypeRegistry build() {
return new ServiceTypeRegistry(buildMap);
}
}
}