You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@esme.apache.org by dp...@apache.org on 2009/01/23 01:26:47 UTC
svn commit: r736864 [3/3] - in /incubator/esme/trunk/server: ./
src/main/scala/bootstrap/liftweb/ src/main/scala/org/
src/main/scala/org/apache/ src/main/scala/org/apache/esme/
src/main/scala/org/apache/esme/actor/ src/main/scala/org/apache/esme/api/
s...
Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala?rev=736864&view=auto
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala (added)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala Thu Jan 22 16:26:46 2009
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2008-2009 WorldWide Conferencing, LLC
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.esme.snippet
+
+import org.apache.esme._
+import model._
+import actor._
+
+import net.liftweb._
+import http._
+import js._
+import JsCmds._
+import JE._
+import util._
+import Helpers._
+
+import scala.xml.{NodeSeq, Text, Node}
+
+object JsonPoster extends SessionVar(S.buildJsonFunc{
+ case JsonCmd("post", _, map: Map[String, Any], _) =>
+ for (msgObj <- map.get("msg");
+ msg <- Box.isA(msgObj, classOf[String]).map(_.trim) if msg.length > 0;
+ tagObj <- map.get("tags");
+ tags <- Box.isA(tagObj, classOf[String]);
+ user <- User.currentUser) {
+
+ val replyTo = map.get("reply-to").map(toLong) match {
+ case Some(x) if x > 0L => Full(x)
+ case _ => Empty
+ }
+
+ Distributor !
+ Distributor.UserCreatedMessage(user.id, msg,
+ Tag.split(tags),
+ millis,
+ Empty,
+ "web",
+ replyTo)
+
+ }
+ Noop
+
+ case _ => Noop
+ }
+)
+
+class UserSnip extends DispatchSnippet {
+ def dispatch: DispatchIt =
+ Map("name" -> userName _,
+ "postScript" -> postScript _,
+ "followers" -> followers _,
+ "following" -> following _,
+ "loginForm" -> loginForm _,
+ "loggedIn" -> loggedInFilter _)
+
+ def loggedInFilter(in: NodeSeq): NodeSeq = {
+ val lookFor = if (User.loggedIn_?) "in" else "out"
+
+ (<foo>{in}</foo> \ lookFor).toList.
+ filter(_.prefix == "logged").
+ map(_.child).firstOption.getOrElse(NodeSeq.Empty)
+ }
+
+ def userFmt(u: User): Node =
+ <li><a href={"/user/"+urlEncode(u.nickname.is)}>{u.niceName}</a> {u.firstName} {u.lastName}</li>
+
+ def calcUser: Box[User] =
+ S.attr("userId").flatMap(s => User.find(toLong(s))) or User.currentUser
+
+ def followers(in: NodeSeq): NodeSeq =
+ <ul>
+ {
+ calcUser.toList.flatMap(_.followers.map(userFmt))
+ }
+ </ul>
+
+ def following(in: NodeSeq): NodeSeq =
+ <ul>
+ {
+ calcUser.toList.flatMap(_.following.map(userFmt))
+ }
+ </ul>
+
+ def loginForm(in: NodeSeq): NodeSeq =
+ if (User.loggedIn_?) NodeSeq.Empty
+ else User.loginForm
+
+
+ def userName(in: NodeSeq) = {
+ if (User.currentUser.map(_.needsChange_?) openOr false)
+ S.redirectTo("/user_mgt/edit")
+
+ Text(User.currentUser.map(_.wholeName) openOr "")
+ }
+
+ def postScript(in: NodeSeq): NodeSeq =
+ <xml:group>
+ {Script(JsonPoster.is._2)}
+ {Script(Function("post_msg", List(),
+ JsonPoster.is._1("post",
+ JsObj("msg" -> ValById("textdude"),
+ "tags" -> ValById("tagdude"),
+ "reply-to" -> JsVar("currentConvNumber"))) &
+ SetValById("textdude", "") &
+ SetValById("tagdude", "") &
+ JsRaw("clearReplyTo();")
+ ))
+ }
+ </xml:group>
+}
Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/.keep
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/.keep?rev=736864&view=auto
==============================================================================
(empty)
Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/ActionView.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/ActionView.scala?rev=736864&view=auto
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/ActionView.scala (added)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/ActionView.scala Thu Jan 22 16:26:46 2009
@@ -0,0 +1,174 @@
+package org.apache.esme.view
+
+/**
+ * Copyright 2008-2009 WorldWide Conferencing, LLC
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import net.liftweb._
+import http._
+import js._
+import JE._
+import JsCmds._
+import SHtml._
+import util._
+import Helpers._
+import sitemap._
+import mapper._
+import Loc._
+
+import org.apache.esme._
+import model._
+
+import scala.xml.{NodeSeq}
+
+object ActionView {
+ def loggedIn_? = User.loggedIn_?
+
+ val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in")
+
+ val menuItems =
+ Menu(Loc("actionMgt", List("action_view", "index"), "Action Management", ifIsLoggedIn)) ::
+ Nil
+}
+
+class ActionView extends LiftView {
+ def dispatch = Map("index" -> index _)
+
+
+ def index() =
+ for (user <- User.currentUser) yield {
+ val spanName = "TokenSpan"
+ val theName = "theName"
+ val theAction = "theAction"
+ val theTest = "theTest"
+
+ var testText = ""
+ var nameText = ""
+
+ def redisplayActions: JsCmd = SetHtml(spanName, displayActions)
+ def saveIt(actionText: String): JsCmd = {
+
+ val toSave = Action.create.name(nameText).user(user)
+ DB.use(toSave.connectionIdentifier) {
+ ignore =>
+ val act: Box[List[FieldError]] =
+ for (a1 <- toSave.setAction(actionText);
+ a2 <- a1.setTest(testText))
+ yield a2.validate
+
+ act match {
+ case Full(Nil) =>
+ toSave.save
+ S.notice("Action added")
+ redisplayActions &
+ SetValById(theName, "") & SetValById(theAction, "") &
+ SetValById(theTest, "")
+
+ case Full(xs) => S.error(xs); Noop
+ case Failure(msg, _, _) => S.error(msg) ; Noop
+ case _ => Noop
+ }
+ }
+ }
+
+ def displayActions: NodeSeq =
+ Action.findAll(By(Action.user, user), By(Action.removed, false),
+ OrderBy(Action.id, Ascending)) match {
+ case Nil => Nil
+ case xs =>
+ <table>
+ <tr>
+ <td>Name</td>
+ <td>Enabled</td>
+ <td>Test</td>
+ <td>Action</td>
+ <td>Remove</td>
+ </tr>
+ {
+ xs.map(at =>
+ <tr>
+ <td>{at.name}</td>
+ <td>Enabled: {ajaxCheckbox(!at.disabled, e => {at.disabled(!e).save; Noop})}</td>
+ <td><pre>{at.testText}</pre></td>
+ <td><pre>{at.actionText}</pre></td>
+ <td>
+ {SHtml.ajaxButton("Remove", () => {at.removed(true).save ; redisplayActions})}
+ </td>
+ </tr>)
+ }
+ </table>
+ }
+
+ <lift:surround with="default" at="content">
+
+ Manage your Actions items: <br/>
+ <span id={spanName}>
+ {
+ displayActions
+ }
+ </span>
+
+ {
+ ajaxForm(
+ <xml:group>
+ <table>
+ <tr><td colspan="3">New Action</td></tr>
+ <tr>
+ <td>Name</td>
+ <td>{text("", nameText = _) % ("id" -> theName)}</td>
+ </tr>
+ <tr>
+ <td>Test</td>
+ <td>{textarea("", testText = _) % ("id" -> theTest)}</td>
+ <td>
+ @foo -- sender is @foo<br />
+ day = (0,1) -- sent on Sunday or Monday<br/>
+ #moo -- contains the #moo tag<br/>
+ 50% -- success 50% of the time<br/>
+ @foo & 50% -- half the time, something sent by @foo<br/>
+ login -- user has logged in<br/>
+ followed -- user is being followed<br/>
+ unfollowed -- user is being unfollowed<br/>
+ profile -- user changed profile<br/>
+ every N mins -- repeat action, N is an integer
+ </td>
+ </tr>
+
+ <tr>
+ <td>Action</td>
+ <td>{textarea("", saveIt) % ("id" -> theAction)}</td>
+ <td>
+ filter -- not put in your timeline<br />
+ resend -- sends the message to all your followers<br />
+ mailto:foo@bar.com -- sends the message to foo@bar.com<br/>
+ http://foo.com/message/in -- HTTP post, %s expands to message<br/>
+ atom:http://blog.com/feed.atom -- posts new messages from Atom feed<br/>
+ rss:http://blog.com/feed.rss -- posts new messages from RSS feed
+ </td>
+ </tr>
+ <input type="submit" value="Add" />
+ </table>
+ </xml:group>
+ )
+ }
+
+ </lift:surround>
+ }
+}
Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Auth.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Auth.scala?rev=736864&view=auto
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Auth.scala (added)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Auth.scala Thu Jan 22 16:26:46 2009
@@ -0,0 +1,104 @@
+package org.apache.esme.view
+
+/**
+ * Copyright 2008-2009 WorldWide Conferencing, LLC
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import net.liftweb._
+import http._
+import js._
+import JE._
+import JsCmds._
+import SHtml._
+import util._
+import Helpers._
+import sitemap._
+import Loc._
+
+import org.apache.esme._
+import model._
+
+import scala.xml.{NodeSeq}
+
+object Auth {
+ def loggedIn_? = User.loggedIn_?
+
+ val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in")
+
+ val menuItems =
+ Menu(Loc("authToken", List("auth", "index"), "Manage Tokens", ifIsLoggedIn)) ::
+ Nil
+}
+
+class Auth extends LiftView {
+ def dispatch = Map("index" -> index _)
+
+ def index() =
+ for (user <- User.currentUser) yield {
+ val spanName = "TokenSpan"
+ val theInput = "theInput"
+ def redisplayTokens: JsCmd = SetHtml(spanName, displayTokens)
+
+ def addAuthToken(desc: String): JsCmd = {
+ desc.trim match {
+ case x if x.length < 3 => S.error("Description too short")
+ case x => AuthToken.create.description(x).user(user).saveMe
+ S.notice("New token added")
+ }
+
+ redisplayTokens & SetValById(theInput, "")
+ }
+
+ def displayTokens: NodeSeq =
+ user.authTokens match {
+ case Nil => Nil
+ case xs =>
+ <ul>
+ {
+ xs.map(at => <li>{at.description} token: {at.uniqueId}
+ {SHtml.ajaxButton("Revoke",
+ () => {at.delete_!
+ redisplayTokens})}</li>)
+ }
+ </ul>
+ }
+
+ <lift:surround with="default" at="content">
+
+ Manage your external application authentication tokens: <br/>
+ <span id={spanName}>
+ {
+ displayTokens
+ }
+ </span>
+
+ {
+ ajaxForm(
+ <xml:group>
+ Create a new Authentication Token.<br />
+ Description: {text("", addAuthToken) % ("id" -> theInput)}
+ <input type="submit" value="Add" />
+ </xml:group>
+ )
+ }
+
+ </lift:surround>
+ }
+}
Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Track.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Track.scala?rev=736864&view=auto
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Track.scala (added)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Track.scala Thu Jan 22 16:26:46 2009
@@ -0,0 +1,107 @@
+package org.apache.esme.view
+
+/**
+ * Copyright 2008-2009 WorldWide Conferencing, LLC
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import net.liftweb._
+import http._
+import js._
+import JE._
+import JsCmds._
+import SHtml._
+import util._
+import Helpers._
+import sitemap._
+import mapper._
+import Loc._
+
+import org.apache.esme._
+import model._
+
+import scala.xml.{NodeSeq}
+
+object Track {
+ def loggedIn_? = User.loggedIn_?
+
+ val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in")
+
+ val menuItems =
+ Menu(Loc("trackMgt", List("track", "index"), "Item Tracking", ifIsLoggedIn)) ::
+ Nil
+}
+
+class Track extends LiftView {
+ def dispatch = Map("index" -> index _)
+ //{
+ //case "index" => index
+//}
+
+ def index() =
+ for (user <- User.currentUser) yield {
+ val spanName = "TokenSpan"
+ val theInput = "theInput"
+ def redisplayTracking: JsCmd = SetHtml(spanName, displayTracking)
+
+ def addTrack(what: String): JsCmd = {
+ what.trim match {
+ case x if x.length < 3 => S.error("Too short")
+ case x => Tracking.create.regex(x).user(user).saveMe
+ S.notice("Now tracking "+x)
+ }
+
+ redisplayTracking & SetValById(theInput, "")
+ }
+
+ def displayTracking: NodeSeq =
+ Tracking.findAll(By(Tracking.user, user), By(Tracking.removed, false),
+ OrderBy(Tracking.id, Ascending)) match {
+ case Nil => Nil
+ case xs =>
+ <ul>
+ {
+ xs.map(at => <li>{at.pattern} Enabled: {ajaxCheckbox(!at.disabled, e => {at.disabled(!e).save; Noop})}
+ {SHtml.ajaxButton("Remove", () => {at.removed(true).save ; redisplayTracking})}</li>)
+ }
+ </ul>
+ }
+
+ <lift:surround with="default" at="content">
+
+ Manage your tracking items: <br/>
+ <span id={spanName}>
+ {
+ displayTracking
+ }
+ </span>
+
+ {
+ ajaxForm(
+ <xml:group>
+ Track something new.<br />
+ What? {text("", addTrack) % ("id" -> theInput)}
+ <input type="submit" value="Add" />
+ </xml:group>
+ )
+ }
+
+ </lift:surround>
+ }
+}
Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/UserView.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/UserView.scala?rev=736864&view=auto
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/UserView.scala (added)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/UserView.scala Thu Jan 22 16:26:46 2009
@@ -0,0 +1,256 @@
+package org.apache.esme.view
+
+/**
+ * Copyright 2008-2009 WorldWide Conferencing, LLC
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import net.liftweb._
+import http._
+import js._
+import JE._
+import JsCmds._
+import SHtml._
+import util._
+import Helpers._
+import sitemap._
+import mapper._
+import Loc._
+
+import org.apache.esme._
+import model._
+import lib._
+
+import scala.xml.{NodeSeq, Text, Elem}
+
+import java.util.logging._
+
+object UserView extends LiftView /* with MsgFormat */ {
+ val logger: Logger = Logger.getLogger("org.apache.esme.view")
+ logger.setLevel(Level.INFO)
+ def loggedIn_? = User.loggedIn_?
+
+ val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in")
+
+ val menuItems =
+ Menu(Loc("userView", List("user_view", "index"), "View User", Hidden)) ::
+ Nil
+
+ implicit def fToO(in: () => NodeSeq): Box[() => NodeSeq] = Full(in)
+ implicit def fToO2(in: Elem): Box[NodeSeq] = Full(in)
+
+ val dispatch =
+ Map("index" -> index _,
+ "tag" -> displayTag _,
+ "search" -> search _,
+ "all" -> allUsers _,
+ "conversation" -> conversation _)
+
+ def conversation(): Box[NodeSeq] = {
+ val cid = S.param("cid").map(toLong).openOr(-1L)
+
+ val msgs = Message.findAndPrime(By(Message.conversation, cid),
+ OrderBy(Message.id, Ascending))
+
+ val replyMap = msgs.foldLeft[Map[Long, List[Message]]](Map.empty){
+ case (map, msg) => msg.replyTo.can match {
+ case Full(rt) => map + (rt -> (msg :: map.getOrElse(rt, Nil)))
+ case _ => map
+ }
+ }
+
+ val start = msgs.firstOption.toList
+
+ def show(what: List[Message]): NodeSeq = {
+ what match {
+ case Nil => Text("")
+ case _ =>
+ <ul>
+ {
+ what.zipWithIndex.map{
+ case (m, idx) =>
+ <span id={"m_"+idx}>
+ {Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m_"+idx).cmd))
+ }
+ </span>
+ }
+ }
+ </ul>
+ }
+ }
+
+ <lift:surround with="default" at="content">
+ <div>
+ <fieldset>
+ <legend>Conversation</legend>
+ {
+ show(start)
+ }
+ </fieldset>
+ </div>
+
+ </lift:surround>
+ }
+
+ def index(): Box[NodeSeq] =
+ (<lift:surround with="default" at="content">
+ {
+ val ui = for (uid <- S.param("uid");
+ user <- User.findFromWeb(uid)) yield {
+ def updateFollow: JsCmd = SetHtml("following", followOrNot)
+
+ def followOrNot: NodeSeq = {
+ User.currentUser match {
+ case Full(u) if u != user =>
+ if (u.following_?(user))
+ ajaxButton("Unfollow", () => {u.unfollow(user); updateFollow})
+ else ajaxButton("Follow", () => {u.follow(user); updateFollow})
+
+ case _ => <xml:group />
+ }
+ }
+
+ <div>
+ <div id="tabs" class="b-view tab1">
+ <dl class="messages">
+ <dt class="caption">{user.niceName}'s Timeline
+ <span id="following">{followOrNot}</span></dt>
+ <dd>
+ {
+ val lst: List[Message] =
+ Mailbox.mostRecentMessagesFor(user.id, 50).map(_._1)
+ // user.latestMessages(50) openOr Nil
+ lst.zipWithIndex.map{
+ case (m, idx) =>
+ <span id={"m2_"+idx}>
+ {
+ Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m2_"+idx).cmd))
+ }
+ </span>
+ }
+ }
+ </dd>
+ </dl>
+
+ <dl class="tagclouds">
+ <dt class="caption">{user.niceName}'s Messages</dt>
+
+ <dd class="b-clouds">
+ {
+ val lst: List[Message] =
+ Message.findAll(By(Message.author, user), MaxRows(50), OrderBy(Message.id, Descending))
+ lst.zipWithIndex.map{
+ case (m, idx) =>
+ <span id={"m3_"+idx}>
+ {
+ Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m3_"+idx).cmd))
+ }
+ </span>
+ }
+ }
+ </dd>
+ </dl>
+ <dl class="contacts">
+ <dt class="caption">
+ Contacts
+ </dt>
+
+ <dd class="b-contacts" style="height: 240px; overflow: auto">
+ Following:
+ <lift:UserSnip.following userId={user.id.toString}/>
+ </dd>
+ <dd class="b-contacts" style="height: 240px; overflow: auto">
+ Followers:
+ <lift:UserSnip.followers userId={user.id.toString}/>
+ </dd>
+ </dl>
+ </div>
+ </div>
+ }
+ ui openOr (<span>User Not Found</span>)
+ }
+ </lift:surround>)
+
+ def search(): Box[NodeSeq] =
+ for (user <- User.currentUser;
+ term <- S.param("term")) yield
+ <lift:surround with="default" at="content">
+ <div>
+ <fieldset>
+ <legend>Search: {term}</legend>
+ <ul>
+ {
+ val lst: List[Message] = Message.search(term, user.following, 50)
+ lst.zipWithIndex.map{
+ case (m, idx) =>
+ <span id={"m4_"+idx}>
+ {
+ Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m4_"+idx).cmd))
+ }
+ </span>
+ }
+ }
+ </ul>
+ </fieldset>
+ </div>
+ </lift:surround>
+
+ def displayTag(): Box[NodeSeq] =
+ (<lift:surround with="default" at="content">
+ {
+ val ui = for (tagText <- S.param("tag").map(_.trim);
+ tag <- Tag.find(By(Tag.name, tagText))) yield {
+ val lst = tag.findMessages()
+
+ (<div>
+ <fieldset>
+ <legend>{tag.name}</legend>
+ <ul>
+ {
+ lst.zipWithIndex.map{
+ case (m, idx) =>
+ <span id={"m5_"+idx}>
+ {
+ Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m5_"+idx).cmd))
+ }
+ </span>
+ }
+ }
+ </ul>
+ </fieldset>
+ </div>)
+ }
+ ui openOr (<span>Tag Not Found</span>)
+ }
+ </lift:surround>)
+
+ def allUsers(): Box[NodeSeq] =
+ <lift:surround with="default" at="content">
+ <fieldset>
+ <legend>Users</legend>
+ <ul>
+ {
+ User.findAll(OrderBy(User.nickname, Ascending)).
+ map(u => <li><a href={"/user/"+urlEncode(u.nickname.is)}>{u.niceName}</a> {u.firstName} {u.lastName}</li>)
+ }
+ </ul>
+ </fieldset>
+ </lift:surround>
+
+}
Added: incubator/esme/trunk/server/src/test/scala/org/apache/esme/AppTest.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/test/scala/org/apache/esme/AppTest.scala?rev=736864&view=auto
==============================================================================
--- incubator/esme/trunk/server/src/test/scala/org/apache/esme/AppTest.scala (added)
+++ incubator/esme/trunk/server/src/test/scala/org/apache/esme/AppTest.scala Thu Jan 22 16:26:46 2009
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2008-2009 WorldWide Conferencing, LLC
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.esme;
+
+import _root_.junit.framework._;
+import Assert._;
+
+object AppTest {
+ def suite: Test = {
+ val suite = new TestSuite(classOf[AppTest]);
+ suite
+ }
+
+ def main(args : Array[String]) {
+ _root_.junit.textui.TestRunner.run(suite);
+ }
+}
+
+/**
+ * Unit test for simple App.
+ */
+class AppTest extends TestCase("app") {
+
+ /**
+ * Rigourous Tests :-)
+ */
+ def testOK() = assertTrue(true);
+ //def testKO() = assertTrue(false);
+
+
+}
Added: incubator/esme/trunk/server/src/test/scala/org/apache/esme/lib/MsgParseTest.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/test/scala/org/apache/esme/lib/MsgParseTest.scala?rev=736864&view=auto
==============================================================================
--- incubator/esme/trunk/server/src/test/scala/org/apache/esme/lib/MsgParseTest.scala (added)
+++ incubator/esme/trunk/server/src/test/scala/org/apache/esme/lib/MsgParseTest.scala Thu Jan 22 16:26:46 2009
@@ -0,0 +1,346 @@
+/**
+ * Copyright 2008-2009 WorldWide Conferencing, LLC
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.esme.lib
+
+import org.specs._
+import org.specs.runner.JUnit3
+import org.specs.runner.ConsoleRunner
+import net.liftweb.util._
+import org.specs.matcher._
+import Helpers._
+import MsgParser._
+import net.sourceforge.jwebunit.junit.WebTester
+import org.mortbay.jetty.Server
+//import org.mortbay.jetty.servlet.Context
+import org.mortbay.jetty.servlet.ServletHolder
+import org.mortbay.jetty.webapp.WebAppContext
+import org.apache.esme._
+import model._
+
+import net.sourceforge.jwebunit.junit.WebTester
+import _root_.junit.framework.AssertionFailedError
+
+class MsgParserSpecsAsTest extends JUnit3(MsgParserSpecs)
+object MsgParserSpecsRunner extends ConsoleRunner(MsgParserSpecs)
+
+object MsgParserSpecs extends Specification {
+ JettyTestServer.start()
+
+ type PFT = MsgParser.ParseResult[_]
+ def parseMatch(name: String, matchr: PartialFunction[PFT, Any]) = new Matcher[PFT] {
+ def apply(v: => PFT) = (matchr.isDefinedAt(v),
+ name+" succeeded parsing",
+ name+" failed parsing")
+ }
+
+ "Msg Parser Parse" should {
+ "parse top label" in {
+ val ret = MsgParser.toplabel("www")
+
+ ret must
+ parseMatch("www", {
+ case MsgParser.Success("www", _) =>
+ })
+ }
+
+ "parse a simple URL" in {
+ MsgParser.httpUrl("http://www.google.com") must
+ parseMatch("google", {
+ case MsgParser.Success("http://www.google.com", _) =>
+ })
+ }
+
+ "parse a complex simple URL" in {
+ val Str = "http://www.google.com:8080/Foo/bar"
+
+ val ret = MsgParser.httpUrl(Str)
+
+ ret must
+ parseMatch("google + port", {
+ case MsgParser.Success(Str, _) =>
+ })
+ }
+
+ "parse a complex URL with query params" in {
+ val Str = "https://www.sdn.sap.com/irj/sdn/weblogs?blog=/pub/wlg/10754"
+
+ val ret = MsgParser.httpUrl(Str)
+
+ ret must
+ parseMatch("sap thing", {
+ case MsgParser.Success(Str, _) =>
+ })
+ }
+
+ "Fail for an empty string" in {
+ MsgParser.begin("") must
+ parseMatch("Empty",
+ {case MsgParser.Error(_, _) =>
+ case MsgParser.Failure(_, _) =>
+ })
+
+ }
+
+ "Find only text" in {
+ MsgParser.begin("This is a message") must
+ parseMatch("only test",
+ {case MsgParser.Success(MsgText(_) :: Nil, _) =>
+
+ })
+
+ }
+
+ "Find only text" in {
+ MsgParser.begin("This is http://$$$ a message") must
+ parseMatch("only test",
+ {case MsgParser.Success(MsgText(_) :: Nil, _) =>
+
+ })
+
+ }
+
+ "Find only text" in {
+ MsgParser.begin("This is #,hello a message") must
+ parseMatch("only test",
+ {case MsgParser.Success(MsgText(_) :: Nil, _) =>
+
+ })
+
+ }
+
+ "Find only text" in {
+ MsgParser.begin("This is @--Moose a message") must
+ parseMatch("only test",
+ {case MsgParser.Success(MsgText(_) :: Nil, _) =>
+
+ })
+
+ }
+
+ "Find a hash tag" in {
+ MsgParser.begin("This is #hash a message") must
+ parseMatch("only test",
+ {case MsgParser.Success(MsgText(_) ::
+ HashTag(tag) ::
+ MsgText(_) :: Nil, _)
+ if tag.name.equalsIgnoreCase("hash") =>
+ }
+ )
+
+ }
+
+ "Find a @msg tag" in {
+ val ret = MsgParser.begin("This is @hash, a message")
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(MsgText(_) ::
+ AtName(_) ::
+ MsgText(_) :: Nil, _) =>
+ }
+ )
+
+ }
+
+ "Find a url tag" in {
+ MsgParser.begin("This is http://www.moo.com a message") must
+ parseMatch("only test",
+ {case MsgParser.Success(MsgText(_) ::
+ URL(_) ::
+ MsgText(_) :: Nil, _) =>
+ }
+ )
+
+ }
+
+ "Find a https url tag" in {
+ MsgParser.begin("This is https://www.moo.com a message") must
+ parseMatch("only test",
+ {case MsgParser.Success(MsgText(_) ::
+ URL(_) ::
+ MsgText(_) :: Nil, _) =>
+ }
+ )
+
+ }
+
+ "match 'any'" in {
+ val ret = MsgParser._testMessage("any")
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(AnyAction, _) =>
+ }
+ )
+
+ }
+
+
+ "match '54%'" in {
+ val ret = MsgParser._testMessage(" 54% ")
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(PercentAction(54), _) =>
+ }
+ )
+
+ }
+
+ "match '#foo'" in {
+ val ret = MsgParser._testMessage(" #foo ")
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(HashAction(_, _), _) =>
+ }
+ )
+
+ }
+
+ /*
+
+ "match '@hash'" in {
+ println("About to test @hash")
+ val ret = MsgParser._testMessage(" @hash ")
+
+ println("hash is is "+ret)
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(AtUserAction(_), _) =>
+ }
+ )
+
+ }
+ */
+
+ "match '@hasher'" in {
+ val ret = MsgParser._testMessage(" @hasher ")
+
+ ret must
+ parseMatch(" @hasher ",
+ {case MsgParser.Failure(_ , _) =>
+ }
+ )
+
+ }
+
+ "match 'day = 4'" in {
+ val ret = MsgParser._testMessage(" day = 4 ")
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(DateTestAction(DayDateType, EqOpr, List(4)), _) =>
+ }
+ )
+
+ }
+
+ "match 'month = (1,2,4)'" in {
+ val ret = MsgParser._testMessage(" month = (1, 2, 4 ) ")
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(DateTestAction(MonthDateType, EqOpr, List(1, 2, 4)), _) =>
+ }
+ )
+
+ }
+
+ "match 'month = (1,2,4) | 74%'" in {
+ val ret = MsgParser._testMessage(" month = (1, 2, 4 )|74% ")
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(OrAction(DateTestAction(MonthDateType, EqOpr, List(1, 2, 4)), PercentAction(74)), _) =>
+ }
+ )
+
+ }
+
+ "match '( month = (1, 2, 4 )|74%) & #frog'" in {
+ val ret = MsgParser._testMessage("( month = (1, 2, 4 )|74%) & #frog ")
+
+ ret must
+ parseMatch("only test",
+ {case MsgParser.Success(AndAction(
+ ParenAction(OrAction(DateTestAction(MonthDateType, EqOpr, List(1, 2, 4)), PercentAction(74))),
+ HashAction(_, _)), _) =>
+ })
+
+ }
+
+ }
+
+}
+
+
+object JettyTestServer {
+ private val serverPort_ = System.getProperty("SERVLET_PORT", "8989").toInt
+ private var baseUrl_ = "http://127.0.0.1:" + serverPort_
+
+ System.setProperty("run.mode", "test")
+
+ private val server_ : Server = {
+ val server = new Server(serverPort_)
+ val context = new WebAppContext()
+ context.setServer(server)
+ context.setContextPath("/")
+ context.setWar("src/main/webapp")
+ //val context = new Context(_server, "/", Context.SESSIONS)
+ //context.addFilter(new FilterHolder(new LiftFilter()), "/");
+ server.addHandler(context)
+ server
+ }
+
+ def urlFor(path: String) = baseUrl_ + path
+
+ def start() = {
+ server_.start()
+ User.create.nickname("hash").save
+ }
+
+ def stop() = {
+ server_.stop()
+ server_.join()
+ }
+
+ def browse(startPath: String, f:(WebTester) => Unit) = {
+ val wc = new WebTester()
+ try {
+ wc.setScriptingEnabled(false)
+ wc.beginAt(JettyTestServer.urlFor(startPath))
+ f(wc)
+ } catch {
+ case exc: AssertionFailedError => {
+ System.err.println("serveur response: ", wc.getServeurResponse())
+ throw exc
+ }
+ } finally {
+ wc.closeBrowser()
+ }
+ }
+
+}
+
+