alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lift Framework example source code file (StringHelpers.scala)

This example Lift Framework source code file (StringHelpers.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lift Framework tags/keywords

char, goodsb, int, int, list, list, map, nil, nil, regex, security, string, string, stringhelpers, superliststring, superstring

The Lift Framework StringHelpers.scala source code

/*
 * Copyright 2006-2011 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.liftweb 
package util 

import java.security.SecureRandom
import java.util.regex._
import java.lang.Character._
import java.lang.{StringBuilder => GoodSB}
import scala.xml.NodeSeq
import common._

object StringHelpers extends StringHelpers

/**
 * Utility methods for manipulating strings.
 */
trait StringHelpers {

  /** random numbers generator */
  private val _random = new SecureRandom

  /**
   * If str is surrounded by quotes it return the content between the quotes
   */
  def unquote(str: String) = {
    if (str != null && str.length >= 2 && str.charAt(0) == '\"' && str.charAt(str.length - 1) == '\"')
      str.substring(1, str.length - 1)
    else
      str
  }

  /**
   * Splits a string of the form <name1=value1, name2=value2, ... > and unquotes the quoted values.
   * The result is a Map[String, String]
   */
  def splitNameValuePairs(props: String): Map[String, String] = {
    val list = props.split(",").toList.map(in => {
      val pair = in.roboSplit("=")
       (pair(0), unquote(pair(1)))
    })
    val map: Map[String, String] = Map.empty

    (map /: list)((m, next) => m + (next))
  }

  /**
   * Replaces the value found in a string surrounded by <%= ... %> by a replacement according to the value found in the subst Map.<p/>
   * Throws an exception if no correspondance can be found.
   *
   * @param msg string where replacements should be done
   * @param subst map of [regular expression with groups, replacement]
   */
  def processString(msg: String, subst: Map[String, String]): String = {
    val pattern = Pattern.compile("\\<\\%\\=([^\\%]*)\\%\\>")
    val m = pattern.matcher(msg)
    val ret = new StringBuffer
    while (m.find) {
      m.appendReplacement(ret, subst(m.group(1).trim))
    }
    m.appendTail(ret)
    ret.toString
  }
  
 /**
   * Turn a string of format "FooBar" into snake case "foo_bar"
   * 
   * Note: snakify is not reversible, ie. in general the following will _not_ be true:
   * 
   * s == camelify(snakify(s))
   * 
   * @return the underscored string
   */
  def snakify(name : String) = name.replaceAll("([A-Z]+)([A-Z][a-z])", "$1_$2").replaceAll("([a-z\\d])([A-Z])", "$1_$2").toLowerCase

  
  /**
   * Turns a string of format "foo_bar" into camel case "FooBar"
   *
   * Functional code courtesy of Jamie Webb (j@jmawebb.cjb.net) 2006/11/28
   * @param name the String to CamelCase
   *
   * @return the CamelCased string
   */
  def camelify(name : String): String = {
    def loop(x : List[Char]): List[Char] = (x: @unchecked) match {
      case '_' :: '_' :: rest => loop('_' :: rest)
      case '_' :: c :: rest => Character.toUpperCase(c) :: loop(rest)
      case '_' :: Nil => Nil
      case c :: rest => c :: loop(rest)
      case Nil => Nil
    }
    if (name == null)
    ""
    else
    loop('_' :: name.toList).mkString
  }

  /**
   * Turn a string of format "foo_bar" into camel case with the first letter in lower case: "fooBar"
   * This function is especially used to camelCase method names.
   *
   * @param name the String to CamelCase
   *
   * @return the CamelCased string
   */
  def camelifyMethod(name: String): String = {
    val tmp: String = camelify(name)
    if (tmp.length == 0)
    ""
    else
    tmp.substring(0,1).toLowerCase + tmp.substring(1)
  }
  /**
   * Capitalize every "word" in the string. A word is either separated by spaces or underscores.
   * @param in string to capify
   * @return the capified string
   */
  def capify(in: String): String = {
    val tmp = ((in match {
      case null => ""
      case s => s
    }).trim match {
      case "" => "n/a"
      case s => s
    }).toLowerCase
    val sb = new GoodSB
    capify(tmp, 0, 250, false, false, sb)
    sb.toString
  }

  /**
   * Replaces the groups found in the msg string with a replacement according to the value found in the subst Map
   * @param msg string where replacements should be done
   * @param subst map of [regular expression with groups, replacement]
   */
  private def capify(in: String, pos: Int, max: Int, lastLetter: Boolean, lastSymbol: Boolean, out: GoodSB): Unit = {
    if (pos >= max || pos >= in.length) return
    else {
      in.charAt(pos) match {
        case c if Character.isDigit(c) => out.append(c); capify(in, pos + 1, max, false, false, out)
        case c if Character.isLetter(c) => out.append(if (lastLetter) c else Character.toUpperCase(c)) ; capify(in, pos + 1, max, true, false, out)
        case c if (c == ' ' || c == '_') && !lastSymbol => out.append(c) ; capify(in, pos + 1, max, false, true, out)
        case _ => capify(in, pos + 1, max, false, true, out)
      }
    }
  }

  /**
   * Remove all the characters from a string exception a-z, A-Z, 0-9, and '_'
   * @return the cleaned string and an empty string if the input is null
   */
  def clean(in : String) =  if (in == null) "" else in.replaceAll("[^a-zA-Z0-9_]", "")

  /**
   * Create a random string of a given size.  5 bits of randomness per character
   * @param size size of the string to create. Must be a positive integer.
   * @return the generated string
   */
  def randomString(size: Int): String = {
    def addChar(pos: Int, lastRand: Int, sb: GoodSB): GoodSB = {
      if (pos >= size) sb
      else {
        val randNum = if ((pos % 6) == 0) {
          _random.synchronized(_random.nextInt)
        } else {
          lastRand
        }

        sb.append((randNum & 0x1f) match {
          case n if n < 26 => ('A' + n).toChar
          case n => ('0' + (n - 26)).toChar
        })
        addChar(pos + 1, randNum >> 5, sb)
      }
    }
    addChar(0, 0, new GoodSB(size)).toString
  }

  /**
   * Create the unicode value of a character
   * @param in character
   * @return the unicode value as a string starting by \\u
   */
  def escChar(in: Char): String = {
    val ret = Integer.toString(in.toInt, 16)
    "\\u"+("0000".substring(ret.length)) + ret
  }

  /**
   * Split a string separated by a point or by a column in 2 parts. Uses default values if only one is found or if no parts are found
   * @param in string to split
   * @param first default value for the first part if no split can be done
   * @param second default value for the second part if one or less parts can be found
   * @return a pair containing the first and second parts
   */
  def splitColonPair(in: String, first: String, second: String): (String, String) = {
    (in match {
      case null => List("")
      case s if s.indexOf(".") != -1 => s.roboSplit("\\.")
      case s => s.roboSplit(":")
    }) match {
      case f :: s :: _ => (f,s)
      case f :: Nil => (f, second)
      case _ => (first, second)
    }
  }

  /** @return an Empty can if the node seq is empty and a full can with the NodeSeq text otherwise */
  implicit def nodeSeqToOptionString(in: NodeSeq): Box[String] = if (in.length == 0) Empty else Full(in.text)

  /**
   * Parse a string and return the Long value of that string.<p/>
   * The string can start with '-' if it is a negative number or '+' for a positive number
   * @return the Long value of the input String
   */
  def parseNumber(tin: String): Long = {
    def cToL(in: Char) = in.toLong - '0'.toLong
    def p(in: List[Char]) = in.takeWhile(isDigit).foldLeft(0L)((acc,c) => (acc * 10L) + cToL(c))

    if (tin eq null) 0L
    else {
      tin.trim.toList match {
        case '-' :: xs => -p(xs)
        case '+' :: xs => p(xs)
        case xs => p(xs)
      }
    }
  }

  /**
   * Creates a List of Strings from two Strings
   */
  def listFromStrings(s1: String, s2: String): List[String] = List(s1, s2)

  /**
   * Creates a List of Strings from a List[String] and a String
   */
  def listFromListAndString(lst: List[String], s: String): List[String] =
    lst ::: List(s)

  /**
   * Split a string according to a separator
   * @param sep a regexp to use with the String::split method
   * @return a list of trimmed parts whose length is > 0
   */
  def roboSplit(what: String, sep: String): List[String] = 
    what match {
      case null => Nil
      case s => s.split(sep).toList.map(_.trim).filter(_.length > 0)
    }

  /**
   * Faster than roboSplit... this method splits Strings at a given
   * character
   */
  def charSplit(what: String, sep: Char): List[String] = 
    what match {
      case null => Nil
      case str => {
        val ret = new scala.collection.mutable.ListBuffer[String]
        
        val len = str.length
        var pos = 0
        var lastPos = 0
        
        while (pos < len) {
          if (str.charAt(pos) == sep) {
            if (pos > lastPos) {
              val ns = str.substring(lastPos, pos)
              ret += ns
            }

            lastPos = pos + 1
          }
          pos += 1
        }

        if (pos > lastPos) {
          ret += str.substring(lastPos, pos)
        }

        ret.toList
      }
    }

  /**
   * Split a string in 2 parts at the first place where a separator is found
   * @return a List containing a pair of the 2 trimmed parts
   */
  def splitAt(what: String, sep: String): List[(String, String)] = {
    if (null eq what)
      return Nil
    else
      what.indexOf(sep) match {
        case -1 => Nil
        case n => List((what.substring(0, n).trim, what.substring(n + sep.length).trim))
      }
  }

  /**
   * Encode the string to be including in JavaScript, replacing '\' or '\\' or non-ASCII characters by their unicode value
   * @return the encoded string inserted into quotes
   */
  def encJs(what: String): String = {
    if (what eq null) "null"
    else {
      val len = what.length
      val sb = new GoodSB(len * 2)
      sb.append('"')
      var pos = 0
      while (pos < len) {
        what.charAt(pos) match {
          case c @ ('\\' | '\'') => sb.append(escChar(c))
          case '"' => sb.append("\\\"")
          case c if c < ' ' || c > '~' || c == ']' || c.toInt >= 127 => sb.append(escChar(c))
          case c => sb.append(c)
        }
        pos += 1
      }
      sb.append('"')
      sb.toString
    }
  }

  /**
   * Add commas before the last 3 characters
   * @return the string with commas
   */
  def commafy(what: String): String = {
    if (null eq what) null
    else {
      val toDo = what.toList.reverse
      
      def commaIt(in: List[Char]): List[Char] = in match {
        case Nil => in
        case x :: Nil => in
        case x1 :: x2 :: Nil => in
        case x1 :: x2 :: x3 :: Nil => in
        case x1 :: x2 :: x3 :: xs => x1 :: x2 :: x3 :: ',' :: commaIt(xs)
      }
      commaIt(toDo).reverse.mkString("")
    }
  }


  /** @return a SuperString with more available methods such as roboSplit or commafy */
  implicit def stringToSuper(in: String): SuperString = new SuperString(in)

  /** @return a SuperString with more available methods such as roboSplit or commafy */
  implicit def listStringToSuper(in: List[String]): SuperListString = new SuperListString(in)


  /**
   * Test for null and return either the given String if not null or the empty String.
   */
  def emptyForNull(s: String) = if (s != null) s else ""
}

/**
 * A class that allows chaining "foo" / "bar" / "baz"
 */
final class SuperListString(lst: List[String]) {
  /**
   * Add the / method that allows chaining "foo" / "bar" / "baz"
   */
  def /(str: String): List[String] = lst ::: List(str)
}

/**
 * The SuperString class adds functionalities to the String class
 */
final case class SuperString(what: String) {
  /**
   * Split a string according to a separator
   * @param sep a regexp to use with the String::split method
   * @return a list of trimmed parts whose length is > 0
   */
  def roboSplit(sep: String): List[String] = Helpers.roboSplit(what, sep)
  
  /**
   * Faster than roboSplit... this method splits Strings at a given
   * character
   */
  def charSplit(sep: Char): List[String] = Helpers.charSplit(what, sep)

  /**
   * Split a string in 2 parts at the first place where a separator is found
   * @return a List containing a pair of the 2 trimmed parts
   */
  def splitAt(sep: String): List[(String, String)] = Helpers.splitAt(what, sep)

  /**
   * Encode the string to be including in JavaScript, replacing '\' or '\\' or non-ASCII characters by their unicode value
   * @return the encoded string inserted into quotes
   */
  def encJs: String = Helpers.encJs(what)

  /**
   * Add commas before the last 3 characters
   * @return the string with commas
   */
  def commafy: String = Helpers.commafy(what)

  /**
   * Create a List of Strings using the / method so you
   * can write "foo" / "bar"
   */
  def /(other: String): List[String] = List(what, other)

  

  
}

Other Lift Framework examples (source code examples)

Here is a short list of links related to this Lift Framework StringHelpers.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.