Here it is

import net.liftweb.http._
import net.liftweb.util._

import net.liftweb.sitemap._
import net.liftweb.sitemap.Loc._

import scala.xml._

object ParamsLoc {
  def apply(name: String, uri: Uri, params: LocStuff*) = new ParamsLoc(name,
uri, Hidden :: params.toList)

  class ParamsLink(uri: Uri) extends Link[NullLocParams](List(), false) {
    override def isDefinedAt(req: RequestState): Boolean = req.path.partPath
== List(uri.templateName)
  }

  implicit def strToUriString(in: String): UriString = UriString(in)
}

class ParamsLoc(theName: String, uri: Uri, params: List[LocStuff]) extends
Loc[NullLocParams] {
  def name = theName
  def link: Loc.Link[NullLocParams] = new ParamsLoc.ParamsLink(uri)

  def text: Loc.LinkText[NullLocParams] = null // No link?
  def defaultParams: Can[NullLocParams] = Full(NullLocParams)

  def stuff: List[LocStuff] = params

  override def rewrite: LocRewrite = Full(new
PartialFunction[RewriteRequest, (RewriteResponse, NullLocParams)] {
    override def isDefinedAt(req: RewriteRequest): Boolean =
uri.matches(req.path.partPath)
    override def apply(req: RewriteRequest): (RewriteResponse,
NullLocParams) =
      (RewriteResponse(List(uri.templateName),
uri.params(req.path.partPath)), NullLocParams)
  })
}


trait UriElement {
  def /(that: UriElement): Uri = Uri(this :: that :: Nil)
}

case class UriString(str: String) extends UriElement

case class Param(name: String) extends UriElement {
  var isOptional = false
  def optional = {isOptional = true; this}
}

case class Uri(elements: List[UriElement]) extends UriElement {
  override def /(that: UriElement): Uri = Uri(this.elements ::: List(that))

  def templatePath: List[String] = for (UriString(str) <- elements) yield
str
  def templateName: String = templatePath.mkString("", "-", "")

  def params(path: List[String]): Map[String, String] = Map((
    for ((Param(name), value) <- elements zip path) yield name -> value
  ):_*)

  def matches(path: List[String]): Boolean = {
    val lastParamIsOptional = elements.last match {
      case p: Param => p.isOptional
      case _ => false
    }
    if (path.length == elements.length || lastParamIsOptional &&
elements.length == path.length+1)
      List.forall2(elements, path)((el, pathPart) => el match {
        case el: UriString => el.str == pathPart
        case el: Param => true
        case _ => false
      })
    else
      false
  }
}

On Mon, Oct 27, 2008 at 4:45 PM, Tim Perrett <[EMAIL PROTECTED]> wrote:

>
> Hey Sasha,
>
> Thanks for your input - if your willing to post the code that would be
> brilliant :)
>
> Cheers, Tim
>
> On Oct 26, 11:50 pm, "Sasha Kazachonak" <[EMAIL PROTECTED]> wrote:
> > Unfortunately, I don't fully understand how the current Loc stuff is
> > supposed to be used. I like many things in lift a lot, but I want
> > first-class friendly URL's support. So I wrote it. It is used like this:
> >
> > val entries =
> >   Menu(Loc("index", List("index"), "Main")) ::
> >   ...
> >   Menu(ParamsLoc("user-profile", "user"/Param("user")) ::
> >   Menu(ParamsLoc("user-actions", "user"/Param("user")/"actions")) ::
> >   Menu(ParamsLoc("user-message", "user
> > "/Param("user")/"message"/Param("to").optional))) :: Nil
> > LiftRules.setSiteMap(SiteMap(entries:_*))
> >
> > Of course, I still use LocStuff:
> > Menu(ParamsLoc("one", "two"/Param("three"), If(Everything.right _,
> > S.??("no-no")))))
> >
> > Then in a snippet I can use params like this:
> >   def showProfile = (for (
> >     id <- S.param("user");
> >     user <- User.findByKey(id.toLong)
> >   ) yield
> >     <table>
> >       ...
> >     </table>
> >   ) openOr Text("User not found")
> >
> > Actual templates for above locations are user.html, user-actions.html and
> > user-message.html. Notice, I could use user/actions.html, but current
> menus
> > don't let you have a folder with the same name as a template. For example
> > Menu(Loc("a", List("a"), "a")) ::
> > Menu(Loc("b", List("a", "b"), "b")) ::
> > work separately. But if you put them in one menu together and try
> entering "
> > server.com/a" url, you'll get confusing
> > Message: java.lang.IllegalArgumentException: line 1 does not exist
> > scala.io.Source.getLine(Source.scala:280)
> > ...
> > Is it a bug?
> >
> > My solution is not ideal, but works for me and took only about 50 LOCs to
> > write:) If you are interested, I'll attach the code.
> >
> > On Sat, Oct 25, 2008 at 5:43 PM, Tim Perrett <[EMAIL PROTECTED]>
> wrote:
> >
> > > Right, i've been working on this for most of the day trying to
> > > understand exactly whats going on. I have a working sample, but its
> > > not how I would want it to work in an ideal world.
> >
> > >http://github.com/timperrett/bloglite/tree/master/src/main/scala/eu/g.
> ..
> >
> > > What I really want to do is split the functionality to point at
> > > differnet HTML files to keep it all tidy as possible and so that the
> > > scala file doesnt get cologged with HTML. So, I try rewriting to a
> > > file called "list" as opposed to "articles" with the following:
> >
> > >  override val rewrite: LocRewrite = Full({
> > >    case RewriteRequest(ParsePath("index" :: Nil, _, _,_),_, _) =>
> > >      (RewriteResponse("list" :: Nil), ListLoc)
> > >  })
> >
> > > But it refuses to have it - jetty just serves the contents of the
> > > directory. There is obviously something going on that is not obvious -
> > > like I say, it all works fine if i just use a single HTML file, but
> > > thats *really* not what I want as its messy.
> >
> > > How can I resolve this?
> >
> > > Cheers
> >
> > > Tim
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to