Direction (int directionKey) { if (directionKey < CONCRETE_DIRECTIONS_OFFSET) { return ourConcreteDirections.get(directionKey); } int paramKey = directionKey - CONCRETE_DIRECTIONS_OFFSET; int paramId = paramKey / DIRECTIONS_PER_PARAM_ID; int subDirectionId = paramKey % DIRECTIONS_PER_PARAM_ID; // 0 - 1 - @NotNull, @Nullable, parameter if (subDirectionId < IN_OUT_OFFSET) { return new In(paramId, subDirectionId == 1); } if (subDirectionId < IN_THROW_OFFSET) { int valueId = subDirectionId - IN_OUT_OFFSET; return new InOut(paramId, Value.values()[valueId]); } int valueId = subDirectionId - IN_THROW_OFFSET; return new InThrow(paramId, Value.values()[valueId]); }