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 final 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          _uniqueIdsCache = null;
56      }
57      
58      public SectionUniqueIdCounter(String prefix)
59      {
60          _activeSection = 0;
61          _radix = Character.MAX_RADIX;
62          _counterStack = new ArrayList<Section>();
63          _counterStack.add(new Section(null,1,_radix));
64          _prefix = prefix;
65          _builder = new StringBuilder(30);
66          _bufferConversion = new char[15];
67          _uniqueIdsCache = null;
68      }
69      
70      public SectionUniqueIdCounter(String prefix, String[] cache)
71      {
72          _activeSection = 0;
73          _radix = Character.MAX_RADIX;
74          _counterStack = new ArrayList<Section>();
75          _counterStack.add(new Section(null,1,_radix));
76          _prefix = prefix;
77          _builder = new StringBuilder(30);
78          _bufferConversion = new char[15];
79          _uniqueIdsCache = cache;
80      }
81      
82      public SectionUniqueIdCounter(String prefix, int radix)
83      {
84          _activeSection = 0;
85          _radix = radix;
86          _counterStack = new ArrayList<Section>();
87          _counterStack.add(new Section(null,1,_radix));
88          _prefix = prefix;
89          _builder = new StringBuilder(30);
90          _bufferConversion = new char[15];
91          _uniqueIdsCache = null;
92      }
93  
94      /**
95       * Creates an array of the generated unique ids for an specified prefix,
96       * than can be used later to prevent calculate the same String over and over.
97       * 
98       * @param prefix
99       * @param count
100      * @return 
101      */
102     public static String[] generateUniqueIdCache(String prefix, int count)
103     {
104         String[] cache = new String[count];
105         SectionUniqueIdCounter counter = new SectionUniqueIdCounter(prefix);
106         for (int i = 0; i < count ; i++)
107         {
108             cache[i] = counter.generateUniqueId();
109         }
110         return cache;
111     }
112 
113     public String startUniqueIdSection()
114     {
115         //1. Calculate prefix
116         _builder.delete(0, _builder.length());
117         boolean added = false;
118         for (int i = 0; i < _counterStack.size(); i++)
119         {
120             if (added)
121             {
122                 _builder.append('_');
123             }
124             //_builder.append(Long.toString(_counterStack.get(i).getCounter(), _radix));
125             appendToBuilder(_counterStack.get(i).getCounter(), _radix, _builder, _bufferConversion);
126             added = true;
127         }
128         
129         _counterStack.add(new Section(_builder.toString(),1,_radix));
130         _activeSection++;
131         return _builder.toString();
132     }
133     
134     public String startUniqueIdSection(String base)
135     {
136         //1. Calculate prefix
137         _builder.delete(0, _builder.length());
138         boolean added = false;
139         for (int i = 0; i < _counterStack.size(); i++)
140         {
141             if (added)
142             {
143                 _builder.append('_');
144             }
145             //_builder.append(Long.toString(_counterStack.get(i).getCounter(), _radix));
146             appendToBuilder(_counterStack.get(i).getCounter(), _radix, _builder, _bufferConversion);
147             added = true;
148         }
149         if (base != null && base.length() > 0)
150         {
151             _builder.append('_');
152             _builder.append(base);
153         }
154         _counterStack.add(new Section(_builder.toString(),1,_radix));
155         _activeSection++;
156         return _builder.toString();
157     }
158 
159     public String generateUniqueId()
160     {
161         if (_activeSection == 0 && _uniqueIdsCache != null)
162         {
163             long i = _counterStack.get(_activeSection).getCounter();
164             if (((int)i) < (long)_uniqueIdsCache.length)
165             {
166                 _counterStack.get(_activeSection).incrementUniqueId();
167                 return _uniqueIdsCache[((int)i)-1];
168             }
169             else
170             {
171                 return _counterStack.get(_activeSection).generateUniqueId(_prefix);
172             }
173         }
174         else
175         {
176             return _counterStack.get(_activeSection).generateUniqueId(_prefix);
177         }
178     }
179     
180     public void generateUniqueId(StringBuilder builderToAdd)
181     {
182         _counterStack.get(_activeSection).generateUniqueId(_prefix, builderToAdd);
183     }
184     
185     public void incrementUniqueId()
186     {
187         _counterStack.get(_activeSection).incrementUniqueId();
188     }
189     
190     public void endUniqueIdSection()
191     {
192         if (_activeSection <= 0)
193         {
194             _counterStack.get(_activeSection).generateUniqueId(_prefix);
195             return;
196         }
197         else
198         {
199             _counterStack.remove(_activeSection);
200             _activeSection--;
201             _counterStack.get(_activeSection).generateUniqueId(_prefix);
202         }
203     }
204     
205     private static class Section
206     {
207         
208         private String prefix;
209         private long counter;
210         private final StringBuilder _builder;
211         private char[] _bufferConversion;
212         private final int _radix;
213         
214         public Section(String prefix, long counter, int radix)
215         {
216             super();
217             this.prefix = prefix;
218             this.counter = counter;
219             _builder = new StringBuilder(30);
220             _bufferConversion = new char[15];
221             _radix = radix;
222         }
223 
224         public long getCounter()
225         {
226             return counter;
227         }
228         
229         public void incrementUniqueId()
230         {
231             this.counter++;
232         }
233 
234         public void generateUniqueId(String base, StringBuilder builder)
235         {
236             long i = this.counter;
237             this.counter++;
238             //_builder.delete(0, _builder.length());
239             if (base != null)
240             {
241                 builder.append(base);
242             }
243             if (this.prefix != null)
244             {
245                 builder.append(this.prefix);
246                 builder.append('_');
247             }
248             // By performance reasons, Long.toString is a very expensive
249             // operation in this location, because it triggers a new String()
250             //_builder.append(Long.toString(i, _radix));
251             appendToBuilder(i, _radix, builder, _bufferConversion);
252             //return _builder.toString();
253         }
254         
255         public String generateUniqueId(String base)
256         {
257             long i = this.counter;
258             this.counter++;
259             _builder.delete(0, _builder.length());
260             if (base != null)
261             {
262                 _builder.append(base);
263             }
264             if (this.prefix != null)
265             {
266                 _builder.append(this.prefix);
267                 _builder.append('_');
268             }
269             // By performance reasons, Long.toString is a very expensive
270             // operation in this location, because it triggers a new String()
271             //_builder.append(Long.toString(i, _radix));
272             appendToBuilder(i, _radix, _builder, _bufferConversion);
273             return _builder.toString();
274         }
275     }
276     
277     //From Harmony Long.toString(l,radix)
278     private static void appendToBuilder(long l, int radix, StringBuilder builder, char[] bufferConversion)
279     {
280         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
281         {
282             radix = 10;
283         }
284         if (l == 0)
285         {
286             builder.append('0');
287             return;
288         }
289 
290         int count = 2;
291         long j = l;
292         boolean negative = l < 0;
293         if (!negative)
294         {
295             count = 1;
296             j = -l;
297         }
298         while ((l /= radix) != 0)
299         {
300             count++;
301         }
302 
303         if (bufferConversion.length < count)
304         {
305             bufferConversion = new char[count];
306         }
307         int finalCount = count;
308 
309         char[] buffer = bufferConversion;
310         do 
311         {
312             int ch = 0 - (int) (j % radix);
313             if (ch > 9)
314             {
315                 ch = ch - 10 + 'a';
316             }
317             else
318             {
319                 ch += '0';
320             }
321             buffer[--count] = (char) ch;
322             j /= radix;
323         }
324         while (j != 0);
325         if (negative)
326         {
327             buffer[0] = '-';
328         }
329         for (int i = 0; i < finalCount; i++)
330         {
331             builder.append(buffer[i]);
332         }
333         //return new String(0, buffer.length, buffer);
334     }
335 }