All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kalix.javasdk.impl.ProtoDescriptorRenderer.scala Maven / Gradle / Ivy

There is a newer version: 1.4.1
Show newest version
/*
 * Copyright 2021 Lightbend Inc.
 *
 * 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 kalix.javasdk.impl

import scala.collection.mutable

import com.google.protobuf.DescriptorProtos.FieldDescriptorProto
import com.google.protobuf.Descriptors.FileDescriptor

object ProtoDescriptorRenderer {

  def toString(fileDescriptor: FileDescriptor): String = {
    // not water tight but better than the default non-protobuf Proto-toString format
    val proto = fileDescriptor.toProto
    val builder = new mutable.StringBuilder()
    builder ++= s"""syntax = "${fileDescriptor.getSyntax.name().toLowerCase}";\n\n"""

    builder ++= "package "
    builder ++= fileDescriptor.getPackage + ";\n\n"

    fileDescriptor.getDependencies.forEach { deps =>
      builder ++= s"""import "${deps.getFullName}";\n"""
    }
    builder ++= "\n"

    if (proto.hasOptions) {
      proto.getOptions.getAllFields.forEach { (option, value) =>
        builder ++= "  option ("
        builder ++= option.getFullName
        builder ++= ") = {\n"
        value.toString.split("\n").foreach { optionLine =>
          val indent = optionLine.count(_ == ' ') / 4
          builder ++= "    "
          builder ++= (" " * indent)
          builder ++= optionLine.replace("^[ ]*", "")
          builder ++= "\n"
        }
        builder ++= "    };\n"
      }
    }

    proto.getMessageTypeList.forEach { messageType =>
      builder ++= "message "
      builder ++= messageType.getName
      builder ++= " {\n"
      messageType.getFieldList.forEach { field =>
        builder ++= "  "
        if (field.getLabel == FieldDescriptorProto.Label.LABEL_REPEATED)
          builder ++= "repeated "
        else if (field.getLabel == FieldDescriptorProto.Label.LABEL_REQUIRED)
          builder ++= "required "
        else if (field.getProto3Optional)
          builder ++= "optional "
        if (field.hasTypeName)
          builder ++= field.getTypeName
        else
          builder ++= field.getType.name().toLowerCase.drop(5)
        builder ++= " "
        builder ++= field.getName
        builder ++= " = ";
        builder ++= field.getNumber.toString
        if (field.hasOptions) {
          field.getOptions.getAllFields.forEach { (option, value) =>
            builder ++= " [("
            builder ++= option.getFullName
            builder ++= ")."
            builder ++= value.toString.replace("\n", "").replace(':', '=')
            builder ++= "]"
          }
        }
        builder ++= ";\n"
      }
      builder ++= "}\n\n"
    }
    proto.getServiceList.forEach { service =>
      builder ++= "service "
      builder ++= service.getName
      builder ++= " {\n"
      if (service.hasOptions) {
        service.getOptions.getAllFields.forEach { (option, value) =>
          builder ++= "  option ("
          builder ++= option.getFullName
          builder ++= ") = {\n"
          value.toString.split("\n").foreach { optionLine =>
            val indent = optionLine.count(_ == ' ') / 4
            builder ++= "    "
            builder ++= (" " * indent)
            builder ++= optionLine.replace("^[ ]*", "")
            builder ++= "\n"
          }
          builder ++= "    };\n"
        }
      }

      service.getMethodList.forEach { method =>
        builder ++= "  rpc "
        builder ++= method.getName
        builder ++= "("
        if (method.getClientStreaming) builder ++= "stream "
        builder ++= method.getInputType
        builder ++= ") returns ("
        if (method.getServerStreaming) builder ++= "stream "
        builder ++= method.getOutputType
        builder ++= ") "
        if (method.hasOptions) {
          builder ++= "{\n"
          method.getOptions.getAllFields.forEach { (option, value) =>
            builder ++= "    option ("
            builder ++= option.getFullName
            builder ++= ") = {\n"
            value.toString.split("\n").foreach { optionLine =>
              val indent = optionLine.count(_ == ' ') / 4
              builder ++= "      "
              builder ++= (" " * indent)
              builder ++= optionLine.replace("^[ ]*", "")
              builder ++= "\n"
            }
            builder ++= "    };\n"
          }
          builder ++= "  }\n"
        } else builder ++= "{}\n\n"
      }
      builder ++= "}\n\n"
    }
    builder.toString()
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy