/*
* Copyright (c) 2005 Thomas Weise
*
* E-Mail : tweise@gmx.de
* Creation Date : 2005-08-11 07:08:05
* Original Filename: org.sfc.text.Text.java
* Version : 2.0.2
* Last modification: 2006-07-28
* by: Thomas Weise
*
* License : GNU LESSER GENERAL PUBLIC LICENSE
* Version 2.1, February 1999
* You should have received a copy of this license along
* with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307, USA or download the license under
* http://www.gnu.org/copyleft/lesser.html.
*
* Warranty : This software is provided "as is" without any
* warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose.
* See the Gnu Lesser General Public License for more
* details.
*/
package org.sfc.text;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Array;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import org.sfc.config.Language;
import org.sfc.config.LanguageEvent;
import org.sfc.events.IEventListener;
import org.sfc.events.SfcEvent;
import org.sfc.utils.Typesafe;
import org.sfc.xml.XML;
/**
* The escaper is able to apply some basic escapting mechanisms.
*
* @author Thomas Weise
*/
public final class Text
{
/**
* The line break characters.
*/
public static final char[] LINE_BREAK_CHARS = {'\r', '\n'};
/**
* The line break string.
*/
public static final String LINE_BREAK
= String.valueOf(LINE_BREAK_CHARS);
/**
* Java's array open char, will normally be '['.
*/
public static final char JAVA_ARRAY_OPEN ;
/**
* Java's array closing char, will normally be ']'.
*/
public static final char JAVA_ARRAY_CLOSE ;
/**
* The csv separator characters.
*/
public static final char[] CSV_SEPARATOR_CHARS = {'\t'};
/**
* The csv separating string.
*/
public static final String CSV_SEPARATOR
= String.valueOf(CSV_SEPARATOR_CHARS);
/**
* The decimal separator.
*/
static char s_decimal_separator =
get_locale_decimal_separator(null) ;
static
{
String l_s;
Language.add_listener(new IEventListener()
{
public final void receive (final SfcEvent p_event)
{
if(p_event instanceof LanguageEvent)
{
s_decimal_separator = get_locale_decimal_separator(
((LanguageEvent)p_event).get_new().get_locale());
}
}
}
);
l_s = new boolean[0].toString();
JAVA_ARRAY_OPEN = l_s.charAt(0);
JAVA_ARRAY_CLOSE = l_s.charAt(1);
}
/**
* The hidden constructor.
*/
private Text ()
{
Typesafe.do_not_call();
}
/**
* Obtain the decimal separator depending of a specified locale.
* @param p_locale The locale to find the decimal separator for.
* @return The decimal separator char of this locale.
*/
public static final char get_locale_decimal_separator(final Locale p_locale)
{
String l_s;
int l_i;
char l_ch;
NumberFormat l_nf;
l_nf = ((p_locale != null) ? NumberFormat.getNumberInstance(p_locale)
: NumberFormat.getNumberInstance());
l_s = l_nf.format(0.5);
for(l_i = 0; l_i < l_s.length(); l_i++)
{
l_ch = l_s.charAt(l_i);
if( ((l_ch > '9') || (l_ch < '0')) &&
((l_ch > 'z') || (l_ch < 'a')) &&
((l_ch > 'Z') || (l_ch < 'A')) )
{
return l_ch;
}
}
return '.';
}
/**
* Returns the current decimal separator.
* @return The current decimal separator.
*/
public static final char get_decimal_separator ()
{
return s_decimal_separator;
}
/**
* Checks wether a string contains a line break or not.
* @param p_string The string potentially containing a line break.
* @return true
if the string containes something like a
* linebreak, false
otherwise.
*/
public static final boolean contains_linebreak (final String p_string)
{
int l_i;
for(l_i = (LINE_BREAK_CHARS.length-1); l_i >= 0; l_i--)
{
if(p_string.indexOf(LINE_BREAK_CHARS[l_i]) >= 0) return true;
}
return false;
}
/**
* This method trims a string and returns null
if it contains
* no characters (or was even null
).
* @param p_string The string to preprocess.
* @return The trimmed string, or null
if it is empty.
*/
public static final String preprocess (String p_string)
{
if(p_string != null)
{
if((p_string = p_string.trim()).length() > 0) return p_string;
}
return null;
}
/**
* Performs xml space preprocessing. Every "\n\r" will be converted to a
* '\n'.
* @param p_text The array to be preprocessed.
* @param p_count The count of valid characters in the array.
* @return The new valid character count.
*/
public static final int xml_spaces (final char[] p_text,
int p_count)
{
char l_n, l_o, l_ch;
int l_i;
l_n = XML.LINE_BREAK;
l_o = ((Text.LINE_BREAK_CHARS[0] == l_n) ? Text.LINE_BREAK_CHARS[1] :
Text.LINE_BREAK_CHARS[0]);
for(l_i = (p_count-1); l_i >= 0; l_i--)
{
l_ch = p_text[l_i];
if(l_ch == l_o)
{
if((l_i <= 0) || (p_text[l_i-1] != l_n))
{
p_text[l_i] = l_n;
}
else
{
p_count--;
System.arraycopy(p_text, l_i+1, p_text, l_i, p_count - l_i);
}
}
}
return p_count;
}
/**
* Create a string representation of a time expression.
* @param p_gc The calendar.
* @param p_relative true
if the time expression is relative.
* @return The time string.
*/
public static final String time_to_string (final Calendar p_gc,
final boolean p_relative)
{
StringBuilder l_sb;
int l_x, l_y;
l_sb = new StringBuilder();
if(p_relative)
{
l_y = (p_gc.get(Calendar.DAY_OF_YEAR)-1);
if(l_y < 100) l_sb.append('0');
if(l_y < 10) l_sb.append('0');
l_sb.append(l_y);
l_sb.append('-');
}
else
{
l_y = 1;
l_sb.append(p_gc.get(Calendar.YEAR));
l_sb.append('-');
l_x = (p_gc.get(Calendar.MONTH)+1);
if(l_x < 10) l_sb.append('0');
l_sb.append(l_x);
l_sb.append('-');
l_x = p_gc.get(Calendar.DAY_OF_MONTH);
if(l_x < 10) l_sb.append('0');
l_sb.append(l_x);
l_sb.append('-');
}
l_x = p_gc.get(Calendar.HOUR_OF_DAY);
if(l_y <= 0) l_x--;
if(l_x < 10) l_sb.append('0');
l_sb.append(l_x);
l_sb.append(':');
l_x = p_gc.get(Calendar.MINUTE);
if(l_x < 10) l_sb.append('0');
l_sb.append(l_x);
l_sb.append(':');
l_x = p_gc.get(Calendar.SECOND);
if(l_x < 10) l_sb.append('0');
l_sb.append(l_x);
return l_sb.toString();
}
/**
* Create a string representation of a time expression.
* @param p_gc The time constant. This is a value of the type
* long
, for example obtained by
* System.currentMillies
.
* @param p_relative true
if the time expression is relative.
* @return The time string.
* @see System#currentTimeMillis()
*/
public static final String time_to_string (final long p_gc,
final boolean p_relative)
{
GregorianCalendar l_gc;
l_gc = new GregorianCalendar();
l_gc.setTimeInMillis(p_gc);
return time_to_string(l_gc, p_relative);
}
/**
* Converts an error to a string.
* @param p_t The error to convert.
* @return A String representing all the error's information.
*/
public static final String error_to_string (Throwable p_t)
{
StringBuilder l_sb;
String l_s;
StackTraceElement[] l_st;
StackTraceElement l_ste;
int l_i;
l_sb = new StringBuilder();
while(p_t != null)
{
l_sb.append(p_t.getClass().getName());
l_sb.append(": ");
l_s = preprocess(p_t.getLocalizedMessage() );
if(l_s == null) l_s = preprocess(p_t.getMessage());
if(l_s != null) l_sb.append(l_s);
l_st = p_t.getStackTrace();
if(l_st != null)
{
for(l_i = 0; l_i < l_st.length; l_i++)
{
l_ste = l_st[l_i];
if(l_ste != null)
{
l_sb.append(LINE_BREAK);
l_sb.append(" at ");
if(l_ste.isNativeMethod()) l_sb.append("");
l_s = preprocess(l_ste.getClassName());
if(l_s != null) l_sb.append(l_s);
l_s = preprocess(l_ste.getMethodName());
if(l_s != null)
{
l_sb.append('.');
l_sb.append(l_s);
}
l_s = preprocess(l_ste.getFileName());
if(l_s != null)
{
l_sb.append('(');
l_sb.append(l_s);
l_sb.append(':');
l_sb.append(l_ste.getLineNumber());
l_sb.append(')');
}
}
}
}
p_t = p_t.getCause();
if(p_t != null)
{
l_sb.append(LINE_BREAK);
l_sb.append("caused by:");
l_sb.append(LINE_BREAK);
}
}
return l_sb.toString();
}
/**
* Convert a double quickly to a string in a locale-depending way.
* @param p_double The double to be converted.
* @return The string representation of this double.
*/
public static final String double_to_string (final double p_double)
{
StringBuilder l_sb;
int l_i, l_n;
char l_ch;
boolean l_b;
l_sb = new StringBuilder();
l_sb.append(p_double);
l_b = true;
l_n = (l_sb.length()-1);
for(l_i = l_n; l_i >= 0; l_i--)
{
l_ch = l_sb.charAt(l_i);
if(l_ch == '.')
{
if((l_i == l_n) && l_b)
{
l_sb.setLength(l_i);
}
else
{
if(l_b) l_sb.setLength(l_n+1);
l_sb.setCharAt(l_i, s_decimal_separator);
}
break;
}
if(l_ch == '0')
{
if(l_n == l_i) l_n = l_i-1;
}
else
{
if((l_ch < '1') || (l_ch > '9')) l_b = false;
}
}
return l_sb.toString();
}
/**
* Convert a string to a sequence of bytes.
* @param p_string The string data.
* @return A sequence of bytes representing the string data.
*/
public static final byte[] string_to_bytes (final String p_string)
{
ByteArrayOutputStream l_baos;
OutputStreamWriter l_osw;
byte[] l_b;
l_b = null;
l_baos = new ByteArrayOutputStream();
try
{
try
{
l_osw = new OutputStreamWriter(l_baos);
try
{
l_osw.write(p_string);
}
finally
{
l_osw.close();
}
}
finally
{
l_baos.close();
}
l_b = l_baos.toByteArray();
}
catch(Throwable l_t)
{
//
}
return l_b;
}
/**
* Converts any given object to a string while considerin if the object is
* an array.
* @param p_object The object to convert into a string.
* @return The string representation of the object.
*/
public static final String to_string (final Object p_object)
{
Class l_c;
StringBuilder l_sb;
int l_i, l_j;
if(p_object == null) return String.valueOf(null);
l_c = p_object.getClass();
if(l_c.isArray())
{
l_sb = new StringBuilder();
l_sb.append('[');
l_j = Array.getLength(p_object);
for(l_i = 0; l_i < l_j; l_i++)
{
l_sb.append(to_string(Array.get(p_object, l_i)));
l_sb.append(", ");
}
l_i = l_sb.length();
l_sb.setCharAt(l_i-2, ']');
l_sb.setLength(l_i-1);
return l_sb.toString();
}
return String.valueOf(p_object);
}
}