View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.view.facelets.impl;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  /**
25   * Hierarchical counter to generate unique ids.
26   * 
27   * @author Leonardo Uribe
28   *
29   */
30  public class SectionUniqueIdCounter
31  {
32      private List<Section> _counterStack;
33      
34      private int _activeSection;
35      
36      private final String _prefix;
37      
38      private final StringBuilder _builder;
39      
40      private char[] _bufferConversion;
41      
42      private final int _radix;
43      
44      private String[] _uniqueIdsCache;
45      
46      public SectionUniqueIdCounter()
47      {
48          _activeSection = 0;
49          _radix = Character.MAX_RADIX;
50          _counterStack = new ArrayList<Section>();
51          _counterStack.add(new Section(null,1,_radix));
52          _prefix = null;
53          _builder = new StringBuilder(30);
54          _bufferConversion = new char[15];
55      }
56      
57      public SectionUniqueIdCounter(String prefix)
58      {
59          _activeSection = 0;
60          _radix = Character.MAX_RADIX;
61          _counterStack = new ArrayList<Section>();
62          _counterStack.add(new Section(null,1,_radix));
63          _prefix = prefix;
64          _builder = new StringBuilder(30);
65          _bufferConversion = new char[15];
66      }
67      
68      public SectionUniqueIdCounter(String prefix, String[] cache)
69      {
70          _activeSection = 0;
71          _radix = Character.MAX_RADIX;
72          _counterStack = new ArrayList<Section>();
73          _counterStack.add(new Section(null,1,_radix));
74          _prefix = prefix;
75          _builder = new StringBuilder(30);
76          _bufferConversion = new char[15];
77          _uniqueIdsCache = cache;
78      }
79      
80      public SectionUniqueIdCounter(String prefix, int radix)
81      {
82          _activeSection = 0;
83          _radix = radix;
84          _counterStack = new ArrayList<Section>();
85          _counterStack.add(new Section(null,1,_radix));
86          _prefix = prefix;
87          _builder = new StringBuilder(30);
88          _bufferConversion = new char[15];
89      }
90  
91      /**
92       * Creates an array of the generated unique ids for an specified prefix,
93       * than can be used later to prevent calculate the same String over and over.
94       * 
95       * @param prefix
96       * @param count
97       * @return 
98       */
99      public static String[] generateUniqueIdCache(String prefix, int count)
100     {
101         String[] cache = new String[count];
102         SectionUniqueIdCounter counter = new SectionUniqueIdCounter(prefix);
103         for (int i = 0; i < count ; i++)
104         {
105             cache[i] = counter.generateUniqueId();
106         }
107         return cache;
108     }
109 
110     public String startUniqueIdSection()
111     {
112         //1. Calculate prefix
113         _builder.delete(0, _builder.length());
114         boolean added = false;
115         for (int i = 0; i < _counterStack.size(); i++)
116         {
117             if (added)
118             {
119                 _builder.append('_');
120             }
121             //_builder.append(Long.toString(_counterStack.get(i).getCounter(), _radix));
122             appendToBuilder(_counterStack.get(i).getCounter(), _radix, _builder, _bufferConversion);
123             added = true;
124         }
125         
126         _counterStack.add(new Section(_builder.toString(),1,_radix));
127         _activeSection++;
128         return _builder.toString();
129     }
130     
131     public String startUniqueIdSection(String base)
132     {
133         //1. Calculate prefix
134         _builder.delete(0, _builder.length());
135         boolean added = false;
136         for (int i = 0; i < _counterStack.size(); i++)
137         {
138             if (added)
139             {
140                 _builder.append('_');
141             }
142             //_builder.append(Long.toString(_counterStack.get(i).getCounter(), _radix));
143             appendToBuilder(_counterStack.get(i).getCounter(), _radix, _builder, _bufferConversion);
144             added = true;
145         }
146         if (base != null && base.length() > 0)
147         {
148             _builder.append('_');
149             _builder.append(base);
150         }
151         _counterStack.add(new Section(_builder.toString(),1,_radix));
152         _activeSection++;
153         return _builder.toString();
154     }
155 
156     public String generateUniqueId()
157     {
158         if (_activeSection == 0 && _uniqueIdsCache != null)
159         {
160             long i = _counterStack.get(_activeSection).getCounter();
161             if (((int)i) < (long)_uniqueIdsCache.length)
162             {
163                 _counterStack.get(_activeSection).incrementUniqueId();
164                 return _uniqueIdsCache[((int)i)-1];
165             }
166             else
167             {
168                 return _counterStack.get(_activeSection).generateUniqueId(_prefix);
169             }
170         }
171         else
172         {
173             return _counterStack.get(_activeSection).generateUniqueId(_prefix);
174         }
175     }
176     
177     public void generateUniqueId(StringBuilder builderToAdd)
178     {
179         _counterStack.get(_activeSection).generateUniqueId(_prefix, builderToAdd);
180     }
181     
182     public void incrementUniqueId()
183     {
184         _counterStack.get(_activeSection).incrementUniqueId();
185     }
186     
187     public void endUniqueIdSection()
188     {
189         if (_activeSection <= 0)
190         {
191             _counterStack.get(_activeSection).generateUniqueId(_prefix);
192             return;
193         }
194         else
195         {
196             _counterStack.remove(_activeSection);
197             _activeSection--;
198             _counterStack.get(_activeSection).generateUniqueId(_prefix);
199         }
200     }
201     
202     private static class Section
203     {
204         
205         private String prefix;
206         private long counter;
207         private final StringBuilder _builder;
208         private char[] _bufferConversion;
209         private final int _radix;
210         
211         public Section(String prefix, long counter, int radix)
212         {
213             super();
214             this.prefix = prefix;
215             this.counter = counter;
216             _builder = new StringBuilder(30);
217             _bufferConversion = new char[15];
218             _radix = radix;
219         }
220 
221         public long getCounter()
222         {
223             return counter;
224         }
225         
226         public void incrementUniqueId()
227         {
228             this.counter++;
229         }
230 
231         public void generateUniqueId(String base, StringBuilder builder)
232         {
233             long i = this.counter;
234             this.counter++;
235             //_builder.delete(0, _builder.length());
236             if (base != null)
237             {
238                 builder.append(base);
239             }
240             if (this.prefix != null)
241             {
242                 builder.append(this.prefix);
243                 builder.append('_');
244             }
245             // By performance reasons, Long.toString is a very expensive
246             // operation in this location, because it triggers a new String()
247             //_builder.append(Long.toString(i, _radix));
248             appendToBuilder(i, _radix, builder, _bufferConversion);
249             //return _builder.toString();
250         }
251         
252         public String generateUniqueId(String base)
253         {
254             long i = this.counter;
255             this.counter++;
256             _builder.delete(0, _builder.length());
257             if (base != null)
258             {
259                 _builder.append(base);
260             }
261             if (this.prefix != null)
262             {
263                 _builder.append(this.prefix);
264                 _builder.append('_');
265             }
266             // By performance reasons, Long.toString is a very expensive
267             // operation in this location, because it triggers a new String()
268             //_builder.append(Long.toString(i, _radix));
269             appendToBuilder(i, _radix, _builder, _bufferConversion);
270             return _builder.toString();
271         }
272     }
273     
274     //From Harmony Long.toString(l,radix)
275     private static void appendToBuilder(long l, int radix, StringBuilder builder, char[] bufferConversion)
276     {
277         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
278         {
279             radix = 10;
280         }
281         if (l == 0)
282         {
283             builder.append('0');
284             return;
285         }
286 
287         int count = 2;
288         long j = l;
289         boolean negative = l < 0;
290         if (!negative)
291         {
292             count = 1;
293             j = -l;
294         }
295         while ((l /= radix) != 0)
296         {
297             count++;
298         }
299 
300         if (bufferConversion.length < count)
301         {
302             bufferConversion = new char[count];
303         }
304         int finalCount = count;
305 
306         char[] buffer = bufferConversion;
307         do 
308         {
309             int ch = 0 - (int) (j % radix);
310             if (ch > 9)
311             {
312                 ch = ch - 10 + 'a';
313             }
314             else
315             {
316                 ch += '0';
317             }
318             buffer[--count] = (char) ch;
319             j /= radix;
320         }
321         while (j != 0);
322         if (negative)
323         {
324             buffer[0] = '-';
325         }
326         for (int i = 0; i < finalCount; i++)
327         {
328             builder.append(buffer[i]);
329         }
330         //return new String(0, buffer.length, buffer);
331     }
332 }