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 paths.put(entry.getKey(), path);
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
126 } catch (IOException ex) {
127 throw new BuildException(ex);
129 if (!filter.hasFilters()) {
130 throw new BuildException("No filter found!");
136 public void execute() throws BuildException {
138 throw new BuildException();
140 FilterSet filter = createFilterSet();
141 getProject().addReference(id, filter);
144 final URL getPath(URL root, String key) throws MalformedURLException {
145 return new URL(root, paths.get(key));
148 private String linize(String input) {
153 StringBuilder copy = new StringBuilder();
154 for (String l : input.split("\n")) {
156 while (spaces < l.length() && l.charAt(spaces) == ' ') {
159 copy.append("<text:p text:style-name='Code'><text:s text:c='" + spaces + "'/>" + l.substring(spaces) + "</text:p>\n");
162 return copy.toString();
165 static final int countChar(CharSequence seq, char ch) {
167 for (int i = 0; i < seq.length(); i++) {
168 if (ch == seq.charAt(i)) {
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;
181 public Item(File file) {
185 public int length() {
189 public char charAt(int index) {
190 return sb.charAt(index);
193 public CharSequence subSequence(int start, int end) {
194 return sb.subSequence(start, end);
197 private void append(String line) {
198 for (int sp = 0; sp < line.length(); sp++) {
199 if (line.charAt(sp) != ' ') {
206 remove.push(sb.length());
212 public String toString() {
213 return toString(false);
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') {
223 sb.deleteCharAt(pos);
229 for (int i = 0; i < sb.length(); i++) {
230 if (sb.charAt(i) == '\n') {
235 throw new BuildException("Line is too long in: " + file + "\n" + sb);
239 int open = countChar(sb, '{');
240 int end = countChar(sb, '}');
242 for (int i = 0; i < open - end; i++) {
247 if (countChar(sb, '{') != countChar(sb, '}')) {
248 throw new BuildException("not paired amount of braces in " + file + "\n" + sb);
252 return sb.toString();