/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.scripting;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Formatter;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.annotations.JSFunction;
import com.servoy.base.scripting.api.IJSFoundSet;
import com.servoy.base.scripting.api.IJSRecord;
import com.servoy.base.scripting.api.IJSUtils;
import com.servoy.base.util.ITagResolver;
import com.servoy.j2db.BasicFormController;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.dataprocessing.FoundSet;
import com.servoy.j2db.dataprocessing.IFoundSetInternal;
import com.servoy.j2db.dataprocessing.IRecordInternal;
import com.servoy.j2db.dataprocessing.JSDatabaseManager;
import com.servoy.j2db.dataprocessing.TagResolver;
import com.servoy.j2db.documentation.ServoyDocumented;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.HtmlUtils;
import com.servoy.j2db.util.RoundHalfUpDecimalFormat;
import com.servoy.j2db.util.Settings;
import com.servoy.j2db.util.Text;
import com.servoy.j2db.util.Utils;
/**
* @author jblok
*/
@ServoyDocumented(category = ServoyDocumented.RUNTIME, publicName = "Utils", scriptingName = "utils")
public class JSUtils implements IJSUtils
{
private volatile IApplication application;
public JSUtils(IApplication application)
{
this.application = application;
}
/**
* @deprecated As of release 2.0, replaced by {@link #hasRecords(JSFoundSet)}.
*/
@Deprecated
public boolean js_hasChildRecords(Object foundset)
{
if (foundset instanceof IFoundSetInternal && foundset instanceof IJSFoundSet)
{
return hasRecords((IJSFoundSet)foundset);
}
return false;
}
/**
* Returns true if the (related)foundset exists and has records.
* Another use is, to pass a record and qualified relations string to test multiple relations/foundset at once
*
* @sample
* //test the orders_to_orderitems foundset
* if (%%elementName%%.hasRecords(orders_to_orderitems))
* {
* //do work on relatedFoundSet
* }
* //test the orders_to_orderitems.orderitems_to_products foundset to be reached from the current record
* //if (%%elementName%%.hasRecords(foundset.getSelectedRecord(),'orders_to_orderitems.orderitems_to_products'))
* //{
* // //do work on deeper relatedFoundSet
* //}
*
* @param foundset the foundset to be tested
* @return true if exists
*/
@JSFunction
public boolean hasRecords(IJSFoundSet foundset)//needed for calcs
{
if (foundset != null)
{
return foundset.getSize() > 0;
}
return false;
}
/**
* @clonedesc hasRecords(IJSFoundSet)
*
* @sampleas hasRecords(IJSFoundSet)
*
* @param record A JSRecord to test.
* @param relationString The relation name.
*
* @return true if the foundset/relation has records.
*/
@JSFunction
public boolean hasRecords(IJSRecord record, String relationString)
{
return JSDatabaseManager.hasRecords((IRecordInternal)record, relationString);
}
/**
* Returns a string containing the character for the unicode number.
*
* @sample
* //returns a big dot
* var dot = utils.getUnicodeCharacter(9679);
*
* @param unicodeCharacterNumber the number indicating the unicode character
*
* @return a string containing the unicode character
*/
public String js_getUnicodeCharacter(int unicodeCharacterNumber)//no cast from int to char possible in javascript
{
return Character.toString((char)unicodeCharacterNumber);
}
/**
* Returns the text with %%tags%% replaced, based on provided record or foundset or form.
*
* @sample
* //Next line places a string in variable x, whereby the tag(%%TAG%%) is filled with the value of the database column 'company_name' of the selected record.
* var x = utils.stringReplaceTags("The companyName of the selected record is %%company_name%% ", foundset)
* //var otherExample = utils.stringReplaceTags("The amount of the related order line %%amount%% ", order_to_orderdetails);
* //var recordExample = utils.stringReplaceTags("The amount of the related order line %%amount%% ", order_to_orderdetails.getRecord(i);
* //Next line places a string in variable y, whereby the tag(%%TAG%%) is filled with the value of the form variable 'x' of the form named 'main'.
* //var y = utils.stringReplaceTags("The value of form variable is %%x%% ", forms.main);
* //The next sample shows the use of a javascript object
* //var obj = new Object();//create a javascript object
* //obj['x'] = 'test';//assign an named value
* //var y = utils.stringReplaceTags("The value of object variable is %%x%% ", obj);//use the named value in a tag
* @param text the text tags to work with
* @param scriptable the javascript object or foundset,record,form to be used to fill in the tags
* @return the text with replaced tags
*/
public String js_stringReplaceTags(String text, Object scriptable)
{
if (text != null)
{
ITagResolver tagResolver = null;
Properties settings = null;
if (scriptable instanceof FoundSet)
{
IRecordInternal record = ((FoundSet)scriptable).getRecord(((FoundSet)scriptable).getSelectedIndex());
if (record != null)
{
settings = record.getParentFoundSet().getFoundSetManager().getApplication().getSettings();
tagResolver = TagResolver.createResolver(record);
}
}
else if (scriptable instanceof IRecordInternal)
{
IRecordInternal record = (IRecordInternal)scriptable;
settings = record.getParentFoundSet().getFoundSetManager().getApplication().getSettings();
tagResolver = TagResolver.createResolver(record);
}
else if (scriptable instanceof BasicFormController)
{
final BasicFormController fc = (BasicFormController)scriptable;
IFoundSetInternal fs = fc.getFoundSet();
final ITagResolver defaultTagResolver = (fs != null) ? TagResolver.createResolver(fs.getRecord(fs.getSelectedIndex())) : null;
settings = fc.getApplication().getSettings();
tagResolver = new ITagResolver()
{
public String getStringValue(String name)
{
Object value = fc.getFormScope().get(name);
if (value == null || value == Scriptable.NOT_FOUND)
{
value = defaultTagResolver != null ? defaultTagResolver.getStringValue(name) : null;
}
return value != null ? value.toString() : ""; //$NON-NLS-1$
}
};
}
else if (scriptable instanceof Scriptable)
{
Scriptable scriptObject = (Scriptable)scriptable;
settings = Settings.getInstance();
tagResolver = TagResolver.createResolver(scriptObject, application.getLocale());
}
if (tagResolver != null && settings != null)
{
return Text.processTags(TagResolver.formatObject(text, application.getLocale(), settings), tagResolver);
}
return ""; //$NON-NLS-1$
}
else
{
return ""; //$NON-NLS-1$
}
}
/**
* Returns true when Monday is the first day of the week for your current locale setting.
*
* @sample
* if(utils.isMondayFirstDayOfWeek())
* {
* //a date calculation
* }
* @return true if Monday is first day of the week in current locale
*/
public boolean js_isMondayFirstDayOfWeek()
{
return Calendar.getInstance().getFirstDayOfWeek() == Calendar.MONDAY;
}
/**
* Parse a string to a date object.
*
* @sample
* var parsedDate = utils.parseDate(datestring,'EEE, d MMM yyyy HH:mm:ss');
*
* @param date the date as text
* @param format the format to parse the to date
* @return the date as date object
*/
public Date js_parseDate(String date, String format)
{
if (format != null && date != null)
{
try
{
return new SimpleDateFormat(format, application.getLocale()).parse(date);
}
catch (ParseException ex)
{
Debug.error("Date parsing error: " + date + ", format: " + format, ex); //$NON-NLS-1$//$NON-NLS-2$
}
}
return null;
}
/**
* @deprecated replaced by parseDate(String, String) or dateFormat(Date, String)
*/
@Deprecated
public Object js_dateFormat(Object date, String format)
{
if (date instanceof String)
{
return js_parseDate((String)date, format);
}
if (date instanceof Date)
{
return dateFormat((Date)date, format);
}
return ""; //$NON-NLS-1$
}
/**
* Format a date object to a text representation.
*
* @sample
* var formattedDateString = utils.dateFormat(dateobject,'EEE, d MMM yyyy HH:mm:ss');
*
* @param date the date
* @param format the format to output
* @return the date as text
*/
@JSFunction
public String dateFormat(Date date, String format)
{
if (format != null && date != null)
{
return new SimpleDateFormat(format, application.getLocale()).format(date);
}
return ""; //$NON-NLS-1$
}
/**
* Returns a datestamp from the timestamp (sets hours,minutes,seconds and milliseconds to 0).
*
* @sample
* var date = utils.timestampToDate(application.getTimeStamp());
*
* @param date object to be stripped from its time elements
* @return the stripped date object
*/
public Date js_timestampToDate(Date date)
{
if (date != null)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
Utils.applyMinTime(calendar);
return calendar.getTime();
}
return null;
}
/**
* Returns the number of words, starting from the left.
*
* @sample
* //returns 'this is a'
* var retval = utils.stringLeftWords('this is a test',3);
*
* @param text to process
* @param numberof_words to return
* @return the string with number of words form the left
*/
public String js_stringLeftWords(String text, Number numberof_words)
{
if (text != null && numberof_words != null)
{
try
{
int words = numberof_words.intValue();
StringBuilder sb = new StringBuilder();
StringTokenizer st = new StringTokenizer(text, " "); //$NON-NLS-1$
int i = 0;
while (st.hasMoreTokens() && i < words)
{
String value = st.nextToken();
sb.append(value);
if (st.hasMoreTokens() && i < (words - 1))
{
sb.append(" "); //$NON-NLS-1$
}
i++;
}
return sb.toString();
}
catch (Exception ex)
{
return text.toString();
}
}
else
{
return ""; //$NON-NLS-1$
}
}
/**
* Returns a substring from the original string.
*
* @sample
* //returns 'is a'
* var retval = utils.stringMiddleWords('this is a test',2,2);
*
* @param text to process
* @param i_start start word index
* @param numberof_words the word count to return
* @return the string with number of words form the left and
*/
public String js_stringMiddleWords(String text, Number i_start, Number numberof_words)
{
if (text != null && i_start != null && numberof_words != null)
{
try
{
int start = i_start.intValue();
int words = numberof_words.intValue();
StringBuilder sb = new StringBuilder();
StringTokenizer st = new StringTokenizer(text.toString(), " "); //$NON-NLS-1$
start = start - 1;
int i = 0;
while (st.hasMoreTokens())
{
String value = st.nextToken();
if (i >= (start) && i < (start + words))
{
sb.append(value);
}
if (st.hasMoreTokens() && i >= (start) && i < (start + words) - 1)
{
sb.append(" "); //$NON-NLS-1$
}
i++;
}
return sb.toString();
}
catch (Exception ex)
{
return text.toString();
}
}
else
{
return ""; //$NON-NLS-1$
}
}
/**
* Returns the number of words, starting from the right.
*
* @sample
* //returns 'is a test'
* var retval = utils.stringRightWords('this is a test',3);
*
* @param text to process
* @param numberof_words to return
* @return the string with number of words form the right
*/
public String js_stringRightWords(String text, Number numberof_words)
{
if (text != null && numberof_words != null)
{
try
{
int words = numberof_words.intValue();
StringBuilder sb = new StringBuilder();
StringTokenizer st = new StringTokenizer(text.toString(), " "); //$NON-NLS-1$
int i = 0;
int countwords = st.countTokens();
while (st.hasMoreTokens())
{
String value = st.nextToken();
if (countwords - words <= i)
{
sb.append(value);
if (st.hasMoreTokens())
{
sb.append(" "); //$NON-NLS-1$
}
}
i++;
}
return sb.toString();
}
catch (Exception ex)
{
return text.toString();
}
}
else
{
return ""; //$NON-NLS-1$
}
}
/**
* Returns the number of times searchString appears in textString.
*
* @sample
* //returns 2 as count
* var count = utils.stringPatternCount('this is a test','is');
*
* @param text the text to process
* @param toSearchFor the string to search for
* @return the occurrenceCount that the search string is found in the text
*/
public int js_stringPatternCount(String text, String toSearchFor)
{
if (text != null && toSearchFor != null && toSearchFor.length() > 0)
{
try
{
int length = toSearchFor.length();
int i = 0;
int index = text.indexOf(toSearchFor);
while (index != -1)
{
i++;
index = text.indexOf(toSearchFor, index + length);
}
return i;
}
catch (Exception ex)
{
}
}
return -1;
}
/**
* @deprecated use stringPatternCount(String text, String searchString)
*/
@Deprecated
public int js_stringPatternCount(String text, Object searchString)
{
if (searchString instanceof String)
{
return js_stringPatternCount(text, (String)searchString);
}
if (searchString instanceof Double)
{
return js_stringPatternCount(text, ScriptRuntime.numberToString(((Double)searchString).doubleValue(), 10));
}
return -1;
}
/**
* Returns the position of the string to search for, from a certain start position and occurrence.
*
* @sample
* //returns 4 as position
* var pos = utils.stringPosition('This is a test','s',1,1)
*
* @param textString the text to process
* @param toSearchFor the string to search
* @param i_start the start index to search from
* @param i_occurrence the occurrence
*
* @return the position
*/
public int js_stringPosition(String textString, String toSearchFor, Number i_start, Number i_occurrence)
{
if (textString != null && toSearchFor != null && i_start != null && i_occurrence != null)
{
try
{
int start = i_start.intValue() - 1;
if (start < 0) start = 0;
int occurrence = i_occurrence.intValue();
if (occurrence == 0) occurrence = 1;
String text = textString.toString();
int length = toSearchFor.length();
if (text.length() <= start) return -1;
if (occurrence < 0)
{
occurrence = occurrence * -1;
int i = 0;
int index = text.lastIndexOf(toSearchFor, start);
while (index != -1)
{
i++;
if (occurrence == i)
{
return index + 1;
}
index = text.lastIndexOf(toSearchFor, index);
}
}
else
{
int i = 0;
int index = text.indexOf(toSearchFor, start);
while (index != -1)
{
i++;
if (occurrence == i)
{
return index + 1;
}
index = text.indexOf(toSearchFor, index + length);
}
}
}
catch (Exception ex)
{
Debug.error("Error in utils.stringPosition", ex); //$NON-NLS-1$
}
}
return -1;
}
/**
* @deprecated use stringPosition(String, String, Number, Number)
*/
@Deprecated
public int js_stringPosition(String textString, Object searchString, Number i_start, Number i_occurrence)
{
if (searchString instanceof String)
{
return js_stringPosition(textString, (String)searchString, i_start, i_occurrence);
}
if (searchString instanceof Double)
{
return js_stringPosition(textString, ScriptRuntime.numberToString(((Double)searchString).doubleValue(), 10), i_start, i_occurrence);
}
return -1;
}
/**
* Replaces a portion of a string with replacement text from a specified index.
*
* @sample
* //returns 'this was a test'
* var retval = utils.stringIndexReplace('this is a test',6,2,'was');
*
* @param text the text to process
* @param i_start the start index to work from
* @param i_size the size of the text to replace
* @param replacement_text the replacement text
* @return the changed text string
*/
@SuppressWarnings("nls")
public String js_stringIndexReplace(String text, Number i_start, Number i_size, String replacement_text)
{
if (text != null && i_start != null && i_size != null)
{
try
{
int start = i_start.intValue();
int size = i_size.intValue();
start = start - 1;
String left = text.substring(0, start);
String right = text.substring(start + size, text.length());
return left + String.valueOf(replacement_text) + right;
}
catch (Exception ex)
{
}
}
return text == null ? "" : text;
}
/**
* @deprecated use stringIndexReplace(String, Number, Number, String)
*/
@Deprecated
public String js_stringIndexReplace(String text, Number i_start, Number i_size, Object replacement_text)
{
if (replacement_text instanceof String)
{
return js_stringIndexReplace(text, i_start, i_size, (String)replacement_text);
}
if (replacement_text instanceof Double)
{
return js_stringIndexReplace(text, i_start, i_size, ScriptRuntime.numberToString(((Double)replacement_text).doubleValue(), 10));
}
return text == null ? "" : text; //$NON-NLS-1$
}
/**
* Replaces a portion of a string with replacement text.
*
* @sample
* //returns 'these are cow 1 and cow 2.'
* var retval = utils.stringReplace('these are test 1 and test 2.','test','cow');
*
* @param text the text to process
* @param search_text the string to search
* @param replacement_text the replacement text
*
* @return the changed text string
*/
@SuppressWarnings("nls")
public String js_stringReplace(String text, String search_text, String replacement_text)
{
if (text != null && search_text != null)
{
return Utils.stringReplace(text.toString(), search_text.toString(), String.valueOf(replacement_text));
}
return text == null ? "" : text;
}
/**
* @deprecated use stringReplace(String, String, String)
*/
@Deprecated
public String js_stringReplace(String text, String search_text, Object replacement_text)
{
if (replacement_text instanceof String)
{
return js_stringReplace(text, search_text, (String)replacement_text);
}
if (replacement_text instanceof Double)
{
return js_stringReplace(text, search_text, ScriptRuntime.numberToString(((Double)replacement_text).doubleValue(), 10));
}
return text == null ? "" : text; //$NON-NLS-1$
}
/**
* Returns a string with the requested number of characters, starting from the left.
*
* @sample
* //returns 'this i'
* var retval = utils.stringLeft('this is a test',6);
*
* @param text the text to process
* @param i_size the size of the text to return
* @return the result text string
*/
public String js_stringLeft(String text, Number i_size)
{
if (text != null && i_size != null)
{
try
{
return text.substring(0, i_size.intValue());
}
catch (Exception ex)
{
return text;
}
}
else
{
return ""; //$NON-NLS-1$
}
}
/**
* Returns a substring from the original string.
*
* @sample
* //returns 'his'
* var retval = utils.stringMiddle('this is a test',2,3);
*
* @param text the text to process
* @param i_start the start index to work from
* @param i_size the size of the text to return
* @return the result text string
*/
public String js_stringMiddle(String text, Number i_start, Number i_size)
{
if (text != null && i_start != null && i_size != null)
{
int start = i_start.intValue();
int length = i_size.intValue();
try
{
start = start - 1;//Filemaker starts counting at 1>>Java at 0
return text.substring((start), (start + length));
}
catch (Exception ex)
{
return text.substring((start), text.length());
}
}
else
{
return ""; //$NON-NLS-1$
}
}
/**
* Returns a string with the requested number of characters, starting from the right.
*
* @sample
* //returns 'a test'
* var retval = utils.stringLeft('this is a test',6);
*
* @param text the text to process
* @param i_size the size of the text to return
* @return the result text string
*/
public String js_stringRight(String text, Number i_size)
{
if (text != null && i_size != null)
{
try
{
int pos = i_size.intValue();
return text.substring(text.length() - pos, text.length());
}
catch (Exception ex)
{
return text;
}
}
else
{
return ""; //$NON-NLS-1$
}
}
/**
* Filters characters out of from a string and leaves digits, returns the number. Uses locale decimal separator.
*
* @sample
* //returns 65567
* var retval = utils.stringToNumber('fg65gf567');
*
* @param textString the text to process
* @return the resulting number
*/
public double js_stringToNumber(String textString)
{
return js_stringToNumber(textString, null);
}
/**
* Filters characters out of from a string and leaves digits, returns the number. Decimal separator is specified as parameter.
*
* @sample
* //returns 65.567
* var retval = utils.stringToNumber('fg65gf.567','.');
*
* @param textString the text to process
* @param decimalSeparator decimal separator
*
* @return the resulting number
*/
public double js_stringToNumber(String textString, String decimalSeparator)
{
if (textString != null)
{
if (decimalSeparator == null)
{
DecimalFormatSymbols dfs = RoundHalfUpDecimalFormat.getDecimalFormatSymbols(application.getLocale());
decimalSeparator = String.valueOf(dfs.getDecimalSeparator());
}
int flag = 0;
StringBuilder sb = new StringBuilder();
char[] array = textString.toCharArray();
for (char element : array)
{
Character c = new Character(element);
String cc = c.toString();
if (Character.isDigit(element))
{
sb.append(element);
}
else if (cc != null && cc.equals(decimalSeparator) && flag == 0)
{
sb.append(element);
flag = 1;
}
}
String textt = sb.toString();
try
{
return Utils.getAsDouble(textt);
}
catch (Exception ex)
{
}
}
return 0;
}
/**
* @deprecated use stringToNumber(String)
*/
@Deprecated
public double js_stringToNumber(Object textString)
{
if (textString instanceof Number) return ((Number)textString).doubleValue();
if (textString != null)
{
return js_stringToNumber(textString.toString());
}
return 0;
}
/**
* Returns the PBKDF2 hash for specified text. This method is preferred above the old MD5 hash for enhanced security.
* It uses a default of 2000 iterations. The string that is returned can only be used in the utils.validatePBKDF2Hash(password,thisReturnValue)
* to check if this hash is a result of that password.
* This will always be false: utils.stringPBKDF2Hash("test") == utils.stringPBKDF2Hash("test"). Because for the same string in multiply calls it will not generate the same hash.
* So you can only check it like this: utils.validatePBKDF2Hash("test",utils.stringPBKDF2Hash("test"))
*
* NOTE: PBKDF2 is the key hash function for the PKCS (Public-Key Cryptography) standard, for more info see: http://en.wikipedia.org/wiki/PBKDF2
* @sample var hashed_password = utils.stringPBKDF2Hash(user_password)
*
* @param textString the text to process
* @return the resulting hashString
*/
public String js_stringPBKDF2Hash(String textString)
{
if (textString != null && !"".equals(textString))
{
return Utils.calculatePBKDF2(textString.toString(), 2000);
}
return null;
}
/**
* Returns the PBKDF2 hash for specified text. This method is preferred above the old MD5 hash for enhanced security.
*
* NOTE: PBKDF2 is the key hash function for the PKCS (Public-Key Cryptography) standard, for more info see: http://en.wikipedia.org/wiki/PBKDF2
* @sample var hashed_password = utils.stringPBKDF2Hash(user_password,5000)
*
* @param textString the text to process
* @param iterations how many hash iterations should be done, minimum should be 1000 or higher.
* @return the resulting hashString
*/
public String js_stringPBKDF2Hash(String textString, int iterations)
{
if (textString != null && !"".equals(textString)) //$NON-NLS-1$
{
return Utils.calculatePBKDF2(textString.toString(), iterations);
}
return null;
}
/**
* Validates the given password against the given hash. The hash should be generated by one of the stringPBKDF2Hash(password [,iteration]) functions. If hash is null or empty string the method will return false.
*
* NOTE: PBKDF2 is the key hash function for the PKCS (Public-Key Cryptography) standard, for more info see: http://en.wikipedia.org/wiki/PBKDF2
* @sample
* if (utils.validatePBKDF2Hash(user_password, hashFromDb)) {
* // logged in
* }
*
* @param password the password to test against
* @param hash the hash the password needs to validate to.
* @return true if his hash is valid for that password
*/
public boolean js_validatePBKDF2Hash(String password, String hash)
{
if (password != null && !"".equals(password) && hash != null)
{
return Utils.validatePBKDF2Hash(password, hash);
}
return false;
}
/**
* Returns the md5 hash (encoded as base64) for specified text.
*
* NOTE: MD5 (Message-Digest Algorythm 5) is a hash function with a 128-bit hash value, for more info see: http://en.wikipedia.org/wiki/MD5
* @sample var hashed_password = utils.stringMD5HashBase64(user_password)
*
* @param textString the text to process
* @return the resulting hashString
*/
public String js_stringMD5HashBase64(String textString)
{
if (textString != null)
{
return Utils.calculateMD5HashBase64(textString.toString());
}
return null;
}
/**
* Returns the md5 hash (encoded as base16) for specified text.
*
* NOTE: MD5 (Message-Digest Algorythm 5) is a hash function with a 128-bit hash value, for more info see: http://en.wikipedia.org/wiki/MD5
* @sample var hashed_password = utils.stringMD5HashBase16(user_password)
*
* @param textString the text to process
* @return the resulting hashString
*/
public String js_stringMD5HashBase16(String textString)
{
if (textString != null)
{
return Utils.calculateMD5HashBase16(textString.toString());
}
return null;
}
/**
* Returns the string without leading or trailing spaces.
*
* @sample
* //returns 'text'
* var retval = utils.stringTrim(' text ');
*
* @param textString the text to process
* @return the resulting trimmed string
*/
public String js_stringTrim(String textString)
{
if (textString != null)
{
return textString.trim();
}
return ""; //$NON-NLS-1$
}
/**
* @deprecated use stringTrim(String)
*/
@Deprecated
public String js_stringTrim(Object textString)
{
if (textString != null)
{
if (textString instanceof Double)
{
return js_stringTrim(ScriptRuntime.numberToString(((Double)textString).doubleValue(), 10));
}
return js_stringTrim(textString.toString());
}
return ""; //$NON-NLS-1$
}
/**
* Format a number to have a defined fraction.
*
* @sample
* var textalNumber = utils.numberFormat(16.749, 2); //returns 16.75
*
* @param number the number to format
* @param digits nr of digits
* @return the resulting number in text
*/
@JSFunction
public String numberFormat(Number number, Number digits)
{
if (number != null)
{
if (digits == null)
{
return number.toString();
}
return Utils.formatNumber(application.getLocale(), number.doubleValue(), digits.intValue());
}
return ""; //$NON-NLS-1$
}
/**
* Format a number to specification.
*
* @sample
* var textalNumber2 = utils.numberFormat(100006.749, '#,###.00'); //returns 100,006.75
*
* @param number the number to format
* @param format the format
* @return the resulting number in text
*/
@JSFunction
public String numberFormat(Number number, String format)
{
if (number != null)
{
if (format == null)
{
return number.toString();
}
return new RoundHalfUpDecimalFormat(format, application.getLocale()).format(number.doubleValue());
}
return ""; //$NON-NLS-1$
}
/**
* @param number the number to format
* @param digitsOrFormat nr of digits or the format
*
* @deprecated use numberFormat(Number, String) or numberFormat(Number, Number)
*/
@Deprecated
public String js_numberFormat(Object number, Object digitsOrFormat)
{
if (number != null)
{
if (digitsOrFormat instanceof Number)
{
return numberFormat(Double.valueOf(Utils.getAsDouble(number)), (Number)digitsOrFormat);
}
if (digitsOrFormat instanceof String)
{
return numberFormat(Double.valueOf(Utils.getAsDouble(number)), (String)digitsOrFormat);
}
return number.toString();
}
return ""; //$NON-NLS-1$
}
/**
* Formats a string according to format specifiers and arguments.
*
* @sample
* // the format specifier has the syntax: %[argument_index$][flags][width][.precision]conversion
* // argument index is 1$, 2$ ...
* // flags is a set of characters that modify the output format
* // typical values: '+'(The result will always include a sign), ','(The result will include locale-specific grouping separators)
* // width is a non-negative decimal integer indicating the minimum number of characters to be written to the output
* // precision is a non-negative decimal integer usually used to restrict the number of characters
* // conversion is a character indicating how the argument should be formatted
* // typical conversion values: b(boolean), s(string), c(character), d(decimal integer), f(floating number), t(prefix for date and time)
* // Date/Time Conversions (used after 't' prefix):
* // 'H' Hour of the day for the 24-hour clock, formatted as two digits with a leading zero as necessary i.e. 00 - 23.
* // 'I' Hour for the 12-hour clock, formatted as two digits with a leading zero as necessary, i.e. 01 - 12.
* // 'k' Hour of the day for the 24-hour clock, i.e. 0 - 23.
* // 'l' Hour for the 12-hour clock, i.e. 1 - 12.
* // 'M' Minute within the hour formatted as two digits with a leading zero as necessary, i.e. 00 - 59.
* // 'S' Seconds within the minute, formatted as two digits with a leading zero as necessary, i.e. 00 - 60 ("60" is a special value required to support leap seconds).
* // 'L' Millisecond within the second formatted as three digits with leading zeros as necessary, i.e. 000 - 999.
* // 'p' Locale-specific morning or afternoon marker in lower case, e.g."am" or "pm". Use of the conversion prefix 'T' forces this output to upper case.
* // 'z' RFC 822 style numeric time zone offset from GMT, e.g. -0800.
* // 'Z' A string representing the abbreviation for the time zone.
* // 'B' Locale-specific full month name, e.g. "January", "February".
* // 'b' Locale-specific abbreviated month name, e.g. "Jan", "Feb".
* // 'h' Same as 'b'.
* // 'A' Locale-specific full name of the day of the week, e.g. "Sunday", "Monday"
* // 'a' Locale-specific short name of the day of the week, e.g. "Sun", "Mon"
* // 'C' Four-digit year divided by 100, formatted as two digits with leading zero as necessary, i.e. 00 - 99
* // 'Y' Year, formatted as at least four digits with leading zeros as necessary, e.g. 0092 equals 92 CE for the Gregorian calendar.
* // 'y' Last two digits of the year, formatted with leading zeros as necessary, i.e. 00 - 99.
* // 'j' Day of year, formatted as three digits with leading zeros as necessary, e.g. 001 - 366 for the Gregorian calendar.
* // 'm' Month, formatted as two digits with leading zeros as necessary, i.e. 01 - 13.
* // 'd' Day of month, formatted as two digits with leading zeros as necessary, i.e. 01 - 31
* // 'e' Day of month, formatted as two digits, i.e. 1 - 31.
*
* // common compositions for date/time conversion
* // 'R' Time formatted for the 24-hour clock as "%tH:%tM"
* // 'T' Time formatted for the 24-hour clock as "%tH:%tM:%tS".
* // 'r' Time formatted for the 12-hour clock as "%tI:%tM:%tS %Tp". The location of the morning or afternoon marker ('%Tp') may be locale-dependent.
* // 'D' Date formatted as "%tm/%td/%ty".
* // 'F' ISO 8601 complete date formatted as "%tY-%tm-%td".
* // 'c' Date and time formatted as "%ta %tb %td %tT %tZ %tY", e.g. "Sun Jul 20 16:17:00 EDT 1969".
*
* utils.stringFormat('%s Birthday: %2$tm %2$te,%2$tY',new Array('My',new Date(2009,0,1))) // returns My Birthday: 01 1,2009
* utils.stringFormat('The time is: %1$tH:%1$tM:%1$tS',new Array(new Date(2009,0,1,12,0,0))) // returns The time is: 12:00:00
* utils.stringFormat('My %s: %2$.0f, my float: %2$.2f',new Array('integer',10)) // returns My integer: 10, my float: 10.00
* utils.stringFormat('Today is: %1$tc',new Array(new Date())) // returns current date/time as: Today is: Fri Feb 20 14:15:54 EET 2009
* utils.stringFormat('Today is: %tF',new Array(new Date())) // returns current date as: Today is: 2009-02-20
*
* @param text_to_format the text to format
* @param parameters the array with parameters
* @return the formatted text
*/
public String js_stringFormat(String text_to_format, Object[] parameters)
{
if (text_to_format == null) return null;
if (parameters != null)
{
for (int i = 0; i < parameters.length; i++)
{
if (parameters[i] instanceof Integer)
{
// possible problem
int j = 0;
int position = text_to_format.indexOf("%"); //$NON-NLS-1$
while (j != i && position >= 0)
{
j++;
position = text_to_format.indexOf("%", position + 1); //$NON-NLS-1$
}
if (i == j && position >= 0)
{
List<Character> conversionsList = Arrays.asList(CONVERSIONS);
for (int k = position + 1; k < text_to_format.length(); k++)
{
if (text_to_format.charAt(k) == 'f')
{
parameters[i] = new Float(((Integer)parameters[i]).intValue());
break;
}
if (conversionsList.contains(Character.valueOf(text_to_format.charAt(k))))
{
break;
}
}
}
}
}
return new Formatter().format(text_to_format, parameters).toString();
}
else return text_to_format;
}
private final Character[] CONVERSIONS = new Character[] { Character.valueOf('b'), Character.valueOf('B'), Character.valueOf('h'), Character.valueOf('H'),//
Character.valueOf('s'), Character.valueOf('S'), Character.valueOf('c'), Character.valueOf('C'), Character.valueOf('d'), Character.valueOf('o'),//
Character.valueOf('x'), Character.valueOf('X'), Character.valueOf('e'), Character.valueOf('E'), Character.valueOf('g'), Character.valueOf('G'), //
Character.valueOf('a'), Character.valueOf('A'), Character.valueOf('t'), Character.valueOf('T'), Character.valueOf('n') };
/**
* Returns the number of words in the text string.
*
* @sample
* //returns '4' as result
* var retval = utils.stringWordCount('this is a test');
*
* @param text the text to process
* @return the word count
*/
public int js_stringWordCount(String text)
{
if (text != null)
{
try
{
StringTokenizer st = new StringTokenizer(text, " \n\r\t"); //$NON-NLS-1$
return st.countTokens();
}
catch (Exception ex)
{
return -1;
}
}
else
{
return -1;
}
}
/**
* Returns the escaped markup text (HTML/XML).
*
* @sample var escapedText = utils.stringEscapeMarkup('<html><body>escape me</body></html>')
*
* @param textString the text to process
* @return the escaped text
*/
public String js_stringEscapeMarkup(String textString)
{
return js_stringEscapeMarkup(textString, Boolean.FALSE, Boolean.FALSE);
}
/**
* @clonedesc js_stringEscapeMarkup(String)
* @sampleas js_stringEscapeMarkup(String)
*
* @param textString the text to process
* @param escapeSpaces boolean indicating to escape spaces
* @return the escaped text
*/
public String js_stringEscapeMarkup(String textString, Boolean escapeSpaces)
{
return js_stringEscapeMarkup(textString, escapeSpaces, Boolean.FALSE);
}
/**
* @clonedesc js_stringEscapeMarkup(String)
* @sampleas js_stringEscapeMarkup(String)
*
* @param textString the text to process
* @param escapeSpaces boolean indicating to escape spaces
* @param convertToHtmlUnicodeEscapes boolean indicating to use unicode escapes
* @return the escaped text
*/
public String js_stringEscapeMarkup(String textString, Boolean escapeSpaces, Boolean convertToHtmlUnicodeEscapes)
{
boolean _escapeSpaces = Utils.getAsBoolean(escapeSpaces);
boolean _convertToHtmlUnicodeEscapes = Utils.getAsBoolean(convertToHtmlUnicodeEscapes);
CharSequence retval = HtmlUtils.escapeMarkup(textString, _escapeSpaces, _convertToHtmlUnicodeEscapes);
return (retval != null ? retval.toString() : null);
}
/**
* Returns all words starting with capital chars.
*
* @sample
* //returns 'This Is A Test'
* var retval = utils.stringInitCap('This is A test');
*
* @param text the text to process
*
* @return the changed text
*/
public String js_stringInitCap(String text)
{
return Utils.stringInitCap(text);
}
@Override
public String toString()
{
return "JavaScript Utils"; //$NON-NLS-1$
}
public void destroy()
{
this.application = null;
}
}