/*
* Copyright (C) 2015 SoftIndex LLC.
*
* 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 io.datakernel.serializer;
import io.datakernel.serializer.asm.SerializerGen;
import io.datakernel.serializer.asm.SerializerGenBuilder;
import java.util.*;
final class TypedModsMap {
private static final TypedModsMap EMPTY = new TypedModsMap();
private final List<SerializerGenBuilder> mods;
private final Map<Integer, TypedModsMap> children;
public static class Builder {
private List<SerializerGenBuilder> mods = new ArrayList<>();
private Map<Integer, Builder> children = new LinkedHashMap<>();
public void add(SerializerGenBuilder serializerGenBuilder) {
this.mods.add(serializerGenBuilder);
}
private Builder ensureChild(int childKey) {
Builder result = children.get(childKey);
if (result == null) {
result = new Builder();
children.put(childKey, result);
}
return result;
}
public Builder ensureChild(int[] path) {
Builder result = this;
for (int i = 0; i < path.length; i++) {
int n = path[i];
result = result.ensureChild(n);
}
return result;
}
public TypedModsMap build() {
if (this.mods.isEmpty() && this.children.isEmpty())
return empty();
return new TypedModsMap(this);
}
}
public static Builder builder() {
return new Builder();
}
public static TypedModsMap empty() {
return EMPTY;
}
private TypedModsMap() {
this.mods = new ArrayList<>();
this.children = new HashMap<>();
}
private TypedModsMap(Builder builder) {
this.mods = new ArrayList<>(builder.mods);
Map<Integer, TypedModsMap> childrenBuilder = new HashMap<>();
for (Integer key : builder.children.keySet()) {
childrenBuilder.put(key, new TypedModsMap(builder.children.get(key)));
}
this.children = childrenBuilder;
}
public boolean hasChildren() {
return !children.isEmpty();
}
public List<SerializerGenBuilder> getMods() {
return mods;
}
public boolean isEmpty() {
return children.isEmpty() && mods.isEmpty();
}
public TypedModsMap get(int typeIndex) {
TypedModsMap result = children.get(typeIndex);
return result == null ? empty() : result;
}
public SerializerGen rewrite(final Class<?> type, final SerializerGenBuilder.SerializerForType[] generics, final SerializerGen serializer) {
SerializerGen result = serializer;
for (SerializerGenBuilder mod : mods) {
result = mod.serializer(type, generics, result);
}
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(32).append(simpleName(this.getClass())).append("{");
sb.append("mods=").append(mods);
sb.append("children=").append(children);
return sb.append("}").toString();
}
private static String simpleName(Class<?> clazz) {
String name = clazz.getName();
name = name.replaceAll("\\$[0-9]+", "\\$");
int start = name.lastIndexOf('$');
if (start == -1) {
start = name.lastIndexOf('.');
}
return name.substring(start + 1);
}
}