This project has retired. For details please refer to its Attic page.
GeneratePrimitiveClasses xref
View Javadoc

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.giraph.generate;
19  
20  import java.io.File;
21  import java.io.FileNotFoundException;
22  import java.io.FileOutputStream;
23  import java.io.IOException;
24  import java.io.OutputStreamWriter;
25  import java.io.Writer;
26  import java.util.EnumSet;
27  import java.util.HashMap;
28  import java.util.Map;
29  
30  import freemarker.core.ParseException;
31  import freemarker.template.Configuration;
32  import freemarker.template.MalformedTemplateNameException;
33  import freemarker.template.Template;
34  import freemarker.template.TemplateException;
35  import freemarker.template.TemplateExceptionHandler;
36  import freemarker.template.TemplateNotFoundException;
37  
38  /**
39   * <p>Code generation utility that generates set of classes from a template files.
40   * Templates are found in giraph-core/template/ folder.
41   * If you want to add new generation, look at the main function, and add a call
42   * to appropriate generate* function.</p>
43   *
44   * <p>Templates are using freemarker template format, which given
45   * template file and map of String-&gt;Object replacements generates
46   * new file.</p>
47   * Main rules:
48   * <ul>
49   * <li><code>${something}</code> gets replaced with value of <code>map.get("something")</code></li>
50   * <li><code>${obj.method}</code> gets replaced with value of <code>map.get("obj").getMethod()</code></li>
51   * </ul>
52   * More description about template format can be found at:
53   * <a href="http://freemarker.org/docs/dgui_quickstart_template.html">tutorial</a>
54   */
55  public class GeneratePrimitiveClasses {
56    public static enum PrimitiveType {
57      BOOLEAN("Boolean"),
58      BYTE("Byte"),
59      SHORT("Short"),
60      INT("Int"),
61      LONG("Long"),
62      FLOAT("Float"),
63      DOUBLE("Double");
64  
65      private final String name;
66      private final String nameLower;
67      private final String boxed;
68      private final boolean numeric;
69      private final boolean id;
70      private final boolean floating;
71      private final boolean hasWritable;
72  
73      private PrimitiveType(String name) {
74        this.name = name;
75        this.nameLower = name.toLowerCase();
76        this.boxed = "Int".equals(name) ? "Integer" : name;
77        this.numeric = !"Boolean".equals(name);
78        this.id = "Int".equals(name) || "Long".equals(name);
79        this.floating = "Float".equals(name) || "Double".equals(name);
80        // For some reason there is no ShortWritable in current Hadoop version
81        this.hasWritable = !"Short".equals(name);
82      }
83  
84      public String getName() {
85        return name;
86      }
87  
88      public String getCamel() {
89        return name;
90      }
91  
92      public String getLower() {
93        return nameLower;
94      }
95  
96      public String getBoxed() {
97        return boxed;
98      }
99  
100     public boolean isNumeric() {
101       return numeric;
102     }
103 
104     public boolean isId() {
105       return id;
106     }
107 
108     public boolean isFloating() {
109       return floating;
110     }
111 
112     public boolean hasWritable() {
113       return hasWritable;
114     }
115   }
116 
117   public static void main(String[] args) throws Exception {
118     /* Create and adjust the configuration singleton */
119     Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
120     cfg.setDirectoryForTemplateLoading(new File("templates"));
121     cfg.setDefaultEncoding("UTF-8");
122     cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
123 
124     String[] primitiveFunctions = {
125       "%sConsumer", "%sPredicate", "Obj2%sFunction", "%s2ObjFunction", "%s2%sFunction"
126     };
127 
128     for (String function: primitiveFunctions) {
129       generateForAll(
130           cfg,
131           EnumSet.allOf(PrimitiveType.class),
132           function.replaceAll("\\%s", "Type") + ".java",
133           "src/main/java/org/apache/giraph/function/primitive/" + function + ".java");
134     }
135 
136 
137     generateForAll(
138         cfg,
139         EnumSet.allOf(PrimitiveType.class),
140         "TypeComparatorFunction.java",
141         "../giraph-block-app-8/src/main/java/org/apache/giraph/function/primitive/comparators/%sComparatorFunction.java");
142 
143     EnumSet<PrimitiveType> writableSet = EnumSet.noneOf(PrimitiveType.class);
144     EnumSet<PrimitiveType> ids = EnumSet.noneOf(PrimitiveType.class);
145     EnumSet<PrimitiveType> numerics = EnumSet.noneOf(PrimitiveType.class);
146     for (PrimitiveType type : EnumSet.allOf(PrimitiveType.class)) {
147       if (type.hasWritable()) {
148         writableSet.add(type);
149         if (type.isId()) {
150           ids.add(type);
151         }
152         if (type.isNumeric()) {
153           numerics.add(type);
154         }
155       }
156     }
157 
158     generateForAll(
159         cfg,
160         writableSet,
161         "TypeTypeOps.java",
162         "src/main/java/org/apache/giraph/types/ops/%sTypeOps.java");
163 
164     generateForAll(
165         cfg,
166         writableSet,
167         "WTypeCollection.java",
168         "src/main/java/org/apache/giraph/types/ops/collections/W%sCollection.java");
169 
170     generateForAll(
171         cfg,
172         writableSet,
173         "WTypeArrayList.java",
174         "src/main/java/org/apache/giraph/types/ops/collections/array/W%sArrayList.java");
175 
176     generateForAll(
177         cfg,
178         writableSet,
179         writableSet,
180         "TypeTypeConsumer.java",
181         "src/main/java/org/apache/giraph/function/primitive/pairs/%s%sConsumer.java");
182 
183     generateForAll(
184         cfg,
185         writableSet,
186         writableSet,
187         "TypeTypePredicate.java",
188         "src/main/java/org/apache/giraph/function/primitive/pairs/%s%sPredicate.java");
189 
190     generateForAll(
191         cfg,
192         ids,
193         numerics,
194         "Type2TypeMapEntryIterable.java",
195         "src/main/java/org/apache/giraph/types/heaps/%s2%sMapEntryIterable.java");
196 
197     generateForAll(
198         cfg,
199         ids,
200         numerics,
201         "FixedCapacityType2TypeMinHeap.java",
202         "src/main/java/org/apache/giraph/types/heaps/FixedCapacity%s%sMinHeap.java");
203 
204     generateForAll(
205         cfg,
206         ids,
207         numerics,
208         "TestFixedCapacityType2TypeMinHeap.java",
209         "src/test/java/org/apache/giraph/types/heaps/TestFixedCapacity%s%sMinHeap.java");
210 
211     System.out.println("Successfully generated classes");
212   }
213 
214   /**
215    * Generate a set of files from a template, one for each type in the passed set,
216    * where added entry for "type" to that object is added, on top of default entries.
217    */
218   private static void generateForAll(Configuration cfg, EnumSet<PrimitiveType> types,
219       String template, String outputPattern) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, FileNotFoundException, IOException, TemplateException {
220     for (PrimitiveType type : types) {
221       Map<String, Object> props = defaultMap();
222       props.put("type", type);
223       generateAndWrite(cfg, props,
224           template,
225           outputPattern.replaceAll("\\%s", type.getCamel()));
226     }
227   }
228 
229   /**
230    * Generate a set of files from a template, one for each combination of
231    * types in the passed sets, where added entry for "type1" and "type2" to
232    * that object is added, on top of default entries.
233    */
234   private static void generateForAll(Configuration cfg,
235       EnumSet<PrimitiveType> types1, EnumSet<PrimitiveType> types2,
236       String template, String outputPattern) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, FileNotFoundException, IOException, TemplateException {
237     for (PrimitiveType type1 : types1) {
238       for (PrimitiveType type2 : types2) {
239         Map<String, Object> props = defaultMap();
240         props.put("type1", type1);
241         props.put("type2", type2);
242         generateAndWrite(cfg, props,
243             template,
244             String.format(outputPattern, type1.getCamel(), type2.getCamel()));
245       }
246     }
247   }
248 
249   /** Generate a single file from a template, replacing mappings from given properties */
250   private static void generateAndWrite(Configuration cfg, Map<String, Object> props,
251       String template, String outputFile)
252           throws TemplateNotFoundException, MalformedTemplateNameException, ParseException,
253           IOException, FileNotFoundException, TemplateException {
254     Template temp = cfg.getTemplate(template);
255     Writer out = new OutputStreamWriter(new FileOutputStream(outputFile));
256     temp.process(props, out);
257     out.close();
258   }
259 
260   public static Map<String, Object> defaultMap() {
261     Map<String, Object> props = new HashMap<>();
262     props.put("generated_message", GENERATED_MESSAGE);
263     return props;
264   }
265 
266   private static final String GENERATED_MESSAGE =
267       "// AUTO-GENERATED class via class:\n// " + GeneratePrimitiveClasses.class.getName();
268 }