1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.doxia.sink.impl;
20
21 import javax.swing.text.AttributeSet;
22
23 import java.util.Collections;
24 import java.util.Enumeration;
25 import java.util.LinkedHashMap;
26 import java.util.Map;
27
28 import org.apache.maven.doxia.sink.SinkEventAttributes;
29
30
31
32
33
34
35
36 public class SinkEventAttributeSet implements SinkEventAttributes, Cloneable {
37
38
39
40 public static final SinkEventAttributes UNDERLINE;
41
42
43
44
45 public static final SinkEventAttributes OVERLINE;
46
47
48
49
50 public static final SinkEventAttributes LINETHROUGH;
51
52
53
54
55 public static final SinkEventAttributes SOURCE;
56
57
58
59
60 public static final SinkEventAttributes BOLD;
61
62
63
64
65 public static final SinkEventAttributes ITALIC;
66
67
68
69
70 public static final SinkEventAttributes MONOSPACED;
71
72
73
74
75 public static final SinkEventAttributes LEFT;
76
77
78
79
80 public static final SinkEventAttributes RIGHT;
81
82
83
84
85 public static final SinkEventAttributes CENTER;
86
87
88
89
90 public static final SinkEventAttributes JUSTIFY;
91
92 static {
93 UNDERLINE = new SinkEventAttributeSet(DECORATION, "underline").unmodifiable();
94 OVERLINE = new SinkEventAttributeSet(DECORATION, "overline").unmodifiable();
95 LINETHROUGH = new SinkEventAttributeSet(DECORATION, "line-through").unmodifiable();
96 SOURCE = new SinkEventAttributeSet(DECORATION, "source").unmodifiable();
97
98 BOLD = new SinkEventAttributeSet(STYLE, "bold").unmodifiable();
99 ITALIC = new SinkEventAttributeSet(STYLE, "italic").unmodifiable();
100 MONOSPACED = new SinkEventAttributeSet(STYLE, "monospaced").unmodifiable();
101
102 LEFT = new SinkEventAttributeSet(ALIGN, "left").unmodifiable();
103 RIGHT = new SinkEventAttributeSet(ALIGN, "right").unmodifiable();
104 CENTER = new SinkEventAttributeSet(ALIGN, "center").unmodifiable();
105 JUSTIFY = new SinkEventAttributeSet(ALIGN, "justify").unmodifiable();
106 }
107
108 private Map<String, Object> attribs;
109
110 private AttributeSet resolveParent;
111
112
113
114
115 public SinkEventAttributeSet() {
116 this(5);
117 }
118
119
120
121
122
123
124 public SinkEventAttributeSet(int size) {
125 attribs = new LinkedHashMap<>(size);
126 }
127
128
129
130
131
132
133
134
135 public SinkEventAttributeSet(String... attributes) {
136 int n = attributes.length;
137
138 if ((n % 2) != 0) {
139 throw new IllegalArgumentException("Missing attribute!");
140 }
141
142 attribs = new LinkedHashMap<>(n / 2);
143
144 for (int i = 0; i < n; i += 2) {
145 attribs.put(attributes[i], attributes[i + 1]);
146 }
147 }
148
149
150
151
152
153
154
155 public SinkEventAttributeSet(AttributeSet attributes) {
156 attribs = new LinkedHashMap<>(attributes.getAttributeCount());
157
158 Enumeration<?> names = attributes.getAttributeNames();
159
160 while (names.hasMoreElements()) {
161 Object name = names.nextElement();
162
163 attribs.put(name.toString(), attributes.getAttribute(name));
164 }
165 }
166
167
168
169
170
171
172
173
174
175 public SinkEventAttributeSet unmodifiable() {
176 this.attribs = Collections.unmodifiableMap(attribs);
177
178 return this;
179 }
180
181
182
183
184
185
186 public boolean isEmpty() {
187 return attribs.isEmpty();
188 }
189
190
191
192
193
194
195 public int getAttributeCount() {
196 return attribs.size();
197 }
198
199
200 public boolean isDefined(Object attrName) {
201 return attribs.containsKey(attrName);
202 }
203
204
205 public boolean isEqual(AttributeSet attr) {
206 return ((getAttributeCount() == attr.getAttributeCount()) && containsAttributes(attr));
207 }
208
209
210
211
212
213
214 public AttributeSet copyAttributes() {
215 return ((AttributeSet) clone());
216 }
217
218
219
220
221
222
223 public Enumeration<String> getAttributeNames() {
224 return Collections.enumeration(attribs.keySet());
225 }
226
227
228 public Object getAttribute(Object key) {
229 Object value = attribs.get(key);
230
231 if (value == null) {
232 AttributeSet parent = getResolveParent();
233
234 if (parent != null) {
235 value = parent.getAttribute(key);
236 }
237 }
238
239 return value;
240 }
241
242
243 public boolean containsAttribute(Object name, Object value) {
244 return value.equals(getAttribute(name));
245 }
246
247
248 public boolean containsAttributes(AttributeSet attributes) {
249 boolean result = true;
250
251 Enumeration<?> names = attributes.getAttributeNames();
252
253 while (result && names.hasMoreElements()) {
254 Object name = names.nextElement();
255 result = attributes.getAttribute(name).equals(getAttribute(name));
256 }
257
258 return result;
259 }
260
261
262
263
264
265
266 public void addAttribute(Object name, Object value) {
267 attribs.put(name.toString(), value);
268 }
269
270
271 public void addAttributes(AttributeSet attributes) {
272 if (attributes == null || attributes.getAttributeCount() == 0) {
273 return;
274 }
275
276 Enumeration<?> names = attributes.getAttributeNames();
277
278 while (names.hasMoreElements()) {
279 Object name = names.nextElement();
280
281 addAttribute(name, attributes.getAttribute(name));
282 }
283 }
284
285
286 public void removeAttribute(Object name) {
287 attribs.remove(name);
288 }
289
290
291 public void removeAttributes(Enumeration<?> names) {
292 while (names.hasMoreElements()) {
293 removeAttribute(names.nextElement());
294 }
295 }
296
297
298
299
300
301
302 public void removeAttributes(AttributeSet attributes) {
303 if (attributes == null) {
304 return;
305 } else if (attributes == this) {
306 attribs.clear();
307 } else {
308 Enumeration<?> names = attributes.getAttributeNames();
309
310 while (names.hasMoreElements()) {
311 Object name = names.nextElement();
312 Object value = attributes.getAttribute(name);
313
314 if (value.equals(getAttribute(name))) {
315 removeAttribute(name);
316 }
317 }
318 }
319 }
320
321
322
323
324
325
326 public AttributeSet getResolveParent() {
327 return this.resolveParent;
328 }
329
330
331 public void setResolveParent(AttributeSet parent) {
332 this.resolveParent = parent;
333 }
334
335
336 @Override
337 public Object clone() {
338 SinkEventAttributeSet attr = new SinkEventAttributeSet(attribs.size());
339 attr.attribs = new LinkedHashMap<>(attribs);
340
341 if (resolveParent != null) {
342 attr.resolveParent = resolveParent.copyAttributes();
343 }
344
345 return attr;
346 }
347
348
349 @Override
350 public int hashCode() {
351 final int parentHash = (resolveParent == null ? 0 : resolveParent.hashCode());
352
353 return attribs.hashCode() + parentHash;
354 }
355
356
357 @Override
358 public boolean equals(Object obj) {
359 if (this == obj) {
360 return true;
361 }
362
363 if (obj instanceof SinkEventAttributeSet) {
364 return isEqual((SinkEventAttributeSet) obj);
365 }
366
367 return false;
368 }
369
370
371 @Override
372 public String toString() {
373 StringBuilder s = new StringBuilder();
374 Enumeration<String> names = getAttributeNames();
375
376 while (names.hasMoreElements()) {
377 String key = names.nextElement();
378 String value = getAttribute(key).toString();
379
380 s.append(' ').append(key).append('=').append(value);
381 }
382
383 return s.toString();
384 }
385
386
387
388
389 public static class Semantics {
390
391
392
393 public static final SinkEventAttributes EMPHASIS;
394
395
396
397
398 public static final SinkEventAttributes STRONG;
399
400
401
402
403 public static final SinkEventAttributes SMALL;
404
405
406
407
408 public static final SinkEventAttributes LINE_THROUGH;
409
410
411
412
413 public static final SinkEventAttributes CITATION;
414
415
416
417
418 public static final SinkEventAttributes QUOTE;
419
420
421
422
423 public static final SinkEventAttributes DEFINITION;
424
425
426
427
428 public static final SinkEventAttributes ABBREVIATION;
429
430
431
432
433 public static final SinkEventAttributes ITALIC;
434
435
436
437
438 public static final SinkEventAttributes BOLD;
439
440
441
442
443 public static final SinkEventAttributes MONOSPACED;
444
445
446
447
448 public static final SinkEventAttributes CODE;
449
450
451
452
453 public static final SinkEventAttributes VARIABLE;
454
455
456
457
458 public static final SinkEventAttributes SAMPLE;
459
460
461
462
463 public static final SinkEventAttributes KEYBOARD;
464
465
466
467
468 public static final SinkEventAttributes SUPERSCRIPT;
469
470
471
472
473 public static final SinkEventAttributes SUBSCRIPT;
474
475
476
477
478 public static final SinkEventAttributes ANNOTATION;
479
480
481
482
483 public static final SinkEventAttributes HIGHLIGHT;
484
485
486
487
488 public static final SinkEventAttributes RUBY;
489
490
491
492
493 public static final SinkEventAttributes RUBY_BASE;
494
495
496
497
498 public static final SinkEventAttributes RUBY_TEXT;
499
500
501
502
503 public static final SinkEventAttributes RUBY_TEXT_CONTAINER;
504
505
506
507
508 public static final SinkEventAttributes RUBY_PARANTHESES;
509
510
511
512
513 public static final SinkEventAttributes BIDIRECTIONAL_ISOLATION;
514
515
516
517
518 public static final SinkEventAttributes BIDIRECTIONAL_OVERRIDE;
519
520
521
522
523 public static final SinkEventAttributes PHRASE;
524
525
526
527
528 public static final SinkEventAttributes INSERT;
529
530
531
532
533 public static final SinkEventAttributes DELETE;
534
535 static {
536 EMPHASIS = new SinkEventAttributeSet(SEMANTICS, "emphasis").unmodifiable();
537 STRONG = new SinkEventAttributeSet(SEMANTICS, "strong").unmodifiable();
538 SMALL = new SinkEventAttributeSet(SEMANTICS, "small").unmodifiable();
539 LINE_THROUGH = new SinkEventAttributeSet(SEMANTICS, "line-through").unmodifiable();
540 CITATION = new SinkEventAttributeSet(SEMANTICS, "citation").unmodifiable();
541 QUOTE = new SinkEventAttributeSet(SEMANTICS, "quote").unmodifiable();
542 DEFINITION = new SinkEventAttributeSet(SEMANTICS, "definition").unmodifiable();
543 ABBREVIATION = new SinkEventAttributeSet(SEMANTICS, "abbreviation").unmodifiable();
544 ITALIC = new SinkEventAttributeSet(SEMANTICS, "italic").unmodifiable();
545 BOLD = new SinkEventAttributeSet(SEMANTICS, "bold").unmodifiable();
546 MONOSPACED = new SinkEventAttributeSet(SEMANTICS, "monospaced").unmodifiable();
547 CODE = new SinkEventAttributeSet(SEMANTICS, "code").unmodifiable();
548 VARIABLE = new SinkEventAttributeSet(SEMANTICS, "variable").unmodifiable();
549 SAMPLE = new SinkEventAttributeSet(SEMANTICS, "sample").unmodifiable();
550 KEYBOARD = new SinkEventAttributeSet(SEMANTICS, "keyboard").unmodifiable();
551 SUPERSCRIPT = new SinkEventAttributeSet(SEMANTICS, "superscript").unmodifiable();
552 SUBSCRIPT = new SinkEventAttributeSet(SEMANTICS, "subscript").unmodifiable();
553 ANNOTATION = new SinkEventAttributeSet(SEMANTICS, "annotation").unmodifiable();
554 HIGHLIGHT = new SinkEventAttributeSet(SEMANTICS, "highlight").unmodifiable();
555 RUBY = new SinkEventAttributeSet(SEMANTICS, "ruby").unmodifiable();
556 RUBY_BASE = new SinkEventAttributeSet(SEMANTICS, "rubyBase").unmodifiable();
557 RUBY_TEXT = new SinkEventAttributeSet(SEMANTICS, "rubyText").unmodifiable();
558 RUBY_TEXT_CONTAINER = new SinkEventAttributeSet(SEMANTICS, "rubyTextContainer").unmodifiable();
559 RUBY_PARANTHESES = new SinkEventAttributeSet(SEMANTICS, "rubyParentheses").unmodifiable();
560 BIDIRECTIONAL_ISOLATION = new SinkEventAttributeSet(SEMANTICS, "bidirectionalIsolation").unmodifiable();
561 BIDIRECTIONAL_OVERRIDE = new SinkEventAttributeSet(SEMANTICS, "bidirectionalOverride").unmodifiable();
562 PHRASE = new SinkEventAttributeSet(SEMANTICS, "phrase").unmodifiable();
563 INSERT = new SinkEventAttributeSet(SEMANTICS, "insert").unmodifiable();
564 DELETE = new SinkEventAttributeSet(SEMANTICS, "delete").unmodifiable();
565 }
566 }
567 }