com.dyuproject.protostuff.EnumMapping Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of protostuff-api Show documentation
Show all versions of protostuff-api Show documentation
serialization api for messages
The newest version!
//========================================================================
//Copyright 2023 David Yu
//------------------------------------------------------------------------
//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.dyuproject.protostuff;
import java.lang.reflect.Field;
import java.util.HashMap;
/**
* Metadata that is (re)used for enum serialization.
*
* @author David Yu
* @created Apr 26, 2023
*/
public final class EnumMapping
{
public static > EnumMapping createFrom(Class clazz, T[] values)
{
return getFrom(clazz, values);
}
public static EnumMapping getOrCreateFrom(Class> clazz)
{
return getFrom(clazz, null);
}
@SuppressWarnings({ "unchecked" })
private static EnumMapping getFrom(final Class> clazz, final Enum>[] values)
{
final Class extends Enum>> enumClass = (Class extends Enum>>)clazz;
final Enum>[] constants = values != null ? values : enumClass.getEnumConstants();
Enum> instance = constants[0];
Field field = null;
EnumMapping mapping = null;
if (values == null && EnumLite.class.isAssignableFrom(instance.getClass()))
{
try
{
field = enumClass.getDeclaredField("$MAPPING");
mapping = (EnumMapping)field.get(null);
}
catch (Exception e)
{
// noop
}
if (mapping != null)
return mapping;
}
try
{
field = enumClass.getField(instance.name());
}
catch (NoSuchFieldException e)
{
throw new RuntimeException(e);
}
if (!field.isAnnotationPresent(Tag.class))
return null;
final HashMap numberIdxMap = new HashMap();
final int[] numbers = new int[constants.length];
final HashMap nameIdxMap = new HashMap();
final String[] names = new String[constants.length];
Integer tmp;
int fieldNumber;
String name;
for (int i = 0, idx = i;; idx = i)
{
Tag annotation = field.getAnnotation(Tag.class);
fieldNumber = annotation.value();
name = annotation.alias();
if (name == null || name.isEmpty())
name = instance.name();
// support multiple name aliasing with the same number
tmp = fieldNumber;
if (numberIdxMap.containsKey(tmp))
idx = numberIdxMap.get(tmp).intValue();
else
numberIdxMap.put(fieldNumber, i);
if (null != (tmp = nameIdxMap.put(name, idx)))
{
throw new IllegalStateException(constants[tmp.intValue()] + " and " +
constants[i] + " cannot have the same alias/name.");
}
numbers[i] = fieldNumber;
names[i] = i == idx ? name : names[idx];
if (constants.length == ++i)
break;
instance = constants[i];
try
{
field = enumClass.getField(instance.name());
}
catch (NoSuchFieldException e)
{
throw new RuntimeException(e);
}
if (!field.isAnnotationPresent(Tag.class))
throw new RuntimeException("Missing @Tag annotation: " + field);
}
return new EnumMapping(numberIdxMap, numbers, nameIdxMap, names);
}
public final HashMap numberIdxMap;
public final int[] numbers;
public final HashMap nameIdxMap;
public final String[] names;
EnumMapping(HashMap numberIdxMap, int[] numbers,
HashMap nameIdxMap, String[] names)
{
this.numberIdxMap = numberIdxMap;
this.numbers = numbers;
this.nameIdxMap = nameIdxMap;
this.names = names;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy