blob: b75951bc46cc67657dc0ddd8e5e22dfb21c7ace0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.view.facelets.impl;
import java.util.ArrayList;
import java.util.List;
/**
* Hierarchical counter to generate unique ids.
*
* @author Leonardo Uribe
*
*/
public class SectionUniqueIdCounter
{
private List<Section> _counterStack;
private int _activeSection;
private final String _prefix;
private final StringBuilder _builder;
private char[] _bufferConversion;
private final int _radix;
private final String[] _uniqueIdsCache;
public SectionUniqueIdCounter()
{
_activeSection = 0;
_radix = Character.MAX_RADIX;
_counterStack = new ArrayList<>();
_counterStack.add(new Section(null, 1, _radix));
_prefix = null;
_builder = new StringBuilder(30);
_bufferConversion = new char[15];
_uniqueIdsCache = null;
}
public SectionUniqueIdCounter(String prefix)
{
_activeSection = 0;
_radix = Character.MAX_RADIX;
_counterStack = new ArrayList<>();
_counterStack.add(new Section(null, 1, _radix));
_prefix = prefix;
_builder = new StringBuilder(30);
_bufferConversion = new char[15];
_uniqueIdsCache = null;
}
public SectionUniqueIdCounter(String prefix, String[] cache)
{
_activeSection = 0;
_radix = Character.MAX_RADIX;
_counterStack = new ArrayList<>();
_counterStack.add(new Section(null, 1 ,_radix));
_prefix = prefix;
_builder = new StringBuilder(30);
_bufferConversion = new char[15];
_uniqueIdsCache = cache;
}
public SectionUniqueIdCounter(String prefix, int radix)
{
_activeSection = 0;
_radix = radix;
_counterStack = new ArrayList<>();
_counterStack.add(new Section(null, 1, _radix));
_prefix = prefix;
_builder = new StringBuilder(30);
_bufferConversion = new char[15];
_uniqueIdsCache = null;
}
/**
* Creates an array of the generated unique ids for an specified prefix,
* than can be used later to prevent calculate the same String over and over.
*
* @param prefix
* @param count
* @return
*/
public static String[] generateUniqueIdCache(String prefix, int count)
{
String[] cache = new String[count];
SectionUniqueIdCounter counter = new SectionUniqueIdCounter(prefix);
for (int i = 0; i < count ; i++)
{
cache[i] = counter.generateUniqueId();
}
return cache;
}
public String startUniqueIdSection()
{
//1. Calculate prefix
_builder.delete(0, _builder.length());
if (!_counterStack.isEmpty())
{
String lastPrefix = _counterStack.get(_counterStack.size()-1).getPrefix();
if (lastPrefix != null)
{
_builder.append(lastPrefix);
_builder.append('_');
}
appendToBuilder(_counterStack.get(_counterStack.size()-1).getCounter(),
_radix, _builder, _bufferConversion);
}
_counterStack.add(new Section(_builder.toString(),1,_radix));
_activeSection++;
return _builder.toString();
}
public String startUniqueIdSection(String base)
{
//1. Calculate prefix
_builder.delete(0, _builder.length());
if (!_counterStack.isEmpty())
{
String lastPrefix = _counterStack.get(_counterStack.size()-1).getPrefix();
if (lastPrefix != null)
{
_builder.append(lastPrefix);
_builder.append('_');
}
appendToBuilder(_counterStack.get(_counterStack.size()-1).getCounter()-1,
_radix, _builder, _bufferConversion);
}
if (base != null && base.length() > 0)
{
_builder.append('_');
_builder.append(base);
}
_counterStack.add(new Section(_builder.toString(), 1, _radix));
_activeSection++;
return _builder.toString();
}
public String generateUniqueId()
{
if (_activeSection == 0 && _uniqueIdsCache != null)
{
long i = _counterStack.get(_activeSection).getCounter();
if (((int)i) < (long)_uniqueIdsCache.length)
{
_counterStack.get(_activeSection).incrementUniqueId();
return _uniqueIdsCache[((int)i)-1];
}
else
{
return _counterStack.get(_activeSection).generateUniqueId(_prefix);
}
}
else
{
return _counterStack.get(_activeSection).generateUniqueId(_prefix);
}
}
public void generateUniqueId(StringBuilder builderToAdd)
{
_counterStack.get(_activeSection).generateUniqueId(_prefix, builderToAdd);
}
public void incrementUniqueId()
{
_counterStack.get(_activeSection).incrementUniqueId();
}
public void endUniqueIdSection()
{
if (_activeSection <= 0)
{
_counterStack.get(_activeSection).generateUniqueId(_prefix);
return;
}
else
{
_counterStack.remove(_activeSection);
_activeSection--;
_counterStack.get(_activeSection).generateUniqueId(_prefix);
}
}
public void endUniqueIdSection(String base)
{
if (_activeSection <= 0)
{
return;
}
else
{
_counterStack.remove(_activeSection);
_activeSection--;
}
}
private static class Section
{
private String prefix;
private long counter;
private final StringBuilder builder;
private char[] bufferConversion;
private final int radix;
public Section(String prefix, long counter, int radix)
{
super();
this.prefix = prefix;
this.counter = counter;
this.builder = new StringBuilder(30);
this.bufferConversion = new char[15];
this.radix = radix;
}
public long getCounter()
{
return counter;
}
public void incrementUniqueId()
{
this.counter++;
}
public void generateUniqueId(String base, StringBuilder builder)
{
long i = this.counter;
this.counter++;
if (base != null)
{
builder.append(base);
}
if (this.prefix != null)
{
builder.append(this.prefix);
builder.append('_');
}
// By performance reasons, Long.toString is a very expensive
// operation in this location, because it triggers a new String()
appendToBuilder(i, radix, builder, bufferConversion);
}
public String generateUniqueId(String base)
{
long i = this.counter;
this.counter++;
builder.delete(0, builder.length());
if (base != null)
{
builder.append(base);
}
if (this.prefix != null)
{
builder.append(this.prefix);
builder.append('_');
}
// By performance reasons, Long.toString is a very expensive
// operation in this location, because it triggers a new String()
//_builder.append(Long.toString(i, _radix));
appendToBuilder(i, radix, builder, bufferConversion);
return builder.toString();
}
public String getPrefix()
{
return prefix;
}
}
//From Harmony Long.toString(l,radix)
private static void appendToBuilder(long l, int radix, StringBuilder builder, char[] bufferConversion)
{
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
{
radix = 10;
}
if (l == 0)
{
builder.append('0');
return;
}
int count = 2;
long j = l;
boolean negative = l < 0;
if (!negative)
{
count = 1;
j = -l;
}
while ((l /= radix) != 0)
{
count++;
}
if (bufferConversion.length < count)
{
bufferConversion = new char[count];
}
int finalCount = count;
char[] buffer = bufferConversion;
do
{
int ch = 0 - (int) (j % radix);
if (ch > 9)
{
ch = ch - 10 + 'a';
}
else
{
ch += '0';
}
buffer[--count] = (char) ch;
j /= radix;
}
while (j != 0);
if (negative)
{
buffer[0] = '-';
}
for (int i = 0; i < finalCount; i++)
{
builder.append(buffer[i]);
}
}
}