daily pastebin goal
69%
SHARE
TWEET

Templatron

a guest Mar 31st, 2015 219 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import java.io.File;
  2. import java.io.FileReader;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.io.Writer;
  6. import java.net.URL;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. import java.util.Map;
  10.  
  11. /**
  12.  * 'Templatron' template library. Quick Example Usage:
  13. <pre>Template template = Templatron.newTemplate("Hello, %{name=NULL}! How are you? I am %{feel}.");
  14.  
  15. HashMap<String, String> valueMap = new HashMap<>();
  16. valueMap.put("name", "Coder");
  17. valueMap.put("feel", "fine");
  18.  
  19. Templatron.render(template, valueMap, new PrintWriter(System.out));
  20.  * </pre>
  21.  * FOR THE SAKE OF SANITY: Do NOT use this library in production! This code was written to just work, without giving a f**k about anything.
  22.  **/
  23. public class Templatron {
  24.         /**
  25.          * Creates a new template from a string.
  26.          * @param source The string to parse.
  27.          * @return A new template, generated from the given string.
  28.          **/
  29.         public static final Template newTemplate(String source) {
  30.                 if(source == null)
  31.                         throw new NullPointerException("'source' cannot be null!");
  32.                
  33.                 Template template = new Template();
  34.                 template.load(source);
  35.                 return template;
  36.         }
  37.        
  38.         /**
  39.          * Creates a new template from a string.
  40.          * @param file The file to parse.
  41.          * @return A new template, generated from the given string.
  42.          * @throws IOException If the file could not be opened/read.
  43.          **/
  44.         public static final Template newTemplate(File file) throws IOException {
  45.                 if(file == null)
  46.                         throw new NullPointerException("'file' cannot be null!");
  47.                
  48.                 StringBuilder bd = new StringBuilder();
  49.                 FileReader read = new FileReader(file);
  50.                 {
  51.                         int i = 0;
  52.                         while((i = read.read()) != -1)
  53.                                 bd.append((char)i);
  54.                 }
  55.                 read.close();
  56.                
  57.                 Template template = new Template();
  58.                 template.load(bd.toString());
  59.                 return template;
  60.         }
  61.        
  62.         /**
  63.          * Creates a new template from a string.
  64.          * @param url The url to parse.
  65.          * @return A new template, generated from the given string.
  66.          * @throws IOException If the url could not be opened/read.
  67.          **/
  68.         public static final Template newTemplate(URL url) throws IOException {
  69.                 if(url == null)
  70.                         throw new NullPointerException("'url' cannot be null!");
  71.                
  72.                 StringBuilder bd = new StringBuilder();
  73.                 InputStreamReader read = new InputStreamReader(url.openStream());
  74.                 {
  75.                         int i = 0;
  76.                         while((i = read.read()) != -1)
  77.                                 bd.append((char)i);
  78.                 }
  79.                 read.close();
  80.                
  81.                 Template template = new Template();
  82.                 template.load(bd.toString());
  83.                 return template;
  84.         }
  85.        
  86.         /**
  87.          * Instances of this class parse and store a template.
  88.          **/
  89.         public static class Template {
  90.                 List<Piece> pieces;
  91.                
  92.                 protected Template() {
  93.                         pieces = new ArrayList<>();
  94.                 }
  95.                
  96.                 @Override
  97.                 public String toString() {
  98.                         return "Template:{pieces.size="+pieces.size()+"}";
  99.                 }
  100.                
  101.                 /**
  102.                  * This is were the magic happens!
  103.                  * @param source The string to parse.
  104.                  **/
  105.                 public void load(String source) {
  106.                         StringBuilder buffer = new StringBuilder(source.length());
  107.                        
  108.                         for(int CHARINDEX = 0; CHARINDEX < source.length(); CHARINDEX++) {
  109.                                 char CHAR = source.charAt(CHARINDEX);
  110.                                
  111.                                 // IF %{ ... }
  112.                                 if(CHAR == '%' && peek(source, CHARINDEX+1, ' ') == '{') {
  113.                                         int start = CHARINDEX+2;
  114.                                         int end = findNext(source, CHARINDEX+1, '}');
  115.                                        
  116.                                         if(end == -1) {
  117.                                                 buffer.append(CHAR);
  118.                                                 continue;
  119.                                         }
  120.                                        
  121.                                         {
  122.                                                 // Flush buffer!
  123.                                                 String str = buffer.toString();
  124.                                                 buffer.setLength(0);
  125.                                                 TextPiece tp = new TextPiece();
  126.                                                 tp.data = str;
  127.                                                 pieces.add(tp);
  128.                                         }
  129.                                        
  130.                                         // Cut it out.
  131.                                         String link = source.substring(start, end);
  132.                                        
  133.                                         // Do your thing!
  134.                                         LinkPiece tp = new LinkPiece();
  135.                                         pieces.add(tp);
  136.                                        
  137.                                         // Has 'default' value embedded?
  138.                                         if(link.indexOf('=') != -1) {
  139.                                                 // Yes, so extract it!
  140.                                                 int i = link.indexOf('=');
  141.                                                 String k = link.substring(0, i);
  142.                                                 String d = link.substring(i+1);
  143.                                                 tp.data = k;
  144.                                                 tp.defaultdata = d;
  145.                                         } else {
  146.                                                 // No, just use all text as value link.
  147.                                                 tp.data = link;
  148.                                                 tp.defaultdata = "%{"+tp.data+"=null}";
  149.                                         }
  150.                                        
  151.                                         // skip forward
  152.                                         CHARINDEX = end;
  153.                                 } else {
  154.                                         // Just text!
  155.                                         buffer.append(CHAR);
  156.                                 }
  157.                         }
  158.                        
  159.                         // If there is something left in the buffer, finish it.
  160.                         if(buffer.length() > 0) {
  161.                                 String str = buffer.toString();
  162.                                 TextPiece tp = new TextPiece();
  163.                                 tp.data = str;
  164.                                 pieces.add(tp);
  165.                         }
  166.                 }
  167.                
  168.                 // Finds the next index of 'searched', then returns it. -1 if it cant be found.
  169.                 private final int findNext(String string, int start, char searched) {
  170.                         for(int i = start; i <= string.length(); i++) {
  171.                                 if(string.charAt(i) == searched)
  172.                                         return i;
  173.                         }
  174.                         return -1;
  175.                 }
  176.                
  177.                 // Safely peeking around in a string without getting IndexOutOfBoundsException's.
  178.                 private final char peek(String string, int index, char def) {
  179.                         if(index < 0)
  180.                                 return def;
  181.                         if(index >= string.length())
  182.                                 return def;
  183.                         return string.charAt(index);
  184.                 }
  185.         }
  186.        
  187.         /** A piece of the template. **/
  188.         public static abstract class Piece {
  189.                 // empty class
  190.         }
  191.        
  192.         /** A piece representing simple text. **/
  193.         public static class TextPiece extends Piece {
  194.                 String data;
  195.                
  196.                 @Override
  197.                 public String toString() {
  198.                         return "TextPiece:\""+data+"\"";
  199.                 }
  200.         }
  201.        
  202.         /** A piece that will be replaced by some value when the template is rendered. **/
  203.         public static class LinkPiece extends Piece {
  204.                 String data;
  205.                 String defaultdata;
  206.                
  207.                 @Override
  208.                 public String toString() {
  209.                         return "LinkPiece:\""+data+"\"|\""+defaultdata+"\"";
  210.                 }
  211.         }
  212.        
  213.         /**
  214.          * "renders" a template using the given data-map.
  215.          * @param template The template to render.
  216.          * @param data The data to insert into the template.
  217.          * @param writer The writer to output the template to.
  218.          * @throws IOException If something goes wrong.
  219.          **/
  220.         public static final void render(Template template, Map<String, String> data, Writer writer) throws IOException {
  221.                 // Go trough all pieces...
  222.                 for(Piece piece : template.pieces) {
  223.                         // If it is a text-piece...
  224.                         if(piece instanceof TextPiece) {
  225.                                 // Write it out!
  226.                                 writer.append(((TextPiece) piece).data);
  227.                         }
  228.                        
  229.                         // If it is a link-piece...
  230.                         if(piece instanceof LinkPiece) {
  231.                                 // Get the name of the 'link'...
  232.                                 String link = ((LinkPiece) piece).data;
  233.                                
  234.                                 // Get the value from the data-map...
  235.                                 String replace = data.get(link);
  236.                                
  237.                                 // Is the value NULL?
  238.                                 if(replace == null) {
  239.                                         // Yes, write the default value stored inside the LinkPiece.
  240.                                         writer.append(((LinkPiece) piece).defaultdata);
  241.                                 } else {
  242.                                         // No, write the actual data!
  243.                                         writer.append(replace);
  244.                                 }
  245.                         }
  246.                 }
  247.                
  248.                 // Flush! Note that we do NOT close the writer,
  249.                 // as one may want to append multiple templates.
  250.                 writer.flush();
  251.         }
  252.        
  253. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top