Extreme Java When vanilla Java is not enough

10May/101

sed-like function in scala

It was a long time without using Scala, but I had a problem that it solved like a charm. I need to edit a huge file with one XML per line, replacing "b" for "bb" (i.e. duplicate a tag). I could do it with a single SED command, but, on an Windows box, I used this scala script:

def solveMyProblem = {
  import java.io.File
  import scala.io.Source
 
  Source.fromFile(new File("path-to-file"))
    .getLines()
    .map {
      _.replaceAll("(<a>(.*)</a>)", "$1<c>$2</c>");
    }
    .foreach {
      Console.println(_)
    }
}

I'm still using Scala 2.7, but this got my problem solved. It was easy to test - instead of thousands of lines on my Console, I put a ".take(10)" and I got something like Linux's "sed | head".

BTW, I guess it could be improved even more, but I don't have time to do that too.

Tagged as: , , 1 Comment
12Nov/090

Customizing LiftWeb’s error/warning/notice messages

After some CRUD experiments with LiftWeb, I'm really in love with the "view first" paradigm. Specially because the XHTML bindings are very webdesigner-friendly.

One big limitation is the <lift:msgs> snippet - it produces a mandatory "Error" title. This obligatory text is unacceptable when developing enterprise applications. Hopefully, there's an workaround: you can create a snippet named "Msgs" with a "render" method. Your snippet will "override" the builtin (without overriding the class), like this:

package mypkg.snippets
class Msgs {
  def msgs(cls : String, ms : List[NodeSeq]) = ms match {
    case Nil => Nil
    case x => <div class={ cls }>{ ms.flatMap(m => <p>{ m }</p>) }</ul>
  }
  def render(xml : NodeSeq) : NodeSeq =
    <div id={ LiftRules.noticesContainerId }>
      { msgs("msgError", noIdMessages(errors)) }
      { msgs("msgWarning", noIdMessages(warnings)) }
      { msgs("msgNotice", noIdMessages(notices)) }
    </div>
}

This little snippet will emit messages using <div> and <p> instead of <ul> and <li> (with that hardcoded title block). And, since you have the control over the snippet, you can put stub code inside <lift:msgs/> and allow your webdesigner use their favorite WYSIWYG editor:

<lift:msgs>
  <div class="msgError">
    <p>name must have 3 charactes</p>
  </div>
</lift:msgs>
Tagged as: , , No Comments
18Sep/090

Copying html attributes on Lift bindings

Since Java and Scala are complementary, I will post Scala-related stuff here, too (without creating a new blog).

Today's tip refers to Lift (Scala's JavaEE/Rails/Grails/Django). Suppose your webdesigner gives you this XHTML:

<input type="text" class="x" style="width: 100px;"/>

When you bind this using Lift, one of possible solutions is surround it with a tag:

<mybind:myfield><input type="text" class="x" style="width: 100px;"/></mybind:myfield>

Please notice I put it without spaces or newlines between "mybind:myfield" and "input" - this will be important later.

I prefer this way because this XHTML can be opened in other applications, like Firefox and Dreamweaver, making life easier for the webdesigner.

Then, if I bind it using old mama's recipe:

bind("mybind", form, "myfield" -> myfield.toForm)

Lift will remove my "input" tag and replace it - destroying "class" and "style". To solve this, I merge "toForm" tag with original attributes:

def merge(form : => Box[NodeSeq])(input : NodeSeq) : NodeSeq = {
  var in = input.first
  var attrs = form.open_!.first.attributes
 
  new Elem(in.prefix, in.label,
      in.attributes append attrs,
      in.scope, Group(in.child))
}
bind("mybind", form,
    FuncBindParam("myfield", merge(myfield.toForm)))

Function "merge" takes the form and returns a function that receives the original XHTML and translates it into XHTML with Lift's attributes ("id", "name", "lift:gc", etc). I guess I can improve it somehow, but works great. And, since I'm keeping only the first child of source XHTML, you need to keep "bind" and "input" together (as I said before).

I know I can use a map function to ignore whitespaces, but I'll leave it as an later exercise (for you and for me, too).

16Sep/090

Mandelbrot with Scala and Java

I'm testing if Scala can be used to increase productivity here. Pretty nice language: as powerful as Ruby and JVM-compatible. To improve my skills, I decided to implement Mandelbrot on Scala, using Swing's BufferedImage to show the image. Very simple, indeed. The code is:

import java.awt.image.BufferedImage
import javax.swing.ImageIcon
import javax.swing.JFrame
import javax.swing.JLabel
object Mandelbrot extends Application {
  case class Complex(r : Double, i : Double) {
    def +(b : Complex) = Complex(r + b.r, i + b.i)
    def *(b : Complex) = Complex(r * b.r - i * b.i, r * b.i + i * b.r)
    def insideM = (r * r + i * i) < (2 * 2)
  }
 
  implicit def start = Complex(0, 0)
 
  def pc(z : Complex, c : Complex) : Complex = z * z + c
 
  def iter(qtd : Int, c : Complex)(implicit z : Complex) : Int = {
    if (qtd == 0) 0
    else if (!z.insideM) qtd
    else iter(qtd - 1, c)(pc(z, c))
  }
 
  val scale = 1.0
  def pixToComplex(x : Double, y : Double) =
    Complex(((x / 640.0) * 3.0 - 2.0) / scale,
        ((y / 480.0) * 2.0 - 1.0) / scale)
 
  def raster(f : (Int, Int, Int) => Unit) = {
    for (y <- 0 until 480; x <- 0 until 640) {
      f(x, y, iter(1024, pixToComplex(x, y)))
    }
  }
 
  def qtdToColor(c : Int) = List(c / 4, c / 4, c / 4).toArray
 
  val frame = new JFrame("Mandelbrot")
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
 
  val lbl = new JLabel
  frame.add(lbl)
  frame.setSize(640, 480)
  frame.setVisible(true)
 
  val img = new BufferedImage(640, 480, BufferedImage.TYPE_3BYTE_BGR)
  raster((x, y, c) => img.getRaster.setPixel(x, y, qtdToColor(c)))
  lbl.setIcon(new ImageIcon(img))
}

Since I'm new to Scala, I guess it's not the best solution. Nevertheless, I have an "Yes-we-can" feeling, because this code have some Scala features, like higher-order functions and (possibly) tail recursion. And, of course, I felt productive implementing Mandelbrot's recursive algorithm (I got a lot of errors misunderstanding the algorithm, BTW).