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.SinkEventAttributes;
35 import org.apache.maven.doxia.sink.impl.SinkAdapter;
36 import org.apache.maven.doxia.util.DoxiaUtils;
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
79 @Singleton
80 @Named("toc")
81 public class TocMacro extends AbstractMacro {
82
83 private int section;
84
85
86 private int fromDepth;
87
88
89 private int toDepth = DEFAULT_DEPTH;
90
91
92 private static final int DEFAULT_DEPTH = 5;
93
94
95 public void execute(Sink sink, MacroRequest request) throws MacroExecutionException {
96 String source = request.getSourceContent();
97 Parser parser = request.getParser();
98
99 section = getInt(request, "section", 0);
100 fromDepth = getInt(request, "fromDepth", 0);
101 toDepth = getInt(request, "toDepth", DEFAULT_DEPTH);
102
103 if (fromDepth > toDepth) {
104 return;
105 }
106
107 IndexingSink tocSink = new IndexingSink(new SinkAdapter());
108 try {
109 parser.parse(new StringReader(source), tocSink);
110 } catch (ParseException e) {
111 throw new MacroExecutionException(e);
112 } finally {
113 tocSink.close();
114 }
115
116 writeTocForIndexEntry(sink, getAttributesFromMap(request.getParameters()), tocSink.getRootEntry());
117 }
118
119 void writeTocForIndexEntry(Sink sink, SinkEventAttributes listAttributes, IndexEntry rootEntry) {
120 IndexEntry index = rootEntry;
121 if (index.getChildEntries().size() > 0) {
122 sink.list(listAttributes);
123
124 int i = 1;
125
126 for (IndexEntry sectionIndex : index.getChildEntries()) {
127 if ((i == section) || (section == 0)) {
128 writeSubSectionN(sink, sectionIndex, 1);
129 }
130
131 i++;
132 }
133
134 sink.list_();
135 }
136 }
137
138
139
140
141
142
143
144 private void writeSubSectionN(Sink sink, IndexEntry sectionIndex, int n) {
145 boolean isRelevantIndex = isRelevantIndexEntry(sectionIndex);
146 if (fromDepth <= n && isRelevantIndex) {
147 sink.listItem();
148 sink.link("#" + DoxiaUtils.encodeId(sectionIndex.getId()));
149 sink.text(sectionIndex.getTitle());
150 sink.link_();
151 }
152
153 if (toDepth > n) {
154 if (sectionIndex.getChildEntries().size() > 0) {
155 if (fromDepth <= n && isRelevantIndex) {
156 sink.list();
157 }
158
159 for (IndexEntry subsectionIndex : sectionIndex.getChildEntries()) {
160 if (n == toDepth - 1 && isRelevantIndex) {
161 sink.listItem();
162 sink.link("#" + DoxiaUtils.encodeId(subsectionIndex.getId()));
163 sink.text(subsectionIndex.getTitle());
164 sink.link_();
165 sink.listItem_();
166 } else {
167 writeSubSectionN(sink, subsectionIndex, n + 1);
168 }
169 }
170
171 if (fromDepth <= n && isRelevantIndex) {
172 sink.list_();
173 }
174 }
175 }
176
177 if (fromDepth <= n && isRelevantIndex) {
178 sink.listItem_();
179 }
180 }
181
182 static boolean isRelevantIndexEntry(IndexEntry indexEntry) {
183 return indexEntry.hasId() && indexEntry.getType().isSection();
184 }
185
186
187
188
189
190
191
192
193 private static int getInt(MacroRequest request, String parameter, int defaultValue) throws MacroExecutionException {
194 String value = (String) request.getParameter(parameter);
195
196 if (value == null || value.isEmpty()) {
197 return defaultValue;
198 }
199
200 int i;
201
202 try {
203 i = Integer.parseInt(value);
204 } catch (NumberFormatException e) {
205 return defaultValue;
206 }
207
208 if (i < 0) {
209 throw new MacroExecutionException("The " + parameter + "=" + i + " should be positive.");
210 }
211
212 return i;
213 }
214 }