java/ant/src/org/apidesign/infra/ant/GrepFilter.java
author Jaroslav Tulach <jtulach@netbeans.org>
Sun, 17 Aug 2008 17:15:52 +0200
changeset 274 e1a7420cea38
parent 268 fb9bf90251e3
child 275 ee4c87a79dba
permissions -rw-r--r--
Generating .url files for each snippet, so the website can link to the hg web
     1 package org.apidesign.infra.ant;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.File;
     5 import java.io.FileReader;
     6 import java.io.IOException;
     7 import java.net.MalformedURLException;
     8 import java.net.URL;
     9 import java.util.HashMap;
    10 import java.util.Map;
    11 import java.util.Stack;
    12 import java.util.regex.Matcher;
    13 import java.util.regex.Pattern;
    14 import org.apache.tools.ant.BuildException;
    15 import org.apache.tools.ant.DirectoryScanner;
    16 import org.apache.tools.ant.Task;
    17 import org.apache.tools.ant.types.FileSet;
    18 import org.apache.tools.ant.types.FilterSet;
    19 
    20 /**
    21  *
    22  * @author Jaroslav Tulach
    23  */
    24 public final class GrepFilter extends Task {
    25     private int len = 80;
    26     private String id;
    27     private FileSet fs;
    28     private Pattern begin = Pattern.compile(".* BEGIN: *(\\p{Graph}+)[-\\> ]*");
    29     private Pattern end = Pattern.compile(".* (END|FINISH): *(\\p{Graph}+)[-\\> ]*");
    30     private boolean openoffice;
    31     private Map<String,String> paths = new HashMap<String, String>();
    32     
    33     
    34     public FileSet createFileSet() {
    35         if (fs != null) {
    36             throw new BuildException();
    37         }
    38         this.fs = new FileSet();
    39         return fs;
    40     }
    41     
    42     public void setId(String id) {
    43         this.id = id;
    44     }
    45     
    46     public void setMaxLineLength(int len) {
    47         this.len = len;
    48     }
    49     
    50     public void setOutputFormat(String f) {
    51         if (f.equals("opendocument")) {
    52             openoffice = true;
    53             return;
    54         }
    55         throw new BuildException("Wrong format: " + f);
    56     }
    57 
    58     final FilterSet createFilterSet() {
    59         if (fs == null) {
    60             throw new BuildException();
    61         }
    62         
    63         FilterSet filter = new FilterSet();
    64 
    65         try {
    66             DirectoryScanner ds = fs.getDirectoryScanner(getProject());
    67             Map<String,CharSequence> texts = new HashMap<String, CharSequence>();
    68             for (String path : ds.getIncludedFiles()) {
    69                 File file = new File(ds.getBasedir(), path);
    70                 BufferedReader r = new BufferedReader(new FileReader(file));
    71                 for (;;) {
    72                     String line = r.readLine();
    73                     if (line == null) {
    74                         break;
    75                     }
    76                     {
    77                         Matcher m = begin.matcher(line);
    78                         if (m.matches()) {
    79                             Item sb = new Item(file);
    80                             CharSequence prev = texts.put(m.group(1), sb);
    81                             if (prev != null) {
    82                                 throw new BuildException("Same pattern is there twice: " + m.group(1) + " in " + file);
    83                             }
    84                             continue;
    85                         }
    86                     }
    87                     {
    88                         Matcher m = end.matcher(line);
    89                         if (m.matches()) {
    90                             CharSequence s = texts.get(m.group(2));
    91                             if (s instanceof Item) {
    92                                 texts.put(m.group(2), ((Item)s).toString(m.group(1).equals("FINISH")));
    93                                 continue;
    94                             }
    95                             
    96                             if (s == null) {
    97                                 throw new BuildException("Closing unknown section: " + m.group(2) + " in " + file);
    98                             }
    99                             throw new BuildException("Closing not opened section: " + m.group(2) + " in " + file);
   100                         }
   101                     }
   102                     
   103                     for (CharSequence charSequence : texts.values()) {
   104                         if (charSequence instanceof Item) {
   105                             Item sb = (Item)charSequence;
   106                             sb.append(line);
   107                         }
   108                     }
   109                 }
   110  
   111                 for (Map.Entry<String, CharSequence> entry : texts.entrySet()) {
   112                     CharSequence v = entry.getValue();
   113                     if (v instanceof Item) {
   114                         throw new BuildException("Not closed section " + entry.getKey() + " in " + file);
   115                     }
   116                     entry.setValue(v.toString());
   117                     paths.put(entry.getKey(), path);
   118                 }
   119             }
   120             
   121             for (Map.Entry<String, CharSequence> entry : texts.entrySet()) {
   122                 String text = entry.getValue().toString();
   123                 String out = linize(text);
   124                 filter.addFilter(entry.getKey(), out); // NOI18N
   125             }
   126         } catch (IOException ex) {
   127             throw new BuildException(ex);
   128         }
   129         if (!filter.hasFilters()) {
   130             throw new BuildException("No filter found!");
   131         }
   132         return filter;
   133     }
   134 
   135     @Override
   136     public void execute() throws BuildException {
   137         if (id == null) {
   138             throw new BuildException();
   139         }
   140         FilterSet filter = createFilterSet();
   141         getProject().addReference(id, filter);
   142     }
   143 
   144     final URL getPath(URL root, String key) throws MalformedURLException {
   145         return new URL(root, paths.get(key));
   146     }
   147     
   148     private String linize(String input) {
   149         if (!openoffice) {
   150             return input;
   151         }
   152         
   153         StringBuilder copy = new StringBuilder();
   154         for (String l : input.split("\n")) {
   155             int spaces = 0;
   156             while (spaces < l.length() && l.charAt(spaces) == ' ') {
   157                 spaces++;
   158             }
   159             copy.append("<text:p text:style-name='Code'><text:s text:c='" + spaces + "'/>" + l.substring(spaces) + "</text:p>\n");
   160         }
   161         
   162         return copy.toString();
   163     }
   164     
   165     static final int countChar(CharSequence seq, char ch) {
   166         int cnt = 0;
   167         for (int i = 0; i < seq.length(); i++) {
   168             if (ch == seq.charAt(i)) {
   169                 cnt++;
   170             }
   171         }
   172         return cnt;
   173     }
   174 
   175     private final class Item implements CharSequence {
   176         private StringBuilder sb = new StringBuilder();
   177         private int spaces = Integer.MAX_VALUE;
   178         private Stack<Integer> remove = new Stack<Integer>();
   179         private final File file;
   180 
   181         public Item(File file) {
   182             this.file = file;
   183         }
   184 
   185         public int length() {
   186             return sb.length();
   187         }
   188 
   189         public char charAt(int index) {
   190             return sb.charAt(index);
   191         }
   192 
   193         public CharSequence subSequence(int start, int end) {
   194             return sb.subSequence(start, end);
   195         }
   196 
   197         private void append(String line) {
   198             for (int sp = 0; sp < line.length(); sp++) {
   199                 if (line.charAt(sp) != ' ') {
   200                     if (sp < spaces) {
   201                         spaces = sp;
   202                         break;
   203                     }
   204                 }
   205             }
   206             remove.push(sb.length());
   207             sb.append(line);
   208             sb.append('\n');
   209         }
   210 
   211         @Override
   212         public String toString() {
   213             return toString(false);
   214         }
   215         public String toString(boolean finish) {
   216             if (remove != null) {
   217                 while (!remove.isEmpty()) {
   218                    Integer pos = remove.pop();
   219                    for (int i = 0; i < spaces; i++) {
   220                        if (sb.charAt(pos) == '\n') {
   221                            break;
   222                        }
   223                        sb.deleteCharAt(pos);
   224                    }
   225                 }
   226                 remove = null;
   227                 
   228                 int line = 0;
   229                 for (int i = 0; i < sb.length(); i++) {
   230                     if (sb.charAt(i) == '\n') {
   231                         line = 0;
   232                         continue;
   233                     }
   234                     if (++line > len) {
   235                         throw new BuildException("Line is too long in: " + file + "\n" + sb);
   236                     }
   237                 }
   238                 
   239                 int open = countChar(sb, '{');
   240                 int end = countChar(sb, '}');
   241                 if (finish) {
   242                     for (int i = 0; i < open - end; i++) {
   243                         sb.append("}\n");
   244                     }
   245                 }
   246                 
   247                 if (countChar(sb, '{') != countChar(sb, '}')) {
   248                     throw new BuildException("not paired amount of braces in " + file + "\n" + sb);
   249                 }
   250                 
   251             }
   252             return sb.toString();
   253         }
   254     } // end of Item
   255 }