Coverage Report - org.galagosearch.tupleflow.typebuilder.TemplateTypeBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
TemplateTypeBuilder
0%
0/57
0%
0/20
0
TemplateTypeBuilder$Field
0%
0/11
N/A
0
TemplateTypeBuilder$OrderSpec
0%
0/53
0%
0/36
0
TemplateTypeBuilder$OrderSpec$FieldPair
0%
0/5
N/A
0
TemplateTypeBuilder$OrderedField
0%
0/10
0%
0/4
0
 
 1  
 // BSD License (http://www.galagosearch.org/license)
 2  
 package org.galagosearch.tupleflow.typebuilder;
 3  
 
 4  
 import java.util.ArrayList;
 5  
 import java.util.Collections;
 6  
 import java.util.HashMap;
 7  
 import java.util.HashSet;
 8  
 import org.antlr.stringtemplate.CommonGroupLoader;
 9  
 import org.antlr.stringtemplate.StringTemplate;
 10  
 import org.antlr.stringtemplate.StringTemplateGroup;
 11  
 import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
 12  
 import org.galagosearch.tupleflow.typebuilder.FieldSpecification.DataType;
 13  
 
 14  
 /**
 15  
  *
 16  
  * @author trevor
 17  
  */
 18  
 public class TemplateTypeBuilder {
 19  
     StringTemplateGroup template;
 20  
     String typeName;
 21  
     String typePackage;
 22  
     ArrayList<Field> typeFields;
 23  
     ArrayList<OrderSpec> typeOrders;
 24  
 
 25  
     /**
 26  
      * For an array master, returns
 27  
      * an array containing the last master.length-index elements.
 28  
      */
 29  
     public static String[] subarray(String[] master, int index) {
 30  0
         if (master.length <= index) {
 31  0
             return new String[0];
 32  
         } else {
 33  0
             String[] sub = new String[master.length - index];
 34  0
             System.arraycopy(master, index, sub, 0, sub.length);
 35  0
             return sub;
 36  
         }
 37  
     }
 38  
 
 39  
     /**
 40  
      * Returns a string containing all the elements of args, space delimited.
 41  
      */
 42  
     public static String join(String[] args, String delimiter) {
 43  0
         String output = "";
 44  0
         StringBuilder builder = new StringBuilder();
 45  
 
 46  0
         for (String arg : args) {
 47  0
             if (builder.length() > 0) {
 48  0
                 builder.append(delimiter);
 49  
             }
 50  0
             builder.append(arg);
 51  
         }
 52  
 
 53  0
         return builder.toString();
 54  
     }
 55  
 
 56  
     public static String join(String[] args) {
 57  0
         return join(args, " ");
 58  
     }
 59  
 
 60  
     public static String caps(String input) {
 61  0
         if (input.length() == 0) {
 62  0
             return input;
 63  
         }
 64  0
         char first = Character.toUpperCase(input.charAt(0));
 65  0
         return "" + first + input.substring(1);
 66  
     }
 67  
 
 68  
     public static String plural(String input) {
 69  0
         return input + "s";
 70  
     }
 71  
 
 72  
     public static class Field {
 73  0
         public Field(DataType type, String name) {
 74  0
             this.dataType = type;
 75  0
             this.type = type.getType();
 76  0
             this.name = name;
 77  0
             this.capsName = caps(name);
 78  0
             this.pluralName = plural(name);
 79  
             
 80  0
             this.inputType = caps(type.getInternalType());
 81  0
             this.baseType = type.getBaseType();
 82  0
             this.classTypeName = type.getClassName();
 83  0
             this.isArray = dataType.isArray();
 84  0
         }
 85  
         public DataType dataType;
 86  
         public String type;
 87  
         public String name;
 88  
         public String baseType;
 89  
         public boolean isInteger;
 90  
         public boolean isString;
 91  
         public boolean isArray;
 92  
         public String classTypeName;
 93  
         public String capsName;
 94  
         public String inputType;
 95  
         public String pluralName;
 96  
     }
 97  
 
 98  
     public static class OrderedField extends Field {
 99  
         public OrderedField(Field field, boolean ascending, boolean delta, boolean runLengthEncoded) {
 100  0
             this(field.dataType, field.name, ascending, delta, runLengthEncoded);
 101  0
         }
 102  
 
 103  
         public OrderedField(DataType type, String name, boolean ascending, boolean delta, boolean runLengthEncoded) {
 104  0
             super(type, name);
 105  0
             this.ascending = ascending;
 106  0
             this.direction = ascending ? "+" : "-";
 107  0
             this.directionName = ascending ? "Ascending" : "Descending";
 108  0
             this.runLengthEncoded = runLengthEncoded;
 109  0
             this.delta = delta;
 110  0
         }
 111  
         public boolean ascending;
 112  
         public String direction;
 113  
         public String directionName;
 114  
         public boolean delta;
 115  
         public boolean runLengthEncoded;
 116  0
         public ArrayList<OrderedField> remaining = new ArrayList();
 117  
     }
 118  
 
 119  
     public static class OrderSpec {
 120  0
         public OrderSpec(OrderSpecification spec, ArrayList<Field> allFields) {
 121  0
             this.allFields = allFields;
 122  
 
 123  0
             HashMap<String, Field> fieldMap = new HashMap();
 124  0
             HashSet<String> orderedNames = new HashSet();
 125  
 
 126  0
             for (Field f : allFields) {
 127  0
                 fieldMap.put(f.name, f);
 128  
             }
 129  
 
 130  0
             ArrayList<OrderedFieldSpecification> inputFields = spec.getOrderedFields();
 131  
             
 132  0
             for (int i = 0; i < inputFields.size(); i++) {
 133  0
                 Field field = fieldMap.get(inputFields.get(i).getName());
 134  0
                 boolean isLastField = ((inputFields.size() - i) == 1);
 135  
                 // BUGBUG: this is where delta encoding should go
 136  0
                 boolean useDelta = false; //isLastField && (field.isInteger || field.isString); 
 137  0
                 boolean useRLE = !useDelta;
 138  0
                 boolean isAscending = (inputFields.get(i).getDirection() == Direction.ASCENDING);
 139  0
                 String fieldName = inputFields.get(i).getName();
 140  
 
 141  0
                 if (fieldMap.get(fieldName) == null) {
 142  0
                     throw new RuntimeException("'" + fieldName + "' is specified in an order statement, " +
 143  
                                                "but it isn't a type field name.");
 144  
                 }
 145  
                 
 146  0
                 OrderedField ordered = new OrderedField(fieldMap.get(fieldName),
 147  
                                                         isAscending, useDelta, useRLE);
 148  0
                 orderedFields.add(ordered);
 149  0
                 orderedNames.add(fieldName);
 150  
             }
 151  
 
 152  0
             for (int i = 0; i < inputFields.size(); i++) {
 153  0
                 orderedFields.get(i).remaining.addAll(
 154  
                         orderedFields.subList(i + 1, orderedFields.size()));
 155  
             }
 156  
 
 157  0
             backwardOrderedFields.addAll(orderedFields);
 158  0
             Collections.reverse(backwardOrderedFields);
 159  
 
 160  0
             for (int i = 0; i < orderedFields.size(); i++) {
 161  0
                 if (orderedFields.get(i).runLengthEncoded) {
 162  0
                     rleFields.add(orderedFields.get(i));
 163  
                 }
 164  0
                 if (orderedFields.get(i).delta) {
 165  0
                     deltaFields.add(orderedFields.get(i));
 166  
                 }
 167  
             }
 168  
 
 169  0
             for (int i = 0; i < orderedFields.size(); i++) {
 170  0
                 OrderedField current = orderedFields.get(i);
 171  0
                 OrderedField next = ((i + 1) < orderedFields.size()) ? orderedFields.get(i + 1) : null;
 172  0
                 OrderedField previous = (i != 0) ? orderedFields.get(i - 1) : null;
 173  
 
 174  0
                 fieldPairs.add(new FieldPair(current, next, previous));
 175  
             }
 176  
 
 177  0
             for (int i = 0; i < allFields.size(); i++) {
 178  0
                 if (orderedNames.contains(allFields.get(i).name)) {
 179  0
                     continue;
 180  
                 }
 181  0
                 unorderedFields.add(allFields.get(i));
 182  
             }
 183  0
         }
 184  
 
 185  
         public String getClassName() {
 186  0
             StringBuilder builder = new StringBuilder();
 187  
 
 188  0
             if (orderedFields.size() > 0) {
 189  0
                 for (OrderedField orderedField : orderedFields) {
 190  0
                     if (!orderedField.ascending) {
 191  0
                         builder.append("Desc");
 192  
                     }
 193  0
                     builder.append(caps(orderedField.name));
 194  
                 }
 195  
 
 196  0
                 builder.append("Order");
 197  
             } else {
 198  0
                 builder.append("Unordered");
 199  
             }
 200  
 
 201  0
             return builder.toString();
 202  
         }
 203  
 
 204  
         public static class FieldPair {
 205  0
             public FieldPair(OrderedField c, OrderedField n, OrderedField p) {
 206  0
                 current = c;
 207  0
                 next = n;
 208  0
                 previous = p;
 209  0
             }
 210  
             public OrderedField current;
 211  
             public OrderedField next;
 212  
             public OrderedField previous;
 213  
         }
 214  0
         public ArrayList<OrderedField> orderedFields = new ArrayList();
 215  0
         public ArrayList<OrderedField> backwardOrderedFields = new ArrayList();
 216  0
         public ArrayList<FieldPair> fieldPairs = new ArrayList();
 217  0
         public ArrayList<OrderedField> rleFields = new ArrayList();
 218  0
         public ArrayList<Field> unorderedFields = new ArrayList();
 219  0
         public ArrayList<OrderedField> deltaFields = new ArrayList();
 220  
         public ArrayList<Field> allFields;
 221  
     }
 222  
 
 223  
     /**
 224  
      * Returns the text of a Type<T> object for the T class.
 225  
      */
 226  
     @Override
 227  
     public String toString() {
 228  0
         StringTemplate t = template.getInstanceOf("type");
 229  0
         HashMap<String, Object> map = new HashMap<String, Object>();
 230  0
         map.put("typeName", this.typeName);
 231  0
         map.put("package", this.typePackage);
 232  0
         map.put("orders", this.typeOrders);
 233  0
         map.put("fields", this.typeFields);
 234  
 
 235  0
         boolean containsArray = false;
 236  0
         for (Field f : typeFields) {
 237  0
             containsArray = containsArray || f.isArray;
 238  
         }
 239  0
         map.put("containsArray", containsArray);
 240  0
         t.setAttributes(map);
 241  0
         return t.toString();
 242  
     }
 243  
 
 244  0
     public TemplateTypeBuilder(TypeSpecification spec) {
 245  0
         CommonGroupLoader loader = new CommonGroupLoader("org/galagosearch/tupleflow/templates", null);
 246  0
         StringTemplateGroup.registerGroupLoader(loader);
 247  0
         StringTemplateGroup.registerDefaultLexer(AngleBracketTemplateLexer.class);
 248  0
         this.template = StringTemplateGroup.loadGroup("GalagoType");
 249  
 
 250  0
         this.typeName = spec.getTypeName();
 251  0
         this.typePackage = spec.getPackageName();
 252  0
         this.typeFields = new ArrayList<Field>();
 253  0
         this.typeOrders = new ArrayList<OrderSpec>();
 254  
 
 255  0
         for (FieldSpecification fieldSpec : spec.getFields()) {
 256  0
             Field field = new Field(fieldSpec.getType(), fieldSpec.getName());
 257  0
             typeFields.add(field);
 258  0
         }
 259  
 
 260  0
         for (OrderSpecification orderSpec : spec.getOrders()) {
 261  0
             OrderSpec order = new OrderSpec(orderSpec, typeFields);
 262  0
             typeOrders.add(order);
 263  0
         }
 264  0
     }
 265  
     
 266  
     public static void main(String[] args) throws java.lang.Exception {
 267  0
         for (String fileName : args) {
 268  0
             TypeSpecification spec = ParserDriver.getTypeSpecification(fileName);
 269  0
             TemplateTypeBuilder builder = new TemplateTypeBuilder(spec);
 270  
             
 271  0
             java.io.FileWriter writer = new java.io.FileWriter(spec.getTypeName() + ".java");
 272  0
             String comment = "// This file was automatically generated with the command: \n" +
 273  
                          "//     java org.galagosearch.tupleflow.typebuilder.TemplateTypeBuilder ...\n";
 274  
 
 275  0
             writer.write(comment);
 276  0
             writer.write(builder.toString());
 277  0
             writer.close();
 278  
         }
 279  0
     }
 280  
 }