Index: jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java diff -u jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java:1.1.1.1 jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java:1.2 --- jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java:1.1.1.1 Mon Oct 30 19:34:05 2006 +++ jrst2/src/java/org/codelutin/jrst/JRSTGenerator.java Fri Nov 3 14:42:08 2006 @@ -23,9 +23,9 @@ * Created: 30 oct. 06 00:14:18 * * @author poussin - * @version $Revision: 1.1.1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2006/10/30 19:34:05 $ + * Last update: $Date: 2006/11/03 14:42:08 $ * by : $Author: bpoussin $ */ @@ -73,7 +73,7 @@ static boolean DEBUG = true; - static private Log log = LogFactory.getLog(JRSTGenerator.class); + static private Log log = LogFactory.getLog(JRSTGeneratorTest.class); protected Writer out = null; protected int sectionLevel = 0; Index: jrst2/src/java/org/codelutin/jrst/JRSTLexer.java diff -u jrst2/src/java/org/codelutin/jrst/JRSTLexer.java:1.1.1.1 jrst2/src/java/org/codelutin/jrst/JRSTLexer.java:1.2 --- jrst2/src/java/org/codelutin/jrst/JRSTLexer.java:1.1.1.1 Mon Oct 30 19:34:05 2006 +++ jrst2/src/java/org/codelutin/jrst/JRSTLexer.java Fri Nov 3 14:42:08 2006 @@ -23,9 +23,9 @@ * Created: 28 oct. 06 00:44:20 * * @author poussin - * @version $Revision: 1.1.1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2006/10/30 19:34:05 $ + * Last update: $Date: 2006/11/03 14:42:08 $ * by : $Author: bpoussin $ */ @@ -40,6 +40,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.dom4j.DocumentHelper; import org.dom4j.Element; @@ -54,33 +56,50 @@ * remove alors il peut relire autant de fois qu'il veut le meme element, ou * essayer d'en lire un autre. *
- * Pour mettre en place ce mecanisme le plus simple est d'utiliser les methodes - * {@link JRSTLexer#beginPeek()} et {@link JRSTLexer#endPeek()} - * + * Pour mettre en place ce mecanisme le plus simple est d'utiliser les methodes + * {@link JRSTLexer#beginPeek()} et {@link JRSTLexer#endPeek()} + * * @author poussin */ public class JRSTLexer { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(JRSTLexer.class); + + static final protected String TABLE = "table"; + static final protected String ROW = "row"; + static final protected String CELL = "cell"; + + static final protected String TABLE_HEADER = "header"; + static final protected String TABLE_WIDTH = "width"; + + static final protected String ROW_END_HEADER = "endHeader"; + + static final protected String CELL_INDEX_START = "indexStart"; + static final protected String CELL_INDEX_END = "indexEnd"; + static final protected String CELL_BEGIN = "begin"; + static final protected String CELL_END = "end"; /** - * retient le niveau du titre, pour un titre de type double, on met + * retient le niveau du titre, pour un titre de type double, on met * deux fois le caratere dans la chaine, sinon on le met une seul fois. - * + * *
* =====
* Super
* =====
- *
+ *
* titre
* -----
*
- *
+ *
* donnera dans la liste ["==", "-"]
*/
private List
* :author: Benjamin Poussin
- * :address:
+ * :address:
* Quelque part
* Dans le monde
*
- *
+ *
* @return
- * @throws IOException
+ * @throws IOException
*/
public Element peekDocInfo() throws IOException {
Element result = null;
@@ -200,12 +219,12 @@
}
if (result == null) {
result = peekFieldList();
- }
-
- return result;
+ }
+
+ return result;
}
-
+
/**
* Return para
* @return
@@ -233,17 +252,17 @@
}
if (result == null) {
result = peekLiteralBlock();
- }
+ }
if (result == null) {
result = peekPara();
- }
-
+ }
+
return result;
}
-
+
public Element peekTransition() throws IOException {
beginPeek();
-
+
Element result = null;
// must have one blank line before
@@ -260,52 +279,52 @@
}
}
}
-
- endPeek();
+
+ endPeek();
return result;
}
/**
* read paragraph with attribut level that represente the space numbers
- * at left side
- *
+ * at left side
+ *
* @return <paragraph level="[int]">[text]</paragraph>
- * @throws IOException
+ * @throws IOException
*/
public Element peekPara() throws IOException {
beginPeek();
-
+
Element result = null;
in.skipBlankLines();
-
+
String [] lines = readBlock(0);
- if (lines.length > 0) {
+ if (lines.length > 0) {
int level = level(lines[0]);
String para = joinBlock(lines);
-
+
if (para.endsWith(": ::")) {
para = para.substring(0, para.length() - " ::".length());
in.unread("::", true);
} else if (para.endsWith("::")) {
para = para.substring(0, para.length() - ":".length()); // keep one :
- in.unread("::", true);
+ in.unread("::", true);
}
-
+
result = DocumentHelper.createElement(PARAGRAPH)
.addAttribute("level", String.valueOf(level))
.addText(para);
}
- endPeek();
+ endPeek();
return result;
}
public Element peekLiteralBlock() throws IOException {
beginPeek();
-
+
Element result = null;
in.skipBlankLines();
-
+
String [] prefix = in.readLines(2);
if (prefix.length == 2 &&
prefix[0].matches("::\\s*") && prefix[1].matches("\\s*")) {
@@ -314,24 +333,24 @@
if (para != null) {
int level = level(para);
para = para.substring(level) + "\n";
-
- // it's literal block until level is down
+
+ // it's literal block until level is down
String [] lines = in.readWhile("^ {"+level+"}.*");
while (lines.length > 0) {
for (String line : lines) {
para += line.substring(level) + "\n";
- }
+ }
in.skipBlankLines();
lines = in.readWhile("^ {"+level+"}.*");
}
-
+
result = DocumentHelper.createElement(LITERAL_BLOCK)
.addAttribute("level", String.valueOf(level))
.addText(para);
}
}
- endPeek();
+ endPeek();
return result;
}
@@ -339,13 +358,13 @@
* read doc info author, date, version, ...
*
* :author: Benjamin Poussin
- * :address:
+ * :address:
* Quelque part
* Dans le monde
*
- *
+ *
* @return
- * @throws IOException
+ * @throws IOException
*/
public Element peekDocInfoItem() throws IOException {
beginPeek();
@@ -358,16 +377,16 @@
result = DocumentHelper.createElement(DOCINFO);
result.addAttribute("level", "0");
String infotype = line.substring(1, line.indexOf(":", 1));
-
+
if (!in.eof()) {
String [] content = readBlock(1);
line += joinBlock(content);
- }
+ }
String text = line.substring(line.indexOf(":", 1) + 1).trim();
-
+
// CVS, RCS support
text = text.replaceAll("\\$\\w+: (.+?)\\$", "$1");
-
+
result.addAttribute("type", infotype).addText(text);
}
@@ -385,42 +404,209 @@
in.skipBlankLines();
String line = in.readLine();
- if (line != null && line.matches("^\\s*(\\+-+)+\\+\\s*$")) { // complexe table
- result = DocumentHelper.createElement(TABLE);
- result.addAttribute("level", String.valueOf(level(line)));
-
- String [] table = in.readUntilBlank();
- line += "\n" + joinBlock(table, "\n", false);
-
- result.addText(line);
- } else if (line != null && line.matches("^\\s*(=+ +)+=+\\s*$")) { // simple table
- // dans les tables simples il peut y avoir des lignes blanches au
- // milieu. Mais la premiere et la derniere lignes sont identiques
- String first = line;
-
- result = DocumentHelper.createElement(TABLE);
- result.addAttribute("level", String.valueOf(level(line)));
-
- String [] table = in.readUntil(first);
- line += "\n" + joinBlock(table, "\n", false);
- String next = in.readLine();
- line += "\n" + next;
+ if (line != null) {
+ Pattern pTableBegin = Pattern.compile("^\\s*(\\+-+)+\\+\\s*$");
+ Matcher matcher = null;
- next = in.readLine();
- if (line != null) {
- if (next.matches("\\s*")) {
- // no header
- in.unread(next, true);
- } else {
- // read body table
- table = in.readUntil(first);
- line += "\n" + joinBlock(table, "\n", false);
- next = in.readLine();
- line += "\n" + next;
+ matcher = pTableBegin.matcher(line);
+ if (matcher.matches()) { // complexe table
+ result = DocumentHelper.createElement(TABLE);
+ result.addAttribute(TABLE_HEADER, "false");
+ int level = level(line);
+ result.addAttribute("level", String.valueOf(level));
+ line = line.trim();
+ int tableWidth = line.length();
+ result.addAttribute(TABLE_WIDTH, String.valueOf(tableWidth));
+
+ Pattern pCellEnd = Pattern.compile("^\\s{"+level+"}(\\+-+\\+|\\|(?:[^+]+))([^+]+(?:\\+|\\|\\s*$)|-+\\+)*\\s*"); // fin de ligne
+ Pattern pCell = Pattern.compile("^\\s{"+level+"}(\\|[^|]+)+\\|\\s*$"); // une ligne
+ Pattern pHeader = Pattern.compile("^\\s{"+level+"}(\\+=+)+\\+\\s*$"); // fin du header
+ Pattern pEnd = Pattern.compile("^\\s{"+level+"}(\\+-+)+\\+\\s*$"); // fin de table
+
+ // used to know if | is cell separator or not
+ String lastSeparationLine = line;
+ String lastLine = line;
+
+ Element row = DocumentHelper.createElement(ROW);
+ String [] table = in.readUntilBlank();
+ boolean done = false;
+ for (String l : table) {
+ done =false;
+ l = l.trim();
+ if (l.length() != tableWidth) {
+ // Erreur dans la table, peut-etre lever une exception ?
+ result = null;
+ break;
+ }
+ matcher = pEnd.matcher(l);
+ if (!done && matcher.matches()) {
+ // fin normale de ligne, on peut directement l'assigner
+ lastSeparationLine = l;
+ for (Element cell : (List
* 1. next line
* 1) next line
* (1) first line
*
- *
+ *
* @return <enumerated_list level="[int]" start="[number]" prefix="[char]" suffix="[char]" enumtype="[(arabic|loweralpha|upperalpha|lowerroman|upperroman]">[text]</enumerated_list>
- * @throws IOException
+ * @throws IOException
*/
public Element peekEnumeratedList() throws IOException {
beginPeek();
@@ -596,8 +782,8 @@
String start = matcher.group(2);
String suffix = matcher.group(3);
int begin = matcher.end(3);
-
- // arabic|loweralpha|upperalpha|lowerroman|upperroman
+
+ // arabic|loweralpha|upperalpha|lowerroman|upperroman
String enumtype = "auto";
if (start.matches("\\d+")) {
enumtype = "arabic";
@@ -614,7 +800,7 @@
enumtype = "upperalpha";
start = String.valueOf((int)start.charAt(0) -(int)'A');
}
-
+
result = DocumentHelper.createElement(ENUMERATED_LIST)
.addAttribute("level", String.valueOf(level))
.addAttribute("start", start)
@@ -625,7 +811,7 @@
if (!in.eof()) {
String [] content = readBlock(level + 1);
line += " " + joinBlock(content);
- }
+ }
String text = line.substring(begin).trim();
result.addText(text);
@@ -638,22 +824,22 @@
/**
* Parse un titre simple ou double
- *
+ *
* simple:
*
* Le titre
* ========
*
- *
+ *
* double:
*
* ============
* le titre
* ============
*
- *
+ *
* @return <title level="[int]" type="[simple|double]" char="[underline char]">
- * @throws IOException
+ * @throws IOException
*/
public Element peekTitle() throws IOException {
beginPeek();
@@ -683,12 +869,12 @@
.addText(line);
}
}
-
+
if (result != null) {
// add level information
String titleLevel = result.attributeValue("char");
if ("double".equals(result.attributeValue("type"))) {
- titleLevel += titleLevel;
+ titleLevel += titleLevel;
}
int level = titleLevels.indexOf(titleLevel);
if (level == -1) {
@@ -697,7 +883,7 @@
}
result.addAttribute("level", String.valueOf(JRSTReader.MAX_SECTION_DEPTH + level));
}
-
+
endPeek();
return result;
}
@@ -716,7 +902,7 @@
boolean result = line.matches("(["+escapeRegex(TITLE_CHAR)+"])\\1+");
return result;
}
-
+
/**
* @param title_char
* @return
@@ -727,13 +913,13 @@
}
private int level(String line) {
- int result = 0;
+ int result = 0;
while (line.length() > result && line.charAt(result) == ' ') {
result++;
}
return result;
}
-
+
}
Index: jrst2/src/java/org/codelutin/jrst/JRSTReader.java
diff -u jrst2/src/java/org/codelutin/jrst/JRSTReader.java:1.1.1.1 jrst2/src/java/org/codelutin/jrst/JRSTReader.java:1.2
--- jrst2/src/java/org/codelutin/jrst/JRSTReader.java:1.1.1.1 Mon Oct 30 19:34:05 2006
+++ jrst2/src/java/org/codelutin/jrst/JRSTReader.java Fri Nov 3 14:42:08 2006
@@ -23,9 +23,9 @@
* Created: 27 oct. 06 00:15:34
*
* @author poussin
- * @version $Revision: 1.1.1.1 $
+ * @version $Revision: 1.2 $
*
- * Last update: $Date: 2006/10/30 19:34:05 $
+ * Last update: $Date: 2006/11/03 14:42:08 $
* by : $Author: bpoussin $
*/
@@ -35,6 +35,10 @@
import java.io.IOException;
import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
import java.util.regex.Matcher;
import org.apache.commons.lang.ObjectUtils;
@@ -159,7 +163,7 @@
* * On construit un arbre XML representant le RST au fur et a mesure, on peut * ensuite appliquer une fueille de style ou autre chose avec - * {@link JRSTGenerator} + * {@link JRSTGeneratorTest} * *
* Tous les elements ont un attribut level qui permet de savoir on il est dans
@@ -317,13 +321,15 @@
Element para = parent.addElement(LITERAL_BLOCK);
copyLevel(item, para);
para.setText(item.getText());
- } else if (itemEquals(TABLE, item)) {
+ } else if (itemEquals(JRSTLexer.TABLE, item)) {
// TODO now we take table as LITERAL_BLOCK, but in near
// futur we must parse correctly TABLE (show JRSTGenerator and JRSTLexer too)
lexer.remove();
- Element para = parent.addElement(TABLE);
- copyLevel(item, para);
- para.setText(item.getText());
+ Element table = composeTable(lexer, item);
+ parent.add(table);
+ // Element para = parent.addElement(TABLE);
+// copyLevel(item, para);
+// para.setText(item.getText());
} else if (itemEquals(BULLET_LIST, item)) {
Element list = composeBulletList(lexer);
parent.add(list);
@@ -348,6 +354,104 @@
return parent;
}
+ /**
+ * @param lexer
+ * @param item
+ * @return
+ */
+ private Element composeTable(JRSTLexer lexer, Element item) throws IOException, DocumentException {
+ Element result = DocumentHelper.createElement(TABLE);
+
+ int tableWidth = Integer.parseInt(item.attributeValue(JRSTLexer.TABLE_WIDTH));
+
+ TreeSet