Example usage for org.apache.commons.lang StringUtils removeStart

List of usage examples for org.apache.commons.lang StringUtils removeStart

Introduction

In this page you can find the example usage for org.apache.commons.lang StringUtils removeStart.

Prototype

public static String removeStart(String str, String remove) 

Source Link

Document

Removes a substring only if it is at the begining of a source string, otherwise returns the source string.

Usage

From source file:org.kuali.rice.krad.uif.util.MessageStructureUtils.java

/**
 * Process a piece of the message that has id content to get a component by id and insert it in the structure
 *
 * @param messagePiece String piece with component by id content
 * @param messageComponentStructure the structure of the message being built
 * @param currentMessageComponent the state of the current text based message being built
 * @param view current View/* ww  w  .java2s .c  o m*/
 * @return null if currentMessageComponent had a value (it is now added to the messageComponentStructure passed in)
 */
private static Message processIdComponentContent(String messagePiece, List<Component> messageComponentStructure,
        Message currentMessageComponent, View view) {
    //splits around spaces not included in single quotes
    String[] parts = messagePiece.trim().trim().split("([ ]+(?=([^']*'[^']*')*[^']*$))");
    messagePiece = parts[0];

    //if there is a currentMessageComponent add it to the structure and reset it to null
    //because component content is now interrupting the string content
    if (currentMessageComponent != null && StringUtils.isNotEmpty(currentMessageComponent.getMessageText())) {
        messageComponentStructure.add(currentMessageComponent);
        currentMessageComponent = null;
    }

    //match component by id from the view
    messagePiece = StringUtils.remove(messagePiece, "'");
    messagePiece = StringUtils.remove(messagePiece, "\"");
    Component component = ComponentFactory.getNewComponentInstance(
            StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.COMPONENT_BY_ID + "="));

    if (component != null) {
        component.addStyleClass(KRADConstants.MessageParsing.INLINE_COMP_CLASS);

        if (parts.length > 1) {
            component = processAdditionalProperties(component, parts);
        }
        messageComponentStructure.add(component);
    }

    return currentMessageComponent;
}

From source file:org.kuali.rice.krad.uif.util.MessageStructureUtils.java

/**
 * Process a piece of the message that has color content by creating a span with that color style set
 *
 * @param messagePiece String piece with color content
 * @param currentMessageComponent the state of the current text based message being built
 * @param view current View//from   w  ww. j a  va 2 s  .c  o  m
 * @return currentMessageComponent with the new textual content generated by this method appended to its
 *         messageText
 */
private static Message processColorContent(String messagePiece, Message currentMessageComponent, View view) {
    if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
        messagePiece = StringUtils.remove(messagePiece, "'");
        messagePiece = StringUtils.remove(messagePiece, "\"");
        messagePiece = "<span style='color: "
                + StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.COLOR + "=") + ";'>";
    } else {
        messagePiece = "</span>";
    }

    return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
}

From source file:org.kuali.rice.krad.uif.util.MessageStructureUtils.java

/**
 * Process a piece of the message that has css content by creating a span with those css classes set
 *
 * @param messagePiece String piece with css class content
 * @param currentMessageComponent the state of the current text based message being built
 * @param view current View// w  ww .  j av  a 2 s.  c om
 * @return currentMessageComponent with the new textual content generated by this method appended to its
 *         messageText
 */
private static Message processCssClassContent(String messagePiece, Message currentMessageComponent, View view) {
    if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
        messagePiece = StringUtils.remove(messagePiece, "'");
        messagePiece = StringUtils.remove(messagePiece, "\"");
        messagePiece = "<span class='"
                + StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.CSS_CLASSES + "=") + "'>";
    } else {
        messagePiece = "</span>";
    }

    return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
}

From source file:org.kuali.rice.krad.uif.util.MessageStructureUtils.java

/**
 * Process a piece of the message that has link content by creating an anchor (a tag) with the href set
 *
 * @param messagePiece String piece with link content
 * @param currentMessageComponent the state of the current text based message being built
 * @param view current View//from   w  ww.j a v a  2s .  c  o  m
 * @return currentMessageComponent with the new textual content generated by this method appended to its
 *         messageText
 */
private static Message processLinkContent(String messagePiece, Message currentMessageComponent, View view) {
    if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
        //clean up href
        messagePiece = StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.LINK + "=");
        messagePiece = StringUtils.removeStart(messagePiece, "'");
        messagePiece = StringUtils.removeEnd(messagePiece, "'");
        messagePiece = StringUtils.removeStart(messagePiece, "\"");
        messagePiece = StringUtils.removeEnd(messagePiece, "\"");

        messagePiece = "<a href='" + messagePiece + "' target='_blank'>";
    } else {
        messagePiece = "</a>";
    }

    return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
}

From source file:org.kuali.rice.krad.uif.util.MessageStructureUtils.java

/**
 * Process a piece of the message that has action link content by creating an anchor (a tag) with the onClick set
 * to perform either ajaxSubmit or submit to the controller with a methodToCall
 *
 * @param messagePiece String piece with action link content
 * @param currentMessageComponent the state of the current text based message being built
 * @param view current View/*from  w  ww . j a  va  2  s  .c o  m*/
 * @return currentMessageComponent with the new textual content generated by this method appended to its
 *         messageText
 */
private static Message processActionLinkContent(String messagePiece, Message currentMessageComponent,
        View view) {
    if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
        messagePiece = StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.ACTION_LINK + "=");
        String[] splitData = messagePiece.split(KRADConstants.MessageParsing.ACTION_DATA + "=");

        String[] params = splitData[0].trim().split("([,]+(?=([^']*'[^']*')*[^']*$))");
        String methodToCall = ((params.length >= 1) ? params[0] : "");
        String validate = ((params.length >= 2) ? params[1] : "true");
        String ajaxSubmit = ((params.length >= 3) ? params[2] : "true");
        String successCallback = ((params.length >= 4) ? params[3] : "null");

        String submitData = "null";

        if (splitData.length > 1) {
            submitData = splitData[1].trim();
        }

        methodToCall = StringUtils.remove(methodToCall, "'");
        methodToCall = StringUtils.remove(methodToCall, "\"");

        messagePiece = "<a href=\"javascript:void(null)\" onclick=\"submitForm(" + "'" + methodToCall + "',"
                + submitData + "," + validate + "," + ajaxSubmit + "," + successCallback
                + "); return false;\">";

        ViewPostMetadata viewPostMetadata = ViewLifecycle.getViewPostMetadata();
        if (viewPostMetadata != null) {
            viewPostMetadata.addAccessibleMethodToCall(methodToCall);
            viewPostMetadata.addAvailableMethodToCall(methodToCall);
        }
    } else {
        messagePiece = "</a>";
    }

    return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
}

From source file:org.kuali.rice.krad.uif.util.ViewModelUtils.java

/**
 * Determines the associated type for the property within the View context
 *
 * <p>/*w ww  .ja  v a2s.  co m*/
 * Property path is full path to property from the View Form class. The abstract type classes
 * map configured on the View will be consulted for any entries that match the property path. If the
 * property path given contains a partial match to an abstract class (somewhere on path is an abstract
 * class), the property type will be retrieved based on the given concrete class to use and the part
 * of the path remaining. If no matching entry is found, standard reflection is used to get the type
 * </p>
 *
 * @param view view instance providing the context (abstract map)
 * @param model the model
 * @param propertyPath full path to property to retrieve type for (relative to the form class)
 * @return Class<?> type of property in model, or Null if type could not be determined
 * @see org.kuali.rice.krad.uif.view.View#getObjectPathToConcreteClassMapping()
 */
public static Class<?> getPropertyTypeByClassAndView(View view, Object model, String propertyPath) {
    if (StringUtils.isBlank(propertyPath)) {
        return null;
    }

    Class<?> propertyType = null;

    // in case of partial match, holds the class that matched and the
    // property so we can get by reflection
    Class<?> modelClass = null;
    String modelProperty = propertyPath;

    int bestMatchLength = 0;

    // removed collection indexes from path for matching
    String flattenedPropertyPath = propertyPath.replaceAll("\\[.+\\]", "");

    // check if property path matches one of the modelClass entries
    Map<String, Class<?>> modelClasses = view.getObjectPathToConcreteClassMapping();
    for (String path : modelClasses.keySet()) {
        // full match
        if (StringUtils.equals(path, flattenedPropertyPath)) {
            propertyType = modelClasses.get(path);
            break;
        }

        // partial match
        if (flattenedPropertyPath.startsWith(path) && (path.length() > bestMatchLength)) {
            bestMatchLength = path.length();

            modelClass = modelClasses.get(path);
            modelProperty = StringUtils.removeStart(flattenedPropertyPath, path);
            modelProperty = StringUtils.removeStart(modelProperty, ".");
        }
    }

    // if full match not found, get type based on reflection
    if (propertyType == null) {
        if (modelClass == null) {
            // no match, check model instance directly
            propertyType = ObjectPropertyUtils.getPropertyType(model, propertyPath);
        } else {
            // partial match, check modelClass
            propertyType = ObjectPropertyUtils.getPropertyType(modelClass, modelProperty);
        }
    }

    return propertyType;
}

From source file:org.kuali.rice.krad.uif.view.DefaultExpressionEvaluator.java

/**
 * {@inheritDoc}//from w w w  .  ja  va2  s.c om
 */
@Override
public String parseExpression(String exp, List<String> controlNames, Map<String, Object> context) {
    // clean up expression to ease parsing
    exp = exp.trim();
    if (exp.startsWith("@{")) {
        exp = StringUtils.removeStart(exp, "@{");
        if (exp.endsWith("}")) {
            exp = StringUtils.removeEnd(exp, "}");
        }
    }

    // Clean up the expression for parsing consistency
    exp = StringUtils.replace(exp, "!=", " != ");
    exp = StringUtils.replace(exp, "==", " == ");
    exp = StringUtils.replace(exp, ">", " > ");
    exp = StringUtils.replace(exp, "<", " < ");
    exp = StringUtils.replace(exp, "<=", " <= ");
    exp = StringUtils.replace(exp, ">=", " >= ");
    exp = StringUtils.replace(exp, "&&", " && ");
    exp = StringUtils.replace(exp, "||", " || ");
    exp = StringUtils.replace(exp, "  ", " ");
    exp = StringUtils.replace(exp, " )", ")");
    exp = StringUtils.replace(exp, "( ", "(");
    exp = StringUtils.replace(exp, " ,", ",");

    Map<String, String> serverEvaluations = new HashMap<String, String>();

    // Evaluate server side method calls and constants
    Matcher matcher = SERVER_EVALUATION_PATTERN.matcher(exp);
    while (matcher.find()) {
        String spelMethodCall = matcher.group(1);

        Object value = this.evaluateExpression(context, spelMethodCall);

        // Convert the value to expected js equivalent
        if (value == null) {
            serverEvaluations.put(spelMethodCall, "null");
        } else if (value instanceof String) {
            serverEvaluations.put(spelMethodCall, "\"" + value + "\"");
        } else if (value instanceof Boolean || NumberUtils.isNumber(value.toString())) {
            serverEvaluations.put(spelMethodCall, value.toString());
        } else {
            // Corner case, assume the object gives us something meaningful from toString, wrap in quotes
            serverEvaluations.put(spelMethodCall, "\"" + value.toString() + "\"");
        }
    }

    String conditionJs = exp;
    controlNames.addAll(findControlNamesInExpression(exp));

    // Replace all known accepted strings with javascript equivalent
    conditionJs = conditionJs.replaceAll("\\s(?i:ne)\\s", " != ").replaceAll("\\s(?i:eq)\\s", " == ")
            .replaceAll("\\s(?i:gt)\\s", " > ").replaceAll("\\s(?i:lt)\\s", " < ")
            .replaceAll("\\s(?i:lte)\\s", " <= ").replaceAll("\\s(?i:gte)\\s", " >= ")
            .replaceAll("\\s(?i:and)\\s", " && ").replaceAll("\\s(?i:or)\\s", " || ")
            .replaceAll("\\s(?i:not)\\s", " != ").replaceAll("\\s(?i:null)\\s?", " '' ")
            .replaceAll("\\s?(?i:#empty)\\((.*?)\\)", "isValueEmpty($1)")
            .replaceAll("\\s?(?i:#listContains)\\((.*?)\\)", "listContains($1)")
            .replaceAll("\\s?(?i:#emptyList)\\((.*?)\\)", "emptyList($1)");

    // Handle matches method conversion
    if (conditionJs.contains("matches")) {
        conditionJs = conditionJs.replaceAll("\\s+(?i:matches)\\s+'.*'", ".match(/" + "$0" + "/) != null ");
        conditionJs = conditionJs.replaceAll("\\(/\\s+(?i:matches)\\s+'", "(/");
        conditionJs = conditionJs.replaceAll("'\\s*/\\)", "/)");
    }

    for (String serverEvalToken : serverEvaluations.keySet()) {
        String evaluatedValue = serverEvaluations.get(serverEvalToken);
        conditionJs = conditionJs.replace(serverEvalToken, evaluatedValue);
    }

    List<String> removeControlNames = new ArrayList<String>();
    List<String> addControlNames = new ArrayList<String>();
    //convert property names to use coerceValue function and convert arrays to js arrays
    for (String propertyName : controlNames) {
        //array definitions are caught in controlNames because of the nature of the parse - convert them and remove
        if (propertyName.trim().startsWith("{") && propertyName.trim().endsWith("}")) {
            String array = propertyName.trim().replace('{', '[');
            array = array.replace('}', ']');
            conditionJs = conditionJs.replace(propertyName, array);
            removeControlNames.add(propertyName);
            continue;
        }

        //handle not
        if (propertyName.startsWith("!")) {
            String actualPropertyName = StringUtils.removeStart(propertyName, "!");
            conditionJs = conditionJs.replace(propertyName, "!coerceValue(\"" + actualPropertyName + "\")");
            removeControlNames.add(propertyName);
            addControlNames.add(actualPropertyName);
        } else {
            conditionJs = conditionJs.replace(propertyName, "coerceValue(\"" + propertyName + "\")");
        }
    }

    controlNames.removeAll(removeControlNames);
    controlNames.addAll(addControlNames);

    // Simple short circuit logic below
    boolean complexCondition = conditionJs.contains(" (") || conditionJs.startsWith("(");

    // Always remove AND'ed true
    if (conditionJs.contains("true && ") || conditionJs.contains(" && true")) {
        conditionJs = conditionJs.replace(" && true", "");
        conditionJs = conditionJs.replace("true && ", "");
    }

    // An AND'ed false, or an OR'ed true, or true/false by themselves will always evaluate to the same outcome
    // in a simple condition, so no need for client evaluation (server will handle the evaluation)
    if (!complexCondition && (conditionJs.contains("false &&")) || conditionJs.contains("&& false")
            || conditionJs.contains("|| true") || conditionJs.contains("true ||") || conditionJs.equals("true")
            || conditionJs.equals("false")) {
        conditionJs = "";
    }

    return conditionJs;
}

From source file:org.kuali.rice.krad.uif.view.DefaultExpressionEvaluator.java

/**
 * {@inheritDoc}/*w ww . j  a  va  2  s. com*/
 */
@Override
public Object evaluateExpression(Map<String, Object> evaluationParameters, String expressionStr) {
    Object result = null;

    // if expression contains placeholders remove before evaluating
    if (StringUtils.startsWith(expressionStr, UifConstants.EL_PLACEHOLDER_PREFIX)
            && StringUtils.endsWith(expressionStr, UifConstants.EL_PLACEHOLDER_SUFFIX)) {
        expressionStr = StringUtils.removeStart(expressionStr, UifConstants.EL_PLACEHOLDER_PREFIX);
        expressionStr = StringUtils.removeEnd(expressionStr, UifConstants.EL_PLACEHOLDER_SUFFIX);
    }

    try {
        Expression expression = retrieveCachedExpression(expressionStr);

        if (evaluationParameters != null) {
            evaluationContext.setVariables(evaluationParameters);
        }

        result = expression.getValue(evaluationContext);
    } catch (Exception e) {
        LOG.error("Exception evaluating expression: " + expressionStr);
        throw new RuntimeException("Exception evaluating expression: " + expressionStr, e);
    }

    return result;
}

From source file:org.kuali.rice.krad.uif.view.History.java

/**
 * Builds the title for the view to display in history (for example breadcrumbs)
 *
 * <p>/*from   w w w .j a  va2 s. c  o  m*/
 * Retrieves the viewLabelFieldPropertyName from the view if configured, otherwise attempts
 * to find the title attribute for the default data object. If view label property is found the
 * corresponding property value is retrieved and appended to the title for the view
 * </p>
 *
 * TODO: Possibly move so it can be used for the actual view title, not just history
 *
 * @param form - form instance containing the view and view data
 * @return String title string to use
 */
protected String buildViewTitle(UifFormBase form) {
    View view = form.getView();
    String title = view.getTitle();

    // may move this into view logic instead in the future if it is required for the view's title (not just breadcrumb)
    // if so remove this and just use getTitle - this logic would be in performFinalize instead
    String viewLabelPropertyName = view.getViewLabelFieldPropertyName();

    // if view label property name given, try to retrieve the title attribute for the main data object
    if (StringUtils.isBlank(viewLabelPropertyName)) {
        Class<?> dataObjectClass;
        if (StringUtils.isNotBlank(view.getDefaultBindingObjectPath())) {
            dataObjectClass = ObjectPropertyUtils.getPropertyType(form, view.getDefaultBindingObjectPath());
        } else {
            dataObjectClass = view.getFormClass();
        }

        DataObjectMetaDataService mds = KRADServiceLocatorWeb.getDataObjectMetaDataService();
        if (dataObjectClass != null) {
            viewLabelPropertyName = mds.getTitleAttribute(dataObjectClass);
        }
    }

    String viewLabelPropertyPath = "";
    if (StringUtils.isNotBlank(viewLabelPropertyName)) {
        // adjust binding prefix
        if (!viewLabelPropertyName.startsWith(UifConstants.NO_BIND_ADJUST_PREFIX)) {
            if (StringUtils.isNotBlank(view.getDefaultBindingObjectPath())) {
                viewLabelPropertyPath = view.getDefaultBindingObjectPath() + "." + viewLabelPropertyName;
            }
        } else {
            viewLabelPropertyPath = StringUtils.removeStart(viewLabelPropertyName,
                    UifConstants.NO_BIND_ADJUST_PREFIX);
        }
    } else {
        // attempt to get title attribute
        Class<?> dataObjectClass;
        if (StringUtils.isNotBlank(view.getDefaultBindingObjectPath())) {
            dataObjectClass = ViewModelUtils.getObjectClassForMetadata(view, form,
                    view.getDefaultBindingObjectPath());
        } else {
            dataObjectClass = view.getFormClass();
        }

        DataObjectMetaDataService mds = KRADServiceLocatorWeb.getDataObjectMetaDataService();
        if (dataObjectClass != null) {
            String titleAttribute = mds.getTitleAttribute(dataObjectClass);
            if (StringUtils.isNotBlank(titleAttribute)) {
                viewLabelPropertyPath = view.getDefaultBindingObjectPath() + "." + titleAttribute;
            }
        }
    }

    Object viewLabelPropertyValue = null;
    if (StringUtils.isNotBlank(viewLabelPropertyPath)
            && ObjectPropertyUtils.isReadableProperty(form, viewLabelPropertyPath)) {
        viewLabelPropertyValue = ObjectPropertyUtils.getPropertyValue(form, viewLabelPropertyPath);
    }

    String titleAppend = "";
    if (viewLabelPropertyValue != null) {
        titleAppend = viewLabelPropertyValue.toString();
    }

    if (StringUtils.isNotBlank(titleAppend) && view.getAppendOption() != null) {
        if (view.getAppendOption().equalsIgnoreCase(UifConstants.TitleAppendTypes.DASH)) {
            title = title + " - " + titleAppend;
        } else if (view.getAppendOption().equalsIgnoreCase(UifConstants.TitleAppendTypes.PARENTHESIS)) {
            title = title + "(" + titleAppend + ")";
        } else if (view.getAppendOption().equalsIgnoreCase(UifConstants.TitleAppendTypes.REPLACE)) {
            title = titleAppend;
        }
        //else it is none or blank so no title modification will be used
    }

    return title;
}

From source file:org.kuali.rice.krad.uif.widget.RichTable.java

/**
 * Builds column options for sorting/*from  www  . j a  v a 2  s  .com*/
 *
 * @param collectionGroup
 */
protected void buildTableOptions(CollectionGroup collectionGroup) {
    checkMutable(false);

    LayoutManager layoutManager = collectionGroup.getLayoutManager();
    final boolean useServerPaging = collectionGroup.isUseServerPaging();

    if (templateOptions.isEmpty()) {
        setTemplateOptions(new HashMap<String, String>());
    }

    // if sub collection exists, don't allow the table sortable
    if (!collectionGroup.getSubCollections().isEmpty()) {
        setDisableTableSort(true);
    }

    if (!isDisableTableSort()) {
        // if rendering add line, skip that row from col sorting
        if (collectionGroup.isRenderAddLine() && !Boolean.TRUE.equals(collectionGroup.getReadOnly())
                && !((layoutManager instanceof TableLayoutManager)
                        && ((TableLayoutManager) layoutManager).isSeparateAddLine())) {

            templateOptions.put(UifConstants.TableToolsKeys.SORT_SKIP_ROWS,
                    "[" + UifConstants.TableToolsValues.ADD_ROW_DEFAULT_INDEX + "]");
        }

        StringBuilder tableColumnOptions = new StringBuilder("[");

        int colIndex = 0;
        int actionIndex = UifConstants.TableLayoutValues.ACTIONS_COLUMN_RIGHT_INDEX;
        boolean actionFieldVisible = collectionGroup.isRenderLineActions()
                && !Boolean.TRUE.equals(collectionGroup.getReadOnly());

        if (layoutManager instanceof TableLayoutManager) {
            actionIndex = ((TableLayoutManager) layoutManager).getActionColumnIndex();
        }

        if (actionIndex == UifConstants.TableLayoutValues.ACTIONS_COLUMN_LEFT_INDEX && actionFieldVisible) {
            String options = constructTableColumnOptions(colIndex, false, useServerPaging, null, null);
            tableColumnOptions.append(options + ",");
            colIndex++;
        }

        // handle sequence field
        if (layoutManager instanceof TableLayoutManager
                && ((TableLayoutManager) layoutManager).isRenderSequenceField()) {
            Class<?> dataTypeClass = Number.class;

            if (((TableLayoutManager) layoutManager).getSequenceFieldPrototype() instanceof DataField) {
                DataField dataField = (DataField) ((TableLayoutManager) layoutManager)
                        .getSequenceFieldPrototype();
                dataTypeClass = ObjectPropertyUtils.getPropertyType(collectionGroup.getCollectionObjectClass(),
                        dataField.getPropertyName());
                // check to see if field has custom sort type
                if (dataField.getSortAs() != null && dataField.getSortAs().length() > 0) {
                    if (dataField.getSortAs().equals(UifConstants.TableToolsValues.DATE)) {
                        dataTypeClass = java.sql.Date.class;
                    } else if (dataField.getSortAs().equals(UifConstants.TableToolsValues.NUMERIC)) {
                        dataTypeClass = Number.class;
                    } else if (dataField.getSortAs().equals(UifConstants.TableToolsValues.STRING)) {
                        dataTypeClass = String.class;
                    }
                }
            }

            // don't allow sorting of sequence field - why?
            // auto sequence column is never sortable
            tableColumnOptions.append("{" + sortable(false) + "," + sortType(getSortType(dataTypeClass)) + ","
                    + sortDataType(UifConstants.TableToolsValues.DOM_TEXT) + mData(useServerPaging, colIndex)
                    + "," + targets(colIndex) + "},");
            colIndex++;

            if (actionIndex == 2 && actionFieldVisible) {
                String options = constructTableColumnOptions(colIndex, false, useServerPaging, null, null);
                tableColumnOptions.append(options + ",");
                colIndex++;
            }
        }

        // skip select field if enabled
        if (collectionGroup.isIncludeLineSelectionField()) {
            String options = constructTableColumnOptions(colIndex, false, useServerPaging, null, null);
            tableColumnOptions.append(options + ",");
            colIndex++;
        }

        // if data dictionary defines aoColumns, copy here and skip default sorting/visibility behaviour
        if (!StringUtils.isEmpty(templateOptions.get(UifConstants.TableToolsKeys.AO_COLUMNS))) {
            // get the contents of the JS array string
            String jsArray = templateOptions.get(UifConstants.TableToolsKeys.AO_COLUMNS);
            int startBrace = StringUtils.indexOf(jsArray, "[");
            int endBrace = StringUtils.lastIndexOf(jsArray, "]");
            tableColumnOptions.append(StringUtils.substring(jsArray, startBrace + 1, endBrace) + ",");

            if (actionFieldVisible && (actionIndex == -1 || actionIndex >= colIndex)) {
                String options = constructTableColumnOptions(colIndex, false, useServerPaging, null, null);
                tableColumnOptions.append(options);
            } else {
                tableColumnOptions = new StringBuilder(
                        StringUtils.removeEnd(tableColumnOptions.toString(), ","));
            }

            tableColumnOptions.append("]");
            templateOptions.put(UifConstants.TableToolsKeys.AO_COLUMNS, tableColumnOptions.toString());
        } else if (!StringUtils.isEmpty(templateOptions.get(UifConstants.TableToolsKeys.AO_COLUMN_DEFS))
                && forceAoColumnDefsOverride) {
            String jsArray = templateOptions.get(UifConstants.TableToolsKeys.AO_COLUMN_DEFS);
            int startBrace = StringUtils.indexOf(jsArray, "[");
            int endBrace = StringUtils.lastIndexOf(jsArray, "]");
            tableColumnOptions.append(StringUtils.substring(jsArray, startBrace + 1, endBrace) + ",");

            if (actionFieldVisible && (actionIndex == -1 || actionIndex >= colIndex)) {
                String options = constructTableColumnOptions(colIndex, false, useServerPaging, null, null);
                tableColumnOptions.append(options);
            } else {
                tableColumnOptions = new StringBuilder(
                        StringUtils.removeEnd(tableColumnOptions.toString(), ","));
            }

            tableColumnOptions.append("]");
            templateOptions.put(UifConstants.TableToolsKeys.AO_COLUMN_DEFS, tableColumnOptions.toString());
        } else if (layoutManager instanceof TableLayoutManager) {
            List<Field> rowFields = ((TableLayoutManager) layoutManager).getFirstRowFields();

            // build column defs from the the first row of the table
            for (Component component : rowFields) {
                if (actionFieldVisible && colIndex + 1 == actionIndex) {
                    String options = constructTableColumnOptions(colIndex, false, useServerPaging, null, null);
                    tableColumnOptions.append(options + ",");
                    colIndex++;
                }

                // for FieldGroup, get the first field from that group
                if (component instanceof FieldGroup) {
                    component = ((FieldGroup) component).getItems().get(0);
                }

                if (component instanceof DataField) {
                    DataField field = (DataField) component;

                    // if a field is marked as invisible in hiddenColumns, append options and skip sorting
                    if (getHiddenColumns() != null && getHiddenColumns().contains(field.getPropertyName())) {
                        tableColumnOptions.append("{" + visible(false) + "," + mData(useServerPaging, colIndex)
                                + targets(colIndex) + "},");
                    } else if (getSortableColumns() != null && !getSortableColumns().isEmpty()) {
                        // if specified as a column as sortable then add it
                        if (getSortableColumns().contains(field.getPropertyName())) {
                            tableColumnOptions
                                    .append(getDataFieldColumnOptions(colIndex, collectionGroup, field) + ",");
                        } else { // else designate it as not sortable
                            tableColumnOptions.append("{" + sortable(false) + ","
                                    + mData(useServerPaging, colIndex) + targets(colIndex) + "},");
                        }
                    } else { // sortable columns not defined
                        String options = getDataFieldColumnOptions(colIndex, collectionGroup, field);
                        tableColumnOptions.append(options + ",");
                    }
                    colIndex++;
                } else if (component instanceof MessageField) {
                    if (component.getDataAttributes() != null && UifConstants.RoleTypes.ROW_GROUPING
                            .equals(component.getDataAttributes().get(UifConstants.DataAttributes.ROLE))) {
                        // Grouping column is never shown, so skip
                        tableColumnOptions.append("{" + visible(false) + "," + mData(useServerPaging, colIndex)
                                + targets(colIndex) + "},");
                    } else {
                        String options = constructTableColumnOptions(colIndex, true, useServerPaging,
                                String.class, UifConstants.TableToolsValues.DOM_TEXT);
                        tableColumnOptions.append(options + ",");
                    }
                    colIndex++;
                } else if (component instanceof LinkField) {
                    LinkField linkField = (LinkField) component;

                    Class<?> dataTypeClass = String.class;
                    // check to see if field has custom sort type
                    if (linkField.getSortAs() != null && linkField.getSortAs().length() > 0) {
                        if (linkField.getSortAs().equals(UifConstants.TableToolsValues.DATE)) {
                            dataTypeClass = java.sql.Date.class;
                        } else if (linkField.getSortAs().equals(UifConstants.TableToolsValues.NUMERIC)) {
                            dataTypeClass = Number.class;
                        } else if (linkField.getSortAs().equals(UifConstants.TableToolsValues.STRING)) {
                            dataTypeClass = String.class;
                        }
                    }

                    String options = constructTableColumnOptions(colIndex, true, useServerPaging, dataTypeClass,
                            UifConstants.TableToolsValues.DOM_TEXT);
                    tableColumnOptions.append(options + ",");
                    colIndex++;
                } else {
                    String options = constructTableColumnOptions(colIndex, false, useServerPaging, null, null);
                    tableColumnOptions.append(options + ",");
                    colIndex++;
                }
            }

            if (actionFieldVisible && (actionIndex == -1 || actionIndex >= colIndex)) {
                String options = constructTableColumnOptions(colIndex, false, useServerPaging, null, null);
                tableColumnOptions.append(options);
            } else {
                tableColumnOptions = new StringBuilder(
                        StringUtils.removeEnd(tableColumnOptions.toString(), ","));
            }

            // merge the aoColumnDefs passed in
            if (!StringUtils.isEmpty(templateOptions.get(UifConstants.TableToolsKeys.AO_COLUMN_DEFS))) {
                String origAoOptions = templateOptions.get(UifConstants.TableToolsKeys.AO_COLUMN_DEFS).trim();
                origAoOptions = StringUtils.removeStart(origAoOptions, "[");
                origAoOptions = StringUtils.removeEnd(origAoOptions, "]");
                tableColumnOptions.append("," + origAoOptions);
            }

            tableColumnOptions.append("]");
            templateOptions.put(UifConstants.TableToolsKeys.AO_COLUMN_DEFS, tableColumnOptions.toString());
        }
    }
}