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