package org.infinispan.marshall.core; import java.io.IOException; import java.util.List; import java.util.Map; import org.infinispan.commons.util.HopscotchHashMap; import org.infinispan.configuration.global.GlobalConfiguration; import org.infinispan.container.entries.InternalCacheValue; class ClassIdentifiers implements ClassIds { // the hashmap is not changed after static ctor, therefore concurrent access is safe private final Map<Class<?>, Integer> classToId = new HopscotchHashMap<>(MAX_ID); private final Class<?>[] internalIdToClass; // for external ids we'll probably use Map<Integer, Class<?>> instead of array public static ClassIdentifiers load(GlobalConfiguration globalConfiguration) { return new ClassIdentifiers(); } private ClassIdentifiers() { add(Object.class, OBJECT); add(String.class, STRING); add(List.class, LIST); add(Map.Entry.class, MAP_ENTRY); add(InternalCacheValue.class, INTERNAL_CACHE_VALUE); internalIdToClass = new Class[MAX_ID]; classToId.entrySet().stream().forEach(e -> internalIdToClass[e.getValue().intValue()] = e.getKey()); } private void add(Class<?> clazz, int id) { Integer prev = classToId.put(clazz, id); assert prev == null; } /** * This method throws IOException because it is assumed that we got the id from network. * @param id * @return * @throws IOException */ public Class<?> getClass(int id) throws IOException { if (id < 0 || id > internalIdToClass.length) { throw new IOException("Unknown class id " + id); } Class<?> clazz = internalIdToClass[id]; if (clazz == null) { throw new IOException("Unknown class id " + id); } return clazz; } /** * @param clazz * @return -1 if the id for given class is not found */ public int getId(Class<?> clazz) { Integer id = classToId.get(clazz); if (id == null) { assert ExternallyMarshallable.isAllowed(clazz) : "Check support for " + clazz; return -1; } else { return id.intValue(); } } }