13c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/*
23c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Copyright (C) 2014 The Android Open Source Project
33c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
43c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
53c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * you may not use this file except in compliance with the License.
63c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * You may obtain a copy of the License at
73c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
83c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
93c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Unless required by applicable law or agreed to in writing, software
113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * See the License for the specific language governing permissions and
143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * limitations under the License.
153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */
163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpackage android.hardware.camera2.marshal.impl;
173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.Marshaler;
193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.MarshalQueryable;
203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.utils.TypeReference;
213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.util.Log;
223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.nio.ByteBuffer;
243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.util.HashMap;
253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport static android.hardware.camera2.impl.CameraMetadataNative.*;
273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport static android.hardware.camera2.marshal.MarshalHelpers.*;
283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/**
303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Marshal any simple enum (0-arg constructors only) into/from either
313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * {@code TYPE_BYTE} or {@code TYPE_INT32}.
323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>Default values of the enum are mapped to its ordinal; this can be overridden
343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * by providing a manual value with {@link #registerEnumValues}.</p>
353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @param <T> the type of {@code Enum}
373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */
383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpublic class MarshalQueryableEnum<T extends Enum<T>> implements MarshalQueryable<T> {
393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static final String TAG = MarshalQueryableEnum.class.getSimpleName();
41a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala    private static final boolean DEBUG = false;
423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static final int UINT8_MIN = 0x0;
443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static final int UINT8_MAX = (1 << Byte.SIZE) - 1;
453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static final int UINT8_MASK = UINT8_MAX;
463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private class MarshalerEnum extends Marshaler<T> {
483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        private final Class<T> mClass;
503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        @SuppressWarnings("unchecked")
523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        protected MarshalerEnum(TypeReference<T> typeReference, int nativeType) {
533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            super(MarshalQueryableEnum.this, typeReference, nativeType);
543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            mClass = (Class<T>)typeReference.getRawType();
563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        @Override
593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        public void marshal(T value, ByteBuffer buffer) {
603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            int enumValue = getEnumValue(value);
613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            if (mNativeType == TYPE_INT32) {
633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                buffer.putInt(enumValue);
643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            } else if (mNativeType == TYPE_BYTE) {
653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                if (enumValue < UINT8_MIN || enumValue > UINT8_MAX) {
663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    throw new UnsupportedOperationException(String.format(
673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            "Enum value %x too large to fit into unsigned byte", enumValue));
683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                }
693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                buffer.put((byte)enumValue);
703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            } else {
713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                throw new AssertionError();
723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        @Override
763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        public T unmarshal(ByteBuffer buffer) {
773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            int enumValue;
783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            switch (mNativeType) {
803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                case TYPE_INT32:
813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    enumValue = buffer.getInt();
823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    break;
833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                case TYPE_BYTE:
843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    // get the unsigned byte value; avoid sign extension
853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    enumValue = buffer.get() & UINT8_MASK;
863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    break;
873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                default:
883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    throw new AssertionError(
893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            "Unexpected native type; impossible since its not supported");
903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            return getEnumFromValue(mClass, enumValue);
933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        @Override
963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        public int getNativeSize() {
973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            return getPrimitiveTypeSize(mNativeType);
983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
1003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @Override
1023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public Marshaler<T> createMarshaler(TypeReference<T> managedType, int nativeType) {
1033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return new MarshalerEnum(managedType, nativeType);
1043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
1053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @Override
1073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public boolean isTypeMappingSupported(TypeReference<T> managedType, int nativeType) {
1083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (nativeType == TYPE_INT32 || nativeType == TYPE_BYTE) {
1093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            if (managedType.getType() instanceof Class<?>) {
1103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                Class<?> typeClass = (Class<?>)managedType.getType();
1113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                if (typeClass.isEnum()) {
113a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala                    if (DEBUG) {
1143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        Log.v(TAG, "possible enum detected for " + typeClass);
1153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    }
1163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    // The enum must not take extra arguments
1183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    try {
1193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        // match a class like: "public enum Fruits { Apple, Orange; }"
1203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        typeClass.getDeclaredConstructor(String.class, int.class);
1213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        return true;
1223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    } catch (NoSuchMethodException e) {
1233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        // Skip: custom enum with a special constructor e.g. Foo(T), but need Foo()
1243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        Log.e(TAG, "Can't marshal class " + typeClass + "; no default constructor");
1253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    } catch (SecurityException e) {
1263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        // Skip: wouldn't be able to touch the enum anyway
1273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        Log.e(TAG, "Can't marshal class " + typeClass + "; not accessible");
1283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    }
1293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                }
1303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
1313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
1323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return false;
1343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
1353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SuppressWarnings("rawtypes")
1373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static final HashMap<Class<? extends Enum>, int[]> sEnumValues =
1383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            new HashMap<Class<? extends Enum>, int[]>();
1393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
1413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Register a non-sequential set of values to be used with the marshal/unmarshal functions.
1423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>This enables get/set to correctly marshal the enum into a value that is C-compatible.</p>
1443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param enumType The class for an enum
1463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param values A list of values mapping to the ordinals of the enum
1473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
1483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public static <T extends Enum<T>> void registerEnumValues(Class<T> enumType, int[] values) {
1493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (enumType.getEnumConstants().length != values.length) {
1503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            throw new IllegalArgumentException(
1513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    "Expected values array to be the same size as the enumTypes values "
1523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            + values.length + " for type " + enumType);
1533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
154a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala        if (DEBUG) {
1553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            Log.v(TAG, "Registered enum values for type " + enumType + " values");
1563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
1573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        sEnumValues.put(enumType, values);
1593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
1603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
1623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Get the numeric value from an enum.
1633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>This is usually the same as the ordinal value for
1653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * enums that have fully sequential values, although for C-style enums the range of values
1663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * may not map 1:1.</p>
1673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param enumValue Enum instance
1693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @return Int guaranteed to be ABI-compatible with the C enum equivalent
1703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
1713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static <T extends Enum<T>> int getEnumValue(T enumValue) {
1723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int[] values;
1733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        values = sEnumValues.get(enumValue.getClass());
1743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int ordinal = enumValue.ordinal();
1763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (values != null) {
1773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            return values[ordinal];
1783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
1793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return ordinal;
1813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
1823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
1843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Finds the enum corresponding to it's numeric value. Opposite of {@link #getEnumValue} method.
1853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param enumType Class of the enum we want to find
1873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param value The numeric value of the enum
1883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @return An instance of the enum
1893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
1903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static <T extends Enum<T>> T getEnumFromValue(Class<T> enumType, int value) {
1913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int ordinal;
1923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int[] registeredValues = sEnumValues.get(enumType);
1943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (registeredValues != null) {
1953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            ordinal = -1;
1963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            for (int i = 0; i < registeredValues.length; ++i) {
1983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                if (registeredValues[i] == value) {
1993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    ordinal = i;
2003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    break;
2013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                }
2023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
2033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        } else {
2043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            ordinal = value;
2053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
2063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        T[] values = enumType.getEnumConstants();
2083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (ordinal < 0 || ordinal >= values.length) {
2103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            throw new IllegalArgumentException(
2113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    String.format(
2123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            "Argument 'value' (%d) was not a valid enum value for type %s "
2133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                                    + "(registered? %b)",
2143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            value,
2153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            enumType, (registeredValues != null)));
2163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
2173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return values[ordinal];
2193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
2203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin}
221