[seam-commits] Seam SVN: r13802 - in modules/resteasy/trunk: examples and 26 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Oct 7 04:28:18 EDT 2010


Author: jharting
Date: 2010-10-07 04:28:16 -0400 (Thu, 07 Oct 2010)
New Revision: 13802

Added:
   modules/resteasy/trunk/examples/
   modules/resteasy/trunk/examples/tasks/
   modules/resteasy/trunk/examples/tasks/ftests.xml
   modules/resteasy/trunk/examples/tasks/pom.xml
   modules/resteasy/trunk/examples/tasks/seam-tasks-ds.xml
   modules/resteasy/trunk/examples/tasks/src/
   modules/resteasy/trunk/examples/tasks/src/main/
   modules/resteasy/trunk/examples/tasks/src/main/java/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/Category.java
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/Task.java
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/TaskValidationGroup.java
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/AbstractCollectionResource.java
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/AbstractEntityResource.java
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/CategoryCollectionResource.java
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/CategoryResource.java
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/TaskCollectionResource.java
   modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/TaskResource.java
   modules/resteasy/trunk/examples/tasks/src/main/resources/
   modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/
   modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/persistence.xml
   modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/seam-beans.xml
   modules/resteasy/trunk/examples/tasks/src/main/resources/import.sql
   modules/resteasy/trunk/examples/tasks/src/main/webapp/
   modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/
   modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/beans.xml
   modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/web.xml
   modules/resteasy/trunk/examples/tasks/src/main/webapp/categories-json.js
   modules/resteasy/trunk/examples/tasks/src/main/webapp/categories.html
   modules/resteasy/trunk/examples/tasks/src/main/webapp/img/
   modules/resteasy/trunk/examples/tasks/src/main/webapp/img/bg.png
   modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-delete.png
   modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-done.png
   modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-edit.png
   modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-undo.png
   modules/resteasy/trunk/examples/tasks/src/main/webapp/img/tasks-logo.png
   modules/resteasy/trunk/examples/tasks/src/main/webapp/index.html
   modules/resteasy/trunk/examples/tasks/src/main/webapp/jquery-1.3.2.min.js
   modules/resteasy/trunk/examples/tasks/src/main/webapp/json2.js
   modules/resteasy/trunk/examples/tasks/src/main/webapp/resolved-json.js
   modules/resteasy/trunk/examples/tasks/src/main/webapp/resolved.html
   modules/resteasy/trunk/examples/tasks/src/main/webapp/seam-tasks-client-json.js
   modules/resteasy/trunk/examples/tasks/src/main/webapp/style.css
   modules/resteasy/trunk/examples/tasks/src/main/webapp/tasks-json.js
   modules/resteasy/trunk/examples/tasks/src/main/webapp/tasks.html
   modules/resteasy/trunk/examples/tasks/src/test/
   modules/resteasy/trunk/examples/tasks/src/test/java/
   modules/resteasy/trunk/examples/tasks/src/test/java/org/
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/AbstractPage.java
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/CategoryPage.java
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/CategoryPageTest.java
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/ResolvedPage.java
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/ResolvedPageTest.java
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/TaskPage.java
   modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/TaskPageTest.java
   modules/resteasy/trunk/examples/tasks/src/test/resources/
Log:
Initial commit of seam-tasks example.


Property changes on: modules/resteasy/trunk/examples/tasks
___________________________________________________________________
Name: svn:ignore
   + .settings
.project
target
.classpath



Added: modules/resteasy/trunk/examples/tasks/ftests.xml
===================================================================
--- modules/resteasy/trunk/examples/tasks/ftests.xml	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/ftests.xml	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,8 @@
+<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
+<suite name="Seam Tasks example" verbose="2" parallel="false">
+	<test name="Seam Tasks">
+		<packages>
+			<package name="org.jboss.seam.resteasy.example.tasks.ftest" />
+		</packages>
+	</test>
+</suite>

Added: modules/resteasy/trunk/examples/tasks/pom.xml
===================================================================
--- modules/resteasy/trunk/examples/tasks/pom.xml	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/pom.xml	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,370 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>org.jboss.seam.resteasy</groupId>
+		<artifactId>seam-resteasy-parent</artifactId>
+		<version>3.0.0-SNAPSHOT</version>
+		<relativePath>../../pom.xml</relativePath>
+	</parent>
+
+	<groupId>org.jboss.seam.security</groupId>
+	<artifactId>seam-tasks-example</artifactId>
+	<packaging>war</packaging>
+	<version>3.0.0-SNAPSHOT</version>
+	<name>Seam Tasks Example</name>
+
+	<properties>
+		<selenium.java.client.version>1.0.1</selenium.java.client.version>
+		<richfaces.selenium.version>1.5.1.Final</richfaces.selenium.version>
+		<ftest.version.discriminator />
+		<selenium.browser>*firefoxproxy /usr/lib64/firefox-3.5/firefox</selenium.browser>
+		<selenium.browser.url>http://localhost:8080</selenium.browser.url>
+		<selenium.server.port>14444</selenium.server.port>
+		<selenium.server.host>localhost</selenium.server.host>
+		<selenium.speed>0</selenium.speed>
+		<selenium.timeout>30000</selenium.timeout>
+		<selenium.debug>false</selenium.debug>
+		<selenium.log.dir>${project.build.directory}/ftest</selenium.log.dir>
+		<application.deploy.timeout>300</application.deploy.timeout>
+		<richfaces.selenium.version>1.5.1.Final</richfaces.selenium.version>
+		<!-- richfaces-selenium -->
+		<browserSessionReuse>true</browserSessionReuse>
+		<cargo.jvmargs.additional />
+		<cargo.timeout.deploy>120000</cargo.timeout.deploy>
+		<context.host>localhost</context.host>
+		<context.root>http://${context.host}:8080/</context.root>
+		<context.path>/${project.build.finalName}/</context.path>
+		<context.deploy.path>${context.path}</context.deploy.path>
+		<jboss.master.configuration>${env.JBOSS_HOME}/server/all</jboss.master.configuration>
+		<deployable.location />
+		<deployable.type>war</deployable.type>
+		<method>*</method>
+		<selenium.maximize>false</selenium.maximize>
+		<selenium.timeout.ajax>15000</selenium.timeout.ajax>
+		<selenium.timeout.default>30000</selenium.timeout.default>
+		<selenium.timeout.gui>5000</selenium.timeout.gui>
+		<selenium.timeout.model>30000</selenium.timeout.model>
+		<ftest.suite.xml>ftests.xml</ftest.suite.xml>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>javax.enterprise</groupId>
+			<artifactId>cdi-api</artifactId>
+			<scope>provided</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>javax.validation</groupId>
+			<artifactId>validation-api</artifactId>
+			<scope>provided</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.hibernate.javax.persistence</groupId>
+			<artifactId>hibernate-jpa-2.0-api</artifactId>
+			<scope>provided</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.jboss.seam.xml</groupId>
+			<artifactId>seam-xml-config</artifactId>
+			<version>3.0.0-SNAPSHOT</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.jboss.seam.resteasy</groupId>
+			<artifactId>seam-resteasy-api</artifactId>
+			<version>3.0.0-SNAPSHOT</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.jboss.seam.resteasy</groupId>
+			<artifactId>seam-resteasy</artifactId>
+			<version>3.0.0-SNAPSHOT</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.jboss.weld</groupId>
+			<artifactId>weld-extensions</artifactId>
+			<version>1.0.0-SNAPSHOT</version>
+			<exclusions>
+				<exclusion>
+					<groupId>javax.transaction</groupId>
+					<artifactId>jta</artifactId>
+				</exclusion>
+				<exclusion>
+					<groupId>org.javassist</groupId>
+					<artifactId>javassist</artifactId>
+				</exclusion>
+				<exclusion>
+					<groupId>javax.persistence</groupId>
+					<artifactId>persistence-api</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
+		<dependency>
+			<groupId>org.jboss.resteasy</groupId>
+			<artifactId>resteasy-atom-provider</artifactId>
+			<version>2.0.1.GA</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.jboss.resteasy</groupId>
+			<artifactId>resteasy-jackson-provider</artifactId>
+			<version>2.0.1.GA</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.jboss.spec.javax.ejb</groupId>
+			<artifactId>jboss-ejb-api_3.1_spec</artifactId>
+			<version>1.0.0.Beta2</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- Test dependencies -->
+		<dependency>
+			<groupId>org.seleniumhq.selenium.client-drivers</groupId>
+			<artifactId>selenium-java-client-driver</artifactId>
+			<version>${selenium.java.client.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.jboss.test</groupId>
+			<artifactId>richfaces-selenium</artifactId>
+			<version>${richfaces.selenium.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.testng</groupId>
+			<artifactId>testng</artifactId>
+			<version>5.12.1</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<finalName>seam-tasks</finalName>
+		<plugins>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>selenium-maven-plugin</artifactId>
+				<version>1.0.1</version>
+			</plugin>
+			<plugin>
+				<groupId>org.codehaus.cargo</groupId>
+				<artifactId>cargo-maven2-plugin</artifactId>
+				<version>1.0</version>
+			</plugin>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>failsafe-maven-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</build>
+
+	<profiles>
+		<profile>
+			<activation>
+				<activeByDefault>true</activeByDefault>
+			</activation>
+			<id>ftest-jboss-remote-6</id>
+			<build>
+				<plugins>
+					<!-- skip unit tests when running functional -->
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-surefire-plugin</artifactId>
+						<configuration>
+							<skip>true</skip>
+						</configuration>
+					</plugin>
+
+					<!-- Start Selenium -->
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>selenium-maven-plugin</artifactId>
+						<executions>
+							<execution>
+								<id>start-selenium</id>
+								<phase>pre-integration-test</phase>
+								<goals>
+									<goal>start-server</goal>
+								</goals>
+								<configuration>
+									<background>true</background>
+									<port>${selenium.server.port}</port>
+									<logOutput>true</logOutput>
+									<logFile>${selenium.log.dir}/selenium-server.log</logFile>
+									<browserSideLog>${selenium.debug}</browserSideLog>
+									<debug>${selenium.debug}</debug>
+								</configuration>
+							</execution>
+						</executions>
+					</plugin>
+
+					<!-- Deploy/undeploy -->
+					<!-- <plugin> -->
+					<!-- <groupId>org.codehaus.cargo</groupId> -->
+					<!-- <artifactId>cargo-maven2-plugin</artifactId> -->
+					<!-- <configuration> -->
+					<!-- <container> -->
+					<!-- <containerId>jboss5x</containerId> -->
+					<!-- <type>remote</type> -->
+					<!-- </container> -->
+					<!-- <configuration> -->
+					<!-- <type>runtime</type> -->
+					<!-- </configuration> -->
+					<!-- </configuration> -->
+					<!-- <executions> -->
+					<!-- <execution> -->
+					<!-- <id>deploy</id> -->
+					<!-- <phase>pre-integration-test</phase> -->
+					<!-- <goals> -->
+					<!-- <goal>deploy</goal> -->
+					<!-- </goals> -->
+					<!-- </execution> -->
+					<!-- <execution> -->
+					<!-- <id>undeploy</id> -->
+					<!-- <phase>post-integration-test</phase> -->
+					<!-- <goals> -->
+					<!-- <goal>undeploy</goal> -->
+					<!-- </goals> -->
+					<!-- </execution> -->
+					<!-- </executions> -->
+					<!-- </plugin> -->
+
+					<!-- run functional tests -->
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>failsafe-maven-plugin</artifactId>
+						<configuration>
+							<suiteXmlFiles>
+								<suiteXmlFile>${basedir}/${ftest.suite.xml}</suiteXmlFile>
+							</suiteXmlFiles>
+							<argLine>-Xmx748m</argLine>
+							<forkMode>once</forkMode>
+							<systemProperties>
+								<property>
+									<name>method</name>
+									<value>${method}</value>
+								</property>
+								<property>
+									<name>browser</name>
+									<value>${selenium.browser}</value>
+								</property>
+								<property>
+									<name>context.root</name>
+									<value>${context.root}</value>
+								</property>
+								<property>
+									<name>context.path</name>
+									<value>${context.path}</value>
+								</property>
+								<property>
+									<name>selenium.host</name>
+									<value>${selenium.server.host}</value>
+								</property>
+								<property>
+									<name>selenium.port</name>
+									<value>${selenium.server.port}</value>
+								</property>
+								<property>
+									<name>selenium.debug</name>
+									<value>${selenium.debug}</value>
+								</property>
+								<property>
+									<name>selenium.maximize</name>
+									<value>${selenium.maximize}</value>
+								</property>
+								<property>
+									<name>maven.resources.dir</name>
+									<value>${resources.dir}</value>
+								</property>
+								<property>
+									<name>maven.project.build.directory</name>
+									<value>${project.build.directory}</value>
+								</property>
+								<property>
+									<name>selenium.timeout.default</name>
+									<value>${selenium.timeout.default}</value>
+								</property>
+								<property>
+									<name>selenium.timeout.gui</name>
+									<value>${selenium.timeout.gui}</value>
+								</property>
+								<property>
+									<name>selenium.timeout.ajax</name>
+									<value>${selenium.timeout.ajax}</value>
+								</property>
+								<property>
+									<name>selenium.timeout.model</name>
+									<value>${selenium.timeout.model}</value>
+								</property>
+								<property>
+									<name>selenium.speed</name>
+									<value>${selenium.speed}</value>
+								</property>
+								<property>
+									<name>selenium.timeout</name>
+									<value>${selenium.timeout}</value>
+								</property>
+								<property>
+									<name>basedir</name>
+									<value>${basedir}</value>
+								</property>
+							</systemProperties>
+						</configuration>
+						<executions>
+							<execution>
+								<id>verify</id>
+								<phase>verify</phase>
+								<goals>
+									<goal>verify</goal>
+								</goals>
+							</execution>
+							<execution>
+								<id>integration-test</id>
+								<phase>integration-test</phase>
+								<goals>
+									<goal>integration-test</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+
+					<!-- Stop Selenium -->
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-antrun-plugin</artifactId>
+						<executions>
+							<execution>
+								<!-- this ant script runs testng natively -->
+								<id>stop-selenium</id>
+								<phase>post-integration-test</phase>
+								<configuration>
+									<tasks>
+										<echo taskname="selenium-shutdown" message="DGF Errors during shutdown are expected" />
+										<get taskname="selenium-shutdown"
+											src="http://${selenium.server.host}:${selenium.server.port}/selenium-server/driver/?cmd=shutDownSeleniumServer"
+											ignoreerrors="true" dest="${selenium.log.dir}/selenium.stop.msg" />
+									</tasks>
+								</configuration>
+								<goals>
+									<goal>run</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+
+</project>
+

Added: modules/resteasy/trunk/examples/tasks/seam-tasks-ds.xml
===================================================================
--- modules/resteasy/trunk/examples/tasks/seam-tasks-ds.xml	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/seam-tasks-ds.xml	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE datasources
+    PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
+    "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
+
+<datasources>
+    <local-tx-datasource>
+        <jndi-name>tasksDatasource</jndi-name>
+        <connection-url>jdbc:hsqldb:.</connection-url>
+        <driver-class>org.hsqldb.jdbcDriver</driver-class>
+        <user-name>sa</user-name>
+        <password></password>
+    </local-tx-datasource>
+</datasources>
+

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/Category.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/Category.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/Category.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.entity;
+
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.jboss.resteasy.annotations.providers.NoJackson;
+
+/**
+ * 
+ * @author Jozef Hartinger
+ * 
+ */
+ at Entity
+ at XmlRootElement
+ at NamedQueries({ 
+   @NamedQuery(name = "categoryByName", query = "select category from Category category where category.name = :category"),
+   @NamedQuery(name = "categories", query = "select category from Category category")
+})
+ at NoJackson
+public class Category
+{
+   private Long id;
+   private String name;
+   private List<Task> tasks;
+
+   public Category()
+   {
+   }
+
+   public Category(String name)
+   {
+      this.name = name;
+   }
+
+   @Id
+   @GeneratedValue
+   @XmlTransient
+   public Long getId()
+   {
+      return id;
+   }
+
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+
+   @NotNull
+   @Column(unique = true)
+   @Size(min = 1, max = 100)
+   public String getName()
+   {
+      return name;
+   }
+
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+
+   @OneToMany(mappedBy = "category", cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)
+   @XmlTransient
+   public List<Task> getTasks()
+   {
+      return tasks;
+   }
+
+   public void setTasks(List<Task> tasks)
+   {
+      this.tasks = tasks;
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/Task.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/Task.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/Task.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,161 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.entity;
+
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+import javax.validation.GroupSequence;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.jboss.resteasy.annotations.providers.NoJackson;
+
+/**
+ * 
+ * @author Jozef Hartinger
+ * 
+ */
+ at Entity
+ at XmlRootElement
+ at GroupSequence({ Task.class, TaskValidationGroup.class })
+ at NamedQueries({
+   @NamedQuery(name = "taskById", query = "select task from Task task where task.id = :tid"),
+   @NamedQuery(name = "taskByCategoryAndId", query = "select task from Task task where task.id = :tid and task.category.name = :category"),
+   @NamedQuery(name = "tasks", query = "select task from Task task where task.resolved in (:r1, :r2)"),
+   @NamedQuery(name = "tasksByCategory", query = "select task from Task task where task.category.name = :category and task.resolved in (:r1, :r2)")
+})
+ at NoJackson
+public class Task
+{
+   @Id
+   @GeneratedValue
+   private Long id;
+   @NotNull
+   @Size(min = 1, max = 100, groups = TaskValidationGroup.class)
+   private String name;
+   @NotNull
+   private Boolean resolved;
+   @Temporal(TemporalType.TIMESTAMP)
+   @NotNull
+   private Date created;
+   @Temporal(TemporalType.TIMESTAMP)
+   @NotNull
+   private Date updated;
+   @ManyToOne
+   @NotNull
+   private Category category;
+
+   public Task()
+   {
+   }
+
+   public Task(Long id, String name, Boolean resolved, Date created, Date updated, Category category)
+   {
+      this.id = id;
+      this.name = name;
+      this.resolved = resolved;
+      this.created = created;
+      this.updated = updated;
+      this.category = category;
+   }
+
+   public Long getId()
+   {
+      return id;
+   }
+
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+
+   public Boolean isResolved()
+   {
+      return resolved;
+   }
+
+   public void setResolved(Boolean resolved)
+   {
+      this.resolved = resolved;
+   }
+
+   @XmlElement(name = "created")
+   public Date getCreated()
+   {
+      return created;
+   }
+
+   public void setCreated(Date created)
+   {
+      this.created = created;
+   }
+
+   public Date getUpdated()
+   {
+      return updated;
+   }
+
+   public void setUpdated(Date updated)
+   {
+      this.updated = updated;
+   }
+
+   @XmlTransient
+   public Category getCategory()
+   {
+      return category;
+   }
+
+   public void setCategory(Category category)
+   {
+      this.category = category;
+   }
+
+   @Transient
+   @XmlElement(name = "category")
+   public String getCategoryName()
+   {
+      return category.getName();
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/TaskValidationGroup.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/TaskValidationGroup.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/entity/TaskValidationGroup.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,27 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.entity;
+
+public interface TaskValidationGroup
+{
+
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/AbstractCollectionResource.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/AbstractCollectionResource.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/AbstractCollectionResource.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.resource;
+
+import javax.persistence.TypedQuery;
+
+/**
+ * Common methods for collection resources
+ * @author Jozef Hartinger
+ *
+ */
+public abstract class AbstractCollectionResource
+{
+   /**
+    * Modifies query passed as a parameter to filter out tasks based on their status (resolved/unresolved/all) 
+    */
+   protected <T> TypedQuery<T> applyResolutionParameter(TypedQuery<T> query, String status)
+   {
+      if ("resolved".equals(status))
+      {
+         // double assignment as a workaround for HHH-4541
+         return query.setParameter("r1", true).setParameter("r2", true);
+      }
+      else if ("unresolved".equals(status))
+      {
+         return query.setParameter("r1", false).setParameter("r2", false);
+      }
+      else
+      {
+         return query.setParameter("r1", true).setParameter("r2", false);
+      }
+   }
+
+   /**
+    * Sets paginatation parameters
+    * @param query JPA query
+    * @param start the first item
+    * @param limit how many items to return (use 0 for unlimited result)
+    * @throws IllegalArgumentException if any of the integer parameters is lesser than 0 
+    */
+   protected <T> void applyPaginationParameters(TypedQuery<T> query, int start, int limit)
+   {
+      if (start < 0)
+      {
+         throw new IllegalArgumentException("start");
+      }
+      query.setFirstResult(start);
+      
+      if (limit < 0)
+      {
+         throw new IllegalArgumentException("limit");
+      }
+      if (limit > 0)
+      {
+         query.setMaxResults(limit);
+      }
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/AbstractEntityResource.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/AbstractEntityResource.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/AbstractEntityResource.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.resource;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.jboss.seam.resteasy.example.tasks.entity.Category;
+
+/**
+ * Common methods for entity resources
+ * @author Jozef Hartinger
+ *
+ */
+public abstract class AbstractEntityResource
+{
+   @PersistenceContext
+   protected EntityManager em;
+   
+   /**
+    * Return category based on its name.
+    */
+   protected Category loadCategory(String name)
+   {
+      return em.createNamedQuery("categoryByName", Category.class).setParameter("category", name).getSingleResult();
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/CategoryCollectionResource.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/CategoryCollectionResource.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/CategoryCollectionResource.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.resource;
+
+import java.util.List;
+
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+import org.jboss.resteasy.annotations.providers.NoJackson;
+import org.jboss.seam.resteasy.example.tasks.entity.Category;
+
+/**
+ * Collection resource for categories
+ * @author Jozef Hartinger
+ *
+ */
+ at Path("/category")
+ at Produces( { "application/xml", "application/json" })
+ at Stateless
+public class CategoryCollectionResource extends AbstractCollectionResource
+{
+   @PersistenceContext
+   private EntityManager em;
+   
+   @GET
+   @NoJackson
+   public List<Category> getCategories(@QueryParam("start") @DefaultValue("0") int start, @QueryParam("limit") @DefaultValue("5") int limit)
+   {
+      TypedQuery<Category> query = em.createNamedQuery("categories", Category.class);
+      applyPaginationParameters(query, start, limit);
+      return query.getResultList();
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/CategoryResource.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/CategoryResource.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/CategoryResource.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,104 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.resource;
+
+import java.net.URI;
+import java.util.Date;
+
+import javax.ejb.Stateless;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.jboss.seam.resteasy.example.tasks.entity.Category;
+import org.jboss.seam.resteasy.example.tasks.entity.Task;
+import org.jboss.seam.resteasy.example.tasks.entity.TaskValidationGroup;
+import org.jboss.seam.resteasy.validation.ValidateRequest;
+
+/**
+ * CRUD resource for categories
+ * @author Jozef Hartinger
+ *
+ */
+ at Path("/category")
+ at Produces( { "application/xml", "application/json" })
+ at Consumes( { "application/xml", "application/json" })
+ at ValidateRequest(groups = TaskValidationGroup.class)
+ at Stateless
+public class CategoryResource extends AbstractEntityResource
+{
+   @Inject
+   private TaskCollectionResource taskCollectionSubresource;
+
+   @Path("/{category}")
+   public TaskCollectionResource getTasks()
+   {
+      return taskCollectionSubresource;
+   }
+
+   @PUT
+   @Path("/{category}")
+   public void putCategory(@PathParam("category") String categoryName)
+   {
+      Category category = new Category(categoryName);
+      em.persist(category);
+   }
+
+   @DELETE
+   @Path("/{category}")
+   public void deleteCategory(@PathParam("category") String categoryName)
+   {
+      em.remove(loadCategory(categoryName));
+   }
+
+   /**
+    * This method only makes sense at /category/{category}/task not /task
+    * 
+    * 
+    */
+   @POST
+   @Path("/{category}/task")
+   public Response createTask(Task incommingTask, @PathParam("category") String categoryName, @Context UriInfo uriInfo)
+   {
+      Category category = loadCategory(categoryName);
+      
+      Task task = new Task();
+      task.setCategory(category);
+      task.setCreated(new Date());
+      task.setUpdated(task.getCreated()); // set update date to creation date
+      task.setName(incommingTask.getName());
+      task.setResolved(false); // not resolved by default
+      em.persist(task);
+      long id = task.getId();
+
+      URI uri = uriInfo.getBaseUriBuilder().path(TaskCollectionResource.class).path(TaskCollectionResource.class, "getTaskSubresource").build(String.valueOf(id));
+      return Response.created(uri).build();
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/TaskCollectionResource.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/TaskCollectionResource.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/TaskCollectionResource.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,85 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.resource;
+
+import java.util.List;
+
+import javax.ejb.Stateless;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import org.jboss.resteasy.annotations.providers.NoJackson;
+import org.jboss.seam.resteasy.example.tasks.entity.Task;
+
+/**
+ * Collection resource for tasks
+ * @author Jozef Hartinger
+ *
+ */
+ at Path("/task")
+ at Produces({ "application/xml", "application/json" })
+ at Stateless
+public class TaskCollectionResource extends AbstractCollectionResource
+{
+   @PersistenceContext
+   private EntityManager em;
+   @Inject
+   private TaskResource taskSubresource;
+
+   @GET
+   @NoJackson
+   public List<Task> getTasks(@Context UriInfo uriInfo, @QueryParam("status") @DefaultValue("unresolved") String status, @QueryParam("start") @DefaultValue("0") int start, @QueryParam("limit") @DefaultValue("5") int limit)
+   {
+      TypedQuery<Task> query = createQuery(uriInfo);
+      query = applyResolutionParameter(query, status);
+      applyPaginationParameters(query, start, limit);
+      return query.getResultList();
+   }
+
+   @Path("/{taskId}")
+   public TaskResource getTaskSubresource()
+   {
+      return taskSubresource;
+   }
+
+   protected TypedQuery<Task> createQuery(UriInfo uriInfo)
+   {
+      String categoryName = uriInfo.getPathParameters().getFirst("category");
+      if (categoryName == null)
+      {
+         return em.createNamedQuery("tasks", Task.class);
+      }
+      else
+      {
+         return em.createNamedQuery("tasksByCategory", Task.class).setParameter("category", categoryName);
+      }
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/TaskResource.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/TaskResource.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/java/org/jboss/seam/resteasy/example/tasks/resource/TaskResource.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,117 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.resteasy.example.tasks.resource;
+
+import java.util.Date;
+
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import org.jboss.resteasy.annotations.providers.NoJackson;
+import org.jboss.seam.resteasy.example.tasks.entity.Category;
+import org.jboss.seam.resteasy.example.tasks.entity.Task;
+import org.jboss.seam.resteasy.example.tasks.entity.TaskValidationGroup;
+import org.jboss.seam.resteasy.validation.ValidateRequest;
+
+/**
+ * CRUD resource for resources
+ * @author Jozef Hartinger
+ *
+ */
+ at Produces({ "application/xml", "application/json" })
+ at Consumes({ "application/xml", "application/json" })
+ at ValidateRequest(groups = TaskValidationGroup.class)
+ at Stateless
+public class TaskResource extends AbstractEntityResource
+{
+   @PersistenceContext
+   private EntityManager em;
+
+   @GET
+   @NoJackson
+   public Task getTask(@PathParam("taskId") long taskId, @Context UriInfo uriInfo)
+   {
+      return loadTask(taskId, uriInfo);
+   }
+
+   @POST
+   @Path("/move")
+   public void move(@PathParam("taskId") long taskId, @QueryParam("category") String newCategoryName, @Context UriInfo uriInfo)
+   {
+      Task task = loadTask(taskId, uriInfo);
+      Category newCategory = em.createNamedQuery("categoryByName", Category.class).setParameter("category", newCategoryName).getSingleResult();
+      Category oldCategory = task.getCategory();
+      
+      oldCategory.getTasks().remove(task);
+      newCategory.getTasks().add(task);
+      task.setCategory(newCategory);
+      task.setUpdated(new Date());
+   }
+   
+   @PUT
+   @NoJackson
+   public void updateTask(@PathParam("taskId") long taskId, @Context UriInfo uriInfo, Task incommingTask)
+   {
+      Task task = loadTask(taskId, uriInfo);
+      if (incommingTask.getName() != null)
+      {
+         task.setName(incommingTask.getName());
+      }
+      if (incommingTask.isResolved() != null)
+      {
+         task.setResolved(incommingTask.isResolved());
+      }
+      task.setUpdated(new Date());
+   }
+
+   @DELETE
+   public void deleteTask(@PathParam("taskId") long taskId, @Context UriInfo uriInfo)
+   {
+      Task task = loadTask(taskId, uriInfo);
+      em.remove(task);
+   }
+
+   protected Task loadTask(long taskId, UriInfo uriInfo)
+   {
+      String categoryName = uriInfo.getPathParameters().getFirst("category");
+      if (categoryName == null)
+      {
+         return em.createNamedQuery("taskById", Task.class).setParameter("tid", taskId).getSingleResult();
+      }
+      else
+      {
+         return em.createNamedQuery("taskByCategoryAndId", Task.class).setParameter("tid", taskId).setParameter("category", categoryName).getSingleResult();
+      }
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/persistence.xml
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/persistence.xml	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/persistence.xml	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
+             version="2.0">
+   <persistence-unit name="tasksDatabase" transaction-type="JTA">
+      <provider>org.hibernate.ejb.HibernatePersistence</provider>
+      <jta-data-source>java:/tasksDatasource</jta-data-source>
+      <properties>
+         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
+         <property name="hibernate.show_sql" value="true"/>
+         <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>
+         <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
+      </properties>
+   </persistence-unit>
+</persistence>

Added: modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/seam-beans.xml
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/seam-beans.xml	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/resources/META-INF/seam-beans.xml	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,26 @@
+<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:s="urn:java:ee" xmlns:resteasy="urn:java:org.jboss.seam.resteasy.configuration">
+	xsi:schemaLocation="
+	http://java.sun.com/xml/ns/javaee
+	http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+	<resteasy:SeamResteasyConfiguration registerValidationExceptionMapper="true">
+		<s:replaces/>
+		<resteasy:exceptionMappings>
+			<s:value>
+				<resteasy:ExceptionMapping exceptionType="javax.persistence.NoResultException" statusCode="404">
+					<resteasy:message>Entity does not exist.</resteasy:message>
+				</resteasy:ExceptionMapping>
+			</s:value>
+			<s:value>
+				<resteasy:ExceptionMapping exceptionType="org.hibernate.exception.ConstraintViolationException" statusCode="409">
+					<resteasy:message>Constraint violation.</resteasy:message>
+				</resteasy:ExceptionMapping>
+			</s:value>
+			<s:value>
+				<resteasy:ExceptionMapping exceptionType="java.lang.IllegalArgumentException" statusCode="400">
+					<resteasy:message>Illegal parameter value.</resteasy:message>
+				</resteasy:ExceptionMapping>
+			</s:value>
+		</resteasy:exceptionMappings>
+	</resteasy:SeamResteasyConfiguration>
+</beans>
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/resources/import.sql
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/resources/import.sql	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/resources/import.sql	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,22 @@
+insert into Category (id, name) values (1, 'School')
+	insert into Task (id, name, resolved, created, updated, category_id) values (1, 'Build the Turing machine', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 1)
+	insert into Task (id, name, resolved, created, updated, category_id) values (2, 'Finish the RESTEasy-Seam integration example', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 1)
+	insert into Task (id, name, resolved, created, updated, category_id) values (3, 'Learn new vocab for English conversations', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 1)
+	insert into Task (id, name, resolved, created, updated, category_id) values (4, 'Prepare a presentation for webdesign seminar', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 1)
+	insert into Task (id, name, resolved, created, updated, category_id) values (5, 'Print study materials', true, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 1)
+insert into Category (id, name) values (2, 'Work')
+	insert into Task (id, name, resolved, created, updated, category_id) values (6, 'Pick up meal tickets', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 2)
+insert into Category (id, name) values (3, 'Buy')
+	insert into Task (id, name, resolved, created, updated, category_id) values (7, 'Buy milk', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 3)
+	insert into Task (id, name, resolved, created, updated, category_id) values (8, 'Buy an infinite tape', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 3)
+	insert into Task (id, name, resolved, created, updated, category_id) values (9, 'Order books', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 3)
+	insert into Task (id, name, resolved, created, updated, category_id) values (10, 'Buy a turtle', true, '2009-04-19 16:11:05', '2009-04-22 13:15:33', 3)
+	insert into Task (id, name, resolved, created, updated, category_id) values (11, 'Buy new shoes', true, '2009-04-19 16:11:05', '2009-04-22 13:15:33', 3)
+	insert into Task (id, name, resolved, created, updated, category_id) values (12, 'Order camera', true, '2009-04-19 16:11:05', '2009-04-22 13:15:33', 3)
+insert into Category (id, name) values (4, 'Other stuff')
+	insert into Task (id, name, resolved, created, updated, category_id) values (13, 'Learn to fly', true, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 4)
+	insert into Task (id, name, resolved, created, updated, category_id) values (14, 'Visit grandma', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 4)
+	insert into Task (id, name, resolved, created, updated, category_id) values (15, 'Extend passport', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 4)
+	insert into Task (id, name, resolved, created, updated, category_id) values (16, 'Get a haircut', false, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 4)
+	insert into Task (id, name, resolved, created, updated, category_id) values (17, 'Pay bills', true, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 4)
+	insert into Task (id, name, resolved, created, updated, category_id) values (18, 'Tidy up', true, '2009-04-19 16:11:05', '2009-04-19 16:11:05', 4)

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/beans.xml
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/beans.xml	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/beans.xml	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,9 @@
+<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:s="urn:java:seam:core" xmlns:test="urn:java:org.jboss.seam.resteasy.configuration"
+	xsi:schemaLocation="
+	http://java.sun.com/xml/ns/javaee
+	http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+	<interceptors>
+		<class>org.jboss.seam.resteasy.validation.ValidationInterceptor</class>
+	</interceptors>
+</beans>
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/web.xml
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/web.xml	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/WEB-INF/web.xml	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+      http://java.sun.com/xml/ns/javaee
+      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+	<context-param>
+		<param-name>resteasy.unwrapped.exceptions</param-name>
+		<param-value>javax.ejb.EJBException,org.jboss.weld.exceptions.WeldException,javax.persistence.PersistenceException</param-value>
+	</context-param>
+</web-app>

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/categories-json.js
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/categories-json.js	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/categories-json.js	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,53 @@
+// global variables that hold fetched tasks and categories
+var categories = new Array();
+
+$(document).ready(function() {
+	printCategories();
+	prepareNewCategoryForm();
+});
+
+function addCategory(categoryName) {
+	var nameCell = $('<td/>').addClass('name').text(categoryName);
+	var deleteButton = $('<img/>').attr('src', 'img/task-delete.png').attr('title', 'Delete this category').click(function(event) {
+		event.preventDefault();
+		deleteCategory(categoryName, function() {
+			// remove the category from global variable
+			delete categories[categoryName];
+			// remove the category from the page
+			$('[id=' + categoryName + ']').remove();
+		});
+	});
+	var buttonCell = $('<td/>').append(deleteButton);
+	$('<tr/>').attr('id', categoryName).append(buttonCell).append(nameCell).appendTo('#categories tbody');
+}
+
+/*
+ * Obtain a list of Categories and render it on the page
+ */
+function printCategories()
+{
+	getCategories(0, 0, function(data) {
+		for (key in data)
+		{
+			var category = data[key].category;
+			categories[category.name] = category;
+			addCategory(category.name);
+		}
+		initialized();
+	}, "all");
+}
+
+/*
+ * Bind logic to the "Create" button
+ */
+function prepareNewCategoryForm()
+{
+	$('#editCategorySubmit').click(function(event) {
+		event.preventDefault();
+		var categoryName = $('#editCategoryName').attr('value');
+		putCategory(categoryName, function() {
+			addCategory(categoryName);
+			$('#editCategoryName').attr('value', '');
+		});
+	});
+}
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/categories.html
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/categories.html	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/categories.html	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,47 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<title>Seam Tasks</title>
+<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
+<script type="text/javascript" src="json2.js"></script>
+<script src="seam-tasks-client-json.js" type="text/javascript"></script>
+<link href="style.css" rel="stylesheet" type="text/css" />
+<script src="categories-json.js" type="text/javascript"></script>
+</head>
+<body>
+<div class="container">
+<div class="header">
+<h1>Seam Tasks</h1>
+<ul id="menu">
+	<li><a href="tasks.html">Tasks</a></li>
+	<li><a href="categories.html">Categories</a></li>
+	<li><a href="resolved.html">Resolved tasks</a></li>
+</ul>
+</div>
+<div id="content">
+<table id="categories">
+	<thead>
+		<tr>
+			<td colspan="2">
+			<h2>Categories</h2>
+			</td>
+		</tr>
+	</thead>
+	<tbody />
+</table>
+
+<hr />
+
+<form action="" id="newCategoryForm">
+<h2>Care for a new category?</h2>
+<input id="editCategoryName" type="text" /> <input
+	id="editCategorySubmit" type="button" value="Create" /></form>
+</div>
+<div id="footer">
+<hr />
+<div>Powered by Seam 3, Java EE 6 and jQuery. Find more at <span><a href="http://seamframework.org">seamframework.org</a></span></div>
+</div>
+</div>
+</body>
+</html>
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/bg.png
===================================================================
(Binary files differ)


Property changes on: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/bg.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-delete.png
===================================================================
(Binary files differ)


Property changes on: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-delete.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-done.png
===================================================================
(Binary files differ)


Property changes on: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-done.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-edit.png
===================================================================
(Binary files differ)


Property changes on: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-edit.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-undo.png
===================================================================
(Binary files differ)


Property changes on: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/task-undo.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/tasks-logo.png
===================================================================
(Binary files differ)


Property changes on: modules/resteasy/trunk/examples/tasks/src/main/webapp/img/tasks-logo.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/index.html
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/index.html	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/index.html	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,5 @@
+<html>
+<head>
+  <meta http-equiv="Refresh" content="0; URL=tasks.html">
+</head>
+</html>
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/jquery-1.3.2.min.js
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/jquery-1.3.2.min.js	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/jquery-1.3.2.min.js	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,19 @@
+/*
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(!
 H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(fun!
 ction(){var G=this;while(G.firstChild){G=G.firstChild}return G!
 }).appen
d(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.no!
 CloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pu!
 shStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilt!
 er(E,thi
s)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.!
 makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;functi!
 on K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?!
 (N.getEl
ementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"}!
 ,isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?!
 I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\!
 s+/),fun
ction(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}ret!
 urn o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("di!
 v");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S!
 ){return
}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.le!
 ngth){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}!
 if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return !
 I&&I.spe
cified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}!
 return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){retu!
 rn o.nth(E,2,"previousSibling")},nextAll:function(E){return o.!
 dir(E,"n
extSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeo!
 f E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"q!
 ueue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.ma!
 keArray(
H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
+/*
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)!
 }if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){!
 if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=!
 false;if
(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{!
 "class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementByI!
 d!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]!
 :[]}},NA
ME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}ret!
 urn X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"sub!
 mit"===T.type},image:function(T){return"image"===T.type},reset!
 :functio
n(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}!
 }return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var !
 M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[!
 O].sourc
e+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplic!
 ate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undef!
 ined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.h!
 ref=func
tion(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;f!
 or(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.!
 match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}!
 T=I.rela
tive[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);!
 H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort(!
 ).join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}!
 else{for
(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)!
 }if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaK!
 ey newValue originalTarget pageX pageY prevValue relatedNode r!
 elatedTa
rget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},s!
 pecial:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagatio!
 nStopped:k,isImmediatePropagationStopped:k};var a=function(F){!
 var E=F.
relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}r!
 eturn this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/!
 \./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false!
 ,readyLi
st:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,e!
 rror").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.st!
 yle.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:fal!
 se,noClo
neEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.s!
 lice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o!
 .fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend!
 ({get:fu
nction(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.dat!
 a=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.h!
 ost)){var H=document.getElementsByTagName("head")[0];var T=doc!
 ument.cr
eateElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState!
 ==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxSt!
 op")}}return J},handleError:function(F,H,E,G){if(F.error){F.er!
 ror(H,E,
G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunctio!
 n(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G]!
 ,"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.le!
 ngth;G<F
;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cu!
 r(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};retur!
 n E},easing:{linear:function(G,H,E,F){return E+F*G},swing:func!
 tion(G,H
,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n)!
 ;n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.e!
 lem)}return false}else{var J=G-this.startTime;this.state=J/thi!
 s.option
s.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this!
 [0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{to!
 p:N,left:I}}}o.offset={initialize:function(){if(this.initializ!
 ed){retu
rn}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:functi!
 on(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||th!
 is[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxMode!
 l&&docum
ent.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/json2.js
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/json2.js	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/json2.js	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,482 @@
+/*
+    http://www.JSON.org/json2.js
+    2010-08-25
+
+    Public Domain.
+
+    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+    See http://www.JSON.org/js.html
+
+
+    This code should be minified before deployment.
+    See http://javascript.crockford.com/jsmin.html
+
+    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+    NOT CONTROL.
+
+
+    This file creates a global JSON object containing two methods: stringify
+    and parse.
+
+        JSON.stringify(value, replacer, space)
+            value       any JavaScript value, usually an object or array.
+
+            replacer    an optional parameter that determines how object
+                        values are stringified for objects. It can be a
+                        function or an array of strings.
+
+            space       an optional parameter that specifies the indentation
+                        of nested structures. If it is omitted, the text will
+                        be packed without extra whitespace. If it is a number,
+                        it will specify the number of spaces to indent at each
+                        level. If it is a string (such as '\t' or '&nbsp;'),
+                        it contains the characters used to indent at each level.
+
+            This method produces a JSON text from a JavaScript value.
+
+            When an object value is found, if the object contains a toJSON
+            method, its toJSON method will be called and the result will be
+            stringified. A toJSON method does not serialize: it returns the
+            value represented by the name/value pair that should be serialized,
+            or undefined if nothing should be serialized. The toJSON method
+            will be passed the key associated with the value, and this will be
+            bound to the value
+
+            For example, this would serialize Dates as ISO strings.
+
+                Date.prototype.toJSON = function (key) {
+                    function f(n) {
+                        // Format integers to have at least two digits.
+                        return n < 10 ? '0' + n : n;
+                    }
+
+                    return this.getUTCFullYear()   + '-' +
+                         f(this.getUTCMonth() + 1) + '-' +
+                         f(this.getUTCDate())      + 'T' +
+                         f(this.getUTCHours())     + ':' +
+                         f(this.getUTCMinutes())   + ':' +
+                         f(this.getUTCSeconds())   + 'Z';
+                };
+
+            You can provide an optional replacer method. It will be passed the
+            key and value of each member, with this bound to the containing
+            object. The value that is returned from your method will be
+            serialized. If your method returns undefined, then the member will
+            be excluded from the serialization.
+
+            If the replacer parameter is an array of strings, then it will be
+            used to select the members to be serialized. It filters the results
+            such that only members with keys listed in the replacer array are
+            stringified.
+
+            Values that do not have JSON representations, such as undefined or
+            functions, will not be serialized. Such values in objects will be
+            dropped; in arrays they will be replaced with null. You can use
+            a replacer function to replace those with JSON values.
+            JSON.stringify(undefined) returns undefined.
+
+            The optional space parameter produces a stringification of the
+            value that is filled with line breaks and indentation to make it
+            easier to read.
+
+            If the space parameter is a non-empty string, then that string will
+            be used for indentation. If the space parameter is a number, then
+            the indentation will be that many spaces.
+
+            Example:
+
+            text = JSON.stringify(['e', {pluribus: 'unum'}]);
+            // text is '["e",{"pluribus":"unum"}]'
+
+
+            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+            text = JSON.stringify([new Date()], function (key, value) {
+                return this[key] instanceof Date ?
+                    'Date(' + this[key] + ')' : value;
+            });
+            // text is '["Date(---current time---)"]'
+
+
+        JSON.parse(text, reviver)
+            This method parses a JSON text to produce an object or array.
+            It can throw a SyntaxError exception.
+
+            The optional reviver parameter is a function that can filter and
+            transform the results. It receives each of the keys and values,
+            and its return value is used instead of the original value.
+            If it returns what it received, then the structure is not modified.
+            If it returns undefined then the member is deleted.
+
+            Example:
+
+            // Parse the text. Values that look like ISO date strings will
+            // be converted to Date objects.
+
+            myData = JSON.parse(text, function (key, value) {
+                var a;
+                if (typeof value === 'string') {
+                    a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+                    if (a) {
+                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+                            +a[5], +a[6]));
+                    }
+                }
+                return value;
+            });
+
+            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+                var d;
+                if (typeof value === 'string' &&
+                        value.slice(0, 5) === 'Date(' &&
+                        value.slice(-1) === ')') {
+                    d = new Date(value.slice(5, -1));
+                    if (d) {
+                        return d;
+                    }
+                }
+                return value;
+            });
+
+
+    This is a reference implementation. You are free to copy, modify, or
+    redistribute.
+*/
+
+/*jslint evil: true, strict: false */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+    lastIndex, length, parse, prototype, push, replace, slice, stringify,
+    test, toJSON, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (!this.JSON) {
+    this.JSON = {};
+}
+
+(function () {
+
+    function f(n) {
+        // Format integers to have at least two digits.
+        return n < 10 ? '0' + n : n;
+    }
+
+    if (typeof Date.prototype.toJSON !== 'function') {
+
+        Date.prototype.toJSON = function (key) {
+
+            return isFinite(this.valueOf()) ?
+                   this.getUTCFullYear()   + '-' +
+                 f(this.getUTCMonth() + 1) + '-' +
+                 f(this.getUTCDate())      + 'T' +
+                 f(this.getUTCHours())     + ':' +
+                 f(this.getUTCMinutes())   + ':' +
+                 f(this.getUTCSeconds())   + 'Z' : null;
+        };
+
+        String.prototype.toJSON =
+        Number.prototype.toJSON =
+        Boolean.prototype.toJSON = function (key) {
+            return this.valueOf();
+        };
+    }
+
+    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        gap,
+        indent,
+        meta = {    // table of character substitutions
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        },
+        rep;
+
+
+    function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+        escapable.lastIndex = 0;
+        return escapable.test(string) ?
+            '"' + string.replace(escapable, function (a) {
+                var c = meta[a];
+                return typeof c === 'string' ? c :
+                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+            }) + '"' :
+            '"' + string + '"';
+    }
+
+
+    function str(key, holder) {
+
+// Produce a string from holder[key].
+
+        var i,          // The loop counter.
+            k,          // The member key.
+            v,          // The member value.
+            length,
+            mind = gap,
+            partial,
+            value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+        if (value && typeof value === 'object' &&
+                typeof value.toJSON === 'function') {
+            value = value.toJSON(key);
+        }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+        if (typeof rep === 'function') {
+            value = rep.call(holder, key, value);
+        }
+
+// What happens next depends on the value's type.
+
+        switch (typeof value) {
+        case 'string':
+            return quote(value);
+
+        case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+            return isFinite(value) ? String(value) : 'null';
+
+        case 'boolean':
+        case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+            return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+        case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+            if (!value) {
+                return 'null';
+            }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+            gap += indent;
+            partial = [];
+
+// Is the value an array?
+
+            if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+                length = value.length;
+                for (i = 0; i < length; i += 1) {
+                    partial[i] = str(i, value) || 'null';
+                }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+                v = partial.length === 0 ? '[]' :
+                    gap ? '[\n' + gap +
+                            partial.join(',\n' + gap) + '\n' +
+                                mind + ']' :
+                          '[' + partial.join(',') + ']';
+                gap = mind;
+                return v;
+            }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+            if (rep && typeof rep === 'object') {
+                length = rep.length;
+                for (i = 0; i < length; i += 1) {
+                    k = rep[i];
+                    if (typeof k === 'string') {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+                for (k in value) {
+                    if (Object.hasOwnProperty.call(value, k)) {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+            v = partial.length === 0 ? '{}' :
+                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+                        mind + '}' : '{' + partial.join(',') + '}';
+            gap = mind;
+            return v;
+        }
+    }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+    if (typeof JSON.stringify !== 'function') {
+        JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+            var i;
+            gap = '';
+            indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+            if (typeof space === 'number') {
+                for (i = 0; i < space; i += 1) {
+                    indent += ' ';
+                }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+            } else if (typeof space === 'string') {
+                indent = space;
+            }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+            rep = replacer;
+            if (replacer && typeof replacer !== 'function' &&
+                    (typeof replacer !== 'object' ||
+                     typeof replacer.length !== 'number')) {
+                throw new Error('JSON.stringify');
+            }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+            return str('', {'': value});
+        };
+    }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+    if (typeof JSON.parse !== 'function') {
+        JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+            var j;
+
+            function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+                var k, v, value = holder[key];
+                if (value && typeof value === 'object') {
+                    for (k in value) {
+                        if (Object.hasOwnProperty.call(value, k)) {
+                            v = walk(value, k);
+                            if (v !== undefined) {
+                                value[k] = v;
+                            } else {
+                                delete value[k];
+                            }
+                        }
+                    }
+                }
+                return reviver.call(holder, key, value);
+            }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+            text = String(text);
+            cx.lastIndex = 0;
+            if (cx.test(text)) {
+                text = text.replace(cx, function (a) {
+                    return '\\u' +
+                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+                });
+            }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+            if (/^[\],:{}\s]*$/
+.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
+.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
+.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+                j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+                return typeof reviver === 'function' ?
+                    walk({'': j}, '') : j;
+            }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+            throw new SyntaxError('JSON.parse');
+        };
+    }
+}());

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/resolved-json.js
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/resolved-json.js	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/resolved-json.js	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,65 @@
+var firstTask = 0;
+var maxResults = 5;
+
+$(document).ready(function() {
+//	 next and previous buttons
+	$('.next').click(function(event) {
+		event.preventDefault();
+		firstTask += maxResults;
+		printTasks();
+	});
+	$('.previous').click(function(event) {
+		event.preventDefault();
+		firstTask -= maxResults;
+		printTasks();
+	});
+	
+	printTasks();
+});
+
+/**
+ * Load tasks and render them on the page
+ */
+function printTasks() {
+	$('#tasks tbody').empty();
+	getTasks("resolved", firstTask, maxResults, function(data) {
+		for (key in data)
+		{
+			addTask(data[key].task);
+		}
+
+		// pagination handling
+		if (data.length == maxResults) {
+			$('.next').show();
+		} else { 
+			$('.next').hide();
+		}
+		if (firstTask >= maxResults) {
+			$('.previous').show();
+		} else {
+			$('.previous').hide();
+		}
+		initialized();
+	});
+}
+
+function addTask(task) {
+	var parent = $('#tasks tbody');
+	var nameCell = $('<td/>').addClass('name').text(task.name);
+	var updatedCell = $('<td/>').addClass('updated').text(task.updated);
+	var undoButton = $('<img/>').attr('src', 'img/task-undo.png').attr('title', 'Undo this task').click(function(event) {
+		event.preventDefault();
+		task.resolved = false;
+		putTask(task, function() {
+			$('#' + task.id).remove();
+		});
+	});
+	var deleteButton = $('<img/>').attr('src', 'img/task-delete.png').attr('title', 'Delete this task').click(function(event) {
+		event.preventDefault();
+		deleteTask(task, function() {
+			$('#' + task.id).remove();
+		});
+	});
+	var buttonCell = $('<td/>').append(undoButton).append(deleteButton);
+	$('<tr/>').attr('id', task.id).append(buttonCell).append(nameCell).append(updatedCell).appendTo(parent);
+}
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/resolved.html
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/resolved.html	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/resolved.html	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,46 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<title>Seam Tasks</title>
+<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
+<script type="text/javascript" src="json2.js"></script>
+<script src="seam-tasks-client-json.js" type="text/javascript"></script>
+<link href="style.css" rel="stylesheet" type="text/css" />
+<script src="resolved-json.js" type="text/javascript"></script>
+</head>
+<body>
+<div class="container">
+<div class="header">
+<h1>Seam Tasks</h1>
+<ul id="menu">
+	<li><a href="tasks.html">Tasks</a></li>
+	<li><a href="categories.html">Categories</a></li>
+	<li><a href="resolved.html">Resolved tasks</a></li>
+</ul>
+</div>
+<div id="content">
+<table id="tasks">
+	<thead>
+		<tr>
+			<td colspan="3">
+			<h2>Hooray, resolved tasks!</h2>
+			</td>
+		</tr>
+	</thead>
+	<tbody />
+	<tfoot>
+		<tr>
+			<td><a href="" class="previous">Previous</a></td>
+			<td><a href="" class="next">Next</a></td>
+		</tr>
+	</tfoot>
+</table>
+</div>
+<div id="footer">
+<hr />
+<div>Powered by Seam 3, Java EE 6 and jQuery. Find more at <span><a href="http://seamframework.org">seamframework.org</a></span></div>
+</div>
+</div>
+</body>
+</html>
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/seam-tasks-client-json.js
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/seam-tasks-client-json.js	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/seam-tasks-client-json.js	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,111 @@
+$(document).ready(function() {
+	$.ajaxSetup({
+		cache : false
+	}); // workaround for IE
+})
+
+function ajax(type, url, callback, data) {
+	$.ajax({
+		type : type,
+		url : url,
+		data : data,
+		complete : function(response) {
+			handleResponse(response, callback);
+		},
+		dataType : "json",
+		contentType : "application/json"
+	});
+}
+
+function getCategories(start, limit, callback) {
+	var url = "/seam-tasks/category?start" + start + "&limit=" + limit;
+	ajax("GET", url, callback);
+}
+
+function putCategory(categoryName, success) {
+	var url = "/seam-tasks/category/" + escape(categoryName);
+	ajax("PUT", url, success);
+}
+
+function deleteCategory(categoryName, success) {
+	var url = "/seam-tasks/category/" + escape(categoryName);
+	ajax("DELETE", url, success);
+}
+
+function getTasksForCategory(categoryName, callback) {
+	var URI = escape("/seam-tasks/category/" + categoryName + "/task");
+	ajax("GET", URI, callback);
+}
+
+function getTask(URI, callback) {
+	ajax("GET", URI, callback)
+}
+
+function getTasks(status, start, limit, callback) {
+	var URI = "/seam-tasks/task?status=" + escape(status) + "&start="
+			+ escape(start) + "&limit=" + escape(limit);
+	ajax("GET", URI, callback);
+}
+
+function postTask(categoryName, taskName, success) {
+	var URI = escape("/seam-tasks/category/" + categoryName + "/task");
+	ajax("POST", URI, success, JSON.stringify({
+		"task" : {
+			"name" : taskName
+		}
+	}))
+}
+
+function putTask(task, success) {
+	var URI = escape("/seam-tasks/task/" + task.id);
+	ajax("PUT", URI, success, JSON.stringify({
+		"task" : task
+	}));
+}
+
+function moveTask(task, newCategory, success) {
+	var URI = "/seam-tasks/task/" + task.id + "/move?category="
+			+ newCategory.name;
+	ajax("POST", URI, success);
+}
+
+function deleteTask(task, success) {
+	var URI = escape("/seam-tasks/task/" + task.id);
+	ajax("DELETE", URI, success);
+}
+
+function handleResponse(response, success) {
+	if (response.status >= 400) {
+		error(response.responseText);
+	} else if (response.responseText) {
+		success(JSON.parse(response.responseText));
+	} else // successful response with no body
+	{
+		success(response);
+	}
+}
+
+function error(response) {
+	var jsonError;
+	try {
+		var jsonError = JSON.parse(response);
+		if (typeof jsonError.message != "undefined") {
+			alert(jsonError.message);
+		} else if (typeof jsonError.messages != "undefined") {
+			var message = "";
+			for (key in jsonError.messages) {
+				message = message + jsonError.messages[key] + "\n";
+			}
+			alert(message);
+		} else {
+			throw "Error";
+		}
+	} catch (e) {
+		alert("Unknown error");
+	}
+}
+
+// needed for functional tests
+function initialized() {
+	$('body').attr('initialized', 'true');
+}
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/style.css
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/style.css	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/style.css	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,133 @@
+body {
+    background: white url(img/bg.png) repeat scroll center;
+    font-family: Verdana, Arial;
+    margin: 0;
+    padding: 0;
+}
+
+div.container
+{
+    background: white url(img/tasks-logo.png) no-repeat left top;
+    background-position:20px 20px;
+    width: 666px;
+    margin: 0 auto;
+    padding: 0;
+}
+
+/* header */
+div.header {
+    padding: 0;
+    height: 140px;
+}
+
+/* image replacemement header */
+div.header h1 {
+    display: none;
+}
+
+#menu {
+    display: block;
+    margin: 110px 0 0 100px;
+    float:left;
+}
+
+#menu  li
+{
+    margin-left: 10px;
+    margin-right: 10px;
+    float:left;
+    display: inline;
+    font-size: 14px;
+}
+
+#menu a {
+    color: #899ea6;
+    text-decoration:none;
+    font-weight: bold;
+}
+
+#menu  a:hover   {
+    color:#99ccff;
+    text-decoration:none;
+    font-weight: bold;
+}
+
+
+/* content */
+
+hr {
+    width: 626px;
+    border: solid #dedede 1px;
+    border-bottom: none;
+}
+
+table
+{
+    border: none;
+    margin: 20px;
+    width: 626px;
+}
+
+#login
+{
+	float: left;
+    margin: 20px;
+    width: 326px;
+}
+
+#login div {
+	margin: 10px;
+}
+
+#login label {
+	display: block;
+}
+
+#rightPanel {
+	width: 270px;
+	margin: 30px 30px 0px 0px;
+	float: right;
+	text-align: justify;
+}
+
+table td.name {
+    color: #99ccff;
+    font-weight: bold;
+}
+
+table td.updated {
+    color: #99ccff;
+}
+
+h2
+{
+    margin: 0;
+    padding:0;
+    color: #899ea6;
+}
+
+#newTask, #newCategoryForm {
+    margin: 10px 20px 10px 20px;
+}
+
+/* footer */
+#footer a
+{
+    color: #99ccff;
+    text-decoration:none;
+    font-weight: bold;
+}
+
+#footer {
+    width: 646px;
+    height: 35px;
+    text-align: center;
+    margin: 0 auto;
+    padding: 0;
+    clear: both;
+}
+
+#footer div {
+    font-size: 11px;
+    margin: 0 20px 2px 0;
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/tasks-json.js
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/tasks-json.js	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/tasks-json.js	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,130 @@
+// global variables that hold fetched tasks and categories
+var categories = new Array();
+var tasks = new Array();
+
+$(document).ready(function() {
+	printCategories();
+	printTasks();
+	setupNewTaskForm();
+});
+
+function showTaskEditForm(task) {
+	var categoryList = $('#editTaskCategory').clone();
+	$(categoryList).find('[value=' + task.category + ']').attr('selected', 'selected');
+	var name = $('<input/>').attr('type', 'text').addClass('nameField').val(task.name);
+	
+	var update = $('<input/>').attr('type', 'button').attr('id', 'update').val('Update').click(function() {
+		var newCategoryName = $(categoryList).val();
+		task.name = $(name).val();
+		putTask(task, function() {
+				removeTaskEditForm(task)
+		});
+		
+		if (task.category != newCategoryName)
+		{
+			moveTask(task, categories[newCategoryName],function() {
+				// update local structures
+				delete categories[task.category].tasks[task.id];
+				task.category = newCategoryName;
+				categories[task.category].tasks[task.id] = task;
+				// move task to a different category
+				$('#' + task.id).remove(); 
+				addTask(task);
+			});
+		}
+		
+	});
+	
+	var form = $('<form/>').attr('id', 'updateTask').append(categoryList).append(name).append(update);
+	$('#' + task.id + ' .name').replaceWith(form);
+}
+
+function printCategories() {
+	getCategories(0, 0, function(data) {
+		var category;
+		for (key in data)
+		{
+			category = data[key].category;
+			categories[category.name] = category;
+			category.tasks = new Array();
+			addCategory(category);
+		}
+	}, "all");
+}
+
+function printTasks() {
+	getTasks("unresolved", 0, 0, function(data) {
+		var task;
+		for (key in data)
+		{
+			task = data[key].task;
+			tasks[task.id] = task;
+			categories[task.category].tasks[task.id] = task;
+			addTask(task);
+		}
+		initialized();
+	}, "unresolved");
+}
+
+
+function addCategory(category) {
+	var categoryName = category.name;
+	var escapedCategoryName = escape(categoryName);
+	var categoryCell = $('<td/>').attr('colspan', '2').addClass('name').text(categoryName);
+	var categoryRow = $('<tr/>').attr('id', categoryName).append(categoryCell);
+	$('#categories tbody').append(categoryRow).appendTo('#categories');
+	$('<option/>').attr('value', categoryName).text(categoryName).appendTo('#editTaskCategory');
+}
+
+function addTask(task) {
+	var parent = $('[id=' + task.category + ']');
+	var nameCell = $('<td/>').append($('<span/>').addClass('name').text(task.name));
+	var doneButton = $('<img/>').attr('src', 'img/task-done.png').attr('title', 'Resolve this task').click(function(event) {
+		event.preventDefault();
+		task.resolved = "true";
+		putTask(task, function() {
+			var taskList = categories[task.category].tasks;
+			delete categories[task.category].tasks[task.id];
+			$('#' + task.id).remove();
+		});
+	});
+	var editButton = $('<img/>').attr('src', 'img/task-edit.png').attr('title', 'Edit this task').click(function(event) {
+		event.preventDefault();
+		if ($('#' + task.id + ' #updateTask').size() == 0) {
+			showTaskEditForm(task);
+		} else {
+			removeTaskEditForm(task);
+		}
+	});
+	var deleteButton = $('<img/>').attr('src', 'img/task-delete.png').attr('title', 'Delete this task').click(function(event) {
+		event.preventDefault();
+		deleteTask(task, function() {
+			var taskList = categories[task.category].tasks;
+			delete categories[task.category].tasks[task.id];
+			$('#' + task.id).remove();
+		});
+	});
+	var buttonCell = $('<td/>').append(doneButton).append(editButton).append(deleteButton);
+	$('<tr/>').attr('id', task.id).append(buttonCell).append(nameCell).insertAfter('[id=' + task.category + ']');
+}
+
+function removeTaskEditForm(task)
+{
+	$('#' + task.id + ' form').replaceWith($('<span/>').addClass('name').text(task.name));	
+}
+
+function setupNewTaskForm()
+{
+	$('#editTaskSubmit').click(function() {
+		var name = $('#editTaskName').val();
+		var categoryName = $('#editTaskCategory').val()
+		postTask(categoryName, name, function(response) {
+			var location = response.getResponseHeader('Location');
+			// reset form value
+			$('#editTaskName').val('');
+			getTask(location, function(data) {
+				addTask(data.task);
+			});
+		});
+	});
+}

Added: modules/resteasy/trunk/examples/tasks/src/main/webapp/tasks.html
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/main/webapp/tasks.html	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/main/webapp/tasks.html	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,45 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<title>Seam Tasks</title>
+<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
+<script type="text/javascript" src="json2.js"></script>
+<script src="seam-tasks-client-json.js" type="text/javascript"></script>
+<link href="style.css" rel="stylesheet" type="text/css" />
+<script src="tasks-json.js" type="text/javascript"></script>
+</head>
+<body>
+<div class="container">
+<div class="header">
+<h1>Seam Tasks</h1>
+<ul id="menu">
+	<li><a href="tasks.html">Tasks</a></li>
+	<li><a href="categories.html">Categories</a></li>
+	<li><a href="resolved.html">Resolved tasks</a></li>
+</ul>
+</div>
+<div id="content">
+<table id="categories">
+	<thead>
+		<tr>
+			<td colspan="2">
+			<h2>Yet, unresolved tasks.</h2>
+			</td>
+		</tr>
+	</thead>
+	<tbody />
+</table>
+<hr />
+<form id="newTask">
+<h2>Create new task</h2>
+<select id="editTaskCategory" /> <input id="editTaskName" type="text" />
+<input id="editTaskSubmit" type="button" value="Create" /></form>
+</div>
+<div id="footer">
+<hr />
+<div>Powered by Seam 3, Java EE 6 and jQuery. Find more at <span><a href="http://seamframework.org">seamframework.org</a></span></div>
+</div>
+</div>
+</body>
+</html>

Added: modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/AbstractPage.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/AbstractPage.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/AbstractPage.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 org.jboss.seam.resteasy.example.tasks.ftest;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.jboss.test.selenium.encapsulated.JavaScript;
+import org.jboss.test.selenium.framework.AjaxSelenium;
+import org.jboss.test.selenium.locator.JQueryLocator;
+import org.jboss.test.selenium.waiting.Wait;
+import org.jboss.test.selenium.waiting.conditions.ElementPresent;
+
+import static org.jboss.test.selenium.locator.LocatorFactory.jq;
+
+/**
+ * This abstract page class contains common methods for all the pages.
+ * @author Jozef Hartinger
+ *
+ */
+public abstract class AbstractPage
+{
+   public static final JQueryLocator TASK_NAME = jq("#{0} .name");
+   public static final JQueryLocator CATEGORY_NAME = jq("#{0} .name");
+   public static final JavaScript JQUERY_IDLE_CONNECTION = new JavaScript("selenium.browserbot.getCurrentWindow().jQuery.active===0");
+   public static final JQueryLocator PAGE_INITIALIZED = jq("body[initialized=true]");
+
+   protected AjaxSelenium selenium;
+   protected URL contextPath;
+
+   public AbstractPage(AjaxSelenium selenium, URL contextPath)
+   {
+      this.selenium = selenium;
+      this.contextPath = contextPath;
+      reload();
+   }
+
+   /**
+    * Return url of the page
+    */
+   public abstract String getPageSuffix();
+
+   public void reload()
+   {
+      URL url;
+      try
+      {
+         url = new URL(contextPath.toString() + getPageSuffix());
+      }
+      catch (MalformedURLException e)
+      {
+         throw new RuntimeException(e);
+      }
+
+      // firefox sometimes freezes, if that happens, let's give it two more tries
+      for (int i = 0; i < 3; i++)
+      {
+         try
+         {
+            selenium.open(url);
+            selenium.waitForPageToLoad();
+            Wait.waitSelenium().interval(1000).until(ElementPresent.getInstance().locator(PAGE_INITIALIZED));
+            break;
+         }
+         catch (Exception e)
+         {
+            continue;
+         }
+      }
+   }
+
+   public void waitForJQuery()
+   {
+      selenium.waitForCondition(JQUERY_IDLE_CONNECTION);
+   }
+
+   public JQueryLocator getTaskNameLocator(int id)
+   {
+      return TASK_NAME.format(id);
+   }
+
+   public ResolvedPage goToResolvedPage()
+   {
+      return new ResolvedPage(selenium, contextPath);
+   }
+
+   public TaskPage goToTaskPage()
+   {
+      return new TaskPage(selenium, contextPath);
+   }
+
+   public CategoryPage goToCategoryPage()
+   {
+      return new CategoryPage(selenium, contextPath);
+   }
+
+   public boolean isTaskPresent(int id)
+   {
+      return selenium.isElementPresent(getTaskNameLocator(id));
+   }
+
+   public boolean isTaskPresent(int id, String name)
+   {
+      return isTaskPresent(id) && selenium.getText(getTaskNameLocator(id)).equals(name);
+   }
+
+   public boolean isCategoryPresent(String name)
+   {
+      return selenium.isElementPresent(CATEGORY_NAME.format(name));
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/CategoryPage.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/CategoryPage.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/CategoryPage.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 org.jboss.seam.resteasy.example.tasks.ftest;
+
+import java.net.URL;
+
+import org.jboss.test.selenium.framework.AjaxSelenium;
+import org.jboss.test.selenium.locator.JQueryLocator;
+import static org.jboss.test.selenium.locator.LocatorFactory.jq;
+import static org.jboss.test.selenium.guard.request.RequestTypeGuardFactory.waitXhr;
+
+/**
+ * Page object for the category page (categories.html)
+ * @author Jozef Hartinger
+ *
+ */
+public class CategoryPage extends AbstractPage
+{
+   public static final JQueryLocator NEW_CATEGORY_NAME = jq("#editCategoryName");
+   public static final JQueryLocator NEW_CATEGORY_SUBMIT = jq("#editCategorySubmit");
+   public static final JQueryLocator CATEGORY_DELETE_BUTTON = jq("#{0} img:first");
+   
+   public CategoryPage(AjaxSelenium selenium, URL contextPath)
+   {
+      super(selenium, contextPath);
+      reload();
+   }
+
+   @Override
+   public String getPageSuffix()
+   {
+      return "categories.html";
+   }
+   
+   public void newCategory(String name)
+   {
+      selenium.type(NEW_CATEGORY_NAME, name);
+      waitXhr(selenium).click(NEW_CATEGORY_SUBMIT);
+   }
+   
+   public void deleteCategory(String name)
+   {
+      waitXhr(selenium).click(CATEGORY_DELETE_BUTTON.format(name));
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/CategoryPageTest.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/CategoryPageTest.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/CategoryPageTest.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 org.jboss.seam.resteasy.example.tasks.ftest;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+
+import org.jboss.test.selenium.AbstractTestCase;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for the category page (categories.html)
+ * @author Jozef Hartinger
+ *
+ */
+public class CategoryPageTest extends AbstractTestCase
+{
+   private CategoryPage page;
+
+   @BeforeMethod
+   public void openCategoryPage()
+   {
+      if (page == null)
+      {
+         page = new CategoryPage(selenium, contextPath);
+      }
+      page.reload();
+   }
+
+   @Test
+   public void testContent()
+   {
+      assertTrue(page.isCategoryPresent("School"));
+      assertTrue(page.isCategoryPresent("Buy"));
+   }
+
+   @Test
+   public void testAddingCategory()
+   {
+      String name = "Home";
+      page.newCategory(name);
+      assertTrue(page.isCategoryPresent(name));
+      page.reload(); // verify changes are stored on the server
+      assertTrue(page.isCategoryPresent(name));
+      assertTrue(page.goToTaskPage().isCategoryPresent(name));
+   }
+
+   @Test
+   public void testRemovingCategory()
+   {
+      String name = "Work";
+      assertTrue(page.isCategoryPresent(name));
+      page.deleteCategory(name);
+      assertFalse(page.isCategoryPresent(name));
+      page.reload(); // verify changes are stored on the server
+      assertFalse(page.isCategoryPresent(name));
+      assertFalse(page.goToTaskPage().isCategoryPresent(name));
+      assertFalse(page.goToTaskPage().isTaskPresent(6)); // cascaded delete
+   }
+}
\ No newline at end of file

Added: modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/ResolvedPage.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/ResolvedPage.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/ResolvedPage.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 org.jboss.seam.resteasy.example.tasks.ftest;
+
+import static org.jboss.test.selenium.guard.request.RequestTypeGuardFactory.waitXhr;
+import static org.jboss.test.selenium.locator.LocatorFactory.jq;
+
+import java.net.URL;
+
+import org.jboss.test.selenium.framework.AjaxSelenium;
+import org.jboss.test.selenium.locator.JQueryLocator;
+
+/**
+ * Page object for the resolved tasks page (resolved.html)
+ * @author Jozef Hartinger
+ *
+ */
+public class ResolvedPage extends AbstractPage
+{
+   public static final JQueryLocator NEXT_LINK = jq(".next");
+   public static final JQueryLocator PREVIOUS_LINK = jq(".previous");
+   public static final JQueryLocator TASK_UNDO = jq("#{0} td:first img:first");
+
+   public ResolvedPage(AjaxSelenium selenium, URL contextPath)
+   {
+      super(selenium, contextPath);
+      reload();
+   }
+
+   @Override
+   public String getPageSuffix()
+   {
+      return "resolved.html";
+   }
+   
+   public void undoTask(int id)
+   {
+      waitXhr(selenium).click(TASK_UNDO.format(id));
+   }
+
+   public void next()
+   {
+      waitXhr(selenium).click(NEXT_LINK);
+      waitForJQuery();
+   }
+
+   public void previous()
+   {
+      waitXhr(selenium).click(PREVIOUS_LINK);
+      waitForJQuery();
+   }
+
+   public boolean isNextAvailable()
+   {
+      return selenium.isVisible(NEXT_LINK);
+   }
+
+   public boolean isPreviousAvailable()
+   {
+      return selenium.isVisible(PREVIOUS_LINK);
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/ResolvedPageTest.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/ResolvedPageTest.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/ResolvedPageTest.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 org.jboss.seam.resteasy.example.tasks.ftest;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+
+import org.jboss.test.selenium.AbstractTestCase;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for the resolved tasks page (resolved.html)
+ * @author Jozef Hartinger
+ *
+ */
+public class ResolvedPageTest extends AbstractTestCase
+{
+   private ResolvedPage page;
+
+   @BeforeMethod
+   public void openResolvedPage()
+   {
+      if (page == null)
+      {
+         page = new ResolvedPage(selenium, contextPath);
+      }
+      page.reload();
+   }
+
+   @Test
+   public void contentTest()
+   {
+      assertTrue(page.isTaskPresent(5, "Print study materials"));
+      assertTrue(page.isTaskPresent(10, "Buy a turtle"));
+      assertTrue(page.isTaskPresent(11, "Buy new shoes"));
+      assertTrue(page.isTaskPresent(13, "Learn to fly"));
+   }
+
+   @Test
+   public void paginationTest()
+   {
+      assertTrue(page.isNextAvailable());
+      assertFalse(page.isPreviousAvailable());
+      page.next();
+      assertTrue(page.isTaskPresent(18, "Tidy up"));
+      assertFalse(page.isNextAvailable());
+      page.previous();
+      assertTrue(page.isNextAvailable());
+      assertFalse(page.isPreviousAvailable());
+   }
+
+   @Test
+   public void testUndo()
+   {
+      int taskId = 12;
+
+      assertTrue(page.isTaskPresent(taskId));
+      page.undoTask(taskId);
+
+      assertFalse(page.isTaskPresent(taskId));
+      page.reload(); // verify changes are stored on the server
+      assertFalse(page.isTaskPresent(taskId));
+
+      assertTrue(page.goToTaskPage().isTaskPresent(taskId));
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/TaskPage.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/TaskPage.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/TaskPage.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,112 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 org.jboss.seam.resteasy.example.tasks.ftest;
+
+import java.net.URL;
+
+import org.jboss.test.selenium.framework.AjaxSelenium;
+import org.jboss.test.selenium.locator.JQueryLocator;
+import org.jboss.test.selenium.locator.option.OptionLocator;
+import org.jboss.test.selenium.locator.option.OptionValueLocator;
+
+import static org.jboss.test.selenium.guard.request.RequestTypeGuardFactory.waitXhr;
+import static org.jboss.test.selenium.locator.LocatorFactory.jq;
+import static org.jboss.test.selenium.locator.option.OptionLocatorFactory.optionValue;
+
+/**
+ * Page object for the tasks page (tasks.html)
+ * @author Jozef Hartinger
+ *
+ */
+public class TaskPage extends AbstractPage
+{
+   public static final JQueryLocator NEW_TASK_NAME_FIELD = jq("#editTaskName");
+   public static final JQueryLocator NEW_TASK_CATEGORY_SELECT = jq("#editTaskCategory");
+   public static final JQueryLocator NEW_TASK_SUBMIT = jq("#editTaskSubmit");
+   public static final JQueryLocator TASK_BY_NAME = jq(".name:contains('{0}')");
+   public static final JQueryLocator TASK_BY_ID_AND_CATEGORY = jq("#{0} ~ #{1}:first .name");
+
+   public static final JQueryLocator TASK_DONE_BUTTON = jq("#{0} img:first");
+   public static final JQueryLocator TASK_DELETE_BUTTON = jq("#{0} img:last");
+   public static final JQueryLocator TASK_EDIT_BUTTON = jq("#{0} img:nth-child(2)");
+   public static final JQueryLocator TASK_EDIT_FORM = jq("#{0} .updateTask");
+   public static final JQueryLocator TASK_EDIT_NAME_FIELD = jq("#{0} .nameField");
+   public static final JQueryLocator TASK_EDIT_CATEGORY_SELECT = jq("#{0} #editTaskCategory");
+   public static final OptionLocator<OptionValueLocator> TASK_CATEGORY_OPTION = optionValue("{0}");
+
+   public static final JQueryLocator TASK_EDIT_UPDATE_BUTTON = jq("#{0} #update");
+
+   public TaskPage(AjaxSelenium selenium, URL contextPath)
+   {
+      super(selenium, contextPath);
+      reload();
+   }
+
+   @Override
+   public String getPageSuffix()
+   {
+      return "tasks.html";
+   }
+
+   public void newTask(String name, String category)
+   {
+      selenium.type(NEW_TASK_NAME_FIELD, name);
+      selenium.select(NEW_TASK_CATEGORY_SELECT, TASK_CATEGORY_OPTION.format(category));
+      waitXhr(selenium).click(NEW_TASK_SUBMIT);
+   }
+
+   public boolean isTaskPresent(String taskName)
+   {
+      return selenium.isElementPresent(TASK_BY_NAME.format(taskName));
+   }
+
+   public boolean isTaskPresent(String categoryName, int taskId)
+   {
+      return selenium.isElementPresent(TASK_BY_ID_AND_CATEGORY.format(categoryName, taskId));
+   }
+
+   public boolean isTaskPresent(String categoryName, int taskId, String taskName)
+   {
+      return isTaskPresent(categoryName, taskId) && selenium.getText(TASK_BY_ID_AND_CATEGORY.format(categoryName, taskId)).equals(taskName);
+   }
+
+   public void resolveTask(int id)
+   {
+      waitXhr(selenium).click(TASK_DONE_BUTTON.format(id));
+   }
+
+   public void editTask(int id, String taskName, String categoryName)
+   {
+      selenium.click(TASK_EDIT_BUTTON.format(id));
+      waitForJQuery();
+      selenium.type(TASK_EDIT_NAME_FIELD.format(id), taskName);
+      // for some reason we need to hit the select first
+      selenium.isElementPresent(TASK_EDIT_CATEGORY_SELECT.format(id));
+      selenium.select(TASK_EDIT_CATEGORY_SELECT.format(id), TASK_CATEGORY_OPTION.format(categoryName));
+      waitXhr(selenium).click(TASK_EDIT_UPDATE_BUTTON.format(id));
+   }
+
+   public void removeTask(int id)
+   {
+      waitXhr(selenium).click(TASK_DELETE_BUTTON.format(id));
+   }
+
+   public boolean isEditFormPresent(int id)
+   {
+      return selenium.isElementPresent(TASK_EDIT_FORM.format(id));
+   }
+}

Added: modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/TaskPageTest.java
===================================================================
--- modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/TaskPageTest.java	                        (rev 0)
+++ modules/resteasy/trunk/examples/tasks/src/test/java/org/jboss/seam/resteasy/example/tasks/ftest/TaskPageTest.java	2010-10-07 08:28:16 UTC (rev 13802)
@@ -0,0 +1,126 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 org.jboss.seam.resteasy.example.tasks.ftest;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+
+import org.jboss.test.selenium.AbstractTestCase;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for the tasks page (tasks.html)
+ * @author Jozef Hartinger
+ *
+ */
+public class TaskPageTest extends AbstractTestCase
+{
+   private TaskPage page;
+
+   @BeforeMethod
+   public void openTaskPage()
+   {
+      if (page == null)
+      {
+         page = new TaskPage(selenium, contextPath);
+      }
+      page.reload();
+   }
+
+   @Test
+   public void testNewTask()
+   {
+      String task = "Learn GIT";
+      page.newTask(task, "School");
+      assertTrue(page.isTaskPresent(task));
+      page.reload();
+      assertTrue(page.isTaskPresent(task));
+   }
+
+   @Test
+   public void testIllegalTaskName()
+   {
+      page.newTask("", "School");
+      assertTrue(selenium.isAlertPresent());
+      assertEquals(selenium.getAlert().trim(), "size must be between 1 and 100");
+   }
+
+   @Test
+   public void testRenamingTask()
+   {
+      int id = 7;
+      String task = "Buy yoghurt";
+      String category = "Buy";
+      page.editTask(id, task, category);
+      assertFalse(page.isEditFormPresent(id));
+      assertTrue(page.isTaskPresent(category, id, task));
+      assertFalse(page.isTaskPresent("Buy milk")); // the old name
+      page.reload();
+      assertTrue(page.isTaskPresent(category, id, task));
+      assertFalse(page.isTaskPresent("Buy milk"));
+   }
+
+   @Test
+   public void testMovingTask()
+   {
+      int id = 8;
+      String name = "Buy an infinite tape";
+      String newCategory = "School";
+      assertTrue(page.isTaskPresent(id, name));
+      page.editTask(id, name, newCategory);
+      assertTrue(page.isTaskPresent(newCategory, id, name));
+      page.reload(); // verify changes are stored on the server
+      assertTrue(page.isTaskPresent(newCategory, id, name));
+   }
+
+   @Test
+   public void testRemovingTask()
+   {
+      assertTrue(page.isTaskPresent(3, "Learn new vocab for English conversations"));
+      page.removeTask(3);
+      assertFalse(page.isTaskPresent(3));
+      page.reload(); // verify changes are stored on the server
+      assertFalse(page.isTaskPresent(3));
+   }
+
+   @Test
+   public void testContent()
+   {
+      assertTrue(page.isCategoryPresent("School"));
+      assertTrue(page.isCategoryPresent("Buy"));
+      assertTrue(page.isTaskPresent("School", 4, "Prepare a presentation for webdesign seminar"));
+      assertTrue(page.isTaskPresent("School", 2, "Finish the RESTEasy-Seam integration example"));
+      assertTrue(page.isTaskPresent("School", 1, "Build the Turing machine"));
+      assertTrue(page.isTaskPresent(16, "Get a haircut"));
+      assertTrue(page.isTaskPresent(15, "Extend passport"));
+      assertTrue(page.isTaskPresent(14, "Visit grandma"));
+   }
+
+   @Test
+   public void testResolvingTask()
+   {
+      int taskId = 9;
+      assertTrue(page.isTaskPresent(taskId, "Order books"));
+      page.resolveTask(taskId);
+      assertFalse(page.isTaskPresent(taskId));
+      page.reload(); // verify changes are stored on the server
+      assertFalse(page.isTaskPresent(taskId));
+      assertTrue(page.goToResolvedPage().isTaskPresent(taskId));
+   }
+}



More information about the seam-commits mailing list