I was looking for a similar functionality.
One thing that i noticed probably comments in proto are missed out while 
printing DebugString?

On Thursday, 19 May 2011 21:13:15 UTC+8, Ben Wright wrote:
>
> previous thread: 
>
> http://groups.google.com/group/protobuf/browse_thread/thread/4bf8bca8c88e82ba/dbaa2803984f3934?lnk=gst&q=debugString()#dbaa2803984f3934
>  
>
> On May 18, 6:05 pm, Ben Wright <[email protected]> wrote: 
> > There has been some back and forth previously about java language 
> > support for generating a proto file from a Descriptor. 
> > 
> > The suggested implementation was to either wrap or port the 
> > DebugString capability from decriptor.cc 
> > 
> > I recently ported the DebugString capability to java - it's a bit 
> > rough as it's a by-hand port from the c code, but I also fixed some 
> > bugs in the way the file was generated.  For instance, extended types 
> > were not output with correct parenthesis around them and options that 
> > were messages did not have appropriate {} around them - these could 
> > easily be due to differences in the C and Java code though.  I'd be 
> > glad to elaborate further for anyone interested, but for now I'm 
> > simply providing the ported code as static functions in a java file. 
> > Notably, if integrated with the java library these functions should 
> > probably not be in a static file, they should be included with their 
> > appropriate descriptor types. 
> > 
> > If it is decided that this functionality should be part of the Java 
> > library, I would be willing to do the leg work and get these functions 
> > in better shape and update the appropriate files.  I can pass them 
> > along in an issue report for a committer to check in. 
> > 
> > Notably, if you're looking for someone to work on the Java library / 
> > outstanding issues at all, I'm looking for something to do in my 
> > mythical free time.  I could help with c too, but I'm much stronger in 
> > Java. 
> > 
> > PS: This is all based on release 2.4.1 
> > 
> > ======================= DebugString.java =================== 
> > 
> > import java.io.IOException; 
> > import java.util.ArrayList; 
> > import java.util.HashSet; 
> > import java.util.List; 
> > import java.util.Set; 
> > import java.util.Stack; 
> > 
> > import com.google.protobuf.Descriptors.Descriptor; 
> > import com.google.protobuf.Descriptors.EnumDescriptor; 
> > import com.google.protobuf.Descriptors.EnumValueDescriptor; 
> > import com.google.protobuf.Descriptors.FieldDescriptor; 
> > import com.google.protobuf.Descriptors.FileDescriptor; 
> > import com.google.protobuf.Descriptors.MethodDescriptor; 
> > import com.google.protobuf.Descriptors.ServiceDescriptor; 
> > import com.google.protobuf.Message; 
> > import com.google.protobuf.TextFormat; 
> > 
> > /** 
> >  * This class provides .proto file generation from Java Proto 
> > Descriptors. 
> >  * <br>Derived from descriptor.cc in Protobuf 2.4.1 
> >  * <br> 
> >  * <br><b>Original Copyright Notice from descriptor.cc:</b> 
> >  * <br> 
> >  * <br> Protocol Buffers - Google's data interchange format 
> >  * <br> Copyright 2008 Google Inc.  All rights reserved. 
> >  * <br>http://code.google.com/p/protobuf/ 
> >  * <br> 
> >  * <br> Redistribution and use in source and binary forms, with or 
> > without 
> >  * <br> modification, are permitted provided that the following 
> > conditions are 
> >  * <br> met: 
> >  * <br> 
> >  * <br>     * Redistributions of source code must retain the above 
> > copyright 
> >  * <br> notice, this list of conditions and the following disclaimer. 
> >  * <br>     * Redistributions in binary form must reproduce the above 
> >  * <br> copyright notice, this list of conditions and the following 
> > disclaimer 
> >  * <br> in the documentation and/or other materials provided with the 
> >  * <br> distribution. 
> >  * <br>     * Neither the name of Google Inc. nor the names of its 
> >  * <br> contributors may be used to endorse or promote products 
> > derived from 
> >  * <br> this software without specific prior written permission. 
> >  * <br> 
> >  * <br> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
> > CONTRIBUTORS 
> >  * <br> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
> > NOT 
> >  * <br> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
> > FITNESS FOR 
> >  * <br> A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
> > COPYRIGHT 
> >  * <br> OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
> > INCIDENTAL, 
> >  * <br> SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
> > NOT 
> >  * <br> LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
> > OF USE, 
> >  * <br> DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
> > ON ANY 
> >  * <br> THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
> > TORT 
> >  * <br> (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
> > THE USE 
> >  * <br> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
> > DAMAGE. 
> >  * <br> 
> >  * <br> Author: [email protected] (Kenton Varda) 
> >  * <br>  Based on original Protocol Buffers design by 
> >  * <br>  Sanjay Ghemawat, Jeff Dean, and others. 
> >  * 
> >  * @author Benjamin Wright ([email protected]) 
> >  */ 
> > public class DebugString { 
> > 
> >         private static void SubstituteAndAppend(StringBuilder contents, 
> > String replace, Object... objects ) { 
> >                 for(int i = 0; i < objects.length; i++) { 
> >                         final String old = "$"+i; 
> >                         replace = replace.replace(old, 
> String.valueOf(objects[i])); 
> >                 } 
> >                 contents.append(replace); 
> >         } 
> > 
> >         private static String PrintFieldValueToString(Message message, 
> >                         FieldDescriptor fieldDescriptor, int i) { 
> >                 return valueAsString(fieldDescriptor, 
> > message.getField(fieldDescriptor)); 
> >         } 
> > 
> >         private static String DefaultValueAsString(FieldDescriptor 
> > fieldDescriptor, boolean b) { 
> >                 return valueAsString(fieldDescriptor, 
> > fieldDescriptor.getDefaultValue()); 
> >         } 
> > 
> >         private static String valueAsString(FieldDescriptor 
> fieldDescriptor, 
> > Object value) { 
> >                 StringBuilder v = new StringBuilder(); 
> >                 try { 
> >                         TextFormat.printFieldValue(fieldDescriptor, 
> value, v); 
> >                 } catch (IOException e) { 
> >                 } 
> >                 return v.toString();//.replace("\n", "").replace("\\", 
> "\\\\"); 
> >         } 
> > 
> >         private static String prefix(int d, char str) { 
> >                 StringBuilder sb = new StringBuilder(); 
> > 
> >                 for(int i = 0; i < d; i++) 
> >                         sb.append(str); 
> > 
> >                 return sb.toString(); 
> >         } 
> > 
> >         private static String join(Stack<String> all_options, String 
> string) 
> > { 
> >                 boolean init = true; 
> >                 StringBuilder sb = new StringBuilder(); 
> >                 for(String option : all_options) { 
> >                         if(init) { 
> >                                 init = false; 
> >                         } else { 
> >                                 sb.append(string); 
> >                         } 
> >                         sb.append(option); 
> >                 } 
> >                 return sb.toString(); 
> >         } 
> > 
> >         // DebugString methods 
> > =============================================== 
> > 
> >         // Used by each of the option formatters. 
> >         static boolean RetrieveOptions(final Message options, 
> Stack<String> 
> > option_entries) { 
> >           option_entries.clear(); 
> >           List<FieldDescriptor> fields = new 
> > ArrayList<FieldDescriptor>(options.getAllFields().keySet()); 
> >           for (int i = 0; i < fields.size(); i++) { 
> > 
> >             int count = 1; 
> >             boolean repeated = false; 
> >             if (fields.get(i).isRepeated()) { 
> >               count = options.getRepeatedFieldCount(fields.get(i)); 
> >               repeated = true; 
> >             } 
> >             for (int j = 0; j < count; j++) { 
> >               String fieldval = 
> >               PrintFieldValueToString(options, fields.get(i), 
> >                           repeated ? count : -1); 
> > 
> > //            .replace("google.protobuf.FileOptions.", "") 
> > 
> >                 final boolean msg = (fields.get(i).getJavaType() == 
> > FieldDescriptor.JavaType.MESSAGE); 
> > 
> >               final String fullName = fields.get(i).getFullName(); 
> >               option_entries.push( 
> >                           (fields.get(i).isExtension() ? "(" : "") + 
> >                           (fullName.startsWith("google.protobuf.") ? 
> > fullName.substring(fullName.lastIndexOf('.')+1): fullName) + 
> >                           (fields.get(i).isExtension() ? ")" : "") + 
> >                           " = " + 
> >                           (msg?"{\n":"") + 
> >                           "  "+ fieldval + 
> >                           (msg?"}":"") ); 
> >             } 
> >           } 
> >           return !option_entries.isEmpty(); 
> >         } 
> > 
> >         // Formats options that all appear together in brackets. Does 
> not 
> > include 
> >         // brackets. 
> >         static boolean FormatBracketedOptions(final Message options, 
> > StringBuilder output) { 
> >           Stack<String> all_options = new Stack<String>(); 
> >           if (RetrieveOptions(options, all_options)) { 
> >             output.append(join(all_options, ",\n")); 
> >           } 
> >           return !all_options.isEmpty(); 
> >         } 
> > 
> >         // Formats options one per line 
> >         static boolean FormatLineOptions(int depth, final Message 
> options, 
> > StringBuilder output) { 
> >           String prefix = prefix(depth * 2, ' '); 
> >           Stack<String> all_options = new Stack<String>(); 
> >           if (RetrieveOptions(options, all_options)) { 
> >             for (int i = 0; i < all_options.size(); i++) { 
> >               SubstituteAndAppend(output, "$0option $1;\n", 
> >                                            prefix, all_options.get(i)); 
> >             } 
> >           } 
> >           return !all_options.isEmpty(); 
> >         } 
> > 
> > //      }  // anonymous namespace 
> > 
> >         /** 
> >          * Top level return function 
> >          */ 
> >         static public StringBuilder 
> FileDescriptor_DebugString(FileDescriptor 
> > fd) { 
> >                 return FileDescriptor_DebugString(fd, false); 
> >         } 
> >         /** 
> >          * Top level return function 
> >          */ 
> >         static public StringBuilder 
> FileDescriptor_DebugString(FileDescriptor 
> > fd, boolean includeProtocolSyntaxVersion) { 
> >           StringBuilder contents = new StringBuilder(); 
> > 
> >           if(includeProtocolSyntaxVersion) { 
> >                   contents.append("syntax = \"proto2\";\n\n"); 
> >           } 
> > 
> >           if (!fd.getPackage().isEmpty()) { 
> >             SubstituteAndAppend(contents, "package $0;\n\n", 
> > fd.getPackage()); 
> >           } 
> > 
> >           for (FileDescriptor dependency : fd.getDependencies()) { 
> >             SubstituteAndAppend(contents, "import \"$0\";\n", 
> >                                          dependency.getName()); 
> >           } 
> > 
> >           if(!fd.getDependencies().isEmpty()){ 
> >                   contents.append("\n"); 
> >           } 
> > 
> >           if (FormatLineOptions(0, fd.getOptions(), contents)) { 
> >             contents.append("\n");  // add some space if we had options 
> >           } 
> > 
> >           for (EnumDescriptor enum_type : fd.getEnumTypes()) { 
> >                 EnumDescriptor_DebugString(enum_type, 0, contents); 
> >             contents.append("\n"); 
> >           } 
> > 
> >           // Find all the 'group' type extensions; we will not output 
> their 
> > nested 
> >           // definitions (those will be done with their group field 
> > descriptor). 
> >           Set<Descriptor> groups = new HashSet<Descriptor>(); 
> >           for (FieldDescriptor extension : fd.getExtensions()) { 
> >             if (extension.getType() == FieldDescriptor.Type.GROUP) { 
> >               groups.add(extension.getMessageType()); 
> >             } 
> >           } 
> > 
> >           for (Descriptor message_type : fd.getMessageTypes()) { 
> >             if (!groups.contains(message_type)) { 
> >               SubstituteAndAppend(contents, "message $0", 
> >                                            message_type.getName()); 
> >               Descriptor_DebugString(message_type, 0, contents); 
> >               contents.append("\n"); 
> >             } 
> >           } 
> > 
> >           for (ServiceDescriptor service : fd.getServices()) { 
> >                   ServiceDescriptor_DebugString(service, contents); 
> >             contents.append("\n"); 
> >           } 
> > 
> >           Descriptor containing_type = null; 
> >           for (FieldDescriptor extension : fd.getExtensions()) { 
> >             if (extension.getContainingType() != containing_type) { 
> >               if (containing_type != null) contents.append("}\n\n"); 
> >               containing_type = extension.getContainingType(); 
> >               SubstituteAndAppend(contents, "extend $0 {\n", 
> >                                           
>  containing_type.getFullName()); 
> >             } 
> >             FieldDescriptor_DebugString(extension, 1, contents); 
> >           } 
> >           if (fd.getExtensions().size() > 0) contents.append("}\n\n"); 
> > 
> >           return contents; 
> >         } 
> > 
> >         static public StringBuilder Descriptor_DebugString(Descriptor d) 
> { 
> >           StringBuilder contents = new StringBuilder(); 
> >           SubstituteAndAppend(contents, "message $0", d.getName()); 
> >           Descriptor_DebugString(d, 0, contents); 
> >           return contents; 
> >         } 
> > 
> >         static void Descriptor_DebugString(Descriptor d, int depth, 
> > StringBuilder contents) { 
> >           String prefix = prefix(depth * 2, ' '); 
> >           ++depth; 
> >           contents.append(" {\n"); 
> > 
> >           FormatLineOptions(depth, d.getOptions(), contents); 
> > 
> >           // Find all the 'group' types for fields and extensions; we 
> will 
> > not output 
> >           // their nested definitions (those will be done with their 
> group 
> > field 
> >           // descriptor). 
> >           Set<Descriptor> groups = new HashSet<Descriptor>(); 
> >           for (int i = 0; i < d.getFields().size(); i++) { 
> >             if (d.getFields().get(i).getType() == 
> FieldDescriptor.Type.GROUP) 
> > { 
> >               groups.add(d.getFields().get(i).getMessageType()); 
> >             } 
> >           } 
> >           for (int i = 0; i < d.getExtensions().size(); i++) { 
> >             if (d.getExtensions().get(i).getType() == 
> > FieldDescriptor.Type.GROUP) { 
> >               groups.add(d.getExtensions().get(i).getMessageType()); 
> >             } 
> >           } 
> > 
> >           for (int i = 0; i < d.getNestedTypes().size(); i++) { 
> >             if (!groups.contains(d.getNestedTypes().get(i))) { 
> >               SubstituteAndAppend(contents, "$0  message $1", 
> >                                            prefix, 
> > d.getNestedTypes().get(i).getName()); 
> >               Descriptor_DebugString(d.getNestedTypes().get(i), depth, 
> > contents); 
> >             } 
> >           } 
> >           for (int i = 0; i < d.getEnumTypes().size(); i++) { 
> >             EnumDescriptor_DebugString(d.getEnumTypes().get(i), depth, 
> > contents); 
> >           } 
> >           for (int i = 0; i < d.getFields().size(); i++) { 
> >             FieldDescriptor_DebugString(d.getFields().get(i), depth, 
> > contents); 
> >           } 
> > 
> >           final int max = 536870911; 
> > 
> >           for (int i = 0; i < d.toProto().getExtensionRangeCount(); i++) 
> { 
> >                   final int end = 
> d.toProto().getExtensionRange(i).getEnd() - 1; 
> >             SubstituteAndAppend(contents, "$0  extensions $1 to $2;\n", 
> >                                          prefix, 
> > 
> > d.toProto().getExtensionRange(i).getStart(), 
> >                                          (end == max ? "max" : end) 
> >                                          ); 
> >           } 
> > 
> >           // Group extensions by what they extend, so they can be 
> printed out 
> > together. 
> >           Descriptor containing_type = null; 
> >           for (int i = 0; i < d.getExtensions().size(); i++) { 
> >             if (d.getExtensions().get(i).getContainingType() != 
> > containing_type) { 
> >               if (i > 0) SubstituteAndAppend(contents, "$0  }\n", 
> prefix); 
> >               containing_type = 
> d.getExtensions().get(i).getContainingType(); 
> >               SubstituteAndAppend(contents, "$0  extend .$1 {\n", 
> >                                            prefix, 
> > containing_type.getFullName()); 
> >             } 
> >             FieldDescriptor_DebugString(d.getExtensions().get(i), depth 
> + 1, 
> > contents); 
> >           } 
> >           if (d.getExtensions().size() > 0) 
> >             SubstituteAndAppend(contents, "$0  }\n", prefix); 
> > 
> >           SubstituteAndAppend(contents, "$0}\n", prefix); 
> >         } 
> > 
> >         static public StringBuilder 
> > FieldDescriptor_DebugString(FieldDescriptor d) { 
> >           StringBuilder contents = new StringBuilder(); 
> >           int depth = 0; 
> >           if (d.isExtension()) { 
> >             SubstituteAndAppend(contents, "extend .$0 {\n", 
> > 
> > d.getContainingType().getFullName()); 
> >             depth = 1; 
> >           } 
> >           FieldDescriptor_DebugString(d, depth, contents); 
> >           if (d.isExtension()) { 
> >              contents.append("}\n"); 
> >           } 
> >           return contents; 
> >         } 
> > 
> >         static void FieldDescriptor_DebugString(FieldDescriptor d, int 
> depth, 
> > StringBuilder contents) { 
> >                 final String pckg = d.getFile().getPackage(); 
> >           String prefix = prefix(depth * 2, ' '); 
> >           String field_type; 
> >           switch (d.getType()) { 
> >             case MESSAGE: 
> >               field_type = 
> > d.getMessageType().getFile().getPackage().equals(pckg) ? 
> > d.getMessageType().getName() : d.getMessageType().getFullName(); 
> >               break; 
> >             case ENUM: 
> >               field_type = 
> > d.getEnumType().getFile().getPackage().equals(pckg) ? 
> > d.getEnumType().getName() : d.getEnumType().getFullName(); 
> >               break; 
> >             default: 
> >               field_type = d.getType().name().toLowerCase(); 
> >           } 
> > 
> >           final String label; 
> >           switch(d.toProto().getLabel()){ 
> >           case LABEL_OPTIONAL: 
> >           default: 
> >                   label = "optional"; 
> >                   break; 
> >           case LABEL_REPEATED: 
> >                   label = "repeated"; 
> >                   break; 
> >           case LABEL_REQUIRED: 
> >                   label = "required"; 
> >                   break; 
> >           } 
> > 
> >           SubstituteAndAppend(contents, "$0$1 $2 $3 = $4", 
> >                                        prefix, 
> >                                        label, 
> >                                        field_type, 
> >                                        d.getType() == 
> > FieldDescriptor.Type.GROUP ? d.getMessageType().getName() : 
> >                                                               
> d.getName(), 
> >                                        d.getNumber()); 
> > 
> >           boolean bracketed = false; 
> >           if (d.hasDefaultValue()) { 
> >             bracketed = true; 
> >             SubstituteAndAppend(contents, " [default = $0", 
> >                                          DefaultValueAsString(d, true)); 
> >           } 
> > 
> >           StringBuilder formatted_options = new StringBuilder(); 
> >           if (FormatBracketedOptions(d.getOptions(), formatted_options)) 
> { 
> >             contents.append(bracketed ? ", " : " ["); 
> >             bracketed = true; 
> >             contents.append(formatted_options); 
> >           } 
> > 
> >           if (bracketed) { 
> >             contents.append("]"); 
> >           } 
> > 
> >           if (d.getType() == FieldDescriptor.Type.GROUP) { 
> >             Descriptor_DebugString(d.getMessageType(), depth, contents); 
> >           } else { 
> >             contents.append(";\n"); 
> >           } 
> >         } 
> > 
> >         static public StringBuilder 
> EnumDescriptor_DebugString(EnumDescriptor 
> > d) { 
> >           StringBuilder contents = new StringBuilder(); 
> >           EnumDescriptor_DebugString(d, 0, contents); 
> >           return contents; 
> >         } 
> > 
> >         static void EnumDescriptor_DebugString(EnumDescriptor d, int 
> depth, 
> > StringBuilder contents) { 
> >           String prefix = prefix(depth * 2, ' '); 
> >           ++depth; 
> >           SubstituteAndAppend(contents, "$0enum $1 {\n", 
> >                                        prefix, d.getName()); 
> > 
> >           FormatLineOptions(depth, d.getOptions(), contents); 
> > 
> >           for (EnumValueDescriptor value : d.getValues()) { 
> >                   EnumValueDescriptor_DebugString(value, depth, 
> contents); 
> >           } 
> >           SubstituteAndAppend(contents, "$0}\n", prefix); 
> >         } 
> > 
> >         static public StringBuilder 
> > EnumValueDescriptor_DebugString(EnumValueDescriptor d) { 
> >           StringBuilder contents = new StringBuilder(); 
> >           EnumValueDescriptor_DebugString(d, 0, contents); 
> >           return contents; 
> >         } 
> > 
> >         static void EnumValueDescriptor_DebugString(EnumValueDescriptor 
> d, 
> > int depth, StringBuilder contents) { 
> >           String prefix = prefix(depth * 2, ' '); 
> >           SubstituteAndAppend(contents, "$0$1 = $2", 
> >                                        prefix, d.getName(), 
> d.getNumber()); 
> > 
> >           StringBuilder formatted_options = new StringBuilder(); 
> >           if (FormatBracketedOptions(d.getOptions(), formatted_options)) 
> { 
> >             SubstituteAndAppend(contents, " [$0]", formatted_options); 
> >           } 
> >           contents.append(";\n"); 
> >         } 
> > 
> >         static public StringBuilder 
> > ServiceDescriptor_DebugString(ServiceDescriptor d) { 
> >           StringBuilder contents = new StringBuilder(); 
> >           ServiceDescriptor_DebugString(d, contents); 
> >           return contents; 
> >         } 
> > 
> >         static void ServiceDescriptor_DebugString(ServiceDescriptor d, 
> > StringBuilder contents) { 
> >           SubstituteAndAppend(contents, "service $0 {\n", d.getName()); 
> > 
> >           FormatLineOptions(1, d.getOptions(), contents); 
> > 
> >           for (MethodDescriptor method : d.getMethods()) { 
> >                   MethodDescriptor_DebugString(method, 1, contents); 
> >           } 
> > 
> >           contents.append("}\n"); 
> >         } 
> > 
> >         static public StringBuilder 
> > MethodDescriptor_DebugString(MethodDescriptor d) { 
> >           StringBuilder contents = new StringBuilder(); 
> >           MethodDescriptor_DebugString(d, 0, contents); 
> >           return contents; 
> >         } 
> > 
> >         static void MethodDescriptor_DebugString(MethodDescriptor d, int 
> > depth, StringBuilder contents) { 
> >           String prefix = prefix(depth * 2, ' '); 
> >           ++depth; 
> >           SubstituteAndAppend(contents, "$0rpc $1(.$2) returns (.$3)", 
> >                                        prefix, d.getName(), 
> >                                        d.getInputType().getFullName(), 
> >                                        d.getOutputType().getFullName()); 
> > 
> >           StringBuilder formatted_options = new StringBuilder(); 
> >           if (FormatLineOptions(depth, d.getOptions(), 
> formatted_options)) { 
> >             SubstituteAndAppend(contents, " {\n$0$1}\n", 
> >                                          formatted_options, prefix); 
> >           } else { 
> >             contents.append(";\n"); 
> >           } 
> >         } 
> >         // 
> > =================================================================== 
> > 
> > 
> > 
> > 
> > 
> > 
> > 
> > }

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.

Reply via email to