Posts Tagged ‘ scala ’

Scala android and actors

Scala expressiveness strikes back !

 

A sample showing iteration between scala actors and android.Activity

Extending activity with a trait  to receive events from another actors, services, or any other source ( listeners , as a observer … )

 
class MainActivity extends Activity 
                      with ActivityUtil 
                      with Reactive { 

    override def onCreate(savedInstanceState: Bundle) { 
        super.onCreate(savedInstanceState) 

        setContentView(R.layout.main) 

        button(R.id.Button01).onClicked { 
            app.actor ! Ping(this) 
        } 
    } 

    onReact { 
        case Pong(count) => onUi { 
            textView(R.id.Label1).setText("Pong -> " + count) 
        } 
    } 
} 

Isn’t she pretty ?

 

  1. ActivityUtil
    • Allow us to access activity components directly
       
      button(R.id.Button01)
  2. Reactive
    • Converts the activity into a scala actor
    • Calling onReact with the desired partialFunctions, allow us to manage the external events
      
      onReact {
          case Pong(count) => onUi {
              textView(R.id.Label1).setText("Pong -> " + count)
          }
      } 

      One problem, onReact resides inside another thread ( the actor one ), so to access components of the view, we must use onUi function

  3. ViewConversions
    • With a bunch of implicit conversions, we can implement Listeners directly with functions
      
      button(R.id.Button01).onClicked {
          app.actor ! Ping(this)
      } 
  4. The application class contains the other actor who returns Pong
    
    
    class App extends Application { 
        val actor = new SampleActor 
    
        override def onCreate(): Unit = { 
            actor.start 
        } 
    } 
    
    
    case class Pong(count: Int) 
    case class Ping(a: Actor) 
    
    class SampleActor extends Actor with L { 
        private var count = 0 
        def act() { 
            loop { 
                receive { 
                    case Ping(a) => { 
                        count = count + 1 
                        a ! Pong(count) 
                    } 
                } 
            } 
        } 
    } 
    


I just remembered why I love scala so much 🙂

 

PD: I used giter8 to get a scala-android template

 g8 gseitz/android-sbt-project 

 

Advertisements

Sample OpenOffice 3 extension with scala 2.8 and sbt

Sample OpenOffice 3 extension with scala and sbt

  • Here’s a small sample of a openoffice 3 extension using scala and sbt
  • Project link: sample scala addon
  • Openoffice devel documentation: DevGuide and sdk samples :

    folder examples/ on openoffice sdk (usually located in /usr/lib/openoffice-dev)
  • I just ported ProtocolHandlerAddon_java to scala and sbt

    under examples/DevelopersGuide/Components/Addons/ProtocolHandlerAddon_java
  • using sbt,
    a little task (create_extension) will help to create the oxt file (with the .xcu files, scala-library jar, manifest …)

    $> sbt
       :> update
       :> compile
       :> package
       :> create_extension
    

Fun with liftweb and jquery dialogs

Here’s a sample of jquery-ui (version 1.8) dialogs in lift,
the code (a little ugly) can be found here : http://github.com/jgoday/liftweb-jquery-dialogs-sample

The sample has two main classes

  • 1: JQueryDialog

    Allow create generic dialogs from templates or with explicit content
    We can create a dialog like this :

    
    new JQueryDialog(<div>Dialog content</div>) {
        override def elementId = "dialog_id"
        override def options = "modal:true" ::
                               "title:'dialog title!'" ::
                               "open: function (event, ui) {alert('dialog is opening!');}" ::
                                super.options
    }
    
    
  • 2: FormDialog
    To create generic dialogs from templates and with default actions (close)

    
    val item = new Item
    def _template: NodeSeq = bind("item",
                TemplateFinder.findAnyTemplate("templates-hidden/item" :: Nil) openOr
                                               <div>{"Cannot find template"}</div>,
                "name" -> item.name.toForm)
    
    val dialog = new FormDialog(true) {
        override def getFormContent = _template
        override def confirmDialog: NodeSeq = SHtml.ajaxSubmit("save",
                () => {println(item);this.closeCmd}) ++ super.confirmDialog
    }
    
    

Scala traits

Really love scala,
traits and the ability of define custom types as interfaces.


type ObjectWithName = {
    def getName: String
}

trait NicePerson[T <: ObjectWithName] {
    def greet: String = {
        "Hello ! My name is %s".format(this.asInstanceOf[ObjectWithName].getName)
    }
}

class Person(name: String) {
    def getName: String = name
}

val peter = new Person("Peter") with NicePerson[Person]
println(peter.greet) // = Hello ! My name is Peter


How nice it is ?

Some references:
http://markthomas.info/blog/?p=92
http://codemonkeyism.com/scala-goodness-structural-typing/

scala dsl to perform sql searches: part 1

Reading designing-internal-dsls-in-scala.html(recommended!)
I come up with the idea of doing some simple scala DSL,
to write and perform SQL searchs using lift-mapper objects.

The result would be something like that:


var find = FIND(Item)
    WITH(ItemType.name AS type_name, ItemResponsible.name as responsible)
    WHEN (
        "type_name" ILIKE _nameVariable,
        "cancelled" IS_NULL,
        OR (
            "responsible" IS_NULL,
            "ItemResponsible.id" EQUALS _getLoggedUserID()
        )
    )
    LIMIT 100 OFFSET 20

...
performSearch(find)

Here’s a sample code



// types
type Condition = (() => Boolean, () => String)
type Operator  = (String, List[Condition])    

def _mergeConditions(operator: Operator): String = {
    var shouldApplyAndOperator = false // ????      

    var sql = ""
    var operatorFilters = ""
    val (operatorSQL, conditions) = operator

    var shouldApplyOperatorFilters = false

    conditions.foreach(cdt => {
        val (condition, filter) = cdt

        if (condition()) {
            val filterValue = shouldApplyOperatorFilters match {
                case true  => " %s (%s) ".format(operatorSQL, filter())
                case _ => " %s ".format(filter())                      
            }                                                          

            operatorFilters += filterValue
            shouldApplyOperatorFilters = true
        }                                    
    })                                       

    if (shouldApplyOperatorFilters) {
        val filterValue = shouldApplyAndOperator match {                        
            case true  => " %s (%s) ".format("AND", operatorFilters)         
  
            case _ => " %s ".format(operatorFilters)                         
  
        }                                                                       
                                                             
        sql += filterValue                                                      
        shouldApplyAndOperator = true                                           
    }                                                                           
                                                             
    sql                                                                         
}                                                                               
                                                             

// Base class to search objects
class Find(obj: String) {      
    private var fields: List[Any]         = List()
    private var operators: List[Operator] = List()

    def toSQL: String = {
        def _getFieldsAsSQL = this.fields.reduceLeft(_ + "," + _)
        def _getTableName = this.obj                             
        def _getOperatorsAsSQL = {                               
            var sql = ""                                         

            this.operators.foreach(op => {
                sql += _mergeConditions(op)
            })                             

            if (sql != "") sql = " WHERE " + sql
            sql                                 
        }                                       

        "SELECT %s FROM %s %s".format(
                _getFieldsAsSQL,      
                _getTableName,        
                _getOperatorsAsSQL)   
    }                                 

    /**
     * Adds a list of conditions around a sql AND operator
     */                                                   
    def AND(conditions: Condition*): Find = {             
        this.operators = ("AND", conditions.toList) :: this.operators
        this                                                         
    }                                                                

    /**
     * Adds a list of conditions around a sql OR operator
     */                                                  
    def OR(conditions: Condition*): Find = {             
        this.operators = ("OR",  conditions.toList) :: this.operators
        this                                                         
    }                                                                

    /**
     * Selects the object with custom fields
     */                                     
    def WITH(fields: Any*): Find = {        
        this.fields = fields.toList ::: this.fields
        this                                       
    }                                              
}                                                  

/** Global operator methods to composite conditions around a find object **/
def AND(conditions: Condition*): Condition = {                              
    (() => true, () => _mergeConditions("AND", conditions.toList))        
 
}                                                                           

def OR(conditions: Condition*): Condition = {
    (() => true, () => _mergeConditions("OR", conditions.toList))
}                                                                

// CONDITIONS AND WRAPPERS

class StaticConditionWrapper(filter: String) extends FunctionConditionWrapper(()
=> filter)
class FunctionConditionWrapper(filter: () => String) {                       
 
    def ALWAYS: Condition = {                                                  
        (() => true, filter)                                                
    }                                                                         
    def IF(condition: () => Boolean): Condition = {                        
        (condition, filter)                                                     
    }
    def IF(value: Boolean): Condition = {
        (() => value, filter)
    }
    def ILIKE(value: String): Condition = {
        (() => value != "", () => " %s ILIKE '%%%s%%' ".format(filter(),
value))
    }
    def IS_NULL: Condition = {
        (() => true, () => " %s IS NULL ".format(filter()))
    }
    def NOT_NULL: Condition = {
        (() => true, () => " %s IS NOT NULL ".format(filter()))
    }
}

implicit def IF(filter: String) = new StaticConditionWrapper(filter)
implicit def IF(filter: () => String) = new FunctionConditionWrapper(filter)


// Object FIND to easy create find objects (FIND("object_name"))
object FIND {
    def apply(obj: String): Find = new Find(obj)
}


The result of evaluting


// TEST
def checkCondition: () =>> Boolean = () => true
def someFilter: () => String = () => " something true"

val f = (
    FIND("ObjectName") WITH(1,2,3,4,5)
    AND (
        someFilter ALWAYS,
        "A" IF true,
        "B" IF checkCondition,
        OR (
            "C" ALWAYS,
            AND (
                "NAME" ILIKE "Pepe",
                "CANCELLED" IS_NULL
            )
        )
    )
)

println(f.toSQL)

is


SELECT 1,2,3,4,5 FROM ObjectName 
    WHERE 
    something true AND (A)  AND (B)  AND
        (  C  OR (   NAME ILIKE '%Pepe%'   AND ( CANCELLED IS NULL )  )  )

really nice 🙂

All filtering is based on

  • Conditions :
    
    type Condition = (() => Boolean, () => String)
    
    sample : (() => {result_of_checking_condition()),
              () => {create_some_sql_filter()})
    

    A couple, containing a function that will decide if the filter applies or not,
    and a function that makes the filter

  • Operators :
    
    type Operator = (String, List[Condition])
    

    Allows to composite conditions and envolves them with a SQL Operator (And/Or)

Logging database changes in lift-mapper

Here is a little trick to log the changed properties
on the lift-mapper objets.

  • First we define a changeLogger trait that extends Mapper

    
    trait ChangeLogger[T <: Mapper[T] ] {
        def checkChanges(obj: T): Unit = {
            if (obj.dirty_?) {
    
                Log.debug("Object " + obj.getSingleton.dbTableName + " has changed")
    
                obj.formFields.foreach(f => {
                    f.dirty_? match {
                        case true => Log.debug(" ---> Property %s was='%s' and now is = '%s'".format(f.name, f.is.toString, f.was.toString))
                    }
                })
            }
        }
    }
    
    

  • Extend LongKeyedMetaMapper (or any other MetaMapper class) to call ChangeLogger checkChanges method after save (or after delete …)

    
    trait ChangeLoggerMetaMapper[T <: LongKeyedMapper[T]] extends LongKeyedMetaMapper[T]
                                                    with ChangeLogger[T] { self : T =>
        override def afterSave: List[(T) => Unit] = checkChanges _ :: super.afterSave
    }
    
    
    
  • Model object

    
    class Item extends LongKeyedMapper[Item] with IdPK
                                             with ChangeLogger[Item] {
        def getSingleton = Item
    
        object name extends MappedString(this, 100) {
            override def validations = valMinLen(1, "Must be not empty") _ ::
                                       valUnique("Name must be unique") _ ::
                                       super.validations
        }
    }
    
    object Item extends Item with ChangeLoggerMetaMapper[Item] {
        def findByName(name: String): List[Item] = {
            Item.findAll(By(Item.name, name))
        }
    }
    
    
    



The code can be found on http://github.com/jgoday/sample_lift_testing

Documentation for lift-mapper (version lift-1.1-M6) http://scala-tools.org/mvnsites/liftweb-1.1-M6/lift-mapper/scaladocs/index.html

Sample list items with lift

Add/Edit/Remove items in lift sample

  • 1- Create the menu in boot

    in src/main/scala/bootstrap/liftweb/Boot.scala

    
    // List items menu
    val itemsMenu = Menu(Loc("Items", "items" :: "index" :: Nil, "List items"))
    
    // Build SiteMap
    val entries = Menu(Loc("Home", List("index"), "Home")) :: itemsMenu :: Nil
    
  • 2- Define the default database
    The properties in src/main/resources/props/default.props with the connection url

    
    db.driver   = org.h2.Driver
    db.url      = jdbc:h2:~/hello_db
    db.user     =
    db.password =
    

    in src/main/scala/bootstrap/liftweb/Boot.scala

    
    
    DB.defineConnectionManager(DefaultConnectionIdentifier, DefaultDBVendor)
    Schemifier.schemify(true, Log.infoF _, Item)
    
    ...
    
    object DefaultDBVendor extends ConnectionManager {
        def newConnection(name: ConnectionIdentifier): Box[Connection] = {
            try {
                val connectionUrl = Props.get("db.url").openOr("") + "?user=" +
                                    Props.get("db.username").openOr("") + "&password=" +
                                    Props.get("db.password").openOr("")
    
                Class.forName(Props.get("db.driver").open_!)
                val dm = DriverManager.getConnection(connectionUrl)
                return Full(dm)
            }
            catch {
                case e: Exception => {
                    Log.error(e.getMessage);
                    return Empty
                }
            }
        }
    
        def releaseConnection(conn: Connection) = conn.close
    }
      
    
  • 3- Create items/index.html
    in src/main/webapp/items/index.html

    
    <lift:surround with="default" at="content">
        <ul>
            <lift:adminItems.list>
                <li>
                    <item:name />
                </li>
            </lift:adminItems.list>
        </ul>
    </lift:surround>
    
    

    and snippet in src/main/scala/com/sample/snippet/AdminItems.scala

    
    package com.sample.snippet
    
    import scala.xml.{NodeSeq, Text}
    
    import net.liftweb.util.{Helpers, Log}
    import Helpers._
    
    import com.sample.model.Item
    
    class AdminItems {
    
        def list(node: NodeSeq): NodeSeq = {
            Item.findAll match {
                case Nil   => Text("There is no items in db")
                case items => items.flatMap(i => bind("item", node, "name" -> {i.name}))
            }
        }
    ...
    }
    
  • 4- Add item form

    create a template for add/edit items in src/main/webapp/templates-hidden/item_form.html,
    we are going to use the same template for edit and add items,
    using TemplateFinder in AdminItems snippet

    
    <fieldset>
        <legend><itemForm:title /></legend>
        <label for="name">Name</label>
    
        <itemForm:name />
        <itemForm:id />
    
        <itemForm:submit />
    </fieldset>
    
    

    we are going to use two requestvars to decide when to display the edit form or the add form

    
        private object ShowAddItem  extends RequestVar[Int](0)
        private object SelectedItem extends RequestVar[Long](0)
    

    declare a showAddItem and showEditItem function in adminItems snippet

    
        def clear = {
            ShowAddItem(0)
            SelectedItem(0)
        }                  
    
        def showAddItem(node: NodeSeq): NodeSeq = {
            ShowAddItem.get match {                
                case 1 => {                        
                    var name = ""                  
                    val template: NodeSeq = TemplateFinder.findAnyTemplate(ITEM_TEMPLATE :: Nil).openOr(<p></p>)                                                                     
                    val content = bind("itemForm", template, "title"  -> Text("New item"),    
                                                              "name"   -> SHtml.text(name, name = _),                                                                                   
                                                              "id"     -> Text(""),           
                                                              "submit" -> SHtml.submit("save", () => addItem(name)),                                                                    
                                                              "close"  -> SHtml.link("index", () => clear, Text("close")))                                                              
    
                    <div>{content}</div>
                }                       
                case _ => SHtml.link("index", () => ShowAddItem(1), <p>Add</p>)
            }                                                                  
        }                                                                      
    
        def showEditItem(node: NodeSeq): NodeSeq = {
            if (SelectedItem.get > 0) {             
                var id = SelectedItem.get           
                val item = Item.find(id).open_!     
    
                var name = item.name.is
    
                val template = TemplateFinder.findAnyTemplate(ITEM_TEMPLATE :: Nil).openOr(<p></p>) 
                val content  = bind("itemForm", template, "title"  -> Text("Edit item"),      
                                                          "name"   -> SHtml.text(name, name = _),                                                                                       
                                                          "id"     -> Html.hidden(() => {id = id}),                                                                                    
                                                          "submit" -> SHtml.submit("save", () => saveItem(id, name)),                                                                   
                                                          "close"  -> SHtml.link("index", () => clear, Text("close")))                                                                  
    
                <div>{content}</div>
            }                       
            else {                  
                <div></div>
            }                       
        }           
    

    Now we can call the showEditItem and showAddItem snippets functions in items/index view

    
    <lift:surround with="default" at="content">
        <ul>
            <lift:adminItems.list>
                <li>
                    <item:name />
    
                    <item:edit />
                    <item:remove />
                </li>
            </lift:adminItems.list>
        </ul>
    
        <lift:adminItems.showAddItem  form="POST" />
        <lift:adminItems.showEditItem form="POST" />
    </lift:surround>
    
    

    The attribute form=”POST” on the snippet will create a form with method=”POST” automatically arround the snippet content.

    And that’s it, a simple list with liftweb.
    The code can be found on http://github.com/jgoday/sample_lift_testing