java/ant/src/org/apidesign/infra/ant/GrepFilter.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 03 Apr 2020 16:32:36 +0200
changeset 416 9ed8788a1a4e
parent 274 e1a7420cea38
permissions -rw-r--r--
Using HTTPS to download the libraries
     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                     if (!paths.containsKey(entry.getKey())) {
   118                         paths.put(entry.getKey(), path);
   119                     }
   120                 }
   121             }
   122             
   123             for (Map.Entry<String, CharSequence> entry : texts.entrySet()) {
   124                 String text = entry.getValue().toString();
   125                 String out = linize(text);
   126                 filter.addFilter(entry.getKey(), out); // NOI18N
   127             }
   128         } catch (IOException ex) {
   129             throw new BuildException(ex);
   130         }
   131         if (!filter.hasFilters()) {
   132             throw new BuildException("No filter found!");
   133         }
   134         return filter;
   135     }
   136 
   137     @Override
   138     public void execute() throws BuildException {
   139         if (id == null) {
   140             throw new BuildException();
   141         }
   142         FilterSet filter = createFilterSet();
   143         getProject().addReference(id, filter);
   144     }
   145 
   146     final URL getPath(URL root, String key) throws MalformedURLException {
   147         return new URL(root, paths.get(key));
   148     }
   149     
   150     private String linize(String input) {
   151         if (!openoffice) {
   152             return input;
   153         }
   154         
   155         StringBuilder copy = new StringBuilder();
   156         for (String l : input.split("\n")) {
   157             int spaces = 0;
   158             while (spaces < l.length() && l.charAt(spaces) == ' ') {
   159                 spaces++;
   160             }
   161             copy.append("<text:p text:style-name='Code'><text:s text:c='" + spaces + "'/>" + l.substring(spaces) + "</text:p>\n");
   162         }
   163         
   164         return copy.toString();
   165     }
   166     
   167     static final int countChar(CharSequence seq, char ch) {
   168         int cnt = 0;
   169         for (int i = 0; i < seq.length(); i++) {
   170             if (ch == seq.charAt(i)) {
   171                 cnt++;
   172             }
   173         }
   174         return cnt;
   175     }
   176 
   177     private final class Item implements CharSequence {
   178         private StringBuilder sb = new StringBuilder();
   179         private int spaces = Integer.MAX_VALUE;
   180         private Stack<Integer> remove = new Stack<Integer>();
   181         private final File file;
   182 
   183         public Item(File file) {
   184             this.file = file;
   185         }
   186 
   187         public int length() {
   188             return sb.length();
   189         }
   190 
   191         public char charAt(int index) {
   192             return sb.charAt(index);
   193         }
   194 
   195         public CharSequence subSequence(int start, int end) {
   196             return sb.subSequence(start, end);
   197         }
   198 
   199         private void append(String line) {
   200             for (int sp = 0; sp < line.length(); sp++) {
   201                 if (line.charAt(sp) != ' ') {
   202                     if (sp < spaces) {
   203                         spaces = sp;
   204                         break;
   205                     }
   206                 }
   207             }
   208             remove.push(sb.length());
   209             sb.append(line);
   210             sb.append('\n');
   211         }
   212 
   213         @Override
   214         public String toString() {
   215             return toString(false);
   216         }
   217         public String toString(boolean finish) {
   218             if (remove != null) {
   219                 while (!remove.isEmpty()) {
   220                    Integer pos = remove.pop();
   221                    for (int i = 0; i < spaces; i++) {
   222                        if (sb.charAt(pos) == '\n') {
   223                            break;
   224                        }
   225                        sb.deleteCharAt(pos);
   226                    }
   227                 }
   228                 remove = null;
   229                 
   230                 int line = 0;
   231                 for (int i = 0; i < sb.length(); i++) {
   232                     if (sb.charAt(i) == '\n') {
   233                         line = 0;
   234                         continue;
   235                     }
   236                     if (++line > len) {
   237                         throw new BuildException("Line is too long in: " + file + "\n" + sb);
   238                     }
   239                 }
   240                 
   241                 int open = countChar(sb, '{');
   242                 int end = countChar(sb, '}');
   243                 if (finish) {
   244                     for (int i = 0; i < open - end; i++) {
   245                         sb.append("}\n");
   246                     }
   247                 }
   248                 
   249                 if (countChar(sb, '{') != countChar(sb, '}')) {
   250                     throw new BuildException("not paired amount of braces in " + file + "\n" + sb);
   251                 }
   252                 
   253             }
   254             return sb.toString();
   255         }
   256     } // end of Item
   257 }