package com.github.protobufel.grammar; import java.util.LinkedHashSet; import java.util.Set; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor.JavaType; import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.DynamicMessage; import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.ExtensionRegistry.ExtensionInfo; /** * Utilities for ExtensionRegistry construction. * * @author protobufel@gmail.com David Tesler */ public class ExtensionRegistries { private ExtensionRegistries() {} /** * Finds extension by its containing type and the dot separated multi-part name. */ public static ExtensionInfo findExtensionByName(final ExtensionRegistry registry, final Descriptor containingType, final String name) { final int index = name.lastIndexOf("."); final String nameLastPart = index == -1 ? name : name.substring(index + 1); return registry.findImmutableExtensionByName(containingType.getFullName() + "." + nameLastPart); } /** * Builds a full unmodifiable, with dependencies, ExtensionRegistry for the given FileDescriptor. */ public static ExtensionRegistry buildFullRegistryOf(final FileDescriptor file) { return addWithDependeciesToRegistry(file, ExtensionRegistry.newInstance()).getUnmodifiable(); } /** * Adds all extensions, including dependencies, for the given FileDescriptor to the registry. */ public static ExtensionRegistry addWithDependeciesToRegistry(final FileDescriptor file, final ExtensionRegistry registry) { for (final FileDescriptor dependency : getFileWithAllDependencies(file)) { addToRegistry(dependency, registry); } return registry; } private static Iterable<FileDescriptor> getFileWithAllDependencies(final FileDescriptor file) { final Set<FileDescriptor> cache = new LinkedHashSet<FileDescriptor>(); cache.add(file); // we must follow the original ProtoBuf here! for (final FileDescriptor dependency : file.getDependencies()) { cache.add(dependency); addPublicDependencies(cache, dependency); } return cache; } private static void addPublicDependencies(final Set<FileDescriptor> cache, final FileDescriptor file) { for (final FileDescriptor dependency : file.getPublicDependencies()) { if (cache.add(dependency)) { addPublicDependencies(cache, dependency); } } } /** * Adds all extensions, without dependencies, for the given FileDescriptor to the registry. */ public static ExtensionRegistry addToRegistry(final FileDescriptor file, final ExtensionRegistry registry) { for (final FieldDescriptor extension : file.getExtensions()) { addToRegistry(extension, registry); } for (final Descriptor descriptor : file.getMessageTypes()) { addToRegistry(descriptor, registry); } return registry; } /** * Adds all extensions for the given Descriptor to the registry. */ public static ExtensionRegistry addToRegistry(final Descriptor descriptor, final ExtensionRegistry registry) { for (final FieldDescriptor extension : descriptor.getExtensions()) { addToRegistry(extension, registry); } for (final Descriptor child : descriptor.getNestedTypes()) { addToRegistry(child, registry); } return registry; } /** * Adds extension to the registry, making a default DynamicMessage if its type is a Message. */ public static ExtensionRegistry addToRegistry(final FieldDescriptor extension, final ExtensionRegistry registry) { if (extension.getJavaType() == JavaType.MESSAGE) { registry.add(extension, DynamicMessage.getDefaultInstance(extension.getMessageType())); } else { registry.add(extension); } return registry; } }