org.dozer.util.ProtoUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.dozer.util.ProtoUtils.java

Source

/*
 * Copyright 2005-2012 the original author or authors.
 *
 * 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 org.dozer.util;

import com.google.protobuf.ByteString;
import com.google.protobuf.Descriptors;
import com.google.protobuf.Message;
import com.google.protobuf.ProtocolMessageEnum;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author Dmitry Spikhalskiy
 */
public class ProtoUtils {
    public static Message.Builder getBuilder(Class<? extends Message> clazz) {
        final Message.Builder protoBuilder;
        try {
            Method newBuilderMethod = clazz.getMethod("newBuilder");
            protoBuilder = (Message.Builder) newBuilderMethod.invoke(null);
        } catch (Exception e) {
            MappingUtils.throwMappingException(e);
            return null;
        }

        return protoBuilder;
    }

    public static List<Descriptors.FieldDescriptor> getFieldDescriptors(Class<? extends Message> clazz) {
        Message.Builder protoBuilder = getBuilder(clazz);

        return getFieldDescriptors(protoBuilder);
    }

    public static List<Descriptors.FieldDescriptor> getFieldDescriptors(Message.Builder protoBuilder) {
        return protoBuilder.getDescriptorForType().getFields();
    }

    public static Descriptors.FieldDescriptor getFieldDescriptor(Class<? extends Message> clazz, String fieldName) {
        final List<Descriptors.FieldDescriptor> protoFieldDescriptors = getFieldDescriptors(clazz);

        Descriptors.FieldDescriptor foundDescriptor = null;
        for (Descriptors.FieldDescriptor descriptor : protoFieldDescriptors) {
            if (fieldName.equals(descriptor.getName())) {
                foundDescriptor = descriptor;
            }
        }

        return foundDescriptor;
    }

    public static Object getFieldValue(Message message, String fieldName) {
        Map<Descriptors.FieldDescriptor, Object> fieldsMap = message.getAllFields();
        for (Map.Entry<Descriptors.FieldDescriptor, Object> field : fieldsMap.entrySet()) {
            if (fieldName.equals(field.getKey().getName())) {
                return field.getValue();
            }
        }

        return null;
    }

    public static Class<?> getJavaClass(final Descriptors.FieldDescriptor descriptor) {
        if (descriptor.isRepeated())
            return List.class;
        return getJavaClassIgnoreRepeated(descriptor);
    }

    public static Class<?> getJavaGenericClassForCollection(final Descriptors.FieldDescriptor descriptor) {
        if (!descriptor.isRepeated())
            return null;
        return getJavaClassIgnoreRepeated(descriptor);
    }

    private static Class<?> getJavaClassIgnoreRepeated(final Descriptors.FieldDescriptor descriptor) {
        switch (descriptor.getJavaType()) {
        case INT:
            return Integer.class;
        case LONG:
            return Long.class;
        case FLOAT:
            return Float.class;
        case DOUBLE:
            return Double.class;
        case BOOLEAN:
            return Boolean.class;
        case STRING:
            return String.class;
        case BYTE_STRING:
            return ByteString.class;
        //code duplicate, but GenericDescriptor interface is private in protobuf
        case ENUM:
            return getEnumClassByEnumDescriptor(descriptor.getEnumType());
        case MESSAGE:
            return MappingUtils.loadClass(StringUtils
                    .join(new String[] { descriptor.getMessageType().getFile().getOptions().getJavaPackage(),
                            descriptor.getMessageType().getFile().getOptions().getJavaOuterClassname(),
                            descriptor.getMessageType().getFullName() }, '.'));
        default:
            throw new RuntimeException();
        }
    }

    private static Class<? extends Enum> getEnumClassByEnumDescriptor(Descriptors.EnumDescriptor descriptor) {
        return (Class<? extends Enum>) MappingUtils.loadClass(StringUtils.join(
                new String[] { descriptor.getFile().getOptions().getJavaPackage(),
                        descriptor.getFile().getOptions().getJavaOuterClassname(), descriptor.getFullName() },
                '.'));
    }

    public static Object wrapEnums(Object value) {
        if (value instanceof ProtocolMessageEnum) {
            return ((ProtocolMessageEnum) value).getValueDescriptor();
        }
        //there is no other collections using in proto, only list
        if (value instanceof List) {
            List modifiedList = new ArrayList(((List) value).size());
            for (Object element : (List) value) {
                modifiedList.add(wrapEnums(element));
            }
            return modifiedList;
        }
        return value;
    }

    public static Object unwrapEnums(Object value) {
        if (value instanceof Descriptors.EnumValueDescriptor) {
            Descriptors.EnumValueDescriptor descriptor = (Descriptors.EnumValueDescriptor) value;
            Class<? extends Enum> enumClass = getEnumClassByEnumDescriptor(descriptor.getType());
            Enum[] enumValues = enumClass.getEnumConstants();
            for (Enum enumValue : enumValues) {
                if (((Descriptors.EnumValueDescriptor) value).getName().equals(enumValue.name()))
                    return enumValue;
            }
            return null;
        }
        if (value instanceof Collection) {
            List modifiedList = new ArrayList(((List) value).size());
            for (Object element : (List) value) {
                modifiedList.add(unwrapEnums(element));
            }
            return modifiedList;
        }
        return value;
    }
}