JRecord.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:33k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.record.compiler;
  19. import java.io.File;
  20. import java.io.FileWriter;
  21. import java.io.IOException;
  22. import java.util.*;
  23. /**
  24.  */
  25. public class JRecord extends JCompType {
  26.   
  27.   class JavaRecord extends JavaCompType {
  28.     
  29.     private String fullName;
  30.     private String name;
  31.     private String module;
  32.     private ArrayList<JField<JavaType>> fields =
  33.       new ArrayList<JField<JavaType>>();
  34.     
  35.     JavaRecord(String name, ArrayList<JField<JType>> flist) {
  36.       super(name, "Record", name, "TypeID.RIOType.STRUCT");
  37.       this.fullName = name;
  38.       int idx = name.lastIndexOf('.');
  39.       this.name = name.substring(idx+1);
  40.       this.module = name.substring(0, idx);
  41.       for (Iterator<JField<JType>> iter = flist.iterator(); iter.hasNext();) {
  42.         JField<JType> f = iter.next();
  43.         fields.add(new JField<JavaType>(f.getName(), f.getType().getJavaType()));
  44.       }
  45.     }
  46.     
  47.     String getTypeIDObjectString() {
  48.       return "new org.apache.hadoop.record.meta.StructTypeID(" + 
  49.       fullName + ".getTypeInfo())";
  50.     }
  51.     void genSetRTIFilter(CodeBuffer cb, Map<String, Integer> nestedStructMap) {
  52.       // ignore, if we'ev already set the type filter for this record
  53.       if (!nestedStructMap.containsKey(fullName)) {
  54.         // we set the RTI filter here
  55.         cb.append(fullName + ".setTypeFilter(rti.getNestedStructTypeInfo(""+
  56.             name + ""));n");
  57.         nestedStructMap.put(fullName, null);
  58.       }
  59.     }
  60.     // for each typeInfo in the filter, we see if there's a similar one in the record. 
  61.     // Since we store typeInfos in ArrayLists, thsi search is O(n squared). We do it faster
  62.     // if we also store a map (of TypeInfo to index), but since setupRtiFields() is called
  63.     // only once when deserializing, we're sticking with the former, as the code is easier.  
  64.     void genSetupRtiFields(CodeBuffer cb) {
  65.       cb.append("private static void setupRtiFields()n{n");
  66.       cb.append("if (null == " + Consts.RTI_FILTER + ") return;n");
  67.       cb.append("// we may already have done thisn");
  68.       cb.append("if (null != " + Consts.RTI_FILTER_FIELDS + ") return;n");
  69.       cb.append("int " + Consts.RIO_PREFIX + "i, " + Consts.RIO_PREFIX + "j;n");
  70.       cb.append(Consts.RTI_FILTER_FIELDS + " = new int [" + 
  71.           Consts.RIO_PREFIX + "rtiFilter.getFieldTypeInfos().size()];n");
  72.       cb.append("for (" + Consts.RIO_PREFIX + "i=0; " + Consts.RIO_PREFIX + "i<"+
  73.           Consts.RTI_FILTER_FIELDS + ".length; " + Consts.RIO_PREFIX + "i++) {n");
  74.       cb.append(Consts.RTI_FILTER_FIELDS + "[" + Consts.RIO_PREFIX + "i] = 0;n");
  75.       cb.append("}n");
  76.       cb.append("java.util.Iterator<org.apache.hadoop.record.meta." +
  77.           "FieldTypeInfo> " + Consts.RIO_PREFIX + "itFilter = " + 
  78.           Consts.RIO_PREFIX + "rtiFilter.getFieldTypeInfos().iterator();n");
  79.       cb.append(Consts.RIO_PREFIX + "i=0;n");
  80.       cb.append("while (" + Consts.RIO_PREFIX + "itFilter.hasNext()) {n");
  81.       cb.append("org.apache.hadoop.record.meta.FieldTypeInfo " + 
  82.           Consts.RIO_PREFIX + "tInfoFilter = " + 
  83.           Consts.RIO_PREFIX + "itFilter.next();n");
  84.       cb.append("java.util.Iterator<org.apache.hadoop.record.meta." + 
  85.           "FieldTypeInfo> " + Consts.RIO_PREFIX + "it = " + Consts.RTI_VAR + 
  86.           ".getFieldTypeInfos().iterator();n");
  87.       cb.append(Consts.RIO_PREFIX + "j=1;n");
  88.       cb.append("while (" + Consts.RIO_PREFIX + "it.hasNext()) {n");
  89.       cb.append("org.apache.hadoop.record.meta.FieldTypeInfo " + 
  90.           Consts.RIO_PREFIX + "tInfo = " + Consts.RIO_PREFIX + "it.next();n");
  91.       cb.append("if (" + Consts.RIO_PREFIX + "tInfo.equals(" +  
  92.           Consts.RIO_PREFIX + "tInfoFilter)) {n");
  93.       cb.append(Consts.RTI_FILTER_FIELDS + "[" + Consts.RIO_PREFIX + "i] = " +
  94.           Consts.RIO_PREFIX + "j;n");
  95.       cb.append("break;n");
  96.       cb.append("}n");
  97.       cb.append(Consts.RIO_PREFIX + "j++;n");
  98.       cb.append("}n");
  99.       /*int ct = 0;
  100.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  101.         ct++;
  102.         JField<JavaType> jf = i.next();
  103.         JavaType type = jf.getType();
  104.         String name = jf.getName();
  105.         if (ct != 1) {
  106.           cb.append("else ");
  107.         }
  108.         type.genRtiFieldCondition(cb, name, ct);
  109.       }
  110.       if (ct != 0) {
  111.         cb.append("else {n");
  112.         cb.append("rtiFilterFields[i] = 0;n");
  113.         cb.append("}n");
  114.       }*/
  115.       cb.append(Consts.RIO_PREFIX + "i++;n");
  116.       cb.append("}n");
  117.       cb.append("}n");
  118.     }
  119.     void genReadMethod(CodeBuffer cb, String fname, String tag, boolean decl) {
  120.       if (decl) {
  121.         cb.append(fullName+" "+fname+";n");
  122.       }
  123.       cb.append(fname+"= new "+fullName+"();n");
  124.       cb.append(fname+".deserialize(" + Consts.RECORD_INPUT + ",""+tag+"");n");
  125.     }
  126.     
  127.     void genWriteMethod(CodeBuffer cb, String fname, String tag) {
  128.       cb.append(fname+".serialize(" + Consts.RECORD_OUTPUT + ",""+tag+"");n");
  129.     }
  130.     
  131.     void genSlurpBytes(CodeBuffer cb, String b, String s, String l) {
  132.       cb.append("{n");
  133.       cb.append("int r = "+fullName+
  134.                 ".Comparator.slurpRaw("+b+","+s+","+l+");n");
  135.       cb.append(s+"+=r; "+l+"-=r;n");
  136.       cb.append("}n");
  137.     }
  138.     
  139.     void genCompareBytes(CodeBuffer cb) {
  140.       cb.append("{n");
  141.       cb.append("int r1 = "+fullName+
  142.                 ".Comparator.compareRaw(b1,s1,l1,b2,s2,l2);n");
  143.       cb.append("if (r1 <= 0) { return r1; }n");
  144.       cb.append("s1+=r1; s2+=r1; l1-=r1; l2-=r1;n");
  145.       cb.append("}n");
  146.     }
  147.     
  148.     void genCode(String destDir, ArrayList<String> options) throws IOException {
  149.       String pkg = module;
  150.       String pkgpath = pkg.replaceAll("\.", "/");
  151.       File pkgdir = new File(destDir, pkgpath);
  152.       final File jfile = new File(pkgdir, name+".java");
  153.       if (!pkgdir.exists()) {
  154.         // create the pkg directory
  155.         boolean ret = pkgdir.mkdirs();
  156.         if (!ret) {
  157.           throw new IOException("Cannnot create directory: "+pkgpath);
  158.         }
  159.       } else if (!pkgdir.isDirectory()) {
  160.         // not a directory
  161.         throw new IOException(pkgpath+" is not a directory.");
  162.       }
  163.       CodeBuffer cb = new CodeBuffer();
  164.       cb.append("// File generated by hadoop record compiler. Do not edit.n");
  165.       cb.append("package "+module+";nn");
  166.       cb.append("public class "+name+
  167.                 " extends org.apache.hadoop.record.Record {n");
  168.       
  169.       // type information declarations
  170.       cb.append("private static final " + 
  171.           "org.apache.hadoop.record.meta.RecordTypeInfo " + 
  172.           Consts.RTI_VAR + ";n");
  173.       cb.append("private static " + 
  174.           "org.apache.hadoop.record.meta.RecordTypeInfo " + 
  175.           Consts.RTI_FILTER + ";n");
  176.       cb.append("private static int[] " + Consts.RTI_FILTER_FIELDS + ";n");
  177.       
  178.       // static init for type information
  179.       cb.append("static {n");
  180.       cb.append(Consts.RTI_VAR + " = " +
  181.           "new org.apache.hadoop.record.meta.RecordTypeInfo("" +
  182.           name + "");n");
  183.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  184.         JField<JavaType> jf = i.next();
  185.         String name = jf.getName();
  186.         JavaType type = jf.getType();
  187.         type.genStaticTypeInfo(cb, name);
  188.       }
  189.       cb.append("}nn");
  190.       // field definitions
  191.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  192.         JField<JavaType> jf = i.next();
  193.         String name = jf.getName();
  194.         JavaType type = jf.getType();
  195.         type.genDecl(cb, name);
  196.       }
  197.       // default constructor
  198.       cb.append("public "+name+"() { }n");
  199.       
  200.       // constructor
  201.       cb.append("public "+name+"(n");
  202.       int fIdx = 0;
  203.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext(); fIdx++) {
  204.         JField<JavaType> jf = i.next();
  205.         String name = jf.getName();
  206.         JavaType type = jf.getType();
  207.         type.genConstructorParam(cb, name);
  208.         cb.append((!i.hasNext())?"":",n");
  209.       }
  210.       cb.append(") {n");
  211.       fIdx = 0;
  212.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext(); fIdx++) {
  213.         JField<JavaType> jf = i.next();
  214.         String name = jf.getName();
  215.         JavaType type = jf.getType();
  216.         type.genConstructorSet(cb, name);
  217.       }
  218.       cb.append("}n");
  219.       // getter/setter for type info
  220.       cb.append("public static org.apache.hadoop.record.meta.RecordTypeInfo"
  221.               + " getTypeInfo() {n");
  222.       cb.append("return " + Consts.RTI_VAR + ";n");
  223.       cb.append("}n");
  224.       cb.append("public static void setTypeFilter("
  225.           + "org.apache.hadoop.record.meta.RecordTypeInfo rti) {n");
  226.       cb.append("if (null == rti) return;n");
  227.       cb.append(Consts.RTI_FILTER + " = rti;n");
  228.       cb.append(Consts.RTI_FILTER_FIELDS + " = null;n");
  229.       // set RTIFilter for nested structs.
  230.       // To prevent setting up the type filter for the same struct more than once, 
  231.       // we use a hash map to keep track of what we've set. 
  232.       Map<String, Integer> nestedStructMap = new HashMap<String, Integer>();
  233.       for (JField<JavaType> jf : fields) {
  234.         JavaType type = jf.getType();
  235.         type.genSetRTIFilter(cb, nestedStructMap);
  236.       }
  237.       cb.append("}n");
  238.       // setupRtiFields()
  239.       genSetupRtiFields(cb);
  240.       // getters/setters for member variables
  241.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  242.         JField<JavaType> jf = i.next();
  243.         String name = jf.getName();
  244.         JavaType type = jf.getType();
  245.         type.genGetSet(cb, name);
  246.       }
  247.       
  248.       // serialize()
  249.       cb.append("public void serialize("+ 
  250.           "final org.apache.hadoop.record.RecordOutput " + 
  251.           Consts.RECORD_OUTPUT + ", final String " + Consts.TAG + ")n"+
  252.                 "throws java.io.IOException {n");
  253.       cb.append(Consts.RECORD_OUTPUT + ".startRecord(this," + Consts.TAG + ");n");
  254.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  255.         JField<JavaType> jf = i.next();
  256.         String name = jf.getName();
  257.         JavaType type = jf.getType();
  258.         type.genWriteMethod(cb, name, name);
  259.       }
  260.       cb.append(Consts.RECORD_OUTPUT + ".endRecord(this," + Consts.TAG+");n");
  261.       cb.append("}n");
  262.       // deserializeWithoutFilter()
  263.       cb.append("private void deserializeWithoutFilter("+
  264.                 "final org.apache.hadoop.record.RecordInput " + 
  265.                 Consts.RECORD_INPUT + ", final String " + Consts.TAG + ")n"+
  266.                 "throws java.io.IOException {n");
  267.       cb.append(Consts.RECORD_INPUT + ".startRecord(" + Consts.TAG + ");n");
  268.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  269.         JField<JavaType> jf = i.next();
  270.         String name = jf.getName();
  271.         JavaType type = jf.getType();
  272.         type.genReadMethod(cb, name, name, false);
  273.       }
  274.       cb.append(Consts.RECORD_INPUT + ".endRecord(" + Consts.TAG+");n");
  275.       cb.append("}n");
  276.       
  277.       // deserialize()
  278.       cb.append("public void deserialize(final " +
  279.           "org.apache.hadoop.record.RecordInput " + 
  280.           Consts.RECORD_INPUT + ", final String " + Consts.TAG + ")n"+
  281.           "throws java.io.IOException {n");
  282.       cb.append("if (null == " + Consts.RTI_FILTER + ") {n");
  283.       cb.append("deserializeWithoutFilter(" + Consts.RECORD_INPUT + ", " + 
  284.           Consts.TAG + ");n");
  285.       cb.append("return;n");
  286.       cb.append("}n");
  287.       cb.append("// if we're here, we need to read based on version infon");
  288.       cb.append(Consts.RECORD_INPUT + ".startRecord(" + Consts.TAG + ");n");
  289.       cb.append("setupRtiFields();n");
  290.       cb.append("for (int " + Consts.RIO_PREFIX + "i=0; " + Consts.RIO_PREFIX + 
  291.           "i<" + Consts.RTI_FILTER + ".getFieldTypeInfos().size(); " + 
  292.           Consts.RIO_PREFIX + "i++) {n");
  293.       int ct = 0;
  294.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  295.         JField<JavaType> jf = i.next();
  296.         String name = jf.getName();
  297.         JavaType type = jf.getType();
  298.         ct++;
  299.         if (1 != ct) {
  300.           cb.append("else ");
  301.         }
  302.         cb.append("if (" + ct + " == " + Consts.RTI_FILTER_FIELDS + "[" +
  303.             Consts.RIO_PREFIX + "i]) {n");
  304.         type.genReadMethod(cb, name, name, false);
  305.         cb.append("}n");
  306.       }
  307.       if (0 != ct) {
  308.         cb.append("else {n");
  309.         cb.append("java.util.ArrayList<"
  310.                 + "org.apache.hadoop.record.meta.FieldTypeInfo> typeInfos = "
  311.                 + "(java.util.ArrayList<"
  312.                 + "org.apache.hadoop.record.meta.FieldTypeInfo>)"
  313.                 + "(" + Consts.RTI_FILTER + ".getFieldTypeInfos());n");
  314.         cb.append("org.apache.hadoop.record.meta.Utils.skip(" + 
  315.             Consts.RECORD_INPUT + ", " + "typeInfos.get(" + Consts.RIO_PREFIX + 
  316.             "i).getFieldID(), typeInfos.get(" + 
  317.             Consts.RIO_PREFIX + "i).getTypeID());n");
  318.         cb.append("}n");
  319.       }
  320.       cb.append("}n");
  321.       cb.append(Consts.RECORD_INPUT + ".endRecord(" + Consts.TAG+");n");
  322.       cb.append("}n");
  323.       // compareTo()
  324.       cb.append("public int compareTo (final Object " + Consts.RIO_PREFIX + 
  325.           "peer_) throws ClassCastException {n");
  326.       cb.append("if (!(" + Consts.RIO_PREFIX + "peer_ instanceof "+name+")) {n");
  327.       cb.append("throw new ClassCastException("Comparing different types of records.");n");
  328.       cb.append("}n");
  329.       cb.append(name+" " + Consts.RIO_PREFIX + "peer = ("+name+") " + 
  330.           Consts.RIO_PREFIX + "peer_;n");
  331.       cb.append("int " + Consts.RIO_PREFIX + "ret = 0;n");
  332.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  333.         JField<JavaType> jf = i.next();
  334.         String name = jf.getName();
  335.         JavaType type = jf.getType();
  336.         type.genCompareTo(cb, name, Consts.RIO_PREFIX + "peer."+name);
  337.         cb.append("if (" + Consts.RIO_PREFIX + "ret != 0) return " + 
  338.             Consts.RIO_PREFIX + "ret;n");
  339.       }
  340.       cb.append("return " + Consts.RIO_PREFIX + "ret;n");
  341.       cb.append("}n");
  342.       
  343.       // equals()
  344.       cb.append("public boolean equals(final Object " + Consts.RIO_PREFIX + 
  345.           "peer_) {n");
  346.       cb.append("if (!(" + Consts.RIO_PREFIX + "peer_ instanceof "+name+")) {n");
  347.       cb.append("return false;n");
  348.       cb.append("}n");
  349.       cb.append("if (" + Consts.RIO_PREFIX + "peer_ == this) {n");
  350.       cb.append("return true;n");
  351.       cb.append("}n");
  352.       cb.append(name+" " + Consts.RIO_PREFIX + "peer = ("+name+") " + 
  353.           Consts.RIO_PREFIX + "peer_;n");
  354.       cb.append("boolean " + Consts.RIO_PREFIX + "ret = false;n");
  355.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  356.         JField<JavaType> jf = i.next();
  357.         String name = jf.getName();
  358.         JavaType type = jf.getType();
  359.         type.genEquals(cb, name, Consts.RIO_PREFIX + "peer."+name);
  360.         cb.append("if (!" + Consts.RIO_PREFIX + "ret) return " + 
  361.             Consts.RIO_PREFIX + "ret;n");
  362.       }
  363.       cb.append("return " + Consts.RIO_PREFIX + "ret;n");
  364.       cb.append("}n");
  365.       // clone()
  366.       cb.append("public Object clone() throws CloneNotSupportedException {n");
  367.       cb.append(name+" " + Consts.RIO_PREFIX + "other = new "+name+"();n");
  368.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  369.         JField<JavaType> jf = i.next();
  370.         String name = jf.getName();
  371.         JavaType type = jf.getType();
  372.         type.genClone(cb, name);
  373.       }
  374.       cb.append("return " + Consts.RIO_PREFIX + "other;n");
  375.       cb.append("}n");
  376.       
  377.       cb.append("public int hashCode() {n");
  378.       cb.append("int " + Consts.RIO_PREFIX + "result = 17;n");
  379.       cb.append("int " + Consts.RIO_PREFIX + "ret;n");
  380.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  381.         JField<JavaType> jf = i.next();
  382.         String name = jf.getName();
  383.         JavaType type = jf.getType();
  384.         type.genHashCode(cb, name);
  385.         cb.append(Consts.RIO_PREFIX + "result = 37*" + Consts.RIO_PREFIX + 
  386.             "result + " + Consts.RIO_PREFIX + "ret;n");
  387.       }
  388.       cb.append("return " + Consts.RIO_PREFIX + "result;n");
  389.       cb.append("}n");
  390.       
  391.       cb.append("public static String signature() {n");
  392.       cb.append("return ""+getSignature()+"";n");
  393.       cb.append("}n");
  394.       
  395.       cb.append("public static class Comparator extends"+
  396.                 " org.apache.hadoop.record.RecordComparator {n");
  397.       cb.append("public Comparator() {n");
  398.       cb.append("super("+name+".class);n");
  399.       cb.append("}n");
  400.       
  401.       cb.append("static public int slurpRaw(byte[] b, int s, int l) {n");
  402.       cb.append("try {n");
  403.       cb.append("int os = s;n");
  404.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  405.         JField<JavaType> jf = i.next();
  406.         String name = jf.getName();
  407.         JavaType type = jf.getType();
  408.         type.genSlurpBytes(cb, "b","s","l");
  409.       }
  410.       cb.append("return (os - s);n");
  411.       cb.append("} catch(java.io.IOException e) {n");
  412.       cb.append("throw new RuntimeException(e);n");
  413.       cb.append("}n");
  414.       cb.append("}n");
  415.       
  416.       cb.append("static public int compareRaw(byte[] b1, int s1, int l1,n");
  417.       cb.append("                             byte[] b2, int s2, int l2) {n");
  418.       cb.append("try {n");
  419.       cb.append("int os1 = s1;n");
  420.       for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
  421.         JField<JavaType> jf = i.next();
  422.         String name = jf.getName();
  423.         JavaType type = jf.getType();
  424.         type.genCompareBytes(cb);
  425.       }
  426.       cb.append("return (os1 - s1);n");
  427.       cb.append("} catch(java.io.IOException e) {n");
  428.       cb.append("throw new RuntimeException(e);n");
  429.       cb.append("}n");
  430.       cb.append("}n");
  431.       cb.append("public int compare(byte[] b1, int s1, int l1,n");
  432.       cb.append("                   byte[] b2, int s2, int l2) {n");
  433.       cb.append("int ret = compareRaw(b1,s1,l1,b2,s2,l2);n");
  434.       cb.append("return (ret == -1)? -1 : ((ret==0)? 1 : 0);");
  435.       cb.append("}n");
  436.       cb.append("}nn");
  437.       cb.append("static {n");
  438.       cb.append("org.apache.hadoop.record.RecordComparator.define("
  439.                 +name+".class, new Comparator());n");
  440.       cb.append("}n");
  441.       cb.append("}n");
  442.       FileWriter jj = new FileWriter(jfile);
  443.       try {
  444.         jj.write(cb.toString());
  445.       } finally {
  446.         jj.close();
  447.       }
  448.     }
  449.   }
  450.   
  451.   class CppRecord extends CppCompType {
  452.     
  453.     private String fullName;
  454.     private String name;
  455.     private String module;
  456.     private ArrayList<JField<CppType>> fields = 
  457.       new ArrayList<JField<CppType>>();
  458.     
  459.     CppRecord(String name, ArrayList<JField<JType>> flist) {
  460.       super(name.replaceAll("\.","::"));
  461.       this.fullName = name.replaceAll("\.", "::");
  462.       int idx = name.lastIndexOf('.');
  463.       this.name = name.substring(idx+1);
  464.       this.module = name.substring(0, idx).replaceAll("\.", "::");
  465.       for (Iterator<JField<JType>> iter = flist.iterator(); iter.hasNext();) {
  466.         JField<JType> f = iter.next();
  467.         fields.add(new JField<CppType>(f.getName(), f.getType().getCppType()));
  468.       }
  469.     }
  470.     
  471.     String getTypeIDObjectString() {
  472.       return "new ::hadoop::StructTypeID(" + 
  473.       fullName + "::getTypeInfo().getFieldTypeInfos())";
  474.     }
  475.     String genDecl(String fname) {
  476.       return "  "+name+" "+fname+";n";
  477.     }
  478.     
  479.     void genSetRTIFilter(CodeBuffer cb) {
  480.       // we set the RTI filter here
  481.       cb.append(fullName + "::setTypeFilter(rti.getNestedStructTypeInfo(""+
  482.           name + ""));n");
  483.     }
  484.     void genSetupRTIFields(CodeBuffer cb) {
  485.       cb.append("void " + fullName + "::setupRtiFields() {n");
  486.       cb.append("if (NULL == p" + Consts.RTI_FILTER + ") return;n");
  487.       cb.append("if (NULL != p" + Consts.RTI_FILTER_FIELDS + ") return;n");
  488.       cb.append("p" + Consts.RTI_FILTER_FIELDS + " = new int[p" + 
  489.           Consts.RTI_FILTER + "->getFieldTypeInfos().size()];n");
  490.       cb.append("for (unsigned int " + Consts.RIO_PREFIX + "i=0; " + 
  491.           Consts.RIO_PREFIX + "i<p" + Consts.RTI_FILTER + 
  492.           "->getFieldTypeInfos().size(); " + Consts.RIO_PREFIX + "i++) {n");
  493.       cb.append("p" + Consts.RTI_FILTER_FIELDS + "[" + Consts.RIO_PREFIX + 
  494.           "i] = 0;n");
  495.       cb.append("}n");
  496.       cb.append("for (unsigned int " + Consts.RIO_PREFIX + "i=0; " + 
  497.           Consts.RIO_PREFIX + "i<p" + Consts.RTI_FILTER + 
  498.           "->getFieldTypeInfos().size(); " + Consts.RIO_PREFIX + "i++) {n");
  499.       cb.append("for (unsigned int " + Consts.RIO_PREFIX + "j=0; " + 
  500.           Consts.RIO_PREFIX + "j<p" + Consts.RTI_VAR + 
  501.           "->getFieldTypeInfos().size(); " + Consts.RIO_PREFIX + "j++) {n");
  502.       cb.append("if (*(p" + Consts.RTI_FILTER + "->getFieldTypeInfos()[" + 
  503.           Consts.RIO_PREFIX + "i]) == *(p" + Consts.RTI_VAR + 
  504.           "->getFieldTypeInfos()[" + Consts.RIO_PREFIX + "j])) {n");
  505.       cb.append("p" + Consts.RTI_FILTER_FIELDS + "[" + Consts.RIO_PREFIX + 
  506.           "i] = " + Consts.RIO_PREFIX + "j+1;n");
  507.       cb.append("break;n");
  508.       cb.append("}n");
  509.       cb.append("}n");
  510.       cb.append("}n");
  511.       cb.append("}n");
  512.     }
  513.     
  514.     void genCode(FileWriter hh, FileWriter cc, ArrayList<String> options)
  515.       throws IOException {
  516.       CodeBuffer hb = new CodeBuffer();
  517.       
  518.       String[] ns = module.split("::");
  519.       for (int i = 0; i < ns.length; i++) {
  520.         hb.append("namespace "+ns[i]+" {n");
  521.       }
  522.       
  523.       hb.append("class "+name+" : public ::hadoop::Record {n");
  524.       hb.append("private:n");
  525.       
  526.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  527.         JField<CppType> jf = i.next();
  528.         String name = jf.getName();
  529.         CppType type = jf.getType();
  530.         type.genDecl(hb, name);
  531.       }
  532.       
  533.       // type info vars
  534.       hb.append("static ::hadoop::RecordTypeInfo* p" + Consts.RTI_VAR + ";n");
  535.       hb.append("static ::hadoop::RecordTypeInfo* p" + Consts.RTI_FILTER + ";n");
  536.       hb.append("static int* p" + Consts.RTI_FILTER_FIELDS + ";n");
  537.       hb.append("static ::hadoop::RecordTypeInfo* setupTypeInfo();n");
  538.       hb.append("static void setupRtiFields();n");
  539.       hb.append("virtual void deserializeWithoutFilter(::hadoop::IArchive& " + 
  540.           Consts.RECORD_INPUT + ", const char* " + Consts.TAG + ");n");
  541.       hb.append("public:n");
  542.       hb.append("static const ::hadoop::RecordTypeInfo& getTypeInfo() " +
  543.           "{return *p" + Consts.RTI_VAR + ";}n");
  544.       hb.append("static void setTypeFilter(const ::hadoop::RecordTypeInfo& rti);n");
  545.       hb.append("static void setTypeFilter(const ::hadoop::RecordTypeInfo* prti);n");
  546.       hb.append("virtual void serialize(::hadoop::OArchive& " + 
  547.           Consts.RECORD_OUTPUT + ", const char* " + Consts.TAG + ") const;n");
  548.       hb.append("virtual void deserialize(::hadoop::IArchive& " + 
  549.           Consts.RECORD_INPUT + ", const char* " + Consts.TAG + ");n");
  550.       hb.append("virtual const ::std::string& type() const;n");
  551.       hb.append("virtual const ::std::string& signature() const;n");
  552.       hb.append("virtual bool operator<(const "+name+"& peer_) const;n");
  553.       hb.append("virtual bool operator==(const "+name+"& peer_) const;n");
  554.       hb.append("virtual ~"+name+"() {};n");
  555.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  556.         JField<CppType> jf = i.next();
  557.         String name = jf.getName();
  558.         CppType type = jf.getType();
  559.         type.genGetSet(hb, name);
  560.       }
  561.       hb.append("}; // end record "+name+"n");
  562.       for (int i=ns.length-1; i>=0; i--) {
  563.         hb.append("} // end namespace "+ns[i]+"n");
  564.       }
  565.       
  566.       hh.write(hb.toString());
  567.       
  568.       CodeBuffer cb = new CodeBuffer();
  569.       // initialize type info vars
  570.       cb.append("::hadoop::RecordTypeInfo* " + fullName + "::p" + 
  571.           Consts.RTI_VAR + " = " + fullName + "::setupTypeInfo();n");
  572.       cb.append("::hadoop::RecordTypeInfo* " + fullName + "::p" + 
  573.           Consts.RTI_FILTER + " = NULL;n");
  574.       cb.append("int* " + fullName + "::p" + 
  575.           Consts.RTI_FILTER_FIELDS + " = NULL;nn");
  576.       // setupTypeInfo()
  577.       cb.append("::hadoop::RecordTypeInfo* "+fullName+"::setupTypeInfo() {n");
  578.       cb.append("::hadoop::RecordTypeInfo* p = new ::hadoop::RecordTypeInfo("" + 
  579.           name + "");n");
  580.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  581.         JField<CppType> jf = i.next();
  582.         String name = jf.getName();
  583.         CppType type = jf.getType();
  584.         type.genStaticTypeInfo(cb, name);
  585.       }
  586.       cb.append("return p;n");
  587.       cb.append("}n");
  588.       // setTypeFilter()
  589.       cb.append("void "+fullName+"::setTypeFilter(const " +
  590.           "::hadoop::RecordTypeInfo& rti) {n");
  591.       cb.append("if (NULL != p" + Consts.RTI_FILTER + ") {n");
  592.       cb.append("delete p" + Consts.RTI_FILTER + ";n");
  593.       cb.append("}n");
  594.       cb.append("p" + Consts.RTI_FILTER + " = new ::hadoop::RecordTypeInfo(rti);n");
  595.       cb.append("if (NULL != p" + Consts.RTI_FILTER_FIELDS + ") {n");
  596.       cb.append("delete p" + Consts.RTI_FILTER_FIELDS + ";n");
  597.       cb.append("}n");
  598.       cb.append("p" + Consts.RTI_FILTER_FIELDS + " = NULL;n");
  599.       // set RTIFilter for nested structs. We may end up with multiple lines that 
  600.       // do the same thing, if the same struct is nested in more than one field, 
  601.       // but that's OK. 
  602.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  603.         JField<CppType> jf = i.next();
  604.         CppType type = jf.getType();
  605.         type.genSetRTIFilter(cb);
  606.       }
  607.       cb.append("}n");
  608.       
  609.       // setTypeFilter()
  610.       cb.append("void "+fullName+"::setTypeFilter(const " +
  611.           "::hadoop::RecordTypeInfo* prti) {n");
  612.       cb.append("if (NULL != prti) {n");
  613.       cb.append("setTypeFilter(*prti);n");
  614.       cb.append("}n");
  615.       cb.append("}n");
  616.       // setupRtiFields()
  617.       genSetupRTIFields(cb);
  618.       // serialize()
  619.       cb.append("void "+fullName+"::serialize(::hadoop::OArchive& " + 
  620.           Consts.RECORD_OUTPUT + ", const char* " + Consts.TAG + ") const {n");
  621.       cb.append(Consts.RECORD_OUTPUT + ".startRecord(*this," + 
  622.           Consts.TAG + ");n");
  623.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  624.         JField<CppType> jf = i.next();
  625.         String name = jf.getName();
  626.         CppType type = jf.getType();
  627.         if (type instanceof JBuffer.CppBuffer) {
  628.           cb.append(Consts.RECORD_OUTPUT + ".serialize("+name+","+name+
  629.               ".length(),""+name+"");n");
  630.         } else {
  631.           cb.append(Consts.RECORD_OUTPUT + ".serialize("+name+",""+
  632.               name+"");n");
  633.         }
  634.       }
  635.       cb.append(Consts.RECORD_OUTPUT + ".endRecord(*this," + Consts.TAG + ");n");
  636.       cb.append("return;n");
  637.       cb.append("}n");
  638.       
  639.       // deserializeWithoutFilter()
  640.       cb.append("void "+fullName+"::deserializeWithoutFilter(::hadoop::IArchive& " +
  641.           Consts.RECORD_INPUT + ", const char* " + Consts.TAG + ") {n");
  642.       cb.append(Consts.RECORD_INPUT + ".startRecord(*this," + 
  643.           Consts.TAG + ");n");
  644.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  645.         JField<CppType> jf = i.next();
  646.         String name = jf.getName();
  647.         CppType type = jf.getType();
  648.         if (type instanceof JBuffer.CppBuffer) {
  649.           cb.append("{nsize_t len=0; " + Consts.RECORD_INPUT + ".deserialize("+
  650.               name+",len,""+name+"");n}n");
  651.         } else {
  652.           cb.append(Consts.RECORD_INPUT + ".deserialize("+name+",""+
  653.               name+"");n");
  654.         }
  655.       }
  656.       cb.append(Consts.RECORD_INPUT + ".endRecord(*this," + Consts.TAG + ");n");
  657.       cb.append("return;n");
  658.       cb.append("}n");
  659.       
  660.       // deserialize()
  661.       cb.append("void "+fullName+"::deserialize(::hadoop::IArchive& " +
  662.           Consts.RECORD_INPUT + ", const char* " + Consts.TAG + ") {n");
  663.       cb.append("if (NULL == p" + Consts.RTI_FILTER + ") {n");
  664.       cb.append("deserializeWithoutFilter(" + Consts.RECORD_INPUT + ", " + 
  665.           Consts.TAG + ");n");
  666.       cb.append("return;n");
  667.       cb.append("}n");
  668.       cb.append("// if we're here, we need to read based on version infon");
  669.       cb.append(Consts.RECORD_INPUT + ".startRecord(*this," + 
  670.           Consts.TAG + ");n");
  671.       cb.append("setupRtiFields();n");
  672.       cb.append("for (unsigned int " + Consts.RIO_PREFIX + "i=0; " + 
  673.           Consts.RIO_PREFIX + "i<p" + Consts.RTI_FILTER + 
  674.           "->getFieldTypeInfos().size(); " + Consts.RIO_PREFIX + "i++) {n");
  675.       int ct = 0;
  676.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  677.         JField<CppType> jf = i.next();
  678.         String name = jf.getName();
  679.         CppType type = jf.getType();
  680.         ct++;
  681.         if (1 != ct) {
  682.           cb.append("else ");
  683.         }
  684.         cb.append("if (" + ct + " == p" + Consts.RTI_FILTER_FIELDS + "[" +
  685.             Consts.RIO_PREFIX + "i]) {n");
  686.         if (type instanceof JBuffer.CppBuffer) {
  687.           cb.append("{nsize_t len=0; " + Consts.RECORD_INPUT + ".deserialize("+
  688.               name+",len,""+name+"");n}n");
  689.         } else {
  690.           cb.append(Consts.RECORD_INPUT + ".deserialize("+name+",""+
  691.               name+"");n");
  692.         }
  693.         cb.append("}n");
  694.       }
  695.       if (0 != ct) {
  696.         cb.append("else {n");
  697.         cb.append("const std::vector< ::hadoop::FieldTypeInfo* >& typeInfos = p" + 
  698.             Consts.RTI_FILTER + "->getFieldTypeInfos();n");
  699.         cb.append("::hadoop::Utils::skip(" + Consts.RECORD_INPUT + 
  700.             ", typeInfos[" + Consts.RIO_PREFIX + "i]->getFieldID()->c_str()" + 
  701.             ", *(typeInfos[" + Consts.RIO_PREFIX + "i]->getTypeID()));n");
  702.         cb.append("}n");
  703.       }
  704.       cb.append("}n");
  705.       cb.append(Consts.RECORD_INPUT + ".endRecord(*this, " + Consts.TAG+");n");
  706.       cb.append("}n");
  707.       // operator <
  708.       cb.append("bool "+fullName+"::operator< (const "+fullName+"& peer_) const {n");
  709.       cb.append("return (1n");
  710.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  711.         JField<CppType> jf = i.next();
  712.         String name = jf.getName();
  713.         cb.append("&& ("+name+" < peer_."+name+")n");
  714.       }
  715.       cb.append(");n");
  716.       cb.append("}n");
  717.       
  718.       cb.append("bool "+fullName+"::operator== (const "+fullName+"& peer_) const {n");
  719.       cb.append("return (1n");
  720.       for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
  721.         JField<CppType> jf = i.next();
  722.         String name = jf.getName();
  723.         cb.append("&& ("+name+" == peer_."+name+")n");
  724.       }
  725.       cb.append(");n");
  726.       cb.append("}n");
  727.       
  728.       cb.append("const ::std::string&"+fullName+"::type() const {n");
  729.       cb.append("static const ::std::string type_(""+name+"");n");
  730.       cb.append("return type_;n");
  731.       cb.append("}n");
  732.       
  733.       cb.append("const ::std::string&"+fullName+"::signature() const {n");
  734.       cb.append("static const ::std::string sig_(""+getSignature()+"");n");
  735.       cb.append("return sig_;n");
  736.       cb.append("}n");
  737.       
  738.       cc.write(cb.toString());
  739.     }
  740.   }
  741.   
  742.   class CRecord extends CCompType {
  743.     
  744.   }
  745.   
  746.   private String signature;
  747.   
  748.   /**
  749.    * Creates a new instance of JRecord
  750.    */
  751.   public JRecord(String name, ArrayList<JField<JType>> flist) {
  752.     setJavaType(new JavaRecord(name, flist));
  753.     setCppType(new CppRecord(name, flist));
  754.     setCType(new CRecord());
  755.     // precompute signature
  756.     int idx = name.lastIndexOf('.');
  757.     String recName = name.substring(idx+1);
  758.     StringBuffer sb = new StringBuffer();
  759.     sb.append("L").append(recName).append("(");
  760.     for (Iterator<JField<JType>> i = flist.iterator(); i.hasNext();) {
  761.       String s = i.next().getType().getSignature();
  762.       sb.append(s);
  763.     }
  764.     sb.append(")");
  765.     signature = sb.toString();
  766.   }
  767.   
  768.   String getSignature() {
  769.     return signature;
  770.   }
  771.   
  772.   void genCppCode(FileWriter hh, FileWriter cc, ArrayList<String> options)
  773.     throws IOException {
  774.     ((CppRecord)getCppType()).genCode(hh, cc, options);
  775.   }
  776.   
  777.   void genJavaCode(String destDir, ArrayList<String> options)
  778.     throws IOException {
  779.     ((JavaRecord)getJavaType()).genCode(destDir, options);
  780.   }
  781. }