jtulach@268: package org.apidesign.infra.ant; jtulach@268: jtulach@268: import java.io.BufferedReader; jtulach@268: import java.io.File; jtulach@268: import java.io.FileReader; jtulach@268: import java.io.IOException; jtulach@274: import java.net.MalformedURLException; jtulach@274: import java.net.URL; jtulach@268: import java.util.HashMap; jtulach@268: import java.util.Map; jtulach@268: import java.util.Stack; jtulach@268: import java.util.regex.Matcher; jtulach@268: import java.util.regex.Pattern; jtulach@268: import org.apache.tools.ant.BuildException; jtulach@268: import org.apache.tools.ant.DirectoryScanner; jtulach@268: import org.apache.tools.ant.Task; jtulach@268: import org.apache.tools.ant.types.FileSet; jtulach@268: import org.apache.tools.ant.types.FilterSet; jtulach@268: jtulach@268: /** jtulach@268: * jtulach@268: * @author Jaroslav Tulach jtulach@268: */ jtulach@268: public final class GrepFilter extends Task { jtulach@268: private int len = 80; jtulach@268: private String id; jtulach@268: private FileSet fs; jtulach@268: private Pattern begin = Pattern.compile(".* BEGIN: *(\\p{Graph}+)[-\\> ]*"); jtulach@268: private Pattern end = Pattern.compile(".* (END|FINISH): *(\\p{Graph}+)[-\\> ]*"); jtulach@268: private boolean openoffice; jtulach@274: private Map paths = new HashMap(); jtulach@268: jtulach@268: jtulach@268: public FileSet createFileSet() { jtulach@268: if (fs != null) { jtulach@268: throw new BuildException(); jtulach@268: } jtulach@268: this.fs = new FileSet(); jtulach@268: return fs; jtulach@268: } jtulach@268: jtulach@268: public void setId(String id) { jtulach@268: this.id = id; jtulach@268: } jtulach@268: jtulach@268: public void setMaxLineLength(int len) { jtulach@268: this.len = len; jtulach@268: } jtulach@268: jtulach@268: public void setOutputFormat(String f) { jtulach@268: if (f.equals("opendocument")) { jtulach@268: openoffice = true; jtulach@268: return; jtulach@268: } jtulach@268: throw new BuildException("Wrong format: " + f); jtulach@268: } jtulach@268: jtulach@268: final FilterSet createFilterSet() { jtulach@268: if (fs == null) { jtulach@268: throw new BuildException(); jtulach@268: } jtulach@268: jtulach@268: FilterSet filter = new FilterSet(); jtulach@268: jtulach@268: try { jtulach@268: DirectoryScanner ds = fs.getDirectoryScanner(getProject()); jtulach@268: Map texts = new HashMap(); jtulach@268: for (String path : ds.getIncludedFiles()) { jtulach@268: File file = new File(ds.getBasedir(), path); jtulach@268: BufferedReader r = new BufferedReader(new FileReader(file)); jtulach@268: for (;;) { jtulach@268: String line = r.readLine(); jtulach@268: if (line == null) { jtulach@268: break; jtulach@268: } jtulach@268: { jtulach@268: Matcher m = begin.matcher(line); jtulach@268: if (m.matches()) { jtulach@268: Item sb = new Item(file); jtulach@268: CharSequence prev = texts.put(m.group(1), sb); jtulach@268: if (prev != null) { jtulach@268: throw new BuildException("Same pattern is there twice: " + m.group(1) + " in " + file); jtulach@268: } jtulach@268: continue; jtulach@268: } jtulach@268: } jtulach@268: { jtulach@268: Matcher m = end.matcher(line); jtulach@268: if (m.matches()) { jtulach@268: CharSequence s = texts.get(m.group(2)); jtulach@268: if (s instanceof Item) { jtulach@268: texts.put(m.group(2), ((Item)s).toString(m.group(1).equals("FINISH"))); jtulach@268: continue; jtulach@268: } jtulach@268: jtulach@268: if (s == null) { jtulach@268: throw new BuildException("Closing unknown section: " + m.group(2) + " in " + file); jtulach@268: } jtulach@268: throw new BuildException("Closing not opened section: " + m.group(2) + " in " + file); jtulach@268: } jtulach@268: } jtulach@268: jtulach@268: for (CharSequence charSequence : texts.values()) { jtulach@268: if (charSequence instanceof Item) { jtulach@268: Item sb = (Item)charSequence; jtulach@268: sb.append(line); jtulach@268: } jtulach@268: } jtulach@268: } jtulach@268: jtulach@268: for (Map.Entry entry : texts.entrySet()) { jtulach@268: CharSequence v = entry.getValue(); jtulach@268: if (v instanceof Item) { jtulach@268: throw new BuildException("Not closed section " + entry.getKey() + " in " + file); jtulach@268: } jtulach@268: entry.setValue(v.toString()); jtulach@275: if (!paths.containsKey(entry.getKey())) { jtulach@275: paths.put(entry.getKey(), path); jtulach@275: } jtulach@268: } jtulach@268: } jtulach@268: jtulach@268: for (Map.Entry entry : texts.entrySet()) { jtulach@268: String text = entry.getValue().toString(); jtulach@268: String out = linize(text); jtulach@268: filter.addFilter(entry.getKey(), out); // NOI18N jtulach@268: } jtulach@268: } catch (IOException ex) { jtulach@268: throw new BuildException(ex); jtulach@268: } jtulach@268: if (!filter.hasFilters()) { jtulach@268: throw new BuildException("No filter found!"); jtulach@268: } jtulach@268: return filter; jtulach@268: } jtulach@268: jtulach@268: @Override jtulach@268: public void execute() throws BuildException { jtulach@268: if (id == null) { jtulach@268: throw new BuildException(); jtulach@268: } jtulach@268: FilterSet filter = createFilterSet(); jtulach@268: getProject().addReference(id, filter); jtulach@268: } jtulach@274: jtulach@274: final URL getPath(URL root, String key) throws MalformedURLException { jtulach@274: return new URL(root, paths.get(key)); jtulach@274: } jtulach@268: jtulach@268: private String linize(String input) { jtulach@268: if (!openoffice) { jtulach@268: return input; jtulach@268: } jtulach@268: jtulach@268: StringBuilder copy = new StringBuilder(); jtulach@268: for (String l : input.split("\n")) { jtulach@268: int spaces = 0; jtulach@268: while (spaces < l.length() && l.charAt(spaces) == ' ') { jtulach@268: spaces++; jtulach@268: } jtulach@268: copy.append("" + l.substring(spaces) + "\n"); jtulach@268: } jtulach@268: jtulach@268: return copy.toString(); jtulach@268: } jtulach@268: jtulach@268: static final int countChar(CharSequence seq, char ch) { jtulach@268: int cnt = 0; jtulach@268: for (int i = 0; i < seq.length(); i++) { jtulach@268: if (ch == seq.charAt(i)) { jtulach@268: cnt++; jtulach@268: } jtulach@268: } jtulach@268: return cnt; jtulach@268: } jtulach@268: jtulach@268: private final class Item implements CharSequence { jtulach@268: private StringBuilder sb = new StringBuilder(); jtulach@268: private int spaces = Integer.MAX_VALUE; jtulach@268: private Stack remove = new Stack(); jtulach@268: private final File file; jtulach@268: jtulach@268: public Item(File file) { jtulach@268: this.file = file; jtulach@268: } jtulach@268: jtulach@268: public int length() { jtulach@268: return sb.length(); jtulach@268: } jtulach@268: jtulach@268: public char charAt(int index) { jtulach@268: return sb.charAt(index); jtulach@268: } jtulach@268: jtulach@268: public CharSequence subSequence(int start, int end) { jtulach@268: return sb.subSequence(start, end); jtulach@268: } jtulach@268: jtulach@268: private void append(String line) { jtulach@268: for (int sp = 0; sp < line.length(); sp++) { jtulach@268: if (line.charAt(sp) != ' ') { jtulach@268: if (sp < spaces) { jtulach@268: spaces = sp; jtulach@268: break; jtulach@268: } jtulach@268: } jtulach@268: } jtulach@268: remove.push(sb.length()); jtulach@268: sb.append(line); jtulach@268: sb.append('\n'); jtulach@268: } jtulach@268: jtulach@268: @Override jtulach@268: public String toString() { jtulach@268: return toString(false); jtulach@268: } jtulach@268: public String toString(boolean finish) { jtulach@268: if (remove != null) { jtulach@268: while (!remove.isEmpty()) { jtulach@268: Integer pos = remove.pop(); jtulach@268: for (int i = 0; i < spaces; i++) { jtulach@268: if (sb.charAt(pos) == '\n') { jtulach@268: break; jtulach@268: } jtulach@268: sb.deleteCharAt(pos); jtulach@268: } jtulach@268: } jtulach@268: remove = null; jtulach@268: jtulach@268: int line = 0; jtulach@268: for (int i = 0; i < sb.length(); i++) { jtulach@268: if (sb.charAt(i) == '\n') { jtulach@268: line = 0; jtulach@268: continue; jtulach@268: } jtulach@268: if (++line > len) { jtulach@268: throw new BuildException("Line is too long in: " + file + "\n" + sb); jtulach@268: } jtulach@268: } jtulach@268: jtulach@268: int open = countChar(sb, '{'); jtulach@268: int end = countChar(sb, '}'); jtulach@268: if (finish) { jtulach@268: for (int i = 0; i < open - end; i++) { jtulach@268: sb.append("}\n"); jtulach@268: } jtulach@268: } jtulach@268: jtulach@268: if (countChar(sb, '{') != countChar(sb, '}')) { jtulach@268: throw new BuildException("not paired amount of braces in " + file + "\n" + sb); jtulach@268: } jtulach@268: jtulach@268: } jtulach@268: return sb.toString(); jtulach@268: } jtulach@268: } // end of Item jtulach@268: }