1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.doxia.macro.toc;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.io.StringReader;
25
26 import org.apache.maven.doxia.index.IndexEntry;
27 import org.apache.maven.doxia.index.IndexingSink;
28 import org.apache.maven.doxia.macro.AbstractMacro;
29 import org.apache.maven.doxia.macro.MacroExecutionException;
30 import org.apache.maven.doxia.macro.MacroRequest;
31 import org.apache.maven.doxia.parser.ParseException;
32 import org.apache.maven.doxia.parser.Parser;
33 import org.apache.maven.doxia.sink.Sink;
34 import org.apache.maven.doxia.sink.impl.SinkAdapter;
35 import org.apache.maven.doxia.util.DoxiaUtils;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 @Singleton
79 @Named("toc")
80 public class TocMacro extends AbstractMacro {
81
82 private int section;
83
84
85 private int fromDepth;
86
87
88 private int toDepth;
89
90
91 private static final int DEFAULT_DEPTH = 5;
92
93
94 public void execute(Sink sink, MacroRequest request) throws MacroExecutionException {
95 String source = request.getSourceContent();
96 Parser parser = request.getParser();
97
98 section = getInt(request, "section", 0);
99 fromDepth = getInt(request, "fromDepth", 0);
100 toDepth = getInt(request, "toDepth", DEFAULT_DEPTH);
101
102 if (fromDepth > toDepth) {
103 return;
104 }
105
106 IndexingSink tocSink = new IndexingSink(new SinkAdapter());
107 try {
108 parser.parse(new StringReader(source), tocSink);
109 } catch (ParseException e) {
110 throw new MacroExecutionException(e);
111 } finally {
112 tocSink.close();
113 }
114
115 IndexEntry index = tocSink.getRootEntry();
116 if (index.getChildEntries().size() > 0) {
117 sink.list(getAttributesFromMap(request.getParameters()));
118
119 int i = 1;
120
121 for (IndexEntry sectionIndex : index.getChildEntries()) {
122 if ((i == section) || (section == 0)) {
123 writeSubSectionN(sink, sectionIndex, 1);
124 }
125
126 i++;
127 }
128
129 sink.list_();
130 }
131 }
132
133
134
135
136
137
138 private void writeSubSectionN(Sink sink, IndexEntry sectionIndex, int n) {
139 if (fromDepth <= n) {
140 sink.listItem();
141 sink.link("#" + DoxiaUtils.encodeId(sectionIndex.getId()));
142 sink.text(sectionIndex.getTitle());
143 sink.link_();
144 }
145
146 if (toDepth > n) {
147 if (sectionIndex.getChildEntries().size() > 0) {
148 if (fromDepth <= n) {
149 sink.list();
150 }
151
152 for (IndexEntry subsectionIndex : sectionIndex.getChildEntries()) {
153 if (n == toDepth - 1) {
154 sink.listItem();
155 sink.link("#" + DoxiaUtils.encodeId(subsectionIndex.getId()));
156 sink.text(subsectionIndex.getTitle());
157 sink.link_();
158 sink.listItem_();
159 } else {
160 writeSubSectionN(sink, subsectionIndex, n + 1);
161 }
162 }
163
164 if (fromDepth <= n) {
165 sink.list_();
166 }
167 }
168 }
169
170 if (fromDepth <= n) {
171 sink.listItem_();
172 }
173 }
174
175
176
177
178
179
180
181
182 private static int getInt(MacroRequest request, String parameter, int defaultValue) throws MacroExecutionException {
183 String value = (String) request.getParameter(parameter);
184
185 if (value == null || value.isEmpty()) {
186 return defaultValue;
187 }
188
189 int i;
190
191 try {
192 i = Integer.parseInt(value);
193 } catch (NumberFormatException e) {
194 return defaultValue;
195 }
196
197 if (i < 0) {
198 throw new MacroExecutionException("The " + parameter + "=" + i + " should be positive.");
199 }
200
201 return i;
202 }
203 }