Bob pointed out that the extends bound is not necessary in Listable. Enough to have it in List.
1 package org.apidesign.infra.ant;
3 import java.io.BufferedReader;
5 import java.io.FileReader;
6 import java.io.IOException;
7 import java.net.MalformedURLException;
9 import java.util.HashMap;
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;
22 * @author Jaroslav Tulach
24 public final class GrepFilter extends Task {
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>();
34 public FileSet createFileSet() {
36 throw new BuildException();
38 this.fs = new FileSet();
42 public void setId(String id) {
46 public void setMaxLineLength(int len) {
50 public void setOutputFormat(String f) {
51 if (f.equals("opendocument")) {
55 throw new BuildException("Wrong format: " + f);
58 final FilterSet createFilterSet() {
60 throw new BuildException();
63 FilterSet filter = new FilterSet();
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));
72 String line = r.readLine();
77 Matcher m = begin.matcher(line);
79 Item sb = new Item(file);
80 CharSequence prev = texts.put(m.group(1), sb);
82 throw new BuildException("Same pattern is there twice: " + m.group(1) + " in " + file);
88 Matcher m = end.matcher(line);
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")));
97 throw new BuildException("Closing unknown section: " + m.group(2) + " in " + file);
99 throw new BuildException("Closing not opened section: " + m.group(2) + " in " + file);
103 for (CharSequence charSequence : texts.values()) {
104 if (charSequence instanceof Item) {
105 Item sb = (Item)charSequence;
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);
116 entry.setValue(v.toString());
117 if (!paths.containsKey(entry.getKey())) {
118 paths.put(entry.getKey(), path);
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
128 } catch (IOException ex) {
129 throw new BuildException(ex);
131 if (!filter.hasFilters()) {
132 throw new BuildException("No filter found!");
138 public void execute() throws BuildException {
140 throw new BuildException();
142 FilterSet filter = createFilterSet();
143 getProject().addReference(id, filter);
146 final URL getPath(URL root, String key) throws MalformedURLException {
147 return new URL(root, paths.get(key));
150 private String linize(String input) {
155 StringBuilder copy = new StringBuilder();
156 for (String l : input.split("\n")) {
158 while (spaces < l.length() && l.charAt(spaces) == ' ') {
161 copy.append("<text:p text:style-name='Code'><text:s text:c='" + spaces + "'/>" + l.substring(spaces) + "</text:p>\n");
164 return copy.toString();
167 static final int countChar(CharSequence seq, char ch) {
169 for (int i = 0; i < seq.length(); i++) {
170 if (ch == seq.charAt(i)) {
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;
183 public Item(File file) {
187 public int length() {
191 public char charAt(int index) {
192 return sb.charAt(index);
195 public CharSequence subSequence(int start, int end) {
196 return sb.subSequence(start, end);
199 private void append(String line) {
200 for (int sp = 0; sp < line.length(); sp++) {
201 if (line.charAt(sp) != ' ') {
208 remove.push(sb.length());
214 public String toString() {
215 return toString(false);
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') {
225 sb.deleteCharAt(pos);
231 for (int i = 0; i < sb.length(); i++) {
232 if (sb.charAt(i) == '\n') {
237 throw new BuildException("Line is too long in: " + file + "\n" + sb);
241 int open = countChar(sb, '{');
242 int end = countChar(sb, '}');
244 for (int i = 0; i < open - end; i++) {
249 if (countChar(sb, '{') != countChar(sb, '}')) {
250 throw new BuildException("not paired amount of braces in " + file + "\n" + sb);
254 return sb.toString();