changeset 2523:27a5dff62edc 8.0-b76

branch merge
author David Grieve<david.grieve@oracle.com>
date Wed, 06 Feb 2013 10:28:22 -0500
parents 5fdb62478264 db6fc38a2116
children d39f91a06d08 a2a4de77db5f ee1e4c0502d4 d28efedf73e3
files javafx-concurrent/test/javafx/concurrent/AbstractService.java javafx-sg-common/src/com/sun/javafx/sg/DirtyRegionContainer.java javafx-sg-common/src/com/sun/javafx/sg/DirtyRegionPool.java javafx-sg-common/src/com/sun/javafx/sg/PGSpan.java javafx-sg-common/src/com/sun/javafx/sg/PGTextHelper.java javafx-sg-common/test/com/sun/javafx/sg/DirtyRegionContainerTest.java javafx-sg-prism/src/com/sun/javafx/sg/prism/NGSpan.java javafx-sg-prism/src/com/sun/javafx/sg/prism/NGTextHelper.java test-stub-toolkit/src/com/sun/javafx/pgstub/StubSpan.java test-stub-toolkit/src/com/sun/javafx/pgstub/StubTextHelper.java
diffstat 589 files changed, 109250 insertions(+), 3075 deletions(-) [+]
line wrap: on
line diff
--- a/.classpath	Tue Feb 05 17:02:37 2013 -0800
+++ b/.classpath	Wed Feb 06 10:28:22 2013 -0500
@@ -43,6 +43,8 @@
 	<classpathentry kind="src" path="javafx-ui-controls/build/builders"/>
 	<classpathentry kind="src" path="javafx-util-converter/src"/>
 	<classpathentry kind="src" path="javafx-util-converter/test"/>
+	<classpathentry kind="src" path="javafx-embed-swing/src"/>
+	<classpathentry kind="src" path="javafx-embed-swt/src"/>
 	<classpathentry kind="src" path="pisces/src"/>
 	<classpathentry kind="src" path="test-stub-toolkit/src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
--- a/.idea/modules.xml	Tue Feb 05 17:02:37 2013 -0800
+++ b/.idea/modules.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -10,6 +10,8 @@
       <module fileurl="file://$PROJECT_DIR$/javafx-ui-controls/javafx-ui-controls.iml" filepath="$PROJECT_DIR$/javafx-ui-controls/javafx-ui-controls.iml" group="Controls" />
       <module fileurl="file://$PROJECT_DIR$/javafx-util-converter/javafx-util-converter.iml" filepath="$PROJECT_DIR$/javafx-util-converter/javafx-util-converter.iml" group="Core" />
       <module fileurl="file://$PROJECT_DIR$/test-stub-toolkit/test-stub-toolkit.iml" filepath="$PROJECT_DIR$/test-stub-toolkit/test-stub-toolkit.iml" group="Tools" />
+      <module fileurl="file://$PROJECT_DIR$/javafx-embed-swing/javafx-embed-swing.iml" filepath="$PROJECT_DIR$/javafx-embed-swing/javafx-embed-swing.iml" />
+      <module fileurl="file://$PROJECT_DIR$/javafx-embed-swt/javafx-embed-swt.iml" filepath="$PROJECT_DIR$/javafx-embed-swt/javafx-embed-swt.iml" />
     </modules>
   </component>
 </project>
--- a/build-defs.xml	Tue Feb 05 17:02:37 2013 -0800
+++ b/build-defs.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -439,7 +439,7 @@
                 <assertions>
                     <enable/>
                 </assertions>
-                <jvmarg line="${run.jvmargs}"/>
+                <jvmarg line="${run.jvmargs} -XX:-UseSplitVerifier"/>
             </junit>
             <fail if="tests.failed"/>
         </sequential>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build.gradle	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,225 @@
+/**
+ * The build script for JavaFX.
+ *
+ * Tasks to complete:
+ *  - special tasks for common needs, such as:
+ *      - updating copyright headers
+ *      - stripping trailing whitespace (?)
+ *  - checkstyle
+ *  - findbugs
+ *  - re needs?
+ *  - testing
+ *  - build check -- making sure the final artifact has the right bits
+ *  - API change check
+ *  - JavaDoc
+ *  - Pushing results to a repo?
+ *  - VersionInfo needs to be parameterized so hudson can produce valid values
+ *  - partial builds for compileXXX shaders isn't working (they also get compiled)
+ *  - ServiceWithSecurityManagerTest fails to complete when run from gradle.
+ */
+defaultTasks = ["assemble"]
+
+/******************************************************************************
+ *        Utility methods, variables                                          *
+ *****************************************************************************/
+String osName = System.properties["os.name"].toLowerCase();
+
+def swtFileName = { ->
+    String fileName = "";
+    if (osName.contains("mac") || osName.contains("darwin")) {
+        fileName = "org.eclipse.swt.cocoa.macosx.x86_64_3.7.2.v3740f.jar"
+    } else if (osName.contains("windows")) {
+        fileName = "org.eclipse.swt.win32.win32.x86_3.7.2.v3740f.jar"
+//                fileName = "org.eclipse.swt.win32.win32.x86_64_3.7.2.v3740f.jar"
+    } else if (osName.contains("linux")) {
+        fileName = "org.eclipse.swt.gtk.linux.x86_3.7.2.v3740f.jar"
+//                fileName = "org.eclipse.swt.gtk.linux.x86_64_3.7.2.v3740f.jar"
+    }
+    return fileName;
+}
+
+/******************************************************************************
+ *        Project definitions (dependencies, etc)                             *
+ *****************************************************************************/
+
+allprojects {
+    apply plugin: "java"
+    sourceCompatibility = 1.7 // NOTE: Cannot make 1.8 or testing doesn't work because ASM 4.0 used by gradle doesn't support 1.8 yet (not even in nightlies)
+    tasks.withType(Compile) { compile ->
+        compile.options.compilerArgs = ["-XDignore.symbol.file"]
+        /* The following 4 lines are a workaround for the fact that presently Gradle can't set the -XDignore.symbol.file
+           flag, because it appears that the Javac API is lacking support for it */
+        compile.options.debug = true
+        compile.options.fork = true
+        compile.options.forkOptions.executable = System.env["JAVA_HOME"] ? System.env["JAVA_HOME"] + "/bin/javac" : "javac"
+        compile.options.warnings = false
+    }
+    repositories {
+        mavenCentral()
+        ivy {
+            url "http://download.eclipse.org/eclipse/updates/3.7/R-3.7.2-201202080800/plugins/"
+            layout "pattern", {
+                artifact "[artifact]"
+            }
+        }
+    }
+}
+
+project(":build-tools") {
+    // Workaround for lack of Antrl 3 support in Gradle. By defining a configuration,
+    // we can then give it a class path and use that classpath to execute a java command
+    configurations {
+        antlr3
+    }
+
+    dependencies {
+        compile "org.antlr:antlr-runtime:3.4"
+        antlr3 "org.antlr:antlr-runtime:3.4"
+        antlr3 "org.antlr:stringtemplate:4.0.2@jar"
+        antlr3 "org.antlr:antlr:3.4@jar"
+        testCompile "junit:junit:4.8.2"
+    }
+
+    task generateGrammarSource(type: JavaExec) {
+        description = "Generate JSL parser from Antlr3 grammars"
+        def dest = "build/generated-src/antlr/com/sun/scenario/effect/compiler"
+        def src = "src/main/antlr"
+        inputs.dir file(src)
+        outputs.dir file(dest)
+        def grammars = fileTree(src).include("**/*.g")
+        main = "org.antlr.Tool"
+        classpath = configurations.antlr3
+        args = ["-o", dest, grammars.files].flatten()
+    }
+
+    compileJava {
+        dependsOn generateGrammarSource
+        source "build/generated-src/antlr/com/sun/scenario/effect/compiler"
+    }
+}
+
+project(":base") {
+    // TODO need to transform the VersionInfo in the src/build prior to compilation
+    dependencies {
+        compile project(":build-tools")
+        testCompile "junit:junit:4.8.2"
+    }
+
+    mkdir "build/generated-src/version-info"
+    def replacements = [BUILD_TIMESTAMP: new java.util.Date(),
+        HUDSON_JOB_NAME: "not_hudson",
+        HUDSON_BUILD_NUMBER: "0000",
+        PROMOTED_BUILD_NUMBER: "00",
+        PRODUCT_NAME: "javafx", // OpenJFX
+        RAW_VERSION: "8.0.0",
+        RELEASE_NAME: "8.0",
+        RELEASE_MILESTONE: "ea"];
+    task processVersion(type: Copy, description: "Replace params in VersionInfo and copy file to destination") {
+        from "src/main/version-info"
+        into "build/generated-src/version-info/com/sun/javafx/runtime"
+        filter {line->
+            replacements.each() {k, v ->
+                line = line.replace("@${k}@", v.toString());
+            }
+            line
+        }
+    }
+
+    sourceSets.main.java.srcDirs = ["src/main/java", "build/generated-src/version-info"]
+    compileJava.dependsOn processVersion
+}
+
+project(":graphics") {
+    sourceSets.main.java.srcDirs = ["src/main/java", "src/main/dt", "src/main/jsl-generator"]
+
+    dependencies {
+        compile project(":base"), project(":build-tools")
+        compile ":$swtFileName:"
+        compile files(rootDir.toString() + "/../crap/plugin_exports.jar")
+        testCompile "junit:junit:4.8.2"
+    }
+
+    task compileJSL(description: "Compile Java Shader Language (JSL) files") { }
+    classes.dependsOn compileJSL
+
+    // TODO need to exclude sources from jsl-generator in the file jar!
+    [[fileName: "ColorAdjust", generator: "CompileJSL", outputs: "-all"],
+            [fileName: "Brightpass", generator: "CompileJSL", outputs: "-all"],
+            [fileName: "SepiaTone", generator: "CompileJSL", outputs: "-all"],
+            [fileName: "PerspectiveTransform", generator: "CompileJSL", outputs: "-all"],
+            [fileName: "DisplacementMap", generator: "CompileJSL", outputs: "-all"],
+            [fileName: "InvertMask", generator: "CompileJSL", outputs: "-all"],
+            [fileName: "Blend", generator: "CompileBlend", outputs: "-all"],
+            [fileName: "PhongLighting", generator: "CompilePhong", outputs: "-all"],
+            [fileName: "LinearConvolve", generator: "CompileLinearConvolve", outputs: "-hw"],
+            [fileName: "LinearConvolveShadow", generator: "CompileLinearConvolve", outputs: "-hw"]].each { settings ->
+        task "compile$settings.fileName"(dependsOn: compileJava, type: JavaExec) {
+            description = "Generate $settings.fileName shader from JSL"
+            mkdir "modules/graphics/build/generated-src/jsl"
+            def destinationDir = "build/generated-src/jsl"
+            def sourceDir = "src/main/jsl"
+            inputs.dir file(sourceDir)
+            outputs.dir file(destinationDir)
+            main = settings.generator
+            classpath = configurations.compile
+            classpath += files("modules/graphics/build/classes/main")
+            args = ["-i", sourceDir, "-o", destinationDir, "-pkg", "com/sun/scenario/effect", "$settings.outputs", "$settings.fileName"].flatten()
+        }
+        compileJSL.dependsOn "compile$settings.fileName"
+    }
+
+    task compileDecoraJava(dependsOn: compileJSL, type: JavaCompile) {
+        description = "Compile Java-based Decora-JSL files"
+        classpath = configurations.compile
+        classpath += files("build/classes/main")
+        source = ["build/generated-src/jsl/decora-jsw/build/gensrc",
+                "build/generated-src/jsl/decora-prism-ps/build/gensrc",
+                "build/generated-src/jsl/decora-sse/build/gensrc"]
+        destinationDir = file("build/classes/main")
+    }
+    classes.dependsOn compileDecoraJava
+
+    task copyShaders(dependsOn: compileJSL, type: Copy, description: "Copy hlsl / frag shaders to build/resources/main") {
+        from("build/generated-src/jsl/decora-d3d/build/gensrc") {
+            include "**/*.hlsl"
+        }
+        from("build/generated-src/jsl/decora-es2/bulid/gensrc") {
+            include("**/*.frag")
+        }
+
+        into "build/resources/main"
+    }
+    processResources.dependsOn copyShaders
+//
+//    test {
+//        systemProperty "javafx.toolkit", "com.sun.javafx.pgstub.StubToolkit"
+//    }
+
+    // TODO Need to compile the Decora SSE Natives now! I don't yet know how to compile natives
+}
+
+project(":controls") {
+    dependencies {
+        compile project(":build-tools"), project(":base"), project(":graphics")
+    }
+}
+
+project(":swing") {
+    dependencies {
+        compile project(":build-tools"), project(":base"), project(":graphics")
+    }
+}
+
+project(":swt") {
+    dependencies {
+        compile project(":build-tools"), project(":base"), project(":graphics")
+        compile ":$swtFileName:"
+    }
+}
+
+project(":fxml") {
+    dependencies {
+        compile project(":build-tools"), project(":base"), project(":graphics"),
+                project(":controls"), /*project(":media"), project(":web"),*/ project(":swt"), project(":swing")
+    }
+}
\ No newline at end of file
--- a/build.xml	Tue Feb 05 17:02:37 2013 -0800
+++ b/build.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -62,6 +62,7 @@
         <ant antfile="${rt.root.dir}/javafx-concurrent/build.xml" target="jar" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-logging/build.xml" target="jar" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-anim/build.xml" target="jar" inheritAll="false"/>
+        <ant antfile="${rt.root.dir}/javafx-beans/build.xml" target="jar" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-common/build.xml" target="jar" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-annotation-processor/build.xml" target="jar" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-sg-common/build.xml" target="jar" inheritAll="false"/>
@@ -73,6 +74,12 @@
         <ant antfile="${rt.root.dir}/javafx-ui-controls/build.xml" target="jar" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-ui-charts/build.xml" target="jar" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-fxml/build.xml" target="jar" inheritAll="false"/>
+        <ant antfile="${rt.root.dir}/javafx-embed-swing/build.xml" target="jar" inheritAll="false"/>
+        <antcall target="jar-javafx-embed-swt"/>
+    </target>
+
+    <target name="jar-javafx-embed-swt" if="swt.available">
+        <ant antfile="${rt.root.dir}/javafx-embed-swt/build.xml" target="jar" inheritAll="false"/>
     </target>
 
     <!--
@@ -87,6 +94,7 @@
         <ant antfile="${rt.root.dir}/javafx-ui-charts/build.xml" target="test" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-logging/build.xml" target="test" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-anim/build.xml" target="test" inheritAll="false"/>
+        <ant antfile="${rt.root.dir}/javafx-beans/build.xml" target="test" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-common/build.xml" target="test" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-annotation-processor/build.xml" target="test" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-sg-common/build.xml" target="test" inheritAll="false"/>
@@ -96,6 +104,12 @@
         <ant antfile="${rt.root.dir}/pisces/build.xml" target="test" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-util-converter/build.xml" target="test" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-fxml/build.xml" target="test" inheritAll="false"/>
+        <ant antfile="${rt.root.dir}/javafx-embed-swing/build.xml" target="test" inheritAll="false"/>
+        <antcall target="test-javafx-embed-swt"/>
+    </target>
+
+    <target name="test-javafx-embed-swt" if="swt.available">
+        <ant antfile="${rt.root.dir}/javafx-embed-swt/build.xml" target="test" inheritAll="false"/>
     </target>
 
     <!--
@@ -112,6 +126,7 @@
         <ant antfile="${rt.root.dir}/javafx-ui-charts/build.xml" target="clean" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-logging/build.xml" target="clean" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-anim/build.xml" target="clean" inheritAll="false"/>
+        <ant antfile="${rt.root.dir}/javafx-beans/build.xml" target="clean" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-common/build.xml" target="clean" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-annotation-processor/build.xml" target="clean" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-sg-common/build.xml" target="clean" inheritAll="false"/>
@@ -121,6 +136,12 @@
         <ant antfile="${rt.root.dir}/pisces/build.xml" target="clean" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-util-converter/build.xml" target="clean" inheritAll="false"/>
         <ant antfile="${rt.root.dir}/javafx-fxml/build.xml" target="clean" inheritAll="false"/>
+        <ant antfile="${rt.root.dir}/javafx-embed-swing/build.xml" target="clean" inheritAll="false"/>
+        <antcall target="clean-javafx-embed-swt"/>
+    </target>
+
+    <target name="clean-javafx-embed-swt" if="swt.available">
+        <ant antfile="${rt.root.dir}/javafx-embed-swt/build.xml" target="clean" inheritAll="false"/>
     </target>
  
     <!--
--- a/common.properties	Tue Feb 05 17:02:37 2013 -0800
+++ b/common.properties	Wed Feb 06 10:28:22 2013 -0500
@@ -16,7 +16,7 @@
 javac.debuglevel=${jfx.javac.debuglevel}
 javac.compilerargs=-XDignore.symbol.file
 javac.processorpath=\
-    ${runtime.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:\
+    ${rt.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:\
     ${rt.dist.root.dir}/javafx-annotation-processor/dist/javafx-annotation-processor.jar:\
     ${javac.classpath}
 javac.deprecation=false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/generator.gradle	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,205 @@
+/**
+ * This task will generate the new project layout structure for JavaFX. The entire new project
+ * structure is generated beneath a new directory simply called "javafx". The idea is that this
+ * could become a single repo under which all public JavaFX sources live (rather than where we
+ * presently have multiple repositories).
+ *
+ * Items left to do:
+ *  - javafx checkstyle
+ *  - media
+ *  - apps
+ *  - performance tests
+ *  - sqe tests
+ *  - unit tests
+ *  - manual tests (toys)
+ *  - media tests
+ *  - native code compilation
+ *  - aria project?
+ *  - iaccessible project?
+ *  - test-stub-toolkit
+ *  - README, README.md, license file, etc.
+ *  - How to handle dt *.properties?
+ *  - cagsrc double vs cagsrc float. Do we need to have both? We never use cagsrc.float now, so only
+ *    if we intended to use it on low end systems would we bother compiling with it, not sure we care.
+ */
+
+defaultTasks = ["generate"]
+RTDir = "."
+FXDir = "../javafx"
+task generate << {
+    def excludeResources = ["META-INF/**", "**/*.properties", "**/*.stg", "**/*.g", "**/*.css", "**/*.html", "**/*.png", "**/*.jpg"]
+    def includeResources = ["META-INF/**", "**/*.properties", "**/*.stg", "**/*.css", "**/*.html", "**/*.png", "**/*.jpg"]
+
+    // Copy over the new gradle build files
+    copy {
+        from RTDir
+        into FXDir
+        include "build.gradle", "settings.gradle"
+    }
+
+    // Create the build-tools project
+    copy {
+        from "${RTDir}/javafx-annotation-processor/src",
+             "${RTDir}/decora-compiler/src"
+        into "${FXDir}/build-tools/src/main/java"
+        exclude excludeResources
+    }
+    copy {
+        from "${RTDir}/javafx-annotation-processor/src",
+             "${RTDir}/decora-compiler/src"
+        into "${FXDir}/build-tools/src/main/resources"
+        include includeResources
+    }
+    copy {
+        from "${RTDir}/decora-compiler/src/com/sun/scenario/effect/compiler/JSL.g"
+        into "${FXDir}/build-tools/src/main/antlr"
+    }
+    copy {
+        from "${RTDir}/decora-compiler/test"
+        into "${FXDir}/build-tools/src/test/java"
+        exclude excludeResources
+    }
+    copy {
+        from "${RTDir}/decora-compiler/test"
+        into "${FXDir}/build-tools/src/test/resources"
+        include includeResources
+    }
+
+    // Create the base module
+    copy {
+        from "${RTDir}/javafx-util-converter/src",
+             "${RTDir}/javafx-anim/src",
+             "${RTDir}/javafx-common/src",
+             "${RTDir}/javafx-logging/src"
+        into "${FXDir}/modules/base/src/main/java"
+        exclude "com/sun/javafx/beans/annotations/**",
+                "com/sun/javafx/collections/annotations/**"
+        exclude excludeResources
+    }
+    copy {
+        from "${RTDir}/javafx-util-converter/src",
+             "${RTDir}/javafx-anim/src",
+             "${RTDir}/javafx-common/src",
+             "${RTDir}/javafx-logging/src"
+        into "${FXDir}/modules/base/src/main/resources"
+        include includeResources
+    }
+    copy {
+        from "${RTDir}/javafx-common/build-tools"
+        into "${FXDir}/modules/base/src/main/version-info"
+    }
+    copy {
+        from "${RTDir}/javafx-util-converter/test",
+             "${RTDir}/javafx-anim/test/unit", // TODO also has functional tests
+             "${RTDir}/javafx-common/test/unit"
+        into "${FXDir}/modules/base/src/test/java"
+        exclude excludeResources
+    }
+    copy {
+        from "${RTDir}/javafx-util-converter/test",
+             "${RTDir}/javafx-anim/test/unit", // TODO also has functional tests
+             "${RTDir}/javafx-common/test/unit"
+        into "${FXDir}/modules/base/src/test/resources"
+        include includeResources
+    }
+
+    // Create the graphics module
+    copy {
+        from "${RTDir}/javafx-ui-common/src",
+             "${RTDir}/javafx-concurrent/src",
+             "${RTDir}/javafx-geom/src",
+             "${RTDir}/javafx-geom/cagsrc.double",
+             "${RTDir}/javafx-sg-common/src",
+             "${RTDir}/javafx-sg-prism/src",
+             "${RTDir}/pisces/src"
+        into "${FXDir}/modules/graphics/src/main/java"
+        exclude "com/sun/scenario/effect/compiler/JSL.g",
+                "com/sun/javafx/css/parser/jfxCssLexer.g",
+                "com/sun/javafx/css/parser/jfxCssParser.g"
+        exclude excludeResources
+    }
+    copy {
+        from "${RTDir}/javafx-ui-common/src",
+             "${RTDir}/javafx-concurrent/src",
+             "${RTDir}/javafx-geom/src",
+             "${RTDir}/javafx-geom/cagsrc.double",
+             "${RTDir}/javafx-sg-common/src",
+             "${RTDir}/javafx-sg-prism/src",
+             "${RTDir}/pisces/src"
+        into "${FXDir}/modules/graphics/src/main/resources"
+        include includeResources
+    }
+    copy {
+        from "${RTDir}/javafx-ui-common/test/unit",
+             "${RTDir}/javafx-concurrent/test",
+             "${RTDir}/javafx-geom/test",
+             "${RTDir}/javafx-sg-common/test",
+             "${RTDir}/javafx-sg-prism/test",
+             "${RTDir}/test-stub-toolkit/src"
+        into "${FXDir}/modules/graphics/src/test/java"
+        exclude excludeResources
+    }
+    copy {
+        from "${RTDir}/javafx-ui-common/test/unit",
+             "${RTDir}/javafx-concurrent/test",
+             "${RTDir}/javafx-geom/test",
+             "${RTDir}/javafx-sg-common/test",
+             "${RTDir}/javafx-sg-prism/test",
+             "${RTDir}/test-stub-toolkit/src"
+        into "${FXDir}/modules/graphics/src/test/resources"
+        include includeResources
+    }
+
+    copy {
+        from "${RTDir}/javafx-ui-common/src/com/sun/javafx/css/parser/jfxCssLexer.g",
+             "${RTDir}/javafx-ui-common/src/com/sun/javafx/css/parser/jfxCssParser.g"
+        into "${FXDir}/modules/graphics/src/main/antlr"
+    }
+
+    copy {
+        from "${RTDir}/javafx-beans-dt/src"
+        into "${FXDir}/modules/graphics/src/main/dt"
+    }
+    copy {
+        from "${RTDir}/javafx-designtime/src"
+        into "${FXDir}/modules/graphics/src/main/dt"
+        include "javafx/scene/ParentDesignInfo.java", "javafx/scene/layout/**", "com/**"
+    }
+
+    // Create the controls module
+    copy {
+        from "${RTDir}/javafx-ui-charts/src",
+             "${RTDir}/javafx-ui-controls/src"
+        into "${FXDir}/modules/controls/src/main/java"
+        exclude excludeResources
+    }
+    copy {
+        from "${RTDir}/javafx-ui-charts/src",
+             "${RTDir}/javafx-ui-controls/src"
+        into "${FXDir}/modules/controls/src/main/resources"
+        include includeResources
+    }
+    copy {
+        from "${RTDir}/javafx-designtime/src"
+        into "${FXDir}/modules/controls/src/main/dt"
+        include "javafx/scene/control/**"
+    }
+
+    // Create the web module
+
+    // Create the swing module
+
+    // Create the swt module
+
+    // Create the fxml module
+    copy {
+        from "${RTDir}/javafx-fxml/src"
+        into "${FXDir}/modules/fxml/src/main/java"
+        exclude excludeResources
+    }
+    copy {
+        from "${RTDir}/javafx-fxml/src"
+        into "${FXDir}/modules/fxml/src/main/resources"
+        include includeResources
+    }
+}
\ No newline at end of file
--- a/javafx-anim/build-closed.xml	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-anim/build-closed.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -5,7 +5,7 @@
     <property name="runtime.dist.root.dir" value="../../rt-closed" />    
     <property name="rt.dist.root.dir" value="../../rt" />
     <path id="javac.closed.classpath.path" path="
-        ${runtime.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:
+        ${rt.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:
         ${rt.dist.root.dir}/javafx-common/dist/javafx-common.jar" />
     <property name="javac.classpath" refid="javac.closed.classpath.path"/>
     
--- a/javafx-anim/src/com/sun/scenario/animation/NumberTangentInterpolator.java	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-anim/src/com/sun/scenario/animation/NumberTangentInterpolator.java	Wed Feb 06 10:28:22 2013 -0500
@@ -24,6 +24,7 @@
  */
 package com.sun.scenario.animation;
 
+import com.sun.javafx.animation.TickCalculation;
 import javafx.animation.Interpolator;
 import javafx.util.Duration;
 
@@ -33,14 +34,18 @@
 
     public abstract double getOutValue();
 
-    public abstract double getInMillis();
+    public abstract double getInTicks();
 
-    public abstract double getOutMillis();
+    public abstract double getOutTicks();
 
     public static NumberTangentInterpolator create(final double inValue,
             final Duration inDuration, final double outValue,
             final Duration outDuration) {
         return new NumberTangentInterpolator() {
+
+            private final long inTicks = TickCalculation.fromDuration(inDuration);
+            private final long outTicks = TickCalculation.fromDuration(outDuration);
+
             @Override
             public double getInValue() {
                 return inValue;
@@ -52,13 +57,13 @@
             }
 
             @Override
-            public double getInMillis() {
-                return inDuration.toMillis();
+            public double getInTicks() {
+                return inTicks;
             }
 
             @Override
-            public double getOutMillis() {
-                return outDuration.toMillis();
+            public double getOutTicks() {
+                return outTicks;
             }
 
             @Override
@@ -73,6 +78,9 @@
     public static NumberTangentInterpolator create(final double value,
             final Duration duration) {
         return new NumberTangentInterpolator() {
+
+        private final long ticks = TickCalculation.fromDuration(duration);
+
             @Override
             public double getInValue() {
                 return value;
@@ -84,13 +92,13 @@
             }
 
             @Override
-            public double getInMillis() {
-                return duration.toMillis();
+            public double getInTicks() {
+                return ticks;
             }
 
             @Override
-            public double getOutMillis() {
-                return duration.toMillis();
+            public double getOutTicks() {
+                return ticks;
             }
 
             @Override
--- a/javafx-anim/src/com/sun/scenario/animation/shared/InterpolationInterval.java	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-anim/src/com/sun/scenario/animation/shared/InterpolationInterval.java	Wed Feb 06 10:28:22 2013 -0500
@@ -24,6 +24,7 @@
  */
 package com.sun.scenario.animation.shared;
 
+import com.sun.javafx.animation.TickCalculation;
 import javafx.animation.Interpolator;
 import javafx.animation.KeyValue;
 import javafx.beans.value.WritableBooleanValue;
@@ -146,7 +147,7 @@
             final double p2Delta = (interpolator == null) ? 0 : (interpolator
                     .getInValue() - p3)
                     * duration
-                    / interpolator.getInMillis()
+                    / interpolator.getInTicks()
                     / 3;
             p2 = p3 + p2Delta;
         }
@@ -165,7 +166,7 @@
             final double p2Delta = (interpolator == null) ? 0 : (interpolator
                     .getInValue() - p3)
                     * duration
-                    / interpolator.getInMillis()
+                    / interpolator.getInTicks()
                     / 3;
             p2 = p3 + p2Delta;
         }
@@ -183,7 +184,7 @@
             p0 = leftValue;
             final double p1Delta = (leftInterpolator == null) ? 0
                     : (leftInterpolator.getOutValue() - p0) * duration
-                            / leftInterpolator.getOutMillis() / 3;
+                            / leftInterpolator.getOutTicks() / 3;
             p1 = p0 + p1Delta;
         }
     }
--- a/javafx-anim/src/javafx/animation/Animation.java	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-anim/src/javafx/animation/Animation.java	Wed Feb 06 10:28:22 2013 -0500
@@ -53,6 +53,7 @@
 
 import static com.sun.javafx.animation.TickCalculation.fromDuration;
 import com.sun.scenario.animation.AbstractMasterTimer;
+import javafx.beans.property.ObjectPropertyBase;
 
 /**
  * The class {@code Animation} provides the core functionality of all animations
@@ -318,12 +319,9 @@
     /**
      * Read-only variable to indicate the duration of one cycle of this
      * {@code Animation}: the time it takes to play from time 0 to the
-     * {@code KeyFrame} with the largest time (at the default {@code rate} of
+     * end of the Animation (at the default {@code rate} of
      * 1.0).
      * 
-     * <p>
-     * This is set to the largest time value of its keyFrames.
-     * 
      * @defaultValue 0ms
      */
     private ReadOnlyObjectProperty<Duration> cycleDuration;
@@ -331,6 +329,9 @@
 
     protected final void setCycleDuration(Duration value) {
         if ((cycleDuration != null) || (!DEFAULT_CYCLE_DURATION.equals(value))) {
+            if (value.lessThan(Duration.ZERO)) {
+                throw new IllegalArgumentException("Cycle duration cannot be negative");
+            }
             ((AnimationReadOnlyProperty<Duration>)cycleDurationProperty()).set(value);
             updateTotalDuration();
         }
@@ -433,6 +434,8 @@
 
     /**
      * Delays the start of an animation.
+     *
+     * Cannot be negative. Setting to a negative number will result in {@link IllegalArgumentException}.
      * 
      * @defaultValue 0ms
      */
@@ -451,7 +454,31 @@
 
     public final ObjectProperty<Duration> delayProperty() {
         if (delay == null) {
-            delay = new SimpleObjectProperty<Duration>(this, "delay", DEFAULT_DELAY);
+            delay = new ObjectPropertyBase<Duration>(DEFAULT_DELAY) {
+
+                @Override
+                public Object getBean() {
+                    return Animation.this;
+                }
+
+                @Override
+                public String getName() {
+                    return "delay";
+                }
+
+                @Override
+                protected void invalidated() {
+                        final Duration newDuration = get();
+                        if (newDuration.lessThan(Duration.ZERO)) {
+                            if (isBound()) {
+                                unbind();
+                            }
+                            set(Duration.ZERO);
+                            throw new IllegalArgumentException("Cannot set delay to negative value. Setting to Duration.ZERO");
+                        }
+                }
+                
+            };
         }
         return delay;
     }
--- a/javafx-anim/src/javafx/animation/Interpolator.java	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-anim/src/javafx/animation/Interpolator.java	Wed Feb 06 10:28:22 2013 -0500
@@ -205,20 +205,29 @@
      * 
      * A tangent interpolator defines the behavior to the left and to the right
      * of a key frame, therefore it is only useful within a {@link Timeline}.
+     * If used in a {@link KeyFrame} after a KeyFrame that has different interpolator,
+     * it's treated as if the out-tangent of that KeyFrame was equal to the value in the KeyFrame.
+     *
+     * <p>
+     * <img src="doc-files/tangent_interpolator.png"/>
      * 
+     * <p>
      * The parameters define the tangent of the animation curve for the in
      * tangent (before a key frame) and out tangent (after a key frame). Each
      * tangent is specified with a pair, the distance to the key frame and the
      * value of the tangent at this moment.
+     * <p>
+     * The interpolation then follows a bezier curve, with 2 control points defined by the specified tangent and
+     * positioned at 1/3 of the duration before the second KeyFrame or after the first KeyFrame. See the picture above.
      * 
      * @param t1
-     *            The delta time of the in-tangent
+     *            The delta time of the in-tangent, relative to the KeyFrame
      * @param v1
-     *            The value of the in-tangent, in degrees
+     *            The value of the in-tangent
      * @param t2
-     *            The delta time of the out-tangent
+     *            The delta time of the out-tangent, relative to the KeyFrame
      * @param v2
-     *            The value of the out-tangent, in degrees
+     *            The value of the out-tangent
      * @return the new tangent interpolator
      */
     public static Interpolator TANGENT(Duration t1, double v1, Duration t2,
@@ -237,7 +246,7 @@
      * @param t
      *            The delta time of the tangent
      * @param v
-     *            The value of the tangent, in degrees
+     *            The value of the tangent
      * @return the new Tangent interpolator
      */
     public static Interpolator TANGENT(Duration t, double v) {
--- a/javafx-anim/src/javafx/animation/Timeline.java	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-anim/src/javafx/animation/Timeline.java	Wed Feb 06 10:28:22 2013 -0500
@@ -50,6 +50,9 @@
  * time interval elapsed, it does not guarantee the timing when {@code KeyFrame}
  * is processed.
  * <p>
+ * The {@link #cycleDurationProperty()} will be set to the largest time value
+ * of Timeline's keyFrames.
+ * <p>
  * If a {@code KeyFrame} is not provided for the {@code time==0s} instant, one
  * will be synthesized using the target values that are current at the time
  * {@link #play()} or {@link #playFromStart()} is called.
Binary file javafx-anim/src/javafx/animation/doc-files/tangent_interpolator.png has changed
--- a/javafx-anim/test/unit/com/sun/scenario/animation/NumberTangentInterpolatorTest.java	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-anim/test/unit/com/sun/scenario/animation/NumberTangentInterpolatorTest.java	Wed Feb 06 10:28:22 2013 -0500
@@ -47,15 +47,15 @@
 	public void testCreate() {
 		final NumberTangentInterpolator interpolator1 = NumberTangentInterpolator.create(Math.PI, Duration.millis(2000));
 		assertEquals(Math.PI, interpolator1.getInValue(), EPSILON_DOUBLE);
-		assertEquals(2000.0, interpolator1.getInMillis(), EPSILON_DOUBLE);
+		assertEquals(12000.0, interpolator1.getInTicks(), EPSILON_DOUBLE);
 		assertEquals(Math.PI, interpolator1.getOutValue(), EPSILON_DOUBLE);
-		assertEquals(2000.0, interpolator1.getOutMillis(), EPSILON_DOUBLE);
+		assertEquals(12000.0, interpolator1.getOutTicks(), EPSILON_DOUBLE);
 
 		final NumberTangentInterpolator interpolator2 = NumberTangentInterpolator.create(Math.E, Duration.millis(500), -Math.PI, Duration.millis(1000));
 		assertEquals(Math.E, interpolator2.getInValue(), EPSILON_DOUBLE);
-		assertEquals(500.0, interpolator2.getInMillis(), EPSILON_DOUBLE);
+		assertEquals(3000.0, interpolator2.getInTicks(), EPSILON_DOUBLE);
 		assertEquals(-Math.PI, interpolator2.getOutValue(), EPSILON_DOUBLE);
-		assertEquals(1000.0, interpolator2.getOutMillis(), EPSILON_DOUBLE);
+		assertEquals(6000.0, interpolator2.getOutTicks(), EPSILON_DOUBLE);
 	}
 	
 	@Test
--- a/javafx-anim/test/unit/javafx/animation/InterpolatorTest.java	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-anim/test/unit/javafx/animation/InterpolatorTest.java	Wed Feb 06 10:28:22 2013 -0500
@@ -24,6 +24,11 @@
  */
 package javafx.animation;
 
+import com.sun.javafx.animation.TickCalculation;
+import com.sun.scenario.animation.shared.InterpolationInterval;
+import javafx.beans.property.Property;
+import javafx.beans.property.SimpleLongProperty;
+import javafx.util.Duration;
 import static org.junit.Assert.assertEquals;
 
 import org.junit.Test;
@@ -257,6 +262,25 @@
         assertEquals(1.8, i.interpolate(1.0, 2.0, 0.8), EPSILON);
         assertEquals(2.0, i.interpolate(1.0, 2.0, 1.0), EPSILON);
     }
+
+    @Test
+    public void testTANGENT_Linear() {
+        SimpleLongProperty property = new SimpleLongProperty();
+
+        Interpolator i0 = Interpolator.TANGENT(Duration.seconds(1), 20);
+        Interpolator i1 = Interpolator.TANGENT(Duration.seconds(1), 40);
+
+        InterpolationInterval interval = InterpolationInterval.create(new KeyValue(property, 60L, i1),
+                TickCalculation.fromDuration(Duration.seconds(3)),
+                new KeyValue(property, 0L, i0), TickCalculation.fromDuration(Duration.seconds(3)));
+
+        interval.interpolate(1.0/3.0);
+        assertEquals(20L, (long)property.getValue());
+        interval.interpolate(1.0/2.0);
+        assertEquals(30L, (long)property.getValue());
+        interval.interpolate(2.0/3.0);
+        assertEquals(40L, (long)property.getValue());
+    }
     
     private static class DummyInterpolatable implements Interpolatable<DummyInterpolatable> {
 
--- a/javafx-annotation-processor/build-closed.xml	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-annotation-processor/build-closed.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -6,7 +6,7 @@
     <property name="rt.dist.root.dir" value="../../rt" />    
     <path id="javac.closed.classpath.path" path="
         ${import.javac.jar}:
-        ${runtime.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:
+        ${rt.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:
         ${rt.dist.root.dir}/javafx-common/dist/javafx-common.jar" />
     <property name="javac.classpath" refid="javac.closed.classpath.path"/>
     
--- a/javafx-annotation-processor/nbproject/project.xml	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-annotation-processor/nbproject/project.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -100,7 +100,7 @@
         <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/2">
             <compilation-unit>
                 <package-root>${src.dir}</package-root>
-                <classpath mode="compile">../../rt-closed/javafx-beans/dist/javafx-beans.jar</classpath>
+                <classpath mode="compile">../javafx-beans/dist/javafx-beans.jar</classpath>
                 <built-to>dist/javafx-annotation-processor.jar</built-to>
                 <source-level>1.5</source-level>
             </compilation-unit>
--- a/javafx-beans-dt/build-closed.xml	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-beans-dt/build-closed.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -6,7 +6,7 @@
     <property name="rt.dist.root.dir" value="../../rt" />
     
     <path id="javac.closed.classpath.path" path="
-        ${runtime.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:
+        ${rt.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:
         ${rt.dist.root.dir}/javafx-common/dist/javafx-common.jar:
         ${rt.dist.root.dir}/javafx-ui-common/dist/javafx-ui-common.jar" />
     <property name="javac.classpath" refid="javac.closed.classpath.path"/>
--- a/javafx-beans-dt/project.properties	Tue Feb 05 17:02:37 2013 -0800
+++ b/javafx-beans-dt/project.properties	Wed Feb 06 10:28:22 2013 -0500
@@ -2,7 +2,7 @@
     ${runtime.dist.root.dir}/../artifacts/sdk/rt
 disable-lombok=true
 javac.classpath=\
-    ${runtime.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:\
+    ${rt.dist.root.dir}/javafx-beans/dist/javafx-beans.jar:\
     ${runtime.dist.root.dir}/javafx-common/dist/javafx-common.jar:\
     ${rt.dist.root.dir}/javafx-ui-common/dist/javafx-ui-common.jar:\
     ${JFXRT_HOME}/lib/ext/jfxrt.jar
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/build-closed.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="javafx-beans" default="jar" basedir=".">
+    <description>Builds, tests, and jars the closed version of the javafx-beans project.</description>
+    
+    <property name="rt.dist.root.dir" value="../../rt" />
+    <property name="runtime.dist.root.dir" value="../../rt-closed" />    
+    <path id="javac.closed.classpath.path" path="
+        ${rt.dist.root.dir}/javafx-logging/dist/javafx-logging.jar:
+        ${rt.dist.root.dir}/javafx-common/dist/javafx-common.jar" />
+    <property name="javac.classpath" refid="javac.closed.classpath.path"/>
+    
+    <import file="../build-defs.xml"/>
+    <import file="build-common.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/build-common.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="javafx-beans-common" default="jar" basedir=".">
+  <target name="debug-test-file" depends="jar">
+      <debug-selected-file-in-test/>
+  </target>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/build.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="javafx-beans" default="jar" basedir=".">
+    <description>Builds, tests, and runs the OpenJFX javafx-beans project.</description>
+
+    <import file="../build-defs.xml"/>
+    <import file="build-common.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/jar.jardesc	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<jardesc>
+    <jar path="javafx-beans/dist/javafx-beans.jar"/>
+    <options buildIfNeeded="true" compress="true" descriptionLocation="/javafx-beans/jar.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
+    <storedRefactorings deprecationInfo="true" structuralOnly="false"/>
+    <selectedProjects/>
+    <manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
+        <sealing sealJar="false">
+            <packagesToSeal/>
+            <packagesToUnSeal/>
+        </sealing>
+    </manifest>
+    <selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
+        <javaElement handleIdentifier="=javafx-beans/src"/>
+    </selectedElements>
+</jardesc>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/javafx-beans.iml	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/build/classes" />
+    <output-test url="file://$MODULE_DIR$/build/test/classes" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/build" />
+      <excludeFolder url="file://$MODULE_DIR$/dist" />
+      <excludeFolder url="file://$MODULE_DIR$/nbproject" />
+    </content>
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="module" module-name="javafx-collections" />
+    <orderEntry type="library" name="junit" level="project" />
+  </component>
+  <component name="org.twodividedbyzero.idea.findbugs">
+    <option name="_basePreferences">
+      <map>
+        <entry key="property.analysisEffortLevel" value="default" />
+        <entry key="property.analyzeAfterCompile" value="false" />
+        <entry key="property.exportAsHtml" value="true" />
+        <entry key="property.exportAsXml" value="true" />
+        <entry key="property.exportBaseDir" value="" />
+        <entry key="property.exportCreateArchiveDir" value="false" />
+        <entry key="property.exportOpenBrowser" value="true" />
+        <entry key="property.minPriorityToReport" value="Medium" />
+        <entry key="property.runAnalysisInBackground" value="false" />
+        <entry key="property.showHiddenDetectors" value="false" />
+        <entry key="property.toolWindowToFront" value="true" />
+      </map>
+    </option>
+    <option name="_detectors">
+      <map>
+        <entry key="AppendingToAnObjectOutputStream" value="true" />
+        <entry key="BCPMethodReturnCheck" value="false" />
+        <entry key="BadAppletConstructor" value="false" />
+        <entry key="BadResultSetAccess" value="true" />
+        <entry key="BadSyntaxForRegularExpression" value="true" />
+        <entry key="BadUseOfReturnValue" value="true" />
+        <entry key="BadlyOverriddenAdapter" value="true" />
+        <entry key="BooleanReturnNull" value="true" />
+        <entry key="BuildInterproceduralCallGraph" value="false" />
+        <entry key="BuildObligationPolicyDatabase" value="true" />
+        <entry key="CallToUnsupportedMethod" value="false" />
+        <entry key="CalledMethods" value="true" />
+        <entry key="CheckCalls" value="false" />
+        <entry key="CheckExpectedWarnings" value="false" />
+        <entry key="CheckImmutableAnnotation" value="true" />
+        <entry key="CheckTypeQualifiers" value="true" />
+        <entry key="CloneIdiom" value="true" />
+        <entry key="ComparatorIdiom" value="true" />
+        <entry key="ConfusedInheritance" value="true" />
+        <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" />
+        <entry key="CrossSiteScripting" value="true" />
+        <entry key="DoInsideDoPrivileged" value="true" />
+        <entry key="DontCatchIllegalMonitorStateException" value="true" />
+        <entry key="DontIgnoreResultOfPutIfAbsent" value="true" />
+        <entry key="DontUseEnum" value="true" />
+        <entry key="DroppedException" value="true" />
+        <entry key="DumbMethodInvocations" value="true" />
+        <entry key="DumbMethods" value="true" />
+        <entry key="DuplicateBranches" value="true" />
+        <entry key="EmptyZipFileEntry" value="true" />
+        <entry key="EqStringTest" value="false" />
+        <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" />
+        <entry key="FieldItemSummary" value="true" />
+        <entry key="FinalizerNullsFields" value="true" />
+        <entry key="FindBadCast" value="false" />
+        <entry key="FindBadCast2" value="true" />
+        <entry key="FindBadEqualsImplementation" value="false" />
+        <entry key="FindBadForLoop" value="true" />
+        <entry key="FindBugsSummaryStats" value="true" />
+        <entry key="FindCircularDependencies" value="false" />
+        <entry key="FindDeadLocalStores" value="true" />
+        <entry key="FindDoubleCheck" value="true" />
+        <entry key="FindEmptySynchronizedBlock" value="true" />
+        <entry key="FindFieldSelfAssignment" value="true" />
+        <entry key="FindFinalizeInvocations" value="true" />
+        <entry key="FindFloatEquality" value="true" />
+        <entry key="FindFloatMath" value="false" />
+        <entry key="FindHEmismatch" value="true" />
+        <entry key="FindInconsistentSync2" value="true" />
+        <entry key="FindJSR166LockMonitorenter" value="true" />
+        <entry key="FindLocalSelfAssignment2" value="true" />
+        <entry key="FindMaskedFields" value="true" />
+        <entry key="FindMismatchedWaitOrNotify" value="true" />
+        <entry key="FindNakedNotify" value="true" />
+        <entry key="FindNonSerializableStoreIntoSession" value="true" />
+        <entry key="FindNonSerializableValuePassedToWriteObject" value="true" />
+        <entry key="FindNonShortCircuit" value="true" />
+        <entry key="FindNullDeref" value="true" />
+        <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" />
+        <entry key="FindOpenStream" value="true" />
+        <entry key="FindPuzzlers" value="true" />
+        <entry key="FindRefComparison" value="true" />
+        <entry key="FindReturnRef" value="true" />
+        <entry key="FindRunInvocations" value="true" />
+        <entry key="FindSelfComparison" value="true" />
+        <entry key="FindSelfComparison2" value="true" />
+        <entry key="FindSleepWithLockHeld" value="true" />
+        <entry key="FindSpinLoop" value="true" />
+        <entry key="FindSqlInjection" value="true" />
+        <entry key="FindTwoLockWait" value="true" />
+        <entry key="FindUncalledPrivateMethods" value="true" />
+        <entry key="FindUnconditionalWait" value="true" />
+        <entry key="FindUninitializedGet" value="true" />
+        <entry key="FindUnrelatedTypesInGenericContainer" value="true" />
+        <entry key="FindUnreleasedLock" value="true" />
+        <entry key="FindUnsatisfiedObligation" value="true" />
+        <entry key="FindUnsyncGet" value="true" />
+        <entry key="FindUselessControlFlow" value="true" />
+        <entry key="FormatStringChecker" value="true" />
+        <entry key="HugeSharedStringConstants" value="true" />
+        <entry key="IDivResultCastToDouble" value="true" />
+        <entry key="IncompatMask" value="true" />
+        <entry key="InconsistentAnnotations" value="true" />
+        <entry key="InefficientMemberAccess" value="false" />
+        <entry key="InefficientToArray" value="true" />
+        <entry key="InfiniteLoop" value="true" />
+        <entry key="InfiniteRecursiveLoop" value="true" />
+        <entry key="InfiniteRecursiveLoop2" value="false" />
+        <entry key="InheritanceUnsafeGetResource" value="true" />
+        <entry key="InitializationChain" value="true" />
+        <entry key="InstantiateStaticClass" value="true" />
+        <entry key="InvalidJUnitTest" value="true" />
+        <entry key="IteratorIdioms" value="true" />
+        <entry key="LazyInit" value="true" />
+        <entry key="LoadOfKnownNullValue" value="true" />
+        <entry key="LockedFields" value="false" />
+        <entry key="LostLoggerDueToWeakReference" value="true" />
+        <entry key="MethodReturnCheck" value="true" />
+        <entry key="Methods" value="true" />
+        <entry key="MultithreadedInstanceAccess" value="true" />
+        <entry key="MutableLock" value="true" />
+        <entry key="MutableStaticFields" value="true" />
+        <entry key="Naming" value="true" />
+        <entry key="Noise" value="false" />
+        <entry key="NoiseNullDeref" value="false" />
+        <entry key="NoteAnnotationRetention" value="true" />
+        <entry key="NoteCheckReturnValue" value="true" />
+        <entry key="NoteCheckReturnValueAnnotations" value="true" />
+        <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" />
+        <entry key="NoteJCIPAnnotation" value="true" />
+        <entry key="NoteNonNullAnnotations" value="true" />
+        <entry key="NoteNonnullReturnValues" value="true" />
+        <entry key="NoteSuppressedWarnings" value="true" />
+        <entry key="NoteUnconditionalParamDerefs" value="true" />
+        <entry key="NumberConstructor" value="true" />
+        <entry key="OverridingEqualsNotSymmetrical" value="true" />
+        <entry key="PreferZeroLengthArrays" value="true" />
+        <entry key="PublicSemaphores" value="false" />
+        <entry key="QuestionableBooleanAssignment" value="true" />
+        <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" />
+        <entry key="ReadReturnShouldBeChecked" value="true" />
+        <entry key="RedundantInterfaces" value="true" />
+        <entry key="ReflectiveClasses" value="true" />
+        <entry key="RepeatedConditionals" value="true" />
+        <entry key="ResolveAllReferences" value="false" />
+        <entry key="RuntimeExceptionCapture" value="true" />
+        <entry key="SerializableIdiom" value="true" />
+        <entry key="StartInConstructor" value="true" />
+        <entry key="StaticCalendarDetector" value="true" />
+        <entry key="StringConcatenation" value="true" />
+        <entry key="SuperfluousInstanceOf" value="true" />
+        <entry key="SuspiciousThreadInterrupted" value="true" />
+        <entry key="SwitchFallthrough" value="true" />
+        <entry key="SynchronizationOnSharedBuiltinConstant" value="true" />
+        <entry key="SynchronizeAndNullCheckField" value="true" />
+        <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" />
+        <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" />
+        <entry key="TestASM" value="false" />
+        <entry key="TestDataflowAnalysis" value="false" />
+        <entry key="TestingGround" value="false" />
+        <entry key="TrainFieldStoreTypes" value="true" />
+        <entry key="TrainNonNullAnnotations" value="true" />
+        <entry key="TrainUnconditionalDerefParams" value="true" />
+        <entry key="URLProblems" value="true" />
+        <entry key="UncallableMethodOfAnonymousClass" value="true" />
+        <entry key="UnnecessaryMath" value="true" />
+        <entry key="UnreadFields" value="true" />
+        <entry key="UseObjectEquals" value="false" />
+        <entry key="UselessSubclassMethod" value="false" />
+        <entry key="VarArgsProblems" value="true" />
+        <entry key="VolatileUsage" value="true" />
+        <entry key="WaitInLoop" value="true" />
+        <entry key="WrongMapIterator" value="true" />
+        <entry key="XMLFactoryBypass" value="true" />
+      </map>
+    </option>
+    <option name="_reportCategories">
+      <map>
+        <entry key="BAD_PRACTICE" value="true" />
+        <entry key="CORRECTNESS" value="true" />
+        <entry key="EXPERIMENTAL" value="true" />
+        <entry key="I18N" value="true" />
+        <entry key="MALICIOUS_CODE" value="true" />
+        <entry key="MT_CORRECTNESS" value="true" />
+        <entry key="NOISE" value="false" />
+        <entry key="PERFORMANCE" value="true" />
+        <entry key="SECURITY" value="true" />
+        <entry key="STYLE" value="true" />
+      </map>
+    </option>
+  </component>
+</module>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/nbproject/project.xml	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.ant.freeform</type>
+    <configuration>
+        <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1">
+            <!-- Do not use Project Properties customizer when editing this file manually. -->
+            <name>javafx-beans</name>
+            <properties>
+                <property-file>../base.properties</property-file>
+                <property-file>project.properties</property-file>
+                <property-file>../common.properties</property-file>
+            </properties>
+            <folders>
+                <source-folder>
+                    <label>Source Packages</label>
+                    <type>java</type>
+                    <location>${src.dir}</location>
+                </source-folder>
+                <source-folder>
+                    <label>Test Packages</label>
+                    <type>java</type>
+                    <location>${test.dir}</location>
+                </source-folder>
+            </folders>
+            <ide-actions>
+                <action name="build">
+                    <target>jar</target>
+                </action>
+                <action name="clean">
+                    <target>clean</target>
+                </action>
+                <action name="test">
+                    <target>test</target>
+                </action>
+                <action name="rebuild">
+                    <target>clean</target>
+                    <target>jar</target>
+                </action>
+                <action name="run.single">
+                    <target>test-single</target>
+                    <context>
+                        <property>run.file</property>
+                        <folder>${test.dir}</folder>
+                        <pattern>\.java$</pattern>
+                        <format>relative-path</format>
+                        <arity>
+                            <one-file-only/>
+                        </arity>
+                    </context>
+                </action>
+                <action name="test.single">
+                    <target>test-single</target>
+                    <context>
+                        <property>run.file</property>
+                        <folder>${test.dir}</folder>
+                        <pattern>\.java$</pattern>
+                        <format>relative-path</format>
+                        <arity>
+                            <one-file-only/>
+                        </arity>
+                    </context>
+                </action>
+                <action name="debug.test.single">
+                    <script>build.xml</script>
+                    <target>debug-test-file</target>
+                    <context>
+                        <property>debug.class</property>
+                        <folder>${test.dir}</folder>
+                        <pattern>\.java$</pattern>
+                        <format>java-name</format>
+                        <arity>
+                            <one-file-only/>
+                        </arity>
+                    </context>
+                </action>
+                <action name="debug.single">
+                    <target>debug-test-file</target>
+                    <context>
+                        <property>debug.class</property>
+                        <folder>${test.dir}</folder>
+                        <pattern>\.java$</pattern>
+                        <format>java-name</format>
+                        <arity>
+                            <one-file-only/>
+                        </arity>
+                    </context>
+                </action>
+            </ide-actions>
+            <export>
+                <type>jar</type>
+                <location>dist/javafx-beans.jar</location>
+                <build-target>jar</build-target>
+            </export>
+            <export>
+                <type>folder</type>
+                <location>${build.test.classes.dir}</location>
+                <build-target>jar</build-target>
+            </export>
+            <view>
+                <items>
+                    <source-folder style="packages">
+                        <label>Source Packages</label>
+                        <location>${src.dir}</location>
+                    </source-folder>
+                    <source-folder style="packages">
+                        <label>Test Packages</label>
+                        <location>${test.dir}</location>
+                    </source-folder>
+                    <source-file>
+                        <location>build.xml</location>
+                    </source-file>
+                    <source-file>
+                        <location>project.properties</location>
+                    </source-file>
+                    <source-file>
+                        <location>nbproject/project.xml</location>
+                    </source-file>
+                </items>
+                <context-menu>
+                    <ide-action name="build"/>
+                    <ide-action name="rebuild"/>
+                    <ide-action name="clean"/>
+                    <ide-action name="test"/>
+                </context-menu>
+            </view>
+            <subprojects/>
+        </general-data>
+        <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/3">
+            <compilation-unit>
+                <package-root>${src.dir}</package-root>
+                <classpath mode="compile">../javafx-common/dist/javafx-common.jar:../javafx-logging/dist/javafx-logging.jar</classpath>
+                <built-to>dist/javafx-beans.jar</built-to>
+                <source-level>1.6</source-level>
+            </compilation-unit>
+            <compilation-unit>
+                <package-root>${test.dir}</package-root>
+                <unit-tests/>
+                <classpath mode="compile">${javac.test.classpath}</classpath>
+                <built-to>${build.test.classes.dir}</built-to>
+                <source-level>1.6</source-level>
+            </compilation-unit>
+        </java-data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/project.properties	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,3 @@
+javac.classpath=${JFXRT_HOME}/lib/ext/jfxrt.jar
+disable-lombok=true
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/beans/IDProperty.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.beans;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies a property to which FXML ID values will be applied.
+ *
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface IDProperty {
+    /**
+     * The name of the ID property.
+     */
+    public String value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/beans/annotations/Default.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.beans.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p>
+ * Specifies the default value for the property corresponding to a constructor
+ * parameter in an immutable class. This allows the generated Builder class to
+ * work correctly when no value is supplied for that parameter.
+ * 
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.PARAMETER)
+public @interface Default {
+    /**
+     * <p>
+     * The default value for this parameter, specified as a string value that
+     * can be used in an initializer. For example, it could be {@code "1.0"} for
+     * a parameter of type {@code double}. An empty string can be used to
+     * indicate the default value for the parameter of this type, so
+     * {@code @Default("")} would indicate {@code 0.0} for a parameter of type
+     * {@code double} or {@code null} for a parameter of type {@code String}.
+     * </p>
+     * 
+     * <p>
+     * Note: for parameters of type {@code String}, it is easy to forget the
+     * quotes around a string literal. A string parameter whose default is the
+     * empty string would be specified like this:<br>
+     * {@code @Default("\"\"") name}.
+     * </p>
+     */
+    public String value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/beans/annotations/Delegate.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.beans.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates that a field is a "delegate": public methods of the type of such
+ * field are present in the type containing the field, and their implementation
+ * simply delegates to the field.
+ * 
+ */
+@Target(FIELD)
+@Retention(SOURCE)
+public @interface Delegate {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/beans/annotations/DuplicateInBuilderProperties.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.beans.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies that the property from the superclass should be copied 
+ * to subclasses of the builder.
+ *
+ * The class whose builder is missing the properties should be annotated, 
+ * the "properties" list should contain names of properties to be generated.
+ * e.g.
+ * @DuplicateInBuilderProperties(properties = {"minHeight", "minWidth"})
+ *  public abstract class Control extends Region implements Skinnable {...}
+ * this means that the ControlBuilder will contain minHeight and minWidth
+ * properties, even though they are inherited from Region (so they wouldn't be
+ * generated without the annotation)
+ *
+ * This annotation was introduced to solve an issue with moving promptText
+ * from TextField to TextInputControl which caused incompatibility in their 
+ * builders (RT-21327).
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+public @interface DuplicateInBuilderProperties {
+    String[] properties();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/beans/annotations/NoBuilder.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.beans.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies that no builder should be generated for this class.
+ * 
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface NoBuilder {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/beans/annotations/NoInit.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.beans.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies that a property can not or should not be initialized on object
+ * creation. This means that it will not be included in any generated builder
+ * class, for example.
+ * 
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({ ElementType.FIELD, ElementType.METHOD })
+public @interface NoInit {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/beans/annotations/NonNull.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.beans.annotations;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.*;
+
+/**
+ * Lombok is smart enough to translate any annotation named {@code @NonNull} or
+ * {@code @NotNull} in any casing and with any package name to the return type
+ * of generated getters and the parameter of generated setters and constructors,
+ * as well as generate the appropriate null checks in the setter and
+ * constructor.
+ * 
+ * You can use this annotation for the purpose, though you can also use JSR305's
+ * annotation, findbugs's, pmd's, or IDEA's, or just about anyone elses. As long
+ * as it is named {@code @NonNull} or {@code @NotNull}.
+ */
+@Target({ FIELD, METHOD, PARAMETER, LOCAL_VARIABLE })
+@Retention(CLASS)
+@Documented
+public @interface NonNull {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/BidirectionalBinding.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.Observable;
+import javafx.beans.WeakListener;
+import javafx.beans.property.*;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.util.StringConverter;
+
+import java.lang.ref.WeakReference;
+import java.text.Format;
+import java.text.ParseException;
+
+public abstract class BidirectionalBinding<T> implements ChangeListener<T>, WeakListener {
+
+    private static void checkParameters(Object property1, Object property2) {
+        if ((property1 == null) || (property2 == null)) {
+            throw new NullPointerException("Both properties must be specified.");
+        }
+        if (property1.equals(property2)) {
+            throw new IllegalArgumentException("Cannot bind property to itself");
+        }
+    }
+
+    public static <T> BidirectionalBinding bind(Property<T> property1, Property<T> property2) {
+        checkParameters(property1, property2);
+        final BidirectionalBinding binding =
+                ((property1 instanceof DoubleProperty) && (property2 instanceof DoubleProperty)) ?
+                        new BidirectionalDoubleBinding((DoubleProperty) property1, (DoubleProperty) property2)
+                : ((property1 instanceof FloatProperty) && (property2 instanceof FloatProperty)) ?
+                        new BidirectionalFloatBinding((FloatProperty) property1, (FloatProperty) property2)
+                : ((property1 instanceof IntegerProperty) && (property2 instanceof IntegerProperty)) ?
+                        new BidirectionalIntegerBinding((IntegerProperty) property1, (IntegerProperty) property2)
+                : ((property1 instanceof LongProperty) && (property2 instanceof LongProperty)) ?
+                        new BidirectionalLongBinding((LongProperty) property1, (LongProperty) property2)
+                : ((property1 instanceof BooleanProperty) && (property2 instanceof BooleanProperty)) ?
+                        new BidirectionalBooleanBinding((BooleanProperty) property1, (BooleanProperty) property2)
+                : new TypedGenericBidirectionalBinding<T>(property1, property2);
+        property1.setValue(property2.getValue());
+        property1.addListener(binding);
+        property2.addListener(binding);
+        return binding;
+    }
+
+    public static Object bind(Property<String> stringProperty, Property<?> otherProperty, Format format) {
+        checkParameters(stringProperty, otherProperty);
+        if (format == null) {
+            throw new NullPointerException("Format cannot be null");
+        }
+        final StringConversionBidirectionalBinding<?> binding = new StringFormatBidirectionalBinding(stringProperty, otherProperty, format);
+        stringProperty.setValue(format.format(otherProperty.getValue()));
+        stringProperty.addListener(binding);
+        otherProperty.addListener(binding);
+        return binding;
+    }
+
+    public static <T> Object bind(Property<String> stringProperty, Property<T> otherProperty, StringConverter<T> converter) {
+        checkParameters(stringProperty, otherProperty);
+        if (converter == null) {
+            throw new NullPointerException("Converter cannot be null");
+        }
+        final StringConversionBidirectionalBinding<T> binding = new StringConverterBidirectionalBinding<T>(stringProperty, otherProperty, converter);
+        stringProperty.setValue(converter.toString(otherProperty.getValue()));
+        stringProperty.addListener(binding);
+        otherProperty.addListener(binding);
+        return binding;
+    }
+
+    public static <T> void unbind(Property<T> property1, Property<T> property2) {
+        checkParameters(property1, property2);
+        final BidirectionalBinding binding = new UntypedGenericBidirectionalBinding(property1, property2);
+        property1.removeListener(binding);
+        property2.removeListener(binding);
+    }
+
+    public static void unbind(Object property1, Object property2) {
+        checkParameters(property1, property2);
+        final BidirectionalBinding binding = new UntypedGenericBidirectionalBinding(property1, property2);
+        if (property1 instanceof ObservableValue) {
+            ((ObservableValue) property1).removeListener(binding);
+        }
+        if (property2 instanceof Observable) {
+            ((ObservableValue) property2).removeListener(binding);
+        }
+    }
+
+    private final int cachedHashCode;
+
+    private BidirectionalBinding(Object property1, Object property2) {
+        cachedHashCode = property1.hashCode() * property2.hashCode();
+    }
+
+    protected abstract Object getProperty1();
+
+    protected abstract Object getProperty2();
+
+    @Override
+    public int hashCode() {
+        return cachedHashCode;
+    }
+
+    @Override
+    public boolean wasGarbageCollected() {
+        return (getProperty1() == null) || (getProperty2() == null);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        final Object propertyA1 = getProperty1();
+        final Object propertyA2 = getProperty2();
+        if ((propertyA1 == null) || (propertyA2 == null)) {
+            return false;
+        }
+
+        if (obj instanceof BidirectionalBinding) {
+            final BidirectionalBinding otherBinding = (BidirectionalBinding) obj;
+            final Object propertyB1 = otherBinding.getProperty1();
+            final Object propertyB2 = otherBinding.getProperty2();
+            if ((propertyB1 == null) || (propertyB2 == null)) {
+                return false;
+            }
+
+            if ((propertyA1.equals(propertyB1) && (propertyA2
+                    .equals(propertyB2)))) {
+                return true;
+            }
+            if ((propertyA1.equals(propertyB2) && (propertyA2
+                    .equals(propertyB1)))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static class BidirectionalBooleanBinding extends BidirectionalBinding<Boolean> {
+        private final WeakReference<BooleanProperty> propertyRef1;
+        private final WeakReference<BooleanProperty> propertyRef2;
+        private boolean updating = false;
+
+        private BidirectionalBooleanBinding(BooleanProperty property1, BooleanProperty property2) {
+            super(property1, property2);
+            propertyRef1 = new WeakReference<BooleanProperty>(property1);
+            propertyRef2 = new WeakReference<BooleanProperty>(property2);
+        }
+
+        @Override
+        protected Property<Boolean> getProperty1() {
+            return propertyRef1.get();
+        }
+
+        @Override
+        protected Property<Boolean> getProperty2() {
+            return propertyRef2.get();
+        }
+
+        @Override
+        public void changed(ObservableValue<? extends Boolean> sourceProperty, Boolean oldValue, Boolean newValue) {
+            if (!updating) {
+                final BooleanProperty property1 = propertyRef1.get();
+                final BooleanProperty property2 = propertyRef2.get();
+                if ((property1 == null) || (property2 == null)) {
+                    if (property1 != null) {
+                        property1.removeListener(this);
+                    }
+                    if (property2 != null) {
+                        property2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        if (property1.equals(sourceProperty)) {
+                            property2.set(newValue);
+                        } else {
+                            property1.set(newValue);
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+    }
+
+    private static class BidirectionalDoubleBinding extends BidirectionalBinding<Number> {
+        private final WeakReference<DoubleProperty> propertyRef1;
+        private final WeakReference<DoubleProperty> propertyRef2;
+        private boolean updating = false;
+
+        private BidirectionalDoubleBinding(DoubleProperty property1, DoubleProperty property2) {
+            super(property1, property2);
+            propertyRef1 = new WeakReference<DoubleProperty>(property1);
+            propertyRef2 = new WeakReference<DoubleProperty>(property2);
+        }
+
+        @Override
+        protected Property<Number> getProperty1() {
+            return propertyRef1.get();
+        }
+
+        @Override
+        protected Property<Number> getProperty2() {
+            return propertyRef2.get();
+        }
+
+        @Override
+        public void changed(ObservableValue<? extends Number> sourceProperty, Number oldValue, Number newValue) {
+            if (!updating) {
+                final DoubleProperty property1 = propertyRef1.get();
+                final DoubleProperty property2 = propertyRef2.get();
+                if ((property1 == null) || (property2 == null)) {
+                    if (property1 != null) {
+                        property1.removeListener(this);
+                    }
+                    if (property2 != null) {
+                        property2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        if (property1.equals(sourceProperty)) {
+                            property2.set(newValue.doubleValue());
+                        } else {
+                            property1.set(newValue.doubleValue());
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+    }
+
+    private static class BidirectionalFloatBinding extends BidirectionalBinding<Number> {
+        private final WeakReference<FloatProperty> propertyRef1;
+        private final WeakReference<FloatProperty> propertyRef2;
+        private boolean updating = false;
+
+        private BidirectionalFloatBinding(FloatProperty property1, FloatProperty property2) {
+            super(property1, property2);
+            propertyRef1 = new WeakReference<FloatProperty>(property1);
+            propertyRef2 = new WeakReference<FloatProperty>(property2);
+        }
+
+        @Override
+        protected Property<Number> getProperty1() {
+            return propertyRef1.get();
+        }
+
+        @Override
+        protected Property<Number> getProperty2() {
+            return propertyRef2.get();
+        }
+
+        @Override
+        public void changed(ObservableValue<? extends Number> sourceProperty, Number oldValue, Number newValue) {
+            if (!updating) {
+                final FloatProperty property1 = propertyRef1.get();
+                final FloatProperty property2 = propertyRef2.get();
+                if ((property1 == null) || (property2 == null)) {
+                    if (property1 != null) {
+                        property1.removeListener(this);
+                    }
+                    if (property2 != null) {
+                        property2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        if (property1.equals(sourceProperty)) {
+                            property2.set(newValue.floatValue());
+                        } else {
+                            property1.set(newValue.floatValue());
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+    }
+
+    private static class BidirectionalIntegerBinding extends BidirectionalBinding<Number>{
+        private final WeakReference<IntegerProperty> propertyRef1;
+        private final WeakReference<IntegerProperty> propertyRef2;
+        private boolean updating = false;
+
+        private BidirectionalIntegerBinding(IntegerProperty property1, IntegerProperty property2) {
+            super(property1, property2);
+            propertyRef1 = new WeakReference<IntegerProperty>(property1);
+            propertyRef2 = new WeakReference<IntegerProperty>(property2);
+        }
+
+        @Override
+        protected Property<Number> getProperty1() {
+            return propertyRef1.get();
+        }
+
+        @Override
+        protected Property<Number> getProperty2() {
+            return propertyRef2.get();
+        }
+
+        @Override
+        public void changed(ObservableValue<? extends Number> sourceProperty, Number oldValue, Number newValue) {
+            if (!updating) {
+                final IntegerProperty property1 = propertyRef1.get();
+                final IntegerProperty property2 = propertyRef2.get();
+                if ((property1 == null) || (property2 == null)) {
+                    if (property1 != null) {
+                        property1.removeListener(this);
+                    }
+                    if (property2 != null) {
+                        property2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        if (property1.equals(sourceProperty)) {
+                            property2.set(newValue.intValue());
+                        } else {
+                            property1.set(newValue.intValue());
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+    }
+
+    private static class BidirectionalLongBinding extends BidirectionalBinding<Number> {
+        private final WeakReference<LongProperty> propertyRef1;
+        private final WeakReference<LongProperty> propertyRef2;
+        private boolean updating = false;
+
+        private BidirectionalLongBinding(LongProperty property1, LongProperty property2) {
+            super(property1, property2);
+            propertyRef1 = new WeakReference<LongProperty>(property1);
+            propertyRef2 = new WeakReference<LongProperty>(property2);
+        }
+
+        @Override
+        protected Property<Number> getProperty1() {
+            return propertyRef1.get();
+        }
+
+        @Override
+        protected Property<Number> getProperty2() {
+            return propertyRef2.get();
+        }
+
+        @Override
+        public void changed(ObservableValue<? extends Number> sourceProperty, Number oldValue, Number newValue) {
+            if (!updating) {
+                final LongProperty property1 = propertyRef1.get();
+                final LongProperty property2 = propertyRef2.get();
+                if ((property1 == null) || (property2 == null)) {
+                    if (property1 != null) {
+                        property1.removeListener(this);
+                    }
+                    if (property2 != null) {
+                        property2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        if (property1.equals(sourceProperty)) {
+                            property2.set(newValue.longValue());
+                        } else {
+                            property1.set(newValue.longValue());
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+    }
+
+    private static class TypedGenericBidirectionalBinding<T> extends BidirectionalBinding<T> {
+        private final WeakReference<Property<T>> propertyRef1;
+        private final WeakReference<Property<T>> propertyRef2;
+        private boolean updating = false;
+
+        private TypedGenericBidirectionalBinding(Property<T> property1, Property<T> property2) {
+            super(property1, property2);
+            propertyRef1 = new WeakReference<Property<T>>(property1);
+            propertyRef2 = new WeakReference<Property<T>>(property2);
+        }
+
+        @Override
+        protected Property<T> getProperty1() {
+            return propertyRef1.get();
+        }
+
+        @Override
+        protected Property<T> getProperty2() {
+            return propertyRef2.get();
+        }
+
+        @Override
+        public void changed(ObservableValue<? extends T> sourceProperty, T oldValue, T newValue) {
+            if (!updating) {
+                final Property<T> property1 = propertyRef1.get();
+                final Property<T> property2 = propertyRef2.get();
+                if ((property1 == null) || (property2 == null)) {
+                    if (property1 != null) {
+                        property1.removeListener(this);
+                    }
+                    if (property2 != null) {
+                        property2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        if (property1.equals(sourceProperty)) {
+                            property2.setValue(property1.getValue());
+                        } else {
+                            property1.setValue(property2.getValue());
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+    }
+
+    private static class UntypedGenericBidirectionalBinding extends BidirectionalBinding<Object> {
+
+        private final Object property1;
+        private final Object property2;
+
+        public UntypedGenericBidirectionalBinding(Object property1, Object property2) {
+            super(property1, property2);
+            this.property1 = property1;
+            this.property2 = property2;
+        }
+
+        @Override
+        protected Object getProperty1() {
+            return property1;
+        }
+
+        @Override
+        protected Object getProperty2() {
+            return property2;
+        }
+
+        @Override
+        public void changed(ObservableValue<? extends Object> sourceProperty, Object oldValue, Object newValue) {
+            throw new RuntimeException("Should not reach here");
+        }
+    }
+
+    public abstract static class StringConversionBidirectionalBinding<T> extends BidirectionalBinding<Object> {
+
+        private final WeakReference<Property<String>> stringPropertyRef;
+        private final WeakReference<Property<T>> otherPropertyRef;
+        private boolean updating;
+
+        public StringConversionBidirectionalBinding(Property<String> stringProperty, Property<T> otherProperty) {
+            super(stringProperty, otherProperty);
+            stringPropertyRef = new WeakReference<Property<String>>(stringProperty);
+            otherPropertyRef = new WeakReference<Property<T>>(otherProperty);
+        }
+
+        protected abstract String toString(T value);
+
+        protected abstract T fromString(String value) throws ParseException;
+
+        @Override
+        protected Object getProperty1() {
+            return stringPropertyRef.get();
+        }
+
+        @Override
+        protected Object getProperty2() {
+            return otherPropertyRef.get();
+        }
+
+        @Override
+        public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) {
+            if (!updating) {
+                final Property<String> property1 = stringPropertyRef.get();
+                final Property<T> property2 = otherPropertyRef.get();
+                if ((property1 == null) || (property2 == null)) {
+                    if (property1 != null) {
+                        property1.removeListener(this);
+                    }
+                    if (property2 != null) {
+                        property2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        if (property1.equals(observable)) {
+                            try {
+                                property2.setValue(fromString(property1.getValue()));
+                            } catch (Exception e) {
+                                Logging.getLogger().warning("Exception while parsing String in bidirectional binding", e);
+                                property2.setValue(null);
+                            }
+                        } else {
+                            try {
+                                property1.setValue(toString(property2.getValue()));
+                            } catch (Exception e) {
+                                Logging.getLogger().warning("Exception while converting Object to String in bidirectional binding", e);
+                                property1.setValue("");
+                            }
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+    }
+
+    private static class StringFormatBidirectionalBinding extends StringConversionBidirectionalBinding {
+
+        private final Format format;
+
+        @SuppressWarnings("unchecked")
+        public StringFormatBidirectionalBinding(Property<String> stringProperty, Property<?> otherProperty, Format format) {
+            super(stringProperty, otherProperty);
+            this.format = format;
+        }
+
+        @Override
+        protected String toString(Object value) {
+            return format.format(value);
+        }
+
+        @Override
+        protected Object fromString(String value) throws ParseException {
+            return format.parseObject(value);
+        }
+    }
+
+    private static class StringConverterBidirectionalBinding<T> extends StringConversionBidirectionalBinding<T> {
+
+        private final StringConverter<T> converter;
+
+        public StringConverterBidirectionalBinding(Property<String> stringProperty, Property<T> otherProperty, StringConverter<T> converter) {
+            super(stringProperty, otherProperty);
+            this.converter = converter;
+        }
+
+        @Override
+        protected String toString(T value) {
+            return converter.toString(value);
+        }
+
+        @Override
+        protected T fromString(String value) throws ParseException {
+            return converter.fromString(value);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/BidirectionalContentBinding.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.WeakListener;
+import javafx.collections.*;
+
+import java.lang.ref.WeakReference;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ */
+public class BidirectionalContentBinding {
+
+    private static void checkParameters(Object property1, Object property2) {
+        if ((property1 == null) || (property2 == null)) {
+            throw new NullPointerException("Both parameters must be specified.");
+        }
+        if (property1 == property2) {
+            throw new IllegalArgumentException("Cannot bind object to itself");
+        }
+    }
+
+    public static <E> Object bind(ObservableList<E> list1, ObservableList<E> list2) {
+        checkParameters(list1, list2);
+        final ListContentBinding<E> binding = new ListContentBinding<E>(list1, list2);
+        list1.setAll(list2);
+        list1.addListener(binding);
+        list2.addListener(binding);
+        return binding;
+    }
+
+    public static <E> Object bind(ObservableSet<E> set1, ObservableSet<E> set2) {
+        checkParameters(set1, set2);
+        final SetContentBinding<E> binding = new SetContentBinding<E>(set1, set2);
+        set1.clear();
+        set1.addAll(set2);
+        set1.addListener(binding);
+        set2.addListener(binding);
+        return binding;
+    }
+
+    public static <K, V> Object bind(ObservableMap<K, V> map1, ObservableMap<K, V> map2) {
+        checkParameters(map1, map2);
+        final MapContentBinding<K, V> binding = new MapContentBinding<K, V>(map1, map2);
+        map1.clear();
+        map1.putAll(map2);
+        map1.addListener(binding);
+        map2.addListener(binding);
+        return binding;
+    }
+
+    public static void unbind(Object obj1, Object obj2) {
+        checkParameters(obj1, obj2);
+        if ((obj1 instanceof ObservableList) && (obj2 instanceof ObservableList)) {
+            final ObservableList list1 = (ObservableList)obj1;
+            final ObservableList list2 = (ObservableList)obj2;
+            final ListContentBinding binding = new ListContentBinding(list1, list2);
+            list1.removeListener(binding);
+            list2.removeListener(binding);
+        } else if ((obj1 instanceof ObservableSet) && (obj2 instanceof ObservableSet)) {
+            final ObservableSet set1 = (ObservableSet)obj1;
+            final ObservableSet set2 = (ObservableSet)obj2;
+            final SetContentBinding binding = new SetContentBinding(set1, set2);
+            set1.removeListener(binding);
+            set2.removeListener(binding);
+        } else if ((obj1 instanceof ObservableMap) && (obj2 instanceof ObservableMap)) {
+            final ObservableMap map1 = (ObservableMap)obj1;
+            final ObservableMap map2 = (ObservableMap)obj2;
+            final MapContentBinding binding = new MapContentBinding(map1, map2);
+            map1.removeListener(binding);
+            map2.removeListener(binding);
+        }
+    }
+
+    private static class ListContentBinding<E> implements ListChangeListener<E>, WeakListener {
+
+        private final WeakReference<ObservableList<E>> propertyRef1;
+        private final WeakReference<ObservableList<E>> propertyRef2;
+
+        private boolean updating = false;
+
+
+        public ListContentBinding(ObservableList<E> list1, ObservableList<E> list2) {
+            propertyRef1 = new WeakReference<ObservableList<E>>(list1);
+            propertyRef2 = new WeakReference<ObservableList<E>>(list2);
+        }
+
+        @Override
+        public void onChanged(Change<? extends E> change) {
+            if (!updating) {
+                final ObservableList<E> list1 = propertyRef1.get();
+                final ObservableList<E> list2 = propertyRef2.get();
+                if ((list1 == null) || (list2 == null)) {
+                    if (list1 != null) {
+                        list1.removeListener(this);
+                    }
+                    if (list2 != null) {
+                        list2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        final ObservableList<E> dest = (list1 ==  change.getList())? list2 : list1;
+                        while (change.next()) {
+                            if (change.wasPermutated()) {
+                                dest.remove(change.getFrom(), change.getTo());
+                                dest.addAll(change.getFrom(), change.getList().subList(change.getFrom(), change.getTo()));
+                            } else {
+                                if (change.wasRemoved()) {
+                                    dest.remove(change.getFrom(), change.getFrom() + change.getRemovedSize());
+                                }
+                                if (change.wasAdded()) {
+                                    dest.addAll(change.getFrom(), change.getAddedSubList());
+                                }
+                            }
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean wasGarbageCollected() {
+            return (propertyRef1.get() == null) || (propertyRef2.get() == null);
+        }
+
+        @Override
+        public int hashCode() {
+            final ObservableList<E> list1 = propertyRef1.get();
+            final ObservableList<E> list2 = propertyRef2.get();
+            final int hc1 = (list1 == null)? 0 : list1.hashCode();
+            final int hc2 = (list2 == null)? 0 : list2.hashCode();
+            return hc1 * hc2;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            final Object propertyA1 = propertyRef1.get();
+            final Object propertyA2 = propertyRef2.get();
+            if ((propertyA1 == null) || (propertyA2 == null)) {
+                return false;
+            }
+
+            if (obj instanceof ListContentBinding) {
+                final ListContentBinding otherBinding = (ListContentBinding) obj;
+                final Object propertyB1 = otherBinding.propertyRef1.get();
+                final Object propertyB2 = otherBinding.propertyRef2.get();
+                if ((propertyB1 == null) || (propertyB2 == null)) {
+                    return false;
+                }
+
+                if ((propertyA1 == propertyB1) && (propertyA2 == propertyB2)) {
+                    return true;
+                }
+                if ((propertyA1 == propertyB2) && (propertyA2 == propertyB1)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    private static class SetContentBinding<E> implements SetChangeListener<E>, WeakListener {
+
+        private final WeakReference<ObservableSet<E>> propertyRef1;
+        private final WeakReference<ObservableSet<E>> propertyRef2;
+
+        private boolean updating = false;
+
+
+        public SetContentBinding(ObservableSet<E> list1, ObservableSet<E> list2) {
+            propertyRef1 = new WeakReference<ObservableSet<E>>(list1);
+            propertyRef2 = new WeakReference<ObservableSet<E>>(list2);
+        }
+
+        @Override
+        public void onChanged(Change<? extends E> change) {
+            if (!updating) {
+                final ObservableSet<E> set1 = propertyRef1.get();
+                final ObservableSet<E> set2 = propertyRef2.get();
+                if ((set1 == null) || (set2 == null)) {
+                    if (set1 != null) {
+                        set1.removeListener(this);
+                    }
+                    if (set2 != null) {
+                        set2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        final Set<E> dest = (set1 == change.getSet())? set2 : set1;
+                        if (change.wasRemoved()) {
+                            dest.remove(change.getElementRemoved());
+                        } else {
+                            dest.add(change.getElementAdded());
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean wasGarbageCollected() {
+            return (propertyRef1.get() == null) || (propertyRef2.get() == null);
+        }
+
+        @Override
+        public int hashCode() {
+            final ObservableSet<E> set1 = propertyRef1.get();
+            final ObservableSet<E> set2 = propertyRef2.get();
+            final int hc1 = (set1 == null)? 0 : set1.hashCode();
+            final int hc2 = (set2 == null)? 0 : set2.hashCode();
+            return hc1 * hc2;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            final Object propertyA1 = propertyRef1.get();
+            final Object propertyA2 = propertyRef2.get();
+            if ((propertyA1 == null) || (propertyA2 == null)) {
+                return false;
+            }
+
+            if (obj instanceof SetContentBinding) {
+                final SetContentBinding otherBinding = (SetContentBinding) obj;
+                final Object propertyB1 = otherBinding.propertyRef1.get();
+                final Object propertyB2 = otherBinding.propertyRef2.get();
+                if ((propertyB1 == null) || (propertyB2 == null)) {
+                    return false;
+                }
+
+                if ((propertyA1 == propertyB1) && (propertyA2 == propertyB2)) {
+                    return true;
+                }
+                if ((propertyA1 == propertyB2) && (propertyA2 == propertyB1)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    private static class MapContentBinding<K, V> implements MapChangeListener<K, V>, WeakListener {
+
+        private final WeakReference<ObservableMap<K, V>> propertyRef1;
+        private final WeakReference<ObservableMap<K, V>> propertyRef2;
+
+        private boolean updating = false;
+
+
+        public MapContentBinding(ObservableMap<K, V> list1, ObservableMap<K, V> list2) {
+            propertyRef1 = new WeakReference<ObservableMap<K, V>>(list1);
+            propertyRef2 = new WeakReference<ObservableMap<K, V>>(list2);
+        }
+
+        @Override
+        public void onChanged(Change<? extends K, ? extends V> change) {
+            if (!updating) {
+                final ObservableMap<K, V> map1 = propertyRef1.get();
+                final ObservableMap<K, V> map2 = propertyRef2.get();
+                if ((map1 == null) || (map2 == null)) {
+                    if (map1 != null) {
+                        map1.removeListener(this);
+                    }
+                    if (map2 != null) {
+                        map2.removeListener(this);
+                    }
+                } else {
+                    try {
+                        updating = true;
+                        final Map<K, V> dest = (map1 == change.getMap())? map2 : map1;
+                        if (change.wasRemoved()) {
+                            dest.remove(change.getKey());
+                        } else {
+                            dest.put(change.getKey(), change.getValueAdded());
+                        }
+                    } finally {
+                        updating = false;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean wasGarbageCollected() {
+            return (propertyRef1.get() == null) || (propertyRef2.get() == null);
+        }
+
+        @Override
+        public int hashCode() {
+            final ObservableMap<K, V> map1 = propertyRef1.get();
+            final ObservableMap<K, V> map2 = propertyRef2.get();
+            final int hc1 = (map1 == null)? 0 : map1.hashCode();
+            final int hc2 = (map2 == null)? 0 : map2.hashCode();
+            return hc1 * hc2;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            final Object propertyA1 = propertyRef1.get();
+            final Object propertyA2 = propertyRef2.get();
+            if ((propertyA1 == null) || (propertyA2 == null)) {
+                return false;
+            }
+
+            if (obj instanceof MapContentBinding) {
+                final MapContentBinding otherBinding = (MapContentBinding) obj;
+                final Object propertyB1 = otherBinding.propertyRef1.get();
+                final Object propertyB2 = otherBinding.propertyRef2.get();
+                if ((propertyB1 == null) || (propertyB2 == null)) {
+                    return false;
+                }
+
+                if ((propertyA1 == propertyB1) && (propertyA2 == propertyB2)) {
+                    return true;
+                }
+                if ((propertyA1 == propertyB2) && (propertyA2 == propertyB1)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/BindingHelperObserver.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import java.lang.ref.WeakReference;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.Observable;
+import javafx.beans.binding.Binding;
+
+public class BindingHelperObserver implements InvalidationListener {
+
+    private final WeakReference<Binding<?>> ref;
+
+    public BindingHelperObserver(Binding<?> binding) {
+        if (binding == null) {
+            throw new NullPointerException("Binding has to be specified.");
+        }
+        ref = new WeakReference<Binding<?>>(binding);
+    }
+
+    @Override
+    public void invalidated(Observable observable) {
+        final Binding<?> binding = ref.get();
+        if (binding == null) {
+            observable.removeListener(this);
+        } else {
+            binding.invalidate();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/ContentBinding.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.WeakListener;
+import javafx.collections.*;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ */
+public class ContentBinding {
+
+    private static void checkParameters(Object property1, Object property2) {
+        if ((property1 == null) || (property2 == null)) {
+            throw new NullPointerException("Both parameters must be specified.");
+        }
+        if (property1 == property2) {
+            throw new IllegalArgumentException("Cannot bind object to itself");
+        }
+    }
+
+    public static <E> Object bind(List<E> list1, ObservableList<? extends E> list2) {
+        checkParameters(list1, list2);
+        final ListContentBinding<E> contentBinding = new ListContentBinding<E>(list1);
+        if (list1 instanceof ObservableList) {
+            ((ObservableList) list1).setAll(list2);
+        } else {
+            list1.clear();
+            list1.addAll(list2);
+        }
+        list2.addListener(contentBinding);
+        return contentBinding;
+    }
+
+    public static <E> Object bind(Set<E> set1, ObservableSet<? extends E> set2) {
+        checkParameters(set1, set2);
+        final SetContentBinding<E> contentBinding = new SetContentBinding<E>(set1);
+        set1.clear();
+        set1.addAll(set2);
+        set2.addListener(contentBinding);
+        return contentBinding;
+    }
+
+    public static <K, V> Object bind(Map<K, V> map1, ObservableMap<? extends K, ? extends V> map2) {
+        checkParameters(map1, map2);
+        final MapContentBinding<K, V> contentBinding = new MapContentBinding<K, V>(map1);
+        map1.clear();
+        map1.putAll(map2);
+        map2.addListener(contentBinding);
+        return contentBinding;
+    }
+
+    public static void unbind(Object obj1, Object obj2) {
+        checkParameters(obj1, obj2);
+        if ((obj1 instanceof List) && (obj2 instanceof ObservableList)) {
+            ((ObservableList)obj2).removeListener(new ListContentBinding((List)obj1));
+        } else if ((obj1 instanceof Set) && (obj2 instanceof ObservableSet)) {
+            ((ObservableSet)obj2).removeListener(new SetContentBinding((Set)obj1));
+        } else if ((obj1 instanceof Map) && (obj2 instanceof ObservableMap)) {
+            ((ObservableMap)obj2).removeListener(new MapContentBinding((Map)obj1));
+        }
+    }
+
+    private static class ListContentBinding<E> implements ListChangeListener<E>, WeakListener {
+
+        private final WeakReference<List<E>> listRef;
+
+        public ListContentBinding(List<E> list) {
+            this.listRef = new WeakReference<List<E>>(list);
+        }
+
+        @Override
+        public void onChanged(Change<? extends E> change) {
+            final List<E> list = listRef.get();
+            if (list == null) {
+                change.getList().removeListener(this);
+            } else {
+                while (change.next()) {
+                    if (change.wasPermutated()) {
+                        list.subList(change.getFrom(), change.getTo()).clear();
+                        list.addAll(change.getFrom(), change.getList().subList(change.getFrom(), change.getTo()));
+                    } else {
+                        if (change.wasRemoved()) {
+                            list.subList(change.getFrom(), change.getFrom() + change.getRemovedSize()).clear();
+                        }
+                        if (change.wasAdded()) {
+                            list.addAll(change.getFrom(), change.getAddedSubList());
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean wasGarbageCollected() {
+            return listRef.get() == null;
+        }
+
+        @Override
+        public int hashCode() {
+            final List<E> list = listRef.get();
+            return (list == null)? 0 : list.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            final List<E> list1 = listRef.get();
+            if (list1 == null) {
+                return false;
+            }
+
+            if (obj instanceof ListContentBinding) {
+                final ListContentBinding<?> other = (ListContentBinding<?>) obj;
+                final List<?> list2 = other.listRef.get();
+                return list1 == list2;
+            }
+            return false;
+        }
+    }
+
+    private static class SetContentBinding<E> implements SetChangeListener<E>, WeakListener {
+
+        private final WeakReference<Set<E>> setRef;
+
+        public SetContentBinding(Set<E> set) {
+            this.setRef = new WeakReference<Set<E>>(set);
+        }
+
+        @Override
+        public void onChanged(Change<? extends E> change) {
+            final Set<E> set = setRef.get();
+            if (set == null) {
+                change.getSet().removeListener(this);
+            } else {
+                if (change.wasRemoved()) {
+                    set.remove(change.getElementRemoved());
+                } else {
+                    set.add(change.getElementAdded());
+                }
+            }
+        }
+
+        @Override
+        public boolean wasGarbageCollected() {
+            return setRef.get() == null;
+        }
+
+        @Override
+        public int hashCode() {
+            final Set<E> set = setRef.get();
+            return (set == null)? 0 : set.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            final Set<E> set1 = setRef.get();
+            if (set1 == null) {
+                return false;
+            }
+
+            if (obj instanceof SetContentBinding) {
+                final SetContentBinding<?> other = (SetContentBinding<?>) obj;
+                final Set<?> set2 = other.setRef.get();
+                return set1 == set2;
+            }
+            return false;
+        }
+    }
+
+    private static class MapContentBinding<K, V> implements MapChangeListener<K, V>, WeakListener {
+
+        private final WeakReference<Map<K, V>> mapRef;
+
+        public MapContentBinding(Map<K, V> map) {
+            this.mapRef = new WeakReference<Map<K, V>>(map);
+        }
+
+        @Override
+        public void onChanged(Change<? extends K, ? extends V> change) {
+            final Map<K, V> map = mapRef.get();
+            if (map == null) {
+                change.getMap().removeListener(this);
+            } else {
+                if (change.wasRemoved()) {
+                    map.remove(change.getKey());
+                } else {
+                    map.put(change.getKey(), change.getValueAdded());
+                }
+            }
+        }
+
+        @Override
+        public boolean wasGarbageCollected() {
+            return mapRef.get() == null;
+        }
+
+        @Override
+        public int hashCode() {
+            final Map<K, V> map = mapRef.get();
+            return (map == null)? 0 : map.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            final Map<K, V> map1 = mapRef.get();
+            if (map1 == null) {
+                return false;
+            }
+
+            if (obj instanceof MapContentBinding) {
+                final MapContentBinding<?, ?> other = (MapContentBinding<?, ?>) obj;
+                final Map<?, ?> map2 = other.mapRef.get();
+                return map1 == map2;
+            }
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/DoubleConstant.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableDoubleValue;
+
+/**
+ * A simple DoubleExpression that represents a single constant value.
+ */
+public final class DoubleConstant implements ObservableDoubleValue {
+
+    private final double value;
+
+    private DoubleConstant(double value) {
+        this.value = value;
+    }
+
+    public static DoubleConstant valueOf(double value) {
+        return new DoubleConstant(value);
+    }
+
+    @Override
+    public double get() {
+        return value;
+    }
+
+    @Override
+    public Double getValue() {
+        return value;
+    }
+
+    @Override
+    public void addListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void addListener(ChangeListener<? super Number> listener) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(ChangeListener<? super Number> listener) {
+        // no-op
+    }
+
+    @Override
+    public int intValue() {
+        return (int) value;
+    }
+
+    @Override
+    public long longValue() {
+        return (long) value;
+    }
+
+    @Override
+    public float floatValue() {
+        return (float) value;
+    }
+
+    @Override
+    public double doubleValue() {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/ExpressionHelper.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+
+import java.util.Arrays;
+
+/**
+ * A convenience class for creating implementations of {@link javafx.beans.value.ObservableValue}.
+ * It contains all of the infrastructure support for value invalidation- and
+ * change event notification.
+ * 
+ * This implementation can handle adding and removing listeners while the
+ * observers are being notified, but it is not thread-safe.
+ * 
+ * 
+ */
+public abstract class ExpressionHelper<T> extends ExpressionHelperBase {
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Static methods
+
+    public static <T> ExpressionHelper<T> addListener(ExpressionHelper<T> helper, ObservableValue<T> observable, InvalidationListener listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        observable.getValue(); // validate observable
+        return (helper == null)? new SingleInvalidation<T>(observable, listener) : helper.addListener(listener);
+    }
+    
+    public static <T> ExpressionHelper<T> removeListener(ExpressionHelper<T> helper, InvalidationListener listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+    
+    public static <T> ExpressionHelper<T> addListener(ExpressionHelper<T> helper, ObservableValue<T> observable, ChangeListener<? super T> listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? new SingleChange<T>(observable, listener) : helper.addListener(listener);
+    }
+    
+    public static <T> ExpressionHelper<T> removeListener(ExpressionHelper<T> helper, ChangeListener<? super T> listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+    
+    public static <T> void fireValueChangedEvent(ExpressionHelper<T> helper) {
+        if (helper != null) {
+            helper.fireValueChangedEvent();
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Common implementations
+
+    protected final ObservableValue<T> observable;
+
+    private ExpressionHelper(ObservableValue<T> observable) {
+        this.observable = observable;
+    }
+
+    protected abstract ExpressionHelper<T> addListener(InvalidationListener listener);
+    protected abstract ExpressionHelper<T> removeListener(InvalidationListener listener);
+    
+    protected abstract ExpressionHelper<T> addListener(ChangeListener<? super T> listener);
+    protected abstract ExpressionHelper<T> removeListener(ChangeListener<? super T> listener);
+    
+    protected abstract void fireValueChangedEvent();
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Implementations
+
+    private static class SingleInvalidation<T> extends ExpressionHelper<T> {
+        
+        private final InvalidationListener listener;
+        
+        private SingleInvalidation(ObservableValue<T> expression, InvalidationListener listener) {
+            super(expression);
+            this.listener = listener;
+        }
+        
+        @Override 
+        protected ExpressionHelper<T> addListener(InvalidationListener listener) {
+            return new Generic<T>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ExpressionHelper<T> removeListener(InvalidationListener listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected ExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
+            return new Generic<T>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            listener.invalidated(observable);
+        }
+    }
+    
+    private static class SingleChange<T> extends ExpressionHelper<T> {
+        
+        private final ChangeListener<? super T> listener;
+        private T currentValue;
+        
+        private SingleChange(ObservableValue<T> observable, ChangeListener<? super T> listener) {
+            super(observable);
+            this.listener = listener;
+            this.currentValue = observable.getValue();
+        }
+        
+        @Override 
+        protected ExpressionHelper<T> addListener(InvalidationListener listener) {
+            return new Generic<T>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected ExpressionHelper<T> removeListener(InvalidationListener listener) {
+            return this;
+        }
+
+        @Override
+        protected ExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
+            return new Generic<T>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            final T oldValue = currentValue;
+            currentValue = observable.getValue();
+            final boolean changed = (currentValue == null)? (oldValue != null) : !currentValue.equals(oldValue);
+            if (changed) {
+                listener.changed(observable, oldValue, currentValue);
+            }
+        }
+    }
+    
+    private static class Generic<T> extends ExpressionHelper<T> {
+        
+        private InvalidationListener[] invalidationListeners;
+        private ChangeListener<? super T>[] changeListeners;
+        private int invalidationSize;
+        private int changeSize;
+        private boolean locked;
+        private T currentValue;
+        
+        private Generic(ObservableValue<T> observable, InvalidationListener listener0, InvalidationListener listener1) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {listener0, listener1};
+            this.invalidationSize = 2;
+        }
+
+        private Generic(ObservableValue<T> observable, ChangeListener<? super T> listener0, ChangeListener<? super T> listener1) {
+            super(observable);
+            this.changeListeners = new ChangeListener[] {listener0, listener1};
+            this.changeSize = 2;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableValue<T> observable, InvalidationListener invalidationListener, ChangeListener<? super T> changeListener) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {invalidationListener};
+            this.invalidationSize = 1;
+            this.changeListeners = new ChangeListener[] {changeListener};
+            this.changeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected Generic<T> addListener(InvalidationListener listener) {
+            if (invalidationListeners == null) {
+                invalidationListeners = new InvalidationListener[] {listener};
+                invalidationSize = 1;
+            } else {
+                final int oldCapacity = invalidationListeners.length;
+                if (locked) {
+                    final int newCapacity = (invalidationSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
+                } else if (invalidationSize == oldCapacity) {
+                    invalidationSize = trim(invalidationSize, invalidationListeners);
+                    if (invalidationSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
+                    }
+                }
+                invalidationListeners[invalidationSize++] = listener;
+            }
+            return this;
+        }
+
+        @Override
+        protected ExpressionHelper<T> removeListener(InvalidationListener listener) {
+            if (invalidationListeners != null) {
+                for (int index = 0; index < invalidationSize; index++) {
+                    if (listener.equals(invalidationListeners[index])) {
+                        if (invalidationSize == 1) {
+                            if (changeSize == 1) {
+                                return new SingleChange<T>(observable, changeListeners[0]);
+                            }
+                            invalidationListeners = null;
+                            invalidationSize = 0;
+                        } else if ((invalidationSize == 2) && (changeSize == 0)) {
+                            return new SingleInvalidation<T>(observable, invalidationListeners[1-index]);
+                        } else {
+                            final int numMoved = invalidationSize - index - 1;
+                            final InvalidationListener[] oldListeners = invalidationListeners;
+                            if (locked) {
+                                invalidationListeners = new InvalidationListener[invalidationListeners.length];
+                                System.arraycopy(oldListeners, 0, invalidationListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, invalidationListeners, index, numMoved);
+                            }
+                            invalidationSize--;
+                            if (!locked) {
+                                invalidationListeners[invalidationSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected ExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
+            if (changeListeners == null) {
+                changeListeners = new ChangeListener[] {listener};
+                changeSize = 1;
+            } else {
+                final int oldCapacity = changeListeners.length;
+                if (locked) {
+                    final int newCapacity = (changeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    changeListeners = Arrays.copyOf(changeListeners, newCapacity);
+                } else if (changeSize == oldCapacity) {
+                    changeSize = trim(changeSize, changeListeners);
+                    if (changeSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        changeListeners = Arrays.copyOf(changeListeners, newCapacity);
+                    }
+                }
+                changeListeners[changeSize++] = listener;
+            }
+            if (changeSize == 1) {
+                currentValue = observable.getValue();
+            }
+            return this;
+        }
+
+        @Override
+        protected ExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
+            if (changeListeners != null) {
+                for (int index = 0; index < changeSize; index++) {
+                    if (listener.equals(changeListeners[index])) {
+                        if (changeSize == 1) {
+                            if (invalidationSize == 1) {
+                                return new SingleInvalidation<T>(observable, invalidationListeners[0]);
+                            }
+                            changeListeners = null;
+                            changeSize = 0;
+                        } else if ((changeSize == 2) && (invalidationSize == 0)) {
+                            return new SingleChange<T>(observable, changeListeners[1-index]);
+                        } else {
+                            final int numMoved = changeSize - index - 1;
+                            final ChangeListener<? super T>[] oldListeners = changeListeners;
+                            if (locked) {
+                                changeListeners = new ChangeListener[changeListeners.length];
+                                System.arraycopy(oldListeners, 0, changeListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, changeListeners, index, numMoved);
+                            }
+                            changeSize--;
+                            if (!locked) {
+                                changeListeners[changeSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            final InvalidationListener[] curInvalidationList = invalidationListeners;
+            final int curInvalidationSize = invalidationSize;
+            final ChangeListener<? super T>[] curChangeList = changeListeners;
+            final int curChangeSize = changeSize;
+
+            try {
+                locked = true;
+                for (int i = 0; i < curInvalidationSize; i++) {
+                    curInvalidationList[i].invalidated(observable);
+                }
+                if (curChangeSize > 0) {
+                    final T oldValue = currentValue;
+                    currentValue = observable.getValue();
+                    final boolean changed = (currentValue == null)? (oldValue != null) : !currentValue.equals(oldValue);
+                    if (changed) {
+                        for (int i = 0; i < curChangeSize; i++) {
+                            curChangeList[i].changed(observable, oldValue, currentValue);
+                        }
+                    }
+                }
+            } finally {
+                locked = false;
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/ExpressionHelperBase.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.WeakListener;
+
+/**
+ */
+public class ExpressionHelperBase {
+
+    protected static int trim(int size, Object[] listeners) {
+        for (int index = 0; index < size; index++) {
+            final Object listener = listeners[index];
+            if (listener instanceof WeakListener) {
+                if (((WeakListener)listener).wasGarbageCollected()) {
+                    final int numMoved = size - index - 1;
+                    if (numMoved > 0)
+                        System.arraycopy(listeners, index+1, listeners, index, numMoved);
+                    listeners[--size] = null; // Let gc do its work
+                    index--;
+                }
+            }
+        }
+        return size;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/FloatConstant.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableFloatValue;
+
+/**
+ * A simple FloatExpression that represents a single constant value.
+ */
+public final class FloatConstant implements ObservableFloatValue {
+
+    private final float value;
+
+    private FloatConstant(float value) {
+        this.value = value;
+    }
+
+    public static FloatConstant valueOf(float value) {
+        return new FloatConstant(value);
+    }
+
+    @Override
+    public float get() {
+        return value;
+    }
+
+    @Override
+    public Float getValue() {
+        return value;
+    }
+
+    @Override
+    public void addListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void addListener(ChangeListener<? super Number> listener) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(ChangeListener<? super Number> listener) {
+        // no-op
+    }
+
+    @Override
+    public int intValue() {
+        return (int) value;
+    }
+
+    @Override
+    public long longValue() {
+        return (long) value;
+    }
+
+    @Override
+    public float floatValue() {
+        return value;
+    }
+
+    @Override
+    public double doubleValue() {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/IntegerConstant.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableIntegerValue;
+
+/**
+ * A simple IntegerExpression that represents a single constant value.
+ */
+public final class IntegerConstant implements ObservableIntegerValue {
+
+    private final int value;
+
+    private IntegerConstant(int value) {
+        this.value = value;
+    }
+
+    public static IntegerConstant valueOf(int value) {
+        return new IntegerConstant(value);
+    }
+
+    @Override
+    public int get() {
+        return value;
+    }
+
+    @Override
+    public Integer getValue() {
+        return value;
+    }
+
+    @Override
+    public void addListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void addListener(ChangeListener<? super Number> listener) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(ChangeListener<? super Number> listener) {
+        // no-op
+    }
+
+    @Override
+    public int intValue() {
+        return value;
+    }
+
+    @Override
+    public long longValue() {
+        return value;
+    }
+
+    @Override
+    public float floatValue() {
+        return value;
+    }
+
+    @Override
+    public double doubleValue() {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/ListExpressionHelper.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import com.sun.javafx.collections.NonIterableChange;
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableListValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static javafx.collections.ListChangeListener.Change;
+
+/**
+ * A convenience class for creating implementations of {@link javafx.beans.value.ObservableValue}.
+ * It contains all of the infrastructure support for value invalidation- and
+ * change event notification.
+ * 
+ * This implementation can handle adding and removing listeners while the
+ * observers are being notified, but it is not thread-safe.
+ * 
+ * 
+ */
+public abstract class ListExpressionHelper<E> extends ExpressionHelperBase {
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Static methods
+
+    public static <E> ListExpressionHelper<E> addListener(ListExpressionHelper<E> helper, ObservableListValue<E> observable, InvalidationListener listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        observable.getValue(); // validate observable
+        return (helper == null)? new SingleInvalidation<E>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <E> ListExpressionHelper<E> removeListener(ListExpressionHelper<E> helper, InvalidationListener listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <E> ListExpressionHelper<E> addListener(ListExpressionHelper<E> helper, ObservableListValue<E> observable, ChangeListener<? super ObservableList<E>> listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? new SingleChange<E>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <E> ListExpressionHelper<E> removeListener(ListExpressionHelper<E> helper, ChangeListener<? super ObservableList<E>> listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <E> ListExpressionHelper<E> addListener(ListExpressionHelper<E> helper, ObservableListValue<E> observable, ListChangeListener<? super E> listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? new SingleListChange<E>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <E> ListExpressionHelper<E> removeListener(ListExpressionHelper<E> helper, ListChangeListener<? super E> listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <E> void fireValueChangedEvent(ListExpressionHelper<E> helper) {
+        if (helper != null) {
+            helper.fireValueChangedEvent();
+        }
+    }
+
+    public static <E> void fireValueChangedEvent(ListExpressionHelper<E> helper, Change<? extends E> change) {
+        if (helper != null) {
+            helper.fireValueChangedEvent(change);
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Common implementations
+
+    protected final ObservableListValue<E> observable;
+
+    protected ListExpressionHelper(ObservableListValue<E> observable) {
+        this.observable = observable;
+    }
+
+    protected abstract ListExpressionHelper<E> addListener(InvalidationListener listener);
+    protected abstract ListExpressionHelper<E> removeListener(InvalidationListener listener);
+
+    protected abstract ListExpressionHelper<E> addListener(ChangeListener<? super ObservableList<E>> listener);
+    protected abstract ListExpressionHelper<E> removeListener(ChangeListener<? super ObservableList<E>> listener);
+
+    protected abstract ListExpressionHelper<E> addListener(ListChangeListener<? super E> listener);
+    protected abstract ListExpressionHelper<E> removeListener(ListChangeListener<? super E> listener);
+
+    protected abstract void fireValueChangedEvent();
+    protected abstract void fireValueChangedEvent(Change<? extends E> change);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Implementations
+
+    private static class SingleInvalidation<E> extends ListExpressionHelper<E> {
+
+        private final InvalidationListener listener;
+
+        private SingleInvalidation(ObservableListValue<E> observable, InvalidationListener listener) {
+            super(observable);
+            this.listener = listener;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(InvalidationListener listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(InvalidationListener listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(ChangeListener<? super ObservableList<E>> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(ChangeListener<? super ObservableList<E>> listener) {
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(ListChangeListener<? super E> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(ListChangeListener<? super E> listener) {
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            listener.invalidated(observable);
+        }
+
+        @Override
+        protected void fireValueChangedEvent(Change<? extends E> change) {
+            listener.invalidated(observable);
+        }
+    }
+
+    private static class SingleChange<E> extends ListExpressionHelper<E> {
+
+        private final ChangeListener<? super ObservableList<E>> listener;
+        private ObservableList<E> currentValue;
+
+        private SingleChange(ObservableListValue<E> observable, ChangeListener<? super ObservableList<E>> listener) {
+            super(observable);
+            this.listener = listener;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(InvalidationListener listener) {
+            return new Generic<E>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(InvalidationListener listener) {
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(ChangeListener<? super ObservableList<E>> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(ChangeListener<? super ObservableList<E>> listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(ListChangeListener<? super E> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(ListChangeListener<? super E> listener) {
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            final ObservableList<E> oldValue = currentValue;
+            currentValue = observable.getValue();
+            if (currentValue != oldValue) {
+                listener.changed(observable, oldValue, currentValue);
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(Change<? extends E> change) {
+            listener.changed(observable, currentValue, currentValue);
+        }
+    }
+
+    private static class SingleListChange<E> extends ListExpressionHelper<E> {
+
+        private final ListChangeListener<? super E> listener;
+        private ObservableList<E> currentValue;
+
+        private SingleListChange(ObservableListValue<E> observable, ListChangeListener<? super E> listener) {
+            super(observable);
+            this.listener = listener;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(InvalidationListener listener) {
+            return new Generic<E>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(InvalidationListener listener) {
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(ChangeListener<? super ObservableList<E>> listener) {
+            return new Generic<E>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(ChangeListener<? super ObservableList<E>> listener) {
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(ListChangeListener<? super E> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(ListChangeListener<? super E> listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            final ObservableList<E> oldValue = currentValue;
+            currentValue = observable.getValue();
+            if (currentValue != oldValue) {
+                final int safeSize = (currentValue == null)? 0 : currentValue.size();
+                final ObservableList<E> safeOldValue = (oldValue == null)? 
+                        FXCollections.<E>emptyObservableList() 
+                        : FXCollections.unmodifiableObservableList(oldValue);
+                final Change<E> change = new NonIterableChange.GenericAddRemoveChange<E>(0, safeSize, safeOldValue, observable);
+                listener.onChanged(change);
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(final Change<? extends E> change) {
+            listener.onChanged(new MappedChange<E>(observable, change));
+        }
+    }
+
+    private static class Generic<E> extends ListExpressionHelper<E> {
+
+        private InvalidationListener[] invalidationListeners;
+        private ChangeListener<? super ObservableList<E>>[] changeListeners;
+        private ListChangeListener<? super E>[] listChangeListeners;
+        private int invalidationSize;
+        private int changeSize;
+        private int listChangeSize;
+        private boolean locked;
+        private ObservableList<E> currentValue;
+
+        private Generic(ObservableListValue<E> observable, InvalidationListener listener0, InvalidationListener listener1) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {listener0, listener1};
+            this.invalidationSize = 2;
+        }
+
+        private Generic(ObservableListValue<E> observable, ChangeListener<? super ObservableList<E>> listener0, ChangeListener<? super ObservableList<E>> listener1) {
+            super(observable);
+            this.changeListeners = new ChangeListener[] {listener0, listener1};
+            this.changeSize = 2;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableListValue<E> observable, ListChangeListener<? super E> listener0, ListChangeListener<? super E> listener1) {
+            super(observable);
+            this.listChangeListeners = new ListChangeListener[] {listener0, listener1};
+            this.listChangeSize = 2;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableListValue<E> observable, InvalidationListener invalidationListener, ChangeListener<? super ObservableList<E>> changeListener) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {invalidationListener};
+            this.invalidationSize = 1;
+            this.changeListeners = new ChangeListener[] {changeListener};
+            this.changeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableListValue<E> observable, InvalidationListener invalidationListener, ListChangeListener<? super E> listChangeListener) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {invalidationListener};
+            this.invalidationSize = 1;
+            this.listChangeListeners = new ListChangeListener[] {listChangeListener};
+            this.listChangeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableListValue<E> observable, ChangeListener<? super ObservableList<E>> changeListener, ListChangeListener<? super E> listChangeListener) {
+            super(observable);
+            this.changeListeners = new ChangeListener[] {changeListener};
+            this.changeSize = 1;
+            this.listChangeListeners = new ListChangeListener[] {listChangeListener};
+            this.listChangeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(InvalidationListener listener) {
+            if (invalidationListeners == null) {
+                invalidationListeners = new InvalidationListener[] {listener};
+                invalidationSize = 1;
+            } else {
+                final int oldCapacity = invalidationListeners.length;
+                if (locked) {
+                    final int newCapacity = (invalidationSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
+                } else if (invalidationSize == oldCapacity) {
+                    invalidationSize = trim(invalidationSize, invalidationListeners);
+                    if (invalidationSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
+                    }
+                }
+                invalidationListeners[invalidationSize++] = listener;
+            }
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(InvalidationListener listener) {
+            if (invalidationListeners != null) {
+                for (int index = 0; index < invalidationSize; index++) {
+                    if (listener.equals(invalidationListeners[index])) {
+                        if (invalidationSize == 1) {
+                            if ((changeSize == 1) && (listChangeSize == 0)) {
+                                return new SingleChange<E>(observable, changeListeners[0]);
+                            } else if ((changeSize == 0) && (listChangeSize == 1)) {
+                                return new SingleListChange<E>(observable, listChangeListeners[0]);
+                            }
+                            invalidationListeners = null;
+                            invalidationSize = 0;
+                        } else if ((invalidationSize == 2) && (changeSize == 0) && (listChangeSize == 0)) {
+                            return new SingleInvalidation<E>(observable, invalidationListeners[1-index]);
+                        } else {
+                            final int numMoved = invalidationSize - index - 1;
+                            final InvalidationListener[] oldListeners = invalidationListeners;
+                            if (locked) {
+                                invalidationListeners = new InvalidationListener[invalidationListeners.length];
+                                System.arraycopy(oldListeners, 0, invalidationListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, invalidationListeners, index, numMoved);
+                            }
+                            invalidationSize--;
+                            if (!locked) {
+                                invalidationListeners[invalidationSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(ChangeListener<? super ObservableList<E>> listener) {
+            if (changeListeners == null) {
+                changeListeners = new ChangeListener[] {listener};
+                changeSize = 1;
+            } else {
+                final int oldCapacity = changeListeners.length;
+                if (locked) {
+                    final int newCapacity = (changeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    changeListeners = Arrays.copyOf(changeListeners, newCapacity);
+                } else if (changeSize == oldCapacity) {
+                    changeSize = trim(changeSize, changeListeners);
+                    if (changeSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        changeListeners = Arrays.copyOf(changeListeners, newCapacity);
+                    }
+                }
+                changeListeners[changeSize++] = listener;
+            }
+            if (changeSize == 1) {
+                currentValue = observable.getValue();
+            }
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(ChangeListener<? super ObservableList<E>> listener) {
+            if (changeListeners != null) {
+                for (int index = 0; index < changeSize; index++) {
+                    if (listener.equals(changeListeners[index])) {
+                        if (changeSize == 1) {
+                            if ((invalidationSize == 1) && (listChangeSize == 0)) {
+                                return new SingleInvalidation<E>(observable, invalidationListeners[0]);
+                            } else if ((invalidationSize == 0) && (listChangeSize == 1)) {
+                                return new SingleListChange<E>(observable, listChangeListeners[0]);
+                            }
+                            changeListeners = null;
+                            changeSize = 0;
+                        } else if ((changeSize == 2) && (invalidationSize == 0) && (listChangeSize == 0)) {
+                            return new SingleChange<E>(observable, changeListeners[1-index]);
+                        } else {
+                            final int numMoved = changeSize - index - 1;
+                            final ChangeListener<? super ObservableList<E>>[] oldListeners = changeListeners;
+                            if (locked) {
+                                changeListeners = new ChangeListener[changeListeners.length];
+                                System.arraycopy(oldListeners, 0, changeListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, changeListeners, index, numMoved);
+                            }
+                            changeSize--;
+                            if (!locked) {
+                                changeListeners[changeSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> addListener(ListChangeListener<? super E> listener) {
+            if (listChangeListeners == null) {
+                listChangeListeners = new ListChangeListener[] {listener};
+                listChangeSize = 1;
+            } else {
+                final int oldCapacity = listChangeListeners.length;
+                if (locked) {
+                    final int newCapacity = (listChangeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    listChangeListeners = Arrays.copyOf(listChangeListeners, newCapacity);
+                } else if (listChangeSize == oldCapacity) {
+                    listChangeSize = trim(listChangeSize, listChangeListeners);
+                    if (listChangeSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        listChangeListeners = Arrays.copyOf(listChangeListeners, newCapacity);
+                    }
+                }
+                listChangeListeners[listChangeSize++] = listener;
+            }
+            if (listChangeSize == 1) {
+                currentValue = observable.getValue();
+            }
+            return this;
+        }
+
+        @Override
+        protected ListExpressionHelper<E> removeListener(ListChangeListener<? super E> listener) {
+            if (listChangeListeners != null) {
+                for (int index = 0; index < listChangeSize; index++) {
+                    if (listener.equals(listChangeListeners[index])) {
+                        if (listChangeSize == 1) {
+                            if ((invalidationSize == 1) && (changeSize == 0)) {
+                                return new SingleInvalidation<E>(observable, invalidationListeners[0]);
+                            } else if ((invalidationSize == 0) && (changeSize == 1)) {
+                                return new SingleChange<E>(observable, changeListeners[0]);
+                            }
+                            listChangeListeners = null;
+                            listChangeSize = 0;
+                        } else if ((listChangeSize == 2) && (invalidationSize == 0) && (changeSize == 0)) {
+                            return new SingleListChange<E>(observable, listChangeListeners[1-index]);
+                        } else {
+                            final int numMoved = listChangeSize - index - 1;
+                            final ListChangeListener<? super E>[] oldListeners = listChangeListeners;
+                            if (locked) {
+                                listChangeListeners = new ListChangeListener[listChangeListeners.length];
+                                System.arraycopy(oldListeners, 0, listChangeListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, listChangeListeners, index, numMoved);
+                            }
+                            listChangeSize--;
+                            if (!locked) {
+                                listChangeListeners[listChangeSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            if ((changeSize == 0) && (listChangeSize == 0)) {
+                notifyListeners(currentValue, null, false);
+            } else {
+                final ObservableList<E> oldValue = currentValue;
+                currentValue = observable.getValue();
+                if ((currentValue == null)? (oldValue != null) : !currentValue.equals(oldValue)) {
+                    Change<E> change = null;
+                    if (listChangeSize > 0) {
+                        final int safeSize = (currentValue == null)? 0 : currentValue.size();
+                        final ObservableList<E> safeOldValue = (oldValue == null)?
+                                FXCollections.<E>emptyObservableList()
+                                : FXCollections.unmodifiableObservableList(oldValue);
+                        change = new NonIterableChange.GenericAddRemoveChange(0, safeSize, safeOldValue, observable);
+                    }
+                    notifyListeners(oldValue, change, false);
+                } else {
+                    notifyListeners(currentValue, null, true);
+                }
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(final Change<? extends E> change) {
+            final Change<E> mappedChange = (listChangeSize == 0)? null : new MappedChange<E>(observable, change);
+            notifyListeners(currentValue, mappedChange, false);
+        }
+
+        private void notifyListeners(ObservableList<E> oldValue, Change<E> change, boolean noChange) {
+            final InvalidationListener[] curInvalidationList = invalidationListeners;
+            final int curInvalidationSize = invalidationSize;
+            final ChangeListener<? super ObservableList<E>>[] curChangeList = changeListeners;
+            final int curChangeSize = changeSize;
+            final ListChangeListener<? super E>[] curListChangeList = listChangeListeners;
+            final int curListChangeSize = listChangeSize;
+            try {
+                locked = true;
+                for (int i = 0; i < curInvalidationSize; i++) {
+                    curInvalidationList[i].invalidated(observable);
+                }
+                if (!noChange) {
+                    for (int i = 0; i < curChangeSize; i++) {
+                        curChangeList[i].changed(observable, oldValue, currentValue);
+                    }
+                    if (change != null) {
+                        for (int i = 0; i < curListChangeSize; i++) {
+                            change.reset();
+                            curListChangeList[i].onChanged(change);
+                        }
+                    }
+                }
+            } finally {
+                locked = false;
+            }
+        }
+
+    }
+
+    private static class MappedChange<E> extends Change<E> {
+        private final Change<? extends E> source;
+        private int[] perm;
+
+        private MappedChange(ObservableList<E> list, Change<? extends E> source) {
+            super(list);
+            this.source = source;
+        }
+
+        @Override public boolean next() {return source.next();}
+        @Override public void reset() {source.reset();}
+        @Override public int getFrom() {return source.getFrom();}
+        @Override public int getTo() {return source.getTo();}
+        @Override public List<E> getRemoved() {return (List<E>)source.getRemoved();}
+        @Override protected int[] getPermutation() {
+            if (perm == null) {
+                if (source.wasPermutated()) {
+                    final int from = source.getFrom();
+                    final int n = source.getTo() - from;
+                    perm = new int[n];
+                    for (int i=0; i<n; i++) {
+                        perm[i] = source.getPermutation(from + i);
+                    }
+                } else {
+                    perm = new int[0];
+                }
+            }
+            return perm;
+        }
+
+        @Override
+        public String toString() {
+            return source.toString();
+        }
+        
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/Logging.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.binding;
+
+import sun.util.logging.PlatformLogger;
+
+public class Logging {
+
+    private static class LoggerHolder {
+        private static final PlatformLogger INSTANCE = PlatformLogger.getLogger("beans");
+    }
+
+    public static PlatformLogger getLogger() {
+        return LoggerHolder.INSTANCE;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/LongConstant.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableLongValue;
+
+/**
+ * A simple LongExpression that represents a single constant value.
+ */
+public final class LongConstant implements ObservableLongValue {
+
+    private final long value;
+
+    private LongConstant(long value) {
+        this.value = value;
+    }
+
+    public static LongConstant valueOf(long value) {
+        return new LongConstant(value);
+    }
+
+    @Override
+    public long get() {
+        return value;
+    }
+
+    @Override
+    public Long getValue() {
+        return value;
+    }
+
+    @Override
+    public void addListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void addListener(ChangeListener<? super Number> observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(ChangeListener<? super Number> observer) {
+        // no-op
+    }
+
+    @Override
+    public int intValue() {
+        return (int) value;
+    }
+
+    @Override
+    public long longValue() {
+        return value;
+    }
+
+    @Override
+    public float floatValue() {
+        return value;
+    }
+
+    @Override
+    public double doubleValue() {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/MapExpressionHelper.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableMapValue;
+import javafx.collections.MapChangeListener;
+import javafx.collections.ObservableMap;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+*/
+public abstract class MapExpressionHelper<K, V> extends ExpressionHelperBase {
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Static methods
+
+    public static <K, V> MapExpressionHelper<K, V> addListener(MapExpressionHelper<K, V> helper, ObservableMapValue<K, V> observable, InvalidationListener listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        observable.getValue(); // validate observable
+        return (helper == null)? new SingleInvalidation<K, V>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <K, V> MapExpressionHelper<K, V> removeListener(MapExpressionHelper<K, V> helper, InvalidationListener listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <K, V> MapExpressionHelper<K, V> addListener(MapExpressionHelper<K, V> helper, ObservableMapValue<K, V> observable, ChangeListener<? super ObservableMap<K, V>> listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? new SingleChange<K, V>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <K, V> MapExpressionHelper<K, V> removeListener(MapExpressionHelper<K, V> helper, ChangeListener<? super ObservableMap<K, V>> listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <K, V> MapExpressionHelper<K, V> addListener(MapExpressionHelper<K, V> helper, ObservableMapValue<K, V> observable, MapChangeListener<? super K, ? super V> listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? new SingleMapChange<K, V>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <K, V> MapExpressionHelper<K, V> removeListener(MapExpressionHelper<K, V> helper, MapChangeListener<? super K, ? super V> listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <K, V> void fireValueChangedEvent(MapExpressionHelper<K, V> helper) {
+        if (helper != null) {
+            helper.fireValueChangedEvent();
+        }
+    }
+
+    public static <K, V> void fireValueChangedEvent(MapExpressionHelper<K, V> helper, MapChangeListener.Change<? extends K, ? extends V> change) {
+        if (helper != null) {
+            helper.fireValueChangedEvent(change);
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Common implementations
+
+    protected final ObservableMapValue<K, V> observable;
+
+    protected MapExpressionHelper(ObservableMapValue<K, V> observable) {
+        this.observable = observable;
+    }
+
+    protected abstract MapExpressionHelper<K, V> addListener(InvalidationListener listener);
+    protected abstract MapExpressionHelper<K, V> removeListener(InvalidationListener listener);
+
+    protected abstract MapExpressionHelper<K, V> addListener(ChangeListener<? super ObservableMap<K, V>> listener);
+    protected abstract MapExpressionHelper<K, V> removeListener(ChangeListener<? super ObservableMap<K, V>> listener);
+
+    protected abstract MapExpressionHelper<K, V> addListener(MapChangeListener<? super K, ? super V> listener);
+    protected abstract MapExpressionHelper<K, V> removeListener(MapChangeListener<? super K, ? super V> listener);
+
+    protected abstract void fireValueChangedEvent();
+    protected abstract void fireValueChangedEvent(MapChangeListener.Change<? extends K, ? extends V> change);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Implementations
+
+    private static class SingleInvalidation<K, V> extends MapExpressionHelper<K, V> {
+
+        private final InvalidationListener listener;
+
+        private SingleInvalidation(ObservableMapValue<K, V> observable, InvalidationListener listener) {
+            super(observable);
+            this.listener = listener;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(InvalidationListener listener) {
+            return new Generic<K, V>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(InvalidationListener listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(ChangeListener<? super ObservableMap<K, V>> listener) {
+            return new Generic<K, V>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(ChangeListener<? super ObservableMap<K, V>> listener) {
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(MapChangeListener<? super K, ? super V> listener) {
+            return new Generic<K, V>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(MapChangeListener<? super K, ? super V> listener) {
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            listener.invalidated(observable);
+        }
+
+        @Override
+        protected void fireValueChangedEvent(MapChangeListener.Change<? extends K, ? extends V> change) {
+            listener.invalidated(observable);
+        }
+    }
+
+    private static class SingleChange<K, V> extends MapExpressionHelper<K, V> {
+
+        private final ChangeListener<? super ObservableMap<K, V>> listener;
+        private ObservableMap<K, V> currentValue;
+
+        private SingleChange(ObservableMapValue<K, V> observable, ChangeListener<? super ObservableMap<K, V>> listener) {
+            super(observable);
+            this.listener = listener;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(InvalidationListener listener) {
+            return new Generic<K, V>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(InvalidationListener listener) {
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(ChangeListener<? super ObservableMap<K, V>> listener) {
+            return new Generic<K, V>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(ChangeListener<? super ObservableMap<K, V>> listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(MapChangeListener<? super K, ? super V> listener) {
+            return new Generic<K, V>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(MapChangeListener<? super K, ? super V> listener) {
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            final ObservableMap<K, V> oldValue = currentValue;
+            currentValue = observable.getValue();
+            if (currentValue != oldValue) {
+                listener.changed(observable, oldValue, currentValue);
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(MapChangeListener.Change<? extends K, ? extends V> change) {
+            listener.changed(observable, currentValue, currentValue);
+        }
+    }
+
+    private static class SingleMapChange<K, V> extends MapExpressionHelper<K, V> {
+
+        private final MapChangeListener<? super K, ? super V> listener;
+        private ObservableMap<K, V> currentValue;
+
+        private SingleMapChange(ObservableMapValue<K, V> observable, MapChangeListener<? super K, ? super V> listener) {
+            super(observable);
+            this.listener = listener;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(InvalidationListener listener) {
+            return new Generic<K, V>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(InvalidationListener listener) {
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(ChangeListener<? super ObservableMap<K, V>> listener) {
+            return new Generic<K, V>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(ChangeListener<? super ObservableMap<K, V>> listener) {
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(MapChangeListener<? super K, ? super V> listener) {
+            return new Generic<K, V>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(MapChangeListener<? super K, ? super V> listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            final ObservableMap<K, V> oldValue = currentValue;
+            currentValue = observable.getValue();
+            if (currentValue != oldValue) {
+                final SimpleChange<K, V> change = new SimpleChange<K, V>(observable);
+                if (currentValue == null) {
+                    for (final Map.Entry<K, V> element : oldValue.entrySet()) {
+                        listener.onChanged(change.setRemoved(element.getKey(), element.getValue()));
+                    }
+                } else if (oldValue == null) {
+                    for (final Map.Entry<K, V> element : currentValue.entrySet()) {
+                        listener.onChanged(change.setAdded(element.getKey(), element.getValue()));
+                    }
+                } else {
+                    for (final Map.Entry<K, V> element : oldValue.entrySet()) {
+                        final K key = element.getKey();
+                        final V oldEntry = element.getValue();
+                        final V newEntry = currentValue.get(key);
+                        if (newEntry != null) {
+                            if (!newEntry.equals(oldEntry)) {
+                                listener.onChanged(change.setPut(key, oldEntry, newEntry));
+                            }
+                        } else {
+                            listener.onChanged(change.setRemoved(key, oldEntry));
+                        }
+                    }
+                    for (final Map.Entry<K, V> element : currentValue.entrySet()) {
+                        final K key = element.getKey();
+                        if (!oldValue.containsKey(key)) {
+                            listener.onChanged(change.setAdded(key, element.getValue()));
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(final MapChangeListener.Change<? extends K, ? extends V> change) {
+            listener.onChanged(new SimpleChange<K, V>(observable, change));
+        }
+    }
+
+    private static class Generic<K, V> extends MapExpressionHelper<K, V> {
+
+        private InvalidationListener[] invalidationListeners;
+        private ChangeListener<? super ObservableMap<K, V>>[] changeListeners;
+        private MapChangeListener<? super K, ? super V>[] mapChangeListeners;
+        private int invalidationSize;
+        private int changeSize;
+        private int mapChangeSize;
+        private boolean locked;
+        private ObservableMap<K, V> currentValue;
+
+        private Generic(ObservableMapValue<K, V> observable, InvalidationListener listener0, InvalidationListener listener1) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {listener0, listener1};
+            this.invalidationSize = 2;
+        }
+
+        private Generic(ObservableMapValue<K, V> observable, ChangeListener<? super ObservableMap<K, V>> listener0, ChangeListener<? super ObservableMap<K, V>> listener1) {
+            super(observable);
+            this.changeListeners = new ChangeListener[] {listener0, listener1};
+            this.changeSize = 2;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableMapValue<K, V> observable, MapChangeListener<? super K, ? super V> listener0, MapChangeListener<? super K, ? super V> listener1) {
+            super(observable);
+            this.mapChangeListeners = new MapChangeListener[] {listener0, listener1};
+            this.mapChangeSize = 2;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableMapValue<K, V> observable, InvalidationListener invalidationListener, ChangeListener<? super ObservableMap<K, V>> changeListener) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {invalidationListener};
+            this.invalidationSize = 1;
+            this.changeListeners = new ChangeListener[] {changeListener};
+            this.changeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableMapValue<K, V> observable, InvalidationListener invalidationListener, MapChangeListener<? super K, ? super V> listChangeListener) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {invalidationListener};
+            this.invalidationSize = 1;
+            this.mapChangeListeners = new MapChangeListener[] {listChangeListener};
+            this.mapChangeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableMapValue<K, V> observable, ChangeListener<? super ObservableMap<K, V>> changeListener, MapChangeListener<? super K, ? super V> listChangeListener) {
+            super(observable);
+            this.changeListeners = new ChangeListener[] {changeListener};
+            this.changeSize = 1;
+            this.mapChangeListeners = new MapChangeListener[] {listChangeListener};
+            this.mapChangeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(InvalidationListener listener) {
+            if (invalidationListeners == null) {
+                invalidationListeners = new InvalidationListener[] {listener};
+                invalidationSize = 1;
+            } else {
+                final int oldCapacity = invalidationListeners.length;
+                if (locked) {
+                    final int newCapacity = (invalidationSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
+                } else if (invalidationSize == oldCapacity) {
+                    invalidationSize = trim(invalidationSize, invalidationListeners);
+                    if (invalidationSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
+                    }
+                }
+                invalidationListeners[invalidationSize++] = listener;
+            }
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(InvalidationListener listener) {
+            if (invalidationListeners != null) {
+                for (int index = 0; index < invalidationSize; index++) {
+                    if (listener.equals(invalidationListeners[index])) {
+                        if (invalidationSize == 1) {
+                            if ((changeSize == 1) && (mapChangeSize == 0)) {
+                                return new SingleChange<K, V>(observable, changeListeners[0]);
+                            } else if ((changeSize == 0) && (mapChangeSize == 1)) {
+                                return new SingleMapChange<K, V>(observable, mapChangeListeners[0]);
+                            }
+                            invalidationListeners = null;
+                            invalidationSize = 0;
+                        } else {
+                            final int numMoved = invalidationSize - index - 1;
+                            final InvalidationListener[] oldListeners = invalidationListeners;
+                            if (locked) {
+                                invalidationListeners = new InvalidationListener[invalidationListeners.length];
+                                System.arraycopy(oldListeners, 0, invalidationListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, invalidationListeners, index, numMoved);
+                            }
+                            if (!locked) {
+                                invalidationListeners[--invalidationSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(ChangeListener<? super ObservableMap<K, V>> listener) {
+            if (changeListeners == null) {
+                changeListeners = new ChangeListener[] {listener};
+                changeSize = 1;
+            } else {
+                final int oldCapacity = changeListeners.length;
+                if (locked) {
+                    final int newCapacity = (changeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    changeListeners = Arrays.copyOf(changeListeners, newCapacity);
+                } else if (changeSize == oldCapacity) {
+                    changeSize = trim(changeSize, changeListeners);
+                    if (changeSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        changeListeners = Arrays.copyOf(changeListeners, newCapacity);
+                    }
+                }
+                changeListeners[changeSize++] = listener;
+            }
+            if (changeSize == 1) {
+                currentValue = observable.getValue();
+            }
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(ChangeListener<? super ObservableMap<K, V>> listener) {
+            if (changeListeners != null) {
+                for (int index = 0; index < changeSize; index++) {
+                    if (listener.equals(changeListeners[index])) {
+                        if (changeSize == 1) {
+                            if ((invalidationSize == 1) && (mapChangeSize == 0)) {
+                                return new SingleInvalidation<K, V>(observable, invalidationListeners[0]);
+                            } else if ((invalidationSize == 0) && (mapChangeSize == 1)) {
+                                return new SingleMapChange<K, V>(observable, mapChangeListeners[0]);
+                            }
+                            changeListeners = null;
+                            changeSize = 0;
+                        } else {
+                            final int numMoved = changeSize - index - 1;
+                            final ChangeListener<? super ObservableMap<K, V>>[] oldListeners = changeListeners;
+                            if (locked) {
+                                changeListeners = new ChangeListener[changeListeners.length];
+                                System.arraycopy(oldListeners, 0, changeListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, changeListeners, index, numMoved);
+                            }
+                            if (!locked) {
+                                changeListeners[--changeSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> addListener(MapChangeListener<? super K, ? super V> listener) {
+            if (mapChangeListeners == null) {
+                mapChangeListeners = new MapChangeListener[] {listener};
+                mapChangeSize = 1;
+            } else {
+                final int oldCapacity = mapChangeListeners.length;
+                if (locked) {
+                    final int newCapacity = (mapChangeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    mapChangeListeners = Arrays.copyOf(mapChangeListeners, newCapacity);
+                } else if (mapChangeSize == oldCapacity) {
+                    mapChangeSize = trim(mapChangeSize, mapChangeListeners);
+                    if (mapChangeSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        mapChangeListeners = Arrays.copyOf(mapChangeListeners, newCapacity);
+                    }
+                }
+                mapChangeListeners[mapChangeSize++] = listener;
+            }
+            if (mapChangeSize == 1) {
+                currentValue = observable.getValue();
+            }
+            return this;
+        }
+
+        @Override
+        protected MapExpressionHelper<K, V> removeListener(MapChangeListener<? super K, ? super V> listener) {
+            if (mapChangeListeners != null) {
+                for (int index = 0; index < mapChangeSize; index++) {
+                    if (listener.equals(mapChangeListeners[index])) {
+                        if (mapChangeSize == 1) {
+                            if ((invalidationSize == 1) && (changeSize == 0)) {
+                                return new SingleInvalidation<K, V>(observable, invalidationListeners[0]);
+                            } else if ((invalidationSize == 0) && (changeSize == 1)) {
+                                return new SingleChange<K, V>(observable, changeListeners[0]);
+                            }
+                            mapChangeListeners = null;
+                            mapChangeSize = 0;
+                        } else {
+                            final int numMoved = mapChangeSize - index - 1;
+                            final MapChangeListener<? super K, ? super V>[] oldListeners = mapChangeListeners;
+                            if (locked) {
+                                mapChangeListeners = new MapChangeListener[mapChangeListeners.length];
+                                System.arraycopy(oldListeners, 0, mapChangeListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, mapChangeListeners, index, numMoved);
+                            }
+                            if (!locked) {
+                                mapChangeListeners[--mapChangeSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            if ((changeSize == 0) && (mapChangeSize == 0)) {
+                notifyListeners(currentValue, null);
+            } else {
+                final ObservableMap<K, V> oldValue = currentValue;
+                currentValue = observable.getValue();
+                notifyListeners(oldValue, null);
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(final MapChangeListener.Change<? extends K, ? extends V> change) {
+            final SimpleChange<K, V> mappedChange = (mapChangeSize == 0)? null : new SimpleChange<K, V>(observable, change);
+            notifyListeners(currentValue, mappedChange);
+        }
+
+        private void notifyListeners(ObservableMap<K, V> oldValue, SimpleChange<K, V> change) {
+            final InvalidationListener[] curInvalidationList = invalidationListeners;
+            final int curInvalidationSize = invalidationSize;
+            final ChangeListener<? super ObservableMap<K, V>>[] curChangeList = changeListeners;
+            final int curChangeSize = changeSize;
+            final MapChangeListener<? super K, ? super V>[] curListChangeList = mapChangeListeners;
+            final int curListChangeSize = mapChangeSize;
+            try {
+                locked = true;
+                for (int i = 0; i < curInvalidationSize; i++) {
+                    curInvalidationList[i].invalidated(observable);
+                }
+                if ((currentValue != oldValue) || (change != null)) {
+                    for (int i = 0; i < curChangeSize; i++) {
+                        curChangeList[i].changed(observable, oldValue, currentValue);
+                    }
+                    if (curListChangeSize > 0) {
+                        if (change != null) {
+                            for (int i = 0; i < curListChangeSize; i++) {
+                                curListChangeList[i].onChanged(change);
+                            }
+                        } else {
+                            change = new SimpleChange<K, V>(observable);
+                            if (currentValue == null) {
+                                for (final Map.Entry<K, V> element : oldValue.entrySet()) {
+                                    change.setRemoved(element.getKey(), element.getValue());
+                                    for (int i = 0; i < curListChangeSize; i++) {
+                                        curListChangeList[i].onChanged(change);
+                                    }
+                                }
+                            } else if (oldValue == null) {
+                                for (final Map.Entry<K, V> element : currentValue.entrySet()) {
+                                    change.setAdded(element.getKey(), element.getValue());
+                                    for (int i = 0; i < curListChangeSize; i++) {
+                                        curListChangeList[i].onChanged(change);
+                                    }
+                                }
+                            } else {
+                                for (final Map.Entry<K, V> element : oldValue.entrySet()) {
+                                    final K key = element.getKey();
+                                    final V oldEntry = element.getValue();
+                                    final V newEntry = currentValue.get(key);
+                                    if (newEntry != null) {
+                                        if (!newEntry.equals(oldEntry)) {
+                                            change.setPut(key, oldEntry, newEntry);
+                                            for (int i = 0; i < curListChangeSize; i++) {
+                                                curListChangeList[i].onChanged(change);
+                                            }
+                                        }
+                                    } else {
+                                        change.setRemoved(key, oldEntry);
+                                        for (int i = 0; i < curListChangeSize; i++) {
+                                            curListChangeList[i].onChanged(change);
+                                        }
+                                    }
+                                }
+                                for (final Map.Entry<K, V> element : currentValue.entrySet()) {
+                                    final K key = element.getKey();
+                                    if (!oldValue.containsKey(key)) {
+                                        change.setAdded(key, element.getValue());
+                                        for (int i = 0; i < curListChangeSize; i++) {
+                                            curListChangeList[i].onChanged(change);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            } finally {
+                locked = false;
+            }
+        }
+
+    }
+
+    public static class SimpleChange<K, V> extends MapChangeListener.Change<K, V> {
+
+        private K key;
+        private V old;
+        private V added;
+
+        public SimpleChange(ObservableMap<K, V> set) {
+            super(set);
+        }
+
+        public SimpleChange(ObservableMap<K, V> set, MapChangeListener.Change<? extends K, ? extends V> source) {
+            super(set);
+            key = source.getKey();
+            old = source.getValueRemoved();
+            added = source.getValueAdded();
+        }
+
+        public SimpleChange<K, V> setRemoved(K key, V old) {
+            this.key = key;
+            this.old = old;
+            this.added = null;
+            return this;
+        }
+
+        public SimpleChange<K, V> setAdded(K key, V added) {
+            this.key = key;
+            this.old = null;
+            this.added = added;
+            return this;
+        }
+        
+        public SimpleChange<K, V> setPut(K key, V old, V added) {
+            this.key = key;
+            this.old = old;
+            this.added = added;
+            return this;
+        }
+
+        @Override
+        public boolean wasAdded() {
+            return added != null;
+        }
+
+        @Override
+        public boolean wasRemoved() {
+            return old != null;
+        }
+
+        @Override
+        public K getKey() {
+            return key;
+        }
+
+        @Override
+        public V getValueAdded() {
+            return added;
+        }
+
+        @Override
+        public V getValueRemoved() {
+            return old;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/ObjectConstant.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableObjectValue;
+
+public class ObjectConstant<T> implements ObservableObjectValue<T> {
+
+    private final T value;
+
+    private ObjectConstant(T value) {
+        this.value = value;
+    }
+
+    public static <T> ObjectConstant<T> valueOf(T value) {
+        return new ObjectConstant<T>(value);
+    }
+
+    @Override
+    public T get() {
+        return value;
+    }
+
+    @Override
+    public T getValue() {
+        return value;
+    }
+
+    @Override
+    public void addListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void addListener(ChangeListener<? super T> observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(ChangeListener<? super T> observer) {
+        // no-op
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/SelectBinding.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.Observable;
+import javafx.beans.WeakInvalidationListener;
+import javafx.beans.binding.Binding;
+import javafx.beans.binding.BooleanBinding;
+import javafx.beans.binding.DoubleBinding;
+import javafx.beans.binding.FloatBinding;
+import javafx.beans.binding.IntegerBinding;
+import javafx.beans.binding.LongBinding;
+import javafx.beans.binding.ObjectBinding;
+import javafx.beans.binding.StringBinding;
+import javafx.beans.value.ObservableBooleanValue;
+import javafx.beans.value.ObservableNumberValue;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+
+import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection;
+import sun.util.logging.PlatformLogger;
+import com.sun.javafx.property.PropertyReference;
+import java.util.Arrays;
+import javafx.beans.property.adapter.JavaBeanObjectPropertyBuilder;
+import javafx.beans.property.adapter.ReadOnlyJavaBeanObjectPropertyBuilder;
+
+/**
+ * A binding used to get a member, such as <code>a.b.c</code>. The value of the
+ * binding will be "c", or null if c could not be reached (due to "b" not having
+ * a "c" property, or "b" being null). "a" must be passed to the constructor of
+ * the SelectBinding and may be any dependency. All subsequent links are simply
+ * PropertyReferences.
+ * <p>
+ * With a SelectBinding, "a" must always exist. Usually "a" will refer to
+ * "this", or some concrete object. "b"* will be some intermediate step in the
+ * select binding.
+ */
+public class SelectBinding {
+
+    private SelectBinding() {}
+    
+    public static class AsObject<T> extends ObjectBinding<T> {
+        
+        private final SelectBindingHelper helper;
+
+        public AsObject(ObservableValue<?> root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+
+        public AsObject(Object root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+        
+        @Override
+        public void dispose() {
+            helper.unregisterListener();
+        }
+
+        @Override
+        protected void onInvalidating() {
+            helper.unregisterListener();
+        }
+        
+        @SuppressWarnings("unchecked")
+        @Override
+        protected T computeValue() {
+            final ObservableValue<?> observable = helper.getObservableValue();
+            if (observable == null) {
+                return null;
+            }
+            try {
+                return (T)helper.getObservableValue().getValue();
+            } catch (ClassCastException ex) {
+                Logging.getLogger().warning("Value of select-binding has wrong type, returning null.", ex);
+            }
+            return null;
+        }
+
+
+        @Override
+        @ReturnsUnmodifiableCollection
+        public ObservableList<ObservableValue<?>> getDependencies() {
+            return helper.getDependencies();
+        }
+
+    }
+    
+    public static class AsBoolean extends BooleanBinding {
+        
+        private static final boolean DEFAULT_VALUE = false;
+        
+        private final SelectBindingHelper helper;
+
+        public AsBoolean(ObservableValue<?> root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+
+        public AsBoolean(Object root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+        
+        @Override
+        public void dispose() {
+            helper.unregisterListener();
+        }
+
+        @Override
+        protected void onInvalidating() {
+            helper.unregisterListener();
+        }
+        
+        @Override
+        protected boolean computeValue() {
+            final ObservableValue<?> observable = helper.getObservableValue();
+            if (observable == null) {
+                return DEFAULT_VALUE;
+            }
+            if (observable instanceof ObservableBooleanValue) {
+                return ((ObservableBooleanValue)observable).get();
+            }
+            try {
+                return (Boolean)observable.getValue();
+            } catch (NullPointerException ex) {
+                Logging.getLogger().info("Value of select binding is null, returning default value", ex);
+            } catch (ClassCastException ex) {
+                Logging.getLogger().warning("Value of select-binding has wrong type, returning default value.", ex);
+            }
+            return DEFAULT_VALUE;
+        }
+
+        @Override
+        @ReturnsUnmodifiableCollection
+        public ObservableList<ObservableValue<?>> getDependencies() {
+            return helper.getDependencies();
+        }
+
+    }
+    
+    public static class AsDouble extends DoubleBinding {
+        
+        private static final double DEFAULT_VALUE = 0.0;
+        
+        private final SelectBindingHelper helper;
+
+        public AsDouble(ObservableValue<?> root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+
+        public AsDouble(Object root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+        
+        @Override
+        public void dispose() {
+            helper.unregisterListener();
+        }
+
+        @Override
+        protected void onInvalidating() {
+            helper.unregisterListener();
+        }
+        
+        @Override
+        protected double computeValue() {
+            final ObservableValue<?> observable = helper.getObservableValue();
+            if (observable == null) {
+                return DEFAULT_VALUE;
+            }
+            if (observable instanceof ObservableNumberValue) {
+                return ((ObservableNumberValue)observable).doubleValue();
+            }
+            try {
+                return ((Number)observable.getValue()).doubleValue();
+            } catch (NullPointerException ex) {
+                Logging.getLogger().info("Value of select binding is null, returning default value", ex);
+            } catch (ClassCastException ex) {
+                Logging.getLogger().warning("Exception while evaluating select-binding", ex);
+            }
+            return DEFAULT_VALUE;
+        }
+
+        @Override
+        @ReturnsUnmodifiableCollection
+        public ObservableList<ObservableValue<?>> getDependencies() {
+            return helper.getDependencies();
+        }
+
+    }
+    
+    public static class AsFloat extends FloatBinding {
+        
+        private static final float DEFAULT_VALUE = 0.0f;
+        
+        private final SelectBindingHelper helper;
+
+        public AsFloat(ObservableValue<?> root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+
+        public AsFloat(Object root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+        
+        @Override
+        public void dispose() {
+            helper.unregisterListener();
+        }
+
+        @Override
+        protected void onInvalidating() {
+            helper.unregisterListener();
+        }
+        
+        @Override
+        protected float computeValue() {
+            final ObservableValue<?> observable = helper.getObservableValue();
+            if (observable == null) {
+                return DEFAULT_VALUE;
+            }
+            if (observable instanceof ObservableNumberValue) {
+                return ((ObservableNumberValue)observable).floatValue();
+            }
+            try {
+                return ((Number)observable.getValue()).floatValue();
+            } catch (NullPointerException ex) {
+                Logging.getLogger().info("Value of select binding is null, returning default value", ex);
+            } catch (ClassCastException ex) {
+                Logging.getLogger().warning("Exception while evaluating select-binding", ex);
+            }
+            return DEFAULT_VALUE;
+        }
+
+        @Override
+        @ReturnsUnmodifiableCollection
+        public ObservableList<ObservableValue<?>> getDependencies() {
+            return helper.getDependencies();
+        }
+
+    }
+    
+    public static class AsInteger extends IntegerBinding {
+        
+        private static final int DEFAULT_VALUE = 0;
+        
+        private final SelectBindingHelper helper;
+
+        public AsInteger(ObservableValue<?> root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+
+        public AsInteger(Object root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+        
+        @Override
+        public void dispose() {
+            helper.unregisterListener();
+        }
+
+        @Override
+        protected void onInvalidating() {
+            helper.unregisterListener();
+        }
+        
+        @Override
+        protected int computeValue() {
+            final ObservableValue<?> observable = helper.getObservableValue();
+            if (observable == null) {
+                return DEFAULT_VALUE;
+            }
+            if (observable instanceof ObservableNumberValue) {
+                return ((ObservableNumberValue)observable).intValue();
+            }
+            try {
+                return ((Number)observable.getValue()).intValue();
+            } catch (NullPointerException ex) {
+                Logging.getLogger().info("Value of select binding is null, returning default value", ex);
+            } catch (ClassCastException ex) {
+                Logging.getLogger().warning("Exception while evaluating select-binding", ex);
+            }
+            return DEFAULT_VALUE;
+        }
+
+        @Override
+        @ReturnsUnmodifiableCollection
+        public ObservableList<ObservableValue<?>> getDependencies() {
+            return helper.getDependencies();
+        }
+
+    }
+    
+    public static class AsLong extends LongBinding {
+        
+        private static final long DEFAULT_VALUE = 0L;
+        
+        private final SelectBindingHelper helper;
+
+        public AsLong(ObservableValue<?> root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+
+        public AsLong(Object root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+        
+        @Override
+        public void dispose() {
+            helper.unregisterListener();
+        }
+
+        @Override
+        protected void onInvalidating() {
+            helper.unregisterListener();
+        }
+        
+        @Override
+        protected long computeValue() {
+            final ObservableValue<?> observable = helper.getObservableValue();
+            if (observable == null) {
+                return DEFAULT_VALUE;
+            }
+            if (observable instanceof ObservableNumberValue) {
+                return ((ObservableNumberValue)observable).longValue();
+            }
+            try {
+                return ((Number)observable.getValue()).longValue();
+            } catch (NullPointerException ex) {
+                Logging.getLogger().info("Value of select binding is null, returning default value", ex);
+            } catch (ClassCastException ex) {
+                Logging.getLogger().warning("Exception while evaluating select-binding", ex);
+            }
+            return DEFAULT_VALUE;
+        }
+
+        @Override
+        @ReturnsUnmodifiableCollection
+        public ObservableList<ObservableValue<?>> getDependencies() {
+            return helper.getDependencies();
+        }
+
+    }
+    
+    public static class AsString extends StringBinding {
+
+        private static final String DEFAULT_VALUE = null;
+
+        private final SelectBindingHelper helper;
+
+        public AsString(ObservableValue<?> root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+
+        public AsString(Object root, String... steps) {
+            helper = new SelectBindingHelper(this, root, steps);
+        }
+        
+        @Override
+        public void dispose() {
+            helper.unregisterListener();
+        }
+
+        @Override
+        protected void onInvalidating() {
+            helper.unregisterListener();
+        }
+        
+        @Override
+        protected String computeValue() {
+            final ObservableValue<?> observable = helper.getObservableValue();
+            if (observable == null) {
+                return DEFAULT_VALUE;
+            }
+            try {
+                return observable.getValue().toString();
+            } catch (RuntimeException ex) {
+                Logging.getLogger().warning("Exception while evaluating select-binding", ex);
+                // return default
+                return DEFAULT_VALUE;
+            }
+        }
+
+        @Override
+        @ReturnsUnmodifiableCollection
+        public ObservableList<ObservableValue<?>> getDependencies() {
+            return helper.getDependencies();
+        }
+
+    }
+
+    private static class SelectBindingHelper implements InvalidationListener {
+
+        private final Binding<?> binding;
+        private final String[] propertyNames;
+        private final ObservableValue<?>[] properties;
+        private final PropertyReference<?>[] propRefs;
+        private final WeakInvalidationListener observer;
+
+        private ObservableList<ObservableValue<?>> dependencies;
+
+        private SelectBindingHelper(Binding<?> binding, ObservableValue<?> firstProperty, String... steps) {
+            if (firstProperty == null) {
+                throw new NullPointerException("Must specify the root");
+            }
+            if (steps == null) {
+                steps = new String[0];
+            }
+
+            this.binding = binding;
+
+            final int n = steps.length;
+            for (int i = 0; i < n; i++) {
+                if (steps[i] == null) {
+                    throw new NullPointerException("all steps must be specified");
+                }
+            }
+
+            observer = new WeakInvalidationListener(this);
+            propertyNames = new String[n];
+            System.arraycopy(steps, 0, propertyNames, 0, n);
+            propRefs = new PropertyReference<?>[n];
+            properties = new ObservableValue<?>[n + 1];
+            properties[0] = firstProperty;
+            properties[0].addListener(observer);
+        }
+
+        private static ObservableValue<?> checkAndCreateFirstStep(Object root, String[] steps) {
+            if (root == null || steps == null || steps[0] == null) {
+                throw new NullPointerException("Must specify the root and the first property");
+            }
+            try {
+                return ReadOnlyJavaBeanObjectPropertyBuilder.create().bean(root).name(steps[0]).build();
+            } catch (NoSuchMethodException ex) {
+                throw new IllegalArgumentException("The first property '" + steps[0] + "' doesn't exist");
+            }
+        }
+
+        private SelectBindingHelper(Binding<?> binding, Object root, String... steps) {
+            this(binding, checkAndCreateFirstStep(root, steps), Arrays.copyOfRange(steps, 1, steps.length));
+        }
+
+        @Override
+        public void invalidated(Observable observable) {
+            binding.invalidate();
+        }
+
+        public ObservableValue<?> getObservableValue() {
+            // Step through each of the steps, and at each step add a listener as
+            // appropriate, accumulating the result.
+            final int n = properties.length;
+            for (int i = 0; i < n - 1; i++) {
+                final Object obj = properties[i].getValue();
+                try {
+                    if ((propRefs[i] == null)
+                            || (!obj.getClass().equals(
+                            propRefs[i].getContainingClass()))) {
+                        propRefs[i] = new PropertyReference<Object>(obj.getClass(),
+                                propertyNames[i]);
+                    }
+                    if (propRefs[i].hasProperty()) {
+                        properties[i + 1] = propRefs[i].getProperty(obj);
+                    } else {
+                        properties[i + 1] = ReadOnlyJavaBeanObjectPropertyBuilder.create().bean(obj).name(propRefs[i].getName()).build();
+                    }
+                } catch (IllegalStateException ex) {
+                    Logging.getLogger().warning("Exception while evaluating select-binding", ex);
+                    // return default
+                    updateDependencies();
+                    return null;
+                } catch (NoSuchMethodException ex) {
+                    Logging.getLogger().warning("Exception while evaluating select-binding", ex);
+                    // return default
+                    updateDependencies();
+                    return null;
+                } catch (RuntimeException ex) {
+                    final PlatformLogger logger = Logging.getLogger();
+                    if (logger.isLoggable(PlatformLogger.WARNING)) {
+                        if (ex instanceof  IllegalStateException) {
+                            logger.warning("Property '" + propertyNames[i] + "' does not exist in " + obj.getClass(), ex);
+                        } else if (ex instanceof NullPointerException) {
+                            logger.warning("Property '" + propertyNames[i] + "' in " + properties[i] + " is null", ex);
+                        } else {
+                            Logging.getLogger().warning("Exception while evaluating select-binding", ex);
+                        }
+                    }
+                    // return default
+                    updateDependencies();
+                    return null;
+                }
+                properties[i + 1].addListener(observer);
+            }
+            updateDependencies();
+            final ObservableValue<?> result = properties[n-1];
+            if (result == null) {
+                Logging.getLogger().warning("Property '" + propertyNames[n-1] + "' in " + properties[n-1] + " is null", new NullPointerException());
+            }
+            return result;
+        }
+
+        private void unregisterListener() {
+            final int n = properties.length;
+            for (int i = 1; i < n; i++) {
+                if (properties[i] == null) {
+                    break;
+                }
+                properties[i].removeListener(observer);
+                properties[i] = null;
+            }
+            updateDependencies();
+        }
+
+        private void updateDependencies() {
+            if (dependencies != null) {
+                dependencies.clear();
+                final int n = properties.length;
+                for (int i = 0; i < n; i++) {
+                    if (properties[i] == null) {
+                        break;
+                    }
+                    dependencies.add(properties[i]);
+                }
+            }
+        }
+
+        @ReturnsUnmodifiableCollection
+        public ObservableList<ObservableValue<?>> getDependencies() {
+            if (dependencies == null) {
+                dependencies = FXCollections.observableArrayList();
+                updateDependencies();
+            }
+
+            return FXCollections.unmodifiableObservableList(dependencies);
+        }
+
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/SetExpressionHelper.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableSetValue;
+import javafx.collections.ObservableSet;
+import javafx.collections.SetChangeListener;
+
+import java.util.Arrays;
+
+/**
+*/
+public abstract class SetExpressionHelper<E> extends ExpressionHelperBase {
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Static methods
+
+    public static <E> SetExpressionHelper<E> addListener(SetExpressionHelper<E> helper, ObservableSetValue<E> observable, InvalidationListener listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        observable.getValue(); // validate observable
+        return (helper == null)? new SingleInvalidation<E>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <E> SetExpressionHelper<E> removeListener(SetExpressionHelper<E> helper, InvalidationListener listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <E> SetExpressionHelper<E> addListener(SetExpressionHelper<E> helper, ObservableSetValue<E> observable, ChangeListener<? super ObservableSet<E>> listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? new SingleChange<E>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <E> SetExpressionHelper<E> removeListener(SetExpressionHelper<E> helper, ChangeListener<? super ObservableSet<E>> listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <E> SetExpressionHelper<E> addListener(SetExpressionHelper<E> helper, ObservableSetValue<E> observable, SetChangeListener<? super E> listener) {
+        if ((observable == null) || (listener == null)) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? new SingleSetChange<E>(observable, listener) : helper.addListener(listener);
+    }
+
+    public static <E> SetExpressionHelper<E> removeListener(SetExpressionHelper<E> helper, SetChangeListener<? super E> listener) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        return (helper == null)? null : helper.removeListener(listener);
+    }
+
+    public static <E> void fireValueChangedEvent(SetExpressionHelper<E> helper) {
+        if (helper != null) {
+            helper.fireValueChangedEvent();
+        }
+    }
+
+    public static <E> void fireValueChangedEvent(SetExpressionHelper<E> helper, SetChangeListener.Change<? extends E> change) {
+        if (helper != null) {
+            helper.fireValueChangedEvent(change);
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Common implementations
+
+    protected final ObservableSetValue<E> observable;
+
+    protected SetExpressionHelper(ObservableSetValue<E> observable) {
+        this.observable = observable;
+    }
+
+    protected abstract SetExpressionHelper<E> addListener(InvalidationListener listener);
+    protected abstract SetExpressionHelper<E> removeListener(InvalidationListener listener);
+
+    protected abstract SetExpressionHelper<E> addListener(ChangeListener<? super ObservableSet<E>> listener);
+    protected abstract SetExpressionHelper<E> removeListener(ChangeListener<? super ObservableSet<E>> listener);
+
+    protected abstract SetExpressionHelper<E> addListener(SetChangeListener<? super E> listener);
+    protected abstract SetExpressionHelper<E> removeListener(SetChangeListener<? super E> listener);
+
+    protected abstract void fireValueChangedEvent();
+    protected abstract void fireValueChangedEvent(SetChangeListener.Change<? extends E> change);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Implementations
+
+    private static class SingleInvalidation<E> extends SetExpressionHelper<E> {
+
+        private final InvalidationListener listener;
+
+        private SingleInvalidation(ObservableSetValue<E> observable, InvalidationListener listener) {
+            super(observable);
+            this.listener = listener;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(InvalidationListener listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(InvalidationListener listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(ChangeListener<? super ObservableSet<E>> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(ChangeListener<? super ObservableSet<E>> listener) {
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(SetChangeListener<? super E> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(SetChangeListener<? super E> listener) {
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            listener.invalidated(observable);
+        }
+
+        @Override
+        protected void fireValueChangedEvent(SetChangeListener.Change<? extends E> change) {
+            listener.invalidated(observable);
+        }
+    }
+
+    private static class SingleChange<E> extends SetExpressionHelper<E> {
+
+        private final ChangeListener<? super ObservableSet<E>> listener;
+        private ObservableSet<E> currentValue;
+
+        private SingleChange(ObservableSetValue<E> observable, ChangeListener<? super ObservableSet<E>> listener) {
+            super(observable);
+            this.listener = listener;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(InvalidationListener listener) {
+            return new Generic<E>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(InvalidationListener listener) {
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(ChangeListener<? super ObservableSet<E>> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(ChangeListener<? super ObservableSet<E>> listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(SetChangeListener<? super E> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(SetChangeListener<? super E> listener) {
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            final ObservableSet<E> oldValue = currentValue;
+            currentValue = observable.getValue();
+            if (currentValue != oldValue) {
+                listener.changed(observable, oldValue, currentValue);
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(SetChangeListener.Change<? extends E> change) {
+            listener.changed(observable, currentValue, currentValue);
+        }
+    }
+
+    private static class SingleSetChange<E> extends SetExpressionHelper<E> {
+
+        private final SetChangeListener<? super E> listener;
+        private ObservableSet<E> currentValue;
+
+        private SingleSetChange(ObservableSetValue<E> observable, SetChangeListener<? super E> listener) {
+            super(observable);
+            this.listener = listener;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(InvalidationListener listener) {
+            return new Generic<E>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(InvalidationListener listener) {
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(ChangeListener<? super ObservableSet<E>> listener) {
+            return new Generic<E>(observable, listener, this.listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(ChangeListener<? super ObservableSet<E>> listener) {
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(SetChangeListener<? super E> listener) {
+            return new Generic<E>(observable, this.listener, listener);
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(SetChangeListener<? super E> listener) {
+            return (listener.equals(this.listener))? null : this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            final ObservableSet<E> oldValue = currentValue;
+            currentValue = observable.getValue();
+            if (currentValue != oldValue) {
+                final SimpleChange<E> change = new SimpleChange<E>(observable);
+                if (currentValue == null) {
+                    for (final E element : oldValue) {
+                        listener.onChanged(change.setRemoved(element));
+                    }
+                } else if (oldValue == null) {
+                    for (final E element : currentValue) {
+                        listener.onChanged(change.setAdded(element));
+                    }
+                } else {
+                    for (final E element : oldValue) {
+                        if (!currentValue.contains(element)) {
+                            listener.onChanged(change.setRemoved(element));
+                        }
+                    }
+                    for (final E element : currentValue) {
+                        if (!oldValue.contains(element)) {
+                            listener.onChanged(change.setAdded(element));
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(final SetChangeListener.Change<? extends E> change) {
+            listener.onChanged(new SimpleChange<E>(observable, change));
+        }
+    }
+
+    private static class Generic<E> extends SetExpressionHelper<E> {
+
+        private InvalidationListener[] invalidationListeners;
+        private ChangeListener<? super ObservableSet<E>>[] changeListeners;
+        private SetChangeListener<? super E>[] setChangeListeners;
+        private int invalidationSize;
+        private int changeSize;
+        private int setChangeSize;
+        private boolean locked;
+        private ObservableSet<E> currentValue;
+
+        private Generic(ObservableSetValue<E> observable, InvalidationListener listener0, InvalidationListener listener1) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {listener0, listener1};
+            this.invalidationSize = 2;
+        }
+
+        private Generic(ObservableSetValue<E> observable, ChangeListener<? super ObservableSet<E>> listener0, ChangeListener<? super ObservableSet<E>> listener1) {
+            super(observable);
+            this.changeListeners = new ChangeListener[] {listener0, listener1};
+            this.changeSize = 2;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableSetValue<E> observable, SetChangeListener<? super E> listener0, SetChangeListener<? super E> listener1) {
+            super(observable);
+            this.setChangeListeners = new SetChangeListener[] {listener0, listener1};
+            this.setChangeSize = 2;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableSetValue<E> observable, InvalidationListener invalidationListener, ChangeListener<? super ObservableSet<E>> changeListener) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {invalidationListener};
+            this.invalidationSize = 1;
+            this.changeListeners = new ChangeListener[] {changeListener};
+            this.changeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableSetValue<E> observable, InvalidationListener invalidationListener, SetChangeListener<? super E> listChangeListener) {
+            super(observable);
+            this.invalidationListeners = new InvalidationListener[] {invalidationListener};
+            this.invalidationSize = 1;
+            this.setChangeListeners = new SetChangeListener[] {listChangeListener};
+            this.setChangeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        private Generic(ObservableSetValue<E> observable, ChangeListener<? super ObservableSet<E>> changeListener, SetChangeListener<? super E> listChangeListener) {
+            super(observable);
+            this.changeListeners = new ChangeListener[] {changeListener};
+            this.changeSize = 1;
+            this.setChangeListeners = new SetChangeListener[] {listChangeListener};
+            this.setChangeSize = 1;
+            this.currentValue = observable.getValue();
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(InvalidationListener listener) {
+            if (invalidationListeners == null) {
+                invalidationListeners = new InvalidationListener[] {listener};
+                invalidationSize = 1;
+            } else {
+                final int oldCapacity = invalidationListeners.length;
+                if (locked) {
+                    final int newCapacity = (invalidationSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
+                } else if (invalidationSize == oldCapacity) {
+                    invalidationSize = trim(invalidationSize, invalidationListeners);
+                    if (invalidationSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
+                    }
+                }
+                invalidationListeners[invalidationSize++] = listener;
+            }
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(InvalidationListener listener) {
+            if (invalidationListeners != null) {
+                for (int index = 0; index < invalidationSize; index++) {
+                    if (listener.equals(invalidationListeners[index])) {
+                        if (invalidationSize == 1) {
+                            if ((changeSize == 1) && (setChangeSize == 0)) {
+                                return new SingleChange<E>(observable, changeListeners[0]);
+                            } else if ((changeSize == 0) && (setChangeSize == 1)) {
+                                return new SingleSetChange<E>(observable, setChangeListeners[0]);
+                            }
+                            invalidationListeners = null;
+                            invalidationSize = 0;
+                        } else {
+                            final int numMoved = invalidationSize - index - 1;
+                            final InvalidationListener[] oldListeners = invalidationListeners;
+                            if (locked) {
+                                invalidationListeners = new InvalidationListener[invalidationListeners.length];
+                                System.arraycopy(oldListeners, 0, invalidationListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, invalidationListeners, index, numMoved);
+                            }
+                            if (!locked) {
+                                invalidationListeners[--invalidationSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(ChangeListener<? super ObservableSet<E>> listener) {
+            if (changeListeners == null) {
+                changeListeners = new ChangeListener[] {listener};
+                changeSize = 1;
+            } else {
+                final int oldCapacity = changeListeners.length;
+                if (locked) {
+                    final int newCapacity = (changeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    changeListeners = Arrays.copyOf(changeListeners, newCapacity);
+                } else if (changeSize == oldCapacity) {
+                    changeSize = trim(changeSize, changeListeners);
+                    if (changeSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        changeListeners = Arrays.copyOf(changeListeners, newCapacity);
+                    }
+                }
+                changeListeners[changeSize++] = listener;
+            }
+            if (changeSize == 1) {
+                currentValue = observable.getValue();
+            }
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(ChangeListener<? super ObservableSet<E>> listener) {
+            if (changeListeners != null) {
+                for (int index = 0; index < changeSize; index++) {
+                    if (listener.equals(changeListeners[index])) {
+                        if (changeSize == 1) {
+                            if ((invalidationSize == 1) && (setChangeSize == 0)) {
+                                return new SingleInvalidation<E>(observable, invalidationListeners[0]);
+                            } else if ((invalidationSize == 0) && (setChangeSize == 1)) {
+                                return new SingleSetChange<E>(observable, setChangeListeners[0]);
+                            }
+                            changeListeners = null;
+                            changeSize = 0;
+                        } else {
+                            final int numMoved = changeSize - index - 1;
+                            final ChangeListener<? super ObservableSet<E>>[] oldListeners = changeListeners;
+                            if (locked) {
+                                changeListeners = new ChangeListener[changeListeners.length];
+                                System.arraycopy(oldListeners, 0, changeListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, changeListeners, index, numMoved);
+                            }
+                            changeSize--;
+                            if (!locked) {
+                                changeListeners[changeSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> addListener(SetChangeListener<? super E> listener) {
+            if (setChangeListeners == null) {
+                setChangeListeners = new SetChangeListener[] {listener};
+                setChangeSize = 1;
+            } else {
+                final int oldCapacity = setChangeListeners.length;
+                if (locked) {
+                    final int newCapacity = (setChangeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
+                    setChangeListeners = Arrays.copyOf(setChangeListeners, newCapacity);
+                } else if (setChangeSize == oldCapacity) {
+                    setChangeSize = trim(setChangeSize, setChangeListeners);
+                    if (setChangeSize == oldCapacity) {
+                        final int newCapacity = (oldCapacity * 3)/2 + 1;
+                        setChangeListeners = Arrays.copyOf(setChangeListeners, newCapacity);
+                    }
+                }
+                setChangeListeners[setChangeSize++] = listener;
+            }
+            if (setChangeSize == 1) {
+                currentValue = observable.getValue();
+            }
+            return this;
+        }
+
+        @Override
+        protected SetExpressionHelper<E> removeListener(SetChangeListener<? super E> listener) {
+            if (setChangeListeners != null) {
+                for (int index = 0; index < setChangeSize; index++) {
+                    if (listener.equals(setChangeListeners[index])) {
+                        if (setChangeSize == 1) {
+                            if ((invalidationSize == 1) && (changeSize == 0)) {
+                                return new SingleInvalidation<E>(observable, invalidationListeners[0]);
+                            } else if ((invalidationSize == 0) && (changeSize == 1)) {
+                                return new SingleChange<E>(observable, changeListeners[0]);
+                            }
+                            setChangeListeners = null;
+                            setChangeSize = 0;
+                        } else {
+                            final int numMoved = setChangeSize - index - 1;
+                            final SetChangeListener<? super E>[] oldListeners = setChangeListeners;
+                            if (locked) {
+                                setChangeListeners = new SetChangeListener[setChangeListeners.length];
+                                System.arraycopy(oldListeners, 0, setChangeListeners, 0, index+1);
+                            }
+                            if (numMoved > 0) {
+                                System.arraycopy(oldListeners, index+1, setChangeListeners, index, numMoved);
+                            }
+                            setChangeSize--;
+                            if (!locked) {
+                                setChangeListeners[setChangeSize] = null; // Let gc do its work
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        protected void fireValueChangedEvent() {
+            if ((changeSize == 0) && (setChangeSize == 0)) {
+                notifyListeners(currentValue, null);
+            } else {
+                final ObservableSet<E> oldValue = currentValue;
+                currentValue = observable.getValue();
+                notifyListeners(oldValue, null);
+            }
+        }
+
+        @Override
+        protected void fireValueChangedEvent(final SetChangeListener.Change<? extends E> change) {
+            final SimpleChange<E> mappedChange = (setChangeSize == 0)? null : new SimpleChange<E>(observable, change);
+            notifyListeners(currentValue, mappedChange);
+        }
+
+        private void notifyListeners(ObservableSet<E> oldValue, SimpleChange<E> change) {
+            final InvalidationListener[] curInvalidationList = invalidationListeners;
+            final int curInvalidationSize = invalidationSize;
+            final ChangeListener<? super ObservableSet<E>>[] curChangeList = changeListeners;
+            final int curChangeSize = changeSize;
+            final SetChangeListener<? super E>[] curListChangeList = setChangeListeners;
+            final int curListChangeSize = setChangeSize;
+            try {
+                locked = true;
+                for (int i = 0; i < curInvalidationSize; i++) {
+                    curInvalidationList[i].invalidated(observable);
+                }
+                if ((currentValue != oldValue) || (change != null)) {
+                    for (int i = 0; i < curChangeSize; i++) {
+                        curChangeList[i].changed(observable, oldValue, currentValue);
+                    }
+                    if (curListChangeSize > 0) {
+                        if (change != null) {
+                            for (int i = 0; i < curListChangeSize; i++) {
+                                curListChangeList[i].onChanged(change);
+                            }
+                        } else {
+                            change = new SimpleChange<E>(observable);
+                            if (currentValue == null) {
+                                for (final E element : oldValue) {
+                                    change.setRemoved(element);
+                                    for (int i = 0; i < curListChangeSize; i++) {
+                                        curListChangeList[i].onChanged(change);
+                                    }
+                                }
+                            } else if (oldValue == null) {
+                                for (final E element : currentValue) {
+                                    change.setAdded(element);
+                                    for (int i = 0; i < curListChangeSize; i++) {
+                                        curListChangeList[i].onChanged(change);
+                                    }
+                                }
+                            } else {
+                                for (final E element : oldValue) {
+                                    if (!currentValue.contains(element)) {
+                                        change.setRemoved(element);
+                                        for (int i = 0; i < curListChangeSize; i++) {
+                                            curListChangeList[i].onChanged(change);
+                                        }
+                                    }
+                                }
+                                for (final E element : currentValue) {
+                                    if (!oldValue.contains(element)) {
+                                        change.setAdded(element);
+                                        for (int i = 0; i < curListChangeSize; i++) {
+                                            curListChangeList[i].onChanged(change);
+                                        }
+                                    }
+                                }
+                            }
+
+                        }
+                    }
+                }
+            } finally {
+                locked = false;
+            }
+        }
+
+    }
+
+    public static class SimpleChange<E> extends SetChangeListener.Change<E> {
+
+        private E old;
+        private E added;
+
+        public SimpleChange(ObservableSet<E> set) {
+            super(set);
+        }
+
+        public SimpleChange(ObservableSet<E> set, SetChangeListener.Change<? extends E> source) {
+            super(set);
+            old = source.getElementRemoved();
+            added = source.getElementAdded();
+        }
+
+        public SimpleChange<E> setRemoved(E old) {
+            this.old = old;
+            this.added = null;
+            return this;
+        }
+
+        public SimpleChange<E> setAdded(E added) {
+            this.old = null;
+            this.added = added;
+            return this;
+        }
+
+        @Override
+        public boolean wasAdded() {
+            return added != null;
+        }
+
+        @Override
+        public boolean wasRemoved() {
+            return old != null;
+        }
+
+        @Override
+        public E getElementAdded() {
+            return added;
+        }
+
+        @Override
+        public E getElementRemoved() {
+            return old;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/StringConstant.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.binding.StringExpression;
+import javafx.beans.value.ChangeListener;
+
+public class StringConstant extends StringExpression {
+
+    private final String value;
+
+    private StringConstant(String value) {
+        this.value = value;
+    }
+
+    public static StringConstant valueOf(String value) {
+        return new StringConstant(value);
+    }
+
+    @Override
+    public String get() {
+        return value;
+    }
+
+    @Override
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public void addListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void addListener(ChangeListener<? super String> observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(InvalidationListener observer) {
+        // no-op
+    }
+
+    @Override
+    public void removeListener(ChangeListener<? super String> observer) {
+        // no-op
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/binding/StringFormatter.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.binding;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import javafx.beans.binding.StringBinding;
+import javafx.beans.binding.StringExpression;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+
+import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection;
+
+public abstract class StringFormatter extends StringBinding {
+
+    private static Object extractValue(Object obj) {
+        return obj instanceof ObservableValue ? ((ObservableValue<?>)obj).getValue() : obj;
+    }
+
+    private static Object[] extractValues(Object[] objs) {
+        final int n = objs.length;
+        final Object[] values = new Object[n];
+        for (int i = 0; i < n; i++) {
+            values[i] = extractValue(objs[i]);
+        }
+        return values;
+    }
+
+    private static ObservableValue<?>[] extractDependencies(Object... args) {
+        final List<ObservableValue<?>> dependencies = new ArrayList<ObservableValue<?>>();
+        for (final Object obj : args) {
+            if (obj instanceof ObservableValue) {
+                dependencies.add((ObservableValue<?>) obj);
+            }
+        }
+        return dependencies.toArray(new ObservableValue[dependencies.size()]);
+    }
+
+    public static StringExpression convert(final ObservableValue<?> observableValue) {
+        if (observableValue == null) {
+            throw new NullPointerException("ObservableValue must be specified");
+        }
+        if (observableValue instanceof StringExpression) {
+            return (StringExpression) observableValue;
+        } else {
+            return new StringBinding() {
+                {
+                    super.bind(observableValue);
+                }
+
+                @Override
+                public void dispose() {
+                    super.unbind(observableValue);
+                }
+
+                @Override
+                protected String computeValue() {
+                    final Object value = observableValue.getValue();
+                    return (value == null)? "null" : value.toString();
+                }
+
+                @Override
+                @ReturnsUnmodifiableCollection
+                public ObservableList<ObservableValue<?>> getDependencies() {
+                    return FXCollections.<ObservableValue<?>> singletonObservableList(observableValue);
+                }
+            };
+        }
+    }
+
+    public static StringExpression concat(final Object... args) {
+        if ((args == null) || (args.length == 0)) {
+            return StringConstant.valueOf("");
+        }
+        if (args.length == 1) {
+            final Object cur = args[0];
+            return cur instanceof ObservableValue ? convert((ObservableValue<?>) cur)
+                    : StringConstant.valueOf(cur.toString());
+        }
+        if (extractDependencies(args).length == 0) {
+            final StringBuilder builder = new StringBuilder();
+            for (final Object obj : args) {
+                builder.append(obj);
+            }
+            return StringConstant.valueOf(builder.toString());
+        }
+        return new StringFormatter() {
+            {
+                super.bind(extractDependencies(args));
+            }
+
+            @Override
+            public void dispose() {
+                super.unbind(extractDependencies(args));
+            }
+
+            @Override
+            protected String computeValue() {
+                final StringBuilder builder = new StringBuilder();
+                for (final Object obj : args) {
+                    builder.append(extractValue(obj));
+                }
+                return builder.toString();
+            }
+
+            @Override
+            @ReturnsUnmodifiableCollection
+            public ObservableList<ObservableValue<?>> getDependencies() {
+                return FXCollections.unmodifiableObservableList(FXCollections
+                        .observableArrayList(extractDependencies(args)));
+            }
+        };
+    }
+
+    public static StringExpression format(final Locale locale, final String format, final Object... args) {
+        if (format == null) {
+            throw new NullPointerException("Format cannot be null.");
+        }
+        if (extractDependencies(args).length == 0) {
+            return StringConstant.valueOf(String.format(locale, format, args));
+        }
+        final StringFormatter formatter = new StringFormatter() {
+            {
+                super.bind(extractDependencies(args));
+            }
+
+            @Override
+            public void dispose() {
+                super.unbind(extractDependencies(args));
+            }
+
+            @Override
+            protected String computeValue() {
+                final Object[] values = extractValues(args);
+                return String.format(locale, format, values);
+            }
+
+            @Override
+            @ReturnsUnmodifiableCollection
+            public ObservableList<ObservableValue<?>> getDependencies() {
+                return FXCollections.unmodifiableObservableList(FXCollections
+                        .observableArrayList(extractDependencies(args)));
+            }
+        };
+        // Force calculation to check format
+        formatter.get();
+        return formatter;
+    }
+
+    public static StringExpression format(final String format, final Object... args) {
+        if (format == null) {
+            throw new NullPointerException("Format cannot be null.");
+        }
+        if (extractDependencies(args).length == 0) {
+            return StringConstant.valueOf(String.format(format, args));
+        }
+        final StringFormatter formatter = new StringFormatter() {
+            {
+                super.bind(extractDependencies(args));
+            }
+
+            @Override
+            public void dispose() {
+                super.unbind(extractDependencies(args));
+            }
+
+            @Override
+            protected String computeValue() {
+                final Object[] values = extractValues(args);
+                return String.format(format, values);
+            }
+
+            @Override
+            @ReturnsUnmodifiableCollection
+            public ObservableList<ObservableValue<?>> getDependencies() {
+                return FXCollections.unmodifiableObservableList(FXCollections
+                        .observableArrayList(extractDependencies(args)));
+            }
+        };
+        // Force calculation to check format
+        formatter.get();
+        return formatter;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/collections/BaseModifiableObservableList.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.collections;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ *
+ * @author martin
+ */
+public abstract class BaseModifiableObservableList<E> extends BaseObservableList<E> {
+
+    @Override
+    public boolean setAll(Collection<? extends E> col) {
+        beginChange();
+        try {
+            clear();
+            addAll(col);
+        } finally {
+            endChange();
+        }
+        return true;
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends E> c) {
+        beginChange();
+        try {
+            boolean res = super.addAll(c);
+            return res;
+        } finally {
+            endChange();
+        }
+    }
+
+    @Override
+    public boolean addAll(int index, Collection<? extends E> c) {
+        beginChange();
+        try {
+            boolean res = super.addAll(index, c);
+            return res;
+        } finally {
+            endChange();
+        }
+    }
+
+    @Override
+    protected void removeRange(int fromIndex, int toIndex) {
+        beginChange();
+        try {
+            super.removeRange(fromIndex, toIndex);
+        } finally {
+            endChange();
+        }
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        beginChange();
+        try {
+            boolean res = super.removeAll(c);
+            return res;
+        } finally {
+            endChange();
+        }
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        beginChange();
+        try {
+            boolean res = super.retainAll(c);
+            return res;
+        } finally {
+            endChange();
+        }
+    }
+
+    @Override
+    public void add(int index, E element) {
+        doAdd(index, element);
+        beginChange();
+        nextAdd(index, index + 1);
+        ++modCount;
+        endChange();
+    }
+
+    @Override
+    public E set(int index, E element) {
+        E old = doSet(index, element);
+        beginChange();
+        nextSet(index, old);
+        endChange();
+        return old;
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        int i = indexOf(o);
+        if (i != - 1) {
+            remove(i);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public E remove(int index) {
+        E old = doRemove(index);
+        beginChange();
+        nextRemove(index, old);
+        ++modCount;
+        endChange();
+        return old;
+    }
+
+    @Override
+    public List<E> subList(int fromIndex, int toIndex) {
+        return new SubObservableList(super.subList(fromIndex, toIndex));
+    }
+
+    @Override
+    public abstract E get(int index);
+
+    @Override
+    public abstract int size();
+
+    protected abstract void doAdd(int index, E element);
+
+    protected abstract E doSet(int index, E element);
+
+    protected abstract E doRemove(int index);
+
+    private class SubObservableList implements List<E> {
+
+        public SubObservableList(List<E> sublist) {
+            this.sublist = sublist;
+        }
+        private List<E> sublist;
+
+        @Override
+        public int size() {
+            return sublist.size();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return sublist.isEmpty();
+        }
+
+        @Override
+        public boolean contains(Object o) {
+            return sublist.contains(o);
+        }
+
+        @Override
+        public Iterator<E> iterator() {
+            return sublist.iterator();
+        }
+
+        @Override
+        public Object[] toArray() {
+            return sublist.toArray();
+        }
+
+        @Override
+        public <T> T[] toArray(T[] a) {
+            return sublist.toArray(a);
+        }
+
+        @Override
+        public boolean add(E e) {
+            return sublist.add(e);
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            return sublist.remove(o);
+        }
+
+        @Override
+        public boolean containsAll(Collection<?> c) {
+            return sublist.containsAll(c);
+        }
+
+        @Override
+        public boolean addAll(Collection<? extends E> c) {
+            beginChange();
+            try {
+                boolean res = sublist.addAll(c);
+                return res;
+            } finally {
+                endChange();
+            }
+        }
+
+        @Override
+        public boolean addAll(int index, Collection<? extends E> c) {
+            beginChange();
+            try {
+                boolean res = sublist.addAll(index, c);
+                return res;
+            } finally {
+                endChange();
+            }
+        }
+
+        @Override
+        public boolean removeAll(Collection<?> c) {
+            beginChange();
+            try {
+                boolean res = sublist.removeAll(c);
+                return res;
+            } finally {
+                endChange();
+            }
+        }
+
+        @Override
+        public boolean retainAll(Collection<?> c) {
+            beginChange();
+            try {
+                boolean res = sublist.retainAll(c);
+                return res;
+            } finally {
+                endChange();
+            }
+        }
+
+        @Override
+        public void clear() {
+            beginChange();
+            try {
+                sublist.clear();
+            } finally {
+                endChange();
+            }
+        }
+
+        @Override
+        public E get(int index) {
+            return sublist.get(index);
+        }
+
+        @Override
+        public E set(int index, E element) {
+            return sublist.set(index, element);
+        }
+
+        @Override
+        public void add(int index, E element) {
+            sublist.add(index, element);
+        }
+
+        @Override
+        public E remove(int index) {
+            return sublist.remove(index);
+        }
+
+        @Override
+        public int indexOf(Object o) {
+            return sublist.indexOf(o);
+        }
+
+        @Override
+        public int lastIndexOf(Object o) {
+            return sublist.lastIndexOf(o);
+        }
+
+        @Override
+        public ListIterator<E> listIterator() {
+            return sublist.listIterator();
+        }
+
+        @Override
+        public ListIterator<E> listIterator(int index) {
+            return sublist.listIterator(index);
+        }
+
+        @Override
+        public List<E> subList(int fromIndex, int toIndex) {
+            return new SubObservableList(sublist.subList(fromIndex, toIndex));
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return sublist.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return sublist.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return sublist.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/collections/BaseObservableList.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.collections;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import javafx.beans.InvalidationListener;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+
+public abstract class BaseObservableList<E> extends AbstractList<E>  implements ObservableList<E> {
+
+    private ListListenerHelper<E> listenerHelper;
+    private final ListChangeBuilder<E> changeBuilder = new ListChangeBuilder<E>(this);
+
+    protected final void nextUpdate(int pos) {
+        changeBuilder.nextUpdate(pos);
+    }
+
+    protected final void nextSet(int idx, E old) {
+        changeBuilder.nextSet(idx, old);
+    }
+
+    protected final void nextReplace(int from, int to, ArrayList removed) {
+        changeBuilder.nextReplace(from, to, removed);
+    }
+
+    protected final void nextRemove(int idx, List removed) {
+        changeBuilder.nextRemove(idx, removed);
+    }
+
+    protected final void nextRemove(int idx, E removed) {
+        changeBuilder.nextRemove(idx, removed);
+    }
+
+    protected final void nextPermutation(int from, int to, int[] perm) {
+        changeBuilder.nextPermutation(from, to, perm);
+    }
+
+    protected final void nextAdd(int from, int to) {
+        changeBuilder.nextAdd(from, to);
+    }
+
+    protected final void endChange() {
+        changeBuilder.endChange();
+    }
+
+    protected final void beginChange() {
+        changeBuilder.beginChange();
+    }
+
+    @Override
+    public final void addListener(InvalidationListener listener) {
+        listenerHelper = ListListenerHelper.addListener(listenerHelper, listener);
+    }
+
+    @Override
+    public final void removeListener(InvalidationListener listener) {
+        listenerHelper = ListListenerHelper.removeListener(listenerHelper, listener);
+    }
+
+    @Override
+    public final void addListener(ListChangeListener<? super E> listener) {
+        listenerHelper = ListListenerHelper.addListener(listenerHelper, listener);
+    }
+
+    @Override
+    public final void removeListener(ListChangeListener<? super E> listener) {
+        listenerHelper = ListListenerHelper.removeListener(listenerHelper, listener);
+    }
+
+    protected final void callObservers(ListChangeListener.Change<? extends E> change) {
+        ListListenerHelper.fireValueChangedEvent(listenerHelper, change);
+    }
+
+    protected final boolean hasListChangeListener() {
+        return ListListenerHelper.hasListeners(listenerHelper);
+    }
+
+    @Override
+    public boolean addAll(E... elements) {
+        return addAll(Arrays.asList(elements));
+    }
+
+    @Override
+    public boolean setAll(E... elements) {
+        return setAll(Arrays.asList(elements));
+    }
+
+    @Override
+    public boolean setAll(Collection<? extends E> col) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeAll(E... elements) {
+        return removeAll(Arrays.asList(elements));
+    }
+
+    @Override
+    public boolean retainAll(E... elements) {
+        return retainAll(Arrays.asList(elements));
+    }
+
+    @Override
+    public void remove(int from, int to) {
+        removeRange(from, to);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/collections/ChangeHelper.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.collections;
+
+import java.util.Arrays;
+import java.util.List;
+
+class ChangeHelper {
+    static String addRemoveChangeToString(int from, int to, List<?> list, List<?> removed) {
+        StringBuilder b = new StringBuilder();
+                
+        if (removed.isEmpty()) {
+            b.append(list.subList(from, to));
+            b.append(" added at ").append(from);
+        } else {
+            b.append(removed);
+            if (from == to) {
+                b.append(" removed at ").append(from);
+            } else {
+                b.append(" replaced by ");
+                b.append(list.subList(from, to));
+                b.append(" at ").append(from);
+            }
+        }
+        return b.toString();
+    }
+
+    static String permChangeToString(int[] permutation) {
+        return "permutated by " + Arrays.toString(permutation);
+    }
+
+    static String updateChangeToString(int from, int to) {
+        return "updated at range [" + from + ", " + to + ")";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/collections/ElementObservableListDecorator.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.collections;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.RandomAccess;
+import javafx.beans.Observable;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ListChangeListener.Change;
+import javafx.collections.ObservableList;
+import javafx.collections.WeakListChangeListener;
+import javafx.util.Callback;
+
+public final class ElementObservableListDecorator<E> extends BaseObservableList<E> implements ObservableList<E> {
+
+    private final ObservableList<E> decoratedList;
+    private final ListChangeListener<E> listener;
+    private ElementObserver<E> observer;
+    
+
+    public ElementObservableListDecorator(ObservableList<E> decorated,
+            Callback<E, Observable[]> extractor) {
+        this.observer = new ElementObserver<E>(extractor, this);
+        this.decoratedList = decorated;
+        final int sz = decoratedList.size();
+        for (int i = 0; i < sz; ++i) {
+            observer.attachListener(decoratedList.get(i));
+        }
+        listener = new ListChangeListener<E>() {
+
+            @Override
+            public void onChanged(Change<? extends E> c) {
+                while (c.next()) {
+                    if (c.wasAdded() || c.wasRemoved()) {
+                        final int removedSize = c.getRemovedSize();
+                        final List<? extends E> removed = c.getRemoved();
+                        for (int i = 0; i < removedSize; ++i) {
+                            observer.detachListener(removed.get(i));
+                        }
+                        if (decoratedList instanceof RandomAccess) {
+                            final int to = c.getTo();
+                            for (int i = c.getFrom(); i < to; ++i) {
+                                observer.attachListener(decoratedList.get(i));
+                            }
+                        } else {
+                            for (E e : c.getAddedSubList()) {
+                                observer.attachListener(e);
+                            }
+                        }
+                    }
+                }
+                c.reset();
+                callObservers(c);
+            }
+        };
+        this.decoratedList.addListener(new WeakListChangeListener<E> (listener));
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+        return decoratedList.toArray(a);
+    }
+
+    @Override
+    public Object[] toArray() {
+        return decoratedList.toArray();
+    }
+
+    @Override
+    public List<E> subList(int fromIndex, int toIndex) {
+        return decoratedList.subList(fromIndex, toIndex);
+    }
+
+    @Override
+    public int size() {
+        return decoratedList.size();
+    }
+
+    @Override
+    public E set(int index, E element) {
+        return decoratedList.set(index, element);
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        return decoratedList.retainAll(c);
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        return decoratedList.removeAll(c);
+    }
+
+    @Override
+    public E remove(int index) {
+        return decoratedList.remove(index);
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        return decoratedList.remove(o);
+    }
+
+    @Override
+    public ListIterator<E> listIterator(int index) {
+        return decoratedList.listIterator(index);
+    }
+
+    @Override
+    public ListIterator<E> listIterator() {
+        return decoratedList.listIterator();
+    }
+
+    @Override
+    public int lastIndexOf(Object o) {
+        return decoratedList.lastIndexOf(o);
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+        return decoratedList.iterator();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return decoratedList.isEmpty();
+    }
+
+    @Override
+    public int indexOf(Object o) {
+        return decoratedList.indexOf(o);
+    }
+
+    @Override
+    public E get(int index) {
+        return decoratedList.get(index);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        return decoratedList.containsAll(c);
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        return decoratedList.contains(o);
+    }
+
+    @Override
+    public void clear() {
+        decoratedList.clear();
+    }
+
+    @Override
+    public boolean addAll(int index, Collection<? extends E> c) {
+        return decoratedList.addAll(index, c);
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends E> c) {
+        return decoratedList.addAll(c);
+    }
+
+    @Override
+    public void add(int index, E element) {
+        decoratedList.add(index, element);
+    }
+
+    @Override
+    public boolean add(E e) {
+        return decoratedList.add(e);
+    }
+
+    @Override
+    public boolean setAll(Collection<? extends E> col) {
+        return decoratedList.setAll(col);
+    }
+
+    @Override
+    public boolean setAll(E... elements) {
+        return decoratedList.setAll(elements);
+    }
+
+    @Override
+    public boolean retainAll(E... elements) {
+        return decoratedList.retainAll(elements);
+    }
+
+    @Override
+    public boolean removeAll(E... elements) {
+        return decoratedList.removeAll(elements);
+    }
+
+    @Override
+    public void remove(int from, int to) {
+        decoratedList.remove(from, to);
+    }
+
+    @Override
+    public boolean addAll(E... elements) {
+        return decoratedList.addAll(elements);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-beans/src/com/sun/javafx/collections/ElementObserver.java	Wed Feb 06 10:28:22 2013 -0500
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.collections;
+
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.RandomAccess;
+import javafx.beans.InvalidationListener;
+import javafx.beans.Observable;
+import javafx.util.Callback;
+
+final class ElementObserver<E> {
+
+    private static class ElementsMapElement {
+        InvalidationListener listener;
+        int counter;
+
+        public ElementsMapElement(InvalidationListener listener) {
+            this.listener = listener;
+            this.counter = 1;
+        }
+
+        public void increment() {
+            counter++;
+        }
+
+        public int decrement() {
+            return --counter;
+        }
+
+        private InvalidationListener getListener() {
+            return listener;
+        }
+    }
+
+    private Callback<E, Observable[]> extractor;
+    private final BaseObservableList<E> list;
+    private IdentityHashMap<E, ElementObserver.ElementsMapElement> elementsMap =
+            new IdentityHashMap<E, ElementObserver.ElementsMapElement>();
+