Package org.infinispan.protostream.descriptors

Source Code of org.infinispan.protostream.descriptors.FileDescriptor$Builder

package org.infinispan.protostream.descriptors;

import org.infinispan.protostream.DescriptorParserException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.Collections.unmodifiableList;

/**
* Representation of a protofile, including dependencies
*
* @author gustavonalle
* @since 2.0
*/
public final class FileDescriptor {

   private final String name;
   private final String packageName;
   private final String fullName;
   private final List<FileDescriptor> dependencies;
   private final List<Option> options;
   private final List<Descriptor> messageTypes;
   private final List<FieldDescriptor> extensions;
   private final List<EnumDescriptor> enumTypes;
   private final List<ExtendDescriptor> extendTypes;
   private final Map<String, ExtendDescriptor> extendDescriptors = new HashMap<>();
   private final Map<String, Object> typeRegistry = new HashMap<>();

   private FileDescriptor(Builder builder) {
      this.name = builder.name;
      this.packageName = builder.packageName;
      this.dependencies = builder.dependencies;
      this.options = unmodifiableList(builder.options);
      this.enumTypes = unmodifiableList(builder.enumTypes);
      this.messageTypes = unmodifiableList(builder.messageTypes);
      this.extensions = builder.extensions;
      this.extendTypes = unmodifiableList(builder.extendDescriptors);
      this.fullName = getScopedName(name);

      for (FileDescriptor dep : dependencies) {
         typeRegistry.putAll(dep.typeRegistry);
      }
      collectTypes();
      wireInternalReferences();
     
   }

   private void collectTypes() {
      for (Descriptor desc : messageTypes) {
         collectDescriptors(desc);
      }
      for (EnumDescriptor enumDesc : enumTypes) {
         collectEnumDescriptors(enumDesc);
      }
      for (ExtendDescriptor extendDescriptor : extendTypes) {
         collectExtensions(extendDescriptor);
      }
   }

   private void collectDescriptors(Descriptor descriptor) {
      typeRegistry.put(descriptor.getFullName(), descriptor);
      for (EnumDescriptor enumDescriptor : descriptor.getEnumTypes()) {
         enumDescriptor.setFileDescriptor(this);
         typeRegistry.put(enumDescriptor.getFullName(), enumDescriptor);
      }
      for (Descriptor nested : descriptor.getNestedTypes()) {
         collectDescriptors(nested);
      }
   }

   private void collectEnumDescriptors(EnumDescriptor enumDesc) {
      typeRegistry.put(enumDesc.getFullName(), enumDesc);
   }

   private void collectExtensions(ExtendDescriptor extendDescriptor) {
      extendDescriptors.put(extendDescriptor.getFullName(), extendDescriptor);
   }

   private void wireDescriptor(Descriptor descriptor) {
      descriptor.setFileDescriptor(this);
      for (FieldDescriptor fieldDescriptor : descriptor.getFields()) {
         fieldDescriptor.setContainingMessage(descriptor);
         fieldDescriptor.setFileDescriptor(this);
         if (fieldDescriptor.getType() == null) {
            Object res = searchType(fieldDescriptor.getTypeName(), descriptor);
            if (res instanceof EnumDescriptor) {
               fieldDescriptor.setType(Type.ENUM);
               fieldDescriptor.setEnumDescriptor((EnumDescriptor) res);
            } else if (res instanceof Descriptor) {
               fieldDescriptor.setType(Type.MESSAGE);
               fieldDescriptor.setMessageType((Descriptor) res);
            } else {
               throw new DescriptorParserException("Field type " + fieldDescriptor.getTypeName() + " not found");
            }
         }
      }

      for (Descriptor nested : descriptor.getNestedTypes()) {
         wireDescriptor(nested);
      }
   }

   private void wireInternalReferences() {
      for (Descriptor descriptor : messageTypes) {
         wireDescriptor(descriptor);
         for (Descriptor nested : descriptor.getNestedTypes()) {
            wireDescriptor(nested);
         }
      }
      for (EnumDescriptor enumDescriptor : enumTypes) {
         enumDescriptor.setFileDescriptor(this);
      }
      for (ExtendDescriptor extendDescriptor : extendTypes) {
         extendDescriptor.setFileDescriptor(this);
         Object res = searchType(extendDescriptor.getName(), null);
         if (res == null) {
            throw new DescriptorParserException("Extension error: type " + extendDescriptor.getName() + " not found");
         }
         extendDescriptor.setExtendedMessage((Descriptor) res);
      }
   }

   private String getScopedName(String name) {
      if (packageName == null) return name;
      return packageName.concat(".").concat(name);
   }

   private Object searchType(String name, Descriptor scope) {
      Object fullyQualified = typeRegistry.get(getScopedName(name));
      if (fullyQualified != null) {
         return fullyQualified;
      }
      Object relativeName = typeRegistry.get(name);
      if (relativeName != null) {
         return relativeName;
      }
      String scoped = scope.getFullName();
      String searchScope = scoped.concat(".").concat(name);
      Object o = typeRegistry.get(searchScope);
      if (o != null) {
         return o;
      }
      Descriptor containingType = scope.getContainingType();

      while (containingType != null) {
         Object res = searchType(name, containingType);
         if (res != null) {
            return res;
         }
         containingType = containingType.getContainingType();
      }

      return null;

   }

   public String getName() {
      return name;
   }

   public String getPackage() {
      return packageName;
   }

   public List<Option> getOptions() {
      return options;
   }

   public List<EnumDescriptor> getEnumTypes() {
      return enumTypes;
   }

   public List<Descriptor> getMessageTypes() {
      return messageTypes;
   }

   public List<ExtendDescriptor> getExtensionsTypes() {
      return extendTypes;
   }

   public String getFullName() {
      return fullName;
   }

   public static final class Builder {

      String name, packageName;
      List<FileDescriptor> dependencies = new ArrayList<>();
      List<FieldDescriptor> extensions;
      List<Option> options;
      List<EnumDescriptor> enumTypes;
      List<Descriptor> messageTypes;
      List<ExtendDescriptor> extendDescriptors;

      public Builder withName(String name) {
         this.name = name;
         return this;
      }

      public Builder withPackageName(String packageName) {
         this.packageName = packageName;
         return this;
      }

      public Builder withDependencies(List<FileDescriptor> dependencies) {
         this.dependencies = dependencies;
         return this;
      }

      public Builder withExtendDescriptors(List<ExtendDescriptor> extendDescriptors) {
         this.extendDescriptors = extendDescriptors;
         return this;
      }

      public Builder withOptions(List<Option> options) {
         this.options = options;
         return this;
      }

      public Builder withEnumTypes(List<EnumDescriptor> enumTypes) {
         this.enumTypes = enumTypes;
         return this;
      }

      public Builder withMessageTypes(List<Descriptor> messageTypes) {
         this.messageTypes = messageTypes;
         return this;
      }

      public FileDescriptor build() {
         return new FileDescriptor(this);
      }

   }

}
TOP

Related Classes of org.infinispan.protostream.descriptors.FileDescriptor$Builder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.