1 package org.apache.maven.doxia.sink.impl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.LinkedHashMap;
25 import java.util.Map;
26
27 import javax.swing.text.AttributeSet;
28
29 import org.apache.maven.doxia.sink.SinkEventAttributes;
30
31
32
33
34
35
36
37
38 public class SinkEventAttributeSet
39 implements SinkEventAttributes, Cloneable
40 {
41
42
43
44 public static final SinkEventAttributes UNDERLINE;
45
46
47
48
49 public static final SinkEventAttributes OVERLINE;
50
51
52
53
54 public static final SinkEventAttributes LINETHROUGH;
55
56
57
58
59 public static final SinkEventAttributes BOXED;
60
61
62
63
64 public static final SinkEventAttributes BOLD;
65
66
67
68
69 public static final SinkEventAttributes ITALIC;
70
71
72
73
74 public static final SinkEventAttributes MONOSPACED;
75
76
77
78
79 public static final SinkEventAttributes LEFT;
80
81
82
83
84 public static final SinkEventAttributes RIGHT;
85
86
87
88
89 public static final SinkEventAttributes CENTER;
90
91
92
93
94 public static final SinkEventAttributes JUSTIFY;
95
96
97 static
98 {
99 UNDERLINE = new SinkEventAttributeSet( new String[] {DECORATION, "underline"} ).unmodifiable();
100 OVERLINE = new SinkEventAttributeSet( new String[] {DECORATION, "overline"} ).unmodifiable();
101 LINETHROUGH = new SinkEventAttributeSet( new String[] {DECORATION, "line-through"} ).unmodifiable();
102 BOXED = new SinkEventAttributeSet( new String[] {DECORATION, "boxed"} ).unmodifiable();
103
104 BOLD = new SinkEventAttributeSet( new String[] {STYLE, "bold"} ).unmodifiable();
105 ITALIC = new SinkEventAttributeSet( new String[] {STYLE, "italic"} ).unmodifiable();
106 MONOSPACED = new SinkEventAttributeSet( new String[] {STYLE, "monospaced"} ).unmodifiable();
107
108 LEFT = new SinkEventAttributeSet( new String[] {ALIGN, "left"} ).unmodifiable();
109 RIGHT = new SinkEventAttributeSet( new String[] {ALIGN, "right"} ).unmodifiable();
110 CENTER = new SinkEventAttributeSet( new String[] {ALIGN, "center"} ).unmodifiable();
111 JUSTIFY = new SinkEventAttributeSet( new String[] {ALIGN, "justify"} ).unmodifiable();
112 }
113
114 private Map<String, Object> attribs;
115
116 private AttributeSet resolveParent;
117
118
119
120
121 public SinkEventAttributeSet()
122 {
123 this( 5 );
124 }
125
126
127
128
129
130
131 public SinkEventAttributeSet( int size )
132 {
133 attribs = new LinkedHashMap<String, Object>( size );
134 }
135
136
137
138
139
140
141
142
143 public SinkEventAttributeSet( String... attributes )
144 {
145 int n = attributes.length;
146
147 if ( ( n % 2 ) != 0 )
148 {
149 throw new IllegalArgumentException( "Missing attribute!" );
150 }
151
152 attribs = new LinkedHashMap<String, Object>( n / 2 );
153
154 for ( int i = 0; i < n; i += 2 )
155 {
156 attribs.put( attributes[i], attributes[i + 1] );
157 }
158 }
159
160
161
162
163
164
165
166 public SinkEventAttributeSet( AttributeSet attributes )
167 {
168 attribs = new LinkedHashMap<String, Object>( attributes.getAttributeCount() );
169
170 Enumeration<?> names = attributes.getAttributeNames();
171
172 while ( names.hasMoreElements() )
173 {
174 Object name = names.nextElement();
175
176 attribs.put( name.toString(), attributes.getAttribute( name ) );
177 }
178 }
179
180
181
182
183
184
185
186
187
188
189 public SinkEventAttributeSet unmodifiable()
190 {
191 this.attribs = Collections.unmodifiableMap( attribs );
192
193 return this;
194 }
195
196
197
198
199
200
201 public boolean isEmpty()
202 {
203 return attribs.isEmpty();
204 }
205
206
207 public int getAttributeCount()
208 {
209 return attribs.size();
210 }
211
212
213 public boolean isDefined( Object attrName )
214 {
215 return attribs.containsKey( attrName );
216 }
217
218
219 public boolean isEqual( AttributeSet attr )
220 {
221 return ( ( getAttributeCount() == attr.getAttributeCount() )
222 && containsAttributes( attr ) );
223 }
224
225
226 public AttributeSet copyAttributes()
227 {
228 return ( (AttributeSet) clone() );
229 }
230
231
232 public Enumeration<String> getAttributeNames()
233 {
234 return Collections.enumeration( attribs.keySet() );
235 }
236
237
238 public Object getAttribute( Object key )
239 {
240 Object value = attribs.get( key );
241
242 if ( value == null )
243 {
244 AttributeSet parent = getResolveParent();
245
246 if ( parent != null )
247 {
248 value = parent.getAttribute( key );
249 }
250 }
251
252 return value;
253 }
254
255
256 public boolean containsAttribute( Object name, Object value )
257 {
258 return value.equals( getAttribute( name ) );
259 }
260
261
262 public boolean containsAttributes( AttributeSet attributes )
263 {
264 boolean result = true;
265
266 Enumeration<?> names = attributes.getAttributeNames();
267
268 while ( result && names.hasMoreElements() )
269 {
270 Object name = names.nextElement();
271 result = attributes.getAttribute( name ).equals( getAttribute( name ) );
272 }
273
274 return result;
275 }
276
277
278
279
280
281
282 public void addAttribute( Object name, Object value )
283 {
284 attribs.put( name.toString(), value );
285 }
286
287
288 public void addAttributes( AttributeSet attributes )
289 {
290 if ( attributes == null || attributes.getAttributeCount() == 0 )
291 {
292 return;
293 }
294
295 Enumeration<?> names = attributes.getAttributeNames();
296
297 while ( names.hasMoreElements() )
298 {
299 Object name = names.nextElement();
300
301 addAttribute( name, attributes.getAttribute( name ) );
302 }
303 }
304
305
306 public void removeAttribute( Object name )
307 {
308 attribs.remove( name );
309 }
310
311
312 public void removeAttributes( Enumeration<?> names )
313 {
314 while ( names.hasMoreElements() )
315 {
316 removeAttribute( names.nextElement() );
317 }
318 }
319
320
321 public void removeAttributes( AttributeSet attributes )
322 {
323 if ( attributes == null )
324 {
325 return;
326 }
327 else if ( attributes == this )
328 {
329 attribs.clear();
330 }
331 else
332 {
333 Enumeration<?> names = attributes.getAttributeNames();
334
335 while ( names.hasMoreElements() )
336 {
337 Object name = names.nextElement();
338 Object value = attributes.getAttribute( name );
339
340 if ( value.equals( getAttribute( name ) ) )
341 {
342 removeAttribute( name );
343 }
344 }
345 }
346 }
347
348
349 public AttributeSet getResolveParent()
350 {
351 return this.resolveParent;
352 }
353
354
355 public void setResolveParent( AttributeSet parent )
356 {
357 this.resolveParent = parent;
358 }
359
360
361 @Override
362 public Object clone()
363 {
364 SinkEventAttributeSet attr = new SinkEventAttributeSet( attribs.size() );
365 attr.attribs = new LinkedHashMap<String, Object>( attribs );
366
367 if ( resolveParent != null )
368 {
369 attr.resolveParent = resolveParent.copyAttributes();
370 }
371
372 return attr;
373 }
374
375
376 @Override
377 public int hashCode()
378 {
379 final int parentHash = ( resolveParent == null ? 0 : resolveParent.hashCode() );
380
381 return attribs.hashCode() + parentHash;
382 }
383
384
385 @Override
386 public boolean equals( Object obj )
387 {
388 if ( this == obj )
389 {
390 return true;
391 }
392
393 if ( obj instanceof SinkEventAttributeSet )
394 {
395 return isEqual( (SinkEventAttributeSet) obj );
396 }
397
398 return false;
399 }
400
401
402 @Override
403 public String toString()
404 {
405 StringBuilder s = new StringBuilder();
406 Enumeration<String> names = getAttributeNames();
407
408 while ( names.hasMoreElements() )
409 {
410 String key = names.nextElement();
411 String value = getAttribute( key ).toString();
412
413 s.append( ' ' ).append( key ).append( '=' ).append( value );
414 }
415
416 return s.toString();
417 }
418
419 }