package org.openrosa.client.util;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;
import org.openrosa.client.PurcConstants;
import org.openrosa.client.locale.LocaleText;
import org.openrosa.client.model.FormDef;
import org.openrosa.client.model.IFormElement;
import org.openrosa.client.model.OptionDef;
import org.openrosa.client.view.ErrorDialog;
import org.openrosa.client.view.ProgressDialog;
import org.openrosa.client.xforms.XformConstants;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.http.client.Response;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
//TODO May need to separate form designer specific utilities from those used by the form runner.
/**
* Utilities used by the form designer and runtime engine.
*
* @author daniel
*
*/
public class FormUtil {
/** The date time format used in the xforms model xml. */
private static DateTimeFormat dateTimeSubmitFormat;
/** The date time format used for display purposes. */
private static DateTimeFormat dateTimeDisplayFormat;
/** The date format used in the xforms model xml. */
private static DateTimeFormat dateSubmitFormat;
/** The date format used for display purposes. */
private static DateTimeFormat dateDisplayFormat;
/** The time format used in the xforms model xml. */
private static DateTimeFormat timeSubmitFormat;
/** The time format used for display purposes. */
private static DateTimeFormat timeDisplayFormat;
private static String formDefDownloadUrlSuffix;
private static String formDefUploadUrlSuffix;
private static String entityFormDefDownloadUrlSuffix;
private static String formDataUploadUrlSuffix;
private static String afterSubmitUrlSuffix;
private static String formDefRefreshUrlSuffix;
private static String externalSourceUrlSuffix;
private static String multimediaUrlSuffix;
private static String fileOpenUrlSuffix;
private static String fileSaveUrlSuffix;
private static String gpsTypeName;
private static String saveFormat;
public static String JAVAROSA = "javarosa";
/**
* The url to navigate to when one closes the form designer by selecting
* Close from the file menu.
*/
private static String closeUrl;
/** The name for the formId field. */
private static String formIdName;
/** The name for the entityId field. */
private static String entityIdName;
/** The form identifier. */
private static String formId;
/** The entity identifier. eg patientId, individualId. */
private static String entityId;
/** The default font family used by the form designer. */
private static String defaultFontFamily;
/** The default font size, in pixels, used by the form designer. */
private static String defaultFontSize;
/** Flag determining whether to append the entity id to the url
* we go to after a form submission. eg ........?patientId=13
*/
private static boolean appendEntityIdAfterSubmit;
/**
* Flag determining whether to display the language xml tab or not.
*/
//private static boolean showLanguageTab = false;
/**
* Flag determining whether to display the form submitted successfully message or not.
*/
private static boolean showSubmitSuccessMsg = false;
/** The dialog used to show all progress messages. */
public static ProgressDialog dlg = new ProgressDialog();
/**
* Maximizes a widget.
*
* @param widget the widget to maximize.
*/
public static void maximizeWidget(Widget widget){
widget.setSize("100%", "100%");
}
//TODO These two functions need to be merged.
public static void allowNumericOnly(TextBox textBox, boolean allowDecimal){
final boolean allowDecimalPoints = allowDecimal;
textBox.addKeyPressHandler(new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
char keyCode = event.getCharCode();
if( keyCode == '%' || keyCode == '&' || keyCode == '(')
((TextBox) event.getSource()).cancelKey();
if ((!Character.isDigit(keyCode)) && (keyCode != (char) KeyCodes.KEY_TAB)
&& (keyCode != (char) KeyCodes.KEY_BACKSPACE) && (keyCode != (char) KeyCodes.KEY_LEFT)
&& (keyCode != (char) KeyCodes.KEY_UP) && (keyCode != (char) KeyCodes.KEY_RIGHT)
&& (keyCode != (char) KeyCodes.KEY_DOWN)) {
if(keyCode == '.' && allowDecimalPoints && !((TextBox)event.getSource()).getText().contains("."))
return;
String text = ((TextBox) event.getSource()).getText().trim();
if(keyCode == '-'){
if(text.length() == 0 || ((TextBox)event.getSource()).getCursorPos() == 0)
return;
}
((TextBox) event.getSource()).cancelKey();
}
}
});
textBox.addChangeHandler(new ChangeHandler(){
public void onChange(ChangeEvent event){
try{
if(allowDecimalPoints)
Double.parseDouble(((TextBox) event.getSource()).getText().trim());
else
Integer.parseInt(((TextBox) event.getSource()).getText().trim());
}
catch(Exception ex){
((TextBox) event.getSource()).setText(null);
}
}
});
}
public static KeyPressHandler getAllowNumericOnlyKeyboardListener(TextBox textBox, boolean allowDecimal){
final boolean allowDecimalPoints = allowDecimal;
return new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
char keyCode = event.getCharCode();
if( keyCode == '%' || keyCode == '&' || keyCode == '(')
((TextBox) event.getSource()).cancelKey();
if ((!Character.isDigit(keyCode)) && (keyCode != (char) KeyCodes.KEY_TAB)
&& (keyCode != (char) KeyCodes.KEY_BACKSPACE) && (keyCode != (char) KeyCodes.KEY_LEFT)
&& (keyCode != (char) KeyCodes.KEY_UP) && (keyCode != (char) KeyCodes.KEY_RIGHT)
&& (keyCode != (char) KeyCodes.KEY_DOWN)) {
if(keyCode == '.' && allowDecimalPoints && !((TextBox)event.getSource()).getText().contains("."))
return;
String text = ((TextBox) event.getSource()).getText().trim();
if((text.length() == 0 && keyCode == '-') || (keyCode == '-' && ((TextBox)event.getSource()).getCursorPos() == 0))
return;
((TextBox) event.getSource()).cancelKey();
}
}
};
}
public static void setWidgetPosition(Widget w, String left, String top) {
com.google.gwt.user.client.Element h = w.getElement();
DOM.setStyleAttribute(h, "position", "absolute");
DOM.setStyleAttribute(h, "left", left);
DOM.setStyleAttribute(h, "top", top);
}
public static void loadOptions(List<OptionDef> options, MultiWordSuggestOracle oracle){
if(options == null)
return;
for(int i=0; i<options.size(); i++){
OptionDef optionDef = (OptionDef)options.get(i);
oracle.add(optionDef.getText());
}
}
private static String indent(String text, int indentLevel) {
for( int count = indentLevel ; count > 0 ; count--)
text += " ";
return text;
}
/**
* Add formatting to an XML string
*/
public static String formatXml(String xmlContent){
if(xmlContent == null)
return null;
return formatXmlPrivate(formatXmlPrivate(xmlContent));
}
private static String formatXmlPrivate(String xmlContent) {
return xmlContent;
// String result = "";
//
// try {
// String prevBeginSection = "";
// int prevIndex = 0;
//
// for(int indentLevel = 0, index = 0 ; index < xmlContent.length() ; index++) {
//
// //Seek to next "<"
// index = xmlContent.indexOf("<", index);
//
// if(index < 0 || index >= xmlContent.length())
// break;
//
// //Trim out XML block
// String section = xmlContent.substring(index, xmlContent.indexOf(">", index) + 1);
//
// if(section.matches("<!--.*-->")) {
// //Is comment <!--....-->
// result = indent(result, indentLevel);
// }
// else if(section.matches("<!.*>")) {
// //Directive
// result = indent(result, indentLevel);
// }
// else if(section.matches("<\\?.*\\?>")) {
// //Is directive <?...?>
// result = indent(result, indentLevel);
// }
// else if(section.matches("<[\\s]*[/\\\\].*>")) {
// //Is closing tag </...>
// result = indent(result, --indentLevel);
// }
// else if(section.matches("<.*[/\\\\][\\s]*>")) {
// //Is standalone tag <.../>
// result = indent(result, indentLevel);
// prevBeginSection = section;
// }
// else {
// //Is begin tag <....>
// result = indent(result, indentLevel++);
// prevBeginSection = section;
// }
//
// //My addition of making <> and </> be on same line and include text between
// //if(prevSection.equalsIgnoreCase(section.replace("/", ""))){
// //and we do this when we come accross a closing tag.
// if(section.matches("<[\\s]*[/\\\\].*>")) {
// if(prevIndex > 0){
// int len = 1+(indentLevel*2);
// if(result.substring(result.length()-len).contains("\n")){
// if(isClosingPreviousBeginTag(prevBeginSection,section))
// result = result.substring(0,result.length()-len);
// String s = xmlContent.substring(prevIndex+1,index);
// if(s.contains("\r\n")){
// if(!s.trim().equals(""))
// result += s.replace("\r\n", " ");
// }
// else if(s.contains("\n")){
// if(!s.trim().equals(""))
// result += s.replace("\n", " ");
// }
// else
// result += s;
//
// prevIndex = 0;
// }
// }
// }
// else
// prevIndex = xmlContent.indexOf(">", index);
//
// result += section + "\n";
// }
// }
// catch(StringIndexOutOfBoundsException s) {
// s.printStackTrace();
// return "Invalid XML";
// }
//
// return result;
}
private static boolean isClosingPreviousBeginTag(String prevBeginSection, String currentEndSection){
int pos = prevBeginSection.indexOf(' ');
if(pos < 0)
pos = prevBeginSection.length()-1;
String s = "</" + prevBeginSection.substring(1,pos) + ">";
return s.equalsIgnoreCase(currentEndSection);
}
/**
* Sets up the GWT uncaught exception handler.
*
*/
public static void setupUncaughtExceptionHandler(){
GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
public void onUncaughtException(Throwable throwable) {
displayException(throwable);
}
});
}
/**
* Gets the parameters passed in the host html file as divs (preferably hidden divs).
* For now this is the way of passing parameters to the form designer and runtime widget.
*/
public static void retrieveUserDivParameters(){
formDefDownloadUrlSuffix = getDivValue("formDefDownloadUrlSuffix");
formDefUploadUrlSuffix = getDivValue("formDefUploadUrlSuffix");
entityFormDefDownloadUrlSuffix = getDivValue("entityFormDefDownloadUrlSuffix");
formDataUploadUrlSuffix = getDivValue("formDataUploadUrlSuffix");
afterSubmitUrlSuffix = getDivValue("afterSubmitUrlSuffix");
formDefRefreshUrlSuffix = getDivValue("formDefRefreshUrlSuffix");
externalSourceUrlSuffix = getDivValue("externalSourceUrlSuffix");
multimediaUrlSuffix = getDivValue("multimediaUrlSuffix");
fileOpenUrlSuffix = getDivValue("fileOpenUrlSuffix");
fileSaveUrlSuffix = getDivValue("fileSaveUrlSuffix");
closeUrl = getDivValue("closeUrl");
if(multimediaUrlSuffix == null || multimediaUrlSuffix.trim().length() == 0)
multimediaUrlSuffix = "multimedia";
formIdName = getDivValue("formIdName");
if(formIdName == null || formIdName.trim().length() == 0)
formIdName = "formId";
entityIdName = getDivValue("entityIdName");
if(entityIdName == null || entityIdName.trim().length() == 0)
entityIdName = "patientId";
formId = getDivValue(formIdName);
entityId = getDivValue(entityIdName);
String format = getDivValue("dateTimeSubmitFormat");
if(format != null && format.trim().length() > 0)
setDateTimeSubmitFormat(format);
format = getDivValue("dateTimeDisplayFormat");
if(format != null && format.trim().length() > 0)
setDateTimeDisplayFormat(format);
format = getDivValue("timeDisplayFormat");
if(format != null && format.trim().length() > 0)
setTimeDisplayFormat(format);
format = getDivValue("timeSubmitFormat");
if(format != null && format.trim().length() > 0)
setTimeSubmitFormat(format);
format = getDivValue("dateDisplayFormat");
if(format != null && format.trim().length() > 0)
setDateDisplayFormat(format);
format = getDivValue("dateSubmitFormat");
if(format != null && format.trim().length() > 0)
setDateSubmitFormat(format);
defaultFontFamily = getDivValue("defaultFontFamily");
if(defaultFontFamily == null || defaultFontFamily.trim().length() == 0)
defaultFontFamily = "Verdana, 'Lucida Grande', 'Trebuchet MS', Arial, Sans-Serif";
defaultFontSize = getDivValue("defaultFontSize");
if(defaultFontSize == null || defaultFontSize.trim().length() == 0)
defaultFontSize = "16";
String s = getDivValue("appendEntityIdAfterSubmit");
if(s == null || s.trim().length() == 0)
appendEntityIdAfterSubmit = false;
else
appendEntityIdAfterSubmit = !s.equals("0");
s = getDivValue("showSubmitSuccessMsg");
if("1".equals(s) || "true".equals(s))
showSubmitSuccessMsg = true;
/*s = getDivValue("showLanguageTab");
if("1".equals(s) || "true".equals(s))
showLanguageTab = true;*/
gpsTypeName = getDivValue("gpsTypeName");
if(gpsTypeName == null || gpsTypeName.trim().length() == 0)
gpsTypeName = XformConstants.DATA_TYPE_TEXT;
s = getDivValue("formKeyAttributeName");
if(s != null && s.trim().length() > 0)
XformConstants.ATTRIBUTE_NAME_FORM_KEY = s;
s = getDivValue("constraintMessageAttributeName");
if(s != null && s.trim().length() > 0)
XformConstants.ATTRIBUTE_NAME_CONSTRAINT_MESSAGE = s;
saveFormat = getDivValue("saveFormat");
if(JAVAROSA.equalsIgnoreCase(saveFormat)){
gpsTypeName = "geopoint";
XformConstants.ATTRIBUTE_NAME_FORM_KEY = "id";
XformConstants.ATTRIBUTE_NAME_CONSTRAINT_MESSAGE = "jr:constraintMsg";
XformConstants.DATA_TYPE_BINARY = "binary";
}
}
public static String getDivValue(String id){
//RootPanel p = RootPanel.get(id);
com.google.gwt.dom.client.Element p = com.google.gwt.dom.client.Document.get().getElementById(id);
if(p != null){
NodeList<Node> nodes = p.getChildNodes();
if(nodes != null && nodes.getLength() > 0){
Node node = nodes.getItem(0);
String s = node.getNodeValue();
p.removeChild(node);
return s;
}
}
return null;
}
public static void setDateTimeSubmitFormat(String format){
dateTimeSubmitFormat = DateTimeFormat.getFormat(format);
}
public static DateTimeFormat getDateTimeSubmitFormat(){
return dateTimeSubmitFormat;
}
public static void setDateTimeDisplayFormat(String format){
dateTimeDisplayFormat = DateTimeFormat.getFormat(format);
}
public static DateTimeFormat getDateTimeDisplayFormat(){
return dateTimeDisplayFormat;
}
public static void setTimeDisplayFormat(String format){
timeDisplayFormat = DateTimeFormat.getFormat(format);
}
public static DateTimeFormat getTimeDisplayFormat(){
return timeDisplayFormat;
}
public static void setDateDisplayFormat(String format){
dateDisplayFormat = DateTimeFormat.getFormat(format);
}
public static DateTimeFormat getDateDisplayFormat(){
return dateDisplayFormat;
}
public static void setTimeSubmitFormat(String format){
timeSubmitFormat = DateTimeFormat.getFormat(format);
}
public static DateTimeFormat getTimeSubmitFormat(){
return timeSubmitFormat;
}
public static void setDateSubmitFormat(String format){
dateSubmitFormat = DateTimeFormat.getFormat(format);
}
public static DateTimeFormat getDateSubmitFormat(){
return dateSubmitFormat;
}
public static String getFormDefDownloadUrlSuffix(){
return formDefDownloadUrlSuffix;
}
public static String getFormDefUploadUrlSuffix(){
return formDefUploadUrlSuffix;
}
public static String getEntityFormDefDownloadUrlSuffix(){
return entityFormDefDownloadUrlSuffix;
}
public static String getFormDataUploadUrlSuffix(){
return formDataUploadUrlSuffix;
}
public static String getAfterSubmitUrlSuffix(){
return afterSubmitUrlSuffix;
}
public static String getFormDefRefreshUrlSuffix(){
return formDefRefreshUrlSuffix;
}
public static String getExternalSourceUrlSuffix(){
return externalSourceUrlSuffix;
}
public static String getMultimediaUrl(){
return getHostPageBaseURL()+ multimediaUrlSuffix;
}
public static String getFileOpenUrl(){
return getHostPageBaseURL()+ fileOpenUrlSuffix;
}
public static String getFileSaveUrl(){
return getHostPageBaseURL()+ fileSaveUrlSuffix;
}
public static String getCloseUrl(){
return closeUrl;
}
public static String getFormIdName(){
return formIdName;
}
public static String getEntityIdName(){
return entityIdName;
}
public static String getFormId(){
return formId;
}
public static String getEntityId(){
return entityId;
}
/*public static boolean getShowLanguageTab(){
return showLanguageTab;
}*/
public static String getGpsTypeName(){
return gpsTypeName;
}
public static String getSaveFormat(){
return saveFormat;
}
public static boolean isJavaRosaSaveFormat(){
return JAVAROSA.equalsIgnoreCase(saveFormat);
}
public static String getHostPageBaseURL(){
//return "http://127.0.0.1:8080/openmrs/";
//or http://dev.cell-life.org/openmrs/
String s = GWT.getHostPageBaseURL();
/*int pos = s.lastIndexOf(':');
if(pos == -1)
return s;
pos = s.indexOf('/', pos+1);
if(pos == -1)
return s;
pos = s.indexOf('/', pos+1);
if(pos == -1)
return s;
return s.substring(0,pos+1);*/
int pos = s.indexOf("//");
if(pos == -1)
return s;
pos = s.indexOf('/', pos+2);
if(pos == -1)
return s;
pos = s.indexOf('/', pos+1);
if(pos == -1)
return s;
return s.substring(0,pos+1);
}
public static String getDefaultFontFamily(){
return defaultFontFamily;
}
public static String getDefaultFontSize(){
return defaultFontSize + PurcConstants.UNITS;
}
public static boolean appendEntityIdAfterSubmit(){
return appendEntityIdAfterSubmit;
}
public static boolean showSubmitSuccessMsg(){
return showSubmitSuccessMsg;
}
public static String getQtnIDFromNodeSetPath(String path){
String p = path.replace(" ", ""); //clean out spaces
String[] tokens = p.split("/");
return tokens[tokens.length-1];
}
/**
* Returns a int that can be used as a unique questionID
* (checks to see if the generated ID already exists,
* if so, generates a new one until it hits a unique)
* @param formDef
* @return
*/
public static int getNextNewQuestionID(FormDef formDef){
int id=formDef.getChildCount();
boolean alreadyUsed = true;
while(alreadyUsed){
id++;
alreadyUsed = formDef.getElement("question"+id) != null;
}
return id;
}
private static int lastOptionID = 0;
private static boolean hasBeenInit = false;
/**
* * Returns a int that can be used as a unique questionID
* (checks to see if the generated ID already exists,
* if so, generates a new one until it hits a unique)
* @param formDef
* @return
*/
public static int getNextNewOptionID(FormDef formDef){
if(!hasBeenInit){
lastOptionID = formDef.getOptionCount();
hasBeenInit = true;
}
lastOptionID++;
return Integer.parseInt(lastOptionID+""+getRand2DigitNum());
}
public static String getTwoRandomAlphaChars(){
int ran = (int)(Random.nextDouble()*25);
char a = "abcdefghijklmnopqrstuvwxyz".charAt(ran);
ran = (int)(Random.nextDouble()*25);
char b = "abcdefghijklmnopqrstuvwxyz".charAt(ran);
return (""+a+b).toUpperCase();
}
public static int getRand2DigitNum(){
return ((int)(Random.nextDouble()*99));
}
/**
* Takes in an element with either a nodeset or a ref
* attribute, returns the question ID extracted from either
* of those attributes. Assumes that either ref or nodeset
* is present, never both.
* Returns null if neither attrs are present.
* @param element
* @return
*/
public static String getQtnIDFromElement(Element element){
String nodeset = element.getAttribute("nodeset");
String ref = element.getAttribute("ref");
if(nodeset == null && ref == null){ return null; }
String path = (nodeset == null ? ref : nodeset);
return getQtnIDFromNodeSetPath(path);
}
/**
* Displays an exception to the user.
*
* @param ex the exception to display.
*/
public static void displayException(Throwable ex){
FormUtil.dlg.hide(); //TODO Some how when an exception is thrown, this may stay on. So needs a fix.
ex.printStackTrace();
String text = LocaleText.get("uncaughtException");
String s = text;
while (ex != null) {
s = ex.getMessage();
StackTraceElement[] stackTraceElements = ex.getStackTrace();
text += ex.toString() + "\n";
for (int i = 0; i < stackTraceElements.length; i++) {
text += " at " + stackTraceElements[i] + "\n";
}
ex = (Exception)ex.getCause();
if (ex != null) {
text += LocaleText.get("causedBy");
}
}
//This check is a temporary workaround for firefox 3.5 which
//throws this error on certain mouse moves which i have not
//yet got the exact cause for.
if(!(s != null && (s.contains("(NS_ERROR_DOM_NOT_SUPPORTED_ERR):") || s.contains("(Error): Permission denied for")))){
ErrorDialog dialogBox = new ErrorDialog();
dialogBox.setText(LocaleText.get("unexpectedFailure"));
dialogBox.setErrorMessage(s);
dialogBox.setCallStack(text);
dialogBox.center();
}//Window.prompt("Please enter the language", "Language");
//else
// Window.alert("Trapped");
}
public static void displayReponseError(Response response){
dlg.hide();
ErrorDialog dialogBox = new ErrorDialog();
dialogBox.setText("Response Error");
String errorMessage = "Status Code: "+response.getStatusCode()+"\n"
+ "Status Text: "+response.getStatusText()+"\n"
+ "Response Text: "+response.getText();
dialogBox.setErrorMessage(errorMessage);
String stackTrace = "NO STACK TRACE";
if(response.getText() != null && response.getText().trim().length() > 0)
stackTrace = response.getText().trim();
dialogBox.setCallStack(stackTrace);
dialogBox.center();
}
public static boolean shouldHaveHintDOMNode(IFormElement def){
boolean hasDefaultHelpText = (def.getHelpText() != null && !def.getHelpText().isEmpty());
boolean hasHelpItext = Itext.getDefaultLocale().hasID(def.getItextId()+";hint");
return (hasDefaultHelpText || hasHelpItext) && def.hasUINode();
}
/**
* Converts string dimension in say pixels to integer.
*
* @param dimension the dimension text.
* @return the integer value.
*/
public static int convertDimensionToInt(String dimension){
if(dimension == null || dimension.trim().length() == 0)
return 0;
try{
return Integer.parseInt(dimension.substring(0,dimension.length()-2));
}catch(Exception ex){}
return 1;
}
/**
* Gets the control node from the parent element (a Group, Repeat or the root html body node)
* based on the specified question ID
* @param questionID
* @param parentElement
* @return - The control node, or null if no such control node was found.
*/
public static Element getControlNodeByQuestionID(String questionID, Element parentElement){
com.google.gwt.xml.client.NodeList children = parentElement.getChildNodes();
Element retChild = null;
for(int i = 0; i<children.getLength();i++){
if(children.item(i).getNodeType() != Node.ELEMENT_NODE){ continue; }
retChild = (Element)children.item(i);
String ref = retChild.getAttribute("ref");
String bind = retChild.getAttribute("bind");
String nodeset = retChild.getAttribute("nodeset");
String childID = getIDfromRefBindOrNodeset(ref, bind, nodeset);
if(questionID.equals(childID)){
return retChild;
}
}
return null;
}
/**
* Pass in any of the params (scraped from the Element attributes with the same name)
* and get a questionID back. Gives preference to ref, then nodeset, then bind
* @param ref
* @param bind
* @param nodeset
* @return
*/
public static String getIDfromRefBindOrNodeset(String ref,String bind, String nodeset){
if(ref == null || ref.isEmpty()){ ref = null; } //I don't want to have to do both checks all day.
if(bind == null || bind.isEmpty()){ bind = null; }
if(nodeset == null || nodeset.isEmpty()){ nodeset = null; }
String attr = (ref == null ? bind : ref);
attr = (attr == null ? nodeset : attr);
if(attr == null){ return null; } //well, clearly nothing was passed in.
//now do the split boogie
String[] tokens = attr.split("/");
return tokens[tokens.length-1];
}
public static String getNodePath(com.google.gwt.xml.client.Node node){
String path = removePrefix(node.getNodeName());
if(node.getNodeType() == Node.ELEMENT_NODE){
com.google.gwt.xml.client.Node parent = node.getParentNode();
while(parent != null && !(parent instanceof Document)){
String value = ((Element)parent).getAttribute(XformConstants.ATTRIBUTE_NAME_ID);
if(value != null)
value = "[@id='" + value + "']";
if(value == null){
value = ((Element)parent).getAttribute(XformConstants.ATTRIBUTE_NAME_BIND);
if(value != null)
value = "[@bind='" + value + "']";
}
if(value == null){
value = ((Element)parent).getAttribute(XformConstants.ATTRIBUTE_NAME_REF);
if(value != null)
value = "[@ref='" + value + "']";
}
path = removePrefix(parent.getNodeName()) + (value == null ? "" : value) + "/" + path;
parent = parent.getParentNode();
}
}
return path;
}
/**
* Gets the xpath expression pointing to a node starting from a given parent node.
*
* @param node the node whose xpath expression to get.
* @param parentNode the parent node.
* @return the xpath expression.
*/
public static String getNodePath(com.google.gwt.xml.client.Node node, com.google.gwt.xml.client.Node parentNode){
String path = removePrefix(node.getNodeName());
if(node.getNodeType() == Node.ELEMENT_NODE){
com.google.gwt.xml.client.Node parent = node.getParentNode();
while(parent != null && !(parent instanceof Document)){
if(parent.getNodeName().equals(parentNode.getNodeName())){
if(parent.toString().equals(parentNode.toString()))
break;
}
String tempPath = "";
String id = ((Element)parent).getAttribute(XformConstants.ATTRIBUTE_NAME_ID);
if(id != null && id.trim().length() > 0)
tempPath = "[@id='" + id + "']";
path = removePrefix(parent.getNodeName()) + tempPath + "/" + path;
parent = parent.getParentNode();
}
}
return path;
}
/**
* Removes a namespace prefix from a name.
*
* @param name the name. eg xf:instance
* @return the new name without the prefix. For the above the value would be instance.
*/
private static String removePrefix(String name){
int pos = name.indexOf(':');
if(pos >= 0)
name = name.substring(pos + 1);
return name;
}
/**
* Gets the name of a node.
*
* @param node the node whose name to get.
* @return the node name.
*/
public static String getNodeName(Element node){
return removePrefix(node.getNodeName());
}
/**
* Tells form runner or designer widget user that we are done displaying the widgets
* and hence they can do initialization stuff if they have any.
*/
public static native void initialize() /*-{
return $wnd.initialize();
}-*/;
public static native void searchExternal(String key,String value,com.google.gwt.user.client.Element parentElement, com.google.gwt.user.client.Element textElement, com.google.gwt.user.client.Element valueElement, String filterField) /*-{
return $wnd.searchExternal(key,value,parentElement.parentNode.parentNode,textElement,valueElement,filterField);
}-*/;
/**
* Checks if the current used is authenticated by the server.
* This method is called every time a user tries to submit form data in non preview mode.
*
* @return
*/
public static native boolean isAuthenticated() /*-{
return $wnd.isUserAuthenticated();
}-*/;
/**
* Checks if a user is logged on the server.
*
* @param username the user name.
* @param password the password.
* @return This return value if value is not used because we are getting the result via a
* callback due to the asyncrounous nature of this call.
*/
public static native boolean authenticate(String username, String password) /*-{
return $wnd.authenticateUser(username,password);
}-*/;
public static Image createImage(ImageResource resource){
return AbstractImagePrototype.create(resource).createImage();
}
/**
* Evaluate scripts in an HTML string. Will eval both <script src=""></script>
* and <script>javascript here</scripts>.
*
* @param element a new HTML(text).getElement() e.g evalScripts(new HTML(response.getText()).getElement())
*/
public static native void evalScripts(com.google.gwt.user.client.Element element) /*-{
var scripts = element.getElementsByTagName("script");
for (i=0; i < scripts.length; i++) {
// if src, eval it, otherwise eval the body
if (scripts[i].hasAttribute("src")) {
var src = scripts[i].getAttribute("src");
var script = $doc.createElement('script');
script.setAttribute("src", src);
$doc.getElementsByTagName('body')[0].appendChild(script);
} else {
$wnd.eval(scripts[i].innerHTML);
}
}
}-*/;
public static native String getElementValue(com.google.gwt.user.client.Element element) /*-{
return element.value;
}-*/;
public static native void setElementValue(com.google.gwt.user.client.Element element, String value1, String value2) /*-{
//element.value = value;
//element.onchange=function(){alert('yo men')};
//element.addEventListener('change',function(){alert(Math.round(0.60))},false)
//element.addEventListener('change',function(){alert(Math.round((new Date().getTime() - value.getTime())/365.25));},false)
var val = Math.round(((Date.parse(value1) - Date.parse(value2))/86400000)/365.25);
//alert(val);
element.value = val;
if(document.createEvent){
// dispatch for firefox + others
var evt = document.createEvent('HTMLEvents');
evt.initEvent('change', true, true ); // event type,bubbling,cancelable
element.dispatchEvent(evt);
}
else{
// dispatch for IE
var evt = document.createEventObject();
element.fireEvent('onchange',evt)
}
}-*/;
public static native void fireChangeEvent(com.google.gwt.user.client.Element element) /*-{
if(document.createEvent){
// dispatch for firefox + others
var evt = document.createEvent('HTMLEvents');
evt.initEvent('change', true, true ); // event type,bubbling,cancelable
element.dispatchEvent(evt);
}
else{
// dispatch for IE
var evt = document.createEventObject();
element.fireEvent('onchange',evt)
}
}-*/;
public static native int evaluateIntExpression(String expression) /*-{
return eval(expression);
}-*/;
public static native double evaluateDoubleExpression(String expression) /*-{
return eval(expression);
}-*/;
public static native String evaluateStringExpression(String expression) /*-{
return eval(expression);
}-*/;
public static void setElementFontSizeAndFamily(com.google.gwt.user.client.Element element){
try{
DOM.setStyleAttribute(element, "fontFamily", getDefaultFontFamily());
DOM.setStyleAttribute(element, "fontSize", getDefaultFontSize());
}catch(Exception ex){}
}
public static boolean isNumeric(String value){
try{
Integer.parseInt(value);
return true;
}
catch(Exception ex){}
return false;
}
/**
* Converts a string into a valid XML token (tag name)
*
* @param s string to convert into XML token
* @return valid XML token based on s
*/
public static String getXmlTagName(String s) {
// Converts a string into a valid XML token (tag name)
// No spaces, start with a letter or underscore, not 'xml*'
// if len(s) < 1, return '_blank'
if (s == null || s.length() < 1)
return "_blank";
// xml tokens must start with a letter
String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
// after the leading letter, xml tokens may have
// digits, period, or hyphen
String nameChars = letters + "0123456789.-";
// special characters that should be replaced with valid text
// all other invalid characters will be removed
HashMap<String, String> swapChars = new HashMap<String, String>();
swapChars.put("!", "bang");
swapChars.put("#", "pound");
swapChars.put("\\*", "star");
swapChars.put("'", "apos");
swapChars.put("\"", "quote");
swapChars.put("%", "percent");
swapChars.put("<", "lt");
swapChars.put(">", "gt");
swapChars.put("=", "eq");
swapChars.put("/", "slash");
swapChars.put("\\\\", "backslash");
s = s.replace("'", "");
// start by cleaning whitespace and converting to lowercase
s = s.replaceAll("^\\s+", "").replaceAll("\\s+$", "").replaceAll("\\s+", "_").toLowerCase();
// swap characters
Set<Entry<String, String>> swaps = swapChars.entrySet();
for (Entry<String, String> entry : swaps) {
if (entry.getValue() != null)
s = s.replaceAll(entry.getKey(), "_" + entry.getValue() + "_");
else
s = s.replaceAll(String.valueOf(entry.getKey()), "");
}
// ensure that invalid characters and consecutive underscores are
// removed
String token = "";
boolean underscoreFlag = false;
for (int i = 0; i < s.length(); i++) {
if (nameChars.indexOf(s.charAt(i)) != -1) {
if (s.charAt(i) != '_' || !underscoreFlag) {
token += s.charAt(i);
underscoreFlag = (s.charAt(i) == '_');
}
}
}
// remove extraneous underscores before returning token
token = token.replaceAll("_+", "_");
token = token.replaceAll("_+$", "");
// make sure token starts with valid letter
if (letters.indexOf(token.charAt(0)) == -1 || token.startsWith("xml"))
token = "_" + token;
// return token
return token;
}
}