001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.fusesource.hawtbuf.proto.compiler;
018
019 import static org.fusesource.hawtbuf.proto.WireFormat.WIRETYPE_FIXED32;
020 import static org.fusesource.hawtbuf.proto.WireFormat.WIRETYPE_FIXED64;
021 import static org.fusesource.hawtbuf.proto.WireFormat.WIRETYPE_LENGTH_DELIMITED;
022 import static org.fusesource.hawtbuf.proto.WireFormat.WIRETYPE_VARINT;
023 import static org.fusesource.hawtbuf.proto.WireFormat.makeTag;
024
025 import java.io.File;
026 import java.io.FileInputStream;
027 import java.io.FileNotFoundException;
028 import java.io.FileOutputStream;
029 import java.io.PrintWriter;
030 import java.util.ArrayList;
031 import java.util.HashSet;
032 import java.util.LinkedHashMap;
033 import java.util.Map;
034 import java.util.StringTokenizer;
035
036 import org.fusesource.hawtbuf.proto.compiler.parser.ParseException;
037 import org.fusesource.hawtbuf.proto.compiler.parser.ProtoParser;
038
039 public class AltJavaGenerator {
040
041 private File out = new File(".");
042 private File[] path = new File[]{new File(".")};
043
044 private ProtoDescriptor proto;
045 private String javaPackage;
046 private String outerClassName;
047 private PrintWriter w;
048 private int indent;
049 private ArrayList<String> errors = new ArrayList<String>();
050 private boolean multipleFiles;
051 private boolean auto_clear_optional_fields;
052
053 private String factoryFeild = "FACTORY";
054 private String getterCN = "Getter";
055 private String beanCN = "Bean";
056 private String bufferCN = "Buffer";
057
058 public static void main(String[] args) {
059
060 AltJavaGenerator generator = new AltJavaGenerator();
061 args = CommandLineSupport.setOptions(generator, args);
062
063 if (args.length == 0) {
064 System.out.println("No proto files specified.");
065 }
066 for (int i = 0; i < args.length; i++) {
067 try {
068 System.out.println("Compiling: " + args[i]);
069 generator.compile(new File(args[i]));
070 } catch (CompilerException e) {
071 System.out.println("Protocol Buffer Compiler failed with the following error(s):");
072 for (String error : e.getErrors()) {
073 System.out.println("");
074 System.out.println(error);
075 }
076 System.out.println("");
077 System.out.println("Compile failed. For more details see error messages listed above.");
078 return;
079 }
080 }
081
082 }
083
084 interface Closure {
085 void execute() throws CompilerException;
086 }
087
088 public void compile(File file) throws CompilerException {
089
090 // Parse the proto file
091 FileInputStream is = null;
092 try {
093 is = new FileInputStream(file);
094 ProtoParser parser = new ProtoParser(is);
095 proto = parser.ProtoDescriptor();
096 proto.setName(file.getName());
097 loadImports(proto, file.getParentFile());
098 proto.validate(errors);
099 } catch (FileNotFoundException e) {
100 errors.add("Failed to open: " + file.getPath() + ":" + e.getMessage());
101 } catch (ParseException e) {
102 errors.add("Failed to parse: " + file.getPath() + ":" + e.getMessage());
103 } finally {
104 try {
105 is.close();
106 } catch (Throwable ignore) {
107 }
108 }
109
110 if (!errors.isEmpty()) {
111 throw new CompilerException(errors);
112 }
113
114 // Load the options..
115 javaPackage = javaPackage(proto);
116 outerClassName = javaClassName(proto);
117 // optimizeFor = getOption(proto.getOptions(), "optimize_for", "SPEED");
118 multipleFiles = isMultipleFilesEnabled(proto);
119 // deferredDecode = Boolean.parseBoolean(getOption(proto.getOptions(), "deferred_decode", "false"));
120 auto_clear_optional_fields = Boolean.parseBoolean(getOption(proto.getOptions(), "auto_clear_optional_fields", "false"));
121
122 if (multipleFiles) {
123 generateProtoFile();
124 } else {
125 writeFile(outerClassName, new Closure() {
126 public void execute() throws CompilerException {
127 generateProtoFile();
128 }
129 });
130 }
131
132 if (!errors.isEmpty()) {
133 throw new CompilerException(errors);
134 }
135
136 }
137
138 private void writeFile(String className, Closure closure) throws CompilerException {
139 PrintWriter oldWriter = w;
140 // Figure out the java file name..
141 File outputFile = out;
142 if (javaPackage != null) {
143 String packagePath = javaPackage.replace('.', '/');
144 outputFile = new File(outputFile, packagePath);
145 }
146 outputFile = new File(outputFile, className + ".java");
147
148 // Start writing the output file..
149 outputFile.getParentFile().mkdirs();
150
151 FileOutputStream fos = null;
152 try {
153 fos = new FileOutputStream(outputFile);
154 w = new PrintWriter(fos);
155 closure.execute();
156 w.flush();
157 } catch (FileNotFoundException e) {
158 errors.add("Failed to write to: " + outputFile.getPath() + ":" + e.getMessage());
159 } finally {
160 try {
161 fos.close();
162 } catch (Throwable ignore) {
163 }
164 w = oldWriter;
165 }
166 }
167
168 private void loadImports(ProtoDescriptor proto, File protoDir) {
169 LinkedHashMap<String, ProtoDescriptor> children = new LinkedHashMap<String, ProtoDescriptor>();
170 for (String imp : proto.getImports()) {
171 File file = new File(protoDir, imp);
172 for (int i = 0; i < path.length && !file.exists(); i++) {
173 file = new File(path[i], imp);
174 }
175 if (!file.exists()) {
176 errors.add("Cannot load import: " + imp);
177 }
178
179 FileInputStream is = null;
180 try {
181 is = new FileInputStream(file);
182 ProtoParser parser = new ProtoParser(is);
183 ProtoDescriptor child = parser.ProtoDescriptor();
184 child.setName(file.getName());
185 loadImports(child, file.getParentFile());
186 children.put(imp, child);
187 } catch (ParseException e) {
188 errors.add("Failed to parse: " + file.getPath() + ":" + e.getMessage());
189 } catch (FileNotFoundException e) {
190 errors.add("Failed to open: " + file.getPath() + ":" + e.getMessage());
191 } finally {
192 try {
193 is.close();
194 } catch (Throwable ignore) {
195 }
196 }
197 }
198 proto.setImportProtoDescriptors(children);
199 }
200
201
202 private void generateProtoFile() throws CompilerException {
203 if (multipleFiles) {
204 for (EnumDescriptor value : proto.getEnums().values()) {
205 final EnumDescriptor o = value;
206 String className = uCamel(o.getName());
207 writeFile(className, new Closure() {
208 public void execute() throws CompilerException {
209 generateFileHeader();
210 generateEnum(o);
211 }
212 });
213 }
214 for (MessageDescriptor value : proto.getMessages().values()) {
215 final MessageDescriptor o = value;
216 String className = uCamel(o.getName());
217 writeFile(className, new Closure() {
218 public void execute() throws CompilerException {
219 generateFileHeader();
220 generateMessageBean(o);
221 }
222 });
223 }
224
225 } else {
226 generateFileHeader();
227
228 p("public class " + outerClassName + " {");
229 indent();
230
231 for (EnumDescriptor enumType : proto.getEnums().values()) {
232 generateEnum(enumType);
233 }
234 for (MessageDescriptor m : proto.getMessages().values()) {
235 generateMessageBean(m);
236 }
237
238 unindent();
239 p("}");
240 }
241 }
242
243 private void generateFileHeader() {
244 p("//");
245 p("// Generated by protoc, do not edit by hand.");
246 p("//");
247 if (javaPackage != null) {
248 p("package " + javaPackage + ";");
249 p("");
250 }
251 }
252
253 private void generateMessageBean(MessageDescriptor m) {
254
255 String type = uCamel(m.getName());
256 p();
257
258 String staticOption = "static ";
259 if (multipleFiles && m.getParent() == null) {
260 staticOption = "";
261 }
262
263 p(staticOption + "public class " + type + " implements org.fusesource.hawtbuf.proto.PBMessageFactory<" + qualified(type, beanCN) + ", " + qualified(type, bufferCN) + "> {");
264 p();
265 indent();
266
267 for (EnumDescriptor enumType : m.getEnums().values()) {
268 generateEnum(enumType);
269 }
270
271 // Generate the Nested Messages.
272 for (MessageDescriptor subMessage : m.getMessages().values()) {
273 generateMessageBean(subMessage);
274 }
275
276 // Generate the Group Messages
277 for (FieldDescriptor field : m.getFields().values()) {
278 if (field.isGroup()) {
279 generateMessageBean(field.getGroup());
280 }
281 }
282
283 p("public static final " + type + " "+factoryFeild+" = new " + type + "();");
284 p("public static final org.fusesource.hawtbuf.proto.PBMessageFramedCodec<"+bufferCN+"> FRAMED_CODEC = new org.fusesource.hawtbuf.proto.PBMessageFramedCodec<"+bufferCN+">("+factoryFeild+");");
285 p("public static final org.fusesource.hawtbuf.proto.PBMessageUnframedCodec<"+bufferCN+"> UNFRAMED_CODEC = new org.fusesource.hawtbuf.proto.PBMessageUnframedCodec<"+bufferCN+">("+factoryFeild+");");
286 p();
287
288 p("public " + beanCN + " create() {");
289 indent();
290 p("return new " + beanCN + "();");
291 unindent();
292 p("}");
293 p();
294 generateMethodParseFrom(m, bufferCN, beanCN);
295
296 // Generate the field getters
297 String gettrsExtendsClause = " extends org.fusesource.hawtbuf.proto.PBMessage<" + qualified(type, beanCN) + ", " + qualified(type, bufferCN) + ">";
298 for (EnumFieldDescriptor enumFeild : m.getAssociatedEnumFieldDescriptors()) {
299 String name = uCamel(enumFeild.getParent().getName());
300 name = name + "." + name + "Creatable";
301 gettrsExtendsClause += ", " + name;
302 }
303 p(staticOption + "public interface " + getterCN + gettrsExtendsClause + " {");
304 p();
305 indent();
306 {
307 for (FieldDescriptor field : m.getFields().values()) {
308 generateFieldGetterSignatures(field);
309 }
310 p("public " + beanCN + " copy();");
311 p("public " + bufferCN + " freeze();");
312 p("public java.lang.StringBuilder toString(java.lang.StringBuilder sb, String prefix);");
313 }
314 unindent();
315 p("}");
316
317 p();
318 p("static public final class " + beanCN + " implements " + getterCN + " {");
319 p();
320 indent();
321
322 p("" + bufferCN + " frozen;");
323 p("" + beanCN + " bean;");
324 p();
325 p("public " + beanCN + "() {");
326 indent();
327 p("this.bean = this;");
328 unindent();
329 p("}");
330 p();
331 p("public " + beanCN + "(" + beanCN + " copy) {");
332 indent();
333 p("this.bean = copy;");
334 unindent();
335 p("}");
336 p();
337 p("public " + beanCN + " copy() {");
338 indent();
339 p("return new " + beanCN + "(bean);");
340 unindent();
341 p("}");
342 p();
343
344 generateMethodFreeze(m, bufferCN);
345
346 p("private void copyCheck() {");
347 indent();
348 p("assert frozen==null : org.fusesource.hawtbuf.proto.MessageBufferSupport.FORZEN_ERROR_MESSAGE;");
349 p("if (bean != this) {");
350 indent();
351 p("copy(bean);");
352 unindent();
353 p("}");
354 unindent();
355 p("}");
356 p();
357
358 generateMethodCopyFromBean(m, beanCN);
359
360 // Generate the field accessors..
361 for (FieldDescriptor field : m.getFields().values()) {
362 generateFieldAccessor(beanCN, field);
363 }
364
365 generateMethodToString(m);
366
367 generateMethodMergeFromStream(m, beanCN);
368
369 generateBeanEquals(m, beanCN);
370
371 generateMethodMergeFromBean(m, getterCN, beanCN);
372
373 generateMethodClear(m);
374
375 generateReadWriteExternal(m);
376
377 for (EnumFieldDescriptor enumFeild : m.getAssociatedEnumFieldDescriptors()) {
378 String enumName = uCamel(enumFeild.getParent().getName());
379 p("public " + enumName + " to" + enumName + "() {");
380 indent();
381 p("return " + enumName + "." + enumFeild.getName() + ";");
382 unindent();
383 p("}");
384 p();
385 }
386
387 unindent();
388 p("}");
389 p();
390
391 p("static public final class " + bufferCN + " implements org.fusesource.hawtbuf.proto.MessageBuffer<" + qualified(type, beanCN) + ", " + qualified(type, bufferCN) + ">, " + getterCN + " {");
392 p();
393 indent();
394
395 p("private " + beanCN + " bean;");
396 p("private org.fusesource.hawtbuf.Buffer buffer;");
397 p("private int size=-1;");
398 p("private int hashCode;");
399 p();
400 p("private " + bufferCN + "(org.fusesource.hawtbuf.Buffer buffer) {");
401 indent();
402 p("this.buffer = buffer;");
403 unindent();
404 p("}");
405 p();
406 p("private " + bufferCN + "(" + beanCN + " bean) {");
407 indent();
408 p("this.bean = bean;");
409 unindent();
410 p("}");
411 p();
412 p("public " + beanCN + " copy() {");
413 indent();
414 p("return bean().copy();");
415 unindent();
416 p("}");
417 p();
418 p("public " + bufferCN + " freeze() {");
419 indent();
420 p("return this;");
421 unindent();
422 p("}");
423 p();
424 p("private " + beanCN + " bean() {");
425 indent();
426 p("if (bean == null) {");
427 indent();
428 p("try {");
429 indent();
430 p("bean = new " + beanCN + "().mergeUnframed(new org.fusesource.hawtbuf.proto.CodedInputStream(buffer));");
431 p("bean.frozen=this;");
432 unindent();
433 p("} catch (org.fusesource.hawtbuf.proto.InvalidProtocolBufferException e) {");
434 indent();
435 p("throw new RuntimeException(e);");
436 unindent();
437 p("} catch (java.io.IOException e) {");
438 indent();
439 p("throw new RuntimeException(\"An IOException was thrown (should never happen in this method).\", e);");
440 unindent();
441 p("}");
442 unindent();
443 p("}");
444 p("return bean;");
445 unindent();
446 p("}");
447 p();
448
449 p("public String toString() {");
450 indent();
451 p("return bean().toString();");
452 unindent();
453 p("}");
454 p();
455 p("public java.lang.StringBuilder toString(java.lang.StringBuilder sb, String prefix) {");
456 indent();
457 p("return bean().toString(sb, prefix);");
458 unindent();
459 p("}");
460 p();
461
462 for (FieldDescriptor field : m.getFields().values()) {
463 generateBufferGetters(field);
464 }
465
466 generateMethodWrite(m);
467
468 generateMethodSerializedSize(m);
469
470 generateBufferEquals(m, bufferCN);
471
472 p("public boolean frozen() {");
473 indent();
474 p("return true;");
475 unindent();
476 p("}");
477
478 for (EnumFieldDescriptor enumFeild : m.getAssociatedEnumFieldDescriptors()) {
479 String enumName = uCamel(enumFeild.getParent().getName());
480 p("public " + enumName + " to" + enumName + "() {");
481 indent();
482 p("return " + enumName + "." + enumFeild.getName() + ";");
483 unindent();
484 p("}");
485 p();
486 }
487
488 unindent();
489 p("}");
490 p();
491
492
493 // generateMethodVisitor(m);
494 // generateMethodType(m, className);
495
496
497 unindent();
498 p("}");
499 p();
500
501 }
502
503
504 private void generateMethodFreeze(MessageDescriptor m, String bufferClassName) {
505 p("public boolean frozen() {");
506 indent();
507 p("return frozen!=null;");
508 unindent();
509 p("}");
510 p();
511 p("public " + bufferClassName + " freeze() {");
512 indent();
513 p("if( frozen==null ) {");
514 indent();
515 p("frozen = new " + bufferClassName + "(bean);");
516 p("assert deepFreeze();");
517 unindent();
518 p("}");
519 p("return frozen;");
520 unindent();
521 p("}");
522 p();
523 p("private boolean deepFreeze() {");
524 indent();
525 p("frozen.serializedSizeUnframed();");
526 p("return true;");
527 unindent();
528 p("}");
529 p();
530
531 }
532
533
534 private boolean isPrimitive(String type) {
535 return type.equals("int") ||
536 type.equals("long") ||
537 type.equals("double") ||
538 type.equals("float") ||
539 type.equals("boolean");
540 }
541
542 private boolean isBuferOrString(String type) {
543 return type.equals("org.fusesource.hawtbuf.AsciiBuffer") ||
544 type.equals("org.fusesource.hawtbuf.UTF8Buffer") ||
545 type.equals("org.fusesource.hawtbuf.Buffer") ||
546 type.equals("String");
547 }
548
549 /**
550 * @param m
551 * @param className
552 */
553 private void generateMethodCopyFromBean(MessageDescriptor m, String className) {
554 p("private void copy(" + className + " other) {");
555 indent();
556 p("this.bean = this;");
557 for (FieldDescriptor field : m.getFields().values()) {
558 String lname = lCamel(field.getName());
559 String type = field.getRule() == FieldDescriptor.REPEATED_RULE ? javaCollectionType(field) : javaType(field);
560 boolean primitive = isPrimitive(type);
561 if (field.isRepeated()) {
562 if (primitive || isBuferOrString(type) || field.getTypeDescriptor().isEnum()) {
563 p("this.f_" + lname + " = other.f_" + lname + ";");
564 p("if( this.f_" + lname + " !=null && !other.frozen()) {");
565 indent();
566 p("this.f_" + lname + " = new java.util.ArrayList<" + type + ">(this.f_" + lname + ");");
567 unindent();
568 p("}");
569 } else {
570 p("this.f_" + lname + " = other.f_" + lname + ";");
571 p("if( this.f_" + lname + " !=null) {");
572 indent();
573 p("this.f_" + lname + " = new java.util.ArrayList<" + type + ">(other.f_" + lname + ".size());");
574 p("for( " + type + " e : other.f_" + lname + ") {");
575 indent();
576 p("this.f_" + lname + ".add(e.copy());");
577 unindent();
578 p("}");
579 unindent();
580 p("}");
581 }
582 } else {
583 if (primitive || isBuferOrString(type) || field.getTypeDescriptor().isEnum()) {
584 p("this.f_" + lname + " = other.f_" + lname + ";");
585 if (primitive) {
586 p("this.b_" + lname + " = other.b_" + lname + ";");
587 }
588 } else {
589 p("this.f_" + lname + " = other.f_" + lname + ";");
590 p("if( this.f_" + lname + " !=null ) {");
591 indent();
592 p("this.f_" + lname + " = this.f_" + lname + ".copy();");
593 unindent();
594 p("}");
595 }
596 }
597 }
598 unindent();
599 p("}");
600 p();
601 }
602
603
604 /**
605 * If the java_visitor message option is set, then this method generates a visitor method. The option
606 * speifiies the class name of the visitor and optionally the return value and exceptions thrown by the visitor.
607 * <p/>
608 * Examples:
609 * <p/>
610 * option java_visitor = "org.apache.kahadb.store.Visitor";
611 * generates:
612 * public void visit(org.apache.kahadb.store.Visitor visitor) {
613 * visitor.visit(this);
614 * }
615 * <p/>
616 * option java_visitor = "org.apache.kahadb.store.Visitor:int:java.io.IOException";
617 * generates:
618 * public int visit(org.apache.kahadb.store.Visitor visitor) throws java.io.IOException {
619 * return visitor.visit(this);
620 * }
621 *
622 * @param m
623 */
624 private void generateMethodVisitor(MessageDescriptor m) {
625 String javaVisitor = getOption(m.getOptions(), "java_visitor", null);
626 if (javaVisitor != null) {
627 String returns = "void";
628 String throwsException = null;
629
630 StringTokenizer st = new StringTokenizer(javaVisitor, ":");
631 String vistorClass = st.nextToken();
632 if (st.hasMoreTokens()) {
633 returns = st.nextToken();
634 }
635 if (st.hasMoreTokens()) {
636 throwsException = st.nextToken();
637 }
638
639 String throwsClause = "";
640 if (throwsException != null) {
641 throwsClause = "throws " + throwsException + " ";
642 }
643
644 p("public " + returns + " visit(" + vistorClass + " visitor) " + throwsClause + "{");
645 indent();
646 if ("void".equals(returns)) {
647 p("visitor.visit(this);");
648 } else {
649 p("return visitor.visit(this);");
650 }
651 unindent();
652 p("}");
653 p();
654 }
655 }
656
657 private void generateMethodType(MessageDescriptor m, String className) {
658 String typeEnum = getOption(m.getOptions(), "java_type_method", null);
659 if (typeEnum != null) {
660
661 TypeDescriptor typeDescriptor = m.getType(typeEnum);
662 if (typeDescriptor == null) {
663 typeDescriptor = m.getProtoDescriptor().getType(typeEnum);
664 }
665 if (typeDescriptor == null || !typeDescriptor.isEnum()) {
666 errors.add("The java_type_method option on the " + m.getName() + " message does not point to valid enum type");
667 return;
668 }
669
670
671 String constant = constantCase(className);
672 EnumDescriptor enumDescriptor = (EnumDescriptor) typeDescriptor;
673 if (enumDescriptor.getFields().get(constant) == null) {
674 errors.add("The java_type_method option on the " + m.getName() + " message does not points to the " + typeEnum + " enum but it does not have an entry for " + constant);
675 }
676
677 String type = qualified(javaFactoryType(typeDescriptor), getterCN);
678
679 p("public " + type + " type() {");
680 indent();
681 p("return " + type + "." + constant + ";");
682 unindent();
683 p("}");
684 p();
685 }
686 }
687
688 private void generateMethodParseFrom(MessageDescriptor m, String bufferClassName, String beanClassName) {
689 p("public " + beanClassName + " parseUnframed(org.fusesource.hawtbuf.proto.CodedInputStream data) throws org.fusesource.hawtbuf.proto.InvalidProtocolBufferException, java.io.IOException {");
690 indent();
691 p("return new " + beanClassName + "().mergeUnframed(data);");
692 unindent();
693 p("}");
694 p();
695 p("public " + beanClassName + " parseUnframed(java.io.InputStream data) throws org.fusesource.hawtbuf.proto.InvalidProtocolBufferException, java.io.IOException {");
696 indent();
697 p("return parseUnframed(new org.fusesource.hawtbuf.proto.CodedInputStream(data));");
698 unindent();
699 p("}");
700 p();
701 p("public " + bufferClassName + " parseUnframed(org.fusesource.hawtbuf.Buffer data) throws org.fusesource.hawtbuf.proto.InvalidProtocolBufferException {");
702 indent();
703 p("return new " + bufferClassName + "(data);");
704 unindent();
705 p("}");
706 p();
707 p("public " + bufferClassName + " parseUnframed(byte[] data) throws org.fusesource.hawtbuf.proto.InvalidProtocolBufferException {");
708 indent();
709 p("return parseUnframed(new org.fusesource.hawtbuf.Buffer(data));");
710 unindent();
711 p("}");
712 p();
713 p("public " + bufferClassName + " parseFramed(org.fusesource.hawtbuf.proto.CodedInputStream data) throws org.fusesource.hawtbuf.proto.InvalidProtocolBufferException, java.io.IOException {");
714 indent();
715 p("int length = data.readRawVarint32();");
716 p("int oldLimit = data.pushLimit(length);");
717 p("" + bufferClassName + " rc = parseUnframed(data.readRawBytes(length));");
718 p("data.popLimit(oldLimit);");
719 p("return rc;");
720 unindent();
721 p("}");
722 p();
723 p("public " + bufferClassName + " parseFramed(org.fusesource.hawtbuf.Buffer data) throws org.fusesource.hawtbuf.proto.InvalidProtocolBufferException {");
724 indent();
725 p("try {");
726 indent();
727 p("org.fusesource.hawtbuf.proto.CodedInputStream input = new org.fusesource.hawtbuf.proto.CodedInputStream(data);");
728 p("" + bufferClassName + " rc = parseFramed(input);");
729 p("input.checkLastTagWas(0);");
730 p("return rc;");
731 unindent();
732 p("} catch (org.fusesource.hawtbuf.proto.InvalidProtocolBufferException e) {");
733 indent();
734 p("throw e;");
735 unindent();
736 p("} catch (java.io.IOException e) {");
737 indent();
738 p("throw new RuntimeException(\"An IOException was thrown (should never happen in this method).\", e);");
739 unindent();
740 p("}");
741 unindent();
742 p("}");
743 p();
744 p("public " + bufferClassName + " parseFramed(byte[] data) throws org.fusesource.hawtbuf.proto.InvalidProtocolBufferException {");
745 indent();
746 p("return parseFramed(new org.fusesource.hawtbuf.Buffer(data));");
747 unindent();
748 p("}");
749 p();
750 p("public " + bufferClassName + " parseFramed(java.io.InputStream data) throws org.fusesource.hawtbuf.proto.InvalidProtocolBufferException, java.io.IOException {");
751 indent();
752 p("return parseUnframed(org.fusesource.hawtbuf.proto.MessageBufferSupport.readFrame(data));");
753 unindent();
754 p("}");
755 p();
756
757 }
758
759 private void generateBeanEquals(MessageDescriptor m, String className) {
760 p("public boolean equals(Object obj) {");
761 indent();
762 p("if( obj==this )");
763 p(" return true;");
764 p("");
765 p("if( obj==null || obj.getClass()!=" + className + ".class )");
766 p(" return false;");
767 p("");
768 p("return equals((" + className + ")obj);");
769 unindent();
770 p("}");
771 p("");
772
773 p("public boolean equals(" + className + " obj) {");
774 indent();
775 for (FieldDescriptor field : m.getFields().values()) {
776 String uname = uCamel(field.getName());
777 String getterMethod = "get" + uname + "()";
778 String hasMethod = "has" + uname + "()";
779
780 if (field.getRule() == FieldDescriptor.REPEATED_RULE) {
781 getterMethod = "get" + uname + "List()";
782 }
783
784 p("if (" + hasMethod + " ^ obj." + hasMethod + " ) ");
785 p(" return false;");
786
787
788 if (field.getRule() != FieldDescriptor.REPEATED_RULE && (field.isNumberType() || field.getType() == FieldDescriptor.BOOL_TYPE)) {
789 p("if (" + hasMethod + " && ( " + getterMethod + "!=obj." + getterMethod + " ))");
790 } else {
791 p("if (" + hasMethod + " && ( !" + getterMethod + ".equals(obj." + getterMethod + ") ))");
792 }
793 p(" return false;");
794 }
795 p("return true;");
796 unindent();
797 p("}");
798 p("");
799 p("public int hashCode() {");
800 indent();
801 int hc = className.hashCode();
802 p("int rc=" + hc + ";");
803 int counter = 0;
804 for (FieldDescriptor field : m.getFields().values()) {
805 counter++;
806
807 String uname = uCamel(field.getName());
808 String getterMethod = "get" + uname + "()";
809 String hasMethod = "has" + uname + "()";
810
811 if (field.getRule() == FieldDescriptor.REPEATED_RULE) {
812 getterMethod = "get" + uname + "List()";
813 }
814
815 p("if (" + hasMethod + ") {");
816 indent();
817
818 if (field.getRule() == FieldDescriptor.REPEATED_RULE) {
819 p("rc ^= ( " + uname.hashCode() + "^" + getterMethod + ".hashCode() );");
820 } else if (field.isInteger32Type()) {
821 p("rc ^= ( " + uname.hashCode() + "^" + getterMethod + " );");
822 } else if (field.isInteger64Type()) {
823 p("rc ^= ( " + uname.hashCode() + "^(new Long(" + getterMethod + ")).hashCode() );");
824 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
825 p("rc ^= ( " + uname.hashCode() + "^(new Double(" + getterMethod + ")).hashCode() );");
826 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
827 p("rc ^= ( " + uname.hashCode() + "^(new Double(" + getterMethod + ")).hashCode() );");
828 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
829 p("rc ^= ( " + uname.hashCode() + "^ (" + getterMethod + "? " + counter + ":-" + counter + ") );");
830 } else {
831 p("rc ^= ( " + uname.hashCode() + "^" + getterMethod + ".hashCode() );");
832 }
833 unindent();
834 p("}");
835 }
836 p("return rc;");
837 unindent();
838 p("}");
839 p("");
840 }
841
842 private void generateBufferEquals(MessageDescriptor m, String className) {
843 p("public boolean equals(Object obj) {");
844 indent();
845 p("if( obj==this )");
846 p(" return true;");
847 p("");
848 p("if( obj==null || obj.getClass()!=" + className + ".class )");
849 p(" return false;");
850 p("");
851 p("return equals((" + className + ")obj);");
852 unindent();
853 p("}");
854 p("");
855
856 p("public boolean equals(" + className + " obj) {");
857 indent();
858 p("return toUnframedBuffer().equals(obj.toUnframedBuffer());");
859 unindent();
860 p("}");
861 p("");
862 p("public int hashCode() {");
863 indent();
864 int hc = className.hashCode();
865 p("if( hashCode==0 ) {");
866 p("hashCode=" + hc + " ^ toUnframedBuffer().hashCode();");
867 p("}");
868 p("return hashCode;");
869 unindent();
870 p("}");
871 p("");
872 }
873
874 /**
875 * @param m
876 */
877 private void generateMethodSerializedSize(MessageDescriptor m) {
878
879 p("public int serializedSizeFramed() {");
880 indent();
881 p("int t = serializedSizeUnframed();");
882 p("return org.fusesource.hawtbuf.proto.CodedOutputStream.computeRawVarint32Size(t) + t;");
883 unindent();
884 p("}");
885 p();
886 p("public int serializedSizeUnframed() {");
887 indent();
888 p("if (buffer != null) {");
889 indent();
890 p("return buffer.length;");
891 unindent();
892 p("}");
893 p("if (size != -1)");
894 p(" return size;");
895 p();
896 p("size = 0;");
897 for (FieldDescriptor field : m.getFields().values()) {
898
899 String uname = uCamel(field.getName());
900 String getter = "get" + uname + "()";
901 String type = javaType(field);
902
903 if (!field.isRequired()) {
904 p("if (has" + uname + "()) {");
905 indent();
906 }
907
908 if (field.getRule() == FieldDescriptor.REPEATED_RULE) {
909 p("for (" + type + " i : get" + uname + "List()) {");
910 indent();
911 getter = "i";
912 }
913
914 if (field.getType() == FieldDescriptor.STRING_TYPE) {
915 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeStringSize(" + field.getTag() + ", " + getter + ");");
916 } else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
917 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeBytesSize(" + field.getTag() + ", " + getter + ");");
918 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
919 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeBoolSize(" + field.getTag() + ", " + getter + ");");
920 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
921 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeDoubleSize(" + field.getTag() + ", " + getter + ");");
922 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
923 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeFloatSize(" + field.getTag() + ", " + getter + ");");
924 } else if (field.getType() == FieldDescriptor.INT32_TYPE) {
925 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeInt32Size(" + field.getTag() + ", " + getter + ");");
926 } else if (field.getType() == FieldDescriptor.INT64_TYPE) {
927 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeInt64Size(" + field.getTag() + ", " + getter + ");");
928 } else if (field.getType() == FieldDescriptor.SINT32_TYPE) {
929 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeSInt32Size(" + field.getTag() + ", " + getter + ");");
930 } else if (field.getType() == FieldDescriptor.SINT64_TYPE) {
931 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeSInt64Size(" + field.getTag() + ", " + getter + ");");
932 } else if (field.getType() == FieldDescriptor.UINT32_TYPE) {
933 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeUInt32Size(" + field.getTag() + ", " + getter + ");");
934 } else if (field.getType() == FieldDescriptor.UINT64_TYPE) {
935 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeUInt64Size(" + field.getTag() + ", " + getter + ");");
936 } else if (field.getType() == FieldDescriptor.FIXED32_TYPE) {
937 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeFixed32Size(" + field.getTag() + ", " + getter + ");");
938 } else if (field.getType() == FieldDescriptor.FIXED64_TYPE) {
939 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeFixed64Size(" + field.getTag() + ", " + getter + ");");
940 } else if (field.getType() == FieldDescriptor.SFIXED32_TYPE) {
941 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeSFixed32Size(" + field.getTag() + ", " + getter + ");");
942 } else if (field.getType() == FieldDescriptor.SFIXED64_TYPE) {
943 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeSFixed64Size(" + field.getTag() + ", " + getter + ");");
944 } else if (field.getTypeDescriptor().isEnum()) {
945 p("size += org.fusesource.hawtbuf.proto.CodedOutputStream.computeEnumSize(" + field.getTag() + ", " + getter + ".getNumber());");
946 } else if (field.getGroup() != null) {
947 errors.add("This code generator does not support group fields.");
948 // p("size += org.fusesource.hawtbuf.proto.MessageBufferSupport.computeGroupSize("+field.getTag()+", ("+type+"Buffer)"+getter+");");
949 } else {
950 p("size += org.fusesource.hawtbuf.proto.MessageBufferSupport.computeMessageSize(" + field.getTag() + ", " + getter + ".freeze());");
951 }
952 if (field.getRule() == FieldDescriptor.REPEATED_RULE) {
953 unindent();
954 p("}");
955 }
956
957 if (!field.isRequired()) {
958 unindent();
959 p("}");
960 }
961
962 }
963 // TODO: handle unknown fields
964 // size += getUnknownFields().getSerializedSize();");
965 p("return size;");
966 unindent();
967 p("}");
968 p();
969 }
970
971 /**
972 * @param m
973 */
974 private void generateMethodWrite(MessageDescriptor m) {
975
976 p("public org.fusesource.hawtbuf.Buffer toUnframedBuffer() {");
977 indent();
978 p("if( buffer !=null ) {");
979 indent();
980 p("return buffer;");
981 unindent();
982 p("}");
983 p("return org.fusesource.hawtbuf.proto.MessageBufferSupport.toUnframedBuffer(this);");
984 unindent();
985 p("}");
986 p();
987 p("public org.fusesource.hawtbuf.Buffer toFramedBuffer() {");
988 indent();
989 p("return org.fusesource.hawtbuf.proto.MessageBufferSupport.toFramedBuffer(this);");
990 unindent();
991 p("}");
992 p();
993 p("public byte[] toUnframedByteArray() {");
994 indent();
995 p("return toUnframedBuffer().toByteArray();");
996 unindent();
997 p("}");
998 p();
999 p("public byte[] toFramedByteArray() {");
1000 indent();
1001 p("return toFramedBuffer().toByteArray();");
1002 unindent();
1003 p("}");
1004 p();
1005 p("public void writeFramed(org.fusesource.hawtbuf.proto.CodedOutputStream output) throws java.io.IOException {");
1006 indent();
1007 p("output.writeRawVarint32(serializedSizeUnframed());");
1008 p("writeUnframed(output);");
1009 unindent();
1010 p("}");
1011 p();
1012 p("public void writeFramed(java.io.OutputStream output) throws java.io.IOException {");
1013 indent();
1014 p("org.fusesource.hawtbuf.proto.CodedOutputStream codedOutput = new org.fusesource.hawtbuf.proto.CodedOutputStream(output);");
1015 p("writeFramed(codedOutput);");
1016 p("codedOutput.flush();");
1017 unindent();
1018 p("}");
1019 p();
1020
1021 p("public void writeUnframed(java.io.OutputStream output) throws java.io.IOException {");
1022 indent();
1023 p("org.fusesource.hawtbuf.proto.CodedOutputStream codedOutput = new org.fusesource.hawtbuf.proto.CodedOutputStream(output);");
1024 p("writeUnframed(codedOutput);");
1025 p("codedOutput.flush();");
1026 unindent();
1027 p("}");
1028 p();
1029
1030 p("public void writeUnframed(org.fusesource.hawtbuf.proto.CodedOutputStream output) throws java.io.IOException {");
1031 indent();
1032
1033 p("if (buffer == null) {");
1034 indent();
1035 p("int size = serializedSizeUnframed();");
1036 p("buffer = output.getNextBuffer(size);");
1037 p("org.fusesource.hawtbuf.proto.CodedOutputStream original=null;");
1038 p("if( buffer == null ) {");
1039 indent();
1040 p("buffer = new org.fusesource.hawtbuf.Buffer(new byte[size]);");
1041 p("original = output;");
1042 p("output = new org.fusesource.hawtbuf.proto.CodedOutputStream(buffer);");
1043 unindent();
1044 p("}");
1045
1046 for (FieldDescriptor field : m.getFields().values()) {
1047 String uname = uCamel(field.getName());
1048 String getter = "bean.get" + uname + "()";
1049 String type = javaType(field);
1050
1051 if (!field.isRequired()) {
1052 p("if (bean.has" + uname + "()) {");
1053 indent();
1054 }
1055
1056 if (field.getRule() == FieldDescriptor.REPEATED_RULE) {
1057 p("for (" + type + " i : bean.get" + uname + "List()) {");
1058 indent();
1059 getter = "i";
1060 }
1061
1062 if (field.getType() == FieldDescriptor.STRING_TYPE) {
1063 p("output.writeString(" + field.getTag() + ", " + getter + ");");
1064 } else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
1065 p("output.writeBytes(" + field.getTag() + ", " + getter + ");");
1066 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
1067 p("output.writeBool(" + field.getTag() + ", " + getter + ");");
1068 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
1069 p("output.writeDouble(" + field.getTag() + ", " + getter + ");");
1070 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
1071 p("output.writeFloat(" + field.getTag() + ", " + getter + ");");
1072 } else if (field.getType() == FieldDescriptor.INT32_TYPE) {
1073 p("output.writeInt32(" + field.getTag() + ", " + getter + ");");
1074 } else if (field.getType() == FieldDescriptor.INT64_TYPE) {
1075 p("output.writeInt64(" + field.getTag() + ", " + getter + ");");
1076 } else if (field.getType() == FieldDescriptor.SINT32_TYPE) {
1077 p("output.writeSInt32(" + field.getTag() + ", " + getter + ");");
1078 } else if (field.getType() == FieldDescriptor.SINT64_TYPE) {
1079 p("output.writeSInt64(" + field.getTag() + ", " + getter + ");");
1080 } else if (field.getType() == FieldDescriptor.UINT32_TYPE) {
1081 p("output.writeUInt32(" + field.getTag() + ", " + getter + ");");
1082 } else if (field.getType() == FieldDescriptor.UINT64_TYPE) {
1083 p("output.writeUInt64(" + field.getTag() + ", " + getter + ");");
1084 } else if (field.getType() == FieldDescriptor.FIXED32_TYPE) {
1085 p("output.writeFixed32(" + field.getTag() + ", " + getter + ");");
1086 } else if (field.getType() == FieldDescriptor.FIXED64_TYPE) {
1087 p("output.writeFixed64(" + field.getTag() + ", " + getter + ");");
1088 } else if (field.getType() == FieldDescriptor.SFIXED32_TYPE) {
1089 p("output.writeSFixed32(" + field.getTag() + ", " + getter + ");");
1090 } else if (field.getType() == FieldDescriptor.SFIXED64_TYPE) {
1091 p("output.writeSFixed64(" + field.getTag() + ", " + getter + ");");
1092 } else if (field.getTypeDescriptor().isEnum()) {
1093 p("output.writeEnum(" + field.getTag() + ", " + getter + ".getNumber());");
1094 } else if (field.getGroup() != null) {
1095 errors.add("This code generator does not support group fields.");
1096 // p("writeGroup(output, "+field.getTag()+", "+getter+");");
1097 } else {
1098 p("org.fusesource.hawtbuf.proto.MessageBufferSupport.writeMessage(output, " + field.getTag() + ", " + getter + ".freeze());");
1099 }
1100
1101 if (field.getRule() == FieldDescriptor.REPEATED_RULE) {
1102 unindent();
1103 p("}");
1104 }
1105
1106 if (!field.isRequired()) {
1107 unindent();
1108 p("}");
1109 }
1110 }
1111
1112 p("if( original !=null ) {");
1113 indent();
1114 p("output.checkNoSpaceLeft();");
1115 p("output = original;");
1116 p("output.writeRawBytes(buffer);");
1117 unindent();
1118 p("}");
1119 unindent();
1120 p("} else {");
1121 indent();
1122 p("output.writeRawBytes(buffer);");
1123 unindent();
1124 p("}");
1125
1126 unindent();
1127 p("}");
1128 p();
1129 }
1130
1131 /**
1132 * @param m
1133 * @param className
1134 */
1135 private void generateMethodMergeFromStream(MessageDescriptor m, String className) {
1136 p("public " + className + " mergeUnframed(java.io.InputStream input) throws java.io.IOException {");
1137 indent();
1138 p("return mergeUnframed(new org.fusesource.hawtbuf.proto.CodedInputStream(input));");
1139 unindent();
1140 p("}");
1141 p();
1142 p("public " + className + " mergeUnframed(org.fusesource.hawtbuf.proto.CodedInputStream input) throws java.io.IOException {");
1143 indent();
1144 {
1145 p("copyCheck();");
1146 p("while (true) {");
1147 indent();
1148 {
1149 p("int tag = input.readTag();");
1150 p("if ((tag & 0x07) == 4) {");
1151 p(" return this;");
1152 p("}");
1153
1154 p("switch (tag) {");
1155 p("case 0:");
1156 p(" return this;");
1157 p("default: {");
1158
1159 p(" break;");
1160 p("}");
1161
1162 for (FieldDescriptor field : m.getFields().values()) {
1163 String uname = uCamel(field.getName());
1164 String setter = "set" + uname;
1165 boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE;
1166 if (repeated) {
1167 setter = "create" + uname + "List().add";
1168 }
1169 if (field.getType() == FieldDescriptor.STRING_TYPE) {
1170 p("case "
1171 + makeTag(field.getTag(),
1172 WIRETYPE_LENGTH_DELIMITED) + ":");
1173 indent();
1174 p(setter + "(input.readString());");
1175 } else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
1176 p("case " + makeTag(field.getTag(), WIRETYPE_LENGTH_DELIMITED) + ":");
1177 indent();
1178 String override = getOption(field.getOptions(), "java_override_type", null);
1179 if ("AsciiBuffer".equals(override)) {
1180 p(setter + "(new org.fusesource.hawtbuf.AsciiBuffer(input.readBytes()));");
1181 } else if ("UTF8Buffer".equals(override)) {
1182 p(setter + "(new org.fusesource.hawtbuf.UTF8Buffer(input.readBytes()));");
1183 } else {
1184 p(setter + "(input.readBytes());");
1185 }
1186 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
1187 p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + ":");
1188 indent();
1189 p(setter + "(input.readBool());");
1190 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
1191 p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64)
1192 + ":");
1193 indent();
1194 p(setter + "(input.readDouble());");
1195 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
1196 p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32)
1197 + ":");
1198 indent();
1199 p(setter + "(input.readFloat());");
1200 } else if (field.getType() == FieldDescriptor.INT32_TYPE) {
1201 p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
1202 + ":");
1203 indent();
1204 p(setter + "(input.readInt32());");
1205 } else if (field.getType() == FieldDescriptor.INT64_TYPE) {
1206 p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
1207 + ":");
1208 indent();
1209 p(setter + "(input.readInt64());");
1210 } else if (field.getType() == FieldDescriptor.SINT32_TYPE) {
1211 p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
1212 + ":");
1213 indent();
1214 p(setter + "(input.readSInt32());");
1215 } else if (field.getType() == FieldDescriptor.SINT64_TYPE) {
1216 p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
1217 + ":");
1218 indent();
1219 p(setter + "(input.readSInt64());");
1220 } else if (field.getType() == FieldDescriptor.UINT32_TYPE) {
1221 p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
1222 + ":");
1223 indent();
1224 p(setter + "(input.readUInt32());");
1225 } else if (field.getType() == FieldDescriptor.UINT64_TYPE) {
1226 p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
1227 + ":");
1228 indent();
1229 p(setter + "(input.readUInt64());");
1230 } else if (field.getType() == FieldDescriptor.FIXED32_TYPE) {
1231 p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32)
1232 + ":");
1233 indent();
1234 p(setter + "(input.readFixed32());");
1235 } else if (field.getType() == FieldDescriptor.FIXED64_TYPE) {
1236 p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64)
1237 + ":");
1238 indent();
1239 p(setter + "(input.readFixed64());");
1240 } else if (field.getType() == FieldDescriptor.SFIXED32_TYPE) {
1241 p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32)
1242 + ":");
1243 indent();
1244 p(setter + "(input.readSFixed32());");
1245 } else if (field.getType() == FieldDescriptor.SFIXED64_TYPE) {
1246 p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64)
1247 + ":");
1248 indent();
1249 p(setter + "(input.readSFixed64());");
1250 } else if (field.getTypeDescriptor().isEnum()) {
1251 p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
1252 + ":");
1253 indent();
1254 String type = javaType(field);
1255 p("{");
1256 indent();
1257 p("int t = input.readEnum();");
1258 p("" + type + " value = " + type + ".valueOf(t);");
1259 p("if( value !=null ) {");
1260 indent();
1261 p(setter + "(value);");
1262 unindent();
1263 p("}");
1264 // TODO: else store it as an known
1265
1266 unindent();
1267 p("}");
1268
1269 } else if (field.getGroup() != null) {
1270 errors.add("This code generator does not support group fields.");
1271 // p("case "+ makeTag(field.getTag(), WIRETYPE_START_GROUP)+ ":");
1272 // indent();
1273 // String type = javaType(field);
1274 // if (repeated) {
1275 // p(setter + "(readGroup(input, " + field.getTag()+ ", new " + type + "()));");
1276 // } else {
1277 // p("if (has" + uname + "()) {");
1278 // indent();
1279 // p("readGroup(input, " + field.getTag() + ", get"
1280 // + uname + "());");
1281 // unindent();
1282 // p("} else {");
1283 // indent();
1284 // p(setter + "(readGroup(input, " + field.getTag()
1285 // + ",new " + type + "()));");
1286 // unindent();
1287 // p("}");
1288 // }
1289 // p("");
1290 } else {
1291 p("case " + makeTag(field.getTag(), WIRETYPE_LENGTH_DELIMITED) + ":");
1292 indent();
1293 String type = javaFactoryType(field.getTypeDescriptor());
1294 if (repeated) {
1295 p(setter + "(" + qualified(type, factoryFeild) + ".parseFramed(input));");
1296 } else {
1297 p("if (has" + uname + "()) {");
1298 indent();
1299 p("set" + uname + "(get" + uname + "().copy().mergeFrom(" + qualified(type, factoryFeild) + ".parseFramed(input)));");
1300 unindent();
1301 p("} else {");
1302 indent();
1303 p(setter + "(" + qualified(type, factoryFeild) + ".parseFramed(input));");
1304 unindent();
1305 p("}");
1306 }
1307 }
1308 p("break;");
1309 unindent();
1310 }
1311 p("}");
1312 }
1313 unindent();
1314 p("}");
1315 }
1316 unindent();
1317 p("}");
1318 }
1319
1320 /**
1321 * @param m
1322 * @param getterClassName
1323 */
1324 private void generateMethodMergeFromBean(MessageDescriptor m, String getterClassName, String beanClassName) {
1325 p("public " + beanClassName + " mergeFrom(" + getterClassName + " other) {");
1326 indent();
1327 p("copyCheck();");
1328 for (FieldDescriptor field : m.getFields().values()) {
1329 String uname = uCamel(field.getName());
1330 p("if (other.has" + uname + "()) {");
1331 indent();
1332
1333 if (field.isScalarType() || field.getTypeDescriptor().isEnum()) {
1334 if (field.isRepeated()) {
1335 p("get" + uname + "List().addAll(other.get" + uname + "List());");
1336 } else {
1337 p("set" + uname + "(other.get" + uname + "());");
1338 }
1339 } else {
1340
1341 String type = qualified(javaFactoryType(field.getTypeDescriptor()), getterCN);
1342
1343 // It's complex type...
1344 if (field.isRepeated()) {
1345 p("for(" + type + " element: other.get" + uname + "List() ) {");
1346 indent();
1347 p("get" + uname + "List().add(element.copy());");
1348 unindent();
1349 p("}");
1350 } else {
1351 p("if (has" + uname + "()) {");
1352 indent();
1353 p("set" + uname + "(get" + uname + "().copy().mergeFrom(other.get" + uname + "()));");
1354 unindent();
1355 p("} else {");
1356 indent();
1357 p("set" + uname + "(other.get" + uname + "().copy());");
1358 unindent();
1359 p("}");
1360 }
1361 }
1362 unindent();
1363 p("}");
1364 }
1365 p("return this;");
1366 unindent();
1367 p("}");
1368 p();
1369 }
1370
1371 /**
1372 * @param m
1373 */
1374 private void generateMethodClear(MessageDescriptor m) {
1375 p("public void clear() {");
1376 indent();
1377 for (FieldDescriptor field : m.getFields().values()) {
1378 String uname = uCamel(field.getName());
1379 p("clear" + uname + "();");
1380 }
1381 unindent();
1382 p("}");
1383 p();
1384 }
1385
1386 private void generateReadWriteExternal(MessageDescriptor m) {
1387
1388 p("public void readExternal(java.io.DataInput in) throws java.io.IOException {");
1389 indent();
1390 p("assert frozen==null : org.fusesource.hawtbuf.proto.MessageBufferSupport.FORZEN_ERROR_MESSAGE;");
1391 p("bean = this;");
1392 p("frozen = null;");
1393
1394 for (FieldDescriptor field : m.getFields().values()) {
1395 String lname = lCamel(field.getName());
1396 String type = javaType(field);
1397 boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE;
1398
1399 // Create the fields..
1400 if (repeated) {
1401 p("{");
1402 indent();
1403 p("int size = in.readShort();");
1404 p("if( size>=0 ) {");
1405 indent();
1406 p("f_" + lname + " = new java.util.ArrayList<" + javaCollectionType(field) + ">(size);");
1407 p("for(int i=0; i<size; i++) {");
1408 indent();
1409 if (field.isInteger32Type()) {
1410 p("f_" + lname + ".add(in.readInt());");
1411 } else if (field.isInteger64Type()) {
1412 p("f_" + lname + ".add(in.readLong());");
1413 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
1414 p("f_" + lname + ".add(in.readDouble());");
1415 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
1416 p("f_" + lname + ".add(in.readFloat());");
1417 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
1418 p("f_" + lname + ".add(in.readBoolean());");
1419 } else if (field.getType() == FieldDescriptor.STRING_TYPE) {
1420 p("f_" + lname + ".add(in.readUTF());");
1421 } else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
1422 p("byte b[] = new byte[in.readInt()];");
1423 p("in.readFully(b);");
1424 p("f_" + lname + ".add(new " + type + "(b));");
1425 } else if (field.getTypeDescriptor().isEnum()) {
1426 p("f_" + lname + ".add(" + type + ".valueOf(in.readShort()));");
1427 } else {
1428 p("" + qualified(type, beanCN) + " o = new " + qualified(type, beanCN) + "();");
1429 p("o.readExternal(in);");
1430 p("f_" + lname + ".add(o);");
1431 }
1432 unindent();
1433 p("}");
1434 unindent();
1435 p("} else {");
1436 indent();
1437 p("f_" + lname + " = null;");
1438 unindent();
1439 p("}");
1440 unindent();
1441 p("}");
1442
1443 } else {
1444 if (field.isInteger32Type()) {
1445 p("f_" + lname + " = in.readInt();");
1446 p("b_" + lname + " = true;");
1447 } else if (field.isInteger64Type()) {
1448 p("f_" + lname + " = in.readLong();");
1449 p("b_" + lname + " = true;");
1450 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
1451 p("f_" + lname + " = in.readDouble();");
1452 p("b_" + lname + " = true;");
1453 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
1454 p("f_" + lname + " = in.readFloat();");
1455 p("b_" + lname + " = true;");
1456 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
1457 p("f_" + lname + " = in.readBoolean();");
1458 p("b_" + lname + " = true;");
1459 } else if (field.getType() == FieldDescriptor.STRING_TYPE) {
1460 p("if( in.readBoolean() ) {");
1461 indent();
1462 p("f_" + lname + " = in.readUTF();");
1463 unindent();
1464 p("} else {");
1465 indent();
1466 p("f_" + lname + " = null;");
1467 unindent();
1468 p("}");
1469 } else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
1470 p("{");
1471 indent();
1472 p("int size = in.readInt();");
1473 p("if( size>=0 ) {");
1474 indent();
1475 p("byte b[] = new byte[size];");
1476 p("in.readFully(b);");
1477 p("f_" + lname + " = new " + type + "(b);");
1478 unindent();
1479 p("} else {");
1480 indent();
1481 p("f_" + lname + " = null;");
1482 unindent();
1483 p("}");
1484 unindent();
1485 p("}");
1486 } else if (field.getTypeDescriptor().isEnum()) {
1487 p("if( in.readBoolean() ) {");
1488 indent();
1489 p("f_" + lname + " = " + type + ".valueOf(in.readShort());");
1490 unindent();
1491 p("} else {");
1492 indent();
1493 p("f_" + lname + " = null;");
1494 unindent();
1495 p("}");
1496 } else {
1497 p("if( in.readBoolean() ) {");
1498 indent();
1499 String factoryType = javaFactoryType(field.getTypeDescriptor());
1500 p("" + qualified(factoryType, beanCN) + " o = new " + qualified(factoryType, beanCN) + "();");
1501 p("o.readExternal(in);");
1502 p("f_" + lname + " = o;");
1503 unindent();
1504 p("} else {");
1505 indent();
1506 p("f_" + lname + " = null;");
1507 unindent();
1508 p("}");
1509 }
1510 }
1511 }
1512
1513 unindent();
1514 p("}");
1515 p();
1516 p("public void writeExternal(java.io.DataOutput out) throws java.io.IOException {");
1517 indent();
1518 for (FieldDescriptor field : m.getFields().values()) {
1519 String lname = lCamel(field.getName());
1520 boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE;
1521
1522 // Create the fields..
1523 if (repeated) {
1524 p("if( bean.f_" + lname + "!=null ) {");
1525 indent();
1526 p("out.writeShort(bean.f_" + lname + ".size());");
1527 p("for(" + javaCollectionType(field) + " o : bean.f_" + lname + ") {");
1528 indent();
1529
1530 if (field.isInteger32Type()) {
1531 p("out.writeInt(o);");
1532 } else if (field.isInteger64Type()) {
1533 p("out.writeLong(o);");
1534 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
1535 p("out.writeDouble(o);");
1536 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
1537 p("out.writeFloat(o);");
1538 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
1539 p("out.writeBoolean(o);");
1540 } else if (field.getType() == FieldDescriptor.STRING_TYPE) {
1541 p("out.writeUTF(o);");
1542 } else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
1543 p("out.writeInt(o.getLength());");
1544 p("out.write(o.getData(), o.getOffset(), o.getLength());");
1545 } else if (field.getTypeDescriptor().isEnum()) {
1546 p("out.writeShort(o.getNumber());");
1547 } else {
1548 p("o.copy().writeExternal(out);");
1549 }
1550 unindent();
1551 p("}");
1552 unindent();
1553 p("} else {");
1554 indent();
1555 p("out.writeShort(-1);");
1556 unindent();
1557 p("}");
1558
1559 } else {
1560 if (field.isInteger32Type()) {
1561 p("out.writeInt(bean.f_" + lname + ");");
1562 } else if (field.isInteger64Type()) {
1563 p("out.writeLong(bean.f_" + lname + ");");
1564 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
1565 p("out.writeDouble(bean.f_" + lname + ");");
1566 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
1567 p("out.writeFloat(bean.f_" + lname + ");");
1568 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
1569 p("out.writeBoolean(bean.f_" + lname + ");");
1570 } else if (field.getType() == FieldDescriptor.STRING_TYPE) {
1571 p("if( bean.f_" + lname + "!=null ) {");
1572 indent();
1573 p("out.writeBoolean(true);");
1574 p("out.writeUTF(bean.f_" + lname + ");");
1575 unindent();
1576 p("} else {");
1577 indent();
1578 p("out.writeBoolean(false);");
1579 unindent();
1580 p("}");
1581 } else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
1582 p("if( bean.f_" + lname + "!=null ) {");
1583 indent();
1584 p("out.writeInt(bean.f_" + lname + ".getLength());");
1585 p("out.write(bean.f_" + lname + ".getData(), bean.f_" + lname + ".getOffset(), bean.f_" + lname + ".getLength());");
1586 unindent();
1587 p("} else {");
1588 indent();
1589 p("out.writeInt(-1);");
1590 unindent();
1591 p("}");
1592 } else if (field.getTypeDescriptor().isEnum()) {
1593 p("if( bean.f_" + lname + "!=null ) {");
1594 indent();
1595 p("out.writeBoolean(true);");
1596 p("out.writeShort(bean.f_" + lname + ".getNumber());");
1597 unindent();
1598 p("} else {");
1599 indent();
1600 p("out.writeBoolean(false);");
1601 unindent();
1602 p("}");
1603 } else {
1604 p("if( bean.f_" + lname + "!=null ) {");
1605 indent();
1606 p("out.writeBoolean(true);");
1607 p("bean.f_" + lname + ".copy().writeExternal(out);");
1608 unindent();
1609 p("} else {");
1610 indent();
1611 p("out.writeBoolean(false);");
1612 unindent();
1613 p("}");
1614 }
1615 }
1616 }
1617
1618 unindent();
1619 p("}");
1620 p();
1621
1622 }
1623
1624
1625 // private void generateMethodAssertInitialized(MessageDescriptor m, String className) {
1626 //
1627 // p("public java.util.ArrayList<String> missingFields() {");
1628 // indent();
1629 // p("java.util.ArrayList<String> missingFields = super.missingFields();");
1630 //
1631 // for (FieldDescriptor field : m.getFields().values()) {
1632 // String uname = uCamel(field.getName());
1633 // if( field.isRequired() ) {
1634 // p("if( !has" + uname + "() ) {");
1635 // indent();
1636 // p("missingFields.add(\""+field.getName()+"\");");
1637 // unindent();
1638 // p("}");
1639 // }
1640 // }
1641 //
1642 // if( !deferredDecode ) {
1643 // for (FieldDescriptor field : m.getFields().values()) {
1644 // if( field.getTypeDescriptor()!=null && !field.getTypeDescriptor().isEnum()) {
1645 // String uname = uCamel(field.getName());
1646 // p("if( has" + uname + "() ) {");
1647 // indent();
1648 // if( !field.isRepeated() ) {
1649 // p("try {");
1650 // indent();
1651 // p("get" + uname + "().assertInitialized();");
1652 // unindent();
1653 // p("} catch (org.fusesource.hawtbuf.proto.UninitializedMessageException e){");
1654 // indent();
1655 // p("missingFields.addAll(prefix(e.getMissingFields(),\""+field.getName()+".\"));");
1656 // unindent();
1657 // p("}");
1658 // } else {
1659 // String type = javaCollectionType(field);
1660 // p("java.util.List<"+type+"> l = get" + uname + "List();");
1661 // p("for( int i=0; i < l.size(); i++ ) {");
1662 // indent();
1663 // p("try {");
1664 // indent();
1665 // p("l.get(i).assertInitialized();");
1666 // unindent();
1667 // p("} catch (org.fusesource.hawtbuf.proto.UninitializedMessageException e){");
1668 // indent();
1669 // p("missingFields.addAll(prefix(e.getMissingFields(),\""+field.getName()+"[\"+i+\"]\"));");
1670 // unindent();
1671 // p("}");
1672 // unindent();
1673 // p("}");
1674 // }
1675 // unindent();
1676 // p("}");
1677 // }
1678 // }
1679 // }
1680 // p("return missingFields;");
1681 // unindent();
1682 // p("}");
1683 // p();
1684 // }
1685
1686 private void generateMethodToString(MessageDescriptor m) {
1687
1688 p("public String toString() {");
1689 indent();
1690 p("return toString(new java.lang.StringBuilder(), \"\").toString();");
1691 unindent();
1692 p("}");
1693 p();
1694
1695 p("public java.lang.StringBuilder toString(java.lang.StringBuilder sb, String prefix) {");
1696 indent();
1697 for (FieldDescriptor field : m.getFields().values()) {
1698 String uname = uCamel(field.getName());
1699 p("if( has" + uname + "() ) {");
1700 indent();
1701 if (field.isRepeated()) {
1702 String type = javaCollectionType(field);
1703 p("java.util.List<" + type + "> l = get" + uname + "List();");
1704 p("for( int i=0; i < l.size(); i++ ) {");
1705 indent();
1706 if (field.getTypeDescriptor() != null && !field.getTypeDescriptor().isEnum()) {
1707 p("sb.append(prefix+\"" + field.getName() + "[\"+i+\"] {\\n\");");
1708 p("l.get(i).toString(sb, prefix+\" \");");
1709 p("sb.append(prefix+\"}\\n\");");
1710 } else {
1711 p("sb.append(prefix+\"" + field.getName() + "[\"+i+\"]: \");");
1712 p("sb.append(l.get(i));");
1713 p("sb.append(\"\\n\");");
1714 }
1715 unindent();
1716 p("}");
1717 } else {
1718 if (field.getTypeDescriptor() != null && !field.getTypeDescriptor().isEnum()) {
1719 p("sb.append(prefix+\"" + field.getName() + " {\\n\");");
1720 p("get" + uname + "().toString(sb, prefix+\" \");");
1721 p("sb.append(prefix+\"}\\n\");");
1722 } else {
1723 p("sb.append(prefix+\"" + field.getName() + ": \");");
1724 p("sb.append(get" + uname + "());");
1725 p("sb.append(\"\\n\");");
1726 }
1727 }
1728 unindent();
1729 p("}");
1730 }
1731 p("return sb;");
1732 unindent();
1733 p("}");
1734 p();
1735
1736 }
1737
1738 /**
1739 * @param field
1740 */
1741 private void generateBufferGetters(FieldDescriptor field) {
1742 String uname = uCamel(field.getName());
1743 String type = field.getRule() == FieldDescriptor.REPEATED_RULE ? javaCollectionType(field) : javaType(field);
1744 boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE;
1745
1746 // Create the fields..
1747 p("// " + field.getRule() + " " + field.getType() + " " + field.getName() + " = " + field.getTag() + ";");
1748 if (repeated) {
1749 // Create the field accessors
1750 p("public boolean has" + uname + "() {");
1751 indent();
1752 p("return bean().has" + uname + "();");
1753 unindent();
1754 p("}");
1755 p();
1756 p("public java.util.List<" + type + "> get" + uname + "List() {");
1757 indent();
1758 p("return bean().get" + uname + "List();");
1759 unindent();
1760 p("}");
1761 p();
1762 p("public int get" + uname + "Count() {");
1763 indent();
1764 p("return bean().get" + uname + "Count();");
1765 unindent();
1766 p("}");
1767 p();
1768 p("public " + type + " get" + uname + "(int index) {");
1769 indent();
1770 p("return bean().get" + uname + "(index);");
1771 unindent();
1772 p("}");
1773 p();
1774 } else {
1775 // Create the field accessors
1776 p("public boolean has" + uname + "() {");
1777 indent();
1778 p("return bean().has" + uname + "();");
1779 unindent();
1780 p("}");
1781 p();
1782 p("public " + type + " get" + uname + "() {");
1783 indent();
1784 p("return bean().get" + uname + "();");
1785 unindent();
1786 p("}");
1787 p();
1788 }
1789 }
1790
1791 /**
1792 * @param field
1793 */
1794 private void generateFieldGetterSignatures(FieldDescriptor field) {
1795 String uname = uCamel(field.getName());
1796 String type = field.getRule() == FieldDescriptor.REPEATED_RULE ? javaCollectionType(field) : javaType(field);
1797 boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE;
1798
1799 // Create the fields..
1800 p("// " + field.getRule() + " " + field.getType() + " " + field.getName() + " = " + field.getTag() + ";");
1801 if (repeated) {
1802 // Create the field accessors
1803 p("public boolean has" + uname + "();");
1804 p("public java.util.List<" + type + "> get" + uname + "List();");
1805 p("public int get" + uname + "Count();");
1806 p("public " + type + " get" + uname + "(int index);");
1807 } else {
1808 // Create the field accessors
1809 p("public boolean has" + uname + "();");
1810 p("public " + type + " get" + uname + "();");
1811 }
1812 }
1813
1814
1815 /**
1816 * @param field
1817 */
1818 private void generateFieldAccessor(String beanClassName, FieldDescriptor field) {
1819
1820 String lname = lCamel(field.getName());
1821 String uname = uCamel(field.getName());
1822 String type = field.getRule() == FieldDescriptor.REPEATED_RULE ? javaCollectionType(field) : javaType(field);
1823 String typeDefault = javaTypeDefault(field);
1824 boolean primitive = isPrimitive(type);
1825 boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE;
1826
1827 // Create the fields..
1828 p("// " + field.getRule() + " " + field.getType() + " " + field.getName() + " = " + field.getTag() + ";");
1829
1830 if (repeated) {
1831 p("private java.util.List<" + type + "> f_" + lname + ";");
1832 p();
1833
1834 // Create the field accessors
1835 p("public boolean has" + uname + "() {");
1836 indent();
1837 p("return bean.f_" + lname + "!=null && !bean.f_" + lname + ".isEmpty();");
1838 unindent();
1839 p("}");
1840 p();
1841
1842 p("public java.util.List<" + type + "> get" + uname + "List() {");
1843 indent();
1844 p("return bean.f_" + lname + ";");
1845 unindent();
1846 p("}");
1847 p();
1848
1849 p("public java.util.List<" + type + "> create" + uname + "List() {");
1850 indent();
1851 p("copyCheck();");
1852 p("if( this.f_" + lname + " == null ) {");
1853 indent();
1854 p("this.f_" + lname + " = new java.util.ArrayList<" + type + ">();");
1855 unindent();
1856 p("}");
1857 p("return bean.f_" + lname + ";");
1858 unindent();
1859 p("}");
1860 p();
1861
1862 p("public " + beanClassName + " set" + uname + "List(java.util.List<" + type + "> " + lname + ") {");
1863 indent();
1864 p("copyCheck();");
1865 p("this.f_" + lname + " = " + lname + ";");
1866 p("return this;");
1867 unindent();
1868 p("}");
1869 p();
1870
1871 p("public int get" + uname + "Count() {");
1872 indent();
1873 p("if( bean.f_" + lname + " == null ) {");
1874 indent();
1875 p("return 0;");
1876 unindent();
1877 p("}");
1878 p("return bean.f_" + lname + ".size();");
1879 unindent();
1880 p("}");
1881 p();
1882
1883 p("public " + type + " get" + uname + "(int index) {");
1884 indent();
1885 p("if( bean.f_" + lname + " == null ) {");
1886 indent();
1887 p("return null;");
1888 unindent();
1889 p("}");
1890 p("return bean.f_" + lname + ".get(index);");
1891 unindent();
1892 p("}");
1893 p();
1894
1895 p("public " + beanClassName + " set" + uname + "(int index, " + type + " value) {");
1896 indent();
1897 p("this.create" + uname + "List().set(index, value);");
1898 p("return this;");
1899 unindent();
1900 p("}");
1901 p();
1902
1903 p("public " + beanClassName + " add" + uname + "(" + type + " value) {");
1904 indent();
1905 p("this.create" + uname + "List().add(value);");
1906 p("return this;");
1907 unindent();
1908 p("}");
1909 p();
1910
1911 p("public " + beanClassName + " addAll" + uname + "(java.lang.Iterable<? extends " + type + "> collection) {");
1912 indent();
1913 p("org.fusesource.hawtbuf.proto.MessageBufferSupport.addAll(collection, this.create" + uname + "List());");
1914 p("return this;");
1915 unindent();
1916 p("}");
1917 p();
1918
1919 p("public void clear" + uname + "() {");
1920 indent();
1921 p("copyCheck();");
1922 p("this.f_" + lname + " = null;");
1923 unindent();
1924 p("}");
1925 p();
1926
1927 } else {
1928
1929 p("private " + type + " f_" + lname + " = " + typeDefault + ";");
1930 if (primitive) {
1931 p("private boolean b_" + lname + ";");
1932 }
1933 p();
1934
1935 // Create the field accessors
1936 p("public boolean has" + uname + "() {");
1937 indent();
1938 if (primitive) {
1939 p("return bean.b_" + lname + ";");
1940 } else {
1941 p("return bean.f_" + lname + "!=null;");
1942 }
1943 unindent();
1944 p("}");
1945 p();
1946
1947 p("public " + type + " get" + uname + "() {");
1948 indent();
1949 p("return bean.f_" + lname + ";");
1950 unindent();
1951 p("}");
1952 p();
1953
1954 p("public " + beanClassName + " set" + uname + "(" + type + " " + lname + ") {");
1955 indent();
1956 p("copyCheck();");
1957 if (primitive) {
1958 if (auto_clear_optional_fields && field.isOptional()) {
1959 if (field.isStringType() && !"null".equals(typeDefault)) {
1960 p("this.b_" + lname + " = (" + lname + " != " + typeDefault + ");");
1961 } else {
1962 p("this.b_" + lname + " = (" + lname + " != " + typeDefault + ");");
1963 }
1964 } else {
1965 p("this.b_" + lname + " = true;");
1966 }
1967 }
1968 p("this.f_" + lname + " = " + lname + ";");
1969 p("return this;");
1970 unindent();
1971 p("}");
1972 p();
1973
1974 p("public void clear" + uname + "() {");
1975 indent();
1976 p("copyCheck();");
1977 if (primitive) {
1978 p("this.b_" + lname + " = false;");
1979 }
1980 p("this.f_" + lname + " = " + typeDefault + ";");
1981 unindent();
1982 p("}");
1983 p();
1984 }
1985
1986 }
1987
1988 private String javaTypeDefault(FieldDescriptor field) {
1989 OptionDescriptor defaultOption = field.getOptions().get("default");
1990 if (defaultOption != null) {
1991 if (field.isStringType()) {
1992 return asJavaString(defaultOption.getValue());
1993 } else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
1994 return "new " + javaType(field) + "(org.fusesource.hawtbuf.UTF8Buffer.encode(" + asJavaString(defaultOption.getValue()) + "))";
1995 } else if (field.isInteger32Type()) {
1996 int v;
1997 if (field.getType() == FieldDescriptor.UINT32_TYPE) {
1998 v = TextFormat.parseUInt32(defaultOption.getValue());
1999 } else {
2000 v = TextFormat.parseInt32(defaultOption.getValue());
2001 }
2002 return "" + v;
2003 } else if (field.isInteger64Type()) {
2004 long v;
2005 if (field.getType() == FieldDescriptor.UINT64_TYPE) {
2006 v = TextFormat.parseUInt64(defaultOption.getValue());
2007 } else {
2008 v = TextFormat.parseInt64(defaultOption.getValue());
2009 }
2010 return "" + v + "l";
2011 } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
2012 double v = Double.valueOf(defaultOption.getValue());
2013 return "" + v + "d";
2014 } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
2015 float v = Float.valueOf(defaultOption.getValue());
2016 return "" + v + "f";
2017 } else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
2018 boolean v = Boolean.valueOf(defaultOption.getValue());
2019 return "" + v;
2020 } else if (field.getTypeDescriptor() != null && field.getTypeDescriptor().isEnum()) {
2021 return javaType(field) + "." + defaultOption.getValue();
2022 }
2023 return defaultOption.getValue();
2024 } else {
2025 if (field.isNumberType()) {
2026 return "0";
2027 }
2028 if (field.getType() == FieldDescriptor.BOOL_TYPE) {
2029 return "false";
2030 }
2031 return "null";
2032 }
2033 }
2034
2035 static final char HEX_TABLE[] = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
2036
2037 private String asJavaString(String value) {
2038 StringBuilder sb = new StringBuilder(value.length() + 2);
2039 sb.append("\"");
2040 for (int i = 0; i < value.length(); i++) {
2041
2042 char b = value.charAt(i);
2043 switch (b) {
2044 // Java does not recognize \a or \v, apparently.
2045 case '\b':
2046 sb.append("\\b");
2047 break;
2048 case '\f':
2049 sb.append("\\f");
2050 break;
2051 case '\n':
2052 sb.append("\\n");
2053 break;
2054 case '\r':
2055 sb.append("\\r");
2056 break;
2057 case '\t':
2058 sb.append("\\t");
2059 break;
2060 case '\\':
2061 sb.append("\\\\");
2062 break;
2063 case '\'':
2064 sb.append("\\\'");
2065 break;
2066 case '"':
2067 sb.append("\\\"");
2068 break;
2069 default:
2070 if (b >= 0x20 && b < 'Z') {
2071 sb.append((char) b);
2072 } else {
2073 sb.append("\\u");
2074 sb.append(HEX_TABLE[(b >>> 12) & 0x0F]);
2075 sb.append(HEX_TABLE[(b >>> 8) & 0x0F]);
2076 sb.append(HEX_TABLE[(b >>> 4) & 0x0F]);
2077 sb.append(HEX_TABLE[b & 0x0F]);
2078 }
2079 break;
2080 }
2081
2082 }
2083 sb.append("\"");
2084 return sb.toString();
2085 }
2086
2087 private void generateEnum(EnumDescriptor ed) {
2088 String uname = uCamel(ed.getName());
2089
2090 String staticOption = "static ";
2091 if (multipleFiles && ed.getParent() == null) {
2092 staticOption = "";
2093 }
2094
2095 // TODO Auto-generated method stub
2096 p();
2097 p("public " + staticOption + "enum " + uname + " {");
2098 indent();
2099
2100
2101 p();
2102 int counter = 0;
2103 for (EnumFieldDescriptor field : ed.getFields().values()) {
2104 boolean last = counter + 1 == ed.getFields().size();
2105 p(field.getName() + "(\"" + field.getName() + "\", " + field.getValue() + ")" + (last ? ";" : ","));
2106 counter++;
2107 }
2108 p();
2109 p("private final String name;");
2110 p("private final int value;");
2111 p();
2112 p("private " + uname + "(String name, int value) {");
2113 p(" this.name = name;");
2114 p(" this.value = value;");
2115 p("}");
2116 p();
2117 p("public final int getNumber() {");
2118 p(" return value;");
2119 p("}");
2120 p();
2121 p("public final String toString() {");
2122 p(" return name;");
2123 p("}");
2124 p();
2125 p("public static " + uname + " valueOf(int value) {");
2126 p(" switch (value) {");
2127
2128 // It's possible to define multiple ENUM fields with the same value..
2129 // we only want to put the first one into the switch statement.
2130 HashSet<Integer> values = new HashSet<Integer>();
2131 for (EnumFieldDescriptor field : ed.getFields().values()) {
2132 if (!values.contains(field.getValue())) {
2133 p(" case " + field.getValue() + ":");
2134 p(" return " + field.getName() + ";");
2135 values.add(field.getValue());
2136 }
2137
2138 }
2139 p(" default:");
2140 p(" return null;");
2141 p(" }");
2142 p("}");
2143 p();
2144
2145
2146 String createMessage = getOption(ed.getOptions(), "java_create_message", null);
2147 if ("true".equals(createMessage)) {
2148
2149 p("public interface " + uname + "Creatable {");
2150 indent();
2151 p("" + uname + " to" + uname + "();");
2152 unindent();
2153 p("}");
2154 p();
2155
2156 p("public " + uname + "Creatable createBean() {");
2157 indent();
2158 p("switch (this) {");
2159 indent();
2160 for (EnumFieldDescriptor field : ed.getFields().values()) {
2161 p("case " + field.getName() + ":");
2162 String type = field.getAssociatedType().getName();
2163 p(" return new " + qualified(type, beanCN) + "();");
2164 }
2165 p("default:");
2166 p(" return null;");
2167 unindent();
2168 p("}");
2169 unindent();
2170 p("}");
2171 p();
2172
2173 generateParseDelegate(ed, "parseUnframed", "org.fusesource.hawtbuf.Buffer", "org.fusesource.hawtbuf.proto.InvalidProtocolBufferException");
2174 generateParseDelegate(ed, "parseFramed", "org.fusesource.hawtbuf.Buffer", "org.fusesource.hawtbuf.proto.InvalidProtocolBufferException");
2175 generateParseDelegate(ed, "parseUnframed", "byte[]", "org.fusesource.hawtbuf.proto.InvalidProtocolBufferException");
2176 generateParseDelegate(ed, "parseFramed", "byte[]", "org.fusesource.hawtbuf.proto.InvalidProtocolBufferException");
2177 generateParseDelegate(ed, "parseFramed", "org.fusesource.hawtbuf.proto.CodedInputStream", "org.fusesource.hawtbuf.proto.InvalidProtocolBufferException, java.io.IOException");
2178 generateParseDelegate(ed, "parseFramed", "java.io.InputStream", "org.fusesource.hawtbuf.proto.InvalidProtocolBufferException, java.io.IOException");
2179 }
2180
2181 unindent();
2182 p("}");
2183 p();
2184 }
2185
2186 private void generateParseDelegate(EnumDescriptor descriptor, String methodName, String inputType, String exceptions) {
2187 p("public org.fusesource.hawtbuf.proto.MessageBuffer " + methodName + "(" + inputType + " data) throws " + exceptions + " {");
2188 indent();
2189 p("switch (this) {");
2190 indent();
2191 for (EnumFieldDescriptor field : descriptor.getFields().values()) {
2192 p("case " + field.getName() + ":");
2193 String type = constantToUCamelCase(field.getName());
2194 p(" return " + qualified(type, factoryFeild) + "." + methodName + "(data);");
2195 }
2196 p("default:");
2197 p(" return null;");
2198 unindent();
2199 p("}");
2200 unindent();
2201 p("}");
2202 p();
2203 }
2204
2205
2206 private String javaCollectionType(FieldDescriptor field) {
2207 if (field.isInteger32Type()) {
2208 return "java.lang.Integer";
2209 }
2210 if (field.isInteger64Type()) {
2211 return "java.lang.Long";
2212 }
2213 if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
2214 return "java.lang.Double";
2215 }
2216 if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
2217 return "java.lang.Float";
2218 }
2219 if (field.getType() == FieldDescriptor.STRING_TYPE) {
2220 // TODO: support handling string fields as buffers.
2221 // String override = getOption(field.getOptions(), "java_override_type", null);
2222 // if( "AsciiBuffer".equals(override) ) {
2223 // return "org.fusesource.hawtbuf.AsciiBuffer";
2224 // } else if( "UTF8Buffer".equals(override) ) {
2225 // return "org.fusesource.hawtbuf.UTF8Buffer";
2226 // } else if( "Buffer".equals(override) ) {
2227 // return "org.fusesource.hawtbuf.Buffer";
2228 // } else {
2229 return "java.lang.String";
2230 // }
2231 }
2232 if (field.getType() == FieldDescriptor.BYTES_TYPE) {
2233 String override = getOption(field.getOptions(), "java_override_type", null);
2234 if ("AsciiBuffer".equals(override)) {
2235 return "org.fusesource.hawtbuf.AsciiBuffer";
2236 } else if ("UTF8Buffer".equals(override)) {
2237 return "org.fusesource.hawtbuf.UTF8Buffer";
2238 } else {
2239 return "org.fusesource.hawtbuf.Buffer";
2240 }
2241 }
2242 if (field.getType() == FieldDescriptor.BOOL_TYPE) {
2243 return "java.lang.Boolean";
2244 }
2245
2246 TypeDescriptor descriptor = field.getTypeDescriptor();
2247 return qualified(javaFactoryType(descriptor), getterCN);
2248 }
2249
2250 private String javaType(FieldDescriptor field) {
2251 if (field.isInteger32Type()) {
2252 return "int";
2253 }
2254 if (field.isInteger64Type()) {
2255 return "long";
2256 }
2257 if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
2258 return "double";
2259 }
2260 if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
2261 return "float";
2262 }
2263 if (field.getType() == FieldDescriptor.STRING_TYPE) {
2264 // TODO: support handling string fields as buffers.
2265 // String override = getOption(field.getOptions(), "java_override_type", null);
2266 // if( "AsciiBuffer".equals(override) ) {
2267 // return "org.fusesource.hawtbuf.AsciiBuffer";
2268 // } else if( "UTF8Buffer".equals(override) ) {
2269 // return "org.fusesource.hawtbuf.UTF8Buffer";
2270 // } else if( "Buffer".equals(override) ) {
2271 // return "org.fusesource.hawtbuf.Buffer";
2272 // } else {
2273 return "java.lang.String";
2274 // }
2275 }
2276 if (field.getType() == FieldDescriptor.BYTES_TYPE) {
2277 String override = getOption(field.getOptions(), "java_override_type", null);
2278 if ("AsciiBuffer".equals(override)) {
2279 return "org.fusesource.hawtbuf.AsciiBuffer";
2280 } else if ("UTF8Buffer".equals(override)) {
2281 return "org.fusesource.hawtbuf.UTF8Buffer";
2282 } else {
2283 return "org.fusesource.hawtbuf.Buffer";
2284 }
2285 }
2286 if (field.getType() == FieldDescriptor.BOOL_TYPE) {
2287 return "boolean";
2288 }
2289
2290 TypeDescriptor descriptor = field.getTypeDescriptor();
2291 return qualified(javaFactoryType(descriptor), getterCN);
2292 }
2293
2294 private String javaFactoryType(TypeDescriptor descriptor) {
2295 ProtoDescriptor p = descriptor.getProtoDescriptor();
2296 if (p != proto) {
2297 // Try to keep it short..
2298 String othePackage = javaPackage(p);
2299 if (equals(othePackage, javaPackage(proto))) {
2300 return javaClassName(p) + "." + descriptor.getQName();
2301 }
2302 // Use the fully qualified class name.
2303 return othePackage + "." + javaClassName(p) + "." + descriptor.getQName();
2304 }
2305 return descriptor.getQName();
2306 }
2307
2308 private String qualified(String type, String suffix) {
2309 // int ix = type.lastIndexOf(".");
2310 // if (ix == -1) {
2311 // // type = Foo, result = Foo.FooBean
2312 // return type+"."+type+suffix;
2313 // }
2314 // // type = Foo.Bar, result = Foo.Bar.BarBean
2315 // return type+"."+type.substring(ix+1)+suffix;
2316 return type + "." + suffix;
2317 }
2318
2319 private boolean equals(String o1, String o2) {
2320 if (o1 == o2)
2321 return true;
2322 if (o1 == null || o2 == null)
2323 return false;
2324 return o1.equals(o2);
2325 }
2326
2327 private String javaClassName(ProtoDescriptor proto) {
2328 return getOption(proto.getOptions(), "java_outer_classname", uCamel(removeFileExtension(proto.getName())));
2329 }
2330
2331 private boolean isMultipleFilesEnabled(ProtoDescriptor proto) {
2332 return "true".equals(getOption(proto.getOptions(), "java_multiple_files", "false"));
2333 }
2334
2335
2336 private String javaPackage(ProtoDescriptor proto) {
2337 String name = proto.getPackageName();
2338 if (name != null) {
2339 name = name.replace('-', '.');
2340 name = name.replace('/', '.');
2341 }
2342 return getOption(proto.getOptions(), "java_package", name);
2343 }
2344
2345
2346 // ----------------------------------------------------------------
2347 // Internal Helper methods
2348 // ----------------------------------------------------------------
2349
2350 private void indent() {
2351 indent++;
2352 }
2353
2354 private void unindent() {
2355 indent--;
2356 }
2357
2358 private void p(String line) {
2359 // Indent...
2360 for (int i = 0; i < indent; i++) {
2361 w.print(" ");
2362 }
2363 // Then print.
2364 w.println(line);
2365 }
2366
2367 private void p() {
2368 w.println();
2369 }
2370
2371 private String getOption(Map<String, OptionDescriptor> options, String optionName, String defaultValue) {
2372 OptionDescriptor optionDescriptor = options.get(optionName);
2373 if (optionDescriptor == null) {
2374 return defaultValue;
2375 }
2376 return optionDescriptor.getValue();
2377 }
2378
2379 static private String removeFileExtension(String name) {
2380 return name.replaceAll("\\..*", "");
2381 }
2382
2383 static private String uCamel(String name) {
2384 boolean upNext = true;
2385 StringBuilder sb = new StringBuilder();
2386 for (int i = 0; i < name.length(); i++) {
2387 char c = name.charAt(i);
2388 if (Character.isJavaIdentifierPart(c) && Character.isLetterOrDigit(c)) {
2389 if (upNext) {
2390 c = Character.toUpperCase(c);
2391 upNext = false;
2392 }
2393 sb.append(c);
2394 } else {
2395 upNext = true;
2396 }
2397 }
2398 return sb.toString();
2399 }
2400
2401 static private String lCamel(String name) {
2402 if (name == null || name.length() < 1)
2403 return name;
2404 String uCamel = uCamel(name);
2405 return uCamel.substring(0, 1).toLowerCase() + uCamel.substring(1);
2406 }
2407
2408
2409 private String constantToUCamelCase(String name) {
2410 boolean upNext = true;
2411 StringBuilder sb = new StringBuilder();
2412 for (int i = 0; i < name.length(); i++) {
2413 char c = name.charAt(i);
2414 if (Character.isJavaIdentifierPart(c) && Character.isLetterOrDigit(c)) {
2415 if (upNext) {
2416 c = Character.toUpperCase(c);
2417 upNext = false;
2418 } else {
2419 c = Character.toLowerCase(c);
2420 }
2421 sb.append(c);
2422 } else {
2423 upNext = true;
2424 }
2425 }
2426 return sb.toString();
2427 }
2428
2429
2430 private String constantCase(String name) {
2431 StringBuilder sb = new StringBuilder();
2432 for (int i = 0; i < name.length(); i++) {
2433 char c = name.charAt(i);
2434 if (i != 0 && Character.isUpperCase(c)) {
2435 sb.append("_");
2436 }
2437 sb.append(Character.toUpperCase(c));
2438 }
2439 return sb.toString();
2440 }
2441
2442 public File getOut() {
2443 return out;
2444 }
2445
2446 public void setOut(File outputDirectory) {
2447 this.out = outputDirectory;
2448 }
2449
2450 public File[] getPath() {
2451 return path;
2452 }
2453
2454 public void setPath(File[] path) {
2455 this.path = path;
2456 }
2457
2458 }