262bee3581c925c0544bbe9ed40dd6fb0c903173
[sixth.git] / src / main / java / eu / svjatoslav / sixth / core / document / Document.java
1 package eu.svjatoslav.sixth.core.document;
2
3 import eu.svjatoslav.commons.string.String2;
4 import eu.svjatoslav.commons.string.tokenizer.InvalidSyntaxException;
5 import eu.svjatoslav.commons.string.tokenizer.Tokenizer;
6 import eu.svjatoslav.commons.string.tokenizer.TokenizerMatch;
7 import eu.svjatoslav.sixth.core.document.text.FormattedText;
8
9 import static eu.svjatoslav.commons.string.tokenizer.Terminator.TerminationStrategy.DROP;
10 import static eu.svjatoslav.commons.string.tokenizer.Terminator.TerminationStrategy.PRESERVE;
11 import static eu.svjatoslav.sixth.core.document.Helper.*;
12 import static eu.svjatoslav.sixth.core.document.text.FormattedText.fromOrg;
13
14 public class Document {
15     public final Heading rootHeading = new Heading( null , 0, null);
16     private Heading currentHeading = rootHeading;
17
18     public Heading createHeading(FormattedText name, int targetLevel){
19         if (currentHeading.level == (targetLevel - 1)){
20             Heading newHeading = new Heading(name, targetLevel, currentHeading);
21             currentHeading.addChild(newHeading);
22             currentHeading = newHeading;
23             return newHeading;
24         }
25
26         if (currentHeading.level > (targetLevel - 1)){
27             currentHeading = currentHeading.parent;
28             return createHeading(name, targetLevel);
29         }
30
31         try {
32             Heading missingIntermediate = new Heading(fromOrg("<noname>"), currentHeading.level + 1, currentHeading);
33             currentHeading.addChild(missingIntermediate);
34             currentHeading = missingIntermediate;
35             return createHeading(name, targetLevel);
36         } catch (InvalidSyntaxException e) {
37             throw new IllegalStateException("impossible situation");
38         }
39     }
40
41     public Heading getCurrentHeading(){
42         return currentHeading;
43     }
44
45     private void parseHeading(TokenizerMatch token) throws InvalidSyntaxException {
46         // expected sample heading:
47         // ***** test heading
48
49         String[] headingSections = String2.getGroups(token.token, "(\\*+)[ \\t](.*)\\r?\\n");
50         int level = headingSections[0].length();
51         String title = headingSections[1];
52         createHeading(fromOrg(title), level);
53     }
54
55     public void parse(String fileContentsAsString) throws InvalidSyntaxException {
56         final Tokenizer tokenizer = new Tokenizer(fileContentsAsString);
57
58         // Org heading:
59         // "*** Example Heading 1234"
60         tokenizer.addTerminator(PRESERVE, "\\*+[ \\t].*\\r?\\n", TG_HEADING);
61
62         // Org list. Examples:
63         // "   + my list title"
64         // "   - my list title"
65         tokenizer.addTerminator(PRESERVE, "[ \\t]*(\\+|-)([ \\t].*)?\\r?\\n", TG_LIST);
66
67         // "   * my list title"
68         tokenizer.addTerminator(PRESERVE, "[ \\t]+\\*([ \\t].*)?\\r?\\n", TG_LIST);
69
70         // DocumentProperty:
71         // "#+OPTIONS: H:20 num:20"
72         tokenizer.addTerminator(PRESERVE, "#\\+.+:.*\\r?\\n", TG_DOCUMENT_PROPERTY);
73
74         // newline
75         tokenizer.addTerminator(DROP,"\\r?\\n", TG_NEWLINE);
76
77
78         while (tokenizer.hasMoreContent()) {
79             final TokenizerMatch tm = tokenizer.getNextToken();
80
81             if (tm.isGroup(TG_HEADING)){
82                 parseHeading(tm);
83                 continue;
84             }
85
86             tokenizer.unreadToken();
87             currentHeading.parse(tokenizer);
88         }
89
90     }
91 }