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 }